@@ -87,9 +87,23 @@ pub fn verify_finalization_proof(
87
87
Ok ( ( ) )
88
88
}
89
89
90
+ /// Verifies the version of input reserved state is valid.
91
+ pub fn verify_version_syntax ( s : & str ) -> bool {
92
+ let mut segments = s. split ( '.' ) ;
93
+
94
+ let is_valid_segment = |segment : & str | {
95
+ segment. parse :: < u32 > ( ) . map_or ( false , |number| number < 10 )
96
+ } ;
97
+
98
+ segments. next ( ) . map_or ( false , is_valid_segment)
99
+ && segments. next ( ) . map_or ( false , is_valid_segment)
100
+ && segments. next ( ) . map_or ( false , is_valid_segment)
101
+ && segments. next ( ) . is_none ( )
102
+ }
103
+
90
104
// Phases of the `CommitSequenceVerifier`.
91
105
//
92
- // Note that `Phase::X` is agenda phase where `Commit::X` is the last commit.
106
+ // Note that `Phase::X` is the phase where `Commit::X` is the last commit.
93
107
#[ derive( Debug , Clone , PartialEq , Eq ) ]
94
108
enum Phase {
95
109
// The transaction phase.
@@ -131,6 +145,9 @@ pub struct CommitSequenceVerifier {
131
145
impl CommitSequenceVerifier {
132
146
/// Creates a new `CommitSequenceVerifier` with the given block header.
133
147
pub fn new ( start_header : BlockHeader , reserved_state : ReservedState ) -> Result < Self , Error > {
148
+ // if verify_reserved_state(&self, reserved_state)? {
149
+ // return Err(Error::InvalidArgument(format!("Reserved state is not valid")));
150
+ // }
134
151
Ok ( Self {
135
152
header : start_header. clone ( ) ,
136
153
phase : Phase :: Block ,
@@ -173,21 +190,43 @@ impl CommitSequenceVerifier {
173
190
174
191
/// Verifies whether the given reserved state is valid from the current state.
175
192
pub fn verify_reserved_state ( & self , _rs : & ReservedState ) -> Result < ( ) , Error > {
176
- // TODO:
177
- // 1. Check that the number of members is at least 4.
178
- // 2. Check that the version advances correctly.
193
+ if _rs. members . len ( ) < 4 {
194
+ return Err ( Error :: InvalidArgument ( format ! ( "Number of members is not over 4" ) ) ) ;
195
+ }
196
+ if self . reserved_state . version != _rs. version {
197
+ if !( self . reserved_state . version < _rs. version && verify_version_syntax ( & _rs. version ) ) {
198
+ return Err ( Error :: InvalidArgument ( format ! ( "Version advances is incorrect" ) ) ) ;
199
+ }
200
+ }
179
201
// 3. Check that `consensus_leader_order` is correct.
180
- // 4. Check that `genesis_info` stays the same.
202
+ if self . reserved_state . consensus_leader_order != _rs. consensus_leader_order {
203
+ return Err ( Error :: InvalidArgument ( format ! ( "Consensus leader order is incorrect" ) ) ) ;
204
+ }
205
+ if self . reserved_state . genesis_info != _rs. genesis_info {
206
+ return Err ( Error :: InvalidArgument ( format ! ( "Genesis_info is not stays the same" ) ) ) ;
207
+ }
181
208
// 5. Check that the newly added (if exists) `Member::name` is unique.
182
- // 6. Check that `member` monotonicaly increases (refer to `Member::expelled`).
183
- // 7. Check that the delegation state doesn't change.
209
+ if !self . reserved_state . members . iter ( ) . all ( |m1| _rs. members . iter ( ) . any ( |m2| m1. public_key == m2. public_key ) ) {
210
+ return Err ( Error :: InvalidArgument ( format ! ( "New member set do not have all previous member" ) ) ) ;
211
+ }
212
+ let public_key_set: HashSet < & PublicKey > = _rs. members . iter ( ) . map ( |m| & m. public_key ) . collect ( ) ;
213
+ if public_key_set. len ( ) != _rs. members . len ( ) {
214
+ return Err ( Error :: InvalidArgument ( format ! ( "Newly added member public keys are not unique" ) ) ) ;
215
+ }
216
+ // 6. Check that `member` monotonic increases (refer to `Member::expelled`).
217
+ if _rs. members . iter ( ) . any ( |member| member. expelled ) {
218
+ return Err ( Error :: InvalidArgument ( format ! ( "Member expulsion time not monotonic increasing" ) ) ) ;
219
+ }
184
220
Ok ( ( ) )
185
221
}
186
222
187
223
/// Verifies the given commit and updates the internal reserved_state of CommitSequenceVerifier.
188
224
pub fn apply_commit ( & mut self , commit : & Commit ) -> Result < ( ) , Error > {
189
225
match ( commit, & mut self . phase ) {
190
226
( Commit :: Block ( block_header) , Phase :: AgendaProof { agenda_proof : _ } ) => {
227
+ if self . reserved_state . version != block_header. version {
228
+ return Err ( Error :: InvalidArgument ( format ! ( "Version of header is not match reserved_state" ) ) ) ;
229
+ }
191
230
verify_header_to_header ( & self . header , block_header) ?;
192
231
// Verify commit merkle root
193
232
let commit_merkle_root =
@@ -202,12 +241,10 @@ impl CommitSequenceVerifier {
202
241
self . phase = Phase :: Block ;
203
242
self . commits_for_next_block = vec ! [ ] ;
204
243
}
205
- (
206
- Commit :: Block ( block_header) ,
207
- Phase :: ExtraAgendaTransaction {
208
- last_extra_agenda_timestamp,
209
- } ,
210
- ) => {
244
+ ( Commit :: Block ( block_header) , Phase :: ExtraAgendaTransaction { last_extra_agenda_timestamp, } ) => {
245
+ if self . reserved_state . version != block_header. version {
246
+ return Err ( Error :: InvalidArgument ( format ! ( "Version of header is not match reserved_state" ) ) ) ;
247
+ }
211
248
verify_header_to_header ( & self . header , block_header) ?;
212
249
// Check if the block contains all the extra-agenda transactions.
213
250
if block_header. timestamp < * last_extra_agenda_timestamp {
@@ -232,20 +269,15 @@ impl CommitSequenceVerifier {
232
269
( Commit :: Transaction ( tx) , Phase :: Block ) => {
233
270
// Update reserved_state for reserved-diff transactions.
234
271
if let Diff :: Reserved ( rs) = & tx. diff {
272
+ self . verify_reserved_state ( rs) ?;
235
273
self . reserved_state = * rs. clone ( ) ;
236
274
}
237
275
self . phase = Phase :: Transaction {
238
276
last_transaction : tx. clone ( ) ,
239
277
preceding_transactions : vec ! [ ] ,
240
278
} ;
241
279
}
242
- (
243
- Commit :: Transaction ( tx) ,
244
- Phase :: Transaction {
245
- last_transaction,
246
- preceding_transactions,
247
- } ,
248
- ) => {
280
+ ( Commit :: Transaction ( tx) , Phase :: Transaction { last_transaction, preceding_transactions} ) => {
249
281
// Check if transactions are in chronological order
250
282
if tx. timestamp < last_transaction. timestamp {
251
283
return Err ( Error :: InvalidArgument ( format ! (
@@ -255,6 +287,7 @@ impl CommitSequenceVerifier {
255
287
}
256
288
// Update reserved_state for reserved-diff transactions.
257
289
if let Diff :: Reserved ( rs) = & tx. diff {
290
+ self . verify_reserved_state ( rs) ?;
258
291
self . reserved_state = * rs. clone ( ) ;
259
292
}
260
293
preceding_transactions. push ( last_transaction. clone ( ) ) ;
@@ -281,13 +314,7 @@ impl CommitSequenceVerifier {
281
314
agenda : agenda. clone ( ) ,
282
315
} ;
283
316
}
284
- (
285
- Commit :: Agenda ( agenda) ,
286
- Phase :: Transaction {
287
- last_transaction,
288
- preceding_transactions,
289
- } ,
290
- ) => {
317
+ ( Commit :: Agenda ( agenda) , Phase :: Transaction { last_transaction, preceding_transactions} ) => {
291
318
// Check if agenda is associated with the current block sequence.
292
319
if agenda. height != self . header . height + 1 {
293
320
return Err ( Error :: InvalidArgument ( format ! (
@@ -398,12 +425,7 @@ impl CommitSequenceVerifier {
398
425
ExtraAgendaTransaction :: Report ( _tx) => unimplemented ! ( ) ,
399
426
}
400
427
}
401
- (
402
- Commit :: ExtraAgendaTransaction ( tx) ,
403
- Phase :: ExtraAgendaTransaction {
404
- last_extra_agenda_timestamp,
405
- } ,
406
- ) => {
428
+ ( Commit :: ExtraAgendaTransaction ( tx) , Phase :: ExtraAgendaTransaction { last_extra_agenda_timestamp} ) => {
407
429
match tx {
408
430
ExtraAgendaTransaction :: Delegate ( tx) => {
409
431
// Update reserved reserved_state by applying delegation
@@ -434,8 +456,7 @@ impl CommitSequenceVerifier {
434
456
ExtraAgendaTransaction :: Report ( _tx) => unimplemented ! ( ) ,
435
457
}
436
458
}
437
- ( Commit :: ChatLog ( _chat_log) , _) => unimplemented ! ( ) ,
438
- ( commit, phase) => {
459
+ ( Commit :: ChatLog ( _chat_log) , _) => unimplemented ! ( ) , ( commit, phase) => {
439
460
return Err ( Error :: PhaseMismatch (
440
461
format ! ( "{commit:?}" ) ,
441
462
format ! ( "{phase:?}" ) ,
@@ -498,6 +519,7 @@ mod test {
498
519
consensus_voting_power : * voting_power,
499
520
governance_delegatee : None ,
500
521
consensus_delegatee : None ,
522
+ expelled : false ,
501
523
} ) ;
502
524
}
503
525
members
@@ -582,6 +604,7 @@ mod test {
582
604
consensus_voting_power : 1 ,
583
605
governance_delegatee : None ,
584
606
consensus_delegatee : None ,
607
+ expelled : false ,
585
608
} ) ;
586
609
reserved_state
587
610
. consensus_leader_order
@@ -1567,4 +1590,16 @@ mod test {
1567
1590
1568
1591
// TODO: add test cases where the `Report` extra-agenda transactions are invalid.
1569
1592
// These test cases are TODO because the `Report` extra-agenda transaction is not implemented yet.
1593
+
1594
+ //#[test]
1595
+ // Test the case where check verify_reserved_state function run well
1596
+ // fn check_verify_reserved_state_run() {
1597
+ // let (validator_keypair, reserved_state, mut csv) = setup_test(3);
1598
+ // csv.verify_reserved_state(&reserved_state).unwrap_err();
1599
+
1600
+
1601
+ // //make wrong reserved_state
1602
+ // //chech vrs function
1603
+
1604
+ // }
1570
1605
}
0 commit comments