Skip to content

Conversation

@agustinmista
Copy link
Contributor

@agustinmista agustinmista commented Dec 8, 2025

This PR comes in preparation to the implementation of the PerasVoteDB, and introduces a couple of new data types related to Peras votes and the certificate forging API:

  • The main PerasVote type, and its corresponding ValidatedPerasVote.
  • The auxiliary types PerasVoteTarget, PerasVoterId, PerasVoteStake, PerasVoteStakeDistr
  • The new Peras parameter PerasQuorumStakeThreshold (corresponding to perasQuorum in the design document, section 2.1)

@agustinmista agustinmista self-assigned this Dec 8, 2025
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from bf3a52c to 4063507 Compare December 9, 2025 10:39
@agustinmista agustinmista changed the title [Peras 13] Add votes and voting API [Peras 13] Add votes and vote forging API Dec 9, 2025
@agustinmista agustinmista changed the title [Peras 13] Add votes and vote forging API [Peras 13] Add votes and certificate forging API Dec 9, 2025
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from 4063507 to 06f4e61 Compare December 9, 2025 10:53
@agustinmista agustinmista changed the title [Peras 13] Add votes and certificate forging API [Peras 13] Introduce votes and certificate forging API Dec 9, 2025
Copy link
Contributor

@tbagrel1 tbagrel1 left a comment

Choose a reason for hiding this comment

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

Looks perfect to me! 😃

@agustinmista agustinmista marked this pull request as ready for review December 9, 2025 14:48
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from 06f4e61 to 42bb662 Compare December 12, 2025 13:42
@agustinmista agustinmista force-pushed the peras/main-pr/new-defs-and-plumbing branch 2 times, most recently from c314f45 to bb97f3f Compare December 16, 2025 09:40
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from 42bb662 to 4f2f0cc Compare December 16, 2025 10:08
pcCertBoostedBlock <- decode
pure $ PerasCert{pcCertRound, pcCertBoostedBlock}

instance Serialise (HeaderHash blk) => Serialise (PerasVote blk) where
Copy link
Contributor

Choose a reason for hiding this comment

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

Why chose Serialise instead of ToCBOR/FromCBOR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tbagrel1 maybe you have a better idea?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ouroboros.Consensus.Network.NodeToNode uses SerialiseNodeToNode class to serialise stuff. For types whose serialisation doesn't depend on a particular NodeToNodeVersion, the instances often fallback to encode/decode from Serialise class. For Peras types we've just followed the same existing pattern :)

Comment on lines +213 to +228
-- Consistent with the 'Serialise' instance for 'PerasVote' defined in Ouroboros.Consensus.Block.SupportsPeras
encodeNodeToNode ccfg version PerasVote{..} =
encodeListLen 3
<> encodeNodeToNode ccfg version pvVoteRound
<> encodeNodeToNode ccfg version pvVoteBlock
<> encodeNodeToNode ccfg version pvVoteVoterId
decodeNodeToNode ccfg version = do
decodeListLenOf 3
pvVoteRound <- decodeNodeToNode ccfg version
pvVoteBlock <- decodeNodeToNode ccfg version
pvVoteVoterId <- decodeNodeToNode ccfg version
pure $ PerasVote pvVoteRound pvVoteBlock pvVoteVoterId

instance SerialiseNodeToNode blk PerasVoterId where
encodeNodeToNode _ccfg _version = KeyHash.toCBOR . unPerasVoterId
decodeNodeToNode _ccfg _version = PerasVoterId <$> KeyHash.fromCBOR
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess the Serialise instance could change as it is used for storing on disk (confirm?), while this one would require a new NTN version etc etc. So if any I would put the comment in the Serialise instance saying that it matches the NTN one.

Also I think I would expose a function

-- Ouroboros.Consensus.Block.SupportsPeras

encodeVoteNodeToNode :: CodecConfig blk -> NodeToNodeVersion -> PerasVote blk -> Encoding
encodeVoteNodeToNode _ccfg _version = encode

maybe? I should check how we do this in other places but I think this is the pattern we usually use.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Bystander comment: I'm not super familiar with how these two type classes interact with each other but, in any case, we should remember to also apply any transformation to the instance for PerasCert defined above.

@agustinmista agustinmista force-pushed the peras/main-pr/new-defs-and-plumbing branch from bb97f3f to 43c1fdc Compare December 16, 2025 10:44
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from 4f2f0cc to fd401fc Compare December 16, 2025 10:59
@agustinmista agustinmista force-pushed the peras/main-pr/new-defs-and-plumbing branch from 43c1fdc to e7eadb3 Compare December 16, 2025 12:00
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from fd401fc to 0006522 Compare December 16, 2025 12:06
deriving Semigroup via Sum Rational
deriving Monoid via Sum Rational

newtype PerasVoteStakeDistr = PerasVoteStakeDistr
Copy link
Contributor

@fraser-iohk fraser-iohk Dec 17, 2025

Choose a reason for hiding this comment

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

can this be named PerasVoteStakeDistribution?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The current name follows the convention established by PoolDistr, but we can easily change it if you guys prefer that.

Up to you 😸

newtype PerasVoteStake = PerasVoteStake
{ unPerasVoteStake :: Rational
}
deriving newtype (Enum, Eq, Ord, Num, Fractional, NoThunks, Serialise)
Copy link
Contributor

Choose a reason for hiding this comment

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

can we remove the Enum instance? it's strange having this type be both Fractional and Enum, even if Rational underneath is

{ vpvVote :: !(PerasVote blk)
, vpvVoteStake :: !PerasVoteStake
}
deriving stock (Show, Eq, Ord, Generic)
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need this Ord instance for Map/Set at the moment, and can we remove it otherwise? I don't like being able to compare two ValidatedPerasVotes when it's only really a meaningful comparison on the stake when they're both for the same vote

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We do have simplified models for the PerasCertDB and (coming soon) PerasVoteDB making use of this Ord instance to store validated certs and votes in sets.

We can refactor those to use an explicit ordering and remove this instance, but I would prefer if we do it in a separate PR. I opened an issue to keep track of this:

tweag/cardano-peras#192

deriving Show via Quiet PerasVoterId

newtype PerasVoteStake = PerasVoteStake
{ unPerasVoteStake :: Rational
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand what exactly this Rational represents w.r.t. the stake amount. Are we just using Rational here to precisely represent a fractional value, or are we using the denominator to indicate the total stake (either across the committee or overall)? Should all of the PerasVoteStake values contained within a PerasVoteStakeDistr sum to exactly 1?

Copy link
Contributor

Choose a reason for hiding this comment

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

At the moment there is no consensus from researchers/engineers on how we go from the absolute stake of a voter in the ledger to the relative stake of their vote in the voting commitee (given that the quorum is expressed as a relative value of the voting commitee total stake). It is still being debated, cf. 2025/12/16 "Peras Acceleration meeting".

So you can consider this Rational as the best approximation we have at the moment of the concrete type for a relative vote stake that can be compared to the quorum value.

Copy link
Member

Choose a reason for hiding this comment

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

It'd be good to clarify the meaning of this in a comment 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a comment in a0c42b0

@agustinmista agustinmista force-pushed the peras/main-pr/new-defs-and-plumbing branch from e7eadb3 to ecff70d Compare December 19, 2025 09:25
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from 0006522 to d94393a Compare December 19, 2025 12:09
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from d94393a to dff3d9b Compare December 19, 2025 12:17
agustinmista and others added 2 commits December 19, 2025 13:21
This commit introduces a couple of new types to represent Peras votes
and their corresponding certificate forging API. Notably, this requires
an initial representation of notions like vote targets, vote stakes and stake
distributions over multiple stake pools.

Co-authored-by: Agustin Mista <agustin.mista@moduscreate.com>
Co-authored-by: Alexander Esgen <alexander.esgen@iohk.io>
Co-authored-by: Georgy Lukyanov <georgy.lukyanov@iohk.io>
Co-authored-by: Thomas BAGREL <thomas.bagrel@tweag.io>
Co-authored-by: Nicolas BACQUEY <nicolas.bacquey@tweag.io>
Co-authored-by: Agustin Mista <agustin.mista@moduscreate.com>
Co-authored-by: Alexander Esgen <alexander.esgen@iohk.io>
Co-authored-by: Georgy Lukyanov <georgy.lukyanov@iohk.io>
Co-authored-by: Thomas BAGREL <thomas.bagrel@tweag.io>
Co-authored-by: Nicolas BACQUEY <nicolas.bacquey@tweag.io>
@agustinmista agustinmista force-pushed the peras/main-pr/votedb-api branch from dff3d9b to 4b0c1af Compare December 19, 2025 12:23
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.

6 participants