Skip to content

Conversation

@tbagrel1
Copy link
Contributor

@tbagrel1 tbagrel1 commented Sep 11, 2025

This pull request introduces the PerasCertDB datatype, used to hold and access all PerasCerts known by a node that could affect chain selection.

In the mid/near-term future, this will be enriched to persist certificates across restarts, and probably also to store historical certificates.


Peras types

  • Added modules Ouroboros.Consensus.Storage.PerasCertDB{,.API,.Impl}, notably defining the typesPerasCertDB, PerasCertSnapshot (read-only snapshot of certs contained in the DB), and AddPerasCertResult; alongside their respectives methods

Tests

  • Added modules Test.Ouroboros.Storage.PerasCertDB{,.StateMachine,.Model} for q-s-m testing of the PerasCertDB datatype. The corresponding tests have been included in the test suite defined by Test.Ouroboros.Storage

Regression

As the previous PR, all the components introduced by this PR are not used at the moment by the rest of the code, so no regression is expected.

@amesgen amesgen added the Peras label Sep 11, 2025
@tbagrel1 tbagrel1 force-pushed the main-pr/basic-peras-types branch from d3cd2fc to 8df7902 Compare September 12, 2025 07:59
@tbagrel1 tbagrel1 force-pushed the main-pr/peras-cert-db branch from 8a7ab97 to 0e67f26 Compare September 12, 2025 08:02
@tbagrel1 tbagrel1 changed the title Introduce PerasCertDB and related tests [Peras #2] Introduce PerasCertDB and related tests Sep 12, 2025
@tbagrel1 tbagrel1 force-pushed the main-pr/basic-peras-types branch 5 times, most recently from f3fbd4f to 01e1c69 Compare September 16, 2025 13:50
@tbagrel1 tbagrel1 force-pushed the main-pr/peras-cert-db branch 3 times, most recently from 8f303af to 6649e71 Compare September 17, 2025 09:27
@amesgen amesgen force-pushed the main-pr/basic-peras-types branch from 2fdba58 to 3db7a62 Compare September 25, 2025 11:47
Base automatically changed from main-pr/basic-peras-types to main September 25, 2025 13:59
@tbagrel1 tbagrel1 force-pushed the main-pr/peras-cert-db branch from 6649e71 to e18c8d6 Compare September 25, 2025 14:04
@tbagrel1 tbagrel1 changed the title [Peras #2] Introduce PerasCertDB and related tests [Peras 2] Introduce PerasCertDB and related tests Sep 25, 2025
@amesgen amesgen marked this pull request as ready for review September 25, 2025 16:20

-- * 'PerasCertSnapshot'
, PerasCertSnapshot (..)
, PerasCertTicketNo
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need ticket numbers for Peras certificates?

Copy link
Member

Choose a reason for hiding this comment

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

We allocate PerasCertTicketNos in monotonically increasing fashion as new certificates arrive, just as we do for transactions in the mempool (we should add this in a Haddock comment). This way, anyone can subscribe to certificates as they arrive, by asking for more certificates after the last ticket number they know of, using getCertsAfter.

One thing to note here is that Peras round numbers almost could play the role of ticket numbers: Apart from edge cases, we will never receive a Peras certificate for round r after we received one for round s if r < s. However, because of these edge cases and a general concern for robustness, we are not using round numbers as "almost ticket numbers".


Lastly, we could also hide the ticket numbers by exposing a more monadic API (essentially a dequeue interface), where the PerasCertNo is maintained "internally". (This would be possible both here and in the Mempool API)

Status quo (simplified) in this PR:

getCertSnapshot :: STM m (PerasCertSnapshot blk)

data PerasCertSnapshot blk = PerasCertSnapshot
  { getCertsAfter :: PerasCertTicketNo -> [(ValidatedPerasCert blk, PerasCertTicketNo)]
  }

Here, the caller is responsible for maintaining the PerasCertTicketNo across calls to getCertsAfter/getCertSnapshot.

More monadic option without ticket numbers:

getCertFollower :: STM m (PerasCertFollower blk)

data PerasCertFollower blk = PerasCertFollower
  { getNextPerasCert :: STM m (ValidatedPerasCert blk)]
  }

Here, getNextPerasCert would internally maintain the PerasCertTicketNo in a TVar (or we could change the implementation to be based on a TChan 🤔 ).

Let us know if you find this appealing, we can explore that.

Copy link
Member

Choose a reason for hiding this comment

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

However, because of these edge cases and a general concern for robustness, we are not using round numbers as "almost ticket numbers".

That makes sense. Should we document this properly (if it's not documented already). Thanks!

Let us know if you find this appealing, we can explore that.

I can't say I have a preference, but the current design seems simpler.

Copy link
Member

Choose a reason for hiding this comment

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

Should we document this properly (if it's not documented already). Thanks!

I enriched the Haddocks of PerasCertTicketNo appropriately 👍


-- | Volatile Peras certificate state, i.e. certificates that could influence
-- chain selection by boosting a volatile block.
data PerasVolatileCertState blk = PerasVolatileCertState
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps we should add some invariant checking here. For instance:

  • Should the different maps have all the same size?
  • For every certificate in pvcsCerts, is there a corresponding weight in pvcsWeightByPoint?
  • Should the range of pvcsCerts and pvcsCertsByTicket be the same?
  • etc.

Copy link
Member

Choose a reason for hiding this comment

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

It might also be worth explaining why we're splitting the information of Peras certificates into multiple maps.

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe the answer to the last question is that these are particular indices that make call site queries execute optimally, otherwise we'd be scanning the entire pvcsCerts looking for a ticketNo.

Copy link
Member

Choose a reason for hiding this comment

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

@bladyjoker is exactly right, we want to efficiently support different use cases using different representations, so that's why we have some redundancy.

In fact, we opened #1649 and submitted #1651 precisely to easily attach an invariant for this particular case, but somehow forgot to do this before opening this PR. Thanks for catching that!

Copy link
Member

Choose a reason for hiding this comment

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

Done, see invariantForPerasVolatileCertState

@nbacquey nbacquey force-pushed the main-pr/peras-cert-db branch 3 times, most recently from 2d628de to d0e0655 Compare October 7, 2025 16:07
tbagrel1 and others added 3 commits October 9, 2025 15:55
Co-authored-by: Agustin Mista <[email protected]>
Co-authored-by: Alexander Esgen <[email protected]>
Co-authored-by: Georgy Lukyanov <[email protected]>
Co-authored-by: Thomas BAGREL <[email protected]>
Co-authored-by: Nicolas BACQUEY <[email protected]>
Co-authored-by: Nicolas "Niols" Jeannerod <[email protected]>
Co-authored-by: Agustin Mista <[email protected]>
Co-authored-by: Alexander Esgen <[email protected]>
Co-authored-by: Georgy Lukyanov <[email protected]>
Co-authored-by: Thomas BAGREL <[email protected]>
Co-authored-by: Nicolas BACQUEY <[email protected]>
Co-authored-by: Nicolas "Niols" Jeannerod <[email protected]>
Co-authored-by: Agustin Mista <[email protected]>
Co-authored-by: Alexander Esgen <[email protected]>
Co-authored-by: Georgy Lukyanov <[email protected]>
Co-authored-by: Thomas BAGREL <[email protected]>
Co-authored-by: Nicolas BACQUEY <[email protected]>
Co-authored-by: Nicolas "Niols" Jeannerod <[email protected]>
@amesgen amesgen force-pushed the main-pr/peras-cert-db branch from d0e0655 to 3f2b421 Compare October 9, 2025 13:55
Copy link
Contributor

@bladyjoker bladyjoker left a comment

Choose a reason for hiding this comment

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

This was a lovely read! Looks good :)

@amesgen amesgen added this pull request to the merge queue Oct 10, 2025
Merged via the queue into main with commit 6308a39 Oct 10, 2025
16 of 19 checks passed
@amesgen amesgen deleted the main-pr/peras-cert-db branch October 10, 2025 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants