mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-08-16 07:30:26 +02:00
fix(infonet): reject non-finite gate lock values (#511)
* fix(infonet): reject non-finite gate lock values * test(infonet): cover non-finite gate lock values
This commit is contained in:
@@ -26,6 +26,7 @@ production should run these *before* emitting):
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, Iterable
|
from typing import Any, Iterable
|
||||||
|
|
||||||
@@ -81,12 +82,18 @@ def _collect_lock_contributions(
|
|||||||
p = _payload(ev)
|
p = _payload(ev)
|
||||||
try:
|
try:
|
||||||
paid = float(p.get("lock_cost") or 0.0)
|
paid = float(p.get("lock_cost") or 0.0)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError, OverflowError):
|
||||||
paid = 0.0
|
continue
|
||||||
if paid < float(_lock_cost_per_member()):
|
if not math.isfinite(paid) or paid < float(_lock_cost_per_member()):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
timestamp = float(ev.get("timestamp") or 0.0)
|
||||||
|
except (TypeError, ValueError, OverflowError):
|
||||||
|
continue
|
||||||
|
if not math.isfinite(timestamp):
|
||||||
continue
|
continue
|
||||||
seen.add(node)
|
seen.add(node)
|
||||||
out.append((node, float(ev.get("timestamp") or 0.0)))
|
out.append((node, timestamp))
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@@ -133,7 +140,10 @@ def validate_lock_request(
|
|||||||
needs to change.
|
needs to change.
|
||||||
"""
|
"""
|
||||||
chain_list = list(chain)
|
chain_list = list(chain)
|
||||||
cost = int(_lock_cost_per_member() if lock_cost is None else lock_cost)
|
try:
|
||||||
|
cost = int(_lock_cost_per_member() if lock_cost is None else lock_cost)
|
||||||
|
except (TypeError, ValueError, OverflowError):
|
||||||
|
return LockValidation(False, "invalid_lock_cost", 0)
|
||||||
if cost < _lock_cost_per_member():
|
if cost < _lock_cost_per_member():
|
||||||
return LockValidation(False, "lock_cost_below_min", cost)
|
return LockValidation(False, "lock_cost_below_min", cost)
|
||||||
if node_id not in compute_member_set(gate_id, chain_list):
|
if node_id not in compute_member_set(gate_id, chain_list):
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
"""Regression coverage for non-finite gate lock contributions."""
|
||||||
|
|
||||||
|
from services.infonet.config import CONFIG
|
||||||
|
from services.infonet.gates import is_locked, validate_lock_request
|
||||||
|
from services.infonet.tests._gate_factory import (
|
||||||
|
make_gate_create,
|
||||||
|
make_gate_enter,
|
||||||
|
make_gate_lock,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _gate_with_members() -> tuple[list[dict], list[str]]:
|
||||||
|
base = 1_000_000.0
|
||||||
|
threshold = int(CONFIG["gate_lock_min_members"])
|
||||||
|
members = [f"m{i}" for i in range(threshold)]
|
||||||
|
chain = [make_gate_create("g1", "creator", ts=base, seq=1)]
|
||||||
|
for i, member in enumerate(members):
|
||||||
|
chain.append(make_gate_enter("g1", member, ts=base + 100 + i, seq=2 + i))
|
||||||
|
return chain, members
|
||||||
|
|
||||||
|
|
||||||
|
def _append_valid_locks(chain: list[dict], members: list[str]) -> None:
|
||||||
|
cost = int(CONFIG["gate_lock_cost_per_member"])
|
||||||
|
for i, member in enumerate(members):
|
||||||
|
chain.append(
|
||||||
|
make_gate_lock(
|
||||||
|
"g1",
|
||||||
|
member,
|
||||||
|
ts=1_001_000.0 + i,
|
||||||
|
seq=200 + i,
|
||||||
|
lock_cost=cost,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_infinite_lock_cost_does_not_count_toward_threshold():
|
||||||
|
chain, members = _gate_with_members()
|
||||||
|
_append_valid_locks(chain, members[:-1])
|
||||||
|
bad = make_gate_lock("g1", members[-1], ts=1_002_000.0, seq=999)
|
||||||
|
bad["payload"]["lock_cost"] = float("inf")
|
||||||
|
chain.append(bad)
|
||||||
|
|
||||||
|
assert not is_locked("g1", chain)
|
||||||
|
|
||||||
|
|
||||||
|
def test_nonfinite_lock_timestamp_does_not_count_toward_threshold():
|
||||||
|
chain, members = _gate_with_members()
|
||||||
|
_append_valid_locks(chain, members[:-1])
|
||||||
|
bad = make_gate_lock("g1", members[-1], ts=float("nan"), seq=999)
|
||||||
|
chain.append(bad)
|
||||||
|
|
||||||
|
assert not is_locked("g1", chain)
|
||||||
|
|
||||||
|
|
||||||
|
def test_validate_lock_request_rejects_nonfinite_cost():
|
||||||
|
chain, members = _gate_with_members()
|
||||||
|
|
||||||
|
decision = validate_lock_request(
|
||||||
|
members[0],
|
||||||
|
"g1",
|
||||||
|
chain,
|
||||||
|
lock_cost=float("inf"), # type: ignore[arg-type]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not decision.accepted
|
||||||
|
assert decision.reason == "invalid_lock_cost"
|
||||||
Reference in New Issue
Block a user