Compare commits

...

3 Commits

Author SHA1 Message Date
ab37f862f5
integrate pallet changes into the runtime
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-09-25 14:23:47 +03:00
9f5a214cd5
receiver amount to existential deposit in benchmarks
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-09-25 14:22:22 +03:00
aa336d9c55
make proof size depend only on runtime constant
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
2026-09-25 14:20:35 +03:00
9 changed files with 67 additions and 29 deletions

View File

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

@ -32,7 +32,7 @@ mod benchmarks {
let dummy_evm_address = EvmAddress::from(evm_addr_bytes); let dummy_evm_address = EvmAddress::from(evm_addr_bytes);
let target_index = max_proof_depth - 1; let target_index = max_proof_depth - 1;
let claim_package_init = ClaimPackage { let claim_package_init = ClaimPackage::<T> {
shares: dummy_shares, shares: dummy_shares,
merkle_proof: Default::default(), merkle_proof: Default::default(),
token_id: 0, token_id: 0,

View File

@ -36,8 +36,6 @@ mod benchmarking;
mod mock; mod mock;
mod tests; mod tests;
const MAX_POSSIBLE_PROOF_DEPTH: u32 = 18;
type TokenId = u128; type TokenId = u128;
type ClaimNonce = u8; type ClaimNonce = u8;
type EvmHash = sp_core::H256; type EvmHash = sp_core::H256;
@ -144,21 +142,36 @@ where
} }
} }
#[derive(Encode, Decode, Clone, RuntimeDebug, TypeInfo, PartialEq, Eq)] #[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct ClaimPackage<Balance> #[scale_info(skip_type_params(T))]
where pub struct ClaimPackage<T: pallet::Config> {
Balance: Default + Copy + Clone,
{
pub index: u32, pub index: u32,
pub token_id: TokenId, pub token_id: TokenId,
pub shares: Balance, pub shares: BalanceOf<T>,
pub merkle_proof: BoundedVec<EvmHash, ConstU32<MAX_POSSIBLE_PROOF_DEPTH>>, pub merkle_proof: BoundedVec<EvmHash, T::MaxProofDepth>,
} }
impl<Balance> ClaimPackage<Balance> impl<T: pallet::Config> Clone for ClaimPackage<T> {
where fn clone(&self) -> Self {
Balance: Default + Copy + Clone + UniqueSaturatedInto<u128>, Self {
{ index: self.index,
token_id: self.token_id,
shares: self.shares,
merkle_proof: self.merkle_proof.clone(),
}
}
}
impl<T: pallet::Config> PartialEq for ClaimPackage<T> {
fn eq(&self, other: &Self) -> bool {
self.index == other.index &&
self.token_id == other.token_id &&
self.shares == other.shares &&
self.merkle_proof == other.merkle_proof
}
}
impl<T: pallet::Config> ClaimPackage<T> {
pub fn get_preimage<NetworkId>( pub fn get_preimage<NetworkId>(
&self, &self,
evm_address: &EvmAddress, evm_address: &EvmAddress,
@ -333,7 +346,7 @@ pub mod pallet {
pub fn claim( pub fn claim(
origin: OriginFor<T>, origin: OriginFor<T>,
network_id: NetworkIdOf<T>, network_id: NetworkIdOf<T>,
claim_package: ClaimPackage<BalanceOf<T>>, claim_package: ClaimPackage<T>,
evm_address: EvmAddress, evm_address: EvmAddress,
evm_signature: EvmSignature, evm_signature: EvmSignature,
requested_shares: BalanceOf<T>, requested_shares: BalanceOf<T>,
@ -425,7 +438,7 @@ impl<T: Config> Pallet<T> {
fn to_ascii_base10<N: PrimInt + UniqueSaturatedInto<u128>>(num: N) -> Vec<u8> { fn to_ascii_base10<N: PrimInt + UniqueSaturatedInto<u128>>(num: N) -> Vec<u8> {
let zero = N::zero(); let zero = N::zero();
if num == zero { return vec![b'0']; } if num == zero { return sp_std::vec![b'0']; }
let ten = N::from(10).unwrap_or_else(|| N::zero()); let ten = N::from(10).unwrap_or_else(|| N::zero());
let num_u128 = num.unique_saturated_into(); let num_u128 = num.unique_saturated_into();
@ -519,7 +532,7 @@ impl<T: Config> Pallet<T> {
fn verify_merkle_proof( fn verify_merkle_proof(
network_id: &NetworkIdOf<T>, network_id: &NetworkIdOf<T>,
preimage: &[u8], preimage: &[u8],
claim_package: &ClaimPackage<BalanceOf<T>>, claim_package: &ClaimPackage<T>,
) -> DispatchResult { ) -> DispatchResult {
let network_state = NetworkShares::<T>::get(network_id); let network_state = NetworkShares::<T>::get(network_id);

View File

@ -52,7 +52,7 @@ impl Config for Test {
type NetworkDataHandler = Networks; type NetworkDataHandler = Networks;
type MinimumDonation = ConstU128<69>; type MinimumDonation = ConstU128<69>;
type MaxProofDepth = ConstU32<5>; type MaxProofDepth = ConstU32<7>;
type MaxPartialClaims = ConstU8<3>; type MaxPartialClaims = ConstU8<3>;
type WeightInfo = (); type WeightInfo = ();

View File

@ -87,7 +87,7 @@ fn claim_happy_path() {
|item: (u8, &NewTestUser)| -> Result<(usize, Vec<u8>), ()> { |item: (u8, &NewTestUser)| -> Result<(usize, Vec<u8>), ()> {
let (index, u) = item; let (index, u) = item;
let tmp_package = ClaimPackage { let tmp_package = ClaimPackage::<Test> {
shares: u.allowed_shares, shares: u.allowed_shares,
merkle_proof: Default::default(), merkle_proof: Default::default(),
token_id: u.token_id, token_id: u.token_id,
@ -118,7 +118,7 @@ fn claim_happy_path() {
let proof = generate_proof::<SubstrateKeccakHasher, u8>(&merkle_tree, max_index, slot_index as u8); let proof = generate_proof::<SubstrateKeccakHasher, u8>(&merkle_tree, max_index, slot_index as u8);
let claim_package = ClaimPackage { let claim_package = ClaimPackage::<Test> {
shares: current_user.allowed_shares, shares: current_user.allowed_shares,
merkle_proof: BoundedVec::try_from(proof).unwrap(), merkle_proof: BoundedVec::try_from(proof).unwrap(),
token_id: current_user.token_id, token_id: current_user.token_id,
@ -211,7 +211,7 @@ fn partial_claims_happy_path() {
|item: (u8, &NewTestUser)| -> Result<(usize, Vec<u8>), ()> { |item: (u8, &NewTestUser)| -> Result<(usize, Vec<u8>), ()> {
let (index, u) = item; let (index, u) = item;
let tmp_package = ClaimPackage { let tmp_package = ClaimPackage::<Test> {
shares: u.allowed_shares, shares: u.allowed_shares,
merkle_proof: Default::default(), merkle_proof: Default::default(),
token_id: u.token_id, token_id: u.token_id,

View File

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

View File

@ -3,6 +3,7 @@
use super::*; use super::*;
use frame_benchmarking::v2::*; use frame_benchmarking::v2::*;
use frame_system::RawOrigin; use frame_system::RawOrigin;
use sp_runtime::traits::Saturating;
use sp_std::vec; use sp_std::vec;
use ghost_helpers::networks::NetworkDataBuilder; use ghost_helpers::networks::NetworkDataBuilder;
@ -144,6 +145,17 @@ mod benchmarks {
let max_history_depth = a as usize; let max_history_depth = a as usize;
let (network_id, _, _) = prepare_pallet::<T>(1, None); let (network_id, _, _) = prepare_pallet::<T>(1, None);
let expected_receiver_bytes = hex::decode("1657090d02985f0cdb41436fe2d5a83a3acb1995d963a698e7e619e927bdcc5e").unwrap();
let mut receiver_raw = [0u8; 32];
receiver_raw.copy_from_slice(&expected_receiver_bytes);
let transfer_amount: u64 = 153348847;
let receiver = T::AccountId::decode(&mut &receiver_raw[..])
.expect("32-byte array must cleanly decode into T::AccountId");
let existential_deposit = <T as Config>::Currency::minimum_balance();
<T as Config>::Currency::set_balance(&receiver, existential_deposit);
// Real world tx at block #481838 // Real world tx at block #481838
// Block https://blockstream.info/block/0000000000000000011bdccb39e19e942a60edffdccd9779653c5b46b337904a // Block https://blockstream.info/block/0000000000000000011bdccb39e19e942a60edffdccd9779653c5b46b337904a
// Transaction: https://blockstream.info/tx/4a3fdd9ebb30b9c6df05d4199f8474b2f0c795d1f40a58d0d73342fc666b4a2e // Transaction: https://blockstream.info/tx/4a3fdd9ebb30b9c6df05d4199f8474b2f0c795d1f40a58d0d73342fc666b4a2e
@ -322,11 +334,16 @@ mod benchmarks {
let pulled_thread_key = thread_proof.get_unique_key(session, network_id); let pulled_thread_key = thread_proof.get_unique_key(session, network_id);
assert!(!PulledThreads::<T>::contains_key(&pulled_thread_key)); assert!(!PulledThreads::<T>::contains_key(&pulled_thread_key));
assert_eq!(T::Currency::balance(&receiver), existential_deposit);
#[extrinsic_call] #[extrinsic_call]
pull_thread(RawOrigin::None, network_id, session, thread_proof); pull_thread(RawOrigin::None, network_id, session, thread_proof);
let final_amount = existential_deposit.saturating_add(
transfer_amount.unique_saturated_into()
);
assert!(PulledThreads::<T>::contains_key(&pulled_thread_key)); assert!(PulledThreads::<T>::contains_key(&pulled_thread_key));
assert_eq!(T::Currency::balance(&receiver), final_amount);
Ok(()) Ok(())
} }
@ -352,8 +369,13 @@ mod benchmarks {
.try_into() .try_into()
.expect("Hex string must be exactly 32 bytes long"); .expect("Hex string must be exactly 32 bytes long");
let receiver_account = sp_runtime::AccountId32::from(receiver_32);
let transfer_amount: BalanceOf<T> = 420u64.unique_saturated_into(); let transfer_amount: BalanceOf<T> = 420u64.unique_saturated_into();
let receiver_account = sp_runtime::AccountId32::from(receiver_32);
let receiver_account_t = T::AccountId::decode(&mut &receiver_32[..])
.expect("32-byte array must cleanly decode into T::AccountId");
let existential_deposit = <T as Config>::Currency::minimum_balance();
<T as Config>::Currency::set_balance(&receiver_account_t, existential_deposit);
let proof = vec![ let proof = vec![
H256::from_slice(&hex::decode("7d831a4be9e37572687117870c3f96669a66bf07971e4fd705a36a0a4d6365b0").expect("Proof should be valid")), H256::from_slice(&hex::decode("7d831a4be9e37572687117870c3f96669a66bf07971e4fd705a36a0a4d6365b0").expect("Proof should be valid")),
@ -370,7 +392,7 @@ mod benchmarks {
.expect("Slot should be valid hex"), .expect("Slot should be valid hex"),
)]; )];
let evm_thread_proof = EvmThreadProof::new(0, 1, receiver_account, transfer_amount, proof, slots); let evm_thread_proof = EvmThreadProof::new(0, 1, receiver_account.into(), transfer_amount, proof, slots);
let thread_proof = ThreadProof::EvmThreadProof(evm_thread_proof); let thread_proof = ThreadProof::EvmThreadProof(evm_thread_proof);
let pulled_thread_key = thread_proof.get_unique_key(session, network_id); let pulled_thread_key = thread_proof.get_unique_key(session, network_id);

View File

@ -1,6 +1,6 @@
[package] [package]
name = "casper-runtime" name = "casper-runtime"
version = "4.0.11" version = "4.0.12"
build = "build.rs" build = "build.rs"
description = "Runtime of the Casper Network" description = "Runtime of the Casper Network"
edition.workspace = true edition.workspace = true

View File

@ -15,7 +15,7 @@ use frame_support::{
traits::{ traits::{
fungible::HoldConsideration, fungible::HoldConsideration,
tokens::{imbalance::ResolveTo, UnityAssetBalanceConversion}, tokens::{imbalance::ResolveTo, UnityAssetBalanceConversion},
ConstU128, ConstU32, InstanceFilter, KeyOwnerProofSystem, ConstU128, ConstU32, ConstU8, InstanceFilter, KeyOwnerProofSystem,
LinearStoragePrice, LinearStoragePrice,
}, },
}; };
@ -860,7 +860,7 @@ impl ghost_nomination_pools::Config for Runtime {
type PalletId = PoolsPalletId; type PalletId = PoolsPalletId;
type MaxPointsToBalance = MaxPointsToBalance; type MaxPointsToBalance = MaxPointsToBalance;
type AdminOrigin = EnsureRoot<Self::AccountId>; type AdminOrigin = EnsureRoot<Self::AccountId>;
type WeightInfo = weights::ghost_nomination_pools::WeightInfo<Runtime>; type WeightInfo = weights::ghost_nomination_pools::WeightInfo<Runtime>;
} }
impl ghost_networks::Config for Runtime { impl ghost_networks::Config for Runtime {
@ -887,7 +887,8 @@ impl ghost_governance::Config for Runtime {
type Currency = Balances; type Currency = Balances;
type NetworkDataHandler = GhostNetworks; type NetworkDataHandler = GhostNetworks;
type MinimumDonation = ConstU128<{ 6_900 * STRH }>; type MinimumDonation = ConstU128<{ 6_900 * STRH }>;
type MaxProofDepth = ConstU32<20>; type MaxProofDepth = ConstU32<18>;
type MaxPartialClaims = ConstU8<20>;
type WeightInfo = weights::ghost_governance::WeightInfo<Runtime>; type WeightInfo = weights::ghost_governance::WeightInfo<Runtime>;
} }
@ -913,6 +914,7 @@ parameter_types! {
pub ExodusDkgRoundPeriod: u64 = 50; pub ExodusDkgRoundPeriod: u64 = 50;
pub ExodusRemovalLimit: u32 = 64; pub ExodusRemovalLimit: u32 = 64;
pub ExodusMaxCursorLen: u32 = 100; pub ExodusMaxCursorLen: u32 = 100;
pub MinBridgeOut: u128 = 500 * STRH;
} }
impl ghost_weaver::Config for Runtime { impl ghost_weaver::Config for Runtime {
@ -951,6 +953,7 @@ impl ghost_exodus::Config for Runtime {
type DkgRoundPeriod = ExodusDkgRoundPeriod; type DkgRoundPeriod = ExodusDkgRoundPeriod;
type RemovalLimit = ExodusRemovalLimit; type RemovalLimit = ExodusRemovalLimit;
type MaxCursorLen = ExodusMaxCursorLen; type MaxCursorLen = ExodusMaxCursorLen;
type BaseEvmAmount = MinBridgeOut;
type WeightInfo = weights::ghost_exodus::WeightInfo<Runtime>; type WeightInfo = weights::ghost_exodus::WeightInfo<Runtime>;
} }