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

Commit 5fb0be3

Browse files
adoerrandresilva
andauthored
Fix should_vote_on() (#160)
* Fix should_vote_on() * by the textbook * fix the algorithm * Apply review suggestions * don't use NumberFor in vote_target Co-authored-by: André Silva <[email protected]>
1 parent 11786fc commit 5fb0be3

File tree

2 files changed

+121
-22
lines changed

2 files changed

+121
-22
lines changed

client/beefy/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ prometheus = { package = "substrate-prometheus-endpoint", git = "https://github.
1717

1818
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
1919
sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" }
20+
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master" }
2021
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
2122
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
2223
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }

client/beefy/src/worker.rs

Lines changed: 120 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ use sc_network_gossip::GossipEngine;
3232

3333
use sp_api::BlockId;
3434
use sp_application_crypto::{AppPublic, Public};
35+
use sp_arithmetic::traits::AtLeast32Bit;
3536
use sp_core::Pair;
3637
use sp_keystore::{SyncCryptoStore, SyncCryptoStorePtr};
3738
use sp_runtime::{
3839
generic::OpaqueDigestItemId,
39-
traits::{Block, Header, NumberFor, Zero},
40+
traits::{Block, Header, NumberFor},
41+
SaturatedConversion,
4042
};
4143

4244
use beefy_primitives::{
@@ -76,8 +78,6 @@ where
7678
best_grandpa_block: NumberFor<B>,
7779
/// Best block a BEEFY voting round has been concluded for
7880
best_beefy_block: Option<NumberFor<B>>,
79-
/// Best block this node has voted for
80-
best_block_voted_on: NumberFor<B>,
8181
/// Validator set id for the last signed commitment
8282
last_signed_id: u64,
8383
// keep rustc happy
@@ -122,7 +122,6 @@ where
122122
finality_notifications: client.finality_notification_stream(),
123123
best_grandpa_block: client.info().finalized_number,
124124
best_beefy_block: None,
125-
best_block_voted_on: Zero::zero(),
126125
last_signed_id: 0,
127126
_backend: PhantomData,
128127
_pair: PhantomData,
@@ -142,32 +141,20 @@ where
142141
{
143142
/// Return `true`, if we should vote on block `number`
144143
fn should_vote_on(&self, number: NumberFor<B>) -> bool {
145-
use sp_runtime::{traits::Saturating, SaturatedConversion};
146-
147144
let best_beefy_block = if let Some(block) = self.best_beefy_block {
148145
block
149146
} else {
150147
debug!(target: "beefy", "🥩 Missing best BEEFY block - won't vote for: {:?}", number);
151148
return false;
152149
};
153150

154-
let diff = self.best_grandpa_block.saturating_sub(best_beefy_block);
155-
let diff = diff.saturated_into::<u32>();
156-
let next_power_of_two = (diff / 2).next_power_of_two();
157-
let next_block_to_vote_on = self.best_block_voted_on + self.min_block_delta.max(next_power_of_two).into();
151+
let target = vote_target(self.best_grandpa_block, best_beefy_block, self.min_block_delta);
158152

159-
trace!(
160-
target: "beefy",
161-
"should_vote_on: #{:?}, diff: {:?}, next_power_of_two: {:?}, next_block_to_vote_on: #{:?}",
162-
number,
163-
diff,
164-
next_power_of_two,
165-
next_block_to_vote_on,
166-
);
153+
trace!(target: "beefy", "🥩 should_vote_on: #{:?}, next_block_to_vote_on: #{:?}", number, target);
167154

168-
metric_set!(self, beefy_should_vote_on, next_block_to_vote_on);
155+
metric_set!(self, beefy_should_vote_on, target);
169156

170-
number == next_block_to_vote_on
157+
number == target
171158
}
172159

173160
fn sign_commitment(&self, id: &P::Public, commitment: &[u8]) -> Result<P::Signature, error::Crypto<P::Public>> {
@@ -274,8 +261,6 @@ where
274261
}
275262
};
276263

277-
self.best_block_voted_on = *notification.header.number();
278-
279264
let message = VoteMessage {
280265
commitment,
281266
id: local_id,
@@ -402,3 +387,116 @@ where
402387

403388
header.digest().convert_first(|l| l.try_to(id).and_then(filter))
404389
}
390+
391+
/// Calculate next block number to vote on
392+
fn vote_target<N>(best_grandpa: N, best_beefy: N, min_delta: u32) -> N
393+
where
394+
N: AtLeast32Bit + Copy + Debug,
395+
{
396+
let diff = best_grandpa.saturating_sub(best_beefy);
397+
let diff = diff.saturated_into::<u32>();
398+
let target = best_beefy + min_delta.max(diff.next_power_of_two()).into();
399+
400+
trace!(
401+
target: "beefy",
402+
"🥩 vote target - diff: {:?}, next_power_of_two: {:?}, target block: #{:?}",
403+
diff,
404+
diff.next_power_of_two(),
405+
target,
406+
);
407+
408+
target
409+
}
410+
411+
#[cfg(test)]
412+
mod tests {
413+
use super::vote_target;
414+
415+
#[test]
416+
fn vote_on_min_block_delta() {
417+
let t = vote_target(1u32, 0, 4);
418+
assert_eq!(4, t);
419+
let t = vote_target(2u32, 0, 4);
420+
assert_eq!(4, t);
421+
let t = vote_target(3u32, 0, 4);
422+
assert_eq!(4, t);
423+
let t = vote_target(4u32, 0, 4);
424+
assert_eq!(4, t);
425+
426+
let t = vote_target(4u32, 4, 4);
427+
assert_eq!(8, t);
428+
429+
let t = vote_target(10u32, 10, 4);
430+
assert_eq!(14, t);
431+
let t = vote_target(11u32, 10, 4);
432+
assert_eq!(14, t);
433+
let t = vote_target(12u32, 10, 4);
434+
assert_eq!(14, t);
435+
let t = vote_target(13u32, 10, 4);
436+
assert_eq!(14, t);
437+
438+
let t = vote_target(10u32, 10, 8);
439+
assert_eq!(18, t);
440+
let t = vote_target(11u32, 10, 8);
441+
assert_eq!(18, t);
442+
let t = vote_target(12u32, 10, 8);
443+
assert_eq!(18, t);
444+
let t = vote_target(13u32, 10, 8);
445+
assert_eq!(18, t);
446+
}
447+
448+
#[test]
449+
fn vote_on_power_of_two() {
450+
let t = vote_target(1008u32, 1000, 4);
451+
assert_eq!(1008, t);
452+
453+
let t = vote_target(1016u32, 1000, 4);
454+
assert_eq!(1016, t);
455+
456+
let t = vote_target(1032u32, 1000, 4);
457+
assert_eq!(1032, t);
458+
459+
let t = vote_target(1064u32, 1000, 4);
460+
assert_eq!(1064, t);
461+
462+
let t = vote_target(1128u32, 1000, 4);
463+
assert_eq!(1128, t);
464+
465+
let t = vote_target(1256u32, 1000, 4);
466+
assert_eq!(1256, t);
467+
468+
let t = vote_target(1512u32, 1000, 4);
469+
assert_eq!(1512, t);
470+
471+
let t = vote_target(1024u32, 0, 4);
472+
assert_eq!(1024, t);
473+
}
474+
475+
#[test]
476+
fn vote_on_target_block() {
477+
let t = vote_target(1008u32, 1002, 4);
478+
assert_eq!(1010, t);
479+
let t = vote_target(1010u32, 1002, 4);
480+
assert_eq!(1010, t);
481+
482+
let t = vote_target(1016u32, 1006, 4);
483+
assert_eq!(1022, t);
484+
let t = vote_target(1022u32, 1006, 4);
485+
assert_eq!(1022, t);
486+
487+
let t = vote_target(1032u32, 1012, 4);
488+
assert_eq!(1044, t);
489+
let t = vote_target(1044u32, 1012, 4);
490+
assert_eq!(1044, t);
491+
492+
let t = vote_target(1064u32, 1014, 4);
493+
assert_eq!(1078, t);
494+
let t = vote_target(1078u32, 1014, 4);
495+
assert_eq!(1078, t);
496+
497+
let t = vote_target(1128u32, 1008, 4);
498+
assert_eq!(1136, t);
499+
let t = vote_target(1136u32, 1008, 4);
500+
assert_eq!(1136, t);
501+
}
502+
}

0 commit comments

Comments
 (0)