Compare commits

..

No commits in common. "ab7f978ccc96f42b33eac9c3748a96fc171671fe" and "bdbf7bd20f2ac022d8c65b520f5916f2ad229e83" have entirely different histories.

20 changed files with 221 additions and 975 deletions

18
Cargo.lock generated
View File

@ -1195,7 +1195,7 @@ dependencies = [
[[package]] [[package]]
name = "casper-runtime" name = "casper-runtime"
version = "4.0.15" version = "4.0.14"
dependencies = [ dependencies = [
"casper-runtime-constants", "casper-runtime-constants",
"frame-benchmarking", "frame-benchmarking",
@ -1209,7 +1209,6 @@ dependencies = [
"frame-try-runtime", "frame-try-runtime",
"ghost-core-primitives", "ghost-core-primitives",
"ghost-exodus", "ghost-exodus",
"ghost-exodus-runtime-api",
"ghost-governance", "ghost-governance",
"ghost-helpers", "ghost-helpers",
"ghost-networks", "ghost-networks",
@ -3685,7 +3684,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-exodus" name = "ghost-exodus"
version = "0.1.1" version = "0.0.17"
dependencies = [ dependencies = [
"chacha20poly1305", "chacha20poly1305",
"frame-benchmarking", "frame-benchmarking",
@ -3695,7 +3694,6 @@ dependencies = [
"frost-core", "frost-core",
"frost-ed25519", "frost-ed25519",
"frost-secp256k1-tr", "frost-secp256k1-tr",
"ghost-exodus-runtime-api",
"ghost-helpers", "ghost-helpers",
"ghost-networks", "ghost-networks",
"ghost-traits", "ghost-traits",
@ -3727,12 +3725,10 @@ dependencies = [
[[package]] [[package]]
name = "ghost-exodus-runtime-api" name = "ghost-exodus-runtime-api"
version = "0.0.2" version = "0.0.0"
dependencies = [ dependencies = [
"ghost-helpers",
"parity-scale-codec", "parity-scale-codec",
"sp-api", "sp-api",
"sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?tag=polkadot-v1.12.0)",
] ]
[[package]] [[package]]
@ -3762,7 +3758,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-helpers" name = "ghost-helpers"
version = "0.0.14" version = "0.0.11"
dependencies = [ dependencies = [
"frame-support", "frame-support",
"ghost-traits", "ghost-traits",
@ -3844,7 +3840,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-networks" name = "ghost-networks"
version = "0.2.12" version = "0.2.10"
dependencies = [ dependencies = [
"frame-benchmarking", "frame-benchmarking",
"frame-support", "frame-support",
@ -4090,7 +4086,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-traits" name = "ghost-traits"
version = "0.4.9" version = "0.4.6"
dependencies = [ dependencies = [
"frame-support", "frame-support",
"frost-core", "frost-core",
@ -4114,7 +4110,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-weaver" name = "ghost-weaver"
version = "0.0.16" version = "0.0.14"
dependencies = [ dependencies = [
"frame-benchmarking", "frame-benchmarking",
"frame-support", "frame-support",

View File

@ -239,7 +239,6 @@ ghost-networks = { path = "pallets/networks", default-features = false }
ghost-governance = { path = "pallets/governance", default-features = false } ghost-governance = { path = "pallets/governance", default-features = false }
ghost-weaver = { path = "pallets/weaver", default-features = false } ghost-weaver = { path = "pallets/weaver", default-features = false }
ghost-exodus = { path = "pallets/exodus", default-features = false } ghost-exodus = { path = "pallets/exodus", default-features = false }
ghost-exodus-runtime-api = { path = "pallets/exodus/runtime-api", default-features = false }
ghost-sudo = { path = "pallets/sudo", default-features = false } ghost-sudo = { path = "pallets/sudo", default-features = false }
ghost-nomination-pools = { path = "pallets/pools", default-features = false } ghost-nomination-pools = { path = "pallets/pools", default-features = false }
ghost-nomination-pools-runtime-api = { path = "pallets/pools/runtime-api", default-features = false } ghost-nomination-pools-runtime-api = { path = "pallets/pools/runtime-api", default-features = false }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-exodus" name = "ghost-exodus"
version = "0.1.1" 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
@ -40,7 +40,6 @@ parking_lot = { workspace = true }
ghost-traits = { workspace = true } ghost-traits = { workspace = true }
ghost-helpers = { workspace = true } ghost-helpers = { workspace = true }
ghost-exodus-runtime-api = { workspace = true }
pallet-balances = { workspace = true } pallet-balances = { workspace = true }
pallet-session = { workspace = true } pallet-session = { workspace = true }
@ -81,7 +80,6 @@ std = [
"frost-core/std", "frost-core/std",
"ghost-traits/std", "ghost-traits/std",
"ghost-helpers/std", "ghost-helpers/std",
"ghost-exodus-runtime-api/std",
"pallet-balances/std", "pallet-balances/std",
"pallet-session/std", "pallet-session/std",
"pallet-staking/std", "pallet-staking/std",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-exodus-runtime-api" name = "ghost-exodus-runtime-api"
version = "0.0.2" 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
@ -14,14 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies] [dependencies]
codec = { workspace = true, features = ["derive"] } codec = { workspace = true, features = ["derive"] }
sp-api = { workspace = true } sp-api = { workspace = true }
sp-std = { workspace = true }
ghost-helpers = { workspace = true }
[features] [features]
default = ["std"] default = ["std"]
std = [ std = ["codec/std", "sp-api/std"]
"codec/std",
"sp-api/std",
"sp-std/std",
"ghost-helpers/std",
]

View File

@ -1,17 +1,28 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
use sp_std::vec::Vec;
use ghost_helpers::networks::{NetworkType, NetworkCurve};
pub type PreparedEvmMessage = Option<(Vec<u8>, Vec<u8>, Vec<u8>)>;
sp_api::decl_runtime_apis! { sp_api::decl_runtime_apis! {
pub trait ExodusApi { pub trait ExodusApi<NetworkId> {
fn get_evm_rotation_metadata(dkg_index: u64, network_type: NetworkType) -> PreparedEvmMessage; fn get_signed_rotation_message(
fn get_evm_bridge_metadata(dkg_index: u64, network_id: u64, session: u64) -> PreparedEvmMessage; session: ExodusSession,
fn get_evm_governance_metadata(dkg_index: u64, network_id: u64, session: u64) -> PreparedEvmMessage; 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;
fn pending_exodus_request_count() -> u32;
fn is_qualification_ongoing(curve: NetworkCurve) -> bool;
} }
} }

View File

@ -539,7 +539,7 @@ mod benchmarks {
intervals: [34, 35], intervals: [34, 35],
booleans: [true, true], booleans: [true, true],
}; };
let request = ExodusRequest::<T>::evm_governance( let request = ExodusRequest::<BalanceOf<T>>::evm_governance(
dummy_address, dummy_address,
create_bond, create_bond,
); );
@ -625,7 +625,7 @@ mod benchmarks {
intervals: [34, 35], intervals: [34, 35],
booleans: [true, true], booleans: [true, true],
}; };
let request = ExodusRequest::<T>::evm_governance( let request = ExodusRequest::<BalanceOf<T>>::evm_governance(
dummy_address, dummy_address,
create_bond, create_bond,
); );
@ -732,7 +732,7 @@ mod benchmarks {
intervals: [34, 35], intervals: [34, 35],
booleans: [true, true], booleans: [true, true],
}; };
let request = ExodusRequest::<T>::evm_governance( let request = ExodusRequest::<BalanceOf<T>>::evm_governance(
dummy_address, dummy_address,
create_bond, create_bond,
); );

View File

@ -31,7 +31,6 @@ use sp_io::hashing::blake2_256;
use ghost_helpers::{ use ghost_helpers::{
get_byzantium_quorum_threshold, SubstrateBlake2Hasher, get_byzantium_quorum_threshold, SubstrateBlake2Hasher,
lcg::PerfectSlotMapperU128,
hash_chain::cumulative_hash, hash_chain::cumulative_hash,
networks::{NetworkData, NetworkCurve, NetworkType}, networks::{NetworkData, NetworkCurve, NetworkType},
bounded_bitmap::{validate_bitmap_sizes, BoundedBitmap}, bounded_bitmap::{validate_bitmap_sizes, BoundedBitmap},
@ -228,16 +227,9 @@ type EvmBytes32 = sp_core::H256;
type ParticipantsBitmap<T> = BoundedBitmap<BitmapChunk, <T as Config>::MaxAuthoritiesChunks>; type ParticipantsBitmap<T> = BoundedBitmap<BitmapChunk, <T as Config>::MaxAuthoritiesChunks>;
type BitmapByAuthority<T> = BoundedBTreeMap<AuthIndex, ParticipantsBitmap<T>, <T as Config>::MaxAuthorities>; type BitmapByAuthority<T> = BoundedBTreeMap<AuthIndex, ParticipantsBitmap<T>, <T as Config>::MaxAuthorities>;
pub type EvmSessionsBundle<T> = BoundedVec::<u8, MaxEvmRotationSessionsSize<T>>;
pub type BalanceOf<T> = <<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance; pub type BalanceOf<T> = <<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
pub type NetworkIdOf<T> = <<T as Config>::NetworkDataHandler as NetworkDataBasicHandler>::NetworkId; pub type NetworkIdOf<T> = <<T as Config>::NetworkDataHandler as NetworkDataBasicHandler>::NetworkId;
pub type ExodusSessionsMap<T> = BoundedBTreeMap<
NetworkIdOf<T>,
ExodusSession,
<<T as Config>::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks,
>;
pub type ValidatorId<T> = <<T as Config>::ValidatorSet as ValidatorSet< pub type ValidatorId<T> = <<T as Config>::ValidatorSet as ValidatorSet<
<T as frame_system::Config>::AccountId, <T as frame_system::Config>::AccountId,
>>::ValidatorId; >>::ValidatorId;
@ -251,16 +243,6 @@ pub type IdentificationTuple<T> = (
type ExodusResult<T> = Result<T, ExodusError>; type ExodusResult<T> = Result<T, ExodusError>;
pub struct MaxEvmRotationSessionsSize<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> Get<u32> for MaxEvmRotationSessionsSize<T> {
fn get() -> u32 {
let exodus_session_size = core::mem::size_of::<ExodusSession>() as u32;
let max_networks = <T::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks::get();
exodus_session_size.saturating_mul(max_networks)
}
}
pub struct MaxAuthoritiesBitmaskSize<T>(sp_std::marker::PhantomData<T>); pub struct MaxAuthoritiesBitmaskSize<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> Get<u32> for MaxAuthoritiesBitmaskSize<T> { impl<T: Config> Get<u32> for MaxAuthoritiesBitmaskSize<T> {
fn get() -> u32 { fn get() -> u32 {
@ -433,7 +415,7 @@ pub mod pallet {
type MaxAuthorities: Get<u32>; type MaxAuthorities: Get<u32>;
#[pallet::constant] #[pallet::constant]
type MaxAuthoritiesChunks: Get<u32>; type MaxAuthoritiesChunks: Get<u32> + core::fmt::Debug;
#[pallet::constant] #[pallet::constant]
type DkgRoundPeriod: Get<u64>; type DkgRoundPeriod: Get<u64>;
@ -572,8 +554,15 @@ pub mod pallet {
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn current_exodus_sessions)] #[pallet::getter(fn current_exodus_sessions)]
pub(super) type CurrentExodusSessions<T: Config> = pub(super) type CurrentExodusSessions<T: Config> = StorageValue<
StorageValue<_, ExodusSessionsMap<T>, ValueQuery>; _,
BoundedBTreeMap<
NetworkIdOf<T>,
ExodusSession,
<T::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks,
>,
ValueQuery
>;
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn exodus_requests)] #[pallet::getter(fn exodus_requests)]
@ -583,7 +572,7 @@ pub mod pallet {
NMapKey<Twox64Concat, NetworkCurve>, NMapKey<Twox64Concat, NetworkCurve>,
NMapKey<Twox64Concat, ExodusContext<NetworkIdOf<T>>>, NMapKey<Twox64Concat, ExodusContext<NetworkIdOf<T>>>,
), ),
ExodusRequest<T>, ExodusRequest<BalanceOf<T>>,
OptionQuery, OptionQuery,
>; >;
@ -657,8 +646,8 @@ pub mod pallet {
pub(super) type ExodusSignedRotations<T: Config> = StorageDoubleMap< pub(super) type ExodusSignedRotations<T: Config> = StorageDoubleMap<
_, _,
Twox64Concat, DkgIndex, Twox64Concat, DkgIndex,
Twox64Concat, NetworkType, Twox64Concat, ExodusContext<NetworkIdOf<T>>,
(ExodusContext<NetworkIdOf<T>>, ExodusSignedMessage<T>), ExodusSignedMessage<BalanceOf<T>>,
OptionQuery, OptionQuery,
>; >;
@ -668,7 +657,7 @@ pub mod pallet {
_, _,
Twox64Concat, DkgIndex, Twox64Concat, DkgIndex,
Twox64Concat, ExodusContext<NetworkIdOf<T>>, Twox64Concat, ExodusContext<NetworkIdOf<T>>,
ExodusSignedMessage<T>, ExodusSignedMessage<BalanceOf<T>>,
OptionQuery, OptionQuery,
>; >;
@ -678,7 +667,7 @@ pub mod pallet {
_, _,
Twox64Concat, DkgIndex, Twox64Concat, DkgIndex,
Twox64Concat, ExodusContext<NetworkIdOf<T>>, Twox64Concat, ExodusContext<NetworkIdOf<T>>,
ExodusSignedMessage<T>, ExodusSignedMessage<BalanceOf<T>>,
OptionQuery, OptionQuery,
>; >;
@ -876,34 +865,18 @@ pub mod pallet {
SCALAR_MAX_BYTES, SCALAR_MAX_BYTES,
); );
for (network_type, network_ids) in T::NetworkDataHandler::iter_types_by_curve(&network_curve) { for (network_id, network_type) in T::NetworkDataHandler::iter_types_by_curve(&network_curve) {
let rotation_message_size = match network_type { let rotation_message_size = match network_type {
NetworkType::Evm => { NetworkType::Evm => {
let dummy_evm_xor_key = u128::MAX;
let dummy_evm_bitmask = u128::MIN;
let dummy_public_address = EvmBytes32::repeat_byte(69u8); let dummy_public_address = EvmBytes32::repeat_byte(69u8);
let mut dummy_packed_sessions =
EvmSessionsBundle::<T>::with_max_capacity();
let max_size = EvmSessionsBundle::<T>::bound();
dummy_packed_sessions.bounded_resize(max_size, 69u8);
let network_id = network_ids
.as_ref()
.first()
.copied()
.expect("At this point we should have at least one `NetworkId` registered; qed");
let dummy_exodus_request = let dummy_exodus_request =
ExodusRequest::<T>::evm_rotation( ExodusRequest::<BalanceOf<T>>::evm_rotation(
dummy_public_address, dummy_public_address,
dummy_evm_xor_key, 0u8, // parity
dummy_evm_bitmask,
dummy_packed_sessions,
); );
let dummy_exodus_context = let dummy_exodus_context = ExodusContext::new(network_id, 0);
ExodusContext::<NetworkIdOf<T>>::new(network_id, 0);
let mut message_buffer = [0u8; MAX_MESSAGE_SIZE as usize]; let mut message_buffer = [0u8; MAX_MESSAGE_SIZE as usize];
dummy_exodus_request dummy_exodus_request
@ -1664,14 +1637,9 @@ pub mod pallet {
ensure!( ensure!(
match exodus_request.r#type { match exodus_request.r#type {
ExodusRequestType::EvmRotation { .. } => { ExodusRequestType::EvmRotation { .. } | ExodusRequestType::UtxoRotation => {
!ExodusSignedRotations::<T>::contains_key( !ExodusSignedRotations::<T>::contains_key(
active_dkg_index, NetworkType::Evm, active_dkg_index, exodus_context,
)
},
ExodusRequestType::UtxoRotation => {
!ExodusSignedRotations::<T>::contains_key(
active_dkg_index, NetworkType::Utxo,
) )
}, },
ExodusRequestType::EvmBridgeOut { .. } | ExodusRequestType::UtxoBridgeOut { .. } => { ExodusRequestType::EvmBridgeOut { .. } | ExodusRequestType::UtxoBridgeOut { .. } => {
@ -1821,26 +1789,25 @@ pub mod pallet {
ExodusRequests::<T>::remove((&network_curve, exodus_context)); ExodusRequests::<T>::remove((&network_curve, exodus_context));
if exodus_signed_message.is_evm_rotation() { match exodus_request.r#type {
ExodusSignedRotations::<T>::insert( ExodusRequestType::EvmRotation { .. } | ExodusRequestType::UtxoRotation => {
active_dkg_index, NetworkType::Evm, ExodusSignedRotations::<T>::insert(
(exodus_context, exodus_signed_message), active_dkg_index, exodus_context,
); exodus_signed_message,
} else if exodus_signed_message.is_utxo_rotation() { );
ExodusSignedRotations::<T>::insert( },
active_dkg_index, NetworkType::Utxo, ExodusRequestType::EvmBridgeOut { .. } | ExodusRequestType::UtxoBridgeOut { .. } => {
(exodus_context, exodus_signed_message), ExodusSignedBridges::<T>::insert(
); active_dkg_index, exodus_context,
} else if exodus_signed_message.is_bridge_out() { exodus_signed_message,
ExodusSignedBridges::<T>::insert( );
active_dkg_index, exodus_context, }
exodus_signed_message, ExodusRequestType::EvmGovernance { .. } => {
); ExodusSignedGovernance::<T>::insert(
} else if exodus_signed_message.is_evm_governance() { active_dkg_index, exodus_context,
ExodusSignedGovernance::<T>::insert( exodus_signed_message,
active_dkg_index, exodus_context, );
exodus_signed_message, }
);
} }
Ok(()) Ok(())
@ -2166,7 +2133,7 @@ impl<T: Config> Pallet<T> {
fn do_register_evm_exodus( fn do_register_evm_exodus(
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,
exodus_request: ExodusRequest<T>, exodus_request: ExodusRequest<BalanceOf<T>>,
) -> DispatchResult { ) -> DispatchResult {
let network = T::NetworkDataHandler::get(&network_id) let network = T::NetworkDataHandler::get(&network_id)
.ok_or(Error::<T>::NetworkDoesNotExist)?; .ok_or(Error::<T>::NetworkDoesNotExist)?;
@ -2621,55 +2588,68 @@ impl<T: Config> Pallet<T> {
return; return;
} }
weight.saturating_accrue(T::DbWeight::get().reads(1)); weight.saturating_accrue(T::DbWeight::get().reads(2));
let mut all_exodus_sessions = CurrentExodusSessions::<T>::get(); let mut all_exodus_sessions = CurrentExodusSessions::<T>::get();
let mut rotation_requests = BoundedVec::<
(ExodusRequest<T>, ExodusContext<NetworkIdOf<T>>),
<T::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks,
>::with_max_capacity();
let mut rotation_failed = false; let max_networks = <T::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks::get();
let mut exodus_requests = Vec::with_capacity(max_networks as usize);
let mut too_much_entries = false;
weight.saturating_accrue(T::DbWeight::get().reads(1)); for (network_id, network_type) in T::NetworkDataHandler::iter_types_by_curve(&network_curve) {
for (network_type, network_ids) in T::NetworkDataHandler::iter_types_by_curve(&network_curve) { if !matches!(network_type, NetworkType::Evm) {
let processed_network_type = matches!(network_type, NetworkType::Evm); continue;
if !processed_network_type { continue; } }
let mut process_iteration = || -> Option<()> { let exodus_session = match all_exodus_sessions.get_mut(&network_id) {
let element_len = network_curve.element_bytes_len(); Some(session_ref) => {
let evm_public_key = EvmBytes32::from_slice( let current = *session_ref;
&verifying_key_slice[1..element_len] *session_ref = current.saturating_add(1);
); current
},
let (request, context) = Self::prepare_evm_rotation( None => {
evm_public_key, if let Err(_) = all_exodus_sessions.try_insert(network_id, 1) {
network_ids.as_ref(), too_much_entries = true;
&mut all_exodus_sessions }
)?; 0
}
if !request.r#type.is_evm_rotation() { return None; }
dkg_qualification.try_push_rotation(network_type, context)?;
rotation_requests.try_push((request, context)).ok()?;
Some(())
}; };
if process_iteration().is_none() { if too_much_entries { break; }
rotation_failed = true;
break; let exodus_request = match network_type {
} NetworkType::Evm => {
let parity_byte = verifying_key_slice[0];
let parity = if parity_byte % 2 == 0 { 0u8 } else { 1u8 };
let public_key = EvmBytes32::from_slice(&verifying_key_slice[1..33]);
ExodusRequest::evm_rotation(public_key, parity)
}
_ => {
unreachable!();
}
};
let exodus_context = ExodusContext::new(network_id, exodus_session);
if let None = dkg_qualification
.try_push_rotation_context(exodus_context) {
too_much_entries = true;
break;
}
let key = (network_curve, exodus_context);
exodus_requests.push((key, exodus_request));
} }
if rotation_failed { if too_much_entries {
dkg_qualification.nullify_indexes(); dkg_qualification.nullify_indexes();
} else { } else {
for (exodus_request, exodus_context) in rotation_requests { let requests_count = exodus_requests.len() as u64;
weight.saturating_accrue(T::DbWeight::get().writes(1)); weight.saturating_accrue(T::DbWeight::get().writes(requests_count));
ExodusRequests::<T>::insert(
(network_curve, exodus_context), for exodus in exodus_requests {
exodus_request ExodusRequests::<T>::insert(exodus.0, exodus.1);
);
} }
weight.saturating_accrue(T::DbWeight::get().writes(1)); weight.saturating_accrue(T::DbWeight::get().writes(1));
@ -2698,15 +2678,15 @@ impl<T: Config> Pallet<T> {
!ActiveVerifyingKey::<T>::contains_key(network_curve); !ActiveVerifyingKey::<T>::contains_key(network_curve);
let all_rotations_have_signatures = dkg_qualification let all_rotations_have_signatures = dkg_qualification
.iter_rotations() .iter_rotation_contexts()
.fold(true, |accumulator, (network_type, exodus_context)| { .fold(true, |accumulator, exodus_context| {
weight.saturating_accrue(T::DbWeight::get().writes(1)); weight.saturating_accrue(T::DbWeight::get().writes(1));
ExodusRequests::<T>::remove((&network_curve, &exodus_context)); ExodusRequests::<T>::remove((&network_curve, &exodus_context));
weight.saturating_accrue(T::DbWeight::get().reads(1)); weight.saturating_accrue(T::DbWeight::get().reads(1));
let has_signature = ExodusSignedRotations::<T>::contains_key( let has_signature = ExodusSignedRotations::<T>::contains_key(
dkg_index, dkg_index,
network_type, exodus_context,
); );
accumulator && has_signature accumulator && has_signature
@ -2729,93 +2709,6 @@ impl<T: Config> Pallet<T> {
}) })
} }
fn prepare_evm_rotation(
evm_public_key: EvmBytes32,
network_ids: &[NetworkIdOf<T>],
evm_exodus_sessions: &mut ExodusSessionsMap<T>,
) -> Option<(ExodusRequest<T>, ExodusContext<NetworkIdOf<T>>)> {
if network_ids.len() >= 128 { return None; }
let exodus_session_size = core::mem::size_of::<ExodusSession>();
let packed_sessions_size = exodus_session_size * network_ids.len();
let evm_xor_key = PerfectSlotMapperU128::get_lcg_xor_mask(network_ids)?;
let (bit_shift, bit_mask) = PerfectSlotMapperU128::get_bits_metadata()?;
let mut evm_sessions_bitmask: u128 = 0;
let mut maybe_best_exodus_context: Option<ExodusContext<NetworkIdOf<T>>> = None;
let mut evm_packed_sessions = EvmSessionsBundle::with_max_capacity();
evm_packed_sessions.bounded_resize(packed_sessions_size, 0u8);
let mut evm_slots = [0usize; 128];
for (i, network_id) in network_ids.iter().enumerate() {
let slot_index =
PerfectSlotMapperU128::get_lcg_based_slot_index(
bit_mask,
bit_shift,
evm_xor_key,
network_id
);
if slot_index > 127 { return None; }
evm_sessions_bitmask |= 1u128 << slot_index;
evm_slots[i] = slot_index;
}
for (i, &network_id) in network_ids.into_iter().enumerate() {
let exodus_session = match evm_exodus_sessions.get_mut(&network_id) {
Some(session_ref) => {
let current = *session_ref;
*session_ref = current.saturating_add(1);
current
},
None => {
evm_exodus_sessions.try_insert(network_id, 1).ok()?;
0
}
};
if maybe_best_exodus_context
.as_ref()
.map_or(true, |c| exodus_session > c.session) {
maybe_best_exodus_context = Some(
ExodusContext::<NetworkIdOf<T>>::new(
network_id,
exodus_session
)
);
}
let lcg_slot_index = evm_slots[i];
let lower_bits = (1u128 << lcg_slot_index) - 1;
let slot_index = (evm_sessions_bitmask & lower_bits).count_ones() as usize;
let offset_start = slot_index * exodus_session_size;
let offset_end = offset_start + exodus_session_size;
if offset_end > evm_packed_sessions.len() {
return None;
}
evm_packed_sessions[offset_start..offset_end]
.copy_from_slice(&exodus_session.to_be_bytes());
}
let best_exodus_context = maybe_best_exodus_context?;
let rotation_request =
ExodusRequest::<T>::evm_rotation(
evm_public_key,
evm_xor_key,
evm_sessions_bitmask,
evm_packed_sessions
);
Some((rotation_request, best_exodus_context))
}
fn validate_round0_package_size( fn validate_round0_package_size(
dkg_package: & DkgPackage<NetworkCurve, BlockNumberFor<T>, T>, dkg_package: & DkgPackage<NetworkCurve, BlockNumberFor<T>, T>,
signature: &<T::AuthorityId as RuntimeAppPublic>::Signature, signature: &<T::AuthorityId as RuntimeAppPublic>::Signature,
@ -3338,7 +3231,7 @@ impl<T: Config> Pallet<T> {
fn validate_exodus_nonce_commitment_size_and_get_metadata<'a>( fn validate_exodus_nonce_commitment_size_and_get_metadata<'a>(
exodus_package: &'a ExodusPackage<NetworkCurve, NetworkIdOf<T>, BlockNumberFor<T>, T>, exodus_package: &'a ExodusPackage<NetworkCurve, NetworkIdOf<T>, BlockNumberFor<T>, T>,
signature: &<T::AuthorityId as RuntimeAppPublic>::Signature, signature: &<T::AuthorityId as RuntimeAppPublic>::Signature,
) -> Result<(ExodusRequest<T>, RoastSession), InvalidTransaction> { ) -> Result<(ExodusRequest<BalanceOf<T>>, RoastSession), InvalidTransaction> {
let ExodusPackage::NonceCommitment(package) = exodus_package else { let ExodusPackage::NonceCommitment(package) = exodus_package else {
return Err(InvalidTransaction::BadProof); return Err(InvalidTransaction::BadProof);
}; };
@ -3633,7 +3526,11 @@ impl<T: Config> Pallet<T> {
let mut exodus_requests_by_network = BoundedBTreeMap::< let mut exodus_requests_by_network = BoundedBTreeMap::<
NetworkIdOf<T>, NetworkIdOf<T>,
BoundedBTreeMap<ExodusSession, ExodusRequest<T>, T::MaxExodusRequestCount>, BoundedBTreeMap<
ExodusSession,
ExodusRequest<BalanceOf<T>>,
T::MaxExodusRequestCount
>,
<T::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks, <T::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks,
>::new(); >::new();
@ -5376,75 +5273,6 @@ impl<T: Config> Pallet<T> {
} }
} }
impl<T: Config> Pallet<T> {
pub fn api_get_evm_rotation(
dkg_index_u64: u64,
network_type: NetworkType,
) -> ghost_exodus_runtime_api::PreparedEvmMessage {
let dkg_index: DkgIndex = dkg_index_u64.unique_saturated_into();
let (context, rotation) =
ExodusSignedRotations::<T>::get(dkg_index, network_type)?;
let mut message_buffer = [0u8; MAX_MESSAGE_SIZE as usize];
let message = rotation.get_message(&mut message_buffer, context)?;
let nonce_bytes = rotation.nonce[1..].to_vec();
let signature_bytes = rotation.signature.to_vec();
Some((message.to_vec(), nonce_bytes, signature_bytes))
}
pub fn api_get_evm_bridge(
dkg_index_u64: u64,
network_id_u64: u64,
session_u64: u64,
) -> ghost_exodus_runtime_api::PreparedEvmMessage {
let dkg_index: DkgIndex = dkg_index_u64.unique_saturated_into();
let session: ExodusSession = session_u64.unique_saturated_into();
let network_id: NetworkIdOf<T> = network_id_u64.unique_saturated_into();
let context = ExodusContext::<NetworkIdOf<T>>::new(network_id, session);
let bridge = ExodusSignedBridges::<T>::get(dkg_index, context)?;
let mut message_buffer = [0u8; MAX_MESSAGE_SIZE as usize];
let message = bridge.get_message(&mut message_buffer, context)?;
let nonce_bytes = bridge.nonce[1..].to_vec();
let signature_bytes = bridge.signature.to_vec();
Some((message.to_vec(), nonce_bytes, signature_bytes))
}
pub fn api_get_evm_governance(
dkg_index_u64: u64,
network_id_u64: u64,
session_u64: u64,
) -> ghost_exodus_runtime_api::PreparedEvmMessage {
let dkg_index: DkgIndex = dkg_index_u64.unique_saturated_into();
let session: ExodusSession = session_u64.unique_saturated_into();
let network_id: NetworkIdOf<T> = network_id_u64.unique_saturated_into();
let context = ExodusContext::<NetworkIdOf<T>>::new(network_id, session);
let governance = ExodusSignedGovernance::<T>::get(dkg_index, context)?;
let mut message_buffer = [0u8; MAX_MESSAGE_SIZE as usize];
let message = governance.get_message(&mut message_buffer, context)?;
let nonce_bytes = governance.nonce[1..].to_vec();
let signature_bytes = governance.signature.to_vec();
Some((message.to_vec(), nonce_bytes, signature_bytes))
}
pub fn api_pending_exodus_request_count() -> u32 {
ExodusRequests::<T>::count()
}
pub fn api_is_qualification_ongoing(network_curve: NetworkCurve) -> bool {
QualificationDkgState::<T>::get(network_curve).is_dkg_pending()
}
}
impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Pallet<T> { impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Pallet<T> {
type Public = T::AuthorityId; type Public = T::AuthorityId;
} }

View File

@ -926,16 +926,6 @@ 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);
ext.execute_with(|| {
let network_data = NetworkDataBuilder::default()
.with_network_curve(curve)
.with_network_type(NetworkType::Evm)
.with_outgoing_share(500_000_000)
.build();
let _ = <Runtime as Config>::NetworkDataHandler::register(network_id, network_data).unwrap();
});
let mut authorities_2 = authorities_1.clone(); let mut authorities_2 = authorities_1.clone();
let new_authority = authorities_2.iter().max().unwrap() + 1; let new_authority = authorities_2.iter().max().unwrap() + 1;
authorities_2.push(new_authority); authorities_2.push(new_authority);
@ -945,6 +935,13 @@ fn test_all_validators_can_execute_dkg() {
run_dkg_session(&mut ext, &tx_pool_state, authorities_1.clone(), authorities_2.clone(), curve); 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()
.with_network_curve(curve)
.with_network_type(NetworkType::Evm)
.with_outgoing_share(500_000_000)
.build();
let _ = <Runtime as Config>::NetworkDataHandler::register(network_id, network_data).unwrap();
let _ = <Runtime as Config>::NetworkDataHandler::register_incoming(&network_id, 1337).unwrap(); let _ = <Runtime as Config>::NetworkDataHandler::register_incoming(&network_id, 1337).unwrap();
Exodus::do_register_evm_bridge_out_exodus( Exodus::do_register_evm_bridge_out_exodus(
@ -1010,14 +1007,6 @@ 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();
}); });
ext.execute_with(|| {
CurrentExodusSessions::<Runtime>::mutate(|sessions| {
if let Some(session) = sessions.get_mut(&420) {
*session = 1337;
}
});
});
run_dkg_session(&mut ext, &tx_pool_state, authorities_1, authorities_2.clone(), curve); run_dkg_session(&mut ext, &tx_pool_state, authorities_1, authorities_2.clone(), curve);
let rotations_count = ext.execute_with(|| { let rotations_count = ext.execute_with(|| {
@ -1036,7 +1025,7 @@ fn test_all_validators_can_execute_dkg() {
ExodusRequests::<Runtime>::count() ExodusRequests::<Runtime>::count()
}); });
assert_eq!(rotations_count, 3); 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);

View File

@ -12,17 +12,16 @@ use ghost_traits::{
}; };
use crate::{ use crate::{
ELEMENT_MAX_BYTES, Config, NetworkType, NetworkIdOf, ExodusContext, ELEMENT_MAX_BYTES, Config, ExodusContext, NetworkIdOf,
ParticipantsBitmap, BlockNumberFor, DkgIndex, ParticipantsBitmap, BlockNumberFor, DkgIndex,
}; };
type RotationItem<T> = (NetworkType, ExodusContext<NetworkIdOf<T>>); type RotationSessions<T> = BoundedVec<
type Rotations<T> = BoundedVec< ExodusContext<NetworkIdOf<T>>,
RotationItem<T>, <<T as Config>::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks,
<<T as Config>::NetworkDataHandler as NetworkDataBasicHandler>::MaxNetworks,
>; >;
#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
#[scale_info(skip_type_params(T))] #[scale_info(skip_type_params(T))]
pub struct ReadyDkgAuthorities<T: Config> { pub struct ReadyDkgAuthorities<T: Config> {
authorities_indexes: ParticipantsBitmap<T>, authorities_indexes: ParticipantsBitmap<T>,
@ -73,12 +72,12 @@ where
} }
} }
#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
#[scale_info(skip_type_params(T))] #[scale_info(skip_type_params(T))]
pub struct PendingDkgAuthorities<T: Config> { pub struct PendingDkgAuthorities<T: Config> {
verifying_key: BoundedVec<u8, ConstU32<ELEMENT_MAX_BYTES>>, verifying_key: BoundedVec<u8, ConstU32<ELEMENT_MAX_BYTES>>,
authorities_indexes: ParticipantsBitmap<T>, authorities_indexes: ParticipantsBitmap<T>,
rotations: Rotations<T>, rotation_sessions: RotationSessions<T>,
dkg_state: DkgState<BlockNumberFor<T>>, dkg_state: DkgState<BlockNumberFor<T>>,
} }
@ -87,7 +86,7 @@ impl<T: Config> Default for PendingDkgAuthorities<T> {
Self { Self {
verifying_key: Default::default(), verifying_key: Default::default(),
authorities_indexes: Default::default(), authorities_indexes: Default::default(),
rotations: Default::default(), rotation_sessions: Default::default(),
dkg_state: Default::default(), dkg_state: Default::default(),
} }
} }
@ -102,7 +101,7 @@ where
pub fn new_dkg(&mut self, authorities_len: usize) { pub fn new_dkg(&mut self, authorities_len: usize) {
self.authorities_indexes = ParticipantsBitmap::<T>::empty(authorities_len); self.authorities_indexes = ParticipantsBitmap::<T>::empty(authorities_len);
self.dkg_state.restart(); self.dkg_state.restart();
self.rotations = Default::default(); self.rotation_sessions = Default::default();
} }
pub fn set_release_block(&mut self, block: BlockNumberFor<T>) { pub fn set_release_block(&mut self, block: BlockNumberFor<T>) {
@ -125,7 +124,7 @@ where
self.verifying_key = Default::default(); self.verifying_key = Default::default();
self.authorities_indexes.nullify(); self.authorities_indexes.nullify();
self.dkg_state.restart(); self.dkg_state.restart();
self.rotations = Default::default(); self.rotation_sessions = Default::default();
} }
pub fn next_phase(&mut self) { pub fn next_phase(&mut self) {
@ -207,13 +206,11 @@ where
self.authorities_indexes.insert(i) self.authorities_indexes.insert(i)
} }
pub fn try_push_rotation( pub fn try_push_rotation_context(
&mut self, &mut self,
network_type: NetworkType, context: ExodusContext<NetworkIdOf<T>>,
exodus_context: ExodusContext<NetworkIdOf<T>>,
) -> Option<()> { ) -> Option<()> {
let item = (network_type, exodus_context); self.rotation_sessions.try_push(context).ok()
self.rotations.try_push(item).ok()
} }
pub fn count_ones<N>(&self) -> N pub fn count_ones<N>(&self) -> N
@ -232,10 +229,10 @@ where
&self.authorities_indexes &self.authorities_indexes
} }
pub fn iter_rotations( pub fn iter_rotation_contexts(
&self &self
) -> impl Iterator<Item = &RotationItem<T>> { ) -> impl Iterator<Item = &ExodusContext<NetworkIdOf<T>>> {
self.rotations.iter() self.rotation_sessions.iter()
} }
} }

View File

@ -6,8 +6,8 @@ use sp_runtime::{
}; };
use crate::{ use crate::{
EvmAddress, EvmBytes32, ExodusContext, RoastSession, EvmSessionsBundle, EvmAddress, EvmBytes32, ExodusContext, RoastSession,
Config, BalanceOf, MAX_MESSAGE_SIZE, MAX_MESSAGE_SIZE,
}; };
pub trait EvmAbiEncode { pub trait EvmAbiEncode {
@ -308,31 +308,24 @@ impl GovernanceAction {
} }
} }
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)] #[derive(Encode, Decode, Clone, Copy, PartialEq, TypeInfo, RuntimeDebug)]
#[scale_info(skip_type_params(T))] pub struct ExodusRequest<Balance> {
pub struct ExodusRequest<T: Config> { pub r#type: ExodusRequestType<Balance>,
pub r#type: ExodusRequestType<T>,
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)]
#[scale_info(skip_type_params(T))] pub enum ExodusRequestType<Balance> {
pub enum ExodusRequestType<T: Config> { EvmRotation { public_key: EvmBytes32, parity: u8 },
EvmRotation {
public_key: EvmBytes32,
xor_key: u128,
bitmask: u128,
sessions: EvmSessionsBundle<T>,
},
UtxoRotation, UtxoRotation,
EvmBridgeOut { amount: BalanceOf<T>, bounty: Perbill, receiver: EvmAddress }, EvmBridgeOut { amount: Balance, bounty: Perbill, receiver: EvmAddress },
EvmGovernance { target: EvmAddress, action: GovernanceAction }, EvmGovernance { target: EvmAddress, action: GovernanceAction },
UtxoBridgeOut, UtxoBridgeOut,
} }
impl<T: Config> ExodusRequestType<T> impl<Balance> ExodusRequestType<Balance>
where where
BalanceOf<T>: UniqueSaturatedInto<u128> + Copy, Balance: UniqueSaturatedInto<u128> + Copy,
{ {
pub fn get_message<'a, NetworkId>( pub fn get_message<'a, NetworkId>(
&self, &self,
@ -343,19 +336,21 @@ where
NetworkId: UniqueSaturatedInto<u64> + Copy + Default, NetworkId: UniqueSaturatedInto<u64> + Copy + Default,
{ {
match &self { match &self {
ExodusRequestType::EvmRotation { public_key, xor_key, bitmask, sessions } => { ExodusRequestType::EvmRotation { public_key, parity } => {
let mut buffer = [0u8; 32]; let mut buffer = [0u8; 32];
buffer[0] = *parity;
buffer[..16].copy_from_slice(&xor_key.to_be_bytes()); let chain_id_u64: u64 = exodus_context.network_id
buffer[16..].copy_from_slice(&bitmask.to_be_bytes()); .unique_saturated_into();
let packed_bits = EvmBytes32::from(&buffer);
let payload = sessions.as_slice(); 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,uint256,bytes)", "rotate(uint256,bytes32,uint256)",
[&exodus_context.session, public_key, &packed_bits, payload] [&exodus_context.session, public_key, &packed_metadata]
) )
}, },
ExodusRequestType::EvmGovernance { target, action } => { ExodusRequestType::EvmGovernance { target, action } => {
@ -412,39 +407,11 @@ where
_ => None _ => None
} }
} }
pub fn is_evm_rotation(&self) -> bool {
match &self {
ExodusRequestType::EvmRotation { .. } => true,
_ => false,
}
}
pub fn is_utxo_rotation(&self) -> bool {
match &self {
ExodusRequestType::UtxoRotation { .. } => true,
_ => false,
}
}
pub fn is_bridge_out(&self) -> bool {
match &self {
ExodusRequestType::EvmBridgeOut { .. } | ExodusRequestType::UtxoBridgeOut { .. } => true,
_ => false,
}
}
pub fn is_evm_governance(&self) -> bool {
match &self {
ExodusRequestType::EvmGovernance { .. } => true,
_ => false,
}
}
} }
impl<T: Config> ExodusRequest<T> impl<Balance> ExodusRequest<Balance>
where where
BalanceOf<T>: UniqueSaturatedInto<u128> + Copy, Balance: UniqueSaturatedInto<u128> + Copy,
{ {
pub fn get_message<'a, NetworkId>( pub fn get_message<'a, NetworkId>(
&self, &self,
@ -457,26 +424,15 @@ where
self.r#type.get_message(message_buffer, exodus_context) self.r#type.get_message(message_buffer, exodus_context)
} }
pub fn evm_rotation( pub fn evm_rotation(public_key: EvmBytes32, parity: u8) -> Self {
public_key: EvmBytes32,
xor_key: u128,
bitmask: u128,
sessions: EvmSessionsBundle<T>,
) -> Self {
let rotation = ExodusRequestType::EvmRotation { let rotation = ExodusRequestType::EvmRotation {
public_key, public_key,
xor_key, parity,
bitmask,
sessions,
}; };
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 {
amount: BalanceOf<T>,
bounty: Perbill,
receiver: EvmAddress
) -> Self {
let evm_bridge_out = ExodusRequestType::EvmBridgeOut { let evm_bridge_out = ExodusRequestType::EvmBridgeOut {
amount, amount,
bounty, bounty,
@ -493,7 +449,14 @@ where
Self::default_request_for(evm_governance) Self::default_request_for(evm_governance)
} }
fn default_request_for(request_type: ExodusRequestType<T>) -> Self { pub fn is_rotation(&self) -> bool {
match &self.r#type {
ExodusRequestType::EvmRotation { .. } | ExodusRequestType::UtxoRotation { .. } => true,
_ => false,
}
}
fn default_request_for(request_type: ExodusRequestType<Balance>) -> Self {
Self { Self {
r#type: request_type, r#type: request_type,
next_roast_session: Default::default() next_roast_session: Default::default()
@ -504,7 +467,6 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::mock::*;
use sp_io::hashing::keccak_256; use sp_io::hashing::keccak_256;
#[test] #[test]
@ -515,45 +477,27 @@ mod tests {
let network_id = 420; let network_id = 420;
let context = ExodusContext::new(network_id, session); let context = ExodusContext::new(network_id, session);
let dummy_xor_key = u128::MAX;
let dummy_evm_bitmask = 1337;
let mut dummy_packed_sessions = let rotation_request = ExodusRequest::<u128>::evm_rotation(
EvmSessionsBundle::<Runtime>::with_max_capacity();
let max_size = EvmSessionsBundle::<Runtime>::bound();
dummy_packed_sessions.bounded_resize(max_size, 69);
let rotation_request = ExodusRequest::<Runtime>::evm_rotation(
public_key.clone(), public_key.clone(),
dummy_xor_key, 1,
dummy_evm_bitmask,
dummy_packed_sessions,
); );
let calldata = rotation_request.get_message(&mut buffer, context).unwrap(); let calldata = rotation_request.get_message(&mut buffer, context).unwrap();
// prefix + public_key + packed_bits + pointer + length + bytes array + padding assert_eq!(calldata.len(), 100);
// 4 + 32 + 32 + 32 + 32 + 32 + (8 * 5) + (32 - 40 % 32)
assert_eq!(calldata.len(), 228);
let expected_hash = keccak_256("rotate(uint256,bytes32,uint256,bytes)".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[68..84], &dummy_xor_key.to_be_bytes()); assert_eq!(calldata[68], 1);
assert_eq!(&calldata[84..100], &dummy_evm_bitmask.to_be_bytes()); assert_eq!(&calldata[69..75], &[0u8; 6]);
assert_eq!(calldata[75], 0x01);
assert_eq!(&calldata[100..131], &[0u8; 31]); assert_eq!(calldata[76], 0xA4);
assert_eq!(calldata[131], 128); assert_eq!(&calldata[77..100], &[0u8; 23]);
assert_eq!(&calldata[132..163], &[0u8; 31]);
assert_eq!(calldata[163], 40);
assert_eq!(calldata[164], 69);
assert_eq!(&calldata[204..228], &[0u8; 24]);
} }
#[test] #[test]
@ -565,8 +509,8 @@ mod tests {
let context = ExodusContext::new(network_id, session); let context = ExodusContext::new(network_id, session);
let bridge_request = ExodusRequest::<Runtime>::evm_bridge_out( let bridge_request = ExodusRequest::<u128>::evm_bridge_out(
1_000_000u64, 1_000_000u128,
sp_runtime::Perbill::from_percent(1), sp_runtime::Perbill::from_percent(1),
receiver.clone() receiver.clone()
); );
@ -642,7 +586,7 @@ mod tests {
let current_session = session + (index as u64); let current_session = session + (index as u64);
let context = ExodusContext::new(network_id, current_session); let context = ExodusContext::new(network_id, current_session);
let governance_request = ExodusRequest::<Runtime>::evm_governance( let governance_request = ExodusRequest::<u128>::evm_governance(
target, target,
action, action,
); );

View File

@ -6,28 +6,27 @@ use sp_runtime::{
traits::{AtLeast32BitUnsigned, UniqueSaturatedInto}, traits::{AtLeast32BitUnsigned, UniqueSaturatedInto},
}; };
use crate::{BalanceOf, Config, ExodusContext}; use crate::ExodusContext;
use super::ExodusRequestType; 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 }>>;
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)] #[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
#[scale_info(skip_type_params(T))] pub struct ExodusSignedMessage<Balance: Default> {
pub struct ExodusSignedMessage<T: Config> {
pub nonce: ExodusNonceT, pub nonce: ExodusNonceT,
pub signature: ExodusSignatureT, pub signature: ExodusSignatureT,
pub r#type: ExodusRequestType<T>, pub r#type: ExodusRequestType<Balance>,
} }
impl<T: Config> ExodusSignedMessage<T> impl<Balance> ExodusSignedMessage<Balance>
where where
BalanceOf<T>: 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: ExodusRequestType<T>, r#type: ExodusRequestType<Balance>,
) -> Option<Self> ) -> Option<Self>
where where
E: Iterator<Item = u8> + ExactSizeIterator, E: Iterator<Item = u8> + ExactSizeIterator,
@ -49,17 +48,4 @@ where
) -> Option<&'a [u8]> { ) -> Option<&'a [u8]> {
self.r#type.get_message(message_buffer, exodus_context) self.r#type.get_message(message_buffer, exodus_context)
} }
pub fn is_evm_rotation(&self) -> bool {
self.r#type.is_evm_rotation()
}
pub fn is_utxo_rotation(&self) -> bool {
self.r#type.is_utxo_rotation()
}
pub fn is_bridge_out(&self) -> bool {
self.r#type.is_bridge_out()
}
pub fn is_evm_governance(&self) -> bool {
self.r#type.is_evm_governance()
}
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-helpers" name = "ghost-helpers"
version = "0.0.14" version = "0.0.13"
description = "Cryptographic utility suite for custom runtimes: optimized Bitmaps, UTXO parsing, Merkle Tree proofs, and Hash Chain components." description = "Cryptographic utility suite for custom runtimes: optimized Bitmaps, UTXO parsing, Merkle Tree proofs, and Hash Chain components."
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -1,452 +0,0 @@
use sp_runtime::traits::UniqueSaturatedInto;
macro_rules! generate_perfect_slot_mapper {
(
struct_name: $struct_name:ident,
inner_type: $inner_type:ty,
init_rng: $init_rng:expr,
golden_ratio: $golden_ratio:expr,
lcg_multiplier: $lcg_multiplier:expr,
lcg_increment: $lcg_increment:expr,
) => {
pub struct $struct_name;
impl $struct_name {
const TOTAL_BITS: usize = core::mem::size_of::<$inner_type>() * 8;
fn get_exact_iterations(items_count: usize) -> Option<usize> {
let table_size = Self::TOTAL_BITS;
if items_count <= 1 { return Some(1); }
if items_count > table_size { return None; }
let density_pct = (items_count * 100) / table_size;
match table_size {
16 => match density_pct {
0 => Some(1),
1..=5 => Some(1), // max 0 items
6..=10 => Some(1), // max 1 items
11..=15 => Some(2), // max 2 items
16..=20 => Some(2), // max 3 items
21..=25 => Some(3), // max 4 items
26..=30 => Some(3), // max 4 items
31..=35 => Some(5), // max 5 items
36..=40 => Some(8), // max 6 items
41..=45 => Some(13), // max 7 items
46..=50 => Some(24), // max 8 items
51..=55 => Some(24), // max 8 items
56..=60 => Some(49), // max 9 items
61..=65 => Some(112), // max 10 items
66..=70 => Some(301), // max 11 items
71..=75 => Some(966), // max 12 items
76..=80 => Some(966), // max 12 items
81..=85 => Some(3868), // max 13 items
86..=90 => Some(20633), // max 14 items
91..=95 => Some(165075), // max 15 items
_ => None,
},
32 => match density_pct {
0 => Some(1),
1..=5 => Some(1), // max 1 items
6..=10 => Some(2), // max 3 items
11..=15 => Some(2), // max 4 items
16..=20 => Some(4), // max 6 items
21..=25 => Some(7), // max 8 items
26..=30 => Some(9), // max 9 items
31..=35 => Some(20), // max 11 items
36..=40 => Some(31), // max 12 items
41..=45 => Some(85), // max 14 items
46..=50 => Some(287), // max 16 items
51..=55 => Some(575), // max 17 items
56..=60 => Some(2807), // max 19 items
61..=65 => Some(6912), // max 20 items
66..=70 => Some(53627), // max 22 items
71..=75 => Some(610170), // max 24 items
_ => None,
},
64 => match density_pct {
0 => Some(1),
1..=5 => Some(1), // max 3 items
6..=10 => Some(2), // max 6 items
11..=15 => Some(4), // max 9 items
16..=20 => Some(8), // max 12 items
21..=25 => Some(22), // max 16 items
26..=30 => Some(58), // max 19 items
31..=35 => Some(180), // max 22 items
36..=40 => Some(686), // max 25 items
41..=45 => Some(3285), // max 28 items
46..=50 => Some(38995), // max 32 items
51..=55 => Some(343497), // max 35 items
_ => None,
},
128 => match density_pct {
0 => Some(1),
1..=5 => Some(2), // max 6 items
6..=10 => Some(4), // max 12 items
11..=15 => Some(11), // max 19 items
16..=20 => Some(36), // max 25 items
21..=25 => Some(207), // max 32 items
26..=30 => Some(1368), // max 38 items
31..=35 => Some(13426), // max 44 items
36..=40 => Some(331105), // max 51 items
_ => None,
},
_ => None,
}
}
pub fn get_bits_metadata() -> Option<($inner_type, $inner_type)> {
let table_size = Self::TOTAL_BITS;
let bits_needed = table_size.trailing_zeros() as usize;
let bit_shift_usize = table_size.checked_sub(bits_needed)?;
let bit_shift = bit_shift_usize as $inner_type;
let bit_mask = (table_size - 1) as $inner_type;
Some((bit_shift, bit_mask))
}
pub fn get_lcg_xor_mask<V>(values: &[V]) -> Option<$inner_type>
where
V: UniqueSaturatedInto<$inner_type> + Copy,
{
let table_size = Self::TOTAL_BITS;
if values.len() > table_size { return None; }
let max_iterations = Self::get_exact_iterations(values.len())?;
let (bit_shift, bit_mask) = Self::get_bits_metadata()?;
let mut lcg_rng_state: $inner_type = $init_rng;
let mut xor_key: $inner_type = lcg_rng_state;
let mut slots_taken = [false; Self::TOTAL_BITS];
for _ in 0..max_iterations {
slots_taken.fill(false);
let mut collision_found = false;
for value in values {
let slot_index = Self::get_lcg_based_slot_index(
bit_mask,
bit_shift,
xor_key,
value
);
if slot_index >= table_size || slots_taken[slot_index] {
collision_found = true;
break;
}
slots_taken[slot_index] = true;
}
if !collision_found { return Some(xor_key); }
lcg_rng_state = lcg_rng_state
.wrapping_mul($lcg_multiplier)
.wrapping_add($lcg_increment);
xor_key = lcg_rng_state;
}
None
}
#[inline(always)]
pub fn get_lcg_based_slot_index<V>(
bit_mask: $inner_type,
bit_shift: $inner_type,
xor_key: $inner_type,
value: &V
) -> usize
where
V: UniqueSaturatedInto<$inner_type> + Copy,
{
let converted_value: $inner_type = (*value).unique_saturated_into();
let knuth_hash = (converted_value ^ xor_key).wrapping_mul($golden_ratio);
let shifted_hash = knuth_hash.checked_shr(bit_shift as u32).unwrap_or(knuth_hash);
let slot_index_converted = shifted_hash & bit_mask;
slot_index_converted as usize
}
}
}
}
generate_perfect_slot_mapper!(
struct_name: PerfectSlotMapperU16,
inner_type: u16,
init_rng: 0x1234,
golden_ratio: 0x9E37, // Computed with: 2^16 * ( (sqrt(5) - 1) / 2)
lcg_multiplier: 25173, // Reference: Peter Grogono, Programming in Pascal, Section 4.5.
lcg_increment: 13849, // http://engr.case.edu/merat_francis/eeap282f97/labs/Random_Lab.pdf
);
generate_perfect_slot_mapper!(
struct_name: PerfectSlotMapperU32,
inner_type: u32,
init_rng: 0x12345678,
golden_ratio: 0x9E3779B9, // Computd with: 2^32 * ( (sqrt(5) - 1) / 2)
lcg_multiplier: 1664525, // Numerical Recipes `ranqd1`, Chapter 7.1,
lcg_increment: 1013904223, // An Even Quicker Generator, Eq. 7.1.6
);
generate_perfect_slot_mapper!(
struct_name: PerfectSlotMapperU64,
inner_type: u64,
init_rng: 0x123456789ABCDEF,
golden_ratio: 0x9E3779B97F4A7C15, // Taken from `splitmix64`, this generator is specifically used in PostgreSQL
lcg_multiplier: 6364136223846793005, // Newlib / Musl libc 64-bit LCG multiplier
lcg_increment: 1, // https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdlib/rand.c
);
generate_perfect_slot_mapper!(
struct_name: PerfectSlotMapperU128,
inner_type: u128,
init_rng: 0x123456789ABCDEF0123456789ABCDEF0,
golden_ratio: 0x9E3779B97F4A7C15F39CC0605CEDC834, // Computd with: 2^128 * ( (sqrt(5) - 1) / 2) with python
lcg_multiplier: 0x2360ED051FC65DA44385DF649FCCF645, // 2549297995355413924ULL,4865540595714422341ULL
lcg_increment: 0x5851F42D4C957F2D14057B7EF767814F, // 6364136223846793005ULL,1442695040888963407ULL
// https://github.com/imneme/pcg-cpp/blob/master/include/pcg_random.hpp
);
#[cfg(test)]
mod perfect_mapper_tests {
use super::*;
macro_rules! generate_mapper_test {
($mod_name:ident, $struct_name:ident, $init_rng:expr, $inner_type:ty) => {
mod $mod_name {
use super::*;
#[test]
fn test_standard_pack_20_percentages() {
const TABLE_SIZE: usize = $struct_name::TOTAL_BITS;
const ITEMS_COUNT: usize = (TABLE_SIZE * 20) / 100;
let mut values = [0 as $inner_type; TABLE_SIZE];
for i in 0..ITEMS_COUNT {
values[i] = ((i as $inner_type).wrapping_mul(999)) ^ 0xABC;
}
let filled_values = &values[0..ITEMS_COUNT];
let mask = $struct_name::get_lcg_xor_mask(filled_values);
assert!(mask.is_some());
let xor_key = mask.unwrap();
let bits_needed = TABLE_SIZE.trailing_zeros() as $inner_type;
let bit_mask = (TABLE_SIZE - 1) as $inner_type;
let bit_shift = (TABLE_SIZE as $inner_type) - bits_needed;
let mut slots = vec![false; TABLE_SIZE];
for val in filled_values {
let idx = $struct_name::get_lcg_based_slot_index(
bit_mask,
bit_shift,
xor_key,
val
);
assert!(idx < TABLE_SIZE);
assert!(!slots[idx]);
slots[idx] = true;
}
}
#[test]
fn test_heavy_math() {
const TABLE_SIZE: usize = $struct_name::TOTAL_BITS;
let max_val = <$inner_type>::MAX;
let one_val = 1 as $inner_type;
let mut block_pattern = 0 as $inner_type;
let mut noise_pattern = 0 as $inner_type;
let total_bytes = core::mem::size_of::<$inner_type>();
let mut i = 0;
while i < total_bytes {
let byte_val = if i % 2 == 0 { 0x55 } else { 0xAA };
noise_pattern = (noise_pattern << 8) | (byte_val as $inner_type);
let block_val = if i < total_bytes / 3 {
0xEE
} else if i < (total_bytes * 2) / 3 {
0xFF
} else {
0xAA
};
block_pattern = (block_pattern << 8) | (block_val as $inner_type);
i += 1;
}
let center_bit_shift = (TABLE_SIZE / 2) as u32;
let center_bit_pattern = (1 as $inner_type)
.checked_shl(center_bit_shift)
.unwrap_or(1);
let values: [$inner_type; 6] = [
$init_rng,
noise_pattern,
max_val,
one_val,
center_bit_pattern,
block_pattern
];
let mask = $struct_name::get_lcg_xor_mask(&values);
assert!(mask.is_some());
}
#[test]
fn test_single_element() {
const TABLE_SIZE: usize = $struct_name::TOTAL_BITS;
let single_value = [420 as $inner_type];
let mask = $struct_name::get_lcg_xor_mask(&single_value);
assert!(mask.is_some());
let xor_key = mask.unwrap();
let bits_needed = TABLE_SIZE.trailing_zeros() as $inner_type;
let bit_mask = (TABLE_SIZE - 1) as $inner_type;
let bit_shift = (TABLE_SIZE as $inner_type) - bits_needed;
let idx = $struct_name::get_lcg_based_slot_index(
bit_mask,
bit_shift,
xor_key,
&single_value[0]
);
assert!(idx < TABLE_SIZE);
}
#[test]
fn test_invalid_bounds_returns_none() {
const TABLE_SIZE: usize = $struct_name::TOTAL_BITS;
let oversized_values = [1 as $inner_type; TABLE_SIZE];
let mask = $struct_name::get_lcg_xor_mask(&oversized_values);
assert!(mask.is_none());
}
#[test]
fn test_top_25_evm_chains_by_tvl() {
const TABLE_SIZE: usize = $struct_name::TOTAL_BITS;
let evm_network_ids: [u64; 25] = [
1, // Ethereum Mainnet
8453, // Base
56, // BNB Smart Chain
42161, // Arbitrum One
10143, // Monad
137, // Polygon PoS
43114, // Avalanche C-Chain
10, // OP Mainnet
57073, // Ink
14, // Flare Network
196, // X Layer
25, // Cronos
5000, // Mantle
100, // Gnosis Chain
59144, // Linea
534352, // Scroll
324, // zkSync Era
146, // Sonic (Fantom)
1116, // Core
42220, // Celo
1088, // Metis
592, // Astar
1284, // Moonbeam
98865, // Plume Network
60808, // BOB (Build on Bitcoin)
];
let mask = $struct_name::get_lcg_xor_mask(&evm_network_ids);
if let Some(xor_key) = mask {
let mut slots_check = [false; TABLE_SIZE];
let bits_needed = TABLE_SIZE.trailing_zeros() as $inner_type;
let bit_mask = (TABLE_SIZE - 1) as $inner_type;
let bit_shift = (TABLE_SIZE as $inner_type) - bits_needed;
for chain_id in &evm_network_ids {
let slot_idx = $struct_name::get_lcg_based_slot_index(
bit_mask,
bit_shift,
xor_key,
chain_id
);
assert!(slot_idx < TABLE_SIZE);
assert!(!slots_check[slot_idx]);
slots_check[slot_idx] = true;
}
} else {
assert!(TABLE_SIZE <= 32);
}
}
#[test]
fn test_top_25_evm_testnet_chains() {
const TABLE_SIZE: usize = $struct_name::TOTAL_BITS;
let evm_network_ids: [u64; 10] = [
63, // Mordor (Ethereum Classic Testnet)
11155111, // Ethereum Sepolia
80002, // Polygon Amoy
421614, // Arbitrum Sepolia
84532, // Base Sepolia
11155420, // Optimism Sepolia
59141, // Linea Sepolia
534351, // Scroll Sepolia
80084, // Berachain Bartio
98864, // Plume Testnet
];
let mask = $struct_name::get_lcg_xor_mask(&evm_network_ids);
if let Some(xor_key) = mask {
let mut slots_check = [false; TABLE_SIZE];
let bits_needed = TABLE_SIZE.trailing_zeros() as $inner_type;
let bit_mask = (TABLE_SIZE - 1) as $inner_type;
let bit_shift = (TABLE_SIZE as $inner_type) - bits_needed;
for chain_id in &evm_network_ids {
let slot_idx = $struct_name::get_lcg_based_slot_index(
bit_mask,
bit_shift,
xor_key,
chain_id
);
assert!(slot_idx < TABLE_SIZE);
assert!(!slots_check[slot_idx]);
slots_check[slot_idx] = true;
}
} else {
assert!(TABLE_SIZE == 16);
}
}
}
}
}
generate_mapper_test!(u16_mapper, PerfectSlotMapperU16, 0x1234, u16);
generate_mapper_test!(u32_mapper, PerfectSlotMapperU32, 0x12345678, u32);
generate_mapper_test!(u64_mapper, PerfectSlotMapperU64, 0x123456789ABCDEF, u64);
generate_mapper_test!(u128_mapper, PerfectSlotMapperU128, 0x123456789ABCDEF0123456789ABCDEF0, u128);
}

View File

@ -9,7 +9,6 @@ pub mod hash_chain;
pub mod merkle_tree; pub mod merkle_tree;
pub mod networks; pub mod networks;
pub mod utxo; pub mod utxo;
pub mod lcg;
pub type AuthIndexU8 = u8; pub type AuthIndexU8 = u8;
pub type AuthIndexU16 = u16; pub type AuthIndexU16 = u16;

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-networks" name = "ghost-networks"
version = "0.2.12" 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

View File

@ -805,8 +805,6 @@ impl<T: Config> NetworkDataBasicHandler for Pallet<T> {
} }
impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> { impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
type TypesItem = BoundedVec<T::NetworkId, T::MaxNetworks>;
fn count() -> u32 { fn count() -> u32 {
NetworkIndexes::<T>::decode_len() NetworkIndexes::<T>::decode_len()
.map(|len| len as u32) .map(|len| len as u32)
@ -852,11 +850,11 @@ impl<T: Config> NetworkDataInspectHandler<NetworkData> for Pallet<T> {
fn iter_types_by_curve( fn iter_types_by_curve(
curve: &Self::NetworkCurve curve: &Self::NetworkCurve
) -> impl Iterator<Item = (Self::NetworkType, Self::TypesItem)> { ) -> impl Iterator<Item = (T::NetworkId, Self::NetworkType)> {
let network_types = NetworkTypes::<T>::get(curve); let network_types = NetworkTypes::<T>::get(curve);
network_types.into_iter().map(|(network_type, network_ids)| { network_types.into_iter().flat_map(|(network_type, network_ids)| {
(network_type, network_ids) network_ids.into_iter().map(move |network_id| (network_id, network_type))
}) })
} }
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-traits" name = "ghost-traits"
version = "0.4.9" 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

View File

@ -36,8 +36,6 @@ pub trait NetworkDataBasicHandler {
} }
pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler { pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
type TypesItem: AsRef<[Self::NetworkId]>;
fn count() -> u32; fn count() -> u32;
fn contains_key(n: &Self::NetworkId) -> bool; fn contains_key(n: &Self::NetworkId) -> bool;
fn curve_exists(c: &Self::NetworkCurve) -> bool; fn curve_exists(c: &Self::NetworkCurve) -> bool;
@ -48,7 +46,7 @@ pub trait NetworkDataInspectHandler<Network>: NetworkDataBasicHandler {
fn iter_curves() -> impl Iterator<Item = Self::NetworkCurve>; fn iter_curves() -> impl Iterator<Item = Self::NetworkCurve>;
fn iter_types_by_curve( fn iter_types_by_curve(
c: &Self::NetworkCurve c: &Self::NetworkCurve
) -> impl Iterator<Item = (Self::NetworkType, Self::TypesItem)>; ) -> impl Iterator<Item = (Self::NetworkId, Self::NetworkType)>;
} }
pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> { pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<Network> {

View File

@ -1,6 +1,6 @@
[package] [package]
name = "casper-runtime" name = "casper-runtime"
version = "4.0.15" version = "4.0.14"
build = "build.rs" build = "build.rs"
description = "Runtime of the Casper Network" description = "Runtime of the Casper Network"
edition.workspace = true edition.workspace = true
@ -75,7 +75,6 @@ ghost-networks = { workspace = true }
ghost-governance = { workspace = true } ghost-governance = { workspace = true }
ghost-weaver = { workspace = true } ghost-weaver = { workspace = true }
ghost-exodus = { workspace = true } ghost-exodus = { workspace = true }
ghost-exodus-runtime-api = { workspace = true }
ghost-sudo = { workspace = true } ghost-sudo = { workspace = true }
ghost-traits = { workspace = true } ghost-traits = { workspace = true }
ghost-helpers = { workspace = true } ghost-helpers = { workspace = true }
@ -189,7 +188,6 @@ std = [
"ghost-governance/std", "ghost-governance/std",
"ghost-weaver/std", "ghost-weaver/std",
"ghost-exodus/std", "ghost-exodus/std",
"ghost-exodus-runtime-api/std",
"ghost-sudo/std", "ghost-sudo/std",
"casper-runtime-constants/std", "casper-runtime-constants/std",
"runtime-common/std", "runtime-common/std",

View File

@ -69,7 +69,6 @@ pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall; pub use pallet_balances::Call as BalancesCall;
pub use pallet_election_provider_multi_phase::{Call as EPMCall, GeometricDepositBase}; pub use pallet_election_provider_multi_phase::{Call as EPMCall, GeometricDepositBase};
use ghost_helpers::networks::{NetworkCurve, NetworkType};
use ghost_weaver::sr25519::AuthorityId as GhostWeaverId; use ghost_weaver::sr25519::AuthorityId as GhostWeaverId;
use ghost_exodus::sr25519::AuthorityId as GhostExodusId; use ghost_exodus::sr25519::AuthorityId as GhostExodusId;
@ -124,7 +123,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("casper"), spec_name: create_runtime_str!("casper"),
impl_name: create_runtime_str!("casper-svengali"), impl_name: create_runtime_str!("casper-svengali"),
authoring_version: 0, authoring_version: 0,
spec_version: 8, spec_version: 7,
impl_version: 0, impl_version: 0,
apis: RUNTIME_API_VERSIONS, apis: RUNTIME_API_VERSIONS,
transaction_version: 1, transaction_version: 1,
@ -907,7 +906,6 @@ parameter_types! {
pub ExodusUnsignedPriority: TransactionPriority = pub ExodusUnsignedPriority: TransactionPriority =
Perbill::from_percent(90) * TransactionPriority::MAX; Perbill::from_percent(90) * TransactionPriority::MAX;
pub MaxExodusRequestCount: u32 = 32;
pub MaxAuthoritiesChunks: u32 = 32; pub MaxAuthoritiesChunks: u32 = 32;
pub WeavingDelay: u64 = 50; pub WeavingDelay: u64 = 50;
pub AttestationDelay: u64 = 25; pub AttestationDelay: u64 = 25;
@ -951,7 +949,6 @@ impl ghost_exodus::Config for Runtime {
type UnsignedPriority = ExodusUnsignedPriority; type UnsignedPriority = ExodusUnsignedPriority;
type MaxAuthorities = MaxActiveValidators; type MaxAuthorities = MaxActiveValidators;
type MaxAuthoritiesChunks = MaxAuthoritiesChunks; type MaxAuthoritiesChunks = MaxAuthoritiesChunks;
type MaxExodusRequestCount = MaxExodusRequestCount;
type DkgRoundPeriod = ExodusDkgRoundPeriod; type DkgRoundPeriod = ExodusDkgRoundPeriod;
type RemovalLimit = ExodusRemovalLimit; type RemovalLimit = ExodusRemovalLimit;
@ -1159,39 +1156,6 @@ sp_api::impl_runtime_apis! {
} }
} }
impl ghost_exodus_runtime_api::ExodusApi<Block> for Runtime {
fn get_evm_rotation_metadata(
dkg_index: u64,
network_type: NetworkType,
) -> ghost_exodus_runtime_api::PreparedEvmMessage {
GhostExodus::api_get_evm_rotation(dkg_index, network_type)
}
fn get_evm_bridge_metadata(
dkg_index: u64,
network_id: u64,
session: u64,
) -> ghost_exodus_runtime_api::PreparedEvmMessage {
GhostExodus::api_get_evm_bridge(dkg_index, network_id, session)
}
fn get_evm_governance_metadata(
dkg_index: u64,
network_id: u64,
session: u64,
) -> ghost_exodus_runtime_api::PreparedEvmMessage {
GhostExodus::api_get_evm_governance(dkg_index, network_id, session)
}
fn pending_exodus_request_count() -> u32 {
GhostExodus::api_pending_exodus_request_count()
}
fn is_qualification_ongoing(network_curve: NetworkCurve) -> bool {
GhostExodus::api_is_qualification_ongoing(network_curve)
}
}
impl pallet_staking_runtime_api::StakingApi<Block, Balance, AccountId> for Runtime { impl pallet_staking_runtime_api::StakingApi<Block, Balance, AccountId> for Runtime {
fn nominations_quota(balance: Balance) -> u32 { fn nominations_quota(balance: Balance) -> u32 {
Staking::api_nominations_quota(balance) Staking::api_nominations_quota(balance)