forked from ghostchain/ghost-node
854 lines
31 KiB
Rust
854 lines
31 KiB
Rust
#![cfg(feature = "runtime-benchmarks")]
|
|
|
|
use super::*;
|
|
use frame_benchmarking::v2::*;
|
|
use frame_system::RawOrigin;
|
|
|
|
use ghost_helpers::networks::NetworkDataBuilder;
|
|
|
|
fn prepare_pallet<T: Config>(authorities_len: usize) -> (
|
|
PendingDkgAuthorities<ParticipantsBitmap<T>, BlockNumberFor<T>>,
|
|
NetworkCurve,
|
|
T::AuthorityId,
|
|
AuthIndex
|
|
) {
|
|
let network_curve = NetworkCurve::Secp256k1;
|
|
let authority = T::AuthorityId::generate_pair(None);
|
|
|
|
let authorities = vec![authority.clone(); authorities_len];
|
|
let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.clone())
|
|
.expect("more than the maximum number of keys provided");
|
|
|
|
QualificationAuthorities::<T>::insert(network_curve, bounded_authorities);
|
|
|
|
let network_id = NetworkIdOf::<T>::default();
|
|
let network_data = NetworkDataBuilder::default()
|
|
.with_network_type(NetworkType::Evm)
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.build();
|
|
|
|
T::NetworkDataHandler::register(network_id, network_data)
|
|
.expect("network should be valid for insertion");
|
|
|
|
let mut dkg_state = PendingDkgAuthorities::default();
|
|
dkg_state.new_dkg(authorities_len);
|
|
|
|
(dkg_state, network_curve, authority, 0)
|
|
}
|
|
|
|
#[benchmarks(where T: Config)]
|
|
mod benchmarks {
|
|
use super::*;
|
|
|
|
#[benchmark]
|
|
fn register_round0_package() -> Result<(), BenchmarkError> {
|
|
let dummy_hash = ExodusHash::repeat_byte(69);
|
|
let (mut dkg_state, network_curve, authority, authority_index) =
|
|
prepare_pallet::<T>(1);
|
|
|
|
dkg_state.next_phase();
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
|
|
let round0_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(0)
|
|
.with_dkg_round0(dummy_hash);
|
|
|
|
let dkg_package = DkgPackage::Round0(round0_package);
|
|
|
|
let signature = authority
|
|
.sign(&dkg_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, dkg_package, signature);
|
|
|
|
let expected_hash = Round0Packages::<T>::get(&network_curve, authority_index);
|
|
assert_eq!(expected_hash, dummy_hash);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_round1_package(
|
|
c: Linear<4, { T::MaxAuthorities::get() }>
|
|
) -> Result<(), BenchmarkError> {
|
|
let max_signers = c as AuthIndex;
|
|
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);
|
|
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
|
|
dkg_state.insert_index(authority_index);
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
|
|
let mut rng = Pallet::<T>::get_offchain_rng(authority_index);
|
|
|
|
let (_, public_package) = network_curve.dkg_part1(
|
|
authority_index,
|
|
max_signers,
|
|
min_signers,
|
|
&mut rng,
|
|
).expect("DKG part1 should work");
|
|
|
|
let package_hash = ExodusHash::from(blake2_256(&public_package));
|
|
Round0Packages::<T>::insert(network_curve, authority_index, package_hash);
|
|
|
|
let round1_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(0)
|
|
.with_dkg_round1(public_package)
|
|
.expect("Round1 package should be valid");
|
|
|
|
let dkg_package = DkgPackage::Round1(round1_package);
|
|
|
|
let signature = authority
|
|
.sign(&dkg_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, dkg_package, signature);
|
|
|
|
let participants = Round1Packages::<T>::get(&network_curve);
|
|
assert!(participants.contains(authority_index));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_encrypted_round2_packages(
|
|
c: Linear<1, { T::MaxAuthorities::get() / 8 }>
|
|
) -> Result<(), BenchmarkError> {
|
|
let max_signers = (c * 8) as AuthIndex;
|
|
|
|
let (mut dkg_state, network_curve, authority, authority_index) =
|
|
prepare_pallet::<T>(max_signers as usize);
|
|
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
|
|
(0..max_signers).for_each(|i| {
|
|
dkg_state.insert_index(i);
|
|
});
|
|
|
|
let padded_participants = dkg_state
|
|
.highest_bit::<usize>()
|
|
.map(|bit_pos| bit_pos.saturating_add(1))
|
|
.unwrap_or_default();
|
|
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
|
|
let bitmask_len = padded_participants.div_ceil(8);
|
|
let blob_len = round2_encrypted_package_size(
|
|
padded_participants,
|
|
network_curve.scalar_bytes_len(),
|
|
network_curve.header_bytes_len(),
|
|
);
|
|
|
|
let mut bitmask = vec![0u8; bitmask_len];
|
|
let blob = vec![0u8; blob_len];
|
|
|
|
(0..max_signers).for_each(|i| {
|
|
if i != authority_index {
|
|
let byte_index = (i / 8) as usize;
|
|
let bit_index = (i % 8) as u8;
|
|
bitmask[byte_index] |= 1 << bit_index;
|
|
}
|
|
});
|
|
|
|
let encryption_bundle = BundledPackages { bitmask, blob };
|
|
|
|
let round2_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(authority_index)
|
|
.with_dkg_round2(encryption_bundle)
|
|
.expect("Round2 package should be valid");
|
|
|
|
let dkg_package = DkgPackage::Round2(round2_package);
|
|
|
|
let signature = authority
|
|
.sign(&dkg_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, dkg_package, signature);
|
|
|
|
let participants = Round2Packages::<T>::get(&network_curve);
|
|
assert!(participants.contains(authority_index));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_round3_complaints(
|
|
c: Linear<1, { T::MaxAuthorities::get() / 8 }>
|
|
) -> Result<(), BenchmarkError> {
|
|
let max_signers = (c * 8) as AuthIndex;
|
|
|
|
let (mut dkg_state, network_curve, authority, authority_index) =
|
|
prepare_pallet::<T>(max_signers as usize);
|
|
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
|
|
(0..max_signers).for_each(|i| {
|
|
dkg_state.insert_index(i);
|
|
});
|
|
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
|
|
let bitvec_len = (max_signers + 7) / 8;
|
|
let mut accused_indexes = vec![0u8; bitvec_len as usize];
|
|
|
|
(0..max_signers).for_each(|i| {
|
|
if i != authority_index {
|
|
let byte_index = (i / 8) as usize;
|
|
let bit_index = (i % 8) as u8;
|
|
accused_indexes[byte_index] |= 1 << bit_index;
|
|
}
|
|
});
|
|
|
|
let round3_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(authority_index)
|
|
.with_dkg_round3(accused_indexes)
|
|
.expect("Round3 package should be valid");
|
|
|
|
let dkg_package = DkgPackage::Round3(round3_package);
|
|
|
|
let signature = authority
|
|
.sign(&dkg_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, dkg_package, signature);
|
|
|
|
let complaints = Complaints::<T>::get(&network_curve);
|
|
let my_complaints = complaints.get(&authority_index)
|
|
.expect("Comlpaints should be registered");
|
|
|
|
assert_eq!(my_complaints.count_ones::<AuthIndex>(), max_signers - 1);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_round4_justifications(
|
|
c: Linear<1, { T::MaxAuthorities::get() / 8 }>
|
|
) -> Result<(), BenchmarkError> {
|
|
let max_signers = (c * 8) as AuthIndex;
|
|
|
|
let (mut dkg_state, network_curve, authority, authority_index) =
|
|
prepare_pallet::<T>(max_signers as usize);
|
|
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
|
|
(0..max_signers).for_each(|i| {
|
|
dkg_state.insert_index(i);
|
|
});
|
|
|
|
let padded_participants = dkg_state
|
|
.highest_bit::<usize>()
|
|
.map(|bit_pos| bit_pos.saturating_add(1))
|
|
.unwrap_or_default();
|
|
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
|
|
let bitmask_len = padded_participants.div_ceil(8);
|
|
let blob_len = round2_package_size(
|
|
padded_participants,
|
|
network_curve.scalar_bytes_len(),
|
|
network_curve.header_bytes_len(),
|
|
);
|
|
|
|
let mut bitmask = vec![0u8; bitmask_len];
|
|
let blob = vec![0u8; blob_len];
|
|
|
|
(0..max_signers).for_each(|i| {
|
|
if i != authority_index {
|
|
let byte_index = (i / 8) as usize;
|
|
let bit_index = (i % 8) as u8;
|
|
bitmask[byte_index] |= 1 << bit_index;
|
|
}
|
|
});
|
|
|
|
let justification_bundle = BundledPackages { bitmask, blob };
|
|
|
|
let round4_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(authority_index)
|
|
.with_dkg_round4(justification_bundle)
|
|
.expect("Round4 package should be valid");
|
|
|
|
let dkg_package = DkgPackage::Round4(round4_package);
|
|
|
|
let signature = authority
|
|
.sign(&dkg_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, dkg_package, signature);
|
|
|
|
let justifications = Justifications::<T>::get(&network_curve);
|
|
let my_justifications = justifications.get(&authority_index)
|
|
.expect("Justifications should be registered");
|
|
|
|
assert_eq!(my_justifications.count_ones::<AuthIndex>(), max_signers - 1);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_round5_verifying_package() -> Result<(), BenchmarkError> {
|
|
let max_signers = 4 as AuthIndex;
|
|
|
|
let (mut dkg_state, network_curve, authority, authority_index) =
|
|
prepare_pallet::<T>(max_signers as usize);
|
|
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
|
|
(0..max_signers).for_each(|i| {
|
|
dkg_state.insert_index(i);
|
|
});
|
|
|
|
let dkg_index = dkg_state.get_dkg_index();
|
|
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
|
|
let dummy_merkle_root = ExodusHash::repeat_byte(69);
|
|
let dummy_verifying_key = vec![69u8; network_curve.element_bytes_len()];
|
|
|
|
let round5_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(authority_index)
|
|
.with_dkg_round5(dummy_verifying_key.clone(), dummy_merkle_root)
|
|
.expect("Round5 package should be valid");
|
|
|
|
let dkg_package = DkgPackage::Round5(round5_package);
|
|
|
|
let signature = authority
|
|
.sign(&dkg_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, dkg_package, signature);
|
|
|
|
let bounded_verifying_key =
|
|
BoundedVec::<u8, ConstU32< { ELEMENT_MAX_BYTES }>>::try_from(
|
|
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 verification_key = (network_curve, dkg_index, verifying_hash);
|
|
let participants = Verifications::<T>::get(verification_key);
|
|
assert!(participants.contains(authority_index));
|
|
|
|
let consensus = VerifyingKeyConsensus::<T>::get(&network_curve, dkg_index);
|
|
assert!(consensus.participants.contains(authority_index));
|
|
assert_eq!(consensus.participants.count_ones::<AuthIndex>(), 1);
|
|
assert_eq!(consensus.merkle_root, dummy_merkle_root);
|
|
assert_eq!(consensus.element_bytes, bounded_verifying_key);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_round6_public_share_package(
|
|
c: Linear<1, { T::MaxAuthorities::get().next_power_of_two().trailing_zeros() }>
|
|
) -> Result<(), BenchmarkError> {
|
|
let computed_max_signers = (1u32 << c) as AuthIndex;
|
|
let constant_max_signers = T::MaxAuthorities::get() as AuthIndex;
|
|
|
|
let max_signers = sp_std::cmp::min(computed_max_signers, constant_max_signers);
|
|
|
|
let (mut dkg_state, network_curve, authority, authority_index) =
|
|
prepare_pallet::<T>(max_signers as usize);
|
|
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
dkg_state.next_phase();
|
|
|
|
(0..max_signers).for_each(|i| {
|
|
dkg_state.insert_index(i);
|
|
});
|
|
|
|
let dkg_index = dkg_state.get_dkg_index();
|
|
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
|
|
let dummy_value = vec![69u8; network_curve.element_bytes_len()];
|
|
|
|
let (dummy_merkle_root, dummy_verifying_share, dummy_merkle_proof) =
|
|
with_ciphersuite!(network_curve, |f| {
|
|
let mut dummy_values = BTreeMap::new();
|
|
|
|
for i in 0..max_signers {
|
|
let non_zero_index = i.saturating_add(1);
|
|
let identifier: frost_core::Identifier<Ciphersuite> =
|
|
frost_core::Identifier::<Ciphersuite>::try_from(non_zero_index)
|
|
.expect("Identifier should be created");
|
|
|
|
dummy_values.insert(identifier, dummy_value.clone());
|
|
}
|
|
|
|
let merkle_tree =
|
|
NetworkCurve::build_merkle_tree(
|
|
&dummy_values,
|
|
|value: &Vec<u8>| Ok(value.clone()),
|
|
).expect("Merkle tree for verifying shares should be valid");
|
|
|
|
let merkle_root = merkle_tree.last().copied().unwrap();
|
|
|
|
let (verifying_share, merkle_proof) = NetworkCurve::generate_merkle_proof_from_tree(
|
|
&dummy_values,
|
|
&merkle_tree,
|
|
authority_index,
|
|
|value: &Vec<u8>| Ok(value.clone())
|
|
).expect("Merkle tree proof should be valid");
|
|
|
|
(merkle_root, verifying_share, merkle_proof)
|
|
});
|
|
|
|
VerifyingKeyConsensus::<T>::mutate(&network_curve, &dkg_index, |consensus| {
|
|
consensus.participants.insert(authority_index);
|
|
consensus.merkle_root = dummy_merkle_root;
|
|
});
|
|
|
|
let round6_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(authority_index)
|
|
.with_dkg_round6(dummy_verifying_share.clone(), dummy_merkle_proof)
|
|
.expect("Round6 package should be valid");
|
|
|
|
let dkg_package = DkgPackage::Round6(round6_package);
|
|
|
|
let signature = authority
|
|
.sign(&dkg_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, dkg_package, signature);
|
|
|
|
let participants = VerifyingSharesParticipants::<T>::get(&network_curve, dkg_index);
|
|
assert!(participants.contains(authority_index));
|
|
|
|
let bundled_verifying_share =
|
|
BoundedVec::<u8, ConstU32<{ ELEMENT_MAX_BYTES }>>::try_from(
|
|
dummy_verifying_share,
|
|
).expect("Verifying share should be bundled");
|
|
|
|
let verifying_share_key = (network_curve, dkg_index, authority_index);
|
|
assert_eq!(
|
|
VerifyingShares::<T>::get(verifying_share_key).unwrap(),
|
|
bundled_verifying_share,
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_nonce_commitment() -> Result<(), BenchmarkError> {
|
|
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
|
|
let (mut dkg_state, network_curve, authority, authority_index) =
|
|
prepare_pallet::<T>(1);
|
|
|
|
loop {
|
|
if !dkg_state.is_dkg_pending() { break; }
|
|
dkg_state.next_phase();
|
|
}
|
|
|
|
dkg_state.insert_index(authority_index);
|
|
let exodus_session = CurrentExodus::<T>::get();
|
|
|
|
let dummy_address = EvmAddress::repeat_byte(69);
|
|
let dummy_nonce = vec![0u8; network_curve.element_bytes_len()];
|
|
|
|
let create_bond = GovernanceAction::Create {
|
|
market: [69, 420, 1337],
|
|
terms: [420, 1337],
|
|
token: dummy_address,
|
|
intervals: [34, 35],
|
|
booleans: [true, true],
|
|
};
|
|
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
|
exodus_session,
|
|
network_id,
|
|
dummy_address,
|
|
create_bond,
|
|
);
|
|
|
|
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
|
let active_dkg: ActivatedState<T> = (&dkg_state).into();
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
|
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
|
ExodusRequests::<T>::insert(network_curve, exodus_session, request);
|
|
|
|
let nonce_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(authority_index)
|
|
.with_exodus_nonce_commitment(
|
|
exodus_session,
|
|
dummy_nonce.clone(),
|
|
dummy_nonce.clone(),
|
|
)
|
|
.expect("Nonce commitment package should be valid");
|
|
|
|
let exodus_package = ExodusPackage::NonceCommitment(nonce_package);
|
|
|
|
let signature = authority
|
|
.sign(&exodus_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, exodus_package, signature);
|
|
|
|
let roast_session = RoastSessions::<T>::get(&exodus_session, authority_index)
|
|
.expect("ROAST session should exist after nonce commitment");
|
|
|
|
let roast_state = RoastSessionStates::<T>::get(&exodus_session, roast_session);
|
|
assert!(roast_state.nonce_committers.contains(authority_index));
|
|
assert!(!roast_state.group_committers.contains(authority_index));
|
|
assert!(!roast_state.partial_signers.contains(authority_index));
|
|
|
|
let registered_nonces = NonceCommitments::<T>::get(
|
|
(exodus_session, roast_session),
|
|
authority_index,
|
|
).expect("Nonces should be registered during nonce commitment");
|
|
|
|
assert_eq!(registered_nonces.hiding, dummy_nonce.clone());
|
|
assert_eq!(registered_nonces.binding, dummy_nonce);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_group_commitment() -> Result<(), BenchmarkError> {
|
|
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
|
|
let (mut dkg_state, network_curve, authority, authority_index) =
|
|
prepare_pallet::<T>(1);
|
|
|
|
loop {
|
|
if !dkg_state.is_dkg_pending() { break; }
|
|
dkg_state.next_phase();
|
|
}
|
|
|
|
dkg_state.insert_index(authority_index);
|
|
let exodus_session = CurrentExodus::<T>::get();
|
|
|
|
let dummy_bytes = EvmBytes32::repeat_byte(69);
|
|
let dummy_address = EvmAddress::repeat_byte(69);
|
|
let dummy_merkle_root = ExodusHash::repeat_byte(69);
|
|
let dummy_group_commitment = vec![0u8; network_curve.element_bytes_len()];
|
|
|
|
let create_bond = GovernanceAction::Create {
|
|
market: [69, 420, 1337],
|
|
terms: [420, 1337],
|
|
token: dummy_address,
|
|
intervals: [34, 35],
|
|
booleans: [true, true],
|
|
};
|
|
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
|
exodus_session,
|
|
network_id,
|
|
dummy_address,
|
|
create_bond,
|
|
);
|
|
|
|
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
|
let active_dkg: ActivatedState<T> = (&dkg_state).into();
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
|
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
|
ExodusRequests::<T>::insert(network_curve, exodus_session, request);
|
|
|
|
let mut roast_state = RoastSessionState::<ParticipantsBitmap::<T>>::default();
|
|
roast_state.status = RoastStatus::GroupCommitments;
|
|
roast_state.nonce_committers.insert(authority_index);
|
|
|
|
let roast_session = 3;
|
|
RoastSessions::<T>::insert(&exodus_session, authority_index, roast_session);
|
|
RoastSessionStates::<T>::insert(exodus_session, roast_session, roast_state);
|
|
|
|
let group_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(authority_index)
|
|
.with_exodus_group_commitment(
|
|
exodus_session,
|
|
dummy_group_commitment.clone(),
|
|
dummy_bytes,
|
|
)
|
|
.expect("Group commitment package should be valid");
|
|
|
|
let exodus_package = ExodusPackage::GroupCommitment(group_package);
|
|
|
|
let signature = authority
|
|
.sign(&exodus_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, exodus_package, signature);
|
|
|
|
let bounded_group_commitment =
|
|
BoundedVec::<u8, ConstU32<{ ELEMENT_MAX_BYTES }>>::try_from(
|
|
dummy_group_commitment,
|
|
).expect("Group commtiment should be valid");
|
|
|
|
let roast_state = RoastSessionStates::<T>::get(&exodus_session, roast_session);
|
|
assert!(roast_state.nonce_committers.contains(authority_index));
|
|
assert!(roast_state.group_committers.contains(authority_index));
|
|
|
|
let consensus = GroupCommitmentsConsensus::<T>::get(exodus_session, roast_session);
|
|
assert!(consensus.participants.contains(authority_index));
|
|
assert_eq!(&consensus.element_bytes, &bounded_group_commitment);
|
|
assert_eq!(consensus.merkle_root, dummy_merkle_root);
|
|
|
|
let group_commitment_key = (exodus_session, roast_session, dummy_merkle_root, bounded_group_commitment);
|
|
let participants = GroupCommitters::<T>::get(group_commitment_key);
|
|
assert!(participants.contains(authority_index));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_signature_share() -> Result<(), BenchmarkError> {
|
|
let max_signers = T::MaxAuthorities::get();
|
|
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) =
|
|
prepare_pallet::<T>(max_signers as usize);
|
|
|
|
loop {
|
|
if !dkg_state.is_dkg_pending() { break; }
|
|
dkg_state.next_phase();
|
|
}
|
|
|
|
dkg_state.insert_index(authority_index);
|
|
let dkg_index = dkg_state.get_dkg_index();
|
|
let exodus_session = CurrentExodus::<T>::get();
|
|
|
|
let mut dummy_element = vec![0u8; network_curve.element_bytes_len()];
|
|
dummy_element[0] = 0x02;
|
|
let g_x_coords = [
|
|
0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
|
|
0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
|
|
0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9,
|
|
0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98
|
|
];
|
|
dummy_element[1..33].copy_from_slice(&g_x_coords);
|
|
|
|
let dummy_address = EvmAddress::repeat_byte(69);
|
|
let create_bond = GovernanceAction::Create {
|
|
market: [69, 420, 1337],
|
|
terms: [420, 1337],
|
|
token: dummy_address,
|
|
intervals: [34, 35],
|
|
booleans: [true, true],
|
|
};
|
|
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
|
exodus_session,
|
|
network_id,
|
|
dummy_address,
|
|
create_bond,
|
|
);
|
|
|
|
let mut dummy_scalar = vec![0u8; network_curve.scalar_bytes_len()];
|
|
dummy_scalar[network_curve.scalar_bytes_len() - 1] = 1;
|
|
|
|
let dummy_signature_share = dummy_scalar.clone();
|
|
let dummy_binding_factor = dummy_scalar.clone();
|
|
let dummy_group_commitment = dummy_element.clone();
|
|
|
|
let (dummy_merkle_root, dummy_merkle_proof) =
|
|
with_ciphersuite!(network_curve, |f| {
|
|
let mut dummy_values = BTreeMap::new();
|
|
|
|
for i in 0..threshold {
|
|
let non_zero_index = (i as AuthIndex).saturating_add(1);
|
|
let identifier: frost_core::Identifier<Ciphersuite> =
|
|
frost_core::Identifier::<Ciphersuite>::try_from(non_zero_index)
|
|
.expect("Identifier should be created");
|
|
|
|
dummy_values.insert(identifier, dummy_binding_factor.clone());
|
|
}
|
|
|
|
let merkle_tree =
|
|
NetworkCurve::build_merkle_tree(
|
|
&dummy_values,
|
|
|value: &Vec<u8>| Ok(value.clone()),
|
|
).expect("Merkle tree for binding factor should be valid");
|
|
|
|
let merkle_root = merkle_tree.last().copied().unwrap();
|
|
|
|
let (_, merkle_proof) =
|
|
NetworkCurve::generate_merkle_proof_from_tree(
|
|
&dummy_values,
|
|
&merkle_tree,
|
|
authority_index,
|
|
|value: &Vec<u8>| Ok(value.clone())
|
|
).expect("Merkle tree proof should be valid");
|
|
|
|
(merkle_root, merkle_proof)
|
|
});
|
|
|
|
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
|
let active_dkg: ActivatedState<T> = (&dkg_state).into();
|
|
let active_dkg_index = active_dkg.get_dkg_index();
|
|
|
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
|
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
|
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
|
ExodusRequests::<T>::insert(network_curve, exodus_session, request);
|
|
|
|
let mut roast_state = RoastSessionState::<ParticipantsBitmap::<T>>::default();
|
|
roast_state.status = RoastStatus::PartialSignatures;
|
|
roast_state.nonce_committers.insert(authority_index);
|
|
roast_state.group_committers.insert(authority_index);
|
|
|
|
(0..threshold).for_each(|i| {
|
|
if i as AuthIndex == authority_index { return; }
|
|
roast_state.partial_signers.insert(i);
|
|
});
|
|
|
|
let roast_session = 3;
|
|
RoastSessions::<T>::insert(&exodus_session, authority_index, roast_session);
|
|
RoastSessionStates::<T>::insert(exodus_session, roast_session, roast_state);
|
|
|
|
let bounded_group_commitment = BoundedVec::try_from(dummy_group_commitment).unwrap();
|
|
let dummy_verifying_key = BoundedVec::try_from(dummy_element.clone()).unwrap();
|
|
|
|
let dummy_verifying_share = BoundedVec::try_from(dummy_element.clone()).unwrap();
|
|
let dummy_nonce = ExodusSeparatedNonce::new(
|
|
BoundedVec::try_from(dummy_element.clone()).unwrap(),
|
|
BoundedVec::try_from(dummy_element.clone()).unwrap(),
|
|
);
|
|
|
|
ActiveVerifyingKey::<T>::insert(&network_curve, dummy_verifying_key);
|
|
VerifyingShares::<T>::insert((&network_curve, active_dkg_index, authority_index), dummy_verifying_share);
|
|
NonceCommitments::<T>::insert((&exodus_session, &roast_session), authority_index, dummy_nonce);
|
|
|
|
GroupCommitmentsConsensus::<T>::mutate(&exodus_session, &roast_session, |consensus| {
|
|
consensus.element_bytes = bounded_group_commitment.clone();
|
|
consensus.merkle_root = dummy_merkle_root;
|
|
(0..threshold).for_each(|i| {
|
|
consensus.participants.insert(i);
|
|
});
|
|
});
|
|
|
|
let share_package = PackageContext::default()
|
|
.with_network_curve(NetworkCurve::Secp256k1)
|
|
.with_authority_index(authority_index)
|
|
.with_exodus_signature_share(
|
|
exodus_session,
|
|
dummy_signature_share.clone(),
|
|
dummy_merkle_proof,
|
|
dummy_binding_factor
|
|
)
|
|
.expect("Signature share package should be valid");
|
|
|
|
let exodus_package = ExodusPackage::SignatureShare(share_package);
|
|
|
|
let signature = authority
|
|
.sign(&exodus_package.encode())
|
|
.expect("Signature should be created");
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::None, exodus_package, signature);
|
|
|
|
let maybe_roast_session = RoastSessions::<T>::get(&exodus_session, authority_index);
|
|
assert!(maybe_roast_session.is_none());
|
|
|
|
let scalar_exists = SignatureScalars::<T>::contains_key(&exodus_session, &roast_session);
|
|
let consensus_exists = GroupCommitmentsConsensus::<T>::contains_key(&exodus_session, &roast_session);
|
|
let committers_exists = GroupCommitters::<T>::contains_key((
|
|
&exodus_session,
|
|
&roast_session,
|
|
&dummy_merkle_root,
|
|
&bounded_group_commitment,
|
|
));
|
|
|
|
assert!(!scalar_exists);
|
|
assert!(!consensus_exists);
|
|
assert!(!committers_exists);
|
|
|
|
assert!(!ExodusRequests::<T>::contains_key(&network_curve, &exodus_session));
|
|
assert!(ExodusSignedGovernance::<T>::contains_key((&exodus_session, network_id), dkg_index));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn register_evm_bridge_out_exodus() -> Result<(), BenchmarkError> {
|
|
let caller: T::AccountId = frame_benchmarking::whitelisted_caller();
|
|
let (_, network_curve, _, _) = prepare_pallet::<T>(1usize);
|
|
|
|
let network_id = NetworkIdOf::<T>::default();
|
|
let amount: BalanceOf<T> = 10_000u32.into();
|
|
let bounty = Perbill::from_percent(5);
|
|
let receiver = EvmAddress::from([69u8; 20]);
|
|
|
|
QualificationDkgState::<T>::mutate(&network_curve, |state| {
|
|
loop {
|
|
if state.is_dkg_finalized() { break; }
|
|
state.next_phase();
|
|
}
|
|
});
|
|
|
|
let total_existential = T::Currency::minimum_balance();
|
|
let initial_balance = total_existential
|
|
.saturating_mul(5u32.into())
|
|
.saturating_add(amount);
|
|
|
|
let _ = T::Currency::make_free_balance_be(&caller, initial_balance);
|
|
let _ = T::NetworkDataHandler::register_incoming(&network_id, amount).unwrap();
|
|
|
|
let current_exodus_session = CurrentExodus::<T>::get();
|
|
|
|
#[extrinsic_call]
|
|
_(
|
|
RawOrigin::Signed(caller.clone()),
|
|
network_id,
|
|
amount,
|
|
bounty,
|
|
receiver,
|
|
);
|
|
|
|
assert!(ExodusRequests::<T>::contains_key(&network_curve, current_exodus_session));
|
|
assert_eq!(CurrentExodus::<T>::get(), current_exodus_session + 1);
|
|
assert_eq!(T::Currency::free_balance(&caller), initial_balance - amount);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
impl_benchmark_test_suite!(
|
|
Pallet,
|
|
crate::mock::new_test_ext_benchmarks(),
|
|
crate::mock::Runtime
|
|
);
|
|
}
|