mirror of
https://github.com/luxfi/dex.git
synced 2026-09-24 00:26:31 +00:00
verifyImports gates on normalOp. No test in the package ever set it, so every rail test proved its property with the block-level check returning at its first line: the forged-object rejection, the absent-object rejection and the bootstrap gate were assertions nothing had executed. Turn normalOp on in the rail harness and TestRail_ClaimImportsOnce — a test whose whole subject is replay — fails immediately. What it was hiding is a permanent halt reachable by an honest party. Delivery is permissionless by design, so two relayers delivering the same claim, or one retrying after a timeout, is the steady state. The second delivery is well formed and carries the real recorded bytes; the object is simply gone from shared memory, because this chain's own accepted Remove took it. The authenticator read that as unbacked and rejected the block, Reject requeued every tx in it, and the next build drained the same delivery and failed the same way. Measured over four rounds, the chain never left the height it stopped at. The consumed set is the committed fact that explains the absence, so consult it first: an import that cannot credit needs no proof. executeImport's replay guard runs before it decodes or credits anything, so a consumed claim pays out nothing whatever bytes ride with it. That is the safety half. The liveness half is that a validator has no lesser answer than rejecting a block carrying an unprovable import — the proposer's execution root already contains the credit — which makes proposing one self-harm. So the proposer screens the same predicate at build and holds what it cannot prove. Held, not dropped: a claim C has recorded but not yet flushed here is unprovable now and provable in a moment, and that lag is the rail's known liveness property, not an invalidity. One predicate, proveClaim, with two callers doing two different jobs. Also covers what running the authenticator buys back: forged bytes, an unrecorded claim id, the bootstrap gate in both positions, an over-export writing no claim, and commitAtomic's no-batch rule and commit-then-apply order. Co-authored-by: Hanzo Dev <[email protected]>