make BFT function name more self-descriptive and align implementation with paper
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
parent
66bf42cbd3
commit
3cf96b1820
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -3684,7 +3684,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-exodus"
|
||||
version = "0.0.7"
|
||||
version = "0.0.8"
|
||||
dependencies = [
|
||||
"chacha20poly1305",
|
||||
"frame-benchmarking",
|
||||
@ -3757,7 +3757,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-helpers"
|
||||
version = "0.0.6"
|
||||
version = "0.0.7"
|
||||
dependencies = [
|
||||
"frame-support",
|
||||
"ghost-traits",
|
||||
@ -4109,7 +4109,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ghost-weaver"
|
||||
version = "0.0.4"
|
||||
version = "0.0.5"
|
||||
dependencies = [
|
||||
"frame-benchmarking",
|
||||
"frame-support",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ghost-exodus"
|
||||
version = "0.0.7"
|
||||
version = "0.0.8"
|
||||
description = "Threshold signature generation with DKG included"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
@ -74,7 +74,7 @@ mod benchmarks {
|
||||
c: Linear<4, { T::MaxAuthorities::get() }>
|
||||
) -> Result<(), BenchmarkError> {
|
||||
let max_signers = c as AuthIndex;
|
||||
let min_signers = get_byzantium_threshold(max_signers);
|
||||
let min_signers = get_byzantium_quorum_threshold(max_signers);
|
||||
|
||||
let (mut dkg_state, network_curve, authority, authority_index) =
|
||||
prepare_pallet::<T>(max_signers as usize);
|
||||
@ -637,7 +637,7 @@ mod benchmarks {
|
||||
#[benchmark]
|
||||
fn register_signature_share() -> Result<(), BenchmarkError> {
|
||||
let max_signers = T::MaxAuthorities::get();
|
||||
let threshold = get_byzantium_threshold(max_signers);
|
||||
let threshold = get_byzantium_quorum_threshold(max_signers);
|
||||
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
|
||||
|
||||
let (mut dkg_state, network_curve, authority, authority_index) =
|
||||
|
||||
@ -29,7 +29,7 @@ use sp_runtime::traits::BlockNumberProvider;
|
||||
use sp_io::hashing::blake2_256;
|
||||
|
||||
use ghost_helpers::{
|
||||
get_byzantium_threshold, SubstrateBlake2Hasher,
|
||||
get_byzantium_quorum_threshold, SubstrateBlake2Hasher,
|
||||
hash_chain::sequential_hash,
|
||||
networks::{NetworkData, NetworkCurve, NetworkType},
|
||||
bounded_bitmap::{validate_bitmap_sizes, BoundedBitmap},
|
||||
@ -263,7 +263,7 @@ pub struct Round1MaxBytes<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> Get<u32> for Round1MaxBytes<T> {
|
||||
fn get() -> u32 {
|
||||
let max_authorities = T::MaxAuthorities::get();
|
||||
let min_authorities = get_byzantium_threshold(max_authorities);
|
||||
let min_authorities = get_byzantium_quorum_threshold(max_authorities);
|
||||
|
||||
round1_package_size(
|
||||
min_authorities as usize,
|
||||
@ -324,7 +324,7 @@ pub struct BindingFactorsProof<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Config> Get<u32> for BindingFactorsProof<T> {
|
||||
fn get() -> u32 {
|
||||
let max_authorities = T::MaxAuthorities::get();
|
||||
get_byzantium_threshold(max_authorities)
|
||||
get_byzantium_quorum_threshold(max_authorities)
|
||||
.next_power_of_two()
|
||||
.trailing_zeros()
|
||||
}
|
||||
@ -1422,7 +1422,7 @@ pub mod pallet {
|
||||
};
|
||||
|
||||
let threshold = ActiveAuthorities::<T>::decode_len(&network_curve)
|
||||
.map(|max_participants| get_byzantium_threshold(max_participants))
|
||||
.map(|max_participants| get_byzantium_quorum_threshold(max_participants))
|
||||
.ok_or(Error::<T>::DkgAuthoritiesNotInitialized)?;
|
||||
|
||||
let exodus_session = package.session;
|
||||
@ -1515,7 +1515,7 @@ pub mod pallet {
|
||||
let max_authorities = ActiveAuthorities::<T>::decode_len(&network_curve)
|
||||
.ok_or(Error::<T>::DkgAuthoritiesNotInitialized)?;
|
||||
|
||||
let threshold = get_byzantium_threshold(max_authorities);
|
||||
let threshold = get_byzantium_quorum_threshold(max_authorities);
|
||||
let exodus_session = package.session;
|
||||
|
||||
ensure!(
|
||||
@ -1633,7 +1633,7 @@ pub mod pallet {
|
||||
};
|
||||
|
||||
let threshold = ActiveAuthorities::<T>::decode_len(&network_curve)
|
||||
.map(|max_participants| get_byzantium_threshold(max_participants))
|
||||
.map(|max_participants| get_byzantium_quorum_threshold(max_participants))
|
||||
.ok_or(Error::<T>::DkgAuthoritiesNotInitialized)?;
|
||||
|
||||
let exodus_session = package.session;
|
||||
@ -1898,7 +1898,7 @@ pub mod pallet {
|
||||
None => return weight,
|
||||
};
|
||||
|
||||
let min_threshold = get_byzantium_threshold(qualification_len);
|
||||
let min_threshold = get_byzantium_quorum_threshold(qualification_len);
|
||||
|
||||
weight.saturating_accrue(T::DbWeight::get().reads(1));
|
||||
let maybe_cursor = DkgMaybeCursor::<T>::get(&network_curve);
|
||||
@ -2711,7 +2711,7 @@ impl<T: Config> Pallet<T> {
|
||||
}
|
||||
|
||||
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
||||
let expected_count = get_byzantium_threshold(authorities.len());
|
||||
let expected_count = get_byzantium_quorum_threshold(authorities.len());
|
||||
|
||||
let expected_package_len = round1_package_size(
|
||||
expected_count,
|
||||
@ -3283,7 +3283,7 @@ impl<T: Config> Pallet<T> {
|
||||
let max_authorities = ActiveAuthorities::<T>::decode_len(&network_curve)
|
||||
.ok_or(ExodusError::NoActiveAuthorities)?;
|
||||
|
||||
let threshold = get_byzantium_threshold(max_authorities);
|
||||
let threshold = get_byzantium_quorum_threshold(max_authorities);
|
||||
|
||||
let mut exodus_requests = ExodusRequests::<T>::iter_prefix(&network_curve)
|
||||
.collect::<Vec<(ExodusSession, ExodusRequest<_, _>)>>();
|
||||
@ -3732,7 +3732,7 @@ impl<T: Config> Pallet<T> {
|
||||
.map(|max_signers| max_signers as AuthIndex)
|
||||
.ok_or(ExodusError::InvalidMaxSigners(0))?;
|
||||
|
||||
let min_signers = get_byzantium_threshold(max_signers);
|
||||
let min_signers = get_byzantium_quorum_threshold(max_signers);
|
||||
|
||||
if qualification_state.contains_index(authority_index) {
|
||||
return Ok(ExodusOk::DkgRoundAlreadyPassed(
|
||||
|
||||
@ -841,7 +841,7 @@ fn run_dkg_session(
|
||||
let threshold = ext.execute_with(|| {
|
||||
let len = ActiveAuthorities::<Runtime>::decode_len(&curve)
|
||||
.unwrap_or(0);
|
||||
get_byzantium_threshold(len) as u16
|
||||
get_byzantium_quorum_threshold(len) as u16
|
||||
});
|
||||
|
||||
let mut exodus_steps_outer = BTreeMap::new();
|
||||
@ -1259,7 +1259,7 @@ fn test_exodus_dkg_robustness() {
|
||||
assert_eq!(state.get_dkg_index(), dkg_index);
|
||||
assert_eq!(state.get_phase(), DkgPhase::Finalized);
|
||||
|
||||
let bft_threshold = get_byzantium_threshold(authorities_len);
|
||||
let bft_threshold = get_byzantium_quorum_threshold(authorities_len);
|
||||
assert!(qualification_count >= bft_threshold);
|
||||
assert!(state.count_ones::<usize>() >= bft_threshold);
|
||||
assert_eq!(state.get_indexes().active_bits_count(), authorities_len as u32);
|
||||
@ -1299,7 +1299,7 @@ fn test_prepare_round4_abort_on_byzantine_attack() {
|
||||
}
|
||||
}
|
||||
|
||||
let bft_threshold = get_byzantium_threshold(authorities_len);
|
||||
let bft_threshold = get_byzantium_quorum_threshold(authorities_len);
|
||||
ext.execute_with(|| {
|
||||
let mut complaints_map = BitmapByAuthority::<Runtime>::default();
|
||||
for authority in 0..=bft_threshold {
|
||||
@ -1344,7 +1344,7 @@ fn test_prepare_round5_abort_on_byzantine_attack() {
|
||||
}
|
||||
}
|
||||
|
||||
let bft_threshold = get_byzantium_threshold(authorities_len);
|
||||
let bft_threshold = get_byzantium_quorum_threshold(authorities_len);
|
||||
ext.execute_with(|| {
|
||||
let mut justifications_map = BitmapByAuthority::<Runtime>::default();
|
||||
for authority in 0..=bft_threshold {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ghost-helpers"
|
||||
version = "0.0.6"
|
||||
version = "0.0.7"
|
||||
description = "Cryptographic utility suite for custom runtimes: optimized Bitmaps, UTXO parsing, Merkle Tree proofs, and Hash Chain components."
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
@ -34,20 +34,18 @@ pub type NetworkIdU32 = u32;
|
||||
pub type NetworkIdU64 = u64;
|
||||
pub type NetworkIdU128 = u128;
|
||||
|
||||
pub fn get_byzantium_threshold<I>(value: I) -> I
|
||||
pub fn get_byzantium_quorum_threshold<I>(value: I) -> I
|
||||
where
|
||||
I: num_traits::PrimInt,
|
||||
{
|
||||
let zero = I::zero();
|
||||
let one = I::one();
|
||||
let two = one + one;
|
||||
let three = two + one;
|
||||
let three = one + one + one;
|
||||
|
||||
if value == zero {
|
||||
return zero;
|
||||
}
|
||||
if value == zero { return zero; }
|
||||
|
||||
(value - one) / three * two + one
|
||||
let f = (value - one) / three;
|
||||
value - f
|
||||
}
|
||||
|
||||
pub struct SubstrateBlake2Hasher;
|
||||
@ -97,3 +95,43 @@ impl GhostHasher for UtxoSha2Hasher {
|
||||
H256::zero()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_bft_threshold_standard_paper_cases() {
|
||||
// Lower boundaries (f increases here)
|
||||
assert_eq!(get_byzantium_quorum_threshold(1u32), 1);
|
||||
assert_eq!(get_byzantium_quorum_threshold(4u32), 3);
|
||||
assert_eq!(get_byzantium_quorum_threshold(7u32), 5);
|
||||
assert_eq!(get_byzantium_quorum_threshold(10u32), 7);
|
||||
|
||||
// Upper boundaries (max nodes for a given 'f')
|
||||
assert_eq!(get_byzantium_quorum_threshold(3u32), 3);
|
||||
assert_eq!(get_byzantium_quorum_threshold(6u32), 5);
|
||||
assert_eq!(get_byzantium_quorum_threshold(9u32), 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bft_threshold_zero_nodes() {
|
||||
assert_eq!(get_byzantium_quorum_threshold(0u32), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bft_threshold_integer_boundaries() {
|
||||
let max_val = usize::MAX;
|
||||
let expected_f = (max_val - 1) / 3;
|
||||
let expected_honest = max_val - expected_f;
|
||||
|
||||
assert_eq!(get_byzantium_quorum_threshold(max_val), expected_honest);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bft_threshold_different_types() {
|
||||
assert_eq!(get_byzantium_quorum_threshold(4u8), 3u8);
|
||||
assert_eq!(get_byzantium_quorum_threshold(4u64), 3u64);
|
||||
assert_eq!(get_byzantium_quorum_threshold(4usize), 3usize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ghost-weaver"
|
||||
version = "0.0.4"
|
||||
version = "0.0.5"
|
||||
description = "Weaving a secure cryptographic tapestry across different external chains."
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
@ -25,7 +25,7 @@ use sp_runtime::{
|
||||
|
||||
use ghost_helpers::{
|
||||
bounded_bitmap::{validate_bitmap_sizes, BoundedBitmap},
|
||||
get_byzantium_threshold,
|
||||
get_byzantium_quorum_threshold,
|
||||
networks::{NetworkData, NetworkType},
|
||||
};
|
||||
use ghost_traits::{
|
||||
@ -487,7 +487,7 @@ pub mod pallet {
|
||||
|
||||
weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 1));
|
||||
let len = Authorities::<T>::decode_len().unwrap_or_default();
|
||||
let weaving_threshold = get_byzantium_threshold(len);
|
||||
let weaving_threshold = get_byzantium_quorum_threshold(len);
|
||||
|
||||
let maybe_tapestry_drafts = TapestryDrafts::<T>::get(&network_id);
|
||||
|
||||
@ -850,7 +850,7 @@ impl<T: Config> Pallet<T> {
|
||||
.parse_block_requests(pending_requests, deadline, request_id);
|
||||
|
||||
let total_blocks = block_numbers.len();
|
||||
let weaving_threshold = get_byzantium_threshold(total_blocks);
|
||||
let weaving_threshold = get_byzantium_quorum_threshold(total_blocks);
|
||||
|
||||
let median_block = Self::validate_block_numbers_consensus(
|
||||
&mut block_numbers,
|
||||
|
||||
@ -65,7 +65,9 @@ fn should_successfully_compute_median_and_start_weaving_round() {
|
||||
let pair3 = AuthorityPair::from_string("//Carol", None).expect("Should be valid seed");
|
||||
|
||||
let network_id = 1;
|
||||
let network_data = NetworkDataBuilder::default().build();
|
||||
let network_data = NetworkDataBuilder::default()
|
||||
.with_block_deviation(5)
|
||||
.build();
|
||||
|
||||
let authorities = vec![pair1.clone(), pair2.clone(), pair3.clone()];
|
||||
let networks = vec![(network_id, network_data, Default::default())];
|
||||
@ -122,8 +124,8 @@ fn should_apply_cooldown_delay_on_consensus_failure() {
|
||||
.with_network_id(network_id);
|
||||
|
||||
let att1 = context.with_authority_index(0).build_block_attestation(100);
|
||||
let att2 = context.with_authority_index(1).build_block_attestation(500);
|
||||
let att3 = context.with_authority_index(2).build_block_attestation(900);
|
||||
let att2 = context.with_authority_index(1).build_block_attestation(102);
|
||||
let att3 = context.with_authority_index(2).build_block_attestation(104);
|
||||
|
||||
let sig1 = pair1.sign(&att1.encode());
|
||||
let sig2 = pair2.sign(&att2.encode());
|
||||
@ -933,7 +935,7 @@ fn should_successfully_pull_utxo_thread_and_mint_currency() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn on_initialize_should_finalize_session_when_threshold_or_timeout_is_reached() {
|
||||
fn on_initialize_should_finalize_session_when_timeout_is_reached() {
|
||||
let pair1 = AuthorityPair::from_string("//Alice", None).expect("Should be valid seed");
|
||||
let pair2 = AuthorityPair::from_string("//Bob", None).expect("Should be valid seed");
|
||||
let pair3 = AuthorityPair::from_string("//Charlie", None).expect("Should be valid seed");
|
||||
@ -995,14 +997,12 @@ fn on_initialize_should_finalize_session_when_threshold_or_timeout_is_reached()
|
||||
let current_session = CurrentWeavingSession::<TestRuntime>::get(&network_id);
|
||||
GhostWeaver::on_initialize(current_substrate_block);
|
||||
|
||||
let saved_loot = LoomStates::<TestRuntime>::get(&network_id, current_session);
|
||||
assert_eq!(saved_loot, target_hash);
|
||||
let saved_loom = LoomStates::<TestRuntime>::get(&network_id, current_session);
|
||||
assert_ne!(saved_loom, target_hash);
|
||||
assert_eq!(saved_loom, saved_loom);
|
||||
|
||||
let updated_session = CurrentWeavingSession::<TestRuntime>::get(&network_id);
|
||||
assert_eq!(updated_session, current_session + 1);
|
||||
|
||||
System::set_block_number(15);
|
||||
GhostWeaver::on_initialize(15);
|
||||
assert_eq!(updated_session, current_session);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user