@@ -24,7 +24,10 @@ use futures::{future, FutureExt, Stream, StreamExt};
24
24
use log:: { debug, error, info, trace, warn} ;
25
25
use parking_lot:: Mutex ;
26
26
27
- use beefy_primitives:: { BeefyApi , Commitment , ConsensusLog , MmrRootHash , SignedCommitment , BEEFY_ENGINE_ID , KEY_TYPE } ;
27
+ use beefy_primitives:: {
28
+ BeefyApi , Commitment , ConsensusLog , MmrRootHash , SignedCommitment , ValidatorSet , ValidatorSetId , BEEFY_ENGINE_ID ,
29
+ KEY_TYPE ,
30
+ } ;
28
31
29
32
use sc_client_api:: { Backend as BackendT , BlockchainEvents , FinalityNotification , Finalizer } ;
30
33
use sc_network_gossip:: {
@@ -194,6 +197,7 @@ struct BeefyWorker<Block: BlockT, Id, Signature, FinalityNotifications> {
194
197
signed_commitment_sender : BeefySignedCommitmentSender < Block , Signature > ,
195
198
best_finalized_block : NumberFor < Block > ,
196
199
best_block_voted_on : NumberFor < Block > ,
200
+ validator_set_id : Option < ValidatorSetId > ,
197
201
}
198
202
199
203
impl < Block , Id , Signature , FinalityNotifications > BeefyWorker < Block , Id , Signature , FinalityNotifications >
@@ -210,6 +214,7 @@ where
210
214
signed_commitment_sender : BeefySignedCommitmentSender < Block , Signature > ,
211
215
best_finalized_block : NumberFor < Block > ,
212
216
best_block_voted_on : NumberFor < Block > ,
217
+ validator_set_id : Option < ValidatorSetId > ,
213
218
) -> Self {
214
219
BeefyWorker {
215
220
local_id,
@@ -221,6 +226,7 @@ where
221
226
signed_commitment_sender,
222
227
best_finalized_block,
223
228
best_block_voted_on,
229
+ validator_set_id,
224
230
}
225
231
}
226
232
}
@@ -259,7 +265,7 @@ where
259
265
}
260
266
261
267
fn handle_finality_notification ( & mut self , notification : FinalityNotification < Block > ) {
262
- debug ! ( target: "beefy" , "Finality notification: {:?}" , notification) ;
268
+ debug ! ( target: "beefy" , "🥩 Finality notification: {:?}" , notification) ;
263
269
264
270
if self . should_vote_on ( * notification. header . number ( ) ) {
265
271
let local_id = if let BeefyId :: Validator ( id) = & self . local_id {
@@ -276,12 +282,22 @@ where
276
282
return ;
277
283
} ;
278
284
279
- // TODO: this needs added support for validator set changes (and abstracting the
280
- // "thing to sign" would be nice).
285
+ if let Some ( new) = find_authorities_change :: < Block , Id > ( & notification. header ) {
286
+ debug ! ( target: "beefy" , "🥩 New validator set: {:?}" , new) ;
287
+ self . validator_set_id = Some ( new. id ) ;
288
+ } ;
289
+
290
+ let current_set_id = if let Some ( set_id) = self . validator_set_id {
291
+ set_id
292
+ } else {
293
+ warn ! ( target: "beefy" , "🥩 Unknown validator set id - can't vote for: {:?}" , notification. header. hash( ) ) ;
294
+ return ;
295
+ } ;
296
+
281
297
let commitment = Commitment {
282
298
payload : mmr_root,
283
299
block_number : notification. header . number ( ) ,
284
- validator_set_id : 0 ,
300
+ validator_set_id : current_set_id ,
285
301
} ;
286
302
287
303
// TODO #92
@@ -299,7 +315,7 @@ where
299
315
} ) {
300
316
Ok ( sig) => sig,
301
317
Err ( err) => {
302
- warn ! ( target: "beefy" , "Error signing: {:?}" , err) ;
318
+ warn ! ( target: "beefy" , "🥩 Error signing: {:?}" , err) ;
303
319
return ;
304
320
}
305
321
} ;
@@ -316,7 +332,7 @@ where
316
332
. lock ( )
317
333
. gossip_message ( topic :: < Block > ( ) , message. encode ( ) , false ) ;
318
334
319
- debug ! ( target: "beefy" , "Sent vote message: {:?}" , message) ;
335
+ debug ! ( target: "beefy" , "🥩 Sent vote message: {:?}" , message) ;
320
336
321
337
self . handle_vote (
322
338
( message. commitment . payload , * message. commitment . block_number ) ,
@@ -333,12 +349,12 @@ where
333
349
334
350
if vote_added && self . rounds . is_done ( & round) {
335
351
if let Some ( signatures) = self . rounds . drop ( & round) {
336
- // TODO: this needs added support for validator set changes (and abstracting the
337
- // "thing to sign" would be nice).
338
352
let commitment = Commitment {
339
353
payload : round. 0 ,
340
354
block_number : round. 1 ,
341
- validator_set_id : 0 ,
355
+ validator_set_id : self
356
+ . validator_set_id
357
+ . expect ( "We voted only in case of a valid validator_set_id; qed" ) ,
342
358
} ;
343
359
344
360
let signed_commitment = SignedCommitment { commitment, signatures } ;
@@ -353,7 +369,7 @@ where
353
369
async fn run ( mut self ) {
354
370
let mut votes = Box :: pin ( self . gossip_engine . lock ( ) . messages_for ( topic :: < Block > ( ) ) . filter_map (
355
371
|notification| async move {
356
- debug ! ( target: "beefy" , "Got vote message: {:?}" , notification) ;
372
+ debug ! ( target: "beefy" , "🥩 Got vote message: {:?}" , notification) ;
357
373
358
374
VoteMessage :: < MmrRootHash , NumberFor < Block > , Id , Signature > :: decode ( & mut & notification. message [ ..] ) . ok ( )
359
375
} ,
@@ -382,7 +398,7 @@ where
382
398
}
383
399
} ,
384
400
_ = gossip_engine. fuse( ) => {
385
- error!( target: "beefy" , "Gossip engine has terminated." ) ;
401
+ error!( target: "beefy" , "🥩 Gossip engine has terminated." ) ;
386
402
return ;
387
403
}
388
404
}
@@ -453,6 +469,8 @@ pub async fn start_beefy_gadget<Block, Pair, Backend, Client, Network, SyncOracl
453
469
signed_commitment_sender,
454
470
best_finalized_block,
455
471
best_block_voted_on,
472
+ // TODO #95
473
+ Some ( 0 ) ,
456
474
) ;
457
475
458
476
worker. run ( ) . await
@@ -470,3 +488,20 @@ where
470
488
}
471
489
} )
472
490
}
491
+
492
+ /// Scan the `header` digest log for a BEEFY validator set change. Return either the new
493
+ /// validator set or `None` in case no validator set change has been signaled.
494
+ fn find_authorities_change < B , Id > ( header : & B :: Header ) -> Option < ValidatorSet < Id > >
495
+ where
496
+ B : BlockT ,
497
+ Id : Codec ,
498
+ {
499
+ let id = OpaqueDigestItemId :: Consensus ( & BEEFY_ENGINE_ID ) ;
500
+
501
+ let filter = |log : ConsensusLog < Id > | match log {
502
+ ConsensusLog :: AuthoritiesChange ( validator_set) => Some ( validator_set) ,
503
+ _ => None ,
504
+ } ;
505
+
506
+ header. digest ( ) . convert_first ( |l| l. try_to ( id) . and_then ( filter) )
507
+ }
0 commit comments