4
4
5
5
use crate :: {
6
6
common:: { Author , Payload , Round } ,
7
+ opt_block_data:: OptBlockData ,
7
8
proposal_ext:: ProposalExt ,
8
9
quorum_cert:: QuorumCert ,
9
10
vote_data:: VoteData ,
10
11
} ;
12
+ use anyhow:: { bail, Result } ;
11
13
use aptos_bitvec:: BitVec ;
12
- use aptos_crypto:: hash:: HashValue ;
13
- use aptos_crypto_derive:: { BCSCryptoHash , CryptoHasher } ;
14
+ use aptos_crypto:: {
15
+ hash:: { CryptoHash , CryptoHasher } ,
16
+ HashValue ,
17
+ } ;
18
+ use aptos_crypto_derive:: CryptoHasher ;
14
19
use aptos_types:: {
15
20
aggregate_signature:: AggregateSignature ,
16
21
block_info:: BlockInfo ,
@@ -49,6 +54,21 @@ pub enum BlockType {
49
54
/// Proposal with extensions (e.g. system transactions).
50
55
ProposalExt ( ProposalExt ) ,
51
56
57
+ /// Optimistic proposal
58
+ OptProposal {
59
+ validator_txns : Vec < ValidatorTransaction > ,
60
+ /// T of the block (e.g. one or more transaction(s)
61
+ payload : Payload ,
62
+ /// Author of the block that can be validated by the author's public key and the signature
63
+ author : Author ,
64
+ /// Failed authors from the parent's block to this block.
65
+ /// I.e. the list of consecutive proposers from the
66
+ /// immediately preceeding rounds that didn't produce a successful block.
67
+ failed_authors : Vec < ( Round , Author ) > ,
68
+ /// Grandparent QC, used to generate previous_bitvec
69
+ grandparent_qc : QuorumCert ,
70
+ } ,
71
+
52
72
/// A virtual block that's constructed by nodes from DAG, this is purely a local thing so
53
73
/// we hide it from serde
54
74
#[ serde( skip_deserializing) ]
@@ -63,7 +83,7 @@ pub enum BlockType {
63
83
} ,
64
84
}
65
85
66
- #[ derive( Deserialize , Serialize , Clone , Debug , PartialEq , Eq , CryptoHasher , BCSCryptoHash ) ]
86
+ #[ derive( Deserialize , Serialize , Clone , Debug , PartialEq , Eq , CryptoHasher ) ]
67
87
/// Block has the core data of a consensus block that should be persistent when necessary.
68
88
/// Each block must know the id of its parent and keep the QuorurmCertificate to that parent.
69
89
pub struct BlockData {
@@ -96,12 +116,34 @@ pub struct BlockData {
96
116
block_type : BlockType ,
97
117
}
98
118
119
+ impl CryptoHash for BlockData {
120
+ type Hasher = BlockDataHasher ;
121
+
122
+ fn hash ( & self ) -> HashValue {
123
+ let mut state = Self :: Hasher :: default ( ) ;
124
+ if self . is_opt_block ( ) {
125
+ state. update ( & self . epoch . to_be_bytes ( ) ) ;
126
+ state. update ( & self . round . to_be_bytes ( ) ) ;
127
+ state. update ( & self . timestamp_usecs . to_be_bytes ( ) ) ;
128
+ state. update (
129
+ & bcs:: to_bytes ( self . quorum_cert ( ) . vote_data ( ) )
130
+ . expect ( "Unable to serialize quorum cert vote data" ) ,
131
+ ) ;
132
+ state
133
+ . update ( & bcs:: to_bytes ( self . block_type ( ) ) . expect ( "Unable to serialize block type" ) ) ;
134
+ } else {
135
+ state. update ( & bcs:: to_bytes ( self ) . expect ( "Failed to serialize BlockData" ) ) ;
136
+ }
137
+ state. finish ( )
138
+ }
139
+ }
140
+
99
141
impl BlockData {
100
142
pub fn author ( & self ) -> Option < Author > {
101
143
match & self . block_type {
102
- BlockType :: Proposal { author, .. } | BlockType :: DAGBlock { author , .. } => {
103
- Some ( * author)
104
- } ,
144
+ BlockType :: Proposal { author, .. }
145
+ | BlockType :: OptProposal { author, .. }
146
+ | BlockType :: DAGBlock { author , .. } => Some ( * author ) ,
105
147
BlockType :: ProposalExt ( p) => Some ( * p. author ( ) ) ,
106
148
_ => None ,
107
149
}
@@ -126,11 +168,18 @@ impl BlockData {
126
168
}
127
169
}
128
170
171
+ pub fn grandparent_qc ( & self ) -> Result < QuorumCert > {
172
+ match & self . block_type {
173
+ BlockType :: OptProposal { grandparent_qc, .. } => Ok ( grandparent_qc. clone ( ) ) ,
174
+ _ => bail ! ( "Invalid block type" ) ,
175
+ }
176
+ }
177
+
129
178
pub fn payload ( & self ) -> Option < & Payload > {
130
179
match & self . block_type {
131
- BlockType :: Proposal { payload, .. } | BlockType :: DAGBlock { payload , .. } => {
132
- Some ( payload)
133
- } ,
180
+ BlockType :: Proposal { payload, .. }
181
+ | BlockType :: DAGBlock { payload, .. }
182
+ | BlockType :: OptProposal { payload , .. } => Some ( payload ) ,
134
183
BlockType :: ProposalExt ( p) => p. payload ( ) ,
135
184
_ => None ,
136
185
}
@@ -141,6 +190,9 @@ impl BlockData {
141
190
BlockType :: ProposalExt ( proposal_ext) => proposal_ext. validator_txns ( ) ,
142
191
BlockType :: Proposal { .. } | BlockType :: NilBlock { .. } | BlockType :: Genesis => None ,
143
192
BlockType :: DAGBlock { validator_txns, .. } => Some ( validator_txns) ,
193
+ BlockType :: OptProposal { validator_txns, .. } => {
194
+ ( !validator_txns. is_empty ( ) ) . then_some ( validator_txns)
195
+ } ,
144
196
}
145
197
}
146
198
@@ -176,13 +228,18 @@ impl BlockData {
176
228
matches ! ( self . block_type, BlockType :: NilBlock { .. } )
177
229
}
178
230
231
+ pub fn is_opt_block ( & self ) -> bool {
232
+ matches ! ( self . block_type, BlockType :: OptProposal { .. } )
233
+ }
234
+
179
235
/// the list of consecutive proposers from the immediately preceeding
180
236
/// rounds that didn't produce a successful block
181
237
pub fn failed_authors ( & self ) -> Option < & Vec < ( Round , Author ) > > {
182
238
match & self . block_type {
183
239
BlockType :: Proposal { failed_authors, .. }
184
240
| BlockType :: NilBlock { failed_authors, .. }
185
- | BlockType :: DAGBlock { failed_authors, .. } => Some ( failed_authors) ,
241
+ | BlockType :: DAGBlock { failed_authors, .. }
242
+ | BlockType :: OptProposal { failed_authors, .. } => Some ( failed_authors) ,
186
243
BlockType :: ProposalExt ( p) => Some ( p. failed_authors ( ) ) ,
187
244
BlockType :: Genesis => None ,
188
245
}
@@ -353,6 +410,45 @@ impl BlockData {
353
410
}
354
411
}
355
412
413
+ // Converting OptBlockData to BlockData
414
+ // by adding QC and failed_authors
415
+ pub fn new_from_opt (
416
+ opt_block_data : OptBlockData ,
417
+ quorum_cert : QuorumCert ,
418
+ new_failed_authors : Vec < ( Round , Author ) > ,
419
+ ) -> Result < Self > {
420
+ let OptBlockData {
421
+ epoch,
422
+ round,
423
+ timestamp_usecs,
424
+ parent_id : _,
425
+ block_type,
426
+ } = opt_block_data;
427
+ let block_type = match block_type {
428
+ BlockType :: OptProposal {
429
+ validator_txns,
430
+ payload,
431
+ author,
432
+ failed_authors : _,
433
+ grandparent_qc,
434
+ } => BlockType :: OptProposal {
435
+ validator_txns,
436
+ payload,
437
+ author,
438
+ failed_authors : new_failed_authors,
439
+ grandparent_qc,
440
+ } ,
441
+ _ => bail ! ( "Invalid block type" ) ,
442
+ } ;
443
+ Ok ( Self {
444
+ epoch,
445
+ round,
446
+ timestamp_usecs,
447
+ quorum_cert,
448
+ block_type,
449
+ } )
450
+ }
451
+
356
452
/// It's a reconfiguration suffix block if the parent block's executed state indicates next epoch.
357
453
pub fn is_reconfiguration_suffix ( & self ) -> bool {
358
454
self . quorum_cert . certified_block ( ) . has_reconfiguration ( )
0 commit comments