3
3
// SPDX-License-Identifier: Apache-2.0
4
4
5
5
use crate :: {
6
- common:: { Author , Payload , Round } ,
7
- proposal_ext:: ProposalExt ,
8
- quorum_cert:: QuorumCert ,
9
- vote_data:: VoteData ,
6
+ common:: { Author , Payload , Round } , opt_block_data:: OptBlockData , proposal_ext:: ProposalExt , quorum_cert:: QuorumCert , vote_data:: VoteData
10
7
} ;
8
+ use anyhow:: { bail, Result } ;
11
9
use aptos_bitvec:: BitVec ;
12
- use aptos_crypto:: hash:: HashValue ;
13
- use aptos_crypto_derive:: { BCSCryptoHash , CryptoHasher } ;
10
+ use aptos_crypto:: { hash:: { CryptoHash , CryptoHasher } , HashValue } ;
11
+ use aptos_crypto_derive:: CryptoHasher ;
14
12
use aptos_types:: {
15
13
aggregate_signature:: AggregateSignature ,
16
14
block_info:: BlockInfo ,
@@ -49,6 +47,21 @@ pub enum BlockType {
49
47
/// Proposal with extensions (e.g. system transactions).
50
48
ProposalExt ( ProposalExt ) ,
51
49
50
+ /// Optimistic proposal
51
+ OptProposal {
52
+ validator_txns : Vec < ValidatorTransaction > ,
53
+ /// T of the block (e.g. one or more transaction(s)
54
+ payload : Payload ,
55
+ /// Author of the block that can be validated by the author's public key and the signature
56
+ author : Author ,
57
+ /// Failed authors from the parent's block to this block.
58
+ /// I.e. the list of consecutive proposers from the
59
+ /// immediately preceeding rounds that didn't produce a successful block.
60
+ failed_authors : Vec < ( Round , Author ) > ,
61
+ /// Grandparent QC, used to generate previous_bitvec
62
+ grandparent_qc : QuorumCert ,
63
+ } ,
64
+
52
65
/// A virtual block that's constructed by nodes from DAG, this is purely a local thing so
53
66
/// we hide it from serde
54
67
#[ serde( skip_deserializing) ]
@@ -63,7 +76,7 @@ pub enum BlockType {
63
76
} ,
64
77
}
65
78
66
- #[ derive( Deserialize , Serialize , Clone , Debug , PartialEq , Eq , CryptoHasher , BCSCryptoHash ) ]
79
+ #[ derive( Deserialize , Serialize , Clone , Debug , PartialEq , Eq , CryptoHasher ) ]
67
80
/// Block has the core data of a consensus block that should be persistent when necessary.
68
81
/// Each block must know the id of its parent and keep the QuorurmCertificate to that parent.
69
82
pub struct BlockData {
@@ -96,10 +109,28 @@ pub struct BlockData {
96
109
block_type : BlockType ,
97
110
}
98
111
112
+ impl CryptoHash for BlockData {
113
+ type Hasher = BlockDataHasher ;
114
+
115
+ fn hash ( & self ) -> HashValue {
116
+ let mut state = Self :: Hasher :: default ( ) ;
117
+ if self . is_opt_block ( ) {
118
+ state. update ( & self . epoch . to_be_bytes ( ) ) ;
119
+ state. update ( & self . round . to_be_bytes ( ) ) ;
120
+ state. update ( & self . timestamp_usecs . to_be_bytes ( ) ) ;
121
+ state. update ( & bcs:: to_bytes ( self . quorum_cert ( ) . vote_data ( ) ) . expect ( "Unable to serialize quorum cert vote data" ) ) ;
122
+ state. update ( & bcs:: to_bytes ( self . block_type ( ) ) . expect ( "Unable to serialize block type" ) ) ;
123
+ } else {
124
+ state. update ( & bcs:: to_bytes ( self ) . expect ( "Failed to serialize BlockData" ) ) ;
125
+ }
126
+ state. finish ( )
127
+ }
128
+ }
129
+
99
130
impl BlockData {
100
131
pub fn author ( & self ) -> Option < Author > {
101
132
match & self . block_type {
102
- BlockType :: Proposal { author, .. } | BlockType :: DAGBlock { author, .. } => {
133
+ BlockType :: Proposal { author, .. } | BlockType :: OptProposal { author , .. } | BlockType :: DAGBlock { author, .. } => {
103
134
Some ( * author)
104
135
} ,
105
136
BlockType :: ProposalExt ( p) => Some ( * p. author ( ) ) ,
@@ -126,6 +157,13 @@ impl BlockData {
126
157
}
127
158
}
128
159
160
+ pub fn grandparent_qc ( & self ) -> Result < QuorumCert > {
161
+ match & self . block_type {
162
+ BlockType :: OptProposal { grandparent_qc, .. } => Ok ( grandparent_qc. clone ( ) ) ,
163
+ _ => bail ! ( "Invalid block type" ) ,
164
+ }
165
+ }
166
+
129
167
pub fn payload ( & self ) -> Option < & Payload > {
130
168
match & self . block_type {
131
169
BlockType :: Proposal { payload, .. } | BlockType :: DAGBlock { payload, .. } => {
@@ -139,8 +177,9 @@ impl BlockData {
139
177
pub fn validator_txns ( & self ) -> Option < & Vec < ValidatorTransaction > > {
140
178
match & self . block_type {
141
179
BlockType :: ProposalExt ( proposal_ext) => proposal_ext. validator_txns ( ) ,
142
- BlockType :: Proposal { .. } | BlockType :: NilBlock { .. } | BlockType :: Genesis => None ,
180
+ BlockType :: Proposal { .. } | BlockType :: NilBlock { .. } | BlockType :: Genesis => None ,
143
181
BlockType :: DAGBlock { validator_txns, .. } => Some ( validator_txns) ,
182
+ BlockType :: OptProposal { validator_txns, .. } => ( !validator_txns. is_empty ( ) ) . then_some ( validator_txns) ,
144
183
}
145
184
}
146
185
@@ -176,13 +215,18 @@ impl BlockData {
176
215
matches ! ( self . block_type, BlockType :: NilBlock { .. } )
177
216
}
178
217
218
+ pub fn is_opt_block ( & self ) -> bool {
219
+ matches ! ( self . block_type, BlockType :: OptProposal { .. } )
220
+ }
221
+
179
222
/// the list of consecutive proposers from the immediately preceeding
180
223
/// rounds that didn't produce a successful block
181
224
pub fn failed_authors ( & self ) -> Option < & Vec < ( Round , Author ) > > {
182
225
match & self . block_type {
183
226
BlockType :: Proposal { failed_authors, .. }
184
227
| BlockType :: NilBlock { failed_authors, .. }
185
- | BlockType :: DAGBlock { failed_authors, .. } => Some ( failed_authors) ,
228
+ | BlockType :: DAGBlock { failed_authors, .. }
229
+ | BlockType :: OptProposal { failed_authors, .. } => Some ( failed_authors) ,
186
230
BlockType :: ProposalExt ( p) => Some ( p. failed_authors ( ) ) ,
187
231
BlockType :: Genesis => None ,
188
232
}
@@ -353,6 +397,35 @@ impl BlockData {
353
397
}
354
398
}
355
399
400
+ // Converting OptBlockData to BlockData
401
+ // by adding QC and failed_authors
402
+ pub fn new_from_opt (
403
+ opt_block_data : OptBlockData ,
404
+ quorum_cert : QuorumCert ,
405
+ new_failed_authors : Vec < ( Round , Author ) > ,
406
+ ) -> Result < Self > {
407
+ let OptBlockData {
408
+ epoch,
409
+ round,
410
+ timestamp_usecs,
411
+ parent_id : _,
412
+ block_type,
413
+ } = opt_block_data;
414
+ let block_type = match block_type {
415
+ BlockType :: OptProposal { validator_txns, payload, author, failed_authors : _, grandparent_qc } => {
416
+ BlockType :: OptProposal { validator_txns, payload, author, failed_authors : new_failed_authors, grandparent_qc }
417
+ }
418
+ _ => bail ! ( "Invalid block type" ) ,
419
+ } ;
420
+ Ok ( Self {
421
+ epoch,
422
+ round,
423
+ timestamp_usecs,
424
+ quorum_cert,
425
+ block_type,
426
+ } )
427
+ }
428
+
356
429
/// It's a reconfiguration suffix block if the parent block's executed state indicates next epoch.
357
430
pub fn is_reconfiguration_suffix ( & self ) -> bool {
358
431
self . quorum_cert . certified_block ( ) . has_reconfiguration ( )
0 commit comments