forked from ghostchain/ghost-node
138 lines
3.4 KiB
Rust
138 lines
3.4 KiB
Rust
#![cfg_attr(not(feature = "std"), no_std)]
|
|
|
|
use ghost_traits::hashing::GhostHasher;
|
|
use sp_core::H256;
|
|
use sp_io::hashing::{blake2_256, keccak_256, sha2_256};
|
|
|
|
pub mod bounded_bitmap;
|
|
pub mod hash_chain;
|
|
pub mod merkle_tree;
|
|
pub mod networks;
|
|
pub mod utxo;
|
|
|
|
pub type AuthIndexU8 = u8;
|
|
pub type AuthIndexU16 = u16;
|
|
pub type AuthIndexU32 = u32;
|
|
pub type AuthIndexU64 = u64;
|
|
pub type AuthIndexU128 = u128;
|
|
|
|
pub type BitmapChunkU8 = u8;
|
|
pub type BitmapChunkU16 = u16;
|
|
pub type BitmapChunkU32 = u32;
|
|
pub type BitmapChunkU64 = u64;
|
|
pub type BitmapChunkU128 = u128;
|
|
|
|
pub type DkgIndexU8 = u8;
|
|
pub type DkgIndexU16 = u16;
|
|
pub type DkgIndexU32 = u32;
|
|
pub type DkgIndexU64 = u64;
|
|
pub type DkgIndexU128 = u128;
|
|
|
|
pub type NetworkIdU8 = u8;
|
|
pub type NetworkIdU16 = u16;
|
|
pub type NetworkIdU32 = u32;
|
|
pub type NetworkIdU64 = u64;
|
|
pub type NetworkIdU128 = u128;
|
|
|
|
pub fn get_byzantium_quorum_threshold<I>(value: I) -> I
|
|
where
|
|
I: num_traits::PrimInt,
|
|
{
|
|
let zero = I::zero();
|
|
let one = I::one();
|
|
let three = one + one + one;
|
|
|
|
if value == zero { return zero; }
|
|
|
|
let f = (value - one) / three;
|
|
value - f
|
|
}
|
|
|
|
pub struct SubstrateBlake2Hasher;
|
|
impl GhostHasher for SubstrateBlake2Hasher {
|
|
type Hash = H256;
|
|
type HashBytes = [u8; 32];
|
|
fn hash(data: &[u8]) -> Self::Hash {
|
|
H256::from(blake2_256(data))
|
|
}
|
|
fn hash_len() -> usize {
|
|
H256::len_bytes()
|
|
}
|
|
fn empty() -> Self::Hash {
|
|
H256::zero()
|
|
}
|
|
}
|
|
|
|
pub struct SubstrateKeccakHasher;
|
|
impl GhostHasher for SubstrateKeccakHasher {
|
|
type Hash = H256;
|
|
type HashBytes = [u8; 32];
|
|
fn hash(data: &[u8]) -> Self::Hash {
|
|
H256::from(keccak_256(data))
|
|
}
|
|
fn hash_len() -> usize {
|
|
H256::len_bytes()
|
|
}
|
|
fn empty() -> Self::Hash {
|
|
H256::zero()
|
|
}
|
|
}
|
|
|
|
pub struct UtxoSha2Hasher;
|
|
impl GhostHasher for UtxoSha2Hasher {
|
|
type Hash = H256;
|
|
type HashBytes = [u8; 32];
|
|
fn hash(data: &[u8]) -> Self::Hash {
|
|
let first_pass: [u8; 32] = sha2_256(data);
|
|
let second_pass: [u8; 32] = sha2_256(&first_pass);
|
|
|
|
H256::from(second_pass)
|
|
}
|
|
fn hash_len() -> usize {
|
|
H256::len_bytes()
|
|
}
|
|
fn empty() -> Self::Hash {
|
|
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);
|
|
}
|
|
}
|