Compare commits

...

2 Commits

Author SHA1 Message Date
8abd114a5b
more secure and optimized Round 5 metadata hashing pipeline
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-10-01 21:41:27 +03:00
6b0033425c
implement more secure entropy hedging for offchain RNG
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-10-01 21:20:17 +03:00
4 changed files with 36 additions and 49 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "ghost-exodus"
version = "0.0.17"
version = "0.0.19"
description = "Threshold signature generation with DKG included"
license.workspace = true
authors.workspace = true

View File

@ -85,8 +85,7 @@ mod benchmarks {
dkg_state.insert_index(authority_index);
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
let mut rng = Pallet::<T>::get_offchain_rng(authority_index);
let mut rng = ChaCha20Rng::seed_from_u64(694201337);
let (_, public_package) = network_curve.dkg_part1(
authority_index,
max_signers,
@ -353,11 +352,8 @@ mod benchmarks {
dummy_verifying_key,
).expect("Bounded verifying key should be correct");
let metadata_hashes = [
SubstrateBlake2Hasher::hash(dummy_merkle_root.as_ref()),
SubstrateBlake2Hasher::hash(bounded_verifying_key.as_ref()),
];
let verifying_hash = sequential_hash::<SubstrateBlake2Hasher, _>(metadata_hashes);
let metadata_hashes = [dummy_merkle_root.as_ref(), bounded_verifying_key.as_ref()];
let verifying_hash = cumulative_hash::<SubstrateBlake2Hasher, _>(metadata_hashes);
let verification_key = (network_curve, dkg_index, verifying_hash);
let participants = Verifications::<T>::get(verification_key);

View File

@ -31,7 +31,7 @@ use sp_io::hashing::blake2_256;
use ghost_helpers::{
get_byzantium_quorum_threshold, SubstrateBlake2Hasher,
hash_chain::sequential_hash,
hash_chain::cumulative_hash,
networks::{NetworkData, NetworkCurve, NetworkType},
bounded_bitmap::{validate_bitmap_sizes, BoundedBitmap},
};
@ -40,7 +40,6 @@ use ghost_helpers::{
use ghost_traits::exodus::IdentifierConverter;
use ghost_traits::{
hashing::GhostHasher,
bounded_bitmap::{
BoundedBitmapGenerator, BoundedBitmapWriter, BoundedBitmapReader,
BoundedBitmapIterable,
@ -1254,11 +1253,9 @@ pub mod pallet {
return Err(Error::<T>::Round5PackageInvalidProof.into());
};
let metadata_hashes = [
SubstrateBlake2Hasher::hash(round5.merkle_root.as_ref()),
SubstrateBlake2Hasher::hash(round5.verifying_key.as_ref()),
];
let verifying_hash = sequential_hash::<SubstrateBlake2Hasher, _>(metadata_hashes);
let metadata_hashes = [round5.merkle_root.as_ref(), round5.verifying_key.as_ref()];
let verifying_hash = cumulative_hash::<SubstrateBlake2Hasher, _>(metadata_hashes);
let state = QualificationDkgState::<T>::get(&network_curve);
ensure!(state.is_fifth_phase(), Error::<T>::DkgWrongRound);
@ -3559,12 +3556,10 @@ impl<T: Config> Pallet<T> {
let authority_index = exodus_storage.authority_index;
let network_curve = exodus_storage.network_curve;
#[cfg(not(any(test, feature = "runtime-benchmarks")))]
let mut rng = Self::get_offchain_rng();
#[cfg(any(test, feature = "runtime-benchmarks"))]
let mut rng = Self::get_offchain_rng(authority_index);
let exodus_storage_encoded = exodus_storage.encode();
let rng_context = [exodus_storage_encoded.as_slice(), secret_share];
let mut rng = Self::get_offchain_rng(&rng_context);
let (nonce, hiding_commitment, binding_commitment) = network_curve
.generate_nonce_commitment(secret_share, &mut rng)?;
@ -3776,12 +3771,15 @@ impl<T: Config> Pallet<T> {
));
}
#[cfg(not(any(test, feature = "runtime-benchmarks")))]
let mut rng = Self::get_offchain_rng();
let dkg_storage_encoded = dkg_storage.encode();
let qualification_state_encoded = qualification_state.encode();
#[cfg(any(test, feature = "runtime-benchmarks"))]
let mut rng = Self::get_offchain_rng(authority_index);
let rng_context = [
dkg_storage_encoded.as_slice(),
qualification_state_encoded.as_slice(),
];
let mut rng = Self::get_offchain_rng(&rng_context);
let (secret_package, public_package) = network_curve
.dkg_part1(authority_index, max_signers, min_signers, &mut rng)?;
@ -4736,11 +4734,17 @@ impl<T: Config> Pallet<T> {
dkg_index: DkgIndex,
network_curve: NetworkCurve,
) {
#[cfg(not(any(test, feature = "runtime-benchmarks")))]
let mut rng = Self::get_offchain_rng();
let authority_index_bytes = authority_index.to_le_bytes();
let dkg_index_bytes = dkg_index.to_le_bytes();
let network_curve_bytes = [network_curve as u8];
#[cfg(any(test, feature = "runtime-benchmarks"))]
let mut rng = Self::get_offchain_rng(authority_index);
let rng_context = [
round1_secret_package,
authority_index_bytes.as_slice(),
dkg_index_bytes.as_slice(),
network_curve_bytes.as_slice(),
];
let mut rng = Self::get_offchain_rng(&rng_context);
for (&receiver_index, round2_package) in round2_packages.iter() {
if receiver_index == authority_index { continue; }
@ -4811,26 +4815,13 @@ impl<T: Config> Pallet<T> {
}
}
#[cfg(any(test, feature = "runtime-benchmarks"))]
fn get_offchain_rng(authority_index: AuthIndex) -> ChaCha20Rng {
let mut seed = [0u8; 32];
let unique_id = (authority_index as u64).saturating_add(1);
let index_bytes = unique_id.to_le_bytes();
for (i, &byte) in index_bytes.iter().enumerate() {
if i < seed.len() {
seed[i] ^= byte;
}
}
rand_chacha::ChaCha20Rng::from_seed(seed)
}
#[cfg(not(any(test, feature = "runtime-benchmarks")))]
fn get_offchain_rng() -> ChaCha20Rng {
fn get_offchain_rng(context: &[&[u8]]) -> ChaCha20Rng {
let seed = sp_io::offchain::random_seed();
ChaCha20Rng::from_seed(seed)
let seeded_context = sp_std::iter::once(&seed[..])
.chain(context.iter().copied());
let hashed_seed = cumulative_hash::<SubstrateBlake2Hasher, _>(seeded_context);
ChaCha20Rng::from_seed(hashed_seed.to_fixed_bytes())
}
fn create_storage_key(first: &[u8], second: &[u8]) -> Vec<u8> {

View File

@ -75,7 +75,7 @@ impl<ExodusInnerType> ExodusStorageWrapper<ExodusInnerType> {
}
}
#[derive(Default)]
#[derive(Default, Encode)]
pub struct ExodusStorage<BlockNumber, NetworkCurve>
where
BlockNumber: Default,
@ -365,7 +365,7 @@ where
}
}
#[derive(Default, Clone, Copy)]
#[derive(Default, Encode, Clone, Copy)]
pub struct DkgStorage<BlockNumber, NetworkCurve>
where
BlockNumber: Copy + Clone,