11use {
22 crate :: CertificateId ,
33 bitvec:: prelude:: * ,
4- solana_bls_signatures:: {
5- BlsError , Pubkey as BlsPubkey , PubkeyProjective , Signature , SignatureProjective ,
6- } ,
4+ solana_bls_signatures:: { BlsError , Pubkey as BlsPubkey , PubkeyProjective , SignatureProjective } ,
75 solana_runtime:: epoch_stakes:: BLSPubkeyToRankMap ,
86 solana_vote:: alpenglow:: {
97 bls_message:: { CertificateMessage , VoteMessage } ,
@@ -29,70 +27,56 @@ pub enum CertificateError {
2927 ValidatorDoesNotExist ( usize ) ,
3028}
3129
32- //TODO(wen): Maybe we can merge all the below functions into CertificateMessage .
30+ /// A builder for creating a `CertificateMessage` by efficiently aggregating BLS signatures .
3331#[ derive( Clone ) ]
34- pub struct VoteCertificate ( CertificateMessage ) ;
32+ pub struct VoteCertificateBuilder {
33+ certificate : Certificate ,
34+ signature : SignatureProjective ,
35+ bitmap : BitVec < u8 , Lsb0 > ,
36+ }
3537
36- impl From < CertificateMessage > for VoteCertificate {
37- fn from ( certificate_message : CertificateMessage ) -> Self {
38- Self ( certificate_message)
38+ impl TryFrom < CertificateMessage > for VoteCertificateBuilder {
39+ type Error = CertificateError ;
40+
41+ fn try_from ( message : CertificateMessage ) -> Result < Self , Self :: Error > {
42+ let projective_signature = SignatureProjective :: try_from ( message. signature ) ?;
43+ Ok ( VoteCertificateBuilder {
44+ certificate : message. certificate ,
45+ signature : projective_signature,
46+ bitmap : message. bitmap ,
47+ } )
3948 }
4049}
4150
42- impl VoteCertificate {
51+ impl VoteCertificateBuilder {
4352 pub fn new ( certificate_id : CertificateId ) -> Self {
44- VoteCertificate ( CertificateMessage {
53+ Self {
4554 certificate : certificate_id. into ( ) ,
46- signature : Signature :: default ( ) ,
55+ signature : SignatureProjective :: identity ( ) ,
4756 bitmap : BitVec :: < u8 , Lsb0 > :: repeat ( false , MAXIMUM_VALIDATORS ) ,
48- } )
57+ }
4958 }
5059
51- pub fn aggregate < ' a , ' b , T > ( & mut self , messages : T )
52- where
53- T : Iterator < Item = & ' a VoteMessage > ,
54- Self : ' b ,
55- ' b : ' a ,
56- {
57- let signature = & mut self . 0 . signature ;
58- // TODO: signature aggregation can be done out-of-order;
59- // consider aggregating signatures separately in parallel
60- let mut current_signature = if signature == & Signature :: default ( ) {
61- SignatureProjective :: identity ( )
62- } else {
63- SignatureProjective :: try_from ( * signature) . expect ( "Invalid signature" )
64- } ;
65-
66- // aggregate the votes
67- let bitmap = & mut self . 0 . bitmap ;
60+ /// Aggregates a slice of `VoteMessage`s into the builder.
61+ pub fn aggregate ( & mut self , messages : & [ VoteMessage ] ) -> Result < ( ) , CertificateError > {
6862 for vote_message in messages {
69- // set bit-vector for the validator
70- //
71- // TODO: This only accounts for one type of vote. Update this after
72- // we have a base3 encoding implementation.
73- assert ! (
74- bitmap. len( ) > vote_message. rank as usize ,
75- "Vote rank {} exceeds bitmap length {}" ,
76- vote_message. rank,
77- bitmap. len( )
78- ) ;
79- assert ! (
80- bitmap. get( vote_message. rank as usize ) . as_deref( ) != Some ( & true ) ,
81- "Conflicting vote check should make this unreachable {vote_message:?}"
82- ) ;
83- bitmap. set ( vote_message. rank as usize , true ) ;
84- // aggregate the signature
85- current_signature
86- . aggregate_with ( [ & vote_message. signature ] )
87- . expect (
88- "Failed to aggregate signature: {vote_message.signature:?} into {current_signature:?}"
89- ) ;
63+ if self . bitmap . len ( ) <= vote_message. rank as usize {
64+ return Err ( CertificateError :: ValidatorDoesNotExist (
65+ vote_message. rank as usize ,
66+ ) ) ;
67+ }
68+ self . bitmap . set ( vote_message. rank as usize , true ) ;
9069 }
91- * signature = Signature :: from ( current_signature) ;
70+ let signature_iter = messages. iter ( ) . map ( |vote_message| & vote_message. signature ) ;
71+ Ok ( self . signature . aggregate_with ( signature_iter) ?)
9272 }
9373
94- pub fn certificate ( self ) -> CertificateMessage {
95- self . 0
74+ pub fn build ( self ) -> CertificateMessage {
75+ CertificateMessage {
76+ certificate : self . certificate ,
77+ signature : self . signature . into ( ) ,
78+ bitmap : self . bitmap ,
79+ }
9680 }
9781}
9882
0 commit comments