Skip to content

InMemory: reject writeEbBody for unregistered points - #2387

Merged
ch1bo merged 1 commit into
IntersectMBO:nfrisby/leios-issue-1071-validate-cert-asapfrom
SundaeSwap-finance:pgrange/leios-issue-1071-validate-cert-asap
Oct 9, 2026
Merged

ch1bo merged 1 commit into
IntersectMBO:nfrisby/leios-issue-1071-validate-cert-asapfrom
SundaeSwap-finance:pgrange/leios-issue-1071-validate-cert-asap

Conversation

@pgrange

@pgrange pgrange commented Oct 9, 2026

Copy link
Copy Markdown

SQLite rejects a body written for a point that writeEbPoint never inserted. InMemory instead registered the point silently, so InMemory-based tests could not catch a missing registration.

Today processLeiosBlock always registers the point first, so nothing hits this and the tests still pass. The guard matters once this TODO lands:

    -- TODO remove the 'writeEbPoint' call below once no important node's
    -- VolatileDB still holds an announcing RB that it fetched without this
    -- patch. [...]
    pointWritten <- writeEbPoint writer point ebBytesSize'

After that, any body reaching processLeiosBlock without a centrally-processed announcement would fail on SQLite. With this change InMemory fails the same way, so the tests surface it instead of passing:

$> cabal test ouroboros-consensus:consensus-test --test-options='--pattern "/LeiosDemoLogic.Invariants/"'
Test suite consensus-test: RUNNING...
ouroboros-consensus
  Leios
    LeiosDemoLogic.Invariants
      curated sequences
        forge purges a body it already holds (offered first):                                      FAIL
          ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:136:
          expected: Right []
           but got: Left "exception on Forge [0,1] 12: LeiosDbWriteException {writeJob = \"WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}}"
          Use -p '/LeiosDemoLogic.Invariants/&&/forge purges a body it already holds (offered first)/' to rerun this test only.
        an offer of a self-forged EB is not re-fetched (forged first):                             FAIL
          ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:138:
          expected: Right []
           but got: Left "exception on Forge [0,1] 12: LeiosDbWriteException {writeJob = \"WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}}"
          Use -p '/LeiosDemoLogic.Invariants/&&/an offer of a self-forged EB is not re-fetched (forged first)/' to rerun this test only.
      a body is claimed acquired only by a settled write:                                          OK
      acquired EB kept until its greatest slot is below the immutable tip:                         OK
      an announcement raises a forged EB's max slot (so it isn't pruned early):                    OK
      an announcement's onset is recorded (earliest kept); an offer never clobbers it:             OK
      start-up seeding marks each completed EB held, with an empty pool:                           OK
      start-up seeding: a peer's offer of a seeded EB is not re-fetched:                           OK
      a big-ledger peer has a larger, but still finite, closure budget:                            OK
      job assignment draws within the least-requested bucket, at random, respecting exclusions:    OK
      only the announcement that takes an election's focus is tracked:                             OK
      EB-hash collision (ported from #2309)
        forged, then the same EB announced at a new slot: both points registered and notified:     FAIL
          Exception: WriteEbBody (5, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99) failed: writeEbBody: point not registered (programmer error)
          CallStack (from HasCallStack):
            throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory

          submitted from:
          CallStack (from HasCallStack):
            resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory
            writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common
            a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic

          HasCallStack backtrace:
            collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
            toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
            throwIO, called at ./Control/Concurrent/Async.hs:78:13 in tsty-1.5.4-843ddea7:Control.Concurrent.Async

          Use -p '/LeiosDemoLogic.Invariants/&&/forged, then the same EB announced at a new slot: both points registered and notified/' to rerun this test only.
        body held, then the same EB announced at a new slot: both points registered:               OK
        both announced before the fetch: both points registered:                                   OK
        forged, then the same EB merely offered at a new slot: the offer registers nothing:        FAIL
          Exception: WriteEbBody (5, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99) failed: writeEbBody: point not registered (programmer error)
          CallStack (from HasCallStack):
            throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory

          submitted from:
          CallStack (from HasCallStack):
            resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory
            writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common
            a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic

          HasCallStack backtrace:
            collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
            toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
            throwIO, called at ./Control/Concurrent/Async.hs:78:13 in tsty-1.5.4-843ddea7:Control.Concurrent.Async

          Use -p '/LeiosDemoLogic.Invariants/&&/forged, then the same EB merely offered at a new slot: the offer registers nothing/' to rerun this test only.
      a certificate tracks an endorser block no announcement did:                                  OK
      an endorser block that references too many tx bytes is dropped, not fetched:                 OK
      an endorser block at exactly its bound is fetched:                                           FAIL
        ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:476:
        expected BodyAcquired, got Just (MkEbState (SlotNo 5) SNothing NoBody)
        Use -p '/LeiosDemoLogic.Invariants/&&/an endorser block at exactly its bound is fetched/' to rerun this test only.
      a certificate leaves a body we already hold held:                                            OK
      outstanding-state invariants hold across arbitrary sequences:                                FAIL
        *** Failed! Falsified (after 4 tests and 1 shrink):
        [ArriveBody [2,3,4] 11,Announce [1,2] 11]
        Left "exception on Announce [1,2] 11: ExceptionInLinkedThread \"ThreadId [1]\" (LeiosDbWriteException {writeJob = \"WriteEbBody (11, ff3e90aa6fbe36b630f58be98da978061e94c0a998da2376f0b4abf615082391)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}})" /= Right ()
        Use --quickcheck-replay="(SMGen 14245007439037612623 12544114665117986533,3)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/outstanding-state invariants hold across arbitrary sequences/' to rerun this test only.
      the fetch logic never requests an already-held EB body:                                      FAIL
        *** Failed! Falsified (after 4 tests and 1 shrink):
        [ArriveBody [2,3,4] 10,Disconnect]
        exception on Disconnect: ExceptionInLinkedThread "ThreadId [1]" (LeiosDbWriteException {writeJob = "WriteEbBody (10, ff3e90aa6fbe36b630f58be98da978061e94c0a998da2376f0b4abf615082391)", submittedFrom = "CallStack (from HasCallStack):\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic", writeFailure = LeiosDbException {errorMessage = "writeEbBody: point not registered (programmer error)", callStack = "CallStack (from HasCallStack):\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory"}})
        Use --quickcheck-replay="(SMGen 10024954925442282638 16722750794533007117,3)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/the fetch logic never requests an already-held EB body/' to rerun this test only.
      a concurrent offer, announcement and body arrival keep the reverse index in sync (IOSimPOR): FAIL
        *** Failed! Falsified (after 1 test):
        Schedule control: ControlDefault
        No thread delayed
        Failure: FailureException (ExceptionInLinkedThread "RacyThreadId [2,2,1]" (LeiosDbWriteException {writeJob = "WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)", submittedFrom = "CallStack (from HasCallStack):\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic", writeFailure = LeiosDbException {errorMessage = "writeEbBody: point not registered (programmer error)", callStack = "CallStack (from HasCallStack):\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory"}}))
        Use --quickcheck-replay="(SMGen 7877884416199475454 17480834384350021,0)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/a concurrent offer, announcement and body arrival keep the reverse index in sync (IOSimPOR)/' to rerun this test only.

8 out of 22 tests failed (0.01s)

SQLite rejects a body written for a point that writeEbPoint never inserted.
InMemory instead registered the point silently, so InMemory-based tests could
not catch a missing registration.

Today processLeiosBlock always registers the point first, so nothing hits this
and the tests still pass. The guard matters once this TODO lands:

    -- TODO remove the 'writeEbPoint' call below once no important node's
    -- VolatileDB still holds an announcing RB that it fetched without this
    -- patch. [...]
    pointWritten <- writeEbPoint writer point ebBytesSize'

After that, any body reaching processLeiosBlock without a centrally-processed
announcement would fail on SQLite. With this change InMemory fails the same way,
so the tests surface it instead of passing:

```
$> cabal test ouroboros-consensus:consensus-test --test-options='--pattern "/LeiosDemoLogic.Invariants/"'
Test suite consensus-test: RUNNING...
ouroboros-consensus
  Leios
    LeiosDemoLogic.Invariants
      curated sequences
        forge purges a body it already holds (offered first):                                      FAIL
          ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:136:
          expected: Right []
           but got: Left "exception on Forge [0,1] 12: LeiosDbWriteException {writeJob = \"WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}}"
          Use -p '/LeiosDemoLogic.Invariants/&&/forge purges a body it already holds (offered first)/' to rerun this test only.
        an offer of a self-forged EB is not re-fetched (forged first):                             FAIL
          ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:138:
          expected: Right []
           but got: Left "exception on Forge [0,1] 12: LeiosDbWriteException {writeJob = \"WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}}"
          Use -p '/LeiosDemoLogic.Invariants/&&/an offer of a self-forged EB is not re-fetched (forged first)/' to rerun this test only.
      a body is claimed acquired only by a settled write:                                          OK
      acquired EB kept until its greatest slot is below the immutable tip:                         OK
      an announcement raises a forged EB's max slot (so it isn't pruned early):                    OK
      an announcement's onset is recorded (earliest kept); an offer never clobbers it:             OK
      start-up seeding marks each completed EB held, with an empty pool:                           OK
      start-up seeding: a peer's offer of a seeded EB is not re-fetched:                           OK
      a big-ledger peer has a larger, but still finite, closure budget:                            OK
      job assignment draws within the least-requested bucket, at random, respecting exclusions:    OK
      only the announcement that takes an election's focus is tracked:                             OK
      EB-hash collision (ported from IntersectMBO#2309)
        forged, then the same EB announced at a new slot: both points registered and notified:     FAIL
          Exception: WriteEbBody (5, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99) failed: writeEbBody: point not registered (programmer error)
          CallStack (from HasCallStack):
            throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory

          submitted from:
          CallStack (from HasCallStack):
            resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory
            writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common
            a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic

          HasCallStack backtrace:
            collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
            toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
            throwIO, called at ./Control/Concurrent/Async.hs:78:13 in tsty-1.5.4-843ddea7:Control.Concurrent.Async

          Use -p '/LeiosDemoLogic.Invariants/&&/forged, then the same EB announced at a new slot: both points registered and notified/' to rerun this test only.
        body held, then the same EB announced at a new slot: both points registered:               OK
        both announced before the fetch: both points registered:                                   OK
        forged, then the same EB merely offered at a new slot: the offer registers nothing:        FAIL
          Exception: WriteEbBody (5, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99) failed: writeEbBody: point not registered (programmer error)
          CallStack (from HasCallStack):
            throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory

          submitted from:
          CallStack (from HasCallStack):
            resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory
            writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common
            a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic

          HasCallStack backtrace:
            collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
            toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
            throwIO, called at ./Control/Concurrent/Async.hs:78:13 in tsty-1.5.4-843ddea7:Control.Concurrent.Async

          Use -p '/LeiosDemoLogic.Invariants/&&/forged, then the same EB merely offered at a new slot: the offer registers nothing/' to rerun this test only.
      a certificate tracks an endorser block no announcement did:                                  OK
      an endorser block that references too many tx bytes is dropped, not fetched:                 OK
      an endorser block at exactly its bound is fetched:                                           FAIL
        ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:476:
        expected BodyAcquired, got Just (MkEbState (SlotNo 5) SNothing NoBody)
        Use -p '/LeiosDemoLogic.Invariants/&&/an endorser block at exactly its bound is fetched/' to rerun this test only.
      a certificate leaves a body we already hold held:                                            OK
      outstanding-state invariants hold across arbitrary sequences:                                FAIL
        *** Failed! Falsified (after 4 tests and 1 shrink):
        [ArriveBody [2,3,4] 11,Announce [1,2] 11]
        Left "exception on Announce [1,2] 11: ExceptionInLinkedThread \"ThreadId [1]\" (LeiosDbWriteException {writeJob = \"WriteEbBody (11, ff3e90aa6fbe36b630f58be98da978061e94c0a998da2376f0b4abf615082391)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}})" /= Right ()
        Use --quickcheck-replay="(SMGen 14245007439037612623 12544114665117986533,3)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/outstanding-state invariants hold across arbitrary sequences/' to rerun this test only.
      the fetch logic never requests an already-held EB body:                                      FAIL
        *** Failed! Falsified (after 4 tests and 1 shrink):
        [ArriveBody [2,3,4] 10,Disconnect]
        exception on Disconnect: ExceptionInLinkedThread "ThreadId [1]" (LeiosDbWriteException {writeJob = "WriteEbBody (10, ff3e90aa6fbe36b630f58be98da978061e94c0a998da2376f0b4abf615082391)", submittedFrom = "CallStack (from HasCallStack):\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic", writeFailure = LeiosDbException {errorMessage = "writeEbBody: point not registered (programmer error)", callStack = "CallStack (from HasCallStack):\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory"}})
        Use --quickcheck-replay="(SMGen 10024954925442282638 16722750794533007117,3)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/the fetch logic never requests an already-held EB body/' to rerun this test only.
      a concurrent offer, announcement and body arrival keep the reverse index in sync (IOSimPOR): FAIL
        *** Failed! Falsified (after 1 test):
        Schedule control: ControlDefault
        No thread delayed
        Failure: FailureException (ExceptionInLinkedThread "RacyThreadId [2,2,1]" (LeiosDbWriteException {writeJob = "WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)", submittedFrom = "CallStack (from HasCallStack):\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic", writeFailure = LeiosDbException {errorMessage = "writeEbBody: point not registered (programmer error)", callStack = "CallStack (from HasCallStack):\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory"}}))
        Use --quickcheck-replay="(SMGen 7877884416199475454 17480834384350021,0)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/a concurrent offer, announcement and body arrival keep the reverse index in sync (IOSimPOR)/' to rerun this test only.

8 out of 22 tests failed (0.01s)
```
@pgrange
pgrange marked this pull request as ready for review October 9, 2026 07:43
@ch1bo
ch1bo self-requested a review October 9, 2026 08:31

@ch1bo ch1bo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Merging it into the omnibus, which we hopefully merge later today

@ch1bo
ch1bo merged commit 3132c9d into IntersectMBO:nfrisby/leios-issue-1071-validate-cert-asap Oct 9, 2026
2 of 62 checks passed
ch1bo added a commit that referenced this pull request Oct 9, 2026
SQLite rejects a body written for a point that `writeEbPoint` never
inserted. InMemory instead registered the point silently, so
InMemory-based tests could not catch a missing registration.

Today `processLeiosBlock` always registers the point first, so nothing
hits this and the tests still pass. The guard matters once this TODO
lands:

```haskell
    -- TODO remove the 'writeEbPoint' call below once no important node's
    -- VolatileDB still holds an announcing RB that it fetched without this
    -- patch. [...]
    pointWritten <- writeEbPoint writer point ebBytesSize'
```

After that, any body reaching processLeiosBlock without a
centrally-processed announcement would fail on SQLite. With this change
InMemory fails the same way, so the tests surface it instead of passing:

```bash
$> cabal test ouroboros-consensus:consensus-test --test-options='--pattern "/LeiosDemoLogic.Invariants/"'
Test suite consensus-test: RUNNING...
ouroboros-consensus
  Leios
    LeiosDemoLogic.Invariants
      curated sequences
        forge purges a body it already holds (offered first):                                      FAIL
          ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:136:
          expected: Right []
           but got: Left "exception on Forge [0,1] 12: LeiosDbWriteException {writeJob = \"WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}}"
          Use -p '/LeiosDemoLogic.Invariants/&&/forge purges a body it already holds (offered first)/' to rerun this test only.
        an offer of a self-forged EB is not re-fetched (forged first):                             FAIL
          ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:138:
          expected: Right []
           but got: Left "exception on Forge [0,1] 12: LeiosDbWriteException {writeJob = \"WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}}"
          Use -p '/LeiosDemoLogic.Invariants/&&/an offer of a self-forged EB is not re-fetched (forged first)/' to rerun this test only.
      a body is claimed acquired only by a settled write:                                          OK
      acquired EB kept until its greatest slot is below the immutable tip:                         OK
      an announcement raises a forged EB's max slot (so it isn't pruned early):                    OK
      an announcement's onset is recorded (earliest kept); an offer never clobbers it:             OK
      start-up seeding marks each completed EB held, with an empty pool:                           OK
      start-up seeding: a peer's offer of a seeded EB is not re-fetched:                           OK
      a big-ledger peer has a larger, but still finite, closure budget:                            OK
      job assignment draws within the least-requested bucket, at random, respecting exclusions:    OK
      only the announcement that takes an election's focus is tracked:                             OK
      EB-hash collision (ported from #2309)
        forged, then the same EB announced at a new slot: both points registered and notified:     FAIL
          Exception: WriteEbBody (5, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99) failed: writeEbBody: point not registered (programmer error)
          CallStack (from HasCallStack):
            throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory

          submitted from:
          CallStack (from HasCallStack):
            resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory
            writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common
            a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic

          HasCallStack backtrace:
            collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
            toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
            throwIO, called at ./Control/Concurrent/Async.hs:78:13 in tsty-1.5.4-843ddea7:Control.Concurrent.Async

          Use -p '/LeiosDemoLogic.Invariants/&&/forged, then the same EB announced at a new slot: both points registered and notified/' to rerun this test only.
        body held, then the same EB announced at a new slot: both points registered:               OK
        both announced before the fetch: both points registered:                                   OK
        forged, then the same EB merely offered at a new slot: the offer registers nothing:        FAIL
          Exception: WriteEbBody (5, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99) failed: writeEbBody: point not registered (programmer error)
          CallStack (from HasCallStack):
            throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory

          submitted from:
          CallStack (from HasCallStack):
            resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory
            writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common
            a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic

          HasCallStack backtrace:
            collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:169:13 in ghc-internal:GHC.Internal.Exception
            toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/IO.hs:260:11 in ghc-internal:GHC.Internal.IO
            throwIO, called at ./Control/Concurrent/Async.hs:78:13 in tsty-1.5.4-843ddea7:Control.Concurrent.Async

          Use -p '/LeiosDemoLogic.Invariants/&&/forged, then the same EB merely offered at a new slot: the offer registers nothing/' to rerun this test only.
      a certificate tracks an endorser block no announcement did:                                  OK
      an endorser block that references too many tx bytes is dropped, not fetched:                 OK
      an endorser block at exactly its bound is fetched:                                           FAIL
        ouroboros-consensus/test/consensus-test/Test/LeiosDemoLogic/Invariants.hs:476:
        expected BodyAcquired, got Just (MkEbState (SlotNo 5) SNothing NoBody)
        Use -p '/LeiosDemoLogic.Invariants/&&/an endorser block at exactly its bound is fetched/' to rerun this test only.
      a certificate leaves a body we already hold held:                                            OK
      outstanding-state invariants hold across arbitrary sequences:                                FAIL
        *** Failed! Falsified (after 4 tests and 1 shrink):
        [ArriveBody [2,3,4] 11,Announce [1,2] 11]
        Left "exception on Announce [1,2] 11: ExceptionInLinkedThread \"ThreadId [1]\" (LeiosDbWriteException {writeJob = \"WriteEbBody (11, ff3e90aa6fbe36b630f58be98da978061e94c0a998da2376f0b4abf615082391)\", submittedFrom = \"CallStack (from HasCallStack):\\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic\", writeFailure = LeiosDbException {errorMessage = \"writeEbBody: point not registered (programmer error)\", callStack = \"CallStack (from HasCallStack):\\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\"}})" /= Right ()
        Use --quickcheck-replay="(SMGen 14245007439037612623 12544114665117986533,3)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/outstanding-state invariants hold across arbitrary sequences/' to rerun this test only.
      the fetch logic never requests an already-held EB body:                                      FAIL
        *** Failed! Falsified (after 4 tests and 1 shrink):
        [ArriveBody [2,3,4] 10,Disconnect]
        exception on Disconnect: ExceptionInLinkedThread "ThreadId [1]" (LeiosDbWriteException {writeJob = "WriteEbBody (10, ff3e90aa6fbe36b630f58be98da978061e94c0a998da2376f0b4abf615082391)", submittedFrom = "CallStack (from HasCallStack):\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic", writeFailure = LeiosDbException {errorMessage = "writeEbBody: point not registered (programmer error)", callStack = "CallStack (from HasCallStack):\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory"}})
        Use --quickcheck-replay="(SMGen 10024954925442282638 16722750794533007117,3)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/the fetch logic never requests an already-held EB body/' to rerun this test only.
      a concurrent offer, announcement and body arrival keep the reverse index in sync (IOSimPOR): FAIL
        *** Failed! Falsified (after 1 test):
        Schedule control: ControlDefault
        No thread delayed
        Failure: FailureException (ExceptionInLinkedThread "RacyThreadId [2,2,1]" (LeiosDbWriteException {writeJob = "WriteEbBody (12, 47f6c6404a56ea658d0b40e31c47eba73beaad3d3d71a5e61fc0e90ea48d6d99)", submittedFrom = "CallStack (from HasCallStack):\n  resolved, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:197:11 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory\n  writeEbBody, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/Common.hs:135:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.Common\n  a use of `writeEbBody', called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoLogic.hs:1112:22 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoLogic", writeFailure = LeiosDbException {errorMessage = "writeEbBody: point not registered (programmer error)", callStack = "CallStack (from HasCallStack):\n  throwLeiosDbException, called at ouroboros-consensus/src/ouroboros-consensus/LeiosDemoDb/InMemory.hs:297:5 in ouroboros-consensus-3.0.1.0-inplace:LeiosDemoDb.InMemory"}}))
        Use --quickcheck-replay="(SMGen 7877884416199475454 17480834384350021,0)" to reproduce.
        Use -p '/LeiosDemoLogic.Invariants/&&/a concurrent offer, announcement and body arrival keep the reverse index in sync (IOSimPOR)/' to rerun this test only.

8 out of 22 tests failed (0.01s)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants