slightly optimize bridge in/out logic; make variable names more self descriptive; fix benchmarking for governance

Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
Uncle Stinky 2026-09-02 02:59:26 +03:00
parent e104a49e53
commit e694489f75
Signed by: st1nky
GPG Key ID: 016064BD97603B40
18 changed files with 359 additions and 870 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-exodus" name = "ghost-exodus"
version = "0.0.1" version = "0.0.2"
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
@ -105,4 +105,4 @@ try-runtime = [
"pallet-session/try-runtime", "pallet-session/try-runtime",
"frame-executive/try-runtime", "frame-executive/try-runtime",
"ghost-networks/try-runtime", "ghost-networks/try-runtime",
] ]

View File

@ -497,7 +497,7 @@ pub mod pallet {
who: T::AccountId, who: T::AccountId,
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,
amount: BalanceOf<T>, amount: BalanceOf<T>,
commission: Perbill, bounty: Perbill,
receiver: EvmAddress, receiver: EvmAddress,
} }
} }
@ -1843,7 +1843,7 @@ pub mod pallet {
origin: OriginFor<T>, origin: OriginFor<T>,
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,
amount: BalanceOf<T>, amount: BalanceOf<T>,
commission: Perbill, bounty: Perbill,
receiver: EvmAddress, receiver: EvmAddress,
) -> DispatchResult { ) -> DispatchResult {
let who = ensure_signed(origin)?; let who = ensure_signed(origin)?;
@ -1858,7 +1858,7 @@ pub mod pallet {
Self::do_register_evm_bridge_out_exodus( Self::do_register_evm_bridge_out_exodus(
network_id, network_id,
amount, amount,
commission, bounty,
receiver, receiver,
)?; )?;
@ -1866,7 +1866,7 @@ pub mod pallet {
who, who,
network_id, network_id,
amount, amount,
commission, bounty,
receiver, receiver,
}); });
@ -2138,7 +2138,7 @@ impl<T: Config> Pallet<T> {
fn do_register_evm_bridge_out_exodus( fn do_register_evm_bridge_out_exodus(
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,
amount: BalanceOf<T>, amount: BalanceOf<T>,
commission: Perbill, bounty: Perbill,
receiver: EvmAddress, receiver: EvmAddress,
) -> DispatchResult { ) -> DispatchResult {
let network = T::NetworkDataHandler::get(&network_id) let network = T::NetworkDataHandler::get(&network_id)
@ -2156,7 +2156,7 @@ impl<T: Config> Pallet<T> {
exodus_session, exodus_session,
network_id, network_id,
amount, amount,
commission, bounty,
receiver receiver
); );

View File

@ -120,7 +120,7 @@ pub enum ExodusRequestType<NetworkId, Balance> {
exodus_session: ExodusSession, exodus_session: ExodusSession,
network_id: NetworkId, network_id: NetworkId,
amount: Balance, amount: Balance,
commission: Perbill, bounty: Perbill,
receiver: EvmAddress, receiver: EvmAddress,
}, },
EvmGovernance { network_id: NetworkId }, EvmGovernance { network_id: NetworkId },
@ -144,22 +144,22 @@ where
[exodus_session, public_key, parity] [exodus_session, public_key, parity]
) )
}, },
ExodusRequestType::EvmBridgeOut { exodus_session, network_id, amount, commission, receiver } => { ExodusRequestType::EvmBridgeOut { exodus_session, network_id, 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 = (*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_commission = multiply_by_rational_with_rounding( let scaled_bounty = multiply_by_rational_with_rounding(
commission.deconstruct() as u128, bounty.deconstruct() as u128,
1u128 << 32, 1u128 << 32,
1_000_000_000, 1_000_000_000,
sp_runtime::Rounding::Down sp_runtime::Rounding::Down
)?; )?;
let commission_uint32 = scaled_commission as u32; let bounty_uint32 = scaled_bounty as u32;
buffer[28..32].copy_from_slice(&commission_uint32.to_be_bytes()); buffer[28..32].copy_from_slice(&bounty_uint32.to_be_bytes());
let mut amount_buffer = [0u8; 32]; let mut amount_buffer = [0u8; 32];
let amount_u128: u128 = (*amount).unique_saturated_into(); let amount_u128: u128 = (*amount).unique_saturated_into();
@ -208,14 +208,14 @@ where
exodus_session: ExodusSession, exodus_session: ExodusSession,
network_id: NetworkId, network_id: NetworkId,
amount: Balance, amount: Balance,
commission: Perbill, bounty: Perbill,
receiver: EvmAddress, receiver: EvmAddress,
) -> Self { ) -> Self {
let evm_bridge_out = ExodusRequestType::EvmBridgeOut { let evm_bridge_out = ExodusRequestType::EvmBridgeOut {
exodus_session, exodus_session,
network_id, network_id,
amount, amount,
commission, bounty,
receiver, receiver,
}; };
Self::default_request_for(evm_bridge_out) Self::default_request_for(evm_bridge_out)

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-governance" name = "ghost-governance"
version = "0.3.1" version = "0.3.2"
description = "Full-chain and cross-chain governance pallet with early adopter share claims" description = "Full-chain and cross-chain governance pallet with early adopter share claims"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -2,20 +2,20 @@
use super::*; use super::*;
use frame_benchmarking::v2::*; use frame_benchmarking::v2::*;
use frame_support::dispatch::RawOrigin; use frame_support::dispatch::RawOrigin;
use ghost_helpers::merkle_tree::{generate_tree, generate_proof};
#[benchmarks(where T: Config)] #[benchmarks(where T: Config)]
mod benchmarks { mod benchmarks {
use super::*; use super::*;
#[benchmark] #[benchmark]
fn claim() { fn claim(
p: Linear<1, { T::MaxProofDepth::get() }>
) -> Result<(), BenchmarkError> {
let network_id = Default::default(); let network_id = Default::default();
let current_account: T::AccountId = frame_benchmarking::whitelisted_caller(); let current_account: T::AccountId = frame_benchmarking::whitelisted_caller();
let max_proof_depth = p;
let max_proof_depth = <<T as Config>::MaxProofDepth as Get<u32>>::get();
let minimum_donation_u128 = <<T as Config>::MinimumDonation as Get<u128>>::get(); let minimum_donation_u128 = <<T as Config>::MinimumDonation as Get<u128>>::get();
let minimum_donation: BalanceOf<T> = minimum_donation_u128.unique_saturated_into(); let minimum_donation: BalanceOf<T> = minimum_donation_u128.unique_saturated_into();
@ -31,32 +31,45 @@ mod benchmarks {
evm_addr_bytes.copy_from_slice(&pubkey_hash.as_ref()[12..32]); evm_addr_bytes.copy_from_slice(&pubkey_hash.as_ref()[12..32]);
let dummy_evm_address = EvmAddress::from(evm_addr_bytes); let dummy_evm_address = EvmAddress::from(evm_addr_bytes);
let total_entries = 1u64 << max_proof_depth; let target_index = 0u32;
let max_index = total_entries - 1; let claim_package_init = ClaimPackage {
let raw_values = (0..total_entries) shares: dummy_shares,
.map(|i| i as TokenId) merkle_proof: Default::default(),
.collect::<Vec<TokenId>>(); token_id: 0,
index: target_index,
};
let merkle_tree = generate_tree::<SubstrateKeccakHasher, _, _, _, _>( let preimage_init = claim_package_init.get_preimage(&dummy_evm_address, network_id);
max_index, let mut current_hash = SubstrateKeccakHasher::hash(&preimage_init);
raw_values,
|index: TokenId| -> Result<(usize, Vec<u8>), ()> {
let claim_package = ClaimPackage {
shares: dummy_shares,
merkle_proof: Default::default(),
token_id: index,
index: index as u32,
};
let claim_preimage = claim_package.get_preimage( let mut proof_hashes = Vec::with_capacity(max_proof_depth as usize);
&dummy_evm_address, let mut current_index = target_index as usize;
network_id,
); let hash_len = SubstrateKeccakHasher::hash_len();
Ok((index as usize, claim_preimage.to_vec())) let mut combined = sp_std::vec![0u8; hash_len * 2];
for i in 0..max_proof_depth {
let mut sibling_bytes = [0u8; 32];
sibling_bytes[24..32].copy_from_slice(&(i as u64).to_be_bytes());
let sibling_hash = EvmHash::from_slice(&sibling_bytes);
proof_hashes.push(sibling_hash);
let sibling_bytes_ref = sibling_hash.as_ref();
let hash_bytes = current_hash.as_ref();
if current_index % 2 == 0 {
combined[..hash_len].copy_from_slice(hash_bytes);
combined[hash_len..].copy_from_slice(sibling_bytes_ref);
} else {
combined[..hash_len].copy_from_slice(sibling_bytes_ref);
combined[hash_len..].copy_from_slice(hash_bytes);
} }
).unwrap();
let merkle_root = *merkle_tree.last().unwrap(); current_hash = SubstrateKeccakHasher::hash(&combined);
current_index >>= 1;
}
let merkle_root = current_hash;
let member_share = MemberShare { let member_share = MemberShare {
initiated_network: None, initiated_network: None,
@ -75,15 +88,9 @@ mod benchmarks {
let global_state = ShareState::new(dummy_shares); let global_state = ShareState::new(dummy_shares);
GlobalShares::<T>::put(global_state); GlobalShares::<T>::put(global_state);
let merkle_proof = generate_proof::<SubstrateKeccakHasher, _>(
&merkle_tree,
total_entries - 1,
0,
);
let claim_package = ClaimPackage { let claim_package = ClaimPackage {
index: 0, index: 0,
merkle_proof: BoundedVec::try_from(merkle_proof).unwrap(), merkle_proof: BoundedVec::try_from(proof_hashes).unwrap(),
shares: dummy_shares, shares: dummy_shares,
token_id: 0 token_id: 0
}; };
@ -130,6 +137,8 @@ mod benchmarks {
dummy_shares, dummy_shares,
NetworkShares::<T>::get(&network_id).claimed_shares(), NetworkShares::<T>::get(&network_id).claimed_shares(),
); );
Ok(())
} }
impl_benchmark_test_suite!( impl_benchmark_test_suite!(

View File

@ -308,7 +308,9 @@ pub mod pallet {
#[pallet::call] #[pallet::call]
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
#[pallet::call_index(0)] #[pallet::call_index(0)]
#[pallet::weight(<T as Config>::WeightInfo::claim())] #[pallet::weight(<T as Config>::WeightInfo::claim(
claim_package.merkle_proof.len() as u32,
))]
pub fn claim( pub fn claim(
origin: OriginFor<T>, origin: OriginFor<T>,
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,

View File

@ -41,14 +41,14 @@
#![allow(missing_docs)] #![allow(missing_docs)]
use frame_support::{ use frame_support::{
traits::Get, traits::Get,
weights::{Weight, constants::RocksDbWeight}, weights::{Weight, constants::RocksDbWeight},
}; };
use core::marker::PhantomData; use core::marker::PhantomData;
/// Weight functions needed for `ghost_claims`. /// Weight functions needed for `ghost_claims`.
pub trait WeightInfo { pub trait WeightInfo {
fn claim() -> Weight; fn claim(p: u32) -> Weight;
} }
impl WeightInfo for () { impl WeightInfo for () {
@ -64,7 +64,7 @@ impl WeightInfo for () {
/// Proof: `CultCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) /// Proof: `CultCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
/// Storage: `CultCollective::IndexToId` (r:0 w:6) /// Storage: `CultCollective::IndexToId` (r:0 w:6)
/// Proof: `CultCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`) /// Proof: `CultCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
fn claim() -> Weight { fn claim(_p: u32) -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `896` // Measured: `896`
// Estimated: `16164` // Estimated: `16164`

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-helpers" name = "ghost-helpers"
version = "0.0.5" version = "0.0.6"
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
@ -40,4 +40,4 @@ std = [
"sp-io/std", "sp-io/std",
"sp-core/std", "sp-core/std",
] ]
runtime-benchmarks = [] runtime-benchmarks = []

View File

@ -223,8 +223,8 @@ pub struct NetworkData {
pub rate_limit_delay: u64, pub rate_limit_delay: u64,
pub block_deviation: u64, pub block_deviation: u64,
pub incoming_fee: u32, pub incoming_share: u32,
pub outgoing_fee: u32, pub outgoing_share: u32,
} }
#[derive(Default)] #[derive(Default)]
@ -240,8 +240,8 @@ pub struct NetworkDataBuilder {
pub rate_limit_delay: u64, pub rate_limit_delay: u64,
pub block_deviation: u64, pub block_deviation: u64,
pub incoming_fee: u32, pub incoming_share: u32,
pub outgoing_fee: u32, pub outgoing_share: u32,
} }
impl NetworkDataBuilder { impl NetworkDataBuilder {
@ -280,13 +280,13 @@ impl NetworkDataBuilder {
self self
} }
pub fn with_incoming_fee(mut self, incoming_fee: u32) -> Self { pub fn with_incoming_share(mut self, incoming_share: u32) -> Self {
self.incoming_fee = incoming_fee; self.incoming_share = incoming_share;
self self
} }
pub fn with_outgoing_fee(mut self, outgoing_fee: u32) -> Self { pub fn with_outgoing_share(mut self, outgoing_share: u32) -> Self {
self.outgoing_fee = outgoing_fee; self.outgoing_share = outgoing_share;
self self
} }
@ -328,8 +328,8 @@ impl NetworkDataBuilder {
rate_limit_delay: self.rate_limit_delay, rate_limit_delay: self.rate_limit_delay,
block_deviation: self.block_deviation, block_deviation: self.block_deviation,
incoming_fee: self.incoming_fee, incoming_share: self.incoming_share,
outgoing_fee: self.outgoing_fee, outgoing_share: self.outgoing_share,
} }
} }
} }

View File

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

@ -42,8 +42,8 @@ fn prepare_network<T: Config>(
.with_rate_limit_delay(6) .with_rate_limit_delay(6)
.with_finality_delay(69) .with_finality_delay(69)
.with_block_deviation(420) .with_block_deviation(420)
.with_incoming_fee(0) .with_incoming_share(0)
.with_outgoing_fee(0) .with_outgoing_share(0)
.build(); .build();
(chain_id, network) (chain_id, network)
@ -204,27 +204,27 @@ benchmarks! {
assert_ne!(GhostNetworks::<T>::networks(chain_id), prev_network); assert_ne!(GhostNetworks::<T>::networks(chain_id), prev_network);
} }
update_incoming_network_fee { update_incoming_network_share {
let incoming_fee = 1337; let incoming_share = 1337;
let (chain_id, network) = prepare_network::<T>(1, 1, 1); let (chain_id, network) = prepare_network::<T>(1, 1, 1);
let authority = T::UpdateOrigin::try_successful_origin() let authority = T::UpdateOrigin::try_successful_origin()
.map_err(|_| BenchmarkError::Weightless)?; .map_err(|_| BenchmarkError::Weightless)?;
let prev_network = create_network::<T>(chain_id, network)?; let prev_network = create_network::<T>(chain_id, network)?;
}: _<T::RuntimeOrigin>(authority, chain_id, incoming_fee) }: _<T::RuntimeOrigin>(authority, chain_id, incoming_share)
verify { verify {
assert_last_event::<T>(Event::NetworkIncomingFeeUpdated { chain_id, incoming_fee }.into()); assert_last_event::<T>(Event::NetworkIncomingShareUpdated { chain_id, incoming_share }.into());
assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network); assert_ne!(GhostNetworks::<T>::networks(chain_id.clone()), prev_network);
} }
update_outgoing_network_fee { update_outgoing_network_share {
let outgoing_fee = 1337; let outgoing_share = 1337;
let (chain_id, network) = prepare_network::<T>(1, 1, 1); let (chain_id, network) = prepare_network::<T>(1, 1, 1);
let authority = T::UpdateOrigin::try_successful_origin() let authority = T::UpdateOrigin::try_successful_origin()
.map_err(|_| BenchmarkError::Weightless)?; .map_err(|_| BenchmarkError::Weightless)?;
let prev_network = create_network::<T>(chain_id, network)?; let prev_network = create_network::<T>(chain_id, network)?;
}: _<T::RuntimeOrigin>(authority, chain_id, outgoing_fee) }: _<T::RuntimeOrigin>(authority, chain_id, outgoing_share)
verify { verify {
assert_last_event::<T>(Event::NetworkOutgoingFeeUpdated { chain_id, outgoing_fee }.into()); assert_last_event::<T>(Event::NetworkOutgoingShareUpdated { chain_id, outgoing_share }.into());
assert_ne!(GhostNetworks::<T>::networks(chain_id), prev_network); assert_ne!(GhostNetworks::<T>::networks(chain_id), prev_network);
} }

View File

@ -1,6 +1,4 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::large_enum_variant)]
#![allow(clippy::too_many_arguments)]
use frame_support::{ use frame_support::{
pallet_prelude::*, pallet_prelude::*,
@ -12,8 +10,11 @@ use scale_info::TypeInfo;
use sp_runtime::{ use sp_runtime::{
curve::PiecewiseLinear, curve::PiecewiseLinear,
traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Member, UniqueSaturatedInto}, traits::{
DispatchResult, AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Member,
Saturating, UniqueSaturatedInto,
},
DispatchResult, Perbill,
}; };
use sp_std::{convert::TryInto, prelude::*}; use sp_std::{convert::TryInto, prelude::*};
@ -42,9 +43,10 @@ pub type BalanceOf<T> =
<<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance; <<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
#[derive(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] #[derive(Default, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct BridgeAdjustment<Balance> { pub struct NetworkImbalanceState<Balance> {
pub bridged_out: Balance, pub outgoing: Balance,
pub bridged_in: Balance, pub incoming: Balance,
pub curve_share: Balance,
} }
pub struct BridgedInflationCurve<RewardCurve, T>(core::marker::PhantomData<(RewardCurve, T)>); pub struct BridgedInflationCurve<RewardCurve, T>(core::marker::PhantomData<(RewardCurve, T)>);
@ -71,16 +73,18 @@ where
_era_duration_in_millis: u64, _era_duration_in_millis: u64,
) -> (Balance, Balance) { ) -> (Balance, Balance) {
let reward_curve = RewardCurve::get(); let reward_curve = RewardCurve::get();
let bridged_imbalance = BridgedImbalance::<T>::take(); let state = NetworkImbalance::<T>::take();
let accumulated_commission = AccumulatedCommission::<T>::take();
let accumulated_commission: Balance = accumulated_commission.into(); let accumulated_commission: Balance = state.curve_share.into();
let adjusted_issuance: Balance = total_issuance let adjusted_issuance: Balance = total_issuance
.saturating_add(bridged_imbalance.bridged_out.into()) .saturating_add(state.outgoing.into())
.saturating_sub(bridged_imbalance.bridged_in.into()); .saturating_sub(state.incoming.into());
let estimated_reward = let estimated_reward =
reward_curve.calculate_for_fraction_times_denominator(total_staked, adjusted_issuance); reward_curve.calculate_for_fraction_times_denominator(
total_staked,
adjusted_issuance,
);
let payout: Balance = sp_runtime::helpers_128bit::multiply_by_rational_with_rounding( let payout: Balance = sp_runtime::helpers_128bit::multiply_by_rational_with_rounding(
estimated_reward.unique_saturated_into(), estimated_reward.unique_saturated_into(),
@ -172,20 +176,19 @@ pub mod module {
NetworkTypeUpdated { chain_id: T::NetworkId, network_type: NetworkType }, NetworkTypeUpdated { chain_id: T::NetworkId, network_type: NetworkType },
NetworkCurveUpdated { chain_id: T::NetworkId, network_curve: NetworkCurve }, NetworkCurveUpdated { chain_id: T::NetworkId, network_curve: NetworkCurve },
NetworkGatekeeperUpdated { chain_id: T::NetworkId }, NetworkGatekeeperUpdated { chain_id: T::NetworkId },
NetworkIncomingFeeUpdated { chain_id: T::NetworkId, incoming_fee: u32 }, NetworkIncomingShareUpdated { chain_id: T::NetworkId, incoming_share: u32 },
NetworkOutgoingFeeUpdated { chain_id: T::NetworkId, outgoing_fee: u32 }, NetworkOutgoingShareUpdated { chain_id: T::NetworkId, outgoing_share: u32 },
NetworkAvgBlockSpeedUpdated { chain_id: T::NetworkId, avg_block_speed: u64 }, NetworkAvgBlockSpeedUpdated { chain_id: T::NetworkId, avg_block_speed: u64 },
NetworkRemoved { chain_id: T::NetworkId }, NetworkRemoved { chain_id: T::NetworkId },
} }
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn bridged_imbalance)] #[pallet::getter(fn network_imbalance)]
pub type BridgedImbalance<T: Config> = pub type NetworkImbalance<T: Config> = StorageValue<
StorageValue<_, BridgeAdjustment<BalanceOf<T>>, ValueQuery>; _,
NetworkImbalanceState<BalanceOf<T>>,
#[pallet::storage] ValueQuery,
#[pallet::getter(fn accumulated_commission)] >;
pub type AccumulatedCommission<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn network_indexes)] #[pallet::getter(fn network_indexes)]
@ -216,8 +219,8 @@ pub mod module {
>; >;
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn gatekeeper_amount)] #[pallet::getter(fn gatekeeper_amounts)]
pub type GatekeeperAmount<T: Config> = pub type GatekeeperAmounts<T: Config> =
StorageMap<_, Twox64Concat, T::NetworkId, BalanceOf<T>, ValueQuery>; StorageMap<_, Twox64Concat, T::NetworkId, BalanceOf<T>, ValueQuery>;
#[pallet::genesis_config] #[pallet::genesis_config]
@ -239,7 +242,7 @@ pub mod module {
.for_each(|network| { .for_each(|network| {
Pallet::<T>::do_register_network(network.id, network.data.clone()) Pallet::<T>::do_register_network(network.id, network.data.clone())
.expect("Error registering network"); .expect("Error registering network");
GatekeeperAmount::<T>::insert(network.id, network.amount); GatekeeperAmounts::<T>::insert(network.id, network.amount);
}); });
} }
@ -366,25 +369,25 @@ pub mod module {
} }
#[pallet::call_index(9)] #[pallet::call_index(9)]
#[pallet::weight(T::WeightInfo::update_incoming_network_fee())] #[pallet::weight(T::WeightInfo::update_incoming_network_share())]
pub fn update_incoming_network_fee( pub fn update_incoming_network_share(
origin: OriginFor<T>, origin: OriginFor<T>,
chain_id: T::NetworkId, chain_id: T::NetworkId,
incoming_fee: u32, incoming_share: u32,
) -> DispatchResult { ) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?; T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_incoming_network_fee(chain_id, incoming_fee) Self::do_update_incoming_network_share(chain_id, incoming_share)
} }
#[pallet::call_index(10)] #[pallet::call_index(10)]
#[pallet::weight(T::WeightInfo::update_outgoing_network_fee())] #[pallet::weight(T::WeightInfo::update_outgoing_network_share())]
pub fn update_outgoing_network_fee( pub fn update_outgoing_network_share(
origin: OriginFor<T>, origin: OriginFor<T>,
chain_id: T::NetworkId, chain_id: T::NetworkId,
outgoing_fee: u32, outgoing_share: u32,
) -> DispatchResult { ) -> DispatchResult {
T::UpdateOrigin::ensure_origin_or_root(origin)?; T::UpdateOrigin::ensure_origin_or_root(origin)?;
Self::do_update_outgoing_network_fee(chain_id, outgoing_fee) Self::do_update_outgoing_network_share(chain_id, outgoing_share)
} }
#[pallet::call_index(11)] #[pallet::call_index(11)]
@ -688,38 +691,38 @@ impl<T: Config> Pallet<T> {
Ok(()) Ok(())
} }
pub fn do_update_incoming_network_fee( pub fn do_update_incoming_network_share(
chain_id: T::NetworkId, chain_id: T::NetworkId,
incoming_fee: u32, incoming_share: u32,
) -> DispatchResult { ) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult { Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist); ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap(); let net = maybe_network.as_mut().unwrap();
net.incoming_fee = incoming_fee; net.incoming_share = incoming_share;
*maybe_network = Some(net.clone()); *maybe_network = Some(net.clone());
Ok(()) Ok(())
})?; })?;
Self::deposit_event(Event::<T>::NetworkIncomingFeeUpdated { Self::deposit_event(Event::<T>::NetworkIncomingShareUpdated {
chain_id, chain_id,
incoming_fee, incoming_share,
}); });
Ok(()) Ok(())
} }
pub fn do_update_outgoing_network_fee( pub fn do_update_outgoing_network_share(
chain_id: T::NetworkId, chain_id: T::NetworkId,
outgoing_fee: u32, outgoing_share: u32,
) -> DispatchResult { ) -> DispatchResult {
Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult { Networks::<T>::try_mutate(&chain_id, |maybe_network| -> DispatchResult {
ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist); ensure!(maybe_network.is_some(), Error::<T>::NetworkDoesNotExist);
let net = maybe_network.as_mut().unwrap(); let net = maybe_network.as_mut().unwrap();
net.outgoing_fee = outgoing_fee; net.outgoing_share = outgoing_share;
*maybe_network = Some(net.clone()); *maybe_network = Some(net.clone());
Ok(()) Ok(())
})?; })?;
Self::deposit_event(Event::<T>::NetworkOutgoingFeeUpdated { Self::deposit_event(Event::<T>::NetworkOutgoingShareUpdated {
chain_id, chain_id,
outgoing_fee, outgoing_share,
}); });
Ok(()) Ok(())
} }
@ -793,79 +796,61 @@ impl<T: Config> NetworkDataMutateHandler<NetworkData, BalanceOf<T>> for Pallet<T
Self::do_remove_network(chain_id) Self::do_remove_network(chain_id)
} }
fn increase_gatekeeper_amount( fn register_incoming(
network_id: &T::NetworkId, network_id: &T::NetworkId,
amount: &BalanceOf<T>, amount: BalanceOf<T>,
) -> Result<BalanceOf<T>, ()> { ) -> Result<BalanceOf<T>, ()> {
let new_gatekeeper_amount = let incoming_share = Networks::<T>::get(&network_id)
GatekeeperAmount::<T>::mutate(network_id, |gatekeeper_amount| match gatekeeper_amount .map(|network| network.incoming_share)
.checked_add(amount) .ok_or(())?;
{
Some(value) => {
*gatekeeper_amount = value;
Ok(value)
}
None => Err(()),
})?;
Ok(new_gatekeeper_amount) GatekeeperAmounts::<T>::try_mutate(network_id, |gatekeeper_amount| -> Result<(), ()> {
} *gatekeeper_amount = gatekeeper_amount.checked_add(&amount).ok_or(())?;
Ok(())
fn decrease_gatekeeper_amount(
network_id: &T::NetworkId,
amount: &BalanceOf<T>,
) -> Result<BalanceOf<T>, ()> {
let new_gatekeeper_amount =
GatekeeperAmount::<T>::mutate(network_id, |gatekeeper_amount| match gatekeeper_amount
.checked_sub(amount)
{
Some(value) => {
*gatekeeper_amount = value;
Ok(value)
}
None => Err(()),
})?;
Ok(new_gatekeeper_amount)
}
fn accumulate_outgoing_imbalance(amount: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> {
let new_bridged_out_amount = BridgedImbalance::<T>::mutate(|bridged_imbalance| {
match bridged_imbalance.bridged_out.checked_add(amount) {
Some(value) => {
(*bridged_imbalance).bridged_out = value;
Ok(value)
}
None => Err(()),
}
})?; })?;
Ok(new_bridged_out_amount) let curve_share = Perbill::from_parts(incoming_share).mul_ceil(amount);
} let final_amount = amount.saturating_sub(curve_share);
fn accumulate_incoming_imbalance(amount: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> { NetworkImbalance::<T>::try_mutate(|imbalance_state| -> Result<(), ()> {
let new_bridged_in_amount = BridgedImbalance::<T>::mutate(|bridged_imbalance| { imbalance_state.incoming = imbalance_state.incoming
match bridged_imbalance.bridged_in.checked_add(amount) { .checked_add(&final_amount)
Some(value) => { .ok_or(())?;
(*bridged_imbalance).bridged_in = value; imbalance_state.curve_share = imbalance_state.curve_share
Ok(value) .checked_add(&curve_share)
} .ok_or(())?;
None => Err(()), Ok(())
}
})?; })?;
Ok(new_bridged_in_amount) Ok(final_amount)
} }
fn accumulate_commission(commission: &BalanceOf<T>) -> Result<BalanceOf<T>, ()> { fn register_outgoing(
AccumulatedCommission::<T>::mutate(|accumulated| { network_id: &T::NetworkId,
match accumulated.checked_add(commission) { amount: BalanceOf<T>
Some(value) => { ) -> Result<BalanceOf<T>, ()> {
*accumulated = value; let outgoing_share = Networks::<T>::get(&network_id)
Ok(value) .map(|network| network.outgoing_share)
} .ok_or(())?;
None => Err(()),
} GatekeeperAmounts::<T>::try_mutate(network_id, |gatekeeper_amount| -> Result<(), ()> {
}) *gatekeeper_amount = gatekeeper_amount.checked_sub(&amount).ok_or(())?;
Ok(())
})?;
let curve_share = Perbill::from_parts(outgoing_share).mul_ceil(amount);
let final_amount = amount.saturating_sub(curve_share);
NetworkImbalance::<T>::try_mutate(|imbalance_state| -> Result<(), ()> {
imbalance_state.outgoing = imbalance_state.outgoing
.checked_add(&final_amount)
.ok_or(())?;
imbalance_state.curve_share = imbalance_state.curve_share
.checked_add(&curve_share)
.ok_or(())?;
Ok(())
})?;
Ok(final_amount)
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -58,8 +58,8 @@ pub trait WeightInfo {
fn update_network_curve() -> Weight; fn update_network_curve() -> Weight;
fn update_network_gatekeeper() -> Weight; fn update_network_gatekeeper() -> Weight;
fn update_network_topic_name() -> Weight; fn update_network_topic_name() -> Weight;
fn update_incoming_network_fee() -> Weight; fn update_incoming_network_share() -> Weight;
fn update_outgoing_network_fee() -> Weight; fn update_outgoing_network_share() -> Weight;
fn update_avg_block_speed() -> Weight; fn update_avg_block_speed() -> Weight;
fn remove_network() -> Weight; fn remove_network() -> Weight;
} }
@ -191,7 +191,7 @@ impl WeightInfo for () {
} }
/// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_incoming_network_fee() -> Weight { fn update_incoming_network_share() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `339` // Measured: `339`
// Estimated: `3804` // Estimated: `3804`
@ -203,7 +203,7 @@ impl WeightInfo for () {
} }
/// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_outgoing_network_fee() -> Weight { fn update_outgoing_network_share() -> Weight {
// Proof Size summary in bytes: // Proof Size summary in bytes:
// Measured: `339` // Measured: `339`
// Estimated: `3804` // Estimated: `3804`

View File

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

@ -47,18 +47,8 @@ pub trait NetworkDataMutateHandler<Network, Balance>: NetworkDataInspectHandler<
fn register(chain_id: Self::NetworkId, network: Network) -> DispatchResult; fn register(chain_id: Self::NetworkId, network: Network) -> DispatchResult;
fn remove(chain_id: Self::NetworkId) -> DispatchResult; fn remove(chain_id: Self::NetworkId) -> DispatchResult;
fn increase_gatekeeper_amount( fn register_incoming(chain_id: &Self::NetworkId, amount: Balance) -> Result<Balance, ()>;
chain_id: &Self::NetworkId, fn register_outgoing(chain_id: &Self::NetworkId, amount: Balance) -> Result<Balance, ()>;
amount: &Balance,
) -> Result<Balance, ()>;
fn decrease_gatekeeper_amount(
chain_id: &Self::NetworkId,
amount: &Balance,
) -> Result<Balance, ()>;
fn accumulate_outgoing_imbalance(amount: &Balance) -> Result<Balance, ()>;
fn accumulate_incoming_imbalance(amount: &Balance) -> Result<Balance, ()>;
fn accumulate_commission(commission: &Balance) -> Result<Balance, ()>;
} }
pub trait NetworkRpcResolver<W, B, H, I, S> { pub trait NetworkRpcResolver<W, B, H, I, S> {

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-weaver" name = "ghost-weaver"
version = "0.0.1" version = "0.0.2"
description = "Weaving a secure cryptographic tapestry across different external chains." description = "Weaving a secure cryptographic tapestry across different external chains."
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true
@ -76,4 +76,4 @@ try-runtime = [
"frame-system/try-runtime", "frame-system/try-runtime",
"ghost-networks/try-runtime", "ghost-networks/try-runtime",
"pallet-balances/try-runtime", "pallet-balances/try-runtime",
] ]

View File

@ -19,8 +19,8 @@ use sp_runtime::{
storage::StorageValueRef, storage::StorageValueRef,
storage_lock::{StorageLock, Time}, storage_lock::{StorageLock, Time},
}, },
traits::{BlockNumberProvider, Saturating, UniqueSaturatedInto}, traits::{BlockNumberProvider, UniqueSaturatedInto},
Perbill, RuntimeAppPublic, RuntimeAppPublic,
}; };
use ghost_helpers::{ use ghost_helpers::{
@ -179,9 +179,7 @@ pub mod pallet {
ThreadAlreadyPulled, ThreadAlreadyPulled,
InvalidMerkleProof, InvalidMerkleProof,
InvalidReceiverAddress, InvalidReceiverAddress,
CouldNotAccumulateIncomingImbalance, CouldNotRegisterIncoming,
CouldNotIncreaseGatekeeperAmount,
CouldNotAccumulateCommission,
} }
#[pallet::storage] #[pallet::storage]
@ -446,24 +444,14 @@ pub mod pallet {
.verify_proof(root_hash, &network_data.gatekeeper) .verify_proof(root_hash, &network_data.gatekeeper)
.ok_or(Error::<T>::InvalidMerkleProof)?; .ok_or(Error::<T>::InvalidMerkleProof)?;
let amount = thread_proof.amount().clone();
let receiver_bytes: &[u8; 32] = receiver_account.as_ref(); let receiver_bytes: &[u8; 32] = receiver_account.as_ref();
let receiver = T::AccountId::decode(&mut &receiver_bytes[..]) let receiver = T::AccountId::decode(&mut &receiver_bytes[..])
.map_err(|_| Error::<T>::InvalidReceiverAddress)?; .map_err(|_| Error::<T>::InvalidReceiverAddress)?;
let commission = Perbill::from_parts(network_data.incoming_fee).mul_ceil(amount); let amount = thread_proof.amount();
let pure_amount = amount.saturating_sub(commission); let pure_amount =
T::NetworkDataHandler::register_incoming(&network_id, amount)
let _ = T::NetworkDataHandler::accumulate_incoming_imbalance(&pure_amount) .map_err(|_| Error::<T>::CouldNotRegisterIncoming)?;
.map_err(|_| Error::<T>::CouldNotAccumulateIncomingImbalance)
.and_then(|_| {
T::NetworkDataHandler::increase_gatekeeper_amount(&network_id, &amount)
.map_err(|_| Error::<T>::CouldNotIncreaseGatekeeperAmount)
})
.and_then(|_| {
T::NetworkDataHandler::accumulate_commission(&commission)
.map_err(|_| Error::<T>::CouldNotAccumulateCommission)
})?;
let _ = T::Currency::deposit_creating(&receiver, pure_amount); let _ = T::Currency::deposit_creating(&receiver, pure_amount);
PulledThreads::<T>::insert(pulled_thread_key, ()); PulledThreads::<T>::insert(pulled_thread_key, ());