Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 639790a

Browse files
authored
Track BEEFY validator set (#94)
* Track BEEFY validator set * Add validator_set_id to BeefyWorker * Make validattor_set_id optional
1 parent 5aef902 commit 639790a

File tree

4 files changed

+70
-29
lines changed

4 files changed

+70
-29
lines changed

client/beefy/src/lib.rs

+47-12
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ use futures::{future, FutureExt, Stream, StreamExt};
2424
use log::{debug, error, info, trace, warn};
2525
use parking_lot::Mutex;
2626

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+
};
2831

2932
use sc_client_api::{Backend as BackendT, BlockchainEvents, FinalityNotification, Finalizer};
3033
use sc_network_gossip::{
@@ -194,6 +197,7 @@ struct BeefyWorker<Block: BlockT, Id, Signature, FinalityNotifications> {
194197
signed_commitment_sender: BeefySignedCommitmentSender<Block, Signature>,
195198
best_finalized_block: NumberFor<Block>,
196199
best_block_voted_on: NumberFor<Block>,
200+
validator_set_id: Option<ValidatorSetId>,
197201
}
198202

199203
impl<Block, Id, Signature, FinalityNotifications> BeefyWorker<Block, Id, Signature, FinalityNotifications>
@@ -210,6 +214,7 @@ where
210214
signed_commitment_sender: BeefySignedCommitmentSender<Block, Signature>,
211215
best_finalized_block: NumberFor<Block>,
212216
best_block_voted_on: NumberFor<Block>,
217+
validator_set_id: Option<ValidatorSetId>,
213218
) -> Self {
214219
BeefyWorker {
215220
local_id,
@@ -221,6 +226,7 @@ where
221226
signed_commitment_sender,
222227
best_finalized_block,
223228
best_block_voted_on,
229+
validator_set_id,
224230
}
225231
}
226232
}
@@ -259,7 +265,7 @@ where
259265
}
260266

261267
fn handle_finality_notification(&mut self, notification: FinalityNotification<Block>) {
262-
debug!(target: "beefy", "Finality notification: {:?}", notification);
268+
debug!(target: "beefy", "🥩 Finality notification: {:?}", notification);
263269

264270
if self.should_vote_on(*notification.header.number()) {
265271
let local_id = if let BeefyId::Validator(id) = &self.local_id {
@@ -276,12 +282,22 @@ where
276282
return;
277283
};
278284

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+
281297
let commitment = Commitment {
282298
payload: mmr_root,
283299
block_number: notification.header.number(),
284-
validator_set_id: 0,
300+
validator_set_id: current_set_id,
285301
};
286302

287303
// TODO #92
@@ -299,7 +315,7 @@ where
299315
}) {
300316
Ok(sig) => sig,
301317
Err(err) => {
302-
warn!(target: "beefy", "Error signing: {:?}", err);
318+
warn!(target: "beefy", "🥩 Error signing: {:?}", err);
303319
return;
304320
}
305321
};
@@ -316,7 +332,7 @@ where
316332
.lock()
317333
.gossip_message(topic::<Block>(), message.encode(), false);
318334

319-
debug!(target: "beefy", "Sent vote message: {:?}", message);
335+
debug!(target: "beefy", "🥩 Sent vote message: {:?}", message);
320336

321337
self.handle_vote(
322338
(message.commitment.payload, *message.commitment.block_number),
@@ -333,12 +349,12 @@ where
333349

334350
if vote_added && self.rounds.is_done(&round) {
335351
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).
338352
let commitment = Commitment {
339353
payload: round.0,
340354
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"),
342358
};
343359

344360
let signed_commitment = SignedCommitment { commitment, signatures };
@@ -353,7 +369,7 @@ where
353369
async fn run(mut self) {
354370
let mut votes = Box::pin(self.gossip_engine.lock().messages_for(topic::<Block>()).filter_map(
355371
|notification| async move {
356-
debug!(target: "beefy", "Got vote message: {:?}", notification);
372+
debug!(target: "beefy", "🥩 Got vote message: {:?}", notification);
357373

358374
VoteMessage::<MmrRootHash, NumberFor<Block>, Id, Signature>::decode(&mut &notification.message[..]).ok()
359375
},
@@ -382,7 +398,7 @@ where
382398
}
383399
},
384400
_ = gossip_engine.fuse() => {
385-
error!(target: "beefy", "Gossip engine has terminated.");
401+
error!(target: "beefy", "🥩 Gossip engine has terminated.");
386402
return;
387403
}
388404
}
@@ -453,6 +469,8 @@ pub async fn start_beefy_gadget<Block, Pair, Backend, Client, Network, SyncOracl
453469
signed_commitment_sender,
454470
best_finalized_block,
455471
best_block_voted_on,
472+
// TODO #95
473+
Some(0),
456474
);
457475

458476
worker.run().await
@@ -470,3 +488,20 @@ where
470488
}
471489
})
472490
}
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+
}

frame/beefy/src/lib.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use sp_runtime::{
2727
};
2828
use sp_std::prelude::*;
2929

30-
use beefy_primitives::{AuthorityIndex, ConsensusLog, BEEFY_ENGINE_ID};
30+
use beefy_primitives::{AuthorityIndex, ConsensusLog, ValidatorSet, BEEFY_ENGINE_ID};
3131

3232
#[cfg(test)]
3333
mod mock;
@@ -102,15 +102,15 @@ impl<T: Config> Pallet<T> {
102102
if new != Self::authorities() {
103103
<Authorities<T>>::put(&new);
104104

105-
let next = Self::validator_set_id() + 1u64;
106-
<ValidatorSetId<T>>::put(next);
105+
let next_id = Self::validator_set_id() + 1u64;
106+
<ValidatorSetId<T>>::put(next_id);
107107

108108
let log: DigestItem<T::Hash> = DigestItem::Consensus(
109109
BEEFY_ENGINE_ID,
110-
ConsensusLog::AuthoritiesChange {
111-
new_validator_set: new,
112-
new_validator_set_id: next,
113-
}
110+
ConsensusLog::AuthoritiesChange(ValidatorSet {
111+
validators: new,
112+
id: next_id,
113+
})
114114
.encode(),
115115
);
116116
<frame_system::Module<T>>::deposit_log(log);

frame/beefy/src/tests.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
use std::vec;
1818

19+
use beefy_primitives::ValidatorSet;
1920
use codec::Encode;
2021

2122
use sp_core::H256;
@@ -69,16 +70,17 @@ fn session_change_updates_authorities() {
6970

7071
assert!(1 == Beefy::validator_set_id());
7172

72-
let want = beefy_log(ConsensusLog::AuthoritiesChange {
73-
new_validator_set: vec![mock_beefy_id(3), mock_beefy_id(4)],
74-
new_validator_set_id: 1,
75-
});
73+
let want = beefy_log(ConsensusLog::AuthoritiesChange(ValidatorSet {
74+
validators: vec![mock_beefy_id(3), mock_beefy_id(4)],
75+
id: 1,
76+
}));
7677

7778
let log = System::digest().logs[0].clone();
7879

7980
assert_eq!(want, log);
8081
});
8182
}
83+
8284
#[test]
8385
fn session_change_updates_next_authorities() {
8486
let want = vec![mock_beefy_id(1), mock_beefy_id(2), mock_beefy_id(3), mock_beefy_id(4)];

primitives/beefy/src/lib.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ pub const BEEFY_ENGINE_ID: sp_runtime::ConsensusEngineId = *b"BEEF";
6969
/// A typedef for validator set id.
7070
pub type ValidatorSetId = u64;
7171

72+
/// A set of BEEFY authorities, a.k.a. validators.
73+
#[derive(Decode, Encode, Debug)]
74+
pub struct ValidatorSet<AuthorityId> {
75+
/// Public keys of the validator set elements
76+
pub validators: Vec<AuthorityId>,
77+
/// Identifier of the validator set
78+
pub id: ValidatorSetId,
79+
}
80+
7281
/// The index of an authority.
7382
pub type AuthorityIndex = u32;
7483

@@ -80,12 +89,7 @@ pub type MmrRootHash = H256;
8089
pub enum ConsensusLog<AuthorityId: Codec> {
8190
/// The authorities have changed.
8291
#[codec(index = 1)]
83-
AuthoritiesChange {
84-
/// Set of new validators to be used
85-
new_validator_set: Vec<AuthorityId>,
86-
/// Id for this new set of validators
87-
new_validator_set_id: ValidatorSetId,
88-
},
92+
AuthoritiesChange(ValidatorSet<AuthorityId>),
8993
/// Disable the authority with given index.
9094
#[codec(index = 2)]
9195
OnDisabled(AuthorityIndex),

0 commit comments

Comments
 (0)