Leios: vote and certify over the announcing RbHash#2086
Conversation
6aa7446 to
005523e
Compare
550cc26 to
7e136f2
Compare
1b8460a to
eb18f0b
Compare
7e136f2 to
3cf5afc
Compare
ch1bo
left a comment
There was a problem hiding this comment.
Not fully through it, but I'm not convinced that we need that many changes.
The certificate verification and vote signing is correct AFAIS, but it's a big of a too big rats tail on the storage and definitely the N2N mini protocols should not change? Please argue for why if I'm wrong.
| Nothing -> | ||
| -- A CertRB always has a (non-genesis) announcing parent; | ||
| -- the apply path shouldn't have produced one otherwise. | ||
| error "applyBlock: cannot determine announcing RB hash for CertRB" |
There was a problem hiding this comment.
Should: replace the call to protocolStateLeiosAnnouncement above with this
The RbHash is the new announcement and all what we need to verify the cert. We might be able to drop protocolStateLeiosAnnouncement completely
| | TraceLeiosVoted {vote :: LeiosVote, weight :: Weight} | ||
| | TraceLeiosVoteAcquired {vote :: LeiosVote} | ||
| | TraceLeiosCertified {point :: LeiosPoint} | ||
| | TraceLeiosCertified {rbHash :: RbHash} |
There was a problem hiding this comment.
Could: keep point and give this a more descriptive name like announcingRbHash
| pure $ MsgLeiosBlockOffer point ebSize | ||
| AcquiredEbTxs point -> | ||
| AcquiredEb point announcingRbHash ebSize -> | ||
| pure $ MsgLeiosBlockOffer point (Leios.rbHashBytes announcingRbHash) ebSize |
There was a problem hiding this comment.
Must: not change the N2N protocol because of this
Why would we need the offer to include the announcement?
| instance SignableRepresentation RbHash where | ||
| getSignableRepresentation point = | ||
| toStrictByteString $ | ||
| encodeRbHash point |
There was a problem hiding this comment.
Should: just use the hash bytes directly instead of CBOR
Not entirely sure what is the more common paradigm in the codebase? In any case, we should keep a note in the CIP / the vote CDDL about this.
| data LeiosVote = MkLeiosVote | ||
| { point :: LeiosPoint | ||
| { point :: RbHash | ||
| -- ^ Point that gets signed. The slot also identifies the voting round. |
There was a problem hiding this comment.
Should: rename this field. It's not a point, but just a block header hash.
Also, there is no slot in this.
| mconcat | ||
| [ "slot" .= point.pointSlotNo | ||
| , "ebHash" .= prettyEbHash point.pointEbHash | ||
| [ "rbHash" .= prettyRbHash point |
There was a problem hiding this comment.
Note to myself: The frontend uses the slot and ebHash to visualize votes
We must update it
| , "voterId" .= voterId.voterIndex | ||
| ] | ||
|
|
||
| -- | Create a vote for given 'LeiosPoint' and signing key. |
| = AcquiredEb LeiosPoint BytesSize | ||
| | AcquiredEbTxs LeiosPoint | ||
| = AcquiredEb LeiosPoint RbHash BytesSize | ||
| | AcquiredEbTxs LeiosPoint RbHash |
There was a problem hiding this comment.
Do we emit this now for each announcement (RbHash) that was completed when an EbTxs (closure) gets completed?
I'm asking because we would need to vote for each announcement (that is not equivocated).
| -- ^ Batch filter: returns the subset of input TxHashes that we do NOT have. | ||
| , leiosDbQueryCompletedEbByPoint :: HasCallStack => LeiosPoint -> m (Maybe [(TxHash, ByteString)]) | ||
| , leiosDbRbOfEb :: HasCallStack => EbHash -> m RbHash | ||
| -- ^ For an EB, find the RB that announced it. |
There was a problem hiding this comment.
Must: store announcements differently
This is not a 1:1 relationship. Instead, we would have a n:m relationship between announcements (RB headers) and EBs.
| -- NOTE: This is O(n) and should only be used at startup for initialization. | ||
| , -- NOTE: yields a LeiosOfferBlock notification | ||
| leiosDbInsertEbBody :: HasCallStack => LeiosPoint -> LeiosEb -> m () | ||
| leiosDbInsertEbBody :: HasCallStack => LeiosPoint -> RbHash -> LeiosEb -> m () |
There was a problem hiding this comment.
Should: not need to change this
An EB body should actually only be indexed by EbHash and having the Slot via LeiosPoint here is already problematic.
c8f869c to
13e6a58
Compare
Vote on the hash of the ranking block that announced the EB instead of the LeiosPoint, which comprises the slot number and EB hash. This forbids reusing Leios certificates across Praos forks.
3cf5afc to
4293065
Compare
Also remove it form leiosDbInsertEbBody and leiosDbInsertTxs
4293065 to
1c2f282
Compare
Fixes input-output-hk/ouroboros-leios#941
Changes to LeiosDemoTypes
RbHash--- a newtype overByteStringrepresenting a hash of a Ranking Block.LeiosVotenow carries anRbHashinstead ofLeiosPoint. This is the crux of the PR, all other changes stem from here.LeiosOutstandinggets a new fieldofferedEbRbHashes :: Map EbHash RbHash. This field records theRbHashfor each EB announcement. We cannot write theRbHashdirectly in the DB, because we don't yet have the EB body to attach to.Changes to the DB interface
leiosDbRbOfEb :: EbHash -> m RbHashfield toLeiosDbConnection.leiosDbRbOfEbmaps anEbHashto theRbHashfor the ranking block that announced this EB.LeiosEbNotificationnow carry anRbHash.leiosDbInsertEbBodyandleiosDbInsertTxsnow acceptRbHash.Changes to the forge
forgeShelleyBlockforges an RB and produces an EB announcement (as decided bydecideLeios), take note of the hash of the forged RB and store it intoleiosDbRbOfEbfor future reference.forgeShelleyBlockcertifies an EB, fetch the hash of its announcing RB fromleiosDbRbOfEb.mkAndStoreEbis split into two separate functions:mkEbandstoreEb. This is necessary becausestoreEbneeds to know theRbHashof the newly forged RB when announcing an EB, so it needs to be called after the RB is forged.Changes to
LeiosNotifyMsgLeiosBlockOffernow carries theRbHashof the announcing block. This is needed so that we can record theRbHashof the EBs we received from peers into the DB.Changes to voting
runLeiosVoting, we now forge votes onRbHashinstead ofLeiosPoint.queryCertnow acceptsRbHashas the index instead ofLeiosPoint.HasLeiosVotinginstance forDijkstranow needs theShelleyCompatibleconstraint in order to convert the previous block'sHeaderHashinto a raw hash and interpret it asRbHashto stick intovalidateLeiosCertificate.HasLeiosVotinginstance forDijkstra, we don't use the payload of the announcement invalidateLeiosBlockCertanymore, as we only need theHeaderHashof the previous block forvalidateLeiosCertificate. We still pattern-match on the announcement to check if it's not Nothing and refuse to validate the cert if it is.