fix for https://ghostforum.org/t/high-lack-of-key-epoch-invalidation-across-dkg-rotations-grants-indefinite-signing-power-to-retired-validator-coalitions-missing-chainid-binding-in-gatekeeper-rotate-amplifies-cross-chain-impact/125 and some other small fixes
Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
parent
653bf08486
commit
bdbf7bd20f
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-exodus"
|
name = "ghost-exodus"
|
||||||
version = "0.0.26"
|
version = "0.1.0"
|
||||||
description = "Threshold signature generation with DKG included"
|
description = "Threshold signature generation with DKG included"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-exodus-runtime-api"
|
name = "ghost-exodus-runtime-api"
|
||||||
version = "0.0.0"
|
version = "0.0.1"
|
||||||
description = "RPC runtime API for ghost EXODUS pallet"
|
description = "RPC runtime API for ghost EXODUS pallet"
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
|||||||
@ -2,6 +2,27 @@
|
|||||||
|
|
||||||
sp_api::decl_runtime_apis! {
|
sp_api::decl_runtime_apis! {
|
||||||
pub trait ExodusApi<NetworkId> {
|
pub trait ExodusApi<NetworkId> {
|
||||||
fn verifying_key(network_id: NetworkId) -> Vec<u8>;
|
fn get_signed_rotation_message(
|
||||||
|
session: ExodusSession,
|
||||||
|
network_id: NetworkId,
|
||||||
|
dkg_index: DkgIndex
|
||||||
|
) -> Vec<u8>;
|
||||||
|
|
||||||
|
fn get_signed_bridge_message(
|
||||||
|
session: ExodusSession,
|
||||||
|
network_id: NetworkId,
|
||||||
|
dkg_index: DkgIndex
|
||||||
|
) -> Vec<u8>;
|
||||||
|
|
||||||
|
fn get_signed_governance_message(
|
||||||
|
session: ExodusSession,
|
||||||
|
network_id: NetworkId,
|
||||||
|
dkg_index: DkgIndex
|
||||||
|
) -> Vec<u8>;
|
||||||
|
|
||||||
|
fn active_verifying_key(network_curve: NetworkCurve) -> Vec<u8>;
|
||||||
|
fn pending_exodus_request_count(network_curve: NetworkCurve) -> u32;
|
||||||
|
fn is_qualification_onging(network_curve: NetworkCurve) -> bool;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use frame_system::RawOrigin;
|
|||||||
use ghost_helpers::networks::NetworkDataBuilder;
|
use ghost_helpers::networks::NetworkDataBuilder;
|
||||||
|
|
||||||
fn prepare_pallet<T: Config>(authorities_len: usize) -> (
|
fn prepare_pallet<T: Config>(authorities_len: usize) -> (
|
||||||
PendingDkgAuthorities<ParticipantsBitmap<T>, BlockNumberFor<T>>,
|
PendingDkgAuthorities<T>,
|
||||||
NetworkCurve,
|
NetworkCurve,
|
||||||
T::AuthorityId,
|
T::AuthorityId,
|
||||||
AuthIndex
|
AuthIndex
|
||||||
@ -99,7 +99,9 @@ mod benchmarks {
|
|||||||
let package_hash = ExodusHash::from(blake2_256(&public_package));
|
let package_hash = ExodusHash::from(blake2_256(&public_package));
|
||||||
Round0Packages::<T>::insert(network_curve, authority_index, package_hash);
|
Round0Packages::<T>::insert(network_curve, authority_index, package_hash);
|
||||||
|
|
||||||
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
let round1_package = PackageContext::default()
|
let round1_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(0)
|
.with_authority_index(0)
|
||||||
.with_dkg_index(dkg_index)
|
.with_dkg_index(dkg_index)
|
||||||
@ -167,7 +169,9 @@ mod benchmarks {
|
|||||||
|
|
||||||
let encryption_bundle = BundledPackages { bitmask, blob };
|
let encryption_bundle = BundledPackages { bitmask, blob };
|
||||||
|
|
||||||
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
let round2_package = PackageContext::default()
|
let round2_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(authority_index)
|
.with_authority_index(authority_index)
|
||||||
.with_dkg_index(dkg_index)
|
.with_dkg_index(dkg_index)
|
||||||
@ -222,7 +226,9 @@ mod benchmarks {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
let round3_package = PackageContext::default()
|
let round3_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(authority_index)
|
.with_authority_index(authority_index)
|
||||||
.with_dkg_index(dkg_index)
|
.with_dkg_index(dkg_index)
|
||||||
@ -295,7 +301,9 @@ mod benchmarks {
|
|||||||
|
|
||||||
let justification_bundle = BundledPackages { bitmask, blob };
|
let justification_bundle = BundledPackages { bitmask, blob };
|
||||||
|
|
||||||
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
let round4_package = PackageContext::default()
|
let round4_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(authority_index)
|
.with_authority_index(authority_index)
|
||||||
.with_dkg_index(dkg_index)
|
.with_dkg_index(dkg_index)
|
||||||
@ -346,7 +354,9 @@ mod benchmarks {
|
|||||||
let dummy_verifying_key = vec![69u8; network_curve.element_bytes_len()];
|
let dummy_verifying_key = vec![69u8; network_curve.element_bytes_len()];
|
||||||
let dummy_key_members = vec![15];
|
let dummy_key_members = vec![15];
|
||||||
|
|
||||||
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
let round5_package = PackageContext::default()
|
let round5_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(authority_index)
|
.with_authority_index(authority_index)
|
||||||
.with_dkg_index(dkg_index)
|
.with_dkg_index(dkg_index)
|
||||||
@ -458,7 +468,9 @@ mod benchmarks {
|
|||||||
consensus.state.merkle_root = dummy_merkle_root;
|
consensus.state.merkle_root = dummy_merkle_root;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
let round6_package = PackageContext::default()
|
let round6_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(authority_index)
|
.with_authority_index(authority_index)
|
||||||
.with_dkg_index(dkg_index)
|
.with_dkg_index(dkg_index)
|
||||||
@ -503,8 +515,13 @@ mod benchmarks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dkg_state.insert_index(authority_index);
|
dkg_state.insert_index(authority_index);
|
||||||
let exodus_session = CurrentExodus::<T>::get();
|
let all_exodus_sessions = CurrentExodusSessions::<T>::get();
|
||||||
|
let exodus_session = all_exodus_sessions
|
||||||
|
.get(&network_id)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
let dummy_context = ExodusContext::new(network_id, exodus_session);
|
||||||
let dummy_address = EvmAddress::repeat_byte(69);
|
let dummy_address = EvmAddress::repeat_byte(69);
|
||||||
|
|
||||||
// generator point for secp256k1
|
// generator point for secp256k1
|
||||||
@ -522,28 +539,28 @@ mod benchmarks {
|
|||||||
intervals: [34, 35],
|
intervals: [34, 35],
|
||||||
booleans: [true, true],
|
booleans: [true, true],
|
||||||
};
|
};
|
||||||
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
let request = ExodusRequest::<BalanceOf<T>>::evm_governance(
|
||||||
exodus_session,
|
|
||||||
network_id,
|
|
||||||
dummy_address,
|
dummy_address,
|
||||||
create_bond,
|
create_bond,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
||||||
let active_dkg: ActivatedState<T> = (&dkg_state).into();
|
let active_dkg: ReadyDkgAuthorities<T> = (&dkg_state).into();
|
||||||
let active_dkg_index = active_dkg.get_dkg_index();
|
let active_dkg_index = active_dkg.get_dkg_index();
|
||||||
|
|
||||||
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
||||||
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
||||||
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
||||||
ExodusRequests::<T>::insert((network_curve, exodus_session), request);
|
ExodusRequests::<T>::insert((&network_curve, &dummy_context), request);
|
||||||
|
|
||||||
let nonce_package = PackageContext::default()
|
let nonce_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(authority_index)
|
.with_authority_index(authority_index)
|
||||||
.with_dkg_index(active_dkg_index)
|
.with_dkg_index(active_dkg_index)
|
||||||
.with_exodus_nonce_commitment(
|
.with_exodus_nonce_commitment(
|
||||||
exodus_session,
|
dummy_context,
|
||||||
dummy_nonce.to_vec(),
|
dummy_nonce.to_vec(),
|
||||||
dummy_nonce.to_vec(),
|
dummy_nonce.to_vec(),
|
||||||
)
|
)
|
||||||
@ -558,16 +575,16 @@ mod benchmarks {
|
|||||||
#[extrinsic_call]
|
#[extrinsic_call]
|
||||||
_(RawOrigin::None, exodus_package, signature);
|
_(RawOrigin::None, exodus_package, signature);
|
||||||
|
|
||||||
let roast_session = RoastSessions::<T>::get(&exodus_session, authority_index)
|
let roast_session = RoastSessions::<T>::get(&dummy_context, authority_index)
|
||||||
.expect("ROAST session should exist after nonce commitment");
|
.expect("ROAST session should exist after nonce commitment");
|
||||||
|
|
||||||
let roast_state = RoastSessionStates::<T>::get(&exodus_session, roast_session);
|
let roast_state = RoastSessionStates::<T>::get(&dummy_context, roast_session);
|
||||||
assert!(roast_state.nonce_committers.contains(authority_index));
|
assert!(roast_state.nonce_committers.contains(authority_index));
|
||||||
assert!(!roast_state.group_committers.contains(authority_index));
|
assert!(!roast_state.group_committers.contains(authority_index));
|
||||||
assert!(!roast_state.partial_signers.contains(authority_index));
|
assert!(!roast_state.partial_signers.contains(authority_index));
|
||||||
|
|
||||||
let registered_nonces = NonceCommitments::<T>::get(
|
let registered_nonces = NonceCommitments::<T>::get(
|
||||||
(exodus_session, roast_session),
|
(dummy_context, roast_session),
|
||||||
authority_index,
|
authority_index,
|
||||||
).expect("Nonces should be registered during nonce commitment");
|
).expect("Nonces should be registered during nonce commitment");
|
||||||
|
|
||||||
@ -589,8 +606,13 @@ mod benchmarks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dkg_state.insert_index(authority_index);
|
dkg_state.insert_index(authority_index);
|
||||||
let exodus_session = CurrentExodus::<T>::get();
|
let all_exodus_sessions = CurrentExodusSessions::<T>::get();
|
||||||
|
let exodus_session = all_exodus_sessions
|
||||||
|
.get(&network_id)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
let dummy_context = ExodusContext::new(network_id, exodus_session);
|
||||||
let dummy_bytes = EvmBytes32::repeat_byte(69);
|
let dummy_bytes = EvmBytes32::repeat_byte(69);
|
||||||
let dummy_address = EvmAddress::repeat_byte(69);
|
let dummy_address = EvmAddress::repeat_byte(69);
|
||||||
let dummy_merkle_root = ExodusHash::repeat_byte(69);
|
let dummy_merkle_root = ExodusHash::repeat_byte(69);
|
||||||
@ -603,36 +625,36 @@ mod benchmarks {
|
|||||||
intervals: [34, 35],
|
intervals: [34, 35],
|
||||||
booleans: [true, true],
|
booleans: [true, true],
|
||||||
};
|
};
|
||||||
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
let request = ExodusRequest::<BalanceOf<T>>::evm_governance(
|
||||||
exodus_session,
|
|
||||||
network_id,
|
|
||||||
dummy_address,
|
dummy_address,
|
||||||
create_bond,
|
create_bond,
|
||||||
);
|
);
|
||||||
|
|
||||||
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
||||||
let active_dkg: ActivatedState<T> = (&dkg_state).into();
|
let active_dkg: ReadyDkgAuthorities<T> = (&dkg_state).into();
|
||||||
let active_dkg_index = active_dkg.get_dkg_index();
|
let active_dkg_index = active_dkg.get_dkg_index();
|
||||||
|
|
||||||
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
||||||
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
||||||
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
||||||
ExodusRequests::<T>::insert((network_curve, exodus_session), request);
|
ExodusRequests::<T>::insert((network_curve, dummy_context), request);
|
||||||
|
|
||||||
let mut roast_state = RoastSessionState::<ParticipantsBitmap::<T>>::default();
|
let mut roast_state = RoastSessionState::<ParticipantsBitmap::<T>>::default();
|
||||||
roast_state.status = RoastStatus::GroupCommitments;
|
roast_state.status = RoastStatus::GroupCommitments;
|
||||||
roast_state.nonce_committers.insert(authority_index);
|
roast_state.nonce_committers.insert(authority_index);
|
||||||
|
|
||||||
let roast_session = 3;
|
let roast_session = 3;
|
||||||
RoastSessions::<T>::insert(&exodus_session, authority_index, roast_session);
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
RoastSessionStates::<T>::insert(exodus_session, roast_session, roast_state);
|
RoastSessions::<T>::insert(&dummy_context, authority_index, roast_session);
|
||||||
|
RoastSessionStates::<T>::insert(dummy_context, roast_session, roast_state);
|
||||||
|
|
||||||
let group_package = PackageContext::default()
|
let group_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(authority_index)
|
.with_authority_index(authority_index)
|
||||||
.with_dkg_index(active_dkg_index)
|
.with_dkg_index(active_dkg_index)
|
||||||
.with_exodus_group_commitment(
|
.with_exodus_group_commitment(
|
||||||
exodus_session,
|
dummy_context,
|
||||||
dummy_group_commitment.clone(),
|
dummy_group_commitment.clone(),
|
||||||
dummy_bytes,
|
dummy_bytes,
|
||||||
)
|
)
|
||||||
@ -652,16 +674,16 @@ mod benchmarks {
|
|||||||
dummy_group_commitment,
|
dummy_group_commitment,
|
||||||
).expect("Group commtiment should be valid");
|
).expect("Group commtiment should be valid");
|
||||||
|
|
||||||
let roast_state = RoastSessionStates::<T>::get(&exodus_session, roast_session);
|
let roast_state = RoastSessionStates::<T>::get(&dummy_context, roast_session);
|
||||||
assert!(roast_state.nonce_committers.contains(authority_index));
|
assert!(roast_state.nonce_committers.contains(authority_index));
|
||||||
assert!(roast_state.group_committers.contains(authority_index));
|
assert!(roast_state.group_committers.contains(authority_index));
|
||||||
|
|
||||||
let consensus = GroupCommitmentsConsensus::<T>::get(exodus_session, roast_session);
|
let consensus = GroupCommitmentsConsensus::<T>::get(dummy_context, roast_session);
|
||||||
assert!(consensus.participants.contains(authority_index));
|
assert!(consensus.participants.contains(authority_index));
|
||||||
assert_eq!(&consensus.element_bytes, &bounded_group_commitment);
|
assert_eq!(&consensus.element_bytes, &bounded_group_commitment);
|
||||||
assert_eq!(consensus.merkle_root, dummy_merkle_root);
|
assert_eq!(consensus.merkle_root, dummy_merkle_root);
|
||||||
|
|
||||||
let group_commitment_key = (exodus_session, roast_session, dummy_merkle_root, bounded_group_commitment);
|
let group_commitment_key = (dummy_context, roast_session, dummy_merkle_root, bounded_group_commitment);
|
||||||
let participants = GroupCommitters::<T>::get(group_commitment_key);
|
let participants = GroupCommitters::<T>::get(group_commitment_key);
|
||||||
assert!(participants.contains(authority_index));
|
assert!(participants.contains(authority_index));
|
||||||
|
|
||||||
@ -684,7 +706,13 @@ mod benchmarks {
|
|||||||
|
|
||||||
dkg_state.insert_index(authority_index);
|
dkg_state.insert_index(authority_index);
|
||||||
let dkg_index = dkg_state.get_dkg_index();
|
let dkg_index = dkg_state.get_dkg_index();
|
||||||
let exodus_session = CurrentExodus::<T>::get();
|
let all_exodus_sessions = CurrentExodusSessions::<T>::get();
|
||||||
|
let exodus_session = all_exodus_sessions
|
||||||
|
.get(&network_id)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
let exodus_context = ExodusContext::new(network_id, exodus_session);
|
||||||
|
|
||||||
let mut dummy_element = vec![0u8; network_curve.element_bytes_len()];
|
let mut dummy_element = vec![0u8; network_curve.element_bytes_len()];
|
||||||
dummy_element[0] = 0x02;
|
dummy_element[0] = 0x02;
|
||||||
@ -704,9 +732,7 @@ mod benchmarks {
|
|||||||
intervals: [34, 35],
|
intervals: [34, 35],
|
||||||
booleans: [true, true],
|
booleans: [true, true],
|
||||||
};
|
};
|
||||||
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
|
let request = ExodusRequest::<BalanceOf<T>>::evm_governance(
|
||||||
exodus_session,
|
|
||||||
network_id,
|
|
||||||
dummy_address,
|
dummy_address,
|
||||||
create_bond,
|
create_bond,
|
||||||
);
|
);
|
||||||
@ -751,13 +777,13 @@ mod benchmarks {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
let authorities = QualificationAuthorities::<T>::get(&network_curve);
|
||||||
let active_dkg: ActivatedState<T> = (&dkg_state).into();
|
let active_dkg: ReadyDkgAuthorities<T> = (&dkg_state).into();
|
||||||
let active_dkg_index = active_dkg.get_dkg_index();
|
let active_dkg_index = active_dkg.get_dkg_index();
|
||||||
|
|
||||||
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
QualificationDkgState::<T>::insert(&network_curve, dkg_state);
|
||||||
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
ActiveDkgAuthorities::<T>::insert(&network_curve, active_dkg);
|
||||||
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
ActiveAuthorities::<T>::insert(&network_curve, authorities);
|
||||||
ExodusRequests::<T>::insert((network_curve, exodus_session), request);
|
ExodusRequests::<T>::insert((network_curve, exodus_context), request);
|
||||||
|
|
||||||
let mut roast_state = RoastSessionState::<ParticipantsBitmap::<T>>::default();
|
let mut roast_state = RoastSessionState::<ParticipantsBitmap::<T>>::default();
|
||||||
roast_state.status = RoastStatus::PartialSignatures;
|
roast_state.status = RoastStatus::PartialSignatures;
|
||||||
@ -770,8 +796,8 @@ mod benchmarks {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let roast_session = 3;
|
let roast_session = 3;
|
||||||
RoastSessions::<T>::insert(&exodus_session, authority_index, roast_session);
|
RoastSessions::<T>::insert(&exodus_context, authority_index, roast_session);
|
||||||
RoastSessionStates::<T>::insert(exodus_session, roast_session, roast_state);
|
RoastSessionStates::<T>::insert(exodus_context, roast_session, roast_state);
|
||||||
|
|
||||||
let bounded_group_commitment = BoundedVec::try_from(dummy_group_commitment).unwrap();
|
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_key = BoundedVec::try_from(dummy_element.clone()).unwrap();
|
||||||
@ -784,9 +810,9 @@ mod benchmarks {
|
|||||||
|
|
||||||
ActiveVerifyingKey::<T>::insert(&network_curve, dummy_verifying_key);
|
ActiveVerifyingKey::<T>::insert(&network_curve, dummy_verifying_key);
|
||||||
VerifyingShares::<T>::insert((&network_curve, active_dkg_index, authority_index), dummy_verifying_share);
|
VerifyingShares::<T>::insert((&network_curve, active_dkg_index, authority_index), dummy_verifying_share);
|
||||||
NonceCommitments::<T>::insert((&exodus_session, &roast_session), authority_index, dummy_nonce);
|
NonceCommitments::<T>::insert((&exodus_context, &roast_session), authority_index, dummy_nonce);
|
||||||
|
|
||||||
GroupCommitmentsConsensus::<T>::mutate(&exodus_session, &roast_session, |consensus| {
|
GroupCommitmentsConsensus::<T>::mutate(&exodus_context, &roast_session, |consensus| {
|
||||||
consensus.element_bytes = bounded_group_commitment.clone();
|
consensus.element_bytes = bounded_group_commitment.clone();
|
||||||
consensus.merkle_root = dummy_merkle_root;
|
consensus.merkle_root = dummy_merkle_root;
|
||||||
(0..threshold).for_each(|i| {
|
(0..threshold).for_each(|i| {
|
||||||
@ -794,12 +820,14 @@ mod benchmarks {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let current_block = <T as Config>::BlockNumberProvider::current_block_number();
|
||||||
let share_package = PackageContext::default()
|
let share_package = PackageContext::default()
|
||||||
|
.with_block_number(current_block)
|
||||||
.with_network_curve(NetworkCurve::Secp256k1)
|
.with_network_curve(NetworkCurve::Secp256k1)
|
||||||
.with_authority_index(authority_index)
|
.with_authority_index(authority_index)
|
||||||
.with_dkg_index(active_dkg_index)
|
.with_dkg_index(active_dkg_index)
|
||||||
.with_exodus_signature_share(
|
.with_exodus_signature_share(
|
||||||
exodus_session,
|
exodus_context,
|
||||||
dummy_signature_share.clone(),
|
dummy_signature_share.clone(),
|
||||||
dummy_merkle_proof,
|
dummy_merkle_proof,
|
||||||
dummy_binding_factor
|
dummy_binding_factor
|
||||||
@ -815,13 +843,13 @@ mod benchmarks {
|
|||||||
#[extrinsic_call]
|
#[extrinsic_call]
|
||||||
_(RawOrigin::None, exodus_package, signature);
|
_(RawOrigin::None, exodus_package, signature);
|
||||||
|
|
||||||
let maybe_roast_session = RoastSessions::<T>::get(&exodus_session, authority_index);
|
let maybe_roast_session = RoastSessions::<T>::get(&exodus_context, authority_index);
|
||||||
assert!(maybe_roast_session.is_none());
|
assert!(maybe_roast_session.is_none());
|
||||||
|
|
||||||
let scalar_exists = SignatureScalars::<T>::contains_key(&exodus_session, &roast_session);
|
let scalar_exists = SignatureScalars::<T>::contains_key(&exodus_context, &roast_session);
|
||||||
let consensus_exists = GroupCommitmentsConsensus::<T>::contains_key(&exodus_session, &roast_session);
|
let consensus_exists = GroupCommitmentsConsensus::<T>::contains_key(&exodus_context, &roast_session);
|
||||||
let committers_exists = GroupCommitters::<T>::contains_key((
|
let committers_exists = GroupCommitters::<T>::contains_key((
|
||||||
&exodus_session,
|
&exodus_context,
|
||||||
&roast_session,
|
&roast_session,
|
||||||
&dummy_merkle_root,
|
&dummy_merkle_root,
|
||||||
&bounded_group_commitment,
|
&bounded_group_commitment,
|
||||||
@ -831,8 +859,8 @@ mod benchmarks {
|
|||||||
assert!(!consensus_exists);
|
assert!(!consensus_exists);
|
||||||
assert!(!committers_exists);
|
assert!(!committers_exists);
|
||||||
|
|
||||||
assert!(!ExodusRequests::<T>::contains_key((&network_curve, &exodus_session)));
|
assert!(!ExodusRequests::<T>::contains_key((&network_curve, &exodus_context)));
|
||||||
assert!(ExodusSignedGovernance::<T>::contains_key((&exodus_session, network_id), dkg_index));
|
assert!(ExodusSignedGovernance::<T>::contains_key(dkg_index, &exodus_context));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -864,7 +892,11 @@ mod benchmarks {
|
|||||||
let _ = T::NetworkDataHandler::register_incoming(&network_id, amount).unwrap();
|
let _ = T::NetworkDataHandler::register_incoming(&network_id, amount).unwrap();
|
||||||
|
|
||||||
let total_issuance = T::Currency::total_issuance();
|
let total_issuance = T::Currency::total_issuance();
|
||||||
let current_exodus_session = CurrentExodus::<T>::get();
|
let all_exodus_sessions = CurrentExodusSessions::<T>::get();
|
||||||
|
let current_exodus_session = all_exodus_sessions
|
||||||
|
.get(&network_id)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
#[extrinsic_call]
|
#[extrinsic_call]
|
||||||
_(
|
_(
|
||||||
@ -875,8 +907,12 @@ mod benchmarks {
|
|||||||
receiver,
|
receiver,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(ExodusRequests::<T>::contains_key((&network_curve, current_exodus_session)));
|
let all_exodus_sessions = CurrentExodusSessions::<T>::get();
|
||||||
assert_eq!(CurrentExodus::<T>::get(), current_exodus_session + 1);
|
let last_exodus_session = all_exodus_sessions.get(&network_id).copied().unwrap();
|
||||||
|
let context = ExodusContext::new(network_id, current_exodus_session);
|
||||||
|
|
||||||
|
assert!(ExodusRequests::<T>::contains_key((&network_curve, &context)));
|
||||||
|
assert_eq!(last_exodus_session, current_exodus_session + 1);
|
||||||
assert_eq!(T::Currency::balance(&caller), initial_balance - amount);
|
assert_eq!(T::Currency::balance(&caller), initial_balance - amount);
|
||||||
assert_eq!(T::Currency::total_issuance(), total_issuance - amount);
|
assert_eq!(T::Currency::total_issuance(), total_issuance - amount);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -136,14 +136,15 @@ impl ghost_exodus::Config for Runtime {
|
|||||||
type DisabledValidators = Session;
|
type DisabledValidators = Session;
|
||||||
|
|
||||||
type UnsignedPriority = ConstU64<{ 1 << 20 }>;
|
type UnsignedPriority = ConstU64<{ 1 << 20 }>;
|
||||||
type UnsignedLongevity = ConstU64<1>;
|
type UnsignedLongevity = ConstU64<5>;
|
||||||
type MaxAuthorities = ConstU32<10>;
|
type MaxAuthorities = ConstU32<10>;
|
||||||
type MaxAuthoritiesChunks = ConstU32<1>;
|
type MaxAuthoritiesChunks = ConstU32<1>;
|
||||||
|
|
||||||
type DkgRoundPeriod = ConstU64<100>;
|
type DkgRoundPeriod = ConstU64<300>;
|
||||||
type RemovalLimit = ConstU32<20>;
|
type RemovalLimit = ConstU32<20>;
|
||||||
type MaxCursorLen = ConstU32<20>;
|
type MaxCursorLen = ConstU32<256>;
|
||||||
type BaseEvmAmount = ConstU128<5>;
|
type BaseEvmAmount = ConstU128<5>;
|
||||||
|
type MaxExodusRequestCount = ConstU32<40>;
|
||||||
|
|
||||||
type WeightInfo = ();
|
type WeightInfo = ();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,12 +70,7 @@ fn run_increase_block_by(ext: &mut sp_io::TestExternalities, increase_by: u64) {
|
|||||||
|
|
||||||
fn run_to_next_round(ext: &mut sp_io::TestExternalities, curve: NetworkCurve) {
|
fn run_to_next_round(ext: &mut sp_io::TestExternalities, curve: NetworkCurve) {
|
||||||
let target_block = ext.execute_with(|| {
|
let target_block = ext.execute_with(|| {
|
||||||
let stored = QualificationDkgState::<Runtime>::get(curve).get_block();
|
QualificationDkgState::<Runtime>::get(curve).get_release_block()
|
||||||
let delay = <<Runtime as Config>::DkgRoundPeriod as frame_support::traits::Get<
|
|
||||||
frame_system::pallet_prelude::BlockNumberFor<Runtime>
|
|
||||||
>>::get();
|
|
||||||
|
|
||||||
stored + delay
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ext.execute_with(|| {
|
ext.execute_with(|| {
|
||||||
@ -139,9 +134,9 @@ fn execute_dkg_happy_path<F1, F2, F3>(
|
|||||||
where
|
where
|
||||||
F1: FnMut(
|
F1: FnMut(
|
||||||
DkgStorage<BlockNumberFor<Runtime>, NetworkCurve>,
|
DkgStorage<BlockNumberFor<Runtime>, NetworkCurve>,
|
||||||
&QualifyingState<Runtime>,
|
&PendingDkgAuthorities<Runtime>,
|
||||||
UintAuthorityId,
|
UintAuthorityId,
|
||||||
) -> Result<ExodusOk<NetworkCurve>, ExodusError>,
|
) -> Result<ExodusOk<NetworkCurve, NetworkIdOf<Runtime>>, ExodusError>,
|
||||||
|
|
||||||
F2: FnMut(Call<Runtime>) -> Result<(), TestError>,
|
F2: FnMut(Call<Runtime>) -> Result<(), TestError>,
|
||||||
F3: FnMut(AuthIndex, NetworkCurve) -> Result<(), TestError>,
|
F3: FnMut(AuthIndex, NetworkCurve) -> Result<(), TestError>,
|
||||||
@ -203,78 +198,6 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_exodus_happy_path<F1, F2>(
|
|
||||||
ext: &mut sp_io::TestExternalities,
|
|
||||||
tx_pool_state: &std::sync::Arc<parking_lot::RwLock<sp_core::offchain::testing::PoolState>>,
|
|
||||||
curve: NetworkCurve,
|
|
||||||
authority: u64,
|
|
||||||
mut apply_transaction: F1,
|
|
||||||
mut check_storage_changed: F2,
|
|
||||||
) -> Result<(), TestError>
|
|
||||||
where
|
|
||||||
F1: FnMut(Call<Runtime>) -> Result<(), TestError>,
|
|
||||||
F2: FnMut(ExodusOk<NetworkCurve>) -> Result<(), TestError>,
|
|
||||||
{
|
|
||||||
use sp_runtime::transaction_validity::TransactionSource;
|
|
||||||
|
|
||||||
let state = ext.execute_with(|| QualificationDkgState::<Runtime>::get(&curve));
|
|
||||||
if state.is_dkg_pending() {
|
|
||||||
return Err(TestError::PhaseMismatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
let active_authorities = ext.execute_with(|| {
|
|
||||||
ActiveDkgAuthorities::<Runtime>::get(&curve)
|
|
||||||
});
|
|
||||||
|
|
||||||
let current_block = ext.execute_with(|| Exodus::current_block_number());
|
|
||||||
let authority_index = authority as AuthIndex;
|
|
||||||
let authority_key = authority.into();
|
|
||||||
|
|
||||||
let exodus_process_result = ext.execute_with(|| {
|
|
||||||
Exodus::exodus_run_process(
|
|
||||||
authority_index,
|
|
||||||
authority_key,
|
|
||||||
curve,
|
|
||||||
current_block,
|
|
||||||
&active_authorities,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
match exodus_process_result {
|
|
||||||
Ok(ExodusOk::ExodusEmptyRequests(_, _)) => return Ok(()),
|
|
||||||
Err(_) => return Err(TestError::WorkerExecutionFailed),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut write_pool = tx_pool_state.write();
|
|
||||||
let raw_tx = write_pool.transactions.pop().ok_or(TestError::PoolIsEmpty)?;
|
|
||||||
let runtime_call = decode_transaction::<Runtime, RuntimeCall, ()>(&raw_tx)
|
|
||||||
.ok_or(TestError::TransactionDecodeFailed)?;
|
|
||||||
|
|
||||||
if let RuntimeCall::Exodus(inner_exodus_call) = runtime_call {
|
|
||||||
ext.execute_with(|| {
|
|
||||||
let is_mempool_ok = Exodus::validate_unsigned(TransactionSource::InBlock, &inner_exodus_call).is_ok();
|
|
||||||
if !is_mempool_ok {
|
|
||||||
return Err(TestError::MempoolRejectedTransaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_transaction(inner_exodus_call)
|
|
||||||
.map_err(|_| TestError::OnChainApplicationFailed)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return Err(TestError::UnexpectedRuntimeCall);
|
|
||||||
}
|
|
||||||
write_pool.transactions.clear();
|
|
||||||
ext.execute_with(|| {
|
|
||||||
check_storage_changed(exodus_process_result.unwrap())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute_round0_happy_path(
|
fn execute_round0_happy_path(
|
||||||
ext: &mut sp_io::TestExternalities,
|
ext: &mut sp_io::TestExternalities,
|
||||||
tx_pool_state: &std::sync::Arc<parking_lot::RwLock<sp_core::offchain::testing::PoolState>>,
|
tx_pool_state: &std::sync::Arc<parking_lot::RwLock<sp_core::offchain::testing::PoolState>>,
|
||||||
@ -701,7 +624,8 @@ fn run_initial_dkg_session(raw_authorities: &[u64], curve: NetworkCurve) -> (
|
|||||||
let member = *authority as AuthIndex;
|
let member = *authority as AuthIndex;
|
||||||
assert!(state.contains_index(member));
|
assert!(state.contains_index(member));
|
||||||
}
|
}
|
||||||
assert_eq!(state.get_block(), start_block + round_delay * 9);
|
|
||||||
|
assert_eq!(state.get_release_block(), start_block + round_delay * 8 + 2 * BLOCKS_FOR_DKG_RESET);
|
||||||
assert_eq!(state.get_dkg_index(), 1);
|
assert_eq!(state.get_dkg_index(), 1);
|
||||||
assert_eq!(state.get_phase(), DkgPhase::Finalized);
|
assert_eq!(state.get_phase(), DkgPhase::Finalized);
|
||||||
|
|
||||||
@ -738,278 +662,74 @@ fn run_dkg_session(
|
|||||||
let (start_block, round_delay) =
|
let (start_block, round_delay) =
|
||||||
run_succesfull_dkg_session_partially(ext, tx_pool_state, &raw_authorities, curve);
|
run_succesfull_dkg_session_partially(ext, tx_pool_state, &raw_authorities, curve);
|
||||||
|
|
||||||
let register_nonce = |call| {
|
let total_validators = prev_authorities.len();
|
||||||
match call {
|
let threshold = get_byzantium_quorum_threshold(total_validators);
|
||||||
Call::register_nonce_commitment { exodus_package, signature } => {
|
let max_allowed_to_skip = total_validators.saturating_sub(threshold);
|
||||||
Exodus::register_nonce_commitment(RuntimeOrigin::none(), exodus_package, signature)
|
|
||||||
.map_err(|_| TestError::OnChainApplicationFailed)
|
|
||||||
}
|
|
||||||
_ => Err(TestError::CallMismatch),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let register_group = |call| {
|
|
||||||
match call {
|
|
||||||
Call::register_group_commitment { exodus_package, signature } => {
|
|
||||||
Exodus::register_group_commitment(RuntimeOrigin::none(), exodus_package, signature)
|
|
||||||
.map_err(|_| TestError::OnChainApplicationFailed)
|
|
||||||
}
|
|
||||||
_ => Err(TestError::CallMismatch),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let register_share = |call| {
|
|
||||||
match call {
|
|
||||||
Call::register_signature_share { exodus_package, signature } => {
|
|
||||||
Exodus::register_signature_share(RuntimeOrigin::none(), exodus_package, signature)
|
|
||||||
.map_err(|_| TestError::OnChainApplicationFailed)
|
|
||||||
}
|
|
||||||
_ => Err(TestError::CallMismatch),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let check_nonce = |exodus_ok| {
|
|
||||||
match exodus_ok {
|
|
||||||
ExodusOk::ExodusNonceCommitted(exodus, roast, idx, _) => {
|
|
||||||
if !NonceCommitments::<Runtime>::contains_key((exodus, roast), idx) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !RoastSessions::<Runtime>::contains_key(exodus, idx) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
let roast_state = RoastSessionStates::<Runtime>::get(exodus, roast);
|
|
||||||
|
|
||||||
if !roast_state.nonce_committers.contains(idx)
|
|
||||||
|| roast_state.group_committers.contains(idx)
|
|
||||||
|| roast_state.partial_signers.contains(idx) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Err(TestError::InvalidStorageAfter),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let check_group = |exodus_ok| {
|
|
||||||
match exodus_ok {
|
|
||||||
ExodusOk::ExodusGroupCommitted(exodus, roast, idx, _) => {
|
|
||||||
if !RoastSessions::<Runtime>::contains_key(exodus, idx) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !GroupCommitters::<Runtime>::iter_prefix_values((exodus, roast))
|
|
||||||
.any(|participants| participants.contains(idx)) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
let roast_state = RoastSessionStates::<Runtime>::get(exodus, roast);
|
|
||||||
|
|
||||||
let is_nonce_committer = roast_state.nonce_committers.contains(idx);
|
|
||||||
let is_group_committer = roast_state.group_committers.contains(idx);
|
|
||||||
|
|
||||||
if !is_nonce_committer || !is_group_committer {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Err(TestError::InvalidStorageAfter),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let check_share = |exodus_ok| {
|
|
||||||
match exodus_ok {
|
|
||||||
ExodusOk::ExodusSignedPartially(exodus, roast, idx, curve) => {
|
|
||||||
if RoastSessions::<Runtime>::contains_key(exodus, idx) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if RoastSessions::<Runtime>::contains_key(exodus, idx) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ExodusRequests::<Runtime>::contains_key((curve, exodus)) {
|
|
||||||
let roast_state = RoastSessionStates::<Runtime>::get(exodus, roast);
|
|
||||||
if !roast_state.partial_signers.contains(idx)
|
|
||||||
|| !roast_state.nonce_committers.contains(idx)
|
|
||||||
|| !roast_state.group_committers.contains(idx) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if RoastSessionStates::<Runtime>::contains_key(exodus, roast) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if SignatureScalars::<Runtime>::contains_key(exodus, roast) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if GroupCommitmentsConsensus::<Runtime>::contains_key(exodus, roast) {
|
|
||||||
return Err(TestError::InvalidStorageAfter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Err(TestError::InvalidStorageAfter),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let threshold = ext.execute_with(|| {
|
|
||||||
let len = ActiveAuthorities::<Runtime>::decode_len(&curve)
|
|
||||||
.unwrap_or(0);
|
|
||||||
get_byzantium_quorum_threshold(len) as u16
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut exodus_steps_outer = BTreeMap::new();
|
|
||||||
let mut roast_sessions_outer = BTreeMap::new();
|
|
||||||
let mut roast_participants_outer = BTreeMap::new();
|
|
||||||
let mut malicious_participants_outer = BTreeMap::new();
|
|
||||||
let mut throttled_participants_outer = BTreeMap::new();
|
|
||||||
|
|
||||||
let malicious = prev_authorities.first().copied().unwrap();
|
|
||||||
let throttled = prev_authorities.last().copied().unwrap();
|
|
||||||
let prev_len = prev_authorities.len() as AuthIndex;
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut current_pending_requests: Vec<ExodusSession> = ext.execute_with(|| {
|
let mut skipped_in_this_round = 0;
|
||||||
|
|
||||||
|
let has_pending_requests = ext.execute_with(|| {
|
||||||
ExodusRequests::<Runtime>::iter_keys()
|
ExodusRequests::<Runtime>::iter_keys()
|
||||||
.filter_map(|(current_curve, exodus_session)| {
|
.any(|(current_curve, _context)| current_curve == curve)
|
||||||
curve.eq(¤t_curve).then(|| exodus_session)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
current_pending_requests.sort();
|
if !has_pending_requests { break; }
|
||||||
|
|
||||||
if let Some(exodus_session) = current_pending_requests.first() {
|
|
||||||
if !current_pending_requests.contains(exodus_session) { continue; }
|
|
||||||
|
|
||||||
let exodus_steps: &mut BTreeMap<u64, RoastSession> = exodus_steps_outer.entry(*exodus_session).or_default();
|
|
||||||
let roast_sessions: &mut BTreeMap<u64, RoastSession> = roast_sessions_outer.entry(*exodus_session).or_default();
|
|
||||||
let roast_participants: &mut BTreeMap<RoastSession, (u16, u16, u16)> = roast_participants_outer.entry(*exodus_session).or_default();
|
|
||||||
|
|
||||||
let malicious_participants: &mut BTreeSet<u64> = malicious_participants_outer.entry(*exodus_session).or_default();
|
|
||||||
let throttled_participants: &mut BTreeSet<u64> = throttled_participants_outer.entry(*exodus_session).or_default();
|
|
||||||
|
|
||||||
for auth in prev_authorities.iter() {
|
for auth in prev_authorities.iter() {
|
||||||
let request_exists = ext.execute_with(|| {
|
let authority_index = *auth as AuthIndex;
|
||||||
ExodusRequests::<Runtime>::contains_key((&curve, &exodus_session))
|
let current_block = ext.execute_with(|| System::block_number());
|
||||||
});
|
let current_block_u64: u64 = current_block.unique_saturated_into();
|
||||||
|
let should_throttle = (current_block_u64 + *auth) % 3 == 0;
|
||||||
|
|
||||||
if !request_exists { break; }
|
if should_throttle && skipped_in_this_round < max_allowed_to_skip {
|
||||||
if malicious_participants.contains(auth) { continue; }
|
skipped_in_this_round += 1;
|
||||||
if throttled_participants.contains(auth) { continue; }
|
run_increase_block_by(ext, 1);
|
||||||
|
continue;
|
||||||
let mut current_step = exodus_steps.get(&auth).copied().unwrap_or(0);
|
|
||||||
let mut roast_session = roast_sessions.get(&auth).copied().unwrap_or(0);
|
|
||||||
|
|
||||||
let mut participants = roast_participants
|
|
||||||
.get(&roast_session)
|
|
||||||
.copied()
|
|
||||||
.unwrap_or((0, 0, 0));
|
|
||||||
|
|
||||||
let mut has_enough_nonces = participants.0 >= threshold;
|
|
||||||
let mut has_enough_groups = participants.1 >= threshold;
|
|
||||||
|
|
||||||
if has_enough_nonces && current_step == 0 {
|
|
||||||
roast_session += 1;
|
|
||||||
|
|
||||||
participants = roast_participants
|
|
||||||
.get(&roast_session)
|
|
||||||
.copied()
|
|
||||||
.unwrap_or((0, 0, 0));
|
|
||||||
|
|
||||||
has_enough_nonces = participants.0 >= threshold;
|
|
||||||
has_enough_groups = participants.1 >= threshold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = match current_step {
|
|
||||||
0 => {
|
|
||||||
current_step += 1;
|
|
||||||
participants.0 += 1;
|
|
||||||
execute_exodus_happy_path(ext, tx_pool_state, curve, *auth, register_nonce, check_nonce)
|
|
||||||
},
|
|
||||||
1 if has_enough_nonces => {
|
|
||||||
participants.1 += 1;
|
|
||||||
let result = execute_exodus_happy_path(ext, tx_pool_state, curve, *auth, register_group, check_group);
|
|
||||||
|
|
||||||
if malicious == *auth && prev_len > threshold {
|
|
||||||
ext.execute_with(|| {
|
ext.execute_with(|| {
|
||||||
let raw_vec = vec![69u8; ELEMENT_MAX_BYTES as usize];
|
let authority_key = (*auth).into();
|
||||||
let fake_group_commitment =
|
let active_authorities = ActiveDkgAuthorities::<Runtime>::get(curve);
|
||||||
BoundedVec::<u8, ConstU32<{ ELEMENT_MAX_BYTES }>>::try_from(raw_vec)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let empty_participants = ParticipantsBitmap::<Runtime>::empty(prev_len);
|
let _ = Exodus::exodus_run_process(
|
||||||
let mut self_participant = empty_participants.clone();
|
authority_index,
|
||||||
self_participant.insert(malicious);
|
authority_key,
|
||||||
|
curve,
|
||||||
let (correct_commitment, correct_root) = GroupCommitmentsConsensus::<Runtime>::mutate(
|
current_block,
|
||||||
&exodus_session,
|
&active_authorities,
|
||||||
&roast_session,
|
|
||||||
|consensus| {
|
|
||||||
let binding_root = consensus.merkle_root;
|
|
||||||
let group_commitment = consensus
|
|
||||||
.element_bytes
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
*consensus = ConsensusState::new(
|
|
||||||
fake_group_commitment.clone(),
|
|
||||||
consensus.participants.clone(),
|
|
||||||
DUMMY_HASH,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
(group_commitment, binding_root)
|
let txs = tx_pool_state.write().transactions.drain(..).collect::<Vec<_>>();
|
||||||
});
|
|
||||||
|
|
||||||
let prev_group_key = (exodus_session, roast_session, correct_root, correct_commitment);
|
for raw_tx in txs.iter() {
|
||||||
GroupCommitters::<Runtime>::insert(prev_group_key, empty_participants);
|
let runtime_call = decode_transaction::<Runtime, RuntimeCall, ()>(&raw_tx)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let fake_group_key = (exodus_session, roast_session, DUMMY_HASH, fake_group_commitment);
|
if let RuntimeCall::Exodus(inner_exodus_call) = runtime_call {
|
||||||
GroupCommitters::<Runtime>::insert(fake_group_key, self_participant);
|
Exodus::validate_unsigned(TransactionSource::InBlock, &inner_exodus_call).unwrap();
|
||||||
|
|
||||||
malicious_participants.insert(malicious);
|
let dispatch_result = match inner_exodus_call {
|
||||||
});
|
Call::register_nonce_commitment { exodus_package, signature } => {
|
||||||
} else {
|
Exodus::register_nonce_commitment(RuntimeOrigin::none(), exodus_package, signature)
|
||||||
current_step += 1;
|
},
|
||||||
}
|
Call::register_group_commitment { exodus_package, signature } => {
|
||||||
|
Exodus::register_group_commitment(RuntimeOrigin::none(), exodus_package, signature)
|
||||||
result
|
},
|
||||||
}
|
Call::register_signature_share { exodus_package, signature } => {
|
||||||
2 if has_enough_groups => {
|
Exodus::register_signature_share(RuntimeOrigin::none(), exodus_package, signature)
|
||||||
if prev_len > threshold + 1 && *auth == throttled {
|
},
|
||||||
throttled_participants.insert(*auth);
|
_ => panic!("Unexpected Call inside Exodus Pallet"),
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_step = 0;
|
|
||||||
participants.2 += 1;
|
|
||||||
execute_exodus_happy_path(ext, tx_pool_state, curve, *auth, register_share, check_share).unwrap();
|
|
||||||
|
|
||||||
exodus_steps.insert(*auth, current_step);
|
|
||||||
roast_sessions.insert(*auth, roast_session + 1);
|
|
||||||
roast_participants.insert(roast_session, participants);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_ => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
result.unwrap();
|
dispatch_result.unwrap();
|
||||||
exodus_steps.insert(*auth, current_step);
|
} else {
|
||||||
roast_sessions.insert(*auth, roast_session);
|
panic!("Expected one of RuntimeCall::Exodus");
|
||||||
roast_participants.insert(roast_session, participants);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
run_increase_block_by(ext, 1);
|
run_increase_block_by(ext, 1);
|
||||||
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1025,7 +745,7 @@ fn run_dkg_session(
|
|||||||
let member = authority as AuthIndex;
|
let member = authority as AuthIndex;
|
||||||
assert!(state.contains_index(member));
|
assert!(state.contains_index(member));
|
||||||
}
|
}
|
||||||
assert_eq!(state.get_block(), start_block + round_delay * 9);
|
assert_eq!(state.get_release_block(), start_block + round_delay * 8 + 2 * BLOCKS_FOR_DKG_RESET);
|
||||||
assert_eq!(state.get_dkg_index(), next_dkg_index);
|
assert_eq!(state.get_dkg_index(), next_dkg_index);
|
||||||
assert_eq!(state.get_phase(), DkgPhase::Finalized);
|
assert_eq!(state.get_phase(), DkgPhase::Finalized);
|
||||||
|
|
||||||
@ -1094,10 +814,13 @@ fn test_dkg_robustness_against_malformed_scale_slots() {
|
|||||||
blob: malformed_blob,
|
blob: malformed_blob,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let current_block_number = Exodus::current_block_number();
|
||||||
|
|
||||||
let dummy_context = PackageContext::default()
|
let dummy_context = PackageContext::default()
|
||||||
.with_authority_index(malicious_validator as AuthIndex)
|
.with_authority_index(malicious_validator as AuthIndex)
|
||||||
.with_network_curve(curve)
|
.with_network_curve(curve)
|
||||||
.with_dkg_index(dkg_index)
|
.with_dkg_index(dkg_index)
|
||||||
|
.with_block_number(current_block_number)
|
||||||
.with_dkg_round2(dummy_encryption_bundle)
|
.with_dkg_round2(dummy_encryption_bundle)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -1203,6 +926,14 @@ fn test_all_validators_can_execute_dkg() {
|
|||||||
|
|
||||||
let (mut ext, tx_pool_state) = run_initial_dkg_session(&authorities_1, curve);
|
let (mut ext, tx_pool_state) = run_initial_dkg_session(&authorities_1, curve);
|
||||||
|
|
||||||
|
let mut authorities_2 = authorities_1.clone();
|
||||||
|
let new_authority = authorities_2.iter().max().unwrap() + 1;
|
||||||
|
authorities_2.push(new_authority);
|
||||||
|
authorities_2.push(new_authority + 1);
|
||||||
|
authorities_2.push(new_authority + 2);
|
||||||
|
|
||||||
|
run_dkg_session(&mut ext, &tx_pool_state, authorities_1.clone(), authorities_2.clone(), curve);
|
||||||
|
|
||||||
ext.execute_with(|| {
|
ext.execute_with(|| {
|
||||||
let network_data = NetworkDataBuilder::default()
|
let network_data = NetworkDataBuilder::default()
|
||||||
.with_network_curve(curve)
|
.with_network_curve(curve)
|
||||||
@ -1248,13 +979,10 @@ fn test_all_validators_can_execute_dkg() {
|
|||||||
Exodus::do_register_evm_governance(network_id, dummy_address, create).unwrap();
|
Exodus::do_register_evm_governance(network_id, dummy_address, create).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut authorities_2 = authorities_1.clone();
|
let mut authorities_3 = FixedAuthorities::get();
|
||||||
let new_authority = authorities_2.iter().max().unwrap() + 1;
|
authorities_3.push(new_authority);
|
||||||
authorities_2.push(new_authority);
|
|
||||||
authorities_2.push(new_authority + 1);
|
|
||||||
authorities_2.push(new_authority + 2);
|
|
||||||
|
|
||||||
run_dkg_session(&mut ext, &tx_pool_state, authorities_1, authorities_2.clone(), curve);
|
run_dkg_session(&mut ext, &tx_pool_state, authorities_2.clone(), authorities_3, curve);
|
||||||
|
|
||||||
ext.execute_with(|| {
|
ext.execute_with(|| {
|
||||||
Exodus::do_register_evm_bridge_out_exodus(
|
Exodus::do_register_evm_bridge_out_exodus(
|
||||||
@ -1279,10 +1007,7 @@ fn test_all_validators_can_execute_dkg() {
|
|||||||
Exodus::do_register_evm_governance(network_id, dummy_address, audit).unwrap();
|
Exodus::do_register_evm_governance(network_id, dummy_address, audit).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut authorities_3 = FixedAuthorities::get();
|
run_dkg_session(&mut ext, &tx_pool_state, authorities_1, authorities_2.clone(), curve);
|
||||||
authorities_3.push(new_authority);
|
|
||||||
|
|
||||||
run_dkg_session(&mut ext, &tx_pool_state, authorities_2, authorities_3, curve);
|
|
||||||
|
|
||||||
let rotations_count = ext.execute_with(|| {
|
let rotations_count = ext.execute_with(|| {
|
||||||
ExodusSignedRotations::<Runtime>::iter().count()
|
ExodusSignedRotations::<Runtime>::iter().count()
|
||||||
@ -1300,7 +1025,7 @@ fn test_all_validators_can_execute_dkg() {
|
|||||||
ExodusRequests::<Runtime>::count()
|
ExodusRequests::<Runtime>::count()
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(rotations_count, 2);
|
assert_eq!(rotations_count, 5);
|
||||||
assert_eq!(bridges_count, 2);
|
assert_eq!(bridges_count, 2);
|
||||||
assert_eq!(governances_count, 15);
|
assert_eq!(governances_count, 15);
|
||||||
assert_eq!(pending_exodus_requests, 0);
|
assert_eq!(pending_exodus_requests, 0);
|
||||||
@ -1331,14 +1056,10 @@ fn test_exodus_dkg_robustness() {
|
|||||||
QualificationDkgState::<Runtime>::get(curve).get_dkg_index()
|
QualificationDkgState::<Runtime>::get(curve).get_dkg_index()
|
||||||
});
|
});
|
||||||
|
|
||||||
let (start_block, round_delay) = ext.execute_with(|| {
|
let round_delay = ext.execute_with(|| {
|
||||||
let round_delay = <<Runtime as Config>::DkgRoundPeriod as frame_support::traits::Get<
|
<<Runtime as Config>::DkgRoundPeriod as frame_support::traits::Get<
|
||||||
frame_system::pallet_prelude::BlockNumberFor<Runtime>
|
frame_system::pallet_prelude::BlockNumberFor<Runtime>
|
||||||
>>::get();
|
>>::get()
|
||||||
|
|
||||||
let start_block = System::block_number();
|
|
||||||
|
|
||||||
(start_block, round_delay)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut failed_at_round = None;
|
let mut failed_at_round = None;
|
||||||
@ -1419,8 +1140,9 @@ fn test_exodus_dkg_robustness() {
|
|||||||
})
|
})
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
let estimated_block = start_block + round_delay * (total_round_idx as u64);
|
let current_system_block = ext.execute_with(|| System::block_number());
|
||||||
assert_eq!(state.get_block(), estimated_block);
|
|
||||||
|
assert_eq!(state.get_release_block(), current_system_block + round_delay);
|
||||||
assert_eq!(state.get_dkg_index(), dkg_index);
|
assert_eq!(state.get_dkg_index(), dkg_index);
|
||||||
assert_eq!(state.get_phase(), DkgPhase::Finalized);
|
assert_eq!(state.get_phase(), DkgPhase::Finalized);
|
||||||
|
|
||||||
|
|||||||
@ -1,28 +1,45 @@
|
|||||||
use sp_runtime::{RuntimeDebug, traits::UniqueSaturatedInto};
|
use sp_runtime::{RuntimeDebug, traits::UniqueSaturatedInto};
|
||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
use strum::EnumCount;
|
|
||||||
|
|
||||||
use frame_support::{BoundedVec, traits::ConstU32};
|
use frame_support::{BoundedVec, traits::ConstU32};
|
||||||
|
|
||||||
use ghost_helpers::networks::NetworkType;
|
use ghost_traits::{
|
||||||
use ghost_traits::bounded_bitmap::{
|
networks::NetworkDataBasicHandler,
|
||||||
|
bounded_bitmap::{
|
||||||
BoundedBitmapGenerator, BoundedBitmapReader, BoundedBitmapWriter,
|
BoundedBitmapGenerator, BoundedBitmapReader, BoundedBitmapWriter,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{ELEMENT_MAX_BYTES, ExodusSession, DkgIndex};
|
use crate::{
|
||||||
|
ELEMENT_MAX_BYTES, Config, ExodusContext, NetworkIdOf,
|
||||||
|
ParticipantsBitmap, BlockNumberFor, DkgIndex,
|
||||||
|
};
|
||||||
|
|
||||||
type RotationSessions = BoundedVec<RotationSession, ConstU32<{ NetworkType::COUNT as u32 }>>;
|
type RotationSessions<T> = BoundedVec<
|
||||||
|
ExodusContext<NetworkIdOf<T>>,
|
||||||
|
<<T as Config>::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks,
|
||||||
|
>;
|
||||||
|
|
||||||
#[derive(Default, Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||||
pub struct ReadyDkgAuthorities<AuthoritiesBitmap> {
|
#[scale_info(skip_type_params(T))]
|
||||||
authorities_indexes: AuthoritiesBitmap,
|
pub struct ReadyDkgAuthorities<T: Config> {
|
||||||
|
authorities_indexes: ParticipantsBitmap<T>,
|
||||||
dkg_index: DkgIndex,
|
dkg_index: DkgIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AuthoritiesBitmap> ReadyDkgAuthorities<AuthoritiesBitmap>
|
impl<T: Config> Default for ReadyDkgAuthorities<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
authorities_indexes: Default::default(),
|
||||||
|
dkg_index: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Config> ReadyDkgAuthorities<T>
|
||||||
where
|
where
|
||||||
AuthoritiesBitmap: BoundedBitmapReader,
|
ParticipantsBitmap<T>: BoundedBitmapReader,
|
||||||
{
|
{
|
||||||
pub fn contains_index<N>(&self, index: N) -> bool
|
pub fn contains_index<N>(&self, index: N) -> bool
|
||||||
where N: UniqueSaturatedInto<usize>,
|
where N: UniqueSaturatedInto<usize>,
|
||||||
@ -30,7 +47,7 @@ where
|
|||||||
self.authorities_indexes.contains(index)
|
self.authorities_indexes.contains(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_indexes(&self) -> &AuthoritiesBitmap {
|
pub fn get_indexes(&self) -> &ParticipantsBitmap<T> {
|
||||||
&self.authorities_indexes
|
&self.authorities_indexes
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,15 +56,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AuthoritiesBitmap, Block>
|
impl<T: Config>
|
||||||
From<&PendingDkgAuthorities<AuthoritiesBitmap, Block>>
|
From<&PendingDkgAuthorities<T>>
|
||||||
for ReadyDkgAuthorities<AuthoritiesBitmap>
|
for ReadyDkgAuthorities<T>
|
||||||
where
|
where
|
||||||
Block: Copy,
|
BlockNumberFor<T>: Copy,
|
||||||
AuthoritiesBitmap: BoundedBitmapWriter + BoundedBitmapReader + BoundedBitmapGenerator + Clone,
|
ParticipantsBitmap<T>: BoundedBitmapWriter + BoundedBitmapReader + BoundedBitmapGenerator + Clone,
|
||||||
for<'a> AuthoritiesBitmap: core::ops::BitAndAssign<&'a AuthoritiesBitmap>,
|
for<'a> ParticipantsBitmap<T>: core::ops::BitAndAssign<&'a ParticipantsBitmap<T>>,
|
||||||
{
|
{
|
||||||
fn from(pending: &PendingDkgAuthorities<AuthoritiesBitmap, Block>) -> Self {
|
fn from(pending: &PendingDkgAuthorities<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
authorities_indexes: pending.get_indexes().clone(),
|
authorities_indexes: pending.get_indexes().clone(),
|
||||||
dkg_index: pending.get_dkg_index(),
|
dkg_index: pending.get_dkg_index(),
|
||||||
@ -55,34 +72,40 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||||
pub struct RotationSession {
|
#[scale_info(skip_type_params(T))]
|
||||||
pub exodus_session: ExodusSession,
|
pub struct PendingDkgAuthorities<T: Config> {
|
||||||
pub network_type: NetworkType
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
|
||||||
pub struct PendingDkgAuthorities<AuthoritiesBitmap, Block> {
|
|
||||||
verifying_key: BoundedVec<u8, ConstU32<ELEMENT_MAX_BYTES>>,
|
verifying_key: BoundedVec<u8, ConstU32<ELEMENT_MAX_BYTES>>,
|
||||||
authorities_indexes: AuthoritiesBitmap,
|
authorities_indexes: ParticipantsBitmap<T>,
|
||||||
rotation_sessions: RotationSessions,
|
rotation_sessions: RotationSessions<T>,
|
||||||
dkg_state: DkgState<Block>,
|
dkg_state: DkgState<BlockNumberFor<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AuthoritiesBitmap, Block> PendingDkgAuthorities<AuthoritiesBitmap, Block>
|
impl<T: Config> Default for PendingDkgAuthorities<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
verifying_key: Default::default(),
|
||||||
|
authorities_indexes: Default::default(),
|
||||||
|
rotation_sessions: Default::default(),
|
||||||
|
dkg_state: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Config> PendingDkgAuthorities<T>
|
||||||
where
|
where
|
||||||
Block: Copy,
|
BlockNumberFor<T>: Copy,
|
||||||
AuthoritiesBitmap: BoundedBitmapWriter + BoundedBitmapReader + BoundedBitmapGenerator + Clone,
|
ParticipantsBitmap<T>: BoundedBitmapWriter + BoundedBitmapReader + BoundedBitmapGenerator + Clone,
|
||||||
for<'a> AuthoritiesBitmap: core::ops::BitAndAssign<&'a AuthoritiesBitmap>,
|
for<'a> ParticipantsBitmap<T>: core::ops::BitAndAssign<&'a ParticipantsBitmap<T>>,
|
||||||
{
|
{
|
||||||
pub fn new_dkg(&mut self, authorities_len: usize) {
|
pub fn new_dkg(&mut self, authorities_len: usize) {
|
||||||
self.authorities_indexes = AuthoritiesBitmap::empty(authorities_len);
|
self.authorities_indexes = ParticipantsBitmap::<T>::empty(authorities_len);
|
||||||
self.dkg_state.restart();
|
self.dkg_state.restart();
|
||||||
self.rotation_sessions = Default::default();
|
self.rotation_sessions = Default::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_block(&mut self, block: Block) {
|
pub fn set_release_block(&mut self, block: BlockNumberFor<T>) {
|
||||||
self.dkg_state.set_block(block);
|
self.dkg_state.set_release_block(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_verifying_key(
|
pub fn set_verifying_key(
|
||||||
@ -109,7 +132,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn intersect_indexes(&mut self, mask: &AuthoritiesBitmap) {
|
pub fn intersect_indexes(&mut self, mask: &ParticipantsBitmap<T>) {
|
||||||
self.authorities_indexes &= mask;
|
self.authorities_indexes &= mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,8 +148,8 @@ where
|
|||||||
self.dkg_state.get_dkg_index()
|
self.dkg_state.get_dkg_index()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_block(&self) -> Block {
|
pub fn get_release_block(&self) -> BlockNumberFor<T> {
|
||||||
self.dkg_state.get_block()
|
self.dkg_state.get_release_block()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_phase(&self) -> DkgPhase {
|
pub fn get_phase(&self) -> DkgPhase {
|
||||||
@ -183,17 +206,11 @@ where
|
|||||||
self.authorities_indexes.insert(i)
|
self.authorities_indexes.insert(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_push_rotation_session(
|
pub fn try_push_rotation_context(
|
||||||
&mut self,
|
&mut self,
|
||||||
exodus_session: ExodusSession,
|
context: ExodusContext<NetworkIdOf<T>>,
|
||||||
network_type: NetworkType,
|
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let rotation_session = RotationSession {
|
self.rotation_sessions.try_push(context).ok()
|
||||||
exodus_session,
|
|
||||||
network_type,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.rotation_sessions.try_push(rotation_session).ok()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count_ones<N>(&self) -> N
|
pub fn count_ones<N>(&self) -> N
|
||||||
@ -208,43 +225,44 @@ where
|
|||||||
self.authorities_indexes.highest_bit()
|
self.authorities_indexes.highest_bit()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_indexes(&self) -> &AuthoritiesBitmap {
|
pub fn get_indexes(&self) -> &ParticipantsBitmap<T> {
|
||||||
&self.authorities_indexes
|
&self.authorities_indexes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_rotation_sessions(&self) -> impl Iterator<Item = &RotationSession> {
|
pub fn iter_rotation_contexts(
|
||||||
|
&self
|
||||||
|
) -> impl Iterator<Item = &ExodusContext<NetworkIdOf<T>>> {
|
||||||
self.rotation_sessions.iter()
|
self.rotation_sessions.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
#[derive(Default, Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)]
|
||||||
pub struct DkgState<Block> {
|
pub struct DkgState<Block> {
|
||||||
block: Block,
|
release_block: Block,
|
||||||
index: DkgIndex,
|
dkg_index: DkgIndex,
|
||||||
phase: DkgPhase,
|
dkg_phase: DkgPhase,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Block: Copy> DkgState<Block> {
|
impl<Block: Copy> DkgState<Block> {
|
||||||
fn is_dkg_pending(&self) -> bool { self.phase.is_dkg_pending() }
|
fn is_dkg_pending(&self) -> bool { self.dkg_phase.is_dkg_pending() }
|
||||||
fn is_dkg_vacant(&self) -> bool { self.phase.is_dkg_vacant() }
|
fn is_dkg_vacant(&self) -> bool { self.dkg_phase.is_dkg_vacant() }
|
||||||
|
|
||||||
fn get_dkg_index(&self) -> DkgIndex { self.index }
|
fn get_dkg_index(&self) -> DkgIndex { self.dkg_index }
|
||||||
fn get_phase(&self) -> DkgPhase { self.phase }
|
fn get_phase(&self) -> DkgPhase { self.dkg_phase }
|
||||||
fn get_block(&self) -> Block { self.block }
|
fn get_release_block(&self) -> Block { self.release_block }
|
||||||
|
|
||||||
fn restart(&mut self) {
|
fn restart(&mut self) {
|
||||||
self.phase = Default::default();
|
self.dkg_phase = Default::default();
|
||||||
self.index = self.index.checked_add(1)
|
self.dkg_index = self.dkg_index.checked_add(1)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_phase(&mut self) {
|
fn next_phase(&mut self) {
|
||||||
self.phase.next_phase()
|
self.dkg_phase.next_phase()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_block(&mut self, block: Block) {
|
fn set_release_block(&mut self, release_block: Block) {
|
||||||
self.block = block;
|
self.release_block = release_block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use sp_runtime::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
EvmAddress, EvmBytes32, ExodusSession, RoastSession,
|
EvmAddress, EvmBytes32, ExodusContext, RoastSession,
|
||||||
MAX_MESSAGE_SIZE,
|
MAX_MESSAGE_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ pub enum GovernanceStatus {
|
|||||||
RewardManager = 4,
|
RewardManager = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
|
#[derive(Encode, Decode, Clone, Copy, PartialEq, TypeInfo, RuntimeDebug)]
|
||||||
pub enum GovernanceAction {
|
pub enum GovernanceAction {
|
||||||
SetDistributor { distributor: EvmAddress },
|
SetDistributor { distributor: EvmAddress },
|
||||||
SetWarmupPeriod { warmup_period: u128 },
|
SetWarmupPeriod { warmup_period: u128 },
|
||||||
@ -308,60 +308,59 @@ impl GovernanceAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
|
#[derive(Encode, Decode, Clone, Copy, PartialEq, TypeInfo, RuntimeDebug)]
|
||||||
pub struct ExodusRequest<NetworkId, Balance> {
|
pub struct ExodusRequest<Balance> {
|
||||||
pub r#type: ExodusRequestType<NetworkId, Balance>,
|
pub r#type: ExodusRequestType<Balance>,
|
||||||
pub next_roast_session: RoastSession,
|
pub next_roast_session: RoastSession,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
|
#[derive(Encode, Decode, Clone, Copy, PartialEq, TypeInfo, RuntimeDebug)]
|
||||||
pub enum ExodusRequestType<NetworkId, Balance> {
|
pub enum ExodusRequestType<Balance> {
|
||||||
EvmRotation {
|
EvmRotation { public_key: EvmBytes32, parity: u8 },
|
||||||
exodus_session: ExodusSession,
|
|
||||||
public_key: EvmBytes32,
|
|
||||||
parity: u8,
|
|
||||||
},
|
|
||||||
UtxoRotation,
|
UtxoRotation,
|
||||||
EvmBridgeOut {
|
EvmBridgeOut { amount: Balance, bounty: Perbill, receiver: EvmAddress },
|
||||||
exodus_session: ExodusSession,
|
EvmGovernance { target: EvmAddress, action: GovernanceAction },
|
||||||
network_id: NetworkId,
|
UtxoBridgeOut,
|
||||||
amount: Balance,
|
|
||||||
bounty: Perbill,
|
|
||||||
receiver: EvmAddress,
|
|
||||||
},
|
|
||||||
EvmGovernance {
|
|
||||||
exodus_session: ExodusSession,
|
|
||||||
network_id: NetworkId,
|
|
||||||
target: EvmAddress,
|
|
||||||
action: GovernanceAction,
|
|
||||||
},
|
|
||||||
UtxoBridgeOut { network_id: NetworkId },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NetworkId, Balance> ExodusRequestType<NetworkId, Balance>
|
impl<Balance> ExodusRequestType<Balance>
|
||||||
where
|
where
|
||||||
NetworkId: UniqueSaturatedInto<u64> + Copy,
|
|
||||||
Balance: UniqueSaturatedInto<u128> + Copy,
|
Balance: UniqueSaturatedInto<u128> + Copy,
|
||||||
{
|
{
|
||||||
pub fn get_message<'a>(
|
pub fn get_message<'a, NetworkId>(
|
||||||
&self,
|
&self,
|
||||||
message_buffer: &'a mut [u8; MAX_MESSAGE_SIZE as usize],
|
message_buffer: &'a mut [u8; MAX_MESSAGE_SIZE as usize],
|
||||||
) -> Option<&'a [u8]> {
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
|
) -> Option<&'a [u8]>
|
||||||
|
where
|
||||||
|
NetworkId: UniqueSaturatedInto<u64> + Copy + Default,
|
||||||
|
{
|
||||||
match &self {
|
match &self {
|
||||||
ExodusRequestType::EvmRotation { exodus_session, public_key, parity } => {
|
ExodusRequestType::EvmRotation { public_key, parity } => {
|
||||||
|
let mut buffer = [0u8; 32];
|
||||||
|
buffer[0] = *parity;
|
||||||
|
|
||||||
|
let chain_id_u64: u64 = exodus_context.network_id
|
||||||
|
.unique_saturated_into();
|
||||||
|
|
||||||
|
buffer[1..9].copy_from_slice(&chain_id_u64.to_be_bytes());
|
||||||
|
|
||||||
|
let packed_metadata = EvmBytes32::from(buffer);
|
||||||
|
|
||||||
abi_encode_evm_message!(
|
abi_encode_evm_message!(
|
||||||
message_buffer,
|
message_buffer,
|
||||||
"rotate(uint256,bytes32,uint8)",
|
"rotate(uint256,bytes32,uint256)",
|
||||||
[exodus_session, public_key, parity]
|
[&exodus_context.session, public_key, &packed_metadata]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
ExodusRequestType::EvmGovernance { exodus_session, network_id, target, action } => {
|
ExodusRequestType::EvmGovernance { target, action } => {
|
||||||
let mut action_buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
let mut action_buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
||||||
let action_payload = action.get_message(&mut action_buffer)?;
|
let action_payload = action.get_message(&mut action_buffer)?;
|
||||||
|
|
||||||
let mut metadata_buffer = [0u8; 32];
|
let mut metadata_buffer = [0u8; 32];
|
||||||
|
let chain_id_u64: u64 = exodus_context.network_id
|
||||||
|
.unique_saturated_into();
|
||||||
|
|
||||||
let chain_id_u64: u64 = (*network_id).unique_saturated_into();
|
|
||||||
metadata_buffer[0..8].copy_from_slice(&chain_id_u64.to_be_bytes());
|
metadata_buffer[0..8].copy_from_slice(&chain_id_u64.to_be_bytes());
|
||||||
metadata_buffer[8..28].copy_from_slice(target.as_ref());
|
metadata_buffer[8..28].copy_from_slice(target.as_ref());
|
||||||
|
|
||||||
@ -370,14 +369,16 @@ where
|
|||||||
abi_encode_evm_message!(
|
abi_encode_evm_message!(
|
||||||
message_buffer,
|
message_buffer,
|
||||||
"govern(uint256,uint256,bytes)",
|
"govern(uint256,uint256,bytes)",
|
||||||
[exodus_session, &packed_metadata, action_payload]
|
[&exodus_context.session, &packed_metadata, action_payload]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
ExodusRequestType::EvmBridgeOut { exodus_session, network_id, amount, bounty, receiver } => {
|
ExodusRequestType::EvmBridgeOut { amount, bounty, receiver } => {
|
||||||
let mut buffer = [0u8; 32];
|
let mut buffer = [0u8; 32];
|
||||||
buffer[0..20].copy_from_slice(receiver.as_ref());
|
buffer[0..20].copy_from_slice(receiver.as_ref());
|
||||||
|
|
||||||
let chain_id_u64: u64 = (*network_id).unique_saturated_into();
|
let chain_id_u64: u64 = exodus_context.network_id
|
||||||
|
.unique_saturated_into();
|
||||||
|
|
||||||
buffer[20..28].copy_from_slice(&chain_id_u64.to_be_bytes());
|
buffer[20..28].copy_from_slice(&chain_id_u64.to_be_bytes());
|
||||||
|
|
||||||
let scaled_bounty = multiply_by_rational_with_rounding(
|
let scaled_bounty = multiply_by_rational_with_rounding(
|
||||||
@ -400,7 +401,7 @@ where
|
|||||||
abi_encode_evm_message!(
|
abi_encode_evm_message!(
|
||||||
message_buffer,
|
message_buffer,
|
||||||
"recall(uint256,uint256,uint256)",
|
"recall(uint256,uint256,uint256)",
|
||||||
[exodus_session, &amount_u256, &packed_metadata]
|
[&exodus_context.session, &amount_u256, &packed_metadata]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => None
|
_ => None
|
||||||
@ -408,41 +409,31 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NetworkId, Balance> ExodusRequest<NetworkId, Balance>
|
impl<Balance> ExodusRequest<Balance>
|
||||||
where
|
where
|
||||||
NetworkId: UniqueSaturatedInto<u64> + Copy,
|
|
||||||
Balance: UniqueSaturatedInto<u128> + Copy,
|
Balance: UniqueSaturatedInto<u128> + Copy,
|
||||||
{
|
{
|
||||||
pub fn get_message<'a>(
|
pub fn get_message<'a, NetworkId>(
|
||||||
&self,
|
&self,
|
||||||
message_buffer: &'a mut [u8; MAX_MESSAGE_SIZE as usize],
|
message_buffer: &'a mut [u8; MAX_MESSAGE_SIZE as usize],
|
||||||
) -> Option<&'a [u8]> {
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
self.r#type.get_message(message_buffer)
|
) -> Option<&'a [u8]>
|
||||||
|
where
|
||||||
|
NetworkId: UniqueSaturatedInto<u64> + Copy + Default,
|
||||||
|
{
|
||||||
|
self.r#type.get_message(message_buffer, exodus_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evm_rotation(
|
pub fn evm_rotation(public_key: EvmBytes32, parity: u8) -> Self {
|
||||||
exodus_session: ExodusSession,
|
|
||||||
public_key: EvmBytes32,
|
|
||||||
parity: u8,
|
|
||||||
) -> Self {
|
|
||||||
let rotation = ExodusRequestType::EvmRotation {
|
let rotation = ExodusRequestType::EvmRotation {
|
||||||
exodus_session,
|
|
||||||
public_key,
|
public_key,
|
||||||
parity,
|
parity,
|
||||||
};
|
};
|
||||||
Self::default_request_for(rotation)
|
Self::default_request_for(rotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evm_bridge_out(
|
pub fn evm_bridge_out(amount: Balance, bounty: Perbill, receiver: EvmAddress) -> Self {
|
||||||
exodus_session: ExodusSession,
|
|
||||||
network_id: NetworkId,
|
|
||||||
amount: Balance,
|
|
||||||
bounty: Perbill,
|
|
||||||
receiver: EvmAddress,
|
|
||||||
) -> Self {
|
|
||||||
let evm_bridge_out = ExodusRequestType::EvmBridgeOut {
|
let evm_bridge_out = ExodusRequestType::EvmBridgeOut {
|
||||||
exodus_session,
|
|
||||||
network_id,
|
|
||||||
amount,
|
amount,
|
||||||
bounty,
|
bounty,
|
||||||
receiver,
|
receiver,
|
||||||
@ -450,15 +441,8 @@ where
|
|||||||
Self::default_request_for(evm_bridge_out)
|
Self::default_request_for(evm_bridge_out)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evm_governance(
|
pub fn evm_governance(target: EvmAddress, action: GovernanceAction) -> Self {
|
||||||
exodus_session: ExodusSession,
|
|
||||||
network_id: NetworkId,
|
|
||||||
target: EvmAddress,
|
|
||||||
action: GovernanceAction,
|
|
||||||
) -> Self {
|
|
||||||
let evm_governance = ExodusRequestType::EvmGovernance {
|
let evm_governance = ExodusRequestType::EvmGovernance {
|
||||||
exodus_session,
|
|
||||||
network_id,
|
|
||||||
target,
|
target,
|
||||||
action,
|
action,
|
||||||
};
|
};
|
||||||
@ -472,10 +456,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_request_for(
|
fn default_request_for(request_type: ExodusRequestType<Balance>) -> Self {
|
||||||
request_type: ExodusRequestType<NetworkId, Balance>,
|
Self {
|
||||||
) -> Self {
|
r#type: request_type,
|
||||||
Self { r#type: request_type, next_roast_session: Default::default() }
|
next_roast_session: Default::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,43 +473,49 @@ mod tests {
|
|||||||
fn test_rotation_message_valid() {
|
fn test_rotation_message_valid() {
|
||||||
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
||||||
let public_key = EvmBytes32::repeat_byte(0x11);
|
let public_key = EvmBytes32::repeat_byte(0x11);
|
||||||
let session = 69u64;
|
let session = 69;
|
||||||
|
let network_id = 420;
|
||||||
|
|
||||||
let rotation_request = ExodusRequest::<u64, u128>::evm_rotation(
|
let context = ExodusContext::new(network_id, session);
|
||||||
session,
|
|
||||||
|
let rotation_request = ExodusRequest::<u128>::evm_rotation(
|
||||||
public_key.clone(),
|
public_key.clone(),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
let calldata = rotation_request.get_message(&mut buffer).unwrap();
|
let calldata = rotation_request.get_message(&mut buffer, context).unwrap();
|
||||||
assert_eq!(calldata.len(), 100);
|
assert_eq!(calldata.len(), 100);
|
||||||
|
|
||||||
let expected_hash = keccak_256("rotate(uint256,bytes32,uint8)".as_bytes());
|
let expected_hash = keccak_256("rotate(uint256,bytes32,uint256)".as_bytes());
|
||||||
|
|
||||||
assert_eq!(calldata[0..4], expected_hash[0..4]);
|
assert_eq!(calldata[0..4], expected_hash[0..4]);
|
||||||
assert_eq!(calldata[35], 0x45);
|
assert_eq!(calldata[35], 0x45);
|
||||||
assert_eq!(&calldata[4..35], &[0u8; 31]);
|
assert_eq!(&calldata[4..35], &[0u8; 31]);
|
||||||
assert_eq!(&calldata[36..68], public_key.as_ref());
|
assert_eq!(&calldata[36..68], public_key.as_ref());
|
||||||
assert_eq!(calldata[99], 1);
|
|
||||||
assert_eq!(&calldata[68..99], &[0u8; 31]);
|
assert_eq!(calldata[68], 1);
|
||||||
|
assert_eq!(&calldata[69..75], &[0u8; 6]);
|
||||||
|
assert_eq!(calldata[75], 0x01);
|
||||||
|
assert_eq!(calldata[76], 0xA4);
|
||||||
|
assert_eq!(&calldata[77..100], &[0u8; 23]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bridge_out_message_valid() {
|
fn test_bridge_out_message_valid() {
|
||||||
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
||||||
let receiver = EvmAddress::repeat_byte(0xAA);
|
let receiver = EvmAddress::repeat_byte(0xAA);
|
||||||
let network_id = 420u64;
|
let network_id = 420;
|
||||||
let session = 69u64;
|
let session = 69;
|
||||||
|
|
||||||
let bridge_request = ExodusRequest::<u64, u128>::evm_bridge_out(
|
let context = ExodusContext::new(network_id, session);
|
||||||
session,
|
|
||||||
network_id,
|
let bridge_request = ExodusRequest::<u128>::evm_bridge_out(
|
||||||
1_000_000u128,
|
1_000_000u128,
|
||||||
sp_runtime::Perbill::from_percent(1),
|
sp_runtime::Perbill::from_percent(1),
|
||||||
receiver.clone()
|
receiver.clone()
|
||||||
);
|
);
|
||||||
|
|
||||||
let calldata = bridge_request.get_message(&mut buffer).unwrap();
|
let calldata = bridge_request.get_message(&mut buffer, context).unwrap();
|
||||||
assert_eq!(calldata.len(), 100);
|
assert_eq!(calldata.len(), 100);
|
||||||
|
|
||||||
let expected_hash = keccak_256("recall(uint256,uint256,uint256)".as_bytes());
|
let expected_hash = keccak_256("recall(uint256,uint256,uint256)".as_bytes());
|
||||||
@ -549,8 +540,8 @@ mod tests {
|
|||||||
fn test_governance_message_valid() {
|
fn test_governance_message_valid() {
|
||||||
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
|
||||||
let target = EvmAddress::repeat_byte(0xAA);
|
let target = EvmAddress::repeat_byte(0xAA);
|
||||||
let network_id = 420u64;
|
let network_id = 420;
|
||||||
let session = 69u64;
|
let session = 69;
|
||||||
|
|
||||||
let actions = vec![
|
let actions = vec![
|
||||||
GovernanceAction::SetDistributor { distributor: EvmAddress::repeat_byte(0x11) },
|
GovernanceAction::SetDistributor { distributor: EvmAddress::repeat_byte(0x11) },
|
||||||
@ -592,16 +583,16 @@ mod tests {
|
|||||||
|
|
||||||
for (index, action) in actions.into_iter().enumerate() {
|
for (index, action) in actions.into_iter().enumerate() {
|
||||||
let action_clone = action.clone();
|
let action_clone = action.clone();
|
||||||
|
let current_session = session + (index as u64);
|
||||||
|
let context = ExodusContext::new(network_id, current_session);
|
||||||
|
|
||||||
let governance_request = ExodusRequest::<u64, u128>::evm_governance(
|
let governance_request = ExodusRequest::<u128>::evm_governance(
|
||||||
session,
|
|
||||||
network_id,
|
|
||||||
target,
|
target,
|
||||||
action,
|
action,
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = governance_request
|
let message = governance_request
|
||||||
.get_message(&mut buffer)
|
.get_message(&mut buffer, context)
|
||||||
.get_or_insert(&[])
|
.get_or_insert(&[])
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
@ -610,7 +601,7 @@ mod tests {
|
|||||||
let expected_master_hash = keccak_256("govern(uint256,uint256,bytes)".as_bytes());
|
let expected_master_hash = keccak_256("govern(uint256,uint256,bytes)".as_bytes());
|
||||||
assert_eq!(message[0..4], expected_master_hash[0..4]);
|
assert_eq!(message[0..4], expected_master_hash[0..4]);
|
||||||
|
|
||||||
assert_eq!(message[35], 69);
|
assert_eq!(message[35], current_session as u8);
|
||||||
assert_eq!(&message[4..35], &[0u8; 31]);
|
assert_eq!(&message[4..35], &[0u8; 31]);
|
||||||
|
|
||||||
assert_eq!(message[43], 0xA4);
|
assert_eq!(message[43], 0xA4);
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use sp_runtime::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{DkgPackage, ExodusPackage, ExodusOk, PackageContext};
|
use super::{DkgPackage, ExodusPackage, ExodusOk, PackageContext};
|
||||||
use crate::{AuthIndex, DkgIndex, ExodusSession, ExodusHash, ExodusError};
|
use crate::{AuthIndex, ExodusContext, DkgIndex, ExodusHash, ExodusError};
|
||||||
|
|
||||||
fn create_storage_key(prefix: &[u8], index: &[u8], network: &[u8]) -> Vec<u8> {
|
fn create_storage_key(prefix: &[u8], index: &[u8], network: &[u8]) -> Vec<u8> {
|
||||||
let mut key = crate::DB_STORAGE_PREFIX.to_vec();
|
let mut key = crate::DB_STORAGE_PREFIX.to_vec();
|
||||||
@ -59,10 +59,10 @@ pub struct ExodusShare;
|
|||||||
#[derive(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
|
#[derive(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
|
||||||
pub struct ExodusExile;
|
pub struct ExodusExile;
|
||||||
|
|
||||||
type ExodusNonces<BlockNumber> = BTreeMap<ExodusSession, PersistentData<BlockNumber, ExodusNonce>>;
|
type ExodusNonces<NetworkId, BlockNumber> = BTreeMap<ExodusContext<NetworkId>, PersistentData<BlockNumber, ExodusNonce>>;
|
||||||
type ExodusGroups<BlockNumber> = BTreeMap<ExodusSession, PersistentData<BlockNumber, ExodusGroup>>;
|
type ExodusGroups<NetworkId, BlockNumber> = BTreeMap<ExodusContext<NetworkId>, PersistentData<BlockNumber, ExodusGroup>>;
|
||||||
type ExodusShares<BlockNumber> = BTreeMap<ExodusSession, PersistentData<BlockNumber, ExodusShare>>;
|
type ExodusShares<NetworkId, BlockNumber> = BTreeMap<ExodusContext<NetworkId>, PersistentData<BlockNumber, ExodusShare>>;
|
||||||
type ExodusExiles<BlockNumber> = BTreeMap<ExodusSession, PersistentData<BlockNumber, ExodusExile>>;
|
type ExodusExiles<NetworkId, BlockNumber> = BTreeMap<ExodusContext<NetworkId>, PersistentData<BlockNumber, ExodusExile>>;
|
||||||
|
|
||||||
pub struct ExodusStorageWrapper<ExodusInnerType> {
|
pub struct ExodusStorageWrapper<ExodusInnerType> {
|
||||||
pub inner: ExodusInnerType,
|
pub inner: ExodusInnerType,
|
||||||
@ -113,34 +113,37 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_local_storage(&self) -> ExodusRecords<B> {
|
pub fn read_local_storage<NI>(&self) -> ExodusRecords<NI, B>
|
||||||
|
where
|
||||||
|
NI: Default + Encode + Decode + AtLeast32BitUnsigned,
|
||||||
|
{
|
||||||
let encoded_index = self.authority_index.encode();
|
let encoded_index = self.authority_index.encode();
|
||||||
let encoded_network = self.network_curve.encode();
|
let encoded_network = self.network_curve.encode();
|
||||||
|
|
||||||
let nonces_key = create_storage_key(crate::EXODUS_PREFIX_NONCES, &encoded_index, &encoded_network);
|
let nonces_key = create_storage_key(crate::EXODUS_PREFIX_NONCES, &encoded_index, &encoded_network);
|
||||||
let exodus_nonces = StorageValueRef::persistent(&nonces_key)
|
let exodus_nonces = StorageValueRef::persistent(&nonces_key)
|
||||||
.get::<ExodusNonces<B>>()
|
.get::<ExodusNonces<NI, B>>()
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()
|
.flatten()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let shares_key = create_storage_key(crate::EXODUS_PREFIX_SHARES, &encoded_index, &encoded_network);
|
let shares_key = create_storage_key(crate::EXODUS_PREFIX_SHARES, &encoded_index, &encoded_network);
|
||||||
let exodus_shares = StorageValueRef::persistent(&shares_key)
|
let exodus_shares = StorageValueRef::persistent(&shares_key)
|
||||||
.get::<ExodusShares<B>>()
|
.get::<ExodusShares<NI, B>>()
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()
|
.flatten()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let groups_key = create_storage_key(crate::EXODUS_PREFIX_BLENDS, &encoded_index, &encoded_network);
|
let groups_key = create_storage_key(crate::EXODUS_PREFIX_BLENDS, &encoded_index, &encoded_network);
|
||||||
let exodus_groups = StorageValueRef::persistent(&groups_key)
|
let exodus_groups = StorageValueRef::persistent(&groups_key)
|
||||||
.get::<ExodusGroups<B>>()
|
.get::<ExodusGroups<NI, B>>()
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()
|
.flatten()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let exiles_key = create_storage_key(crate::EXODUS_PREFIX_EXILES, &encoded_index, &encoded_network);
|
let exiles_key = create_storage_key(crate::EXODUS_PREFIX_EXILES, &encoded_index, &encoded_network);
|
||||||
let exodus_exiles = StorageValueRef::persistent(&exiles_key)
|
let exodus_exiles = StorageValueRef::persistent(&exiles_key)
|
||||||
.get::<ExodusExiles<B>>()
|
.get::<ExodusExiles<NI, B>>()
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()
|
.flatten()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
@ -153,11 +156,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_signed_call_with_context<T, A, F1, F2, F3>(
|
pub fn prepare_signed_call_with_context<T, A, F1, F2, F3, NI>(
|
||||||
&self,
|
&self,
|
||||||
authority_key: &A,
|
authority_key: &A,
|
||||||
current_dkg_index: DkgIndex,
|
current_dkg_index: DkgIndex,
|
||||||
exodus_records: &mut ExodusRecords<B>,
|
exodus_records: &mut ExodusRecords<NI, B>,
|
||||||
make_data: F1,
|
make_data: F1,
|
||||||
submit_call: F2,
|
submit_call: F2,
|
||||||
insert_data: F3,
|
insert_data: F3,
|
||||||
@ -165,11 +168,13 @@ where
|
|||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
A: RuntimeAppPublic,
|
A: RuntimeAppPublic,
|
||||||
F1: FnOnce(PackageContext<NC>) -> Result<ExodusPackage<NC, T>, ExodusError>,
|
NI: Default + Encode + Decode + AtLeast32BitUnsigned,
|
||||||
F2: FnOnce(ExodusPackage<NC, T>, A::Signature) -> Result<(), ExodusError>,
|
F1: FnOnce(PackageContext<NC, B>) -> Result<ExodusPackage<NC, NI, B, T>, ExodusError>,
|
||||||
F3: FnOnce(&mut ExodusRecords<B>, B),
|
F2: FnOnce(ExodusPackage<NC, NI, B, T>, A::Signature) -> Result<(), ExodusError>,
|
||||||
|
F3: FnOnce(&mut ExodusRecords<NI, B>, B),
|
||||||
{
|
{
|
||||||
let context = PackageContext::default()
|
let context = PackageContext::default()
|
||||||
|
.with_block_number(self.current_block)
|
||||||
.with_authority_index(self.authority_index)
|
.with_authority_index(self.authority_index)
|
||||||
.with_network_curve(self.network_curve)
|
.with_network_curve(self.network_curve)
|
||||||
.with_dkg_index(current_dkg_index);
|
.with_dkg_index(current_dkg_index);
|
||||||
@ -205,7 +210,10 @@ where
|
|||||||
StorageValueRef::persistent(&exiles_key).clear();
|
StorageValueRef::persistent(&exiles_key).clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_write_local_storage(&self, records: &ExodusRecords<B>) {
|
pub fn try_write_local_storage<NI: Default>(&self, records: &ExodusRecords<NI, B>)
|
||||||
|
where
|
||||||
|
NI: Encode + Decode + AtLeast32BitUnsigned,
|
||||||
|
{
|
||||||
let encoded_index = self.authority_index.encode();
|
let encoded_index = self.authority_index.encode();
|
||||||
let encoded_network = self.network_curve.encode();
|
let encoded_network = self.network_curve.encode();
|
||||||
|
|
||||||
@ -231,99 +239,104 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExodusRecords<BlockNumber>
|
pub struct ExodusRecords<NetworkId, BlockNumber>
|
||||||
where
|
where
|
||||||
|
NetworkId: Default,
|
||||||
BlockNumber: AtLeast32BitUnsigned,
|
BlockNumber: AtLeast32BitUnsigned,
|
||||||
{
|
{
|
||||||
exodus_nonces: ExodusStorageWrapper<ExodusNonces<BlockNumber>>,
|
exodus_nonces: ExodusStorageWrapper<ExodusNonces<NetworkId, BlockNumber>>,
|
||||||
exodus_shares: ExodusStorageWrapper<ExodusShares<BlockNumber>>,
|
exodus_shares: ExodusStorageWrapper<ExodusShares<NetworkId, BlockNumber>>,
|
||||||
exodus_groups: ExodusStorageWrapper<ExodusGroups<BlockNumber>>,
|
exodus_groups: ExodusStorageWrapper<ExodusGroups<NetworkId, BlockNumber>>,
|
||||||
exodus_exiles: ExodusStorageWrapper<ExodusExiles<BlockNumber>>,
|
exodus_exiles: ExodusStorageWrapper<ExodusExiles<NetworkId, BlockNumber>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BlockNumber> ExodusRecords<BlockNumber>
|
impl<NetworkId, BlockNumber> ExodusRecords<NetworkId, BlockNumber>
|
||||||
where
|
where
|
||||||
BlockNumber: AtLeast32BitUnsigned + Default,
|
BlockNumber: AtLeast32BitUnsigned + Default,
|
||||||
|
NetworkId: AtLeast32BitUnsigned + Default,
|
||||||
{
|
{
|
||||||
pub fn get_secret_nonce(&self, exodus_session: &ExodusSession) -> Option<&[u8]> {
|
pub fn get_secret_nonce(
|
||||||
|
&self,
|
||||||
|
exodus_context: &ExodusContext<NetworkId>,
|
||||||
|
) -> Option<&[u8]> {
|
||||||
self.exodus_nonces.inner
|
self.exodus_nonces.inner
|
||||||
.get(exodus_session)
|
.get(exodus_context)
|
||||||
.map(|v| v.data.0.as_slice())
|
.map(|v| v.data.0.as_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_group_record(
|
pub fn get_group_record(
|
||||||
&self,
|
&self,
|
||||||
exodus_session: &ExodusSession,
|
exodus_context: &ExodusContext<NetworkId>,
|
||||||
) -> Option<ExodusGroup> {
|
) -> Option<ExodusGroup> {
|
||||||
self.exodus_groups.inner
|
self.exodus_groups.inner
|
||||||
.get(exodus_session)
|
.get(exodus_context)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|storage| storage.data)
|
.map(|storage| storage.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_exodus_session_banned(
|
pub fn is_exodus_session_banned(
|
||||||
&self,
|
&self,
|
||||||
exodus_session: &ExodusSession,
|
exodus_context: &ExodusContext<NetworkId>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.exodus_exiles.inner.contains_key(exodus_session)
|
self.exodus_exiles.inner.contains_key(exodus_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_group_registered(
|
pub fn is_group_registered(
|
||||||
&self,
|
&self,
|
||||||
exodus_session: &ExodusSession,
|
exodus_context: &ExodusContext<NetworkId>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.exodus_groups.inner.contains_key(exodus_session)
|
self.exodus_groups.inner.contains_key(exodus_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_waiting_period_for_nonce(
|
pub fn is_waiting_period_for_nonce(
|
||||||
&self,
|
&self,
|
||||||
exodus_session: &ExodusSession,
|
exodus_context: &ExodusContext<NetworkId>,
|
||||||
current_block: &BlockNumber
|
current_block: &BlockNumber,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.exodus_nonces.inner
|
self.exodus_nonces.inner
|
||||||
.get(exodus_session)
|
.get(exodus_context)
|
||||||
.map(|data| data.release_block.gt(current_block))
|
.map(|data| data.release_block.gt(current_block))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_waiting_period_for_share(
|
pub fn is_waiting_period_for_share(
|
||||||
&self,
|
&self,
|
||||||
exodus_session: &ExodusSession,
|
exodus_context: &ExodusContext<NetworkId>,
|
||||||
current_block: &BlockNumber,
|
current_block: &BlockNumber,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.exodus_shares.inner
|
self.exodus_shares.inner
|
||||||
.get(exodus_session)
|
.get(exodus_context)
|
||||||
.map(|data| data.release_block.gt(¤t_block))
|
.map(|data| data.release_block.gt(¤t_block))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_waiting_period_for_group(
|
pub fn is_waiting_period_for_group(
|
||||||
&self,
|
&self,
|
||||||
exodus_session: &ExodusSession,
|
exodus_context: &ExodusContext<NetworkId>,
|
||||||
current_block: &BlockNumber,
|
current_block: &BlockNumber,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.exodus_groups.inner
|
self.exodus_groups.inner
|
||||||
.get(exodus_session)
|
.get(exodus_context)
|
||||||
.map(|data| data.release_block.gt(¤t_block))
|
.map(|data| data.release_block.gt(¤t_block))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exclude_exodus_session(
|
pub fn exclude_exodus_session(
|
||||||
&mut self,
|
&mut self,
|
||||||
exodus_session: ExodusSession,
|
exodus_context: ExodusContext<NetworkId>
|
||||||
) {
|
) {
|
||||||
let exodus_exile = PersistentData {
|
let exodus_exile = PersistentData {
|
||||||
data: ExodusExile,
|
data: ExodusExile,
|
||||||
release_block: Default::default(),
|
release_block: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.exodus_exiles.inner.insert(exodus_session, exodus_exile);
|
|
||||||
self.exodus_exiles.data_changed = true;
|
self.exodus_exiles.data_changed = true;
|
||||||
|
self.exodus_exiles.inner.insert(exodus_context, exodus_exile);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_exodus_nonce(
|
pub fn insert_exodus_nonce(
|
||||||
&mut self,
|
&mut self,
|
||||||
exodus_session: ExodusSession,
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
next_release_block: BlockNumber,
|
next_release_block: BlockNumber,
|
||||||
nonce_commitment: Vec<u8>,
|
nonce_commitment: Vec<u8>,
|
||||||
) {
|
) {
|
||||||
@ -332,13 +345,13 @@ where
|
|||||||
release_block: next_release_block,
|
release_block: next_release_block,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.exodus_nonces.inner.insert(exodus_session, exodus_nonce);
|
|
||||||
self.exodus_nonces.data_changed = true;
|
self.exodus_nonces.data_changed = true;
|
||||||
|
self.exodus_nonces.inner.insert(exodus_context, exodus_nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_exodus_share(
|
pub fn insert_exodus_share(
|
||||||
&mut self,
|
&mut self,
|
||||||
exodus_session: ExodusSession,
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
next_release_block: BlockNumber,
|
next_release_block: BlockNumber,
|
||||||
) {
|
) {
|
||||||
let exodus_share = PersistentData {
|
let exodus_share = PersistentData {
|
||||||
@ -346,13 +359,13 @@ where
|
|||||||
release_block: next_release_block,
|
release_block: next_release_block,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.exodus_shares.inner.insert(exodus_session, exodus_share);
|
|
||||||
self.exodus_shares.data_changed = true;
|
self.exodus_shares.data_changed = true;
|
||||||
|
self.exodus_shares.inner.insert(exodus_context, exodus_share);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_exodus_group(
|
pub fn insert_exodus_group(
|
||||||
&mut self,
|
&mut self,
|
||||||
exodus_session: ExodusSession,
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
next_release_block: BlockNumber,
|
next_release_block: BlockNumber,
|
||||||
self_binding_factor: Vec<u8>,
|
self_binding_factor: Vec<u8>,
|
||||||
binding_factors_proof: Vec<ExodusHash>,
|
binding_factors_proof: Vec<ExodusHash>,
|
||||||
@ -362,8 +375,8 @@ where
|
|||||||
release_block: next_release_block,
|
release_block: next_release_block,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.exodus_groups.inner.insert(exodus_session, exodus_group);
|
|
||||||
self.exodus_groups.data_changed = true;
|
self.exodus_groups.data_changed = true;
|
||||||
|
self.exodus_groups.inner.insert(exodus_context, exodus_group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,10 +421,10 @@ where
|
|||||||
self.current_block.saturating_add(self.block_longevity)
|
self.current_block.saturating_add(self.block_longevity)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_dkg_result(
|
pub fn get_dkg_result<NI>(
|
||||||
&self,
|
&self,
|
||||||
dkg_record: DkgRecord<B>,
|
dkg_record: DkgRecord<B>,
|
||||||
) -> Result<ExodusOk<NC>, ExodusError> {
|
) -> Result<ExodusOk<NC, NI>, ExodusError> {
|
||||||
match dkg_record.prefix_slice {
|
match dkg_record.prefix_slice {
|
||||||
crate::DKG_ROUND0_PREFIX => return Ok(ExodusOk::DkgRoundRegistered(0u8, self.authority_index, self.network_curve)),
|
crate::DKG_ROUND0_PREFIX => return Ok(ExodusOk::DkgRoundRegistered(0u8, self.authority_index, self.network_curve)),
|
||||||
crate::DKG_ROUND1_PREFIX => return Ok(ExodusOk::DkgRoundRegistered(1u8, self.authority_index, self.network_curve)),
|
crate::DKG_ROUND1_PREFIX => return Ok(ExodusOk::DkgRoundRegistered(1u8, self.authority_index, self.network_curve)),
|
||||||
@ -464,10 +477,11 @@ where
|
|||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
A: RuntimeAppPublic,
|
A: RuntimeAppPublic,
|
||||||
F1: FnOnce(PackageContext<NC>) -> Result<DkgPackage<NC, T>, ExodusError>,
|
F1: FnOnce(PackageContext<NC, B>) -> Result<DkgPackage<NC, B, T>, ExodusError>,
|
||||||
F2: FnOnce(DkgPackage<NC, T>, A::Signature) -> Result<(), ExodusError>,
|
F2: FnOnce(DkgPackage<NC, B, T>, A::Signature) -> Result<(), ExodusError>,
|
||||||
{
|
{
|
||||||
let context = PackageContext::default()
|
let context = PackageContext::default()
|
||||||
|
.with_block_number(self.current_block)
|
||||||
.with_authority_index(self.authority_index)
|
.with_authority_index(self.authority_index)
|
||||||
.with_network_curve(self.network_curve)
|
.with_network_curve(self.network_curve)
|
||||||
.with_dkg_index(current_dkg_index);
|
.with_dkg_index(current_dkg_index);
|
||||||
|
|||||||
@ -6,37 +6,58 @@ use codec::{Encode, Decode};
|
|||||||
use frame_support::{BoundedVec, traits::ConstU32};
|
use frame_support::{BoundedVec, traits::ConstU32};
|
||||||
use crate::{AuthIndex, DkgIndex, ExodusSession, ExodusHash, ExodusError};
|
use crate::{AuthIndex, DkgIndex, ExodusSession, ExodusHash, ExodusError};
|
||||||
|
|
||||||
pub trait PackageMetadata<NetworkCurve>
|
pub trait PackageMetadata<NetworkCurve, BlockNumber>
|
||||||
where
|
where
|
||||||
NetworkCurve: Copy,
|
NetworkCurve: Copy,
|
||||||
|
BlockNumber: Copy,
|
||||||
{
|
{
|
||||||
fn context(&self) -> &PackageContext<NetworkCurve>;
|
fn package_context(&self) -> &PackageContext<NetworkCurve, BlockNumber>;
|
||||||
|
|
||||||
fn get_authority_index(&self) -> AuthIndex {
|
fn get_authority_index(&self) -> AuthIndex {
|
||||||
self.context().get_authority_index()
|
self.package_context().get_authority_index()
|
||||||
}
|
}
|
||||||
fn get_network_curve(&self) -> NetworkCurve {
|
fn get_network_curve(&self) -> NetworkCurve {
|
||||||
self.context().get_network_curve()
|
self.package_context().get_network_curve()
|
||||||
}
|
}
|
||||||
fn get_dkg_index(&self) -> DkgIndex {
|
fn get_dkg_index(&self) -> DkgIndex {
|
||||||
self.context().get_dkg_index()
|
self.package_context().get_dkg_index()
|
||||||
}
|
}
|
||||||
|
fn get_block_number(&self) -> BlockNumber {
|
||||||
|
self.package_context().get_block_number()
|
||||||
|
}
|
||||||
|
fn get_metadata(&self) -> (NetworkCurve, AuthIndex, DkgIndex) {
|
||||||
|
let network_curve = self.get_network_curve();
|
||||||
|
let authority_index = self.get_authority_index();
|
||||||
|
let dkg_index = self.get_dkg_index();
|
||||||
|
|
||||||
|
(network_curve, authority_index, dkg_index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ExodusMetadata<NetworkId>
|
||||||
|
where
|
||||||
|
NetworkId: Default + Copy,
|
||||||
|
{
|
||||||
|
fn get_exodus_context(&self) -> &ExodusContext<NetworkId>;
|
||||||
|
fn copy_exodus_context(&self) -> ExodusContext<NetworkId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Clone, RuntimeDebug, TypeInfo, PartialEq, Eq)]
|
#[derive(Encode, Decode, Clone, RuntimeDebug, TypeInfo, PartialEq, Eq)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub enum ExodusPackage<NetworkCurve, T>
|
pub enum ExodusPackage<NetworkCurve, NetworkId, BlockNumber, T>
|
||||||
where
|
where
|
||||||
|
NetworkId: Default,
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
NonceCommitment(ExodusNonceCommitment<NetworkCurve>),
|
NonceCommitment(ExodusNonceCommitment<NetworkCurve, NetworkId, BlockNumber>),
|
||||||
GroupCommitment(ExodusGroupCommitment<NetworkCurve>),
|
GroupCommitment(ExodusGroupCommitment<NetworkCurve, NetworkId, BlockNumber>),
|
||||||
SignatureShare(ExodusSignatureShare<NetworkCurve, T>),
|
SignatureShare(ExodusSignatureShare<NetworkCurve, NetworkId, BlockNumber, T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NetworkCurve, T> ExodusPackage<NetworkCurve, T>
|
impl<NC, NI, B, T> ExodusPackage<NC, NI, B, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
|
NI: Default,
|
||||||
{
|
{
|
||||||
pub fn bytes_len(&self) -> u32 {
|
pub fn bytes_len(&self) -> u32 {
|
||||||
let length = match self {
|
let length = match self {
|
||||||
@ -54,32 +75,24 @@ where
|
|||||||
|
|
||||||
length as u32
|
length as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_exodus_session(&self) -> ExodusSession {
|
|
||||||
match &self {
|
|
||||||
Self::SignatureShare(package) => package.session,
|
|
||||||
Self::NonceCommitment(package) => package.session,
|
|
||||||
Self::GroupCommitment(package) => package.session,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Clone, RuntimeDebug, TypeInfo, PartialEq, Eq)]
|
#[derive(Encode, Decode, Clone, RuntimeDebug, TypeInfo, PartialEq, Eq)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub enum DkgPackage<NetworkCurve, T>
|
pub enum DkgPackage<NetworkCurve, BlockNumber, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
Round0(Round0Package<NetworkCurve>),
|
Round0(Round0Package<NetworkCurve, BlockNumber>),
|
||||||
Round1(Round1Package<NetworkCurve, T>),
|
Round1(Round1Package<NetworkCurve, BlockNumber, T>),
|
||||||
Round2(Round2Package<NetworkCurve, T>),
|
Round2(Round2Package<NetworkCurve, BlockNumber, T>),
|
||||||
Round3(Round3Package<NetworkCurve, T>),
|
Round3(Round3Package<NetworkCurve, BlockNumber, T>),
|
||||||
Round4(Round4Package<NetworkCurve, T>),
|
Round4(Round4Package<NetworkCurve, BlockNumber, T>),
|
||||||
Round5(Round5Package<NetworkCurve, T>),
|
Round5(Round5Package<NetworkCurve, BlockNumber, T>),
|
||||||
Round6(Round6Package<NetworkCurve, T>),
|
Round6(Round6Package<NetworkCurve, BlockNumber, T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NetworkCurve, T> DkgPackage<NetworkCurve, T>
|
impl<NC, B, T> DkgPackage<NC, B, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
@ -102,15 +115,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(Default, RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
pub struct PackageContext<NetworkCurve> {
|
pub struct PackageContext<NetworkCurve, BlockNumber> {
|
||||||
authority_index: AuthIndex,
|
authority_index: AuthIndex,
|
||||||
network_curve: NetworkCurve,
|
network_curve: NetworkCurve,
|
||||||
|
block_number: BlockNumber,
|
||||||
dkg_index: DkgIndex,
|
dkg_index: DkgIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NetworkCurve> PackageContext<NetworkCurve>
|
impl<NetworkCurve, BlockNumber> PackageContext<NetworkCurve, BlockNumber>
|
||||||
where
|
where
|
||||||
NetworkCurve: Copy,
|
NetworkCurve: Copy,
|
||||||
|
BlockNumber: Copy,
|
||||||
{
|
{
|
||||||
pub fn get_authority_index(&self) -> AuthIndex {
|
pub fn get_authority_index(&self) -> AuthIndex {
|
||||||
self.authority_index
|
self.authority_index
|
||||||
@ -124,6 +139,10 @@ where
|
|||||||
self.dkg_index
|
self.dkg_index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_block_number(&self) -> BlockNumber {
|
||||||
|
self.block_number
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_network_curve(mut self, network_curve: NetworkCurve) -> Self {
|
pub fn with_network_curve(mut self, network_curve: NetworkCurve) -> Self {
|
||||||
self.network_curve = network_curve;
|
self.network_curve = network_curve;
|
||||||
self
|
self
|
||||||
@ -138,6 +157,11 @@ where
|
|||||||
self.dkg_index = dkg_index;
|
self.dkg_index = dkg_index;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_block_number(mut self, block_number: BlockNumber) -> Self {
|
||||||
|
self.block_number = block_number;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
@ -214,89 +238,112 @@ impl<T: crate::pallet::Config> TryFrom<BundledPackages> for JustificationsBundle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(RuntimeDebug, Default, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
|
pub struct ExodusContext<NetworkId: Default> {
|
||||||
|
pub session: ExodusSession,
|
||||||
|
pub network_id: NetworkId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<NetworkId: Default + Copy> ExodusContext<NetworkId> {
|
||||||
|
pub fn new(network_id: NetworkId, session: ExodusSession) -> Self {
|
||||||
|
Self { session, network_id }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_network_id(mut self, network_id: NetworkId) -> Self {
|
||||||
|
self.network_id = network_id;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_exodus_session(mut self, session: ExodusSession) -> Self {
|
||||||
|
self.session = session;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub struct ExodusNonceCommitment<NetworkCurve> {
|
pub struct ExodusNonceCommitment<NetworkCurve, NetworkId: Default, BlockNumber> {
|
||||||
context: PackageContext<NetworkCurve>,
|
package_context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
pub hiding_commitment: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
pub hiding_commitment: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
||||||
pub binding_commitment: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
pub binding_commitment: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
||||||
pub session: ExodusSession,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
pub struct ExodusGroupCommitment<NetworkCurve> {
|
pub struct ExodusGroupCommitment<NetworkCurve, NetworkId: Default, BlockNumber> {
|
||||||
context: PackageContext<NetworkCurve>,
|
package_context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
pub group_commitment: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
pub group_commitment: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
||||||
pub binding_factors_root: ExodusHash,
|
pub binding_factors_root: ExodusHash,
|
||||||
pub session: ExodusSession,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub struct ExodusSignatureShare<NetworkCurve, T>
|
pub struct ExodusSignatureShare<NetworkCurve, NetworkId, BlockNumber, T>
|
||||||
where
|
where
|
||||||
|
NetworkId: Default,
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
context: PackageContext<NetworkCurve>,
|
package_context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
pub binding_factors_proof: BoundedVec<ExodusHash, crate::BindingFactorsProof<T>>,
|
pub binding_factors_proof: BoundedVec<ExodusHash, crate::BindingFactorsProof<T>>,
|
||||||
pub signature_share: BoundedVec<u8, ConstU32<{ crate::SCALAR_MAX_BYTES }>>,
|
pub signature_share: BoundedVec<u8, ConstU32<{ crate::SCALAR_MAX_BYTES }>>,
|
||||||
pub self_binding_factor: BoundedVec<u8, ConstU32<{ crate::SCALAR_MAX_BYTES }>>,
|
pub self_binding_factor: BoundedVec<u8, ConstU32<{ crate::SCALAR_MAX_BYTES }>>,
|
||||||
pub session: ExodusSession,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
pub struct Round0Package<NetworkCurve> {
|
pub struct Round0Package<NetworkCurve, BlockNumber> {
|
||||||
context: PackageContext<NetworkCurve>,
|
context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
pub package_hash: ExodusHash,
|
pub package_hash: ExodusHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub struct Round1Package<NetworkCurve, T>
|
pub struct Round1Package<NetworkCurve, BlockNumber, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
context: PackageContext<NetworkCurve>,
|
context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
pub package: BoundedVec<u8, crate::Round1MaxBytes<T>>,
|
pub package: BoundedVec<u8, crate::Round1MaxBytes<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub struct Round2Package<NetworkCurve, T>
|
pub struct Round2Package<NetworkCurve, BlockNumber, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
context: PackageContext<NetworkCurve>,
|
context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
pub bundle: EncryptionBundledPackages<T>,
|
pub bundle: EncryptionBundledPackages<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub struct Round3Package<NetworkCurve, T>
|
pub struct Round3Package<NetworkCurve, BlockNumber, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
context: PackageContext<NetworkCurve>,
|
|
||||||
pub indices: BoundedVec<u8, crate::AccusedIndicesMaxBytes<T>>,
|
pub indices: BoundedVec<u8, crate::AccusedIndicesMaxBytes<T>>,
|
||||||
|
context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub struct Round4Package<NetworkCurve, T>
|
pub struct Round4Package<NetworkCurve, BlockNumber, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
context: PackageContext<NetworkCurve>,
|
context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
pub bundle: JustificationsBundledPackages<T>,
|
pub bundle: JustificationsBundledPackages<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub struct Round5Package<NetworkCurve, T>
|
pub struct Round5Package<NetworkCurve, BlockNumber, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
context: PackageContext<NetworkCurve>,
|
context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
pub key_members: BoundedVec<u8, crate::MaxAuthoritiesBitmaskSize<T>>,
|
pub key_members: BoundedVec<u8, crate::MaxAuthoritiesBitmaskSize<T>>,
|
||||||
pub verifying_key: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
pub verifying_key: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
||||||
pub merkle_root: ExodusHash,
|
pub merkle_root: ExodusHash,
|
||||||
@ -304,22 +351,22 @@ where
|
|||||||
|
|
||||||
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
#[derive(RuntimeDebug, Clone, Eq, PartialEq, Encode, Decode, TypeInfo)]
|
||||||
#[scale_info(skip_type_params(T))]
|
#[scale_info(skip_type_params(T))]
|
||||||
pub struct Round6Package<NetworkCurve, T>
|
pub struct Round6Package<NetworkCurve, BlockNumber, T>
|
||||||
where
|
where
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
context: PackageContext<NetworkCurve>,
|
context: PackageContext<NetworkCurve, BlockNumber>,
|
||||||
pub verifying_share: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
pub verifying_share: BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>,
|
||||||
pub merkle_proof: BoundedVec<ExodusHash, crate::MerkleProofMaxSize<T>>,
|
pub merkle_proof: BoundedVec<ExodusHash, crate::MerkleProofMaxSize<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NetworkCurve> PackageContext<NetworkCurve> {
|
impl<NetworkCurve, BlockNumber> PackageContext<NetworkCurve, BlockNumber> {
|
||||||
pub fn with_exodus_nonce_commitment(
|
pub fn with_exodus_nonce_commitment<NetworkId: Default>(
|
||||||
self,
|
self,
|
||||||
session: ExodusSession,
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
hiding_commitment_vec: Vec<u8>,
|
hiding_commitment_vec: Vec<u8>,
|
||||||
binding_commitment_vec: Vec<u8>,
|
binding_commitment_vec: Vec<u8>,
|
||||||
) -> Result<ExodusNonceCommitment<NetworkCurve>, ExodusError> {
|
) -> Result<ExodusNonceCommitment<NetworkCurve, NetworkId, BlockNumber>, ExodusError> {
|
||||||
let hiding_commitment =
|
let hiding_commitment =
|
||||||
BoundedVec::<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>::try_from(hiding_commitment_vec)
|
BoundedVec::<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>::try_from(hiding_commitment_vec)
|
||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
@ -328,34 +375,39 @@ impl<NetworkCurve> PackageContext<NetworkCurve> {
|
|||||||
BoundedVec::<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>::try_from(binding_commitment_vec)
|
BoundedVec::<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>::try_from(binding_commitment_vec)
|
||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
|
|
||||||
Ok(ExodusNonceCommitment { context: self, hiding_commitment, binding_commitment, session })
|
Ok(ExodusNonceCommitment {
|
||||||
|
package_context: self,
|
||||||
|
exodus_context,
|
||||||
|
hiding_commitment,
|
||||||
|
binding_commitment,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_exodus_group_commitment(
|
pub fn with_exodus_group_commitment<NetworkId: Default>(
|
||||||
self,
|
self,
|
||||||
session: ExodusSession,
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
commitment_vec: Vec<u8>,
|
commitment_vec: Vec<u8>,
|
||||||
binding_factors_root: ExodusHash,
|
binding_factors_root: ExodusHash,
|
||||||
) -> Result<ExodusGroupCommitment<NetworkCurve>, ExodusError> {
|
) -> Result<ExodusGroupCommitment<NetworkCurve, NetworkId, BlockNumber>, ExodusError> {
|
||||||
let group_commitment =
|
let group_commitment =
|
||||||
BoundedVec::<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>::try_from(commitment_vec)
|
BoundedVec::<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>::try_from(commitment_vec)
|
||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
|
|
||||||
Ok(ExodusGroupCommitment {
|
Ok(ExodusGroupCommitment {
|
||||||
context: self,
|
package_context: self,
|
||||||
|
exodus_context,
|
||||||
group_commitment,
|
group_commitment,
|
||||||
binding_factors_root,
|
binding_factors_root,
|
||||||
session,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_exodus_signature_share<T: crate::pallet::Config>(
|
pub fn with_exodus_signature_share<NetworkId: Default, T: crate::pallet::Config>(
|
||||||
self,
|
self,
|
||||||
session: ExodusSession,
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
signature_share_vec: Vec<u8>,
|
signature_share_vec: Vec<u8>,
|
||||||
binding_factors_proof_vec: Vec<ExodusHash>,
|
binding_factors_proof_vec: Vec<ExodusHash>,
|
||||||
self_binding_factor_vec: Vec<u8>,
|
self_binding_factor_vec: Vec<u8>,
|
||||||
) -> Result<ExodusSignatureShare<NetworkCurve, T>, ExodusError> {
|
) -> Result<ExodusSignatureShare<NetworkCurve, NetworkId, BlockNumber, T>, ExodusError> {
|
||||||
let signature_share =
|
let signature_share =
|
||||||
BoundedVec::<u8, ConstU32<{ crate::SCALAR_MAX_BYTES }>>::try_from(signature_share_vec)
|
BoundedVec::<u8, ConstU32<{ crate::SCALAR_MAX_BYTES }>>::try_from(signature_share_vec)
|
||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
@ -369,25 +421,25 @@ impl<NetworkCurve> PackageContext<NetworkCurve> {
|
|||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
|
|
||||||
Ok(ExodusSignatureShare {
|
Ok(ExodusSignatureShare {
|
||||||
context: self,
|
package_context: self,
|
||||||
|
exodus_context,
|
||||||
binding_factors_proof,
|
binding_factors_proof,
|
||||||
self_binding_factor,
|
self_binding_factor,
|
||||||
signature_share,
|
signature_share,
|
||||||
session,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_dkg_round0(
|
pub fn with_dkg_round0(
|
||||||
self,
|
self,
|
||||||
package_hash: ExodusHash,
|
package_hash: ExodusHash,
|
||||||
) -> Round0Package<NetworkCurve> {
|
) -> Round0Package<NetworkCurve, BlockNumber> {
|
||||||
Round0Package { context: self, package_hash }
|
Round0Package { context: self, package_hash }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_dkg_round1<T: crate::pallet::Config>(
|
pub fn with_dkg_round1<T: crate::pallet::Config>(
|
||||||
self,
|
self,
|
||||||
package_vec: Vec<u8>,
|
package_vec: Vec<u8>,
|
||||||
) -> Result<Round1Package<NetworkCurve, T>, ExodusError> {
|
) -> Result<Round1Package<NetworkCurve, BlockNumber, T>, ExodusError> {
|
||||||
let package =
|
let package =
|
||||||
BoundedVec::<u8, crate::Round1MaxBytes<T>>::try_from(package_vec)
|
BoundedVec::<u8, crate::Round1MaxBytes<T>>::try_from(package_vec)
|
||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
@ -398,7 +450,7 @@ impl<NetworkCurve> PackageContext<NetworkCurve> {
|
|||||||
pub fn with_dkg_round2<T: crate::pallet::Config>(
|
pub fn with_dkg_round2<T: crate::pallet::Config>(
|
||||||
self,
|
self,
|
||||||
bundle_raw: BundledPackages,
|
bundle_raw: BundledPackages,
|
||||||
) -> Result<Round2Package<NetworkCurve, T>, ExodusError> {
|
) -> Result<Round2Package<NetworkCurve, BlockNumber, T>, ExodusError> {
|
||||||
let bundle: EncryptionBundledPackages<T> = bundle_raw.try_into()?;
|
let bundle: EncryptionBundledPackages<T> = bundle_raw.try_into()?;
|
||||||
Ok(Round2Package { context: self, bundle })
|
Ok(Round2Package { context: self, bundle })
|
||||||
}
|
}
|
||||||
@ -406,7 +458,7 @@ impl<NetworkCurve> PackageContext<NetworkCurve> {
|
|||||||
pub fn with_dkg_round3<T: crate::pallet::Config>(
|
pub fn with_dkg_round3<T: crate::pallet::Config>(
|
||||||
self,
|
self,
|
||||||
indices_vec: Vec<u8>
|
indices_vec: Vec<u8>
|
||||||
) -> Result<Round3Package<NetworkCurve, T>, ExodusError> {
|
) -> Result<Round3Package<NetworkCurve, BlockNumber, T>, ExodusError> {
|
||||||
let indices =
|
let indices =
|
||||||
BoundedVec::<u8, crate::AccusedIndicesMaxBytes<T>>::try_from(indices_vec)
|
BoundedVec::<u8, crate::AccusedIndicesMaxBytes<T>>::try_from(indices_vec)
|
||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
@ -417,7 +469,7 @@ impl<NetworkCurve> PackageContext<NetworkCurve> {
|
|||||||
pub fn with_dkg_round4<T: crate::pallet::Config>(
|
pub fn with_dkg_round4<T: crate::pallet::Config>(
|
||||||
self,
|
self,
|
||||||
bundle_raw: BundledPackages,
|
bundle_raw: BundledPackages,
|
||||||
) -> Result<Round4Package<NetworkCurve, T>, ExodusError> {
|
) -> Result<Round4Package<NetworkCurve, BlockNumber, T>, ExodusError> {
|
||||||
let bundle: JustificationsBundledPackages<T> = bundle_raw.try_into()?;
|
let bundle: JustificationsBundledPackages<T> = bundle_raw.try_into()?;
|
||||||
Ok(Round4Package { context: self, bundle })
|
Ok(Round4Package { context: self, bundle })
|
||||||
}
|
}
|
||||||
@ -427,7 +479,7 @@ impl<NetworkCurve> PackageContext<NetworkCurve> {
|
|||||||
verifying_key_vec: Vec<u8>,
|
verifying_key_vec: Vec<u8>,
|
||||||
key_members_vec: Vec<u8>,
|
key_members_vec: Vec<u8>,
|
||||||
merkle_root: ExodusHash,
|
merkle_root: ExodusHash,
|
||||||
) -> Result<Round5Package<NetworkCurve, T>, ExodusError> {
|
) -> Result<Round5Package<NetworkCurve, BlockNumber, T>, ExodusError> {
|
||||||
let key_members = BoundedVec::<u8, crate::MaxAuthoritiesBitmaskSize<T>>::try_from(key_members_vec)
|
let key_members = BoundedVec::<u8, crate::MaxAuthoritiesBitmaskSize<T>>::try_from(key_members_vec)
|
||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
|
|
||||||
@ -442,7 +494,7 @@ impl<NetworkCurve> PackageContext<NetworkCurve> {
|
|||||||
self,
|
self,
|
||||||
verifying_share_vec: Vec<u8>,
|
verifying_share_vec: Vec<u8>,
|
||||||
merkle_proof_vec: Vec<ExodusHash>,
|
merkle_proof_vec: Vec<ExodusHash>,
|
||||||
) -> Result<Round6Package<NetworkCurve, T>, ExodusError> {
|
) -> Result<Round6Package<NetworkCurve, BlockNumber, T>, ExodusError> {
|
||||||
let verifying_share =
|
let verifying_share =
|
||||||
BoundedVec::<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>::try_from(verifying_share_vec)
|
BoundedVec::<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>::try_from(verifying_share_vec)
|
||||||
.map_err(|_| ExodusError::DeserializationError)?;
|
.map_err(|_| ExodusError::DeserializationError)?;
|
||||||
@ -455,26 +507,51 @@ impl<NetworkCurve> PackageContext<NetworkCurve> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NC, T> PackageMetadata<NC> for ExodusPackage<NC, T>
|
impl<NC, NI, B, T> ExodusMetadata<NI> for ExodusPackage<NC, NI, B, T>
|
||||||
where
|
where
|
||||||
NC: Copy,
|
NI: Default + Copy,
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
fn context(&self) -> &PackageContext<NC> {
|
fn copy_exodus_context(&self) -> ExodusContext<NI> {
|
||||||
match self {
|
match self {
|
||||||
Self::NonceCommitment(package) => &package.context,
|
Self::NonceCommitment(package) => (*package).exodus_context,
|
||||||
Self::GroupCommitment(package) => &package.context,
|
Self::GroupCommitment(package) => (*package).exodus_context,
|
||||||
Self::SignatureShare(package) => &package.context,
|
Self::SignatureShare(package) => (*package).exodus_context,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_exodus_context(&self) -> &ExodusContext<NI> {
|
||||||
|
match self {
|
||||||
|
Self::NonceCommitment(package) => &package.exodus_context,
|
||||||
|
Self::GroupCommitment(package) => &package.exodus_context,
|
||||||
|
Self::SignatureShare(package) => &package.exodus_context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NC, T> PackageMetadata<NC> for DkgPackage<NC, T>
|
impl<NC, NI, B, T> PackageMetadata<NC, B> for ExodusPackage<NC, NI, B, T>
|
||||||
where
|
where
|
||||||
|
NI: Default,
|
||||||
NC: Copy,
|
NC: Copy,
|
||||||
|
B: Copy,
|
||||||
T: crate::pallet::Config,
|
T: crate::pallet::Config,
|
||||||
{
|
{
|
||||||
fn context(&self) -> &PackageContext<NC> {
|
fn package_context(&self) -> &PackageContext<NC, B> {
|
||||||
|
match self {
|
||||||
|
Self::NonceCommitment(package) => &package.package_context,
|
||||||
|
Self::GroupCommitment(package) => &package.package_context,
|
||||||
|
Self::SignatureShare(package) => &package.package_context,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<NC, B, T> PackageMetadata<NC, B> for DkgPackage<NC, B, T>
|
||||||
|
where
|
||||||
|
NC: Copy,
|
||||||
|
B: Copy,
|
||||||
|
T: crate::pallet::Config,
|
||||||
|
{
|
||||||
|
fn package_context(&self) -> &PackageContext<NC, B> {
|
||||||
match self {
|
match self {
|
||||||
Self::Round0(package) => &package.context,
|
Self::Round0(package) => &package.context,
|
||||||
Self::Round1(package) => &package.context,
|
Self::Round1(package) => &package.context,
|
||||||
|
|||||||
@ -1,28 +1,32 @@
|
|||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
use frame_support::{BoundedVec, traits::ConstU32};
|
use frame_support::{BoundedVec, traits::ConstU32};
|
||||||
use sp_runtime::{RuntimeDebug, traits::UniqueSaturatedInto};
|
use sp_runtime::{
|
||||||
|
RuntimeDebug,
|
||||||
|
traits::{AtLeast32BitUnsigned, UniqueSaturatedInto},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::ExodusContext;
|
||||||
|
use super::ExodusRequestType;
|
||||||
|
|
||||||
type ExodusNonceT = BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>;
|
type ExodusNonceT = BoundedVec<u8, ConstU32<{ crate::ELEMENT_MAX_BYTES }>>;
|
||||||
type ExodusSignatureT = BoundedVec<u8, ConstU32<{ crate::SCALAR_MAX_BYTES }>>;
|
type ExodusSignatureT = BoundedVec<u8, ConstU32<{ crate::SCALAR_MAX_BYTES }>>;
|
||||||
type Type<NetworkId, Balance> = super::ExodusRequestType<NetworkId, Balance>;
|
|
||||||
|
|
||||||
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
|
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
|
||||||
pub struct ExodusSignedMessage<NetworkId: Default, Balance: Default> {
|
pub struct ExodusSignedMessage<Balance: Default> {
|
||||||
pub nonce: ExodusNonceT,
|
pub nonce: ExodusNonceT,
|
||||||
pub signature: ExodusSignatureT,
|
pub signature: ExodusSignatureT,
|
||||||
pub r#type: Type<NetworkId, Balance>,
|
pub r#type: ExodusRequestType<Balance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NetworkId, Balance> ExodusSignedMessage<NetworkId, Balance>
|
impl<Balance> ExodusSignedMessage<Balance>
|
||||||
where
|
where
|
||||||
NetworkId: UniqueSaturatedInto<u64> + Copy + Default,
|
|
||||||
Balance: UniqueSaturatedInto<u128> + Copy + Default,
|
Balance: UniqueSaturatedInto<u128> + Copy + Default,
|
||||||
{
|
{
|
||||||
pub fn new<E, S>(
|
pub fn new<E, S>(
|
||||||
nonce_iter: E,
|
nonce_iter: E,
|
||||||
signature_iter: S,
|
signature_iter: S,
|
||||||
r#type: Type<NetworkId, Balance>
|
r#type: ExodusRequestType<Balance>,
|
||||||
) -> Option<Self>
|
) -> Option<Self>
|
||||||
where
|
where
|
||||||
E: Iterator<Item = u8> + ExactSizeIterator,
|
E: Iterator<Item = u8> + ExactSizeIterator,
|
||||||
@ -37,10 +41,11 @@ where
|
|||||||
Some(Self { nonce, signature, r#type })
|
Some(Self { nonce, signature, r#type })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_message<'a>(
|
pub fn get_message<'a, NetworkId: Default + Copy + AtLeast32BitUnsigned>(
|
||||||
&self,
|
&self,
|
||||||
message_buffer: &'a mut [u8; crate::MAX_MESSAGE_SIZE as usize],
|
message_buffer: &'a mut [u8; crate::MAX_MESSAGE_SIZE as usize],
|
||||||
|
exodus_context: ExodusContext<NetworkId>,
|
||||||
) -> Option<&'a [u8]> {
|
) -> Option<&'a [u8]> {
|
||||||
self.r#type.get_message(message_buffer)
|
self.r#type.get_message(message_buffer, exodus_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,19 @@
|
|||||||
|
use sp_runtime::traits::UniqueSaturatedInto;
|
||||||
use crate::{AuthIndex, ExodusSession, DkgIndex, RoastSession};
|
use crate::{AuthIndex, ExodusSession, DkgIndex, RoastSession};
|
||||||
|
|
||||||
pub enum ExodusOk<NetworkCurve> {
|
pub enum ExodusOk<NetworkCurve, NetworkId> {
|
||||||
|
ExodusRequestsFinished(AuthIndex, NetworkCurve, u32, u32),
|
||||||
ExodusEmptyRequests(AuthIndex, NetworkCurve),
|
ExodusEmptyRequests(AuthIndex, NetworkCurve),
|
||||||
ExodusWaitingState(AuthIndex, NetworkCurve),
|
ExodusWaitingState(AuthIndex, NetworkCurve),
|
||||||
ExodusNonceCommitted(ExodusSession, RoastSession, AuthIndex, NetworkCurve),
|
ExodusNonceCommitted(ExodusSession, NetworkId, RoastSession, AuthIndex, NetworkCurve),
|
||||||
ExodusGroupCommitted(ExodusSession, RoastSession, AuthIndex, NetworkCurve),
|
ExodusGroupCommitted(ExodusSession, NetworkId, RoastSession, AuthIndex, NetworkCurve),
|
||||||
ExodusSignedPartially(ExodusSession, RoastSession, AuthIndex, NetworkCurve),
|
ExodusSignedPartially(ExodusSession, NetworkId, RoastSession, AuthIndex, NetworkCurve),
|
||||||
ExodusVerifyingShareMissed(AuthIndex, DkgIndex, NetworkCurve),
|
ExodusVerifyingShareMissed(AuthIndex, DkgIndex, NetworkCurve),
|
||||||
|
|
||||||
DkgNotPartOfRound(u8, AuthIndex, NetworkCurve),
|
DkgNotPartOfRound(u8, AuthIndex, NetworkCurve),
|
||||||
DkgRoundRegistered(u8, AuthIndex, NetworkCurve),
|
DkgRoundRegistered(u8, AuthIndex, NetworkCurve),
|
||||||
DkgPreviousPurged(AuthIndex, NetworkCurve),
|
DkgPreviousPurged(AuthIndex, NetworkCurve, u32),
|
||||||
|
DkgLocalStoragePurged(AuthIndex, NetworkCurve, DkgIndex),
|
||||||
DkgRoundsCleared(AuthIndex, NetworkCurve),
|
DkgRoundsCleared(AuthIndex, NetworkCurve),
|
||||||
DkgRoundAlreadyPassed(u8, AuthIndex, NetworkCurve),
|
DkgRoundAlreadyPassed(u8, AuthIndex, NetworkCurve),
|
||||||
DkgRoundWaitingPeriod(u8, AuthIndex, NetworkCurve),
|
DkgRoundWaitingPeriod(u8, AuthIndex, NetworkCurve),
|
||||||
@ -18,27 +21,41 @@ pub enum ExodusOk<NetworkCurve> {
|
|||||||
DkgRoundMaxSignersNarrowed(u8, AuthIndex, AuthIndex, AuthIndex, NetworkCurve),
|
DkgRoundMaxSignersNarrowed(u8, AuthIndex, AuthIndex, AuthIndex, NetworkCurve),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NetworkCurve> core::fmt::Display for ExodusOk<NetworkCurve>
|
impl<NetworkCurve, NetworkId> core::fmt::Debug for ExodusOk<NetworkCurve, NetworkId>
|
||||||
where
|
where
|
||||||
NetworkCurve: core::fmt::Display
|
NetworkCurve: core::fmt::Display,
|
||||||
|
NetworkId: UniqueSaturatedInto<u64> + Copy,
|
||||||
{
|
{
|
||||||
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
|
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ExodusOk::ExodusEmptyRequests(auth_index, curve) => write!(fmt, "No EXODUS requests found by authority #{auth_index} for curve {curve}."),
|
ExodusOk::ExodusRequestsFinished(auth_index, curve, success_count, failed_count) => {
|
||||||
ExodusOk::ExodusWaitingState(auth_index, curve) => write!(fmt, "Waiting for EXODUS requests to be processed by authority #{auth_index} for curve {curve}."),
|
write!(fmt, "EXODUS requests processing round completed by authority #{auth_index} for curve {curve}: {success_count} tasks succeeded, {failed_count} tasks failed.")
|
||||||
ExodusOk::ExodusNonceCommitted(exodus, roast, auth_index, curve) => write!(fmt, "Nonce committed for EXODUS {exodus:?} on ROAST session {roast:?} by authority #{auth_index} for curve {curve}."),
|
}
|
||||||
ExodusOk::ExodusGroupCommitted(exodus, roast, auth_index, curve) => write!(fmt, "Aggregated nonce and binding factor proof committed for EXODUS {exodus:?} on ROAST session {roast:?} by authority #{auth_index} for curve {curve}."),
|
ExodusOk::ExodusEmptyRequests(auth_index, curve) => write!(fmt, "No EXODUS requests found for authority #{auth_index} on curve {curve}."),
|
||||||
ExodusOk::ExodusSignedPartially(exodus, roast, auth_index, curve) => write!(fmt, "Partial signature created for EXODUS {exodus:?} on ROAST session {roast:?} by authority #{auth_index} for curve {curve}."),
|
ExodusOk::ExodusWaitingState(auth_index, curve) => write!(fmt, "Waiting for EXODUS requests to be processed by authority #{auth_index} on curve {curve}."),
|
||||||
ExodusOk::ExodusVerifyingShareMissed(auth_index, dkg_index, curve) => write!(fmt, "EXODUS Round no verifying share for authority #{auth_index} based on DKG session #{dkg_index} for curve {curve}."),
|
ExodusOk::ExodusNonceCommitted(exodus, network_id, roast, auth_index, curve) => {
|
||||||
|
let network_id_u64: u64 = (*network_id).unique_saturated_into();
|
||||||
|
write!(fmt, "Nonce committed for EXODUS {exodus:?} on ROAST session {roast:?} by authority #{auth_index} for curve {curve} on network #{network_id_u64}.")
|
||||||
|
},
|
||||||
|
ExodusOk::ExodusGroupCommitted(exodus, network_id, roast, auth_index, curve) => {
|
||||||
|
let network_id_u64: u64 = (*network_id).unique_saturated_into();
|
||||||
|
write!(fmt, "Aggregated nonce and binding factor proof committed for EXODUS {exodus:?} on ROAST session {roast:?} by authority #{auth_index} for curve {curve} on network #{network_id_u64}.")
|
||||||
|
},
|
||||||
|
ExodusOk::ExodusSignedPartially(exodus, network_id, roast, auth_index, curve) => {
|
||||||
|
let network_id_u64: u64 = (*network_id).unique_saturated_into();
|
||||||
|
write!(fmt, "Partial signature created for EXODUS {exodus:?} on ROAST session {roast:?} by authority #{auth_index} for curve {curve} on network #{network_id_u64}.")
|
||||||
|
},
|
||||||
|
ExodusOk::ExodusVerifyingShareMissed(auth_index, dkg_index, curve) => write!(fmt, "No verifying share found for authority #{auth_index} in EXODUS round based on DKG session #{dkg_index} for curve {curve}."),
|
||||||
|
|
||||||
ExodusOk::DkgNotPartOfRound(round, auth_index, curve) => write!(fmt, "DKG authority #{auth_index} for network curve {curve} is not part of Round{round}."),
|
ExodusOk::DkgNotPartOfRound(round, auth_index, curve) => write!(fmt, "DKG authority #{auth_index} is not part of Round {round} for network curve {curve}."),
|
||||||
ExodusOk::DkgRoundRegistered(round, auth_index, curve) => write!(fmt, "DKG Round{round} registered by authority #{auth_index} for network curve {curve}."),
|
ExodusOk::DkgRoundRegistered(round, auth_index, curve) => write!(fmt, "DKG Round {round} registered by authority #{auth_index} for network curve {curve}."),
|
||||||
ExodusOk::DkgPreviousPurged(auth_index, curve) => write!(fmt, "Storage prepared for new DKG session by authority #{auth_index} for network curve {curve}."),
|
ExodusOk::DkgPreviousPurged(auth_index, curve, removed_count) => write!(fmt, "Storage prepared for a new DKG session by authority #{auth_index} for network curve {curve}. {removed_count} entries removed."),
|
||||||
|
ExodusOk::DkgLocalStoragePurged(auth_index, curve, dkg_index) => write!(fmt, "Storage for DKG session #{dkg_index} cleared by authority #{auth_index} for network curve {curve}."),
|
||||||
ExodusOk::DkgRoundsCleared(auth_index, curve) => write!(fmt, "DKG Rounds cleared from storage by authority #{auth_index} for network curve {curve}."),
|
ExodusOk::DkgRoundsCleared(auth_index, curve) => write!(fmt, "DKG Rounds cleared from storage by authority #{auth_index} for network curve {curve}."),
|
||||||
ExodusOk::DkgRoundAlreadyPassed(round, auth_index, curve) => write!(fmt, "DKG Round{round} already done by authority #{auth_index} for network curve {curve}."),
|
ExodusOk::DkgRoundAlreadyPassed(round, auth_index, curve) => write!(fmt, "DKG Round {round} already completed by authority #{auth_index} for network curve {curve}."),
|
||||||
ExodusOk::DkgRoundWaitingPeriod(round, auth_index, curve) => write!(fmt, "DKG Round{round} waiting to be applied by authority #{auth_index} for network curve {curve}."),
|
ExodusOk::DkgRoundWaitingPeriod(round, auth_index, curve) => write!(fmt, "DKG Round {round} is waiting to be applied by authority #{auth_index} for network curve {curve}."),
|
||||||
ExodusOk::DkgRoundNothingStored(round, auth_index, curve) => write!(fmt, "DKG nothing stored from Round{round} by authority #{auth_index} for network curve {curve}."),
|
ExodusOk::DkgRoundNothingStored(round, auth_index, curve) => write!(fmt, "No data stored for DKG Round {round} by authority #{auth_index} for network curve {curve}."),
|
||||||
ExodusOk::DkgRoundMaxSignersNarrowed(round, auth_index, prev_max, curr_max, curve) => write!(fmt, "DKG Round{round} narrowed max_signers from {prev_max} to {curr_max} by {auth_index} for network curve {curve}."),
|
ExodusOk::DkgRoundMaxSignersNarrowed(round, auth_index, prev_max, curr_max, curve) => write!(fmt, "DKG Round {round} narrowed max_signers from {prev_max} to {curr_max} by authority #{auth_index} for network curve {curve}."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-networks"
|
name = "ghost-networks"
|
||||||
version = "0.2.10"
|
version = "0.2.11"
|
||||||
description = "Registry and lifecycle management for external network metadata and cryptographic profiles."
|
description = "Registry and lifecycle management for external network metadata and cryptographic profiles."
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
|||||||
@ -197,17 +197,21 @@ pub mod module {
|
|||||||
StorageValue<_, BoundedVec<T::NetworkId, T::MaxNetworks>, ValueQuery>;
|
StorageValue<_, BoundedVec<T::NetworkId, T::MaxNetworks>, ValueQuery>;
|
||||||
|
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
#[pallet::getter(fn network_curves)]
|
#[pallet::getter(fn network_types)]
|
||||||
pub type NetworkCurves<T: Config> = StorageMap<
|
pub type NetworkTypes<T: Config> = StorageMap<
|
||||||
_,
|
_,
|
||||||
Twox64Concat, NetworkCurve,
|
Twox64Concat, NetworkCurve,
|
||||||
BoundedBTreeMap<NetworkType, u32, T::MaxNetworks>,
|
BoundedBTreeMap<
|
||||||
|
NetworkType,
|
||||||
|
BoundedVec<T::NetworkId, T::MaxNetworks>,
|
||||||
|
T::MaxNetworks,
|
||||||
|
>,
|
||||||
ValueQuery,
|
ValueQuery,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
#[pallet::getter(fn network_curves_vec)]
|
#[pallet::getter(fn network_curves)]
|
||||||
pub type NetworkCurvesVec<T: Config> =
|
pub type NetworkCurves<T: Config> =
|
||||||
StorageValue<_, BoundedVec<NetworkCurve, T::MaxNetworks>, ValueQuery>;
|
StorageValue<_, BoundedVec<NetworkCurve, T::MaxNetworks>, ValueQuery>;
|
||||||
|
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
@ -429,24 +433,26 @@ impl<T: Config> Pallet<T> {
|
|||||||
modified_indexes.try_push(chain_id.clone())
|
modified_indexes.try_push(chain_id.clone())
|
||||||
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
|
|
||||||
let mut modified_curves_map = NetworkCurves::<T>::get(network_curve);
|
let mut modified_types = NetworkTypes::<T>::get(network_curve);
|
||||||
if let Some(counter) = modified_curves_map.get_mut(&network_type) {
|
if let Some(chain_ids) = modified_types.get_mut(&network_type) {
|
||||||
*counter = counter.saturating_add(1);
|
chain_ids.try_push(chain_id).map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
} else {
|
} else {
|
||||||
modified_curves_map.try_insert(network_type, 1u32)
|
let mut new_ids_vec = BoundedVec::<T::NetworkId, T::MaxNetworks>::default();
|
||||||
|
new_ids_vec.try_push(chain_id).map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
|
modified_types.try_insert(network_type, new_ids_vec)
|
||||||
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut modified_curves_vec = NetworkCurvesVec::<T>::get();
|
let mut modified_curves = NetworkCurves::<T>::get();
|
||||||
if !modified_curves_vec.contains(&network_curve) {
|
if !modified_curves.contains(&network_curve) {
|
||||||
modified_curves_vec.try_push(network_curve)
|
modified_curves.try_push(network_curve)
|
||||||
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Networks::<T>::insert(&chain_id, network);
|
Networks::<T>::insert(&chain_id, network);
|
||||||
NetworkIndexes::<T>::put(modified_indexes);
|
NetworkIndexes::<T>::put(modified_indexes);
|
||||||
NetworkCurves::<T>::insert(network_curve, modified_curves_map);
|
NetworkTypes::<T>::insert(network_curve, modified_types);
|
||||||
NetworkCurvesVec::<T>::put(modified_curves_vec);
|
NetworkCurves::<T>::put(modified_curves);
|
||||||
|
|
||||||
Self::deposit_event(Event::<T>::NetworkRegistered { chain_id });
|
Self::deposit_event(Event::<T>::NetworkRegistered { chain_id });
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -460,38 +466,38 @@ impl<T: Config> Pallet<T> {
|
|||||||
let network_curve = network.curve;
|
let network_curve = network.curve;
|
||||||
let network_type = network.r#type;
|
let network_type = network.r#type;
|
||||||
|
|
||||||
let mut modified_curves_map = NetworkCurves::<T>::get(network_curve);
|
let mut modified_types = NetworkTypes::<T>::get(network_curve);
|
||||||
|
|
||||||
let counter = modified_curves_map
|
let chain_ids = modified_types
|
||||||
.get_mut(&network_type)
|
.get_mut(&network_type)
|
||||||
.ok_or(Error::<T>::NetworkTypeDoesNotExist)?;
|
.ok_or(Error::<T>::NetworkTypeDoesNotExist)?;
|
||||||
|
|
||||||
*counter = counter.saturating_sub(1);
|
chain_ids.retain(|id| id != &chain_id);
|
||||||
|
|
||||||
let mut should_remove_curve_from_vec = false;
|
let mut should_remove_curve = false;
|
||||||
if *counter == 0 {
|
if chain_ids.is_empty() {
|
||||||
modified_curves_map.remove(&network_type);
|
modified_types.remove(&network_type);
|
||||||
if modified_curves_map.is_empty() {
|
if modified_types.is_empty() {
|
||||||
should_remove_curve_from_vec = true;
|
should_remove_curve = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut modified_indexes = NetworkIndexes::<T>::get();
|
let mut modified_indexes = NetworkIndexes::<T>::get();
|
||||||
modified_indexes.retain(|id| id != &chain_id);
|
modified_indexes.retain(|id| id != &chain_id);
|
||||||
|
|
||||||
let mut modified_curves_vec = NetworkCurvesVec::<T>::get();
|
let mut modified_curves = NetworkCurves::<T>::get();
|
||||||
if should_remove_curve_from_vec {
|
if should_remove_curve {
|
||||||
modified_curves_vec.retain(|curve| curve != &network_curve);
|
modified_curves.retain(|curve| curve != &network_curve);
|
||||||
}
|
}
|
||||||
|
|
||||||
Networks::<T>::remove(&chain_id);
|
Networks::<T>::remove(&chain_id);
|
||||||
NetworkIndexes::<T>::put(modified_indexes);
|
NetworkIndexes::<T>::put(modified_indexes);
|
||||||
NetworkCurvesVec::<T>::put(modified_curves_vec);
|
NetworkCurves::<T>::put(modified_curves);
|
||||||
|
|
||||||
if modified_curves_map.is_empty() {
|
if modified_types.is_empty() {
|
||||||
NetworkCurves::<T>::remove(network_curve);
|
NetworkTypes::<T>::remove(network_curve);
|
||||||
} else {
|
} else {
|
||||||
NetworkCurves::<T>::insert(network_curve, modified_curves_map);
|
NetworkTypes::<T>::insert(network_curve, modified_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::deposit_event(Event::<T>::NetworkRemoved { chain_id });
|
Self::deposit_event(Event::<T>::NetworkRemoved { chain_id });
|
||||||
@ -625,15 +631,46 @@ impl<T: Config> Pallet<T> {
|
|||||||
chain_id: T::NetworkId,
|
chain_id: T::NetworkId,
|
||||||
network_type: NetworkType,
|
network_type: NetworkType,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
|
let mut network = Networks::<T>::get(&chain_id)
|
||||||
let network = maybe_network.as_mut().ok_or(Error::<T>::NetworkDoesNotExist)?;
|
.ok_or(Error::<T>::NetworkDoesNotExist)?;
|
||||||
|
|
||||||
|
let network_curve = network.curve;
|
||||||
|
let prev_type = network.r#type;
|
||||||
|
|
||||||
|
if prev_type == network_type {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut modified_types = NetworkTypes::<T>::get(network_curve);
|
||||||
|
let prev_chain_ids = modified_types
|
||||||
|
.get_mut(&prev_type)
|
||||||
|
.ok_or(Error::<T>::NetworkTypeDoesNotExist)?;
|
||||||
|
|
||||||
|
prev_chain_ids.retain(|id| id != &chain_id);
|
||||||
|
|
||||||
|
if prev_chain_ids.is_empty() {
|
||||||
|
modified_types.remove(&prev_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(chain_ids) = modified_types.get_mut(&network_type) {
|
||||||
|
chain_ids.try_push(chain_id).map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
|
} else {
|
||||||
|
let mut new_ids_vec = BoundedVec::<T::NetworkId, T::MaxNetworks>::default();
|
||||||
|
new_ids_vec.try_push(chain_id).map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
|
modified_types.try_insert(network_type, new_ids_vec)
|
||||||
|
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
|
}
|
||||||
|
|
||||||
network.r#type = network_type;
|
network.r#type = network_type;
|
||||||
Ok(())
|
|
||||||
})?;
|
Networks::<T>::insert(&chain_id, network);
|
||||||
|
NetworkTypes::<T>::insert(network_curve, modified_types);
|
||||||
|
|
||||||
Self::deposit_event(Event::<T>::NetworkTypeUpdated {
|
Self::deposit_event(Event::<T>::NetworkTypeUpdated {
|
||||||
chain_id,
|
chain_id,
|
||||||
network_type,
|
network_type,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,50 +689,53 @@ impl<T: Config> Pallet<T> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut modified_prev_map = NetworkCurves::<T>::get(prev_curve);
|
let mut modified_prev_types = NetworkTypes::<T>::get(prev_curve);
|
||||||
let counter = modified_prev_map
|
let prev_chain_ids = modified_prev_types
|
||||||
.get_mut(&network_type)
|
.get_mut(&network_type)
|
||||||
.ok_or(Error::<T>::NetworkTypeDoesNotExist)?;
|
.ok_or(Error::<T>::NetworkTypeDoesNotExist)?;
|
||||||
|
|
||||||
*counter = counter.saturating_sub(1);
|
prev_chain_ids.retain(|id| id != &chain_id);
|
||||||
|
|
||||||
let mut should_remove_prev_from_vec = false;
|
let mut should_remove_prev_curve = false;
|
||||||
if *counter == 0 {
|
if prev_chain_ids.is_empty() {
|
||||||
modified_prev_map.remove(&network_type);
|
modified_prev_types.remove(&network_type);
|
||||||
if modified_prev_map.is_empty() {
|
if modified_prev_types.is_empty() {
|
||||||
should_remove_prev_from_vec = true;
|
should_remove_prev_curve = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut modified_curr_map = NetworkCurves::<T>::get(network_curve);
|
let mut modified_curr_types = NetworkTypes::<T>::get(network_curve);
|
||||||
if let Some(counter) = modified_curr_map.get_mut(&network_type) {
|
if let Some(chain_ids) = modified_curr_types.get_mut(&network_type) {
|
||||||
*counter = counter.saturating_add(1);
|
chain_ids.try_push(chain_id)
|
||||||
|
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
} else {
|
} else {
|
||||||
modified_curr_map.try_insert(network_type, 1u32)
|
let mut new_ids_vec = BoundedVec::<T::NetworkId, T::MaxNetworks>::default();
|
||||||
|
new_ids_vec.try_push(chain_id).map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
|
modified_curr_types.try_insert(network_type, new_ids_vec)
|
||||||
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut modified_curves_vec = NetworkCurvesVec::<T>::get();
|
let mut modified_curves = NetworkCurves::<T>::get();
|
||||||
|
|
||||||
if should_remove_prev_from_vec {
|
if should_remove_prev_curve {
|
||||||
modified_curves_vec.retain(|curve| curve != &prev_curve);
|
modified_curves.retain(|curve| curve != &prev_curve);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !modified_curves_vec.contains(&network_curve) {
|
if !modified_curves.contains(&network_curve) {
|
||||||
modified_curves_vec.try_push(network_curve)
|
modified_curves.try_push(network_curve)
|
||||||
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
.map_err(|_| Error::<T>::TooManyNetworks)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
network.curve = network_curve;
|
network.curve = network_curve;
|
||||||
|
|
||||||
Networks::<T>::insert(&chain_id, network);
|
Networks::<T>::insert(&chain_id, network);
|
||||||
NetworkCurves::<T>::insert(network_curve, modified_curr_map);
|
NetworkTypes::<T>::insert(network_curve, modified_curr_types);
|
||||||
NetworkCurvesVec::<T>::put(modified_curves_vec);
|
NetworkCurves::<T>::put(modified_curves);
|
||||||
|
|
||||||
if modified_prev_map.is_empty() {
|
if modified_prev_types.is_empty() {
|
||||||
NetworkCurves::<T>::remove(prev_curve);
|
NetworkTypes::<T>::remove(prev_curve);
|
||||||
} else {
|
} else {
|
||||||
NetworkCurves::<T>::insert(prev_curve, modified_prev_map);
|
NetworkTypes::<T>::insert(prev_curve, modified_prev_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::deposit_event(Event::<T>::NetworkCurveUpdated {
|
Self::deposit_event(Event::<T>::NetworkCurveUpdated {
|
||||||
@ -761,6 +801,7 @@ impl<T: Config> NetworkDataBasicHandler for Pallet<T> {
|
|||||||
type NetworkId = T::NetworkId;
|
type NetworkId = T::NetworkId;
|
||||||
type NetworkType = NetworkType;
|
type NetworkType = NetworkType;
|
||||||
type NetworkCurve = NetworkCurve;
|
type NetworkCurve = NetworkCurve;
|
||||||
|
type MaxNetworks = T::MaxNetworks;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
|
impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
|
||||||
@ -775,7 +816,7 @@ impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn curve_exists(curve: &Self::NetworkCurve) -> bool {
|
fn curve_exists(curve: &Self::NetworkCurve) -> bool {
|
||||||
NetworkCurves::<T>::contains_key(curve)
|
NetworkTypes::<T>::contains_key(curve)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(n: &Self::NetworkId) -> Option<NetworkData> {
|
fn get(n: &Self::NetworkId) -> Option<NetworkData> {
|
||||||
@ -804,15 +845,17 @@ impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn iter_curves() -> impl Iterator<Item = Self::NetworkCurve> {
|
fn iter_curves() -> impl Iterator<Item = Self::NetworkCurve> {
|
||||||
NetworkCurvesVec::<T>::get().into_iter()
|
NetworkCurves::<T>::get().into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_types_by_curve(
|
fn iter_types_by_curve(
|
||||||
curve: &Self::NetworkCurve
|
curve: &Self::NetworkCurve
|
||||||
) -> impl Iterator<Item = Self::NetworkType> {
|
) -> impl Iterator<Item = (T::NetworkId, Self::NetworkType)> {
|
||||||
NetworkCurves::<T>::get(curve)
|
let network_types = NetworkTypes::<T>::get(curve);
|
||||||
.into_iter()
|
|
||||||
.map(|(network_type, _)| network_type)
|
network_types.into_iter().flat_map(|(network_type, network_ids)| {
|
||||||
|
network_ids.into_iter().map(move |network_id| (network_id, network_type))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,8 +45,8 @@ fn register_and_check_network(chain_id: u32, network: NetworkData) {
|
|||||||
));
|
));
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), Some(network));
|
assert_eq!(Networks::<Test>::get(chain_id), Some(network));
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
|
||||||
assert!(NetworkCurves::<Test>::contains_key(&network_curve));
|
assert!(NetworkTypes::<Test>::contains_key(&network_curve));
|
||||||
assert!(NetworkCurvesVec::<Test>::get().contains(&network_curve));
|
assert!(NetworkCurves::<Test>::get().contains(&network_curve));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -55,8 +55,8 @@ fn could_add_network_from_authority() {
|
|||||||
let (chain_id, network) = prepare_network_data(None, None);
|
let (chain_id, network) = prepare_network_data(None, None);
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), None);
|
assert_eq!(Networks::<Test>::get(chain_id), None);
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
||||||
assert!(!NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(!NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(!NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(!NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
|
|
||||||
assert_ok!(GhostNetworks::register_network(
|
assert_ok!(GhostNetworks::register_network(
|
||||||
RuntimeOrigin::signed(RegistererAccount::get()),
|
RuntimeOrigin::signed(RegistererAccount::get()),
|
||||||
@ -68,8 +68,8 @@ fn could_add_network_from_authority() {
|
|||||||
));
|
));
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), Some(network));
|
assert_eq!(Networks::<Test>::get(chain_id), Some(network));
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
|
||||||
assert!(NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +79,8 @@ fn could_not_add_network_from_random_account() {
|
|||||||
let (chain_id, network) = prepare_network_data(None, None);
|
let (chain_id, network) = prepare_network_data(None, None);
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), None);
|
assert_eq!(Networks::<Test>::get(chain_id), None);
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
||||||
assert!(!NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(!NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(!NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(!NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
|
|
||||||
assert_err!(
|
assert_err!(
|
||||||
GhostNetworks::register_network(
|
GhostNetworks::register_network(
|
||||||
@ -108,8 +108,8 @@ fn could_not_add_network_from_random_account() {
|
|||||||
);
|
);
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), None);
|
assert_eq!(Networks::<Test>::get(chain_id), None);
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
||||||
assert!(!NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(!NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(!NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(!NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,10 +351,10 @@ fn could_update_network_curve_from_authority_account() {
|
|||||||
let (chain_id, network) = prepare_network_data(None, None);
|
let (chain_id, network) = prepare_network_data(None, None);
|
||||||
register_and_check_network(chain_id, network.clone());
|
register_and_check_network(chain_id, network.clone());
|
||||||
|
|
||||||
assert!(!NetworkCurves::<Test>::contains_key(&new_curve));
|
assert!(!NetworkTypes::<Test>::contains_key(&new_curve));
|
||||||
assert!(NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(!NetworkCurvesVec::<Test>::get().contains(&new_curve));
|
assert!(!NetworkCurves::<Test>::get().contains(&new_curve));
|
||||||
assert!(NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
|
|
||||||
assert_ok!(GhostNetworks::update_network_curve(
|
assert_ok!(GhostNetworks::update_network_curve(
|
||||||
RuntimeOrigin::signed(UpdaterAccount::get()),
|
RuntimeOrigin::signed(UpdaterAccount::get()),
|
||||||
@ -370,10 +370,10 @@ fn could_update_network_curve_from_authority_account() {
|
|||||||
let mut final_network = network.clone();
|
let mut final_network = network.clone();
|
||||||
final_network.r#curve = new_curve;
|
final_network.r#curve = new_curve;
|
||||||
|
|
||||||
assert!(NetworkCurves::<Test>::contains_key(&new_curve));
|
assert!(NetworkTypes::<Test>::contains_key(&new_curve));
|
||||||
assert!(!NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(!NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(NetworkCurvesVec::<Test>::get().contains(&new_curve));
|
assert!(NetworkCurves::<Test>::get().contains(&new_curve));
|
||||||
assert!(!NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(!NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
|
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), Some(final_network.clone()));
|
assert_eq!(Networks::<Test>::get(chain_id), Some(final_network.clone()));
|
||||||
assert_ne!(network, final_network);
|
assert_ne!(network, final_network);
|
||||||
@ -1050,8 +1050,8 @@ fn could_remove_network_from_authority_account() {
|
|||||||
));
|
));
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), None);
|
assert_eq!(Networks::<Test>::get(chain_id), None);
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
||||||
assert!(!NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(!NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(!NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(!NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1077,8 +1077,8 @@ fn could_not_remove_network_from_random_account() {
|
|||||||
);
|
);
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), Some(network));
|
assert_eq!(Networks::<Test>::get(chain_id), Some(network));
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![chain_id]);
|
||||||
assert!(NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,8 +1093,8 @@ fn could_not_remove_non_existent_network() {
|
|||||||
);
|
);
|
||||||
assert_eq!(Networks::<Test>::get(chain_id), None);
|
assert_eq!(Networks::<Test>::get(chain_id), None);
|
||||||
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
assert_eq!(NetworkIndexes::<Test>::get(), vec![]);
|
||||||
assert!(!NetworkCurves::<Test>::contains_key(&CURRENT_CURVE));
|
assert!(!NetworkTypes::<Test>::contains_key(&CURRENT_CURVE));
|
||||||
assert!(!NetworkCurvesVec::<Test>::get().contains(&CURRENT_CURVE));
|
assert!(!NetworkCurves::<Test>::get().contains(&CURRENT_CURVE));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ghost-traits"
|
name = "ghost-traits"
|
||||||
version = "0.4.7"
|
version = "0.4.8"
|
||||||
description = "Shared traits including `GhostHasher`, `NetworkDataBasicHandler`, `BoundedBTreeMap`, `MerkleTree` and more."
|
description = "Shared traits including `GhostHasher`, `NetworkDataBasicHandler`, `BoundedBTreeMap`, `MerkleTree` and more."
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
use frame_support::{pallet_prelude::*, storage::PrefixIterator};
|
use frame_support::{
|
||||||
|
pallet_prelude::*,
|
||||||
|
storage::PrefixIterator,
|
||||||
|
};
|
||||||
use sp_std::vec::Vec;
|
use sp_std::vec::Vec;
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
offchain::http::PendingRequest,
|
offchain::http::PendingRequest,
|
||||||
@ -29,6 +32,7 @@ pub trait NetworkDataBasicHandler {
|
|||||||
+ TypeInfo
|
+ TypeInfo
|
||||||
+ MaybeSerializeDeserialize
|
+ MaybeSerializeDeserialize
|
||||||
+ MaxEncodedLen;
|
+ MaxEncodedLen;
|
||||||
|
type MaxNetworks: Get<u32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
|
pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
|
||||||
@ -40,7 +44,9 @@ pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
|
|||||||
fn iter() -> PrefixIterator<(Self::NetworkId, Network)>;
|
fn iter() -> PrefixIterator<(Self::NetworkId, Network)>;
|
||||||
fn iter_indexes() -> impl Iterator<Item = Self::NetworkId>;
|
fn iter_indexes() -> impl Iterator<Item = Self::NetworkId>;
|
||||||
fn iter_curves() -> impl Iterator<Item = Self::NetworkCurve>;
|
fn iter_curves() -> impl Iterator<Item = Self::NetworkCurve>;
|
||||||
fn iter_types_by_curve(n: &Self::NetworkCurve) -> impl Iterator<Item = Self::NetworkType>;
|
fn iter_types_by_curve(
|
||||||
|
c: &Self::NetworkCurve
|
||||||
|
) -> impl Iterator<Item = (Self::NetworkId, Self::NetworkType)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> {
|
pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user