Add handling for Auxiliary info#402
Conversation
98a5139 to
cdff0f1
Compare
| parentAuxInfo := parentBlock.Metadata.AuxiliaryInfo | ||
| if parentAuxInfo != nil { | ||
| auxInfo = &AuxiliaryInfo{ | ||
| VersionID: parentAuxInfo.VersionID, |
There was a problem hiding this comment.
so here we use the version ID from the parent, but in collectAuxillaryInfo we check against the oldest version id.
There was a problem hiding this comment.
do we have any tests for upgrading the version in the middle of an epoch, or is this not testable until we implement AuxiliaryInfoGenVerifier
There was a problem hiding this comment.
also if the struct implementing the interface already has the DefaultVersionID function, why do we need to call it, then pass it back to the other functions?
we are basically doing
version := GetDefaultVersion()
version = oldestVersion ? oldestVersion : version
IsLegalAuxInfoAppend(version) It seems like we will need to associate the version & epoch in the struct implementing the interface anyways, so why pass it in everywhere?
There was a problem hiding this comment.
collectAuxiliaryInfo checks if we have auxiliary information in this epoch.
it returns the default version ID if we don't have auxiliary information in the epoch.
In case we end up upgrading the auxiliary information app, we'll also change the default version ID (.DefaultVersionID()) and then it will return that.
The idea is to fallback to the older version ID if we already have a block in the epoch with a version ID.
There was a problem hiding this comment.
do we have any tests for upgrading the version in the middle of an epoch, or is this not testable until we implement AuxiliaryInfoGenVerifier
makes sense, I still think we should have a test where the version ID varies between blocks in an epoch if possible
| parentAuxInfo := parentBlock.Metadata.AuxiliaryInfo | ||
| if parentAuxInfo != nil { | ||
| auxInfo = &AuxiliaryInfo{ | ||
| VersionID: parentAuxInfo.VersionID, |
There was a problem hiding this comment.
do we have any tests for upgrading the version in the middle of an epoch, or is this not testable until we implement AuxiliaryInfoGenVerifier
makes sense, I still think we should have a test where the version ID varies between blocks in an epoch if possible
Introduce an AuxiliaryInfoApp interface abstraction that lets an application
piggyback application-specific data on Simplex epoch changes (e.g.
threshold distributed key generation), and gate the epoch transition on
that data being final. Final doesn't mean finalized as in Simplex,
but rather that the data is "good enough" to be used for the next epoch.
Metadata & encoding:
- Add AuxiliaryInfo (Info, PrevAuxInfoSeq, ApplicationID) to block
metadata and an AppID type, with Canoto (de)serialization.
- Each block's PrevAuxInfoSeq back-points to the most recent block with a
non-empty Info, skipping empty-Info blocks. collectAuxiliaryInfo walks
these pointers to rebuild the epoch's aux info history.
The digest of the last AuxInfo in a final history is signed by the node,
rather than the entire history of non-empty Aux Info.
This is done for flexibility, as some applications like publicly verifiable DKG
have commutative histories.
State machine:
- AuxiliaryInfoApp drives the flow: GenerateAuxInfo contributes to the
history until IsFinalAuxInfoHistory reports it ready; only then are
next-epoch approvals collected. IsLegalAuxInfoAppend validates a
proposed append on the verify path. Each method also receives the
next epoch's validator set (NodeBLSMappings).
- The builder carries forward / extends aux info, and the verifier
reconstructs the expected AuxiliaryInfo (ApplicationID, PrevAuxInfoSeq)
and enforces it via the block-digest comparison.
Approvals:
- Approvals now bind to the auxiliary info: the signed payload is
(NextPChainReferenceHeight, auxInfoDigest), where auxInfoDigest is the
sha256 of the last aux info element in the history.
- The ApprovalStore is now keyed by (NodeID, PChainHeight, AuxInfoSeqDigest)
so approvals for different digests coexist, and sanitizeApprovals only
aggregates approvals matching the candidate height and digest.
Tests:
- Verify approvals with real ECDSA signatures over the signed payload
(the test signature verifier now actually checks signatures and
(NextPChainReferenceHeight, auxInfoDigest), where auxInfoDigest is the
sha256 of the final aux info history. assembleApprovalToBeSigned
replaces the previous height-only payload.
The switch to ECDSA is because this way we make sure we really sign
the correct digest and not an empty one because of a bug.
- The ApprovalStore is keyed by (NodeID, PChainHeight, AuxInfoSeqDigest)
so approvals for different digests coexist, and sanitizeApprovals only
aggregates approvals matching the candidate height and digest.
Signed-off-by: Yacov Manevich <yacov.manevich@avalabs.org>
Introduce an AuxiliaryInfoApp interface abstraction that lets an application
piggyback application-specific data on Simplex epoch changes (e.g.
threshold distributed key generation), and gate the epoch transition on
that data being final. Final doesn't mean finalized as in Simplex,
but rather that the data is "good enough" to be used for the next epoch.
Metadata & encoding:
metadata and an AppID type, with Canoto (de)serialization.
non-empty Info, skipping empty-Info blocks. collectAuxiliaryInfo walks
these pointers to rebuild the epoch's aux info history.
The digest of the last AuxInfo in a final history is signed by the node,
rather than the entire history of non-empty Aux Info.
This is done for flexibility, as some applications like publicly verifiable DKG
have commutative histories.
State machine:
history until IsFinalAuxInfoHistory reports it ready; only then are
next-epoch approvals collected. IsLegalAuxInfoAppend validates a
proposed append on the verify path. Each method also receives the
next epoch's validator set (NodeBLSMappings).
reconstructs the expected AuxiliaryInfo (ApplicationID, PrevAuxInfoSeq)
and enforces it via the block-digest comparison.
Approvals:
(NextPChainReferenceHeight, auxInfoDigest), where auxInfoDigest is the
sha256 of the last aux info element in the history.
so approvals for different digests coexist, and sanitizeApprovals only
aggregates approvals matching the candidate height and digest.
Tests:
(the test signature verifier now actually checks signatures and
(NextPChainReferenceHeight, auxInfoDigest), where auxInfoDigest is the
sha256 of the final aux info history. assembleApprovalToBeSigned
replaces the previous height-only payload.
The switch to ECDSA is because this way we make sure we really sign
the correct digest and not an empty one because of a bug.
so approvals for different digests coexist, and sanitizeApprovals only
aggregates approvals matching the candidate height and digest.