Compare commits

..

No commits in common. "f2544e3876d4b1ef30f90a944ee78d1bd63e1fb0" and "90dfc76581080152714750a29dc7c9258c534084" have entirely different histories.

36 changed files with 1428 additions and 1784 deletions

16
Cargo.lock generated
View File

@ -3628,7 +3628,7 @@ dependencies = [
[[package]]
name = "ghost-cli"
version = "0.9.2"
version = "0.9.1"
dependencies = [
"cfg-if",
"clap 4.5.4",
@ -3684,7 +3684,7 @@ dependencies = [
[[package]]
name = "ghost-exodus"
version = "0.0.3"
version = "0.0.2"
dependencies = [
"chacha20poly1305",
"frame-benchmarking",
@ -3775,7 +3775,7 @@ dependencies = [
[[package]]
name = "ghost-machine-primitives"
version = "0.9.2"
version = "0.9.1"
dependencies = [
"lazy_static",
"sc-sysinfo",
@ -3784,7 +3784,7 @@ dependencies = [
[[package]]
name = "ghost-metrics"
version = "0.9.2"
version = "0.9.1"
dependencies = [
"assert_cmd",
"bs58 0.5.1",
@ -3862,7 +3862,7 @@ dependencies = [
[[package]]
name = "ghost-node"
version = "0.9.2"
version = "0.9.1"
dependencies = [
"assert_cmd",
"color-eyre",
@ -3945,7 +3945,7 @@ dependencies = [
[[package]]
name = "ghost-rpc"
version = "0.9.2"
version = "0.9.1"
dependencies = [
"ghost-core-primitives",
"jsonrpsee",
@ -3974,7 +3974,7 @@ dependencies = [
[[package]]
name = "ghost-service"
version = "0.9.2"
version = "0.9.1"
dependencies = [
"assert_matches",
"async-trait",
@ -4085,7 +4085,7 @@ dependencies = [
[[package]]
name = "ghost-traits"
version = "0.4.4"
version = "0.4.3"
dependencies = [
"frame-support",
"frost-core",

View File

@ -17,7 +17,7 @@ homepage.workspace = true
[workspace.package]
license = "GPL-3.0-only"
authors = ["571nky", "57r37ch", "f4750"]
version = "0.9.2"
version = "0.9.1"
edition = "2021"
homepage = "https://ghostchain.io"
repository = "https://git.ghostchain.io/ghostchain/ghost-node"

View File

@ -1,8 +1,13 @@
use crate::cli::{Cli, Subcommand};
use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory};
use futures::future::TryFutureExt;
use keyring::Sr25519Keyring;
use sc_cli::SubstrateCli;
use service::{self, IdentifyVariant};
use service::{
self,
benchmarking::{benchmark_inherent_data, RemarkBuilder, TransferKeepAliveBuilder},
IdentifyVariant,
};
pub use crate::{error::Error, service::BlockId};
#[cfg(feature = "pyroscope")]
@ -295,8 +300,6 @@ pub fn run() -> Result<()> {
}),
// These commands are very similar and can be handled in nearly the same way
BenchmarkCmd::Extrinsic(_) | BenchmarkCmd::Overhead(_) => {
use service::benchmarking::{benchmark_inherent_data, RemarkBuilder, TransferKeepAliveBuilder};
runner.sync_run(|mut config| {
let (client, _, _, _) = service::new_chain_ops(&mut config)?;
@ -310,7 +313,7 @@ pub fn run() -> Result<()> {
BenchmarkCmd::Extrinsic(cmd) => {
let tka_builder = TransferKeepAliveBuilder::new(
client.clone(),
keyring::Sr25519Keyring::Alice.to_account_id(),
Sr25519Keyring::Alice.to_account_id(),
config.chain_spec.identify_chain(),
);
@ -357,6 +360,13 @@ pub fn run() -> Result<()> {
_ => Err(Error::CommandNotImplemented),
}
}
#[cfg(not(feature = "runtime-benchmarks"))]
Some(Subcommand::Benchmark(_)) => {
return Err(sc_cli::Error::Input(
"Benchmarking wasn't enabled when building the node. \
You can enable it with `--features=runtime-benchmarks`.".into(),
).into())
},
Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
Some(Subcommand::ChainInfo(cmd)) => {
let runner = cli.create_runner(cmd)?;

View File

@ -1,6 +1,6 @@
[package]
name = "ghost-exodus"
version = "0.0.5"
version = "0.0.2"
description = "Threshold signature generation with DKG included"
license.workspace = true
authors.workspace = true
@ -56,53 +56,53 @@ rand = { workspace = true }
default = ["std"]
std = [
"frame-benchmarking?/std",
"scale-info/std",
"strum/std",
"log/std",
"hex/std",
"k256/std",
"num-traits/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
"strum/std",
"log/std",
"hex/std",
"k256/std",
"num-traits/std",
"frame-support/std",
"frame-system/std",
"sha2/std",
"hkdf/std",
"chacha20poly1305/std",
"rand_chacha/std",
"sp-arithmetic/std",
"sp-application-crypto/std",
"sp-runtime/std",
"sp-staking/std",
"sp-core/std",
"sp-std/std",
"sp-io/std",
"frost-secp256k1/std",
"frost-ed25519/std",
"frost-core/std",
"ghost-traits/std",
"ghost-helpers/std",
"pallet-balances/std",
"pallet-session/std",
"pallet-staking/std",
"ghost-networks/std",
"frame-executive/std",
"sp-keystore/std",
"chacha20poly1305/std",
"rand_chacha/std",
"sp-arithmetic/std",
"sp-application-crypto/std",
"sp-runtime/std",
"sp-staking/std",
"sp-core/std",
"sp-std/std",
"sp-io/std",
"frost-secp256k1/std",
"frost-ed25519/std",
"frost-core/std",
"ghost-traits/std",
"ghost-helpers/std",
"pallet-balances/std",
"pallet-session/std",
"pallet-staking/std",
"ghost-networks/std",
"frame-executive/std",
"sp-keystore/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-staking/runtime-benchmarks",
"ghost-networks/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-staking/runtime-benchmarks",
"ghost-networks/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"sp-runtime/try-runtime",
"pallet-balances/try-runtime",
"pallet-session/try-runtime",
"frame-executive/try-runtime",
"ghost-networks/try-runtime",
"frame-support/try-runtime",
"frame-system/try-runtime",
"sp-runtime/try-runtime",
"pallet-balances/try-runtime",
"pallet-session/try-runtime",
"frame-executive/try-runtime",
"ghost-networks/try-runtime",
]

View File

@ -472,7 +472,6 @@ mod benchmarks {
#[benchmark]
fn register_nonce_commitment() -> Result<(), BenchmarkError> {
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
let (mut dkg_state, network_curve, authority, authority_index) =
prepare_pallet::<T>(1);
@ -484,22 +483,9 @@ mod benchmarks {
dkg_state.insert_index(authority_index);
let exodus_session = CurrentExodus::<T>::get();
let dummy_address = EvmAddress::repeat_byte(69);
let dummy_bytes = EvmBytes32::repeat_byte(69);
let dummy_nonce = vec![0u8; network_curve.element_bytes_len()];
let create_bond = GovernanceAction::Create {
market: [69, 420, 1337],
terms: [420, 1337],
token: dummy_address,
intervals: [34, 35],
booleans: [true, true],
};
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
exodus_session,
network_id,
dummy_address,
create_bond,
);
let request = ExodusRequest::evm_rotation(exodus_session, dummy_bytes, 0);
let authorities = QualificationAuthorities::<T>::get(&network_curve);
let active_dkg: ActivatedState<T> = (&dkg_state).into();
@ -548,7 +534,6 @@ mod benchmarks {
#[benchmark]
fn register_group_commitment() -> Result<(), BenchmarkError> {
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
let (mut dkg_state, network_curve, authority, authority_index) =
prepare_pallet::<T>(1);
@ -561,23 +546,9 @@ mod benchmarks {
let exodus_session = CurrentExodus::<T>::get();
let dummy_bytes = EvmBytes32::repeat_byte(69);
let dummy_address = EvmAddress::repeat_byte(69);
let dummy_merkle_root = ExodusHash::repeat_byte(69);
let dummy_group_commitment = vec![0u8; network_curve.element_bytes_len()];
let create_bond = GovernanceAction::Create {
market: [69, 420, 1337],
terms: [420, 1337],
token: dummy_address,
intervals: [34, 35],
booleans: [true, true],
};
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
exodus_session,
network_id,
dummy_address,
create_bond,
);
let request = ExodusRequest::evm_rotation(exodus_session, dummy_bytes, 0);
let authorities = QualificationAuthorities::<T>::get(&network_curve);
let active_dkg: ActivatedState<T> = (&dkg_state).into();
@ -638,7 +609,6 @@ mod benchmarks {
fn register_signature_share() -> Result<(), BenchmarkError> {
let max_signers = T::MaxAuthorities::get();
let threshold = get_byzantium_threshold(max_signers);
let network_id: NetworkIdOf<T> = 69_420u64.unique_saturated_into();
let (mut dkg_state, network_curve, authority, authority_index) =
prepare_pallet::<T>(max_signers as usize);
@ -662,20 +632,8 @@ mod benchmarks {
];
dummy_element[1..33].copy_from_slice(&g_x_coords);
let dummy_address = EvmAddress::repeat_byte(69);
let create_bond = GovernanceAction::Create {
market: [69, 420, 1337],
terms: [420, 1337],
token: dummy_address,
intervals: [34, 35],
booleans: [true, true],
};
let request = ExodusRequest::<NetworkIdOf<T>, BalanceOf<T>>::evm_governance(
exodus_session,
network_id,
dummy_address,
create_bond,
);
let dummy_bytes = EvmBytes32::repeat_byte(69);
let request = ExodusRequest::evm_rotation(exodus_session, dummy_bytes, 0);
let mut dummy_scalar = vec![0u8; network_curve.scalar_bytes_len()];
dummy_scalar[network_curve.scalar_bytes_len() - 1] = 1;
@ -797,7 +755,7 @@ mod benchmarks {
assert!(!committers_exists);
assert!(!ExodusRequests::<T>::contains_key(&network_curve, &exodus_session));
assert!(ExodusSignedGovernance::<T>::contains_key((&exodus_session, network_id), dkg_index));
assert!(ExodusSignedRotations::<T>::contains_key((&exodus_session, NetworkType::Evm), dkg_index));
Ok(())
}

View File

@ -0,0 +1,496 @@
use crate::{EncryptedMessage, FrostError};
use ghost_networks::NetworkCurve;
use chacha20poly1305::{
aead::{self, Aead, AeadCore, KeyInit},
Key as EncryptionKey,
Nonce as EncryptionNonce,
ChaCha20Poly1305 as EncryptionCipher,
};
use hkdf::Hkdf as KeyDerivation;
use sha2::{Digest, Sha256 as Hashing};
use rand_chacha::rand_core::{CryptoRng, RngCore};
use sp_std::collections::btree_map::BTreeMap;
macro_rules! with_ciphersuite {
($curve:expr, |$alias:ident| $body:block) => {
match $curve {
ExodusCurve::Secp256k1 => {
use frost_secp256k1 as $alias;
$body
},
NetworkCurve::Ed25519 => {
use frost_ed25519 as $alias;
$body
}
}
}
}
impl ExodusCurve {
pub fn dkg_verify_proof_of_knowledge(
&self,
index: u16,
round1_package_bytes: &[u8],
) -> Result<(), FrostError> {
with_ciphersuite!(self, |f| {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let round1_package = f::keys::dkg::round1::Package::deserialize(round1_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
frost_core::keys::dkg::verify_proof_of_knowledge(
identifier,
&round1_package.commitment(),
&round1_package.proof_of_knowledge(),
).map_err(|_| FrostError::InvalidProofOfKnowledge)
})
}
pub fn verify_signature_share(
&self,
index: u16,
verifying_share_bytes: &[u8],
signature_share_bytes: &[u8],
signing_package_bytes: &[u8],
verifying_key_bytes: &[u8],
) -> Result<(), FrostError> {
with_ciphersuite!(self, |f| {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let verifying_share = f::keys::VerifyingShare::deserialize(verifying_share_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let signature_share = f::round2::SignatureShare::deserialize(signature_share_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let signing_package = f::SigningPackage::deserialize(signing_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let verifying_key = f::VerifyingKey::deserialize(verifying_key_bytes)
.map_err(|_| FrostError::DeserializationError)?;
frost_core::verify_signature_share(
identifier,
&verifying_share,
&signature_share,
&signing_package,
&verifying_key,
).map_err(|err| match err {
f::Error::IdentityCommitment => FrostError::IdentityCommitment,
f::Error::UnknownIdentifier => FrostError::UnknownIdentifier,
f::Error::DuplicatedIdentifier => FrostError::DuplicatedIdentifier,
f::Error::InvalidSignatureShare { .. } => FrostError::InvalidSignatureShare,
_ => FrostError::Unknown,
})
})
}
pub fn aggregate_signature(
&self,
signing_package_bytes: &[u8],
signature_shares_bytes: &BTreeMap<u16, Vec<u8>>,
pubkeys_bytes: &[u8],
) -> Result<Vec<u8>, FrostError> {
with_ciphersuite!(self, |f| {
let signing_package = f::SigningPackage::deserialize(signing_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let mut signature_shares = BTreeMap::new();
for (&index, signature_share_bytes) in signature_shares_bytes.iter() {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let signature_share = f::round2::SignatureShare::deserialize(signature_share_bytes)
.map_err(|_| FrostError::DeserializationError)?;
signature_shares.insert(identifier, signature_share);
}
let pubkeys = f::keys::PublicKeyPackage::deserialize(pubkeys_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let signature = f::aggregate(&signing_package, &signature_shares, &pubkeys)
.map_err(|err| match err {
f::Error::UnknownIdentifier => FrostError::UnknownIdentifier,
f::Error::SerializationError => FrostError::SerializationError,
f::Error::IdentityCommitment => FrostError::IdentityCommitment,
f::Error::IncorrectNumberOfIdentifiers => FrostError::IncorrectNumberOfIdentifiers,
f::Error::DuplicatedIdentifier => FrostError::DuplicatedIdentifier,
f::Error::InvalidSecretShare { .. } => FrostError::InvalidSecretShare,
f::Error::InvalidSignature { .. } => FrostError::InvalidSignature,
_ => FrostError::Unknown,
})?;
let signature_bytes = signature.serialize()
.map_err(|_| FrostError::SerializationError)?;
Ok(signature_bytes)
})
}
pub fn is_signature_valid(
&self,
pubkey_bytes: &[u8],
signature_bytes: &[u8],
message: &[u8],
) -> bool {
with_ciphersuite!(self, |f| {
let get_verification_result = || -> Result<(), FrostError> {
let pubkeys = f::keys::PublicKeyPackage::deserialize(pubkey_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let signature = f::Signature::deserialize(signature_bytes)
.map_err(|_| FrostError::DeserializationError)?;
pubkeys.verifying_key()
.verify(message, &signature)
.map_err(|_| FrostError::InvalidSignature)?;
Ok(())
};
get_verification_result().is_ok()
})
}
pub fn dkg_part1<R: RngCore + CryptoRng>(
&self,
index: u16,
max_signers: u16,
min_signers: u16,
mut rng: R,
) -> Result<(Vec<u8>, Vec<u8>), FrostError> {
with_ciphersuite!(self, |f| {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let (round1_secret_package, round1_package) = f::keys::dkg::part1(
identifier,
max_signers,
min_signers,
&mut rng,
).map_err(|err| {
match err {
f::Error::InvalidMinSigners => FrostError::InvalidMinSigners(min_signers, max_signers),
f::Error::InvalidMaxSigners => FrostError::InvalidMaxSigners(max_signers),
f::Error::DKGNotSupported => FrostError::DKGNotSupported(*self),
_ => FrostError::Unknown,
}
})?;
let round1_secret_package_bytes = round1_secret_package.serialize()
.map_err(|_| FrostError::SerializationError)?;
let round1_package_bytes = round1_package.serialize()
.map_err(|_| FrostError::SerializationError)?;
Ok((round1_secret_package_bytes, round1_package_bytes))
})
}
fn convert_identifier_to_index(
identifier_bytes: Vec<u8>
) -> Result<u16, FrostError> {
const SIZE: usize = core::mem::size_of::<u16>();
let start = identifier_bytes.len().checked_sub(SIZE)
.ok_or(FrostError::InvalidParticipantId)?;
let bytes_array = identifier_bytes.get(start..)
.and_then(|slice| slice.try_into().ok())
.ok_or(FrostError::InvalidParticipantId)?;
Ok(u16::from_be_bytes(bytes_array))
}
pub fn dkg_part2(
&self,
round1_secret_package_bytes: &[u8],
round1_packages_bytes: &BTreeMap<u16, Vec<u8>>,
) -> Result<(Vec<u8>, BTreeMap<u16, Vec<u8>>), FrostError> {
with_ciphersuite!(self, |f| {
let round1_secret_package = f::keys::dkg::round1::SecretPackage::deserialize(round1_secret_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let mut round1_packages = BTreeMap::new();
for (&index, round1_package_bytes) in round1_packages_bytes.iter() {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let round1_package = f::keys::dkg::round1::Package::deserialize(round1_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
round1_packages.insert(identifier, round1_package);
}
let (round2_secret_package, round2_packages) = f::keys::dkg::part2(
round1_secret_package,
&round1_packages,
).map_err(|err| match err {
f::Error::IncorrectNumberOfCommitments => FrostError::IncorrectNumberOfCommitments,
f::Error::IncorrectNumberOfPackages => FrostError::IncorrectNumberOfPackages,
f::Error::InvalidProofOfKnowledge { .. } => FrostError::InvalidProofOfKnowledge,
_ => FrostError::Unknown,
})?;
let round2_secret_package_bytes = round2_secret_package.serialize()
.map_err(|_| FrostError::SerializationError)?;
let mut round2_packages_bytes = BTreeMap::new();
for (participant_identifier, round2_package) in round2_packages.iter() {
let index = Self::convert_identifier_to_index(
participant_identifier.serialize(),
)?;
let round2_package_bytes = round2_package.serialize()
.map_err(|_| FrostError::SerializationError)?;
round2_packages_bytes.insert(index as u16, round2_package_bytes);
}
Ok((round2_secret_package_bytes, round2_packages_bytes))
})
}
pub fn dkg_encrypt_round2_package<R: RngCore + CryptoRng>(
&self,
cipher: &EncryptionCipher,
associated_data: &[u8],
round2_package_bytes: &[u8],
mut rng: R,
) -> Result<(Vec<u8>, Vec<u8>), FrostError> {
let payload = aead::Payload {
msg: round2_package_bytes,
aad: associated_data,
};
let nonce = EncryptionCipher::generate_nonce(&mut rng);
let ciphertext = cipher.encrypt(&nonce, payload)
.map_err(|_| FrostError::EncryptionFailed)?;
Ok((ciphertext, nonce.to_vec()))
}
pub fn dkg_decrypt_round2_package(
&self,
cipher: &EncryptionCipher,
encrypted_message: &EncryptedMessage,
associated_data: &[u8],
) -> Result<Vec<u8>, FrostError> {
let nonce = EncryptionNonce::from_iter(encrypted_message.nonce.iter().cloned());
let payload = aead::Payload {
msg: &encrypted_message.ciphertext,
aad: associated_data,
};
cipher.decrypt(&nonce, payload)
.map_err(|_| FrostError::DecryptionFailed)
}
pub fn prepare_additional_info(
&self,
sender_index: u16,
receiver_index: u16,
session_index: u16,
) -> Vec<u8> {
let mut additional_info = match self {
ExodusCurve::Secp256k1 => b"EXODUS-SECP256K1-DKG-V1".to_vec(),
};
additional_info.extend_from_slice(&sender_index.to_be_bytes());
additional_info.extend_from_slice(&receiver_index.to_be_bytes());
additional_info.extend_from_slice(&session_index.to_be_bytes());
additional_info
}
pub fn prepare_cipher_from_keys(
&self,
round1_receiver_package_bytes: &[u8],
round1_secret_package_bytes: &[u8],
additional_info: &[u8],
) -> Result<EncryptionCipher, FrostError> {
with_ciphersuite!(self, |f| {
let coefficients =
f::keys::dkg::round1::SecretPackage::deserialize(round1_secret_package_bytes)
.map_err(|_| FrostError::DeserializationError)?
.coefficients();
let sender_secret_key = coefficients
.first()
.ok_or(FrostError::IncorrectNumberOfCoefficients)?;
let receiver_public_key =
f::keys::dkg::round1::Package::deserialize(round1_receiver_package_bytes)
.map_err(|_| FrostError::DeserializationError)?
.commitment()
.coefficients()
.first()
.ok_or(FrostError::MissingCommitment)?
.value();
let shared_secret_bytes = f::VerifyingKey::new(receiver_public_key * sender_secret_key)
.serialize()
.map_err(|_| FrostError::SerializationError)?;
let salt = Hashing::digest(&additional_info);
let hk = KeyDerivation::<Hashing>::new(Some(&salt), &shared_secret_bytes);
let mut encryption_key = EncryptionKey::default();
hk.expand(additional_info, &mut encryption_key)
.map_err(|_| FrostError::HKDFFailed)?;
let cipher = EncryptionCipher::new_from_slice(&encryption_key)
.expect("could not happen; length is already correct qed");
Ok(cipher)
})
}
pub fn dkg_verify_private_package(
&self,
index: u16,
round1_package_bytes: &[u8],
round2_package_bytes: &[u8],
) -> Result<(), FrostError> {
with_ciphersuite!(self, |f| {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let commitment = f::keys::dkg::round1::Package::deserialize(round1_package_bytes)
.map(|round1_package| round1_package.commitment().clone())
.map_err(|_| FrostError::DeserializationError)?;
let secret_share = f::keys::dkg::round2::Package::deserialize(round2_package_bytes)
.map(|round2_package| {
let signing_share = round2_package.signing_share().clone();
f::keys::SecretShare::new(identifier, signing_share, commitment)
})
.map_err(|_| FrostError::DeserializationError)?;
let _ = secret_share.verify().map_err(|_| FrostError::InvalidSecretShare)?;
Ok(())
})
}
pub fn dkg_part3(
&self,
round2_secret_package_bytes: &[u8],
round1_packages_bytes: &BTreeMap<u16, Vec<u8>>,
round2_packages_bytes: &BTreeMap<u16, Vec<u8>>,
) -> Result<(Vec<u8>, Vec<u8>), FrostError> {
with_ciphersuite!(self, |f| {
let round2_secret_package = f::keys::dkg::round2::SecretPackage::deserialize(round2_secret_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let mut round1_packages = BTreeMap::new();
for (&index, round1_package_bytes) in round1_packages_bytes.iter() {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let round1_package = f::keys::dkg::round1::Package::deserialize(round1_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
round1_packages.insert(identifier, round1_package);
}
let mut round2_packages = BTreeMap::new();
for (&index, round2_package_bytes) in round2_packages_bytes.iter() {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let round2_package = f::keys::dkg::round2::Package::deserialize(round2_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
round2_packages.insert(identifier, round2_package);
}
let (key_package, pubkey_package) = f::keys::dkg::part3(
&round2_secret_package,
&round1_packages,
&round2_packages,
).map_err(|err| match err {
f::Error::IncorrectNumberOfPackages => FrostError::IncorrectNumberOfPackages,
f::Error::IncorrectPackage => FrostError::IncorrectPackage,
f::Error::PackageNotFound => FrostError::PackageNotFound,
f::Error::InvalidSecretShare { .. } => FrostError::InvalidSecretShare,
f::Error::IncorrectNumberOfCommitments => FrostError::IncorrectNumberOfCommitments,
_ => FrostError::Unknown,
})?;
let key_package_bytes = key_package.serialize()
.map_err(|_| FrostError::SerializationError)?;
let pubkey_package_bytes = pubkey_package.serialize()
.map_err(|_| FrostError::SerializationError)?;
Ok((key_package_bytes, pubkey_package_bytes))
})
}
pub fn generate_nonce<R: CryptoRng + RngCore>(
&self,
secret_key_package_bytes: &[u8],
mut rng: R
) -> Result<(Vec<u8>, Vec<u8>), FrostError> {
with_ciphersuite!(self, |f| {
let signing_share = f::keys::KeyPackage::deserialize(secret_key_package_bytes)
.map(|key_package| *key_package.signing_share())
.map_err(|_| FrostError::DeserializationError)?;
let (signing_nonces, signing_commitments) =
f::round1::commit(&signing_share, &mut rng);
let signing_nonces_bytes = signing_nonces.serialize()
.map_err(|_| FrostError::SerializationError)?;
let signing_commitments_bytes = signing_commitments.serialize()
.map_err(|_| FrostError::SerializationError)?;
Ok((signing_nonces_bytes, signing_commitments_bytes))
})
}
pub fn generate_signing_package(
&self,
commitments_map_bytes: &BTreeMap<u16, Vec<u8>>,
message: &[u8],
) -> Result<Vec<u8>, FrostError> {
with_ciphersuite!(self, |f| {
let mut commitments_map = BTreeMap::new();
for (&index, commitment_bytes) in commitments_map_bytes.iter() {
let identifier = index.try_into().map_err(|_| FrostError::InvalidParticipantId)?;
let commitment = f::round1::SigningCommitments::deserialize(commitment_bytes)
.map_err(|_| FrostError::DeserializationError)?;
commitments_map.insert(identifier, commitment);
}
f::SigningPackage::new(commitments_map, message)
.serialize()
.map_err(|_| FrostError::SerializationError)
})
}
pub fn sign_message(
&self,
signing_package_bytes: &[u8],
signer_nonces_bytes: &[u8],
secret_key_share_bytes: &[u8]
) -> Result<Vec<u8>, FrostError> {
with_ciphersuite!(self, |f| {
let signing_package = f::SigningPackage::deserialize(signing_package_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let signer_nonces = f::round1::SigningNonces::deserialize(signer_nonces_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let secret_key_share = f::keys::KeyPackage::deserialize(secret_key_share_bytes)
.map_err(|_| FrostError::DeserializationError)?;
let signature_share_bytes = f::round2::sign(&signing_package, &signer_nonces, &secret_key_share)
.map(|signature_share| signature_share.serialize())
.map_err(|err| match err {
f::Error::IncorrectNumberOfCommitments => FrostError::IncorrectNumberOfCommitments,
f::Error::MissingCommitment => FrostError::MissingCommitment,
f::Error::IncorrectCommitment => FrostError::IncorrectCommitment,
f::Error::SerializationError => FrostError::SerializationError,
f::Error::UnknownIdentifier => FrostError::UnknownIdentifier,
f::Error::IdentityCommitment => FrostError::IdentityCommitment,
f::Error::DuplicatedIdentifier => FrostError::DuplicatedIdentifier,
f::Error::IncorrectNumberOfIdentifiers => FrostError::IncorrectNumberOfIdentifiers,
_ => FrostError::Unknown,
})?;
Ok(signature_share_bytes)
})
}
}

View File

@ -46,7 +46,7 @@ use ghost_traits::{
},
exodus::{
MerkleTreeBuilder, DistributedKeyGeneration, EllipticCurveDiffieHellman,
FlexibleRoundOptimizedSchnorrThresholdSignature, EvmGovernanceRegistrar,
FlexibleRoundOptimizedSchnorrThresholdSignature,
},
networks::{
NetworkDataBasicHandler, NetworkDataInspectHandler,
@ -108,7 +108,7 @@ const EXODUS_PREFIX_SHARES: &[u8] = b"exodus-shares";
const EXODUS_PREFIX_BLENDS: &[u8] = b"exodus-blends";
const EXODUS_PREFIX_EXILES: &[u8] = b"exodus-exiles";
const MAX_MESSAGE_SIZE : u32 = 512;
const MAX_MESSAGE_SIZE : u32 = 420;
const HEADER_MAX_BYTES : u32 = 1 + 4;
const ELEMENT_MAX_BYTES : u32 = 33;
const SCALAR_MAX_BYTES : u32 = 32;
@ -506,7 +506,6 @@ pub mod pallet {
pub enum Error<T> {
DkgWrongRound,
TooManyEntries,
BridgeOverflow,
TooManyPackages,
WrongNetworkType,
InvalidMerkleProof,
@ -2136,13 +2135,12 @@ pub mod pallet {
}
impl<T: Config> Pallet<T> {
fn do_register_evm_exodus<F>(
fn do_register_evm_bridge_out_exodus(
network_id: NetworkIdOf<T>,
request_builder: F,
) -> DispatchResult
where
F: FnOnce(ExodusSession) -> ExodusRequest<NetworkIdOf<T>, BalanceOf<T>>,
{
amount: BalanceOf<T>,
bounty: Perbill,
receiver: EvmAddress,
) -> DispatchResult {
let network = T::NetworkDataHandler::get(&network_id)
.ok_or(Error::<T>::NetworkDoesNotExist)?;
@ -2154,7 +2152,13 @@ impl<T: Config> Pallet<T> {
ensure!(network.r#type.is_evm(), Error::<T>::WrongNetworkType);
let exodus_session = CurrentExodus::<T>::get();
let request = request_builder(exodus_session);
let request = ExodusRequest::evm_bridge_out(
exodus_session,
network_id,
amount,
bounty,
receiver
);
ExodusRequests::<T>::insert(&network.curve, &exodus_session, request);
CurrentExodus::<T>::put(exodus_session.saturating_add(1));
@ -2162,42 +2166,6 @@ impl<T: Config> Pallet<T> {
Ok(())
}
fn do_register_evm_bridge_out_exodus(
network_id: NetworkIdOf<T>,
amount: BalanceOf<T>,
bounty: Perbill,
receiver: EvmAddress,
) -> DispatchResult {
let out_amount =
T::NetworkDataHandler::register_outgoing(&network_id, amount)
.map_err(|_| Error::<T>::BridgeOverflow)?;
Self::do_register_evm_exodus(network_id, |exodus_session| {
ExodusRequest::evm_bridge_out(
exodus_session,
network_id,
out_amount,
bounty,
receiver,
)
})
}
fn do_register_evm_governance(
network_id: NetworkIdOf<T>,
target_address: EvmAddress,
governance_action: GovernanceAction,
) -> DispatchResult {
Self::do_register_evm_exodus(network_id, |exodus_session| {
ExodusRequest::evm_governance(
exodus_session,
network_id,
target_address,
governance_action,
)
})
}
fn prepare_round_storage<ClearFn, CompleteFn>(
network_curve: NetworkCurve,
maybe_cursor: Option<BoundedVec<u8, T::MaxCursorLen>>,
@ -4907,20 +4875,6 @@ impl<T: Config> BlockNumberProvider for Pallet<T> {
}
}
impl<T: Config> EvmGovernanceRegistrar<NetworkIdOf<T>, EvmAddress, GovernanceAction> for Pallet<T> {
fn register_evm_governance_action(
network_id: NetworkIdOf<T>,
target_address: EvmAddress,
governance_action: GovernanceAction,
) -> DispatchResult {
Self::do_register_evm_governance(
network_id,
target_address,
governance_action,
)
}
}
impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
type Key = T::AuthorityId;

View File

@ -181,7 +181,7 @@ pub fn new_test_ext() -> (
let networks = vec![
NetworkInitiationBuilder::<MockedNetworkId, u64>::default()
.with_network_id(420)
.with_network_id(31_337)
.with_gatekeeper_amount(0)
.with_network_data(network_data)
.build(),

View File

@ -8,7 +8,6 @@ use sp_std::{
};
use frame_support::{assert_ok, assert_err, traits::Hooks};
use sp_runtime::testing::UintAuthorityId;
use ghost_helpers::networks::NetworkDataBuilder;
use rand::Rng;
use rand_chacha::rand_core::SeedableRng;
@ -1037,55 +1036,16 @@ fn test_all_validators_can_execute_initial_dkg() {
fn test_all_validators_can_execute_dkg() {
let curve = NetworkCurve::Secp256k1;
let authorities_1 = FixedAuthorities::get();
let dummy_address = EvmAddress::repeat_byte(1);
let network_id = 31_337;
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 _ = <Runtime as Config>::NetworkDataHandler::register_incoming(&network_id, 1337).unwrap();
Exodus::do_register_evm_bridge_out_exodus(
network_id,
31_337,
69,
Default::default(),
EvmAddress::from_low_u64_be(1),
).unwrap();
let set_distributor = GovernanceAction::SetDistributor { distributor: dummy_address };
let set_warmup = GovernanceAction::SetWarmupPeriod { warmup_period: 69 };
let update_gatekeeper = GovernanceAction::UpdateGatekeeperAddress { new_gatekeeper: dummy_address };
let set_bounty = GovernanceAction::SetBounty { bounty: 69 };
let set_adjustment = GovernanceAction::SetAdjustment { rate: 69, target: 420, add: true };
let add_pool = GovernanceAction::AddPool { address: dummy_address };
let remove_pool = GovernanceAction::RemovePool { index: 1337 };
let close = GovernanceAction::Close { id: 420 };
let create = GovernanceAction::Create {
market: [69, 420, 1337],
terms: [420, 1337],
token: dummy_address,
intervals: [34, 35],
booleans: [true, true],
};
Exodus::do_register_evm_governance(network_id, dummy_address, set_distributor).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, set_warmup).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, set_bounty).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, set_adjustment).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, update_gatekeeper).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, add_pool).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, remove_pool).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, close).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, create).unwrap();
});
let mut authorities_2 = authorities_1.clone();
@ -1098,25 +1058,11 @@ fn test_all_validators_can_execute_dkg() {
ext.execute_with(|| {
Exodus::do_register_evm_bridge_out_exodus(
network_id,
31_337,
420,
Perbill::from_percent(50),
EvmAddress::from_low_u64_be(2),
).unwrap();
let enable = GovernanceAction::Enable { status: GovernanceStatus::ReserveToken, address: dummy_address, calculator: dummy_address };
let disable = GovernanceAction::Disable { status: GovernanceStatus::LiquidityToken, address: dummy_address };
let forfeit = GovernanceAction::ForfeitReserves { router: dummy_address, liquidity: 420, destroyer_mode: true };
let redeem = GovernanceAction::RedeemReserves { router: dummy_address, amount: 420 };
let withdraw = GovernanceAction::Withdraw { token: dummy_address, amount: 420 };
let audit = GovernanceAction::AuditReserves;
Exodus::do_register_evm_governance(network_id, dummy_address, enable).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, disable).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, forfeit).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, redeem).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, withdraw).unwrap();
Exodus::do_register_evm_governance(network_id, dummy_address, audit).unwrap();
});
let mut authorities_3 = FixedAuthorities::get();
@ -1132,13 +1078,8 @@ fn test_all_validators_can_execute_dkg() {
ExodusSignedBridges::<Runtime>::iter().count()
});
let governances_count = ext.execute_with(|| {
ExodusSignedGovernance::<Runtime>::iter().count()
});
assert_eq!(rotations_count, 3);
assert_eq!(bridges_count, 2);
assert_eq!(governances_count, 15);
}
#[test]

View File

@ -71,70 +71,10 @@ macro_rules! impl_evm_encodable {
}
)*
};
(const_array: $( [ $inner_ty:ty ; $len:expr ] ),* $(,)? ) => {
$(
impl EvmAbiEncode for [ $inner_ty ; $len ] {
#[inline(always)]
fn size(&self) -> usize {
$len * 32
}
#[inline(always)]
fn abi_encode(&self, buffer: &mut [u8], cursor: &mut usize) -> Option<()> {
for item in self.iter() {
EvmAbiEncode::abi_encode(item, buffer, cursor)?;
}
Some(())
}
}
)*
};
(bytes_slice: ) => {
impl EvmAbiEncode for [u8] {
#[inline(always)]
fn size(&self) -> usize {
let content_len = self.len();
let remainder = content_len % 32;
let alignment = if remainder == 0 { 0 } else { 32 - remainder };
32 + content_len + alignment
}
#[inline(always)]
fn abi_encode(&self, buffer: &mut [u8], cursor: &mut usize) -> Option<()> {
if self.size() >= MAX_MESSAGE_SIZE as usize { return None; }
let pointer = cursor.checked_sub(4).map(|x| x.saturating_add(32))?;
let head_pointer = pointer as u32;
EvmAbiEncode::abi_encode(&head_pointer, buffer, cursor);
let content_len = self.len() as u32;
EvmAbiEncode::abi_encode(&content_len, buffer, cursor)?;
let value_slice = buffer.get_mut(*cursor..*cursor + self.len())?;
value_slice.copy_from_slice(self);
*cursor += self.len();
let remainder = self.len() % 32;
if remainder != 0 {
let alignment = 32 - remainder;
let alignment_slice = buffer.get_mut(*cursor..*cursor + alignment)?;
alignment_slice.fill(0);
*cursor += alignment;
}
Some(())
}
}
};
}
impl_evm_encodable!(numeric: u8, u16, u32, u64, u128);
impl_evm_encodable!(bytes_fixed: EvmAddress, EvmBytes32);
impl_evm_encodable!(const_array: [u128; 3], [u128; 2], [u32; 2], [u8; 2]);
impl_evm_encodable!(bytes_slice:);
macro_rules! abi_encode_evm_message {
($buffer:expr, $sig:expr, [ $( $val:expr ),* $(,)? ]) => {{
@ -162,152 +102,6 @@ macro_rules! abi_encode_evm_message {
}};
}
#[derive(Encode, Decode, Clone, Copy, PartialEq, TypeInfo, RuntimeDebug)]
#[repr(u8)]
pub enum GovernanceStatus {
ReserveDepositor = 0,
ReserveToken = 1,
LiquidityDepositor = 2,
LiquidityToken = 3,
RewardManager = 4,
}
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
pub enum GovernanceAction {
SetDistributor { distributor: EvmAddress },
SetWarmupPeriod { warmup_period: u128 },
UpdateGatekeeperAddress { new_gatekeeper: EvmAddress },
SetBounty { bounty: u128 },
AddPool { address: EvmAddress },
RemovePool { index: u128 },
SetAdjustment { rate: u128, target: u128, add: bool },
Enable { status: GovernanceStatus, address: EvmAddress, calculator: EvmAddress },
Disable { status: GovernanceStatus, address: EvmAddress },
ForfeitReserves { router: EvmAddress, liquidity: u128, destroyer_mode: bool },
RedeemReserves { router: EvmAddress, amount: u128 },
Withdraw { token: EvmAddress, amount: u128 },
AuditReserves,
Close { id: u128 },
Create {
market: [u128; 3],
terms: [u128; 2],
token: EvmAddress,
intervals: [u32; 2],
booleans: [bool; 2],
},
}
impl GovernanceAction {
pub fn get_message<'a>(
&self,
message_buffer: &'a mut [u8; MAX_MESSAGE_SIZE as usize],
) -> Option<&'a [u8]> {
match &self {
Self::SetDistributor { distributor } => {
abi_encode_evm_message!(
message_buffer,
"setDistributor(address)",
[distributor]
)
},
Self::SetWarmupPeriod { warmup_period } => {
abi_encode_evm_message!(
message_buffer,
"setWarmupPeriod(uint256)",
[warmup_period]
)
},
Self::UpdateGatekeeperAddress { new_gatekeeper } => {
abi_encode_evm_message!(
message_buffer,
"updateGatekeeperAddress(address)",
[new_gatekeeper]
)
},
Self::SetBounty { bounty } => {
abi_encode_evm_message!(
message_buffer,
"setBounty(uint256)",
[bounty]
)
},
Self::AddPool { address } => {
abi_encode_evm_message!(
message_buffer,
"addPool(address)",
[address]
)
},
Self::RemovePool { index } => {
abi_encode_evm_message!(
message_buffer,
"removePool(uint256)",
[index]
)
},
Self::SetAdjustment { rate, target, add } => {
abi_encode_evm_message!(
message_buffer,
"setAdjustment(uint256,uint256,bool)",
[rate, target, &(*add as u8)]
)
},
Self::Enable { status, address, calculator } => {
abi_encode_evm_message!(
message_buffer,
"enable(uint8,address,address)",
[&(*status as u8), address, calculator]
)
},
Self::Disable { status, address } => {
abi_encode_evm_message!(
message_buffer,
"disable(uint8,address)",
[&(*status as u8), address]
)
},
Self::ForfeitReserves { router, liquidity, destroyer_mode } => {
abi_encode_evm_message!(
message_buffer,
"forfeitReserves(address,uint256,bool)",
[router, liquidity, &(*destroyer_mode as u8)]
)
},
Self::RedeemReserves { router, amount } => {
abi_encode_evm_message!(
message_buffer,
"redeemReserve(address,uint256)",
[router, amount]
)
},
Self::Withdraw { token, amount } => {
abi_encode_evm_message!(
message_buffer,
"withdraw(address,uint256)",
[token, amount]
)
},
Self::AuditReserves => {
abi_encode_evm_message!(message_buffer, "auditReserves()", [])
},
Self::Close { id } => {
abi_encode_evm_message!(message_buffer, "close(uint256)", [id])
},
Self::Create { market, terms, token, intervals, booleans } => {
let booleans_u8 = [booleans[0] as u8, booleans[1] as u8];
abi_encode_evm_message!(
message_buffer,
"create(uint256[3],uint256[2],address,uint32[2],bool[2])",
[market, terms, token, intervals, &booleans_u8]
)
},
}
}
}
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, RuntimeDebug)]
pub struct ExodusRequest<NetworkId, Balance> {
pub r#type: ExodusRequestType<NetworkId, Balance>,
@ -329,12 +123,7 @@ pub enum ExodusRequestType<NetworkId, Balance> {
bounty: Perbill,
receiver: EvmAddress,
},
EvmGovernance {
exodus_session: ExodusSession,
network_id: NetworkId,
target: EvmAddress,
action: GovernanceAction,
},
EvmGovernance { network_id: NetworkId },
UtxoBridgeOut { network_id: NetworkId },
}
@ -355,24 +144,6 @@ where
[exodus_session, public_key, parity]
)
},
ExodusRequestType::EvmGovernance { exodus_session, network_id, target, action } => {
let mut action_buffer = [0u8; MAX_MESSAGE_SIZE as usize];
let action_payload = action.get_message(&mut action_buffer)?;
let mut metadata_buffer = [0u8; 32];
let chain_id_u64: u64 = (*network_id).unique_saturated_into();
metadata_buffer[0..8].copy_from_slice(&chain_id_u64.to_be_bytes());
metadata_buffer[8..28].copy_from_slice(target.as_ref());
let packed_metadata = EvmBytes32::from(&metadata_buffer);
abi_encode_evm_message!(
message_buffer,
"govern(uint256,uint256,bytes)",
[exodus_session, &packed_metadata, action_payload]
)
},
ExodusRequestType::EvmBridgeOut { exodus_session, network_id, amount, bounty, receiver } => {
let mut buffer = [0u8; 32];
buffer[0..20].copy_from_slice(receiver.as_ref());
@ -399,7 +170,7 @@ where
abi_encode_evm_message!(
message_buffer,
"recall(uint256,uint256,uint256)",
"materialize(uint256,uint256,uint256)",
[exodus_session, &amount_u256, &packed_metadata]
)
}
@ -450,21 +221,6 @@ where
Self::default_request_for(evm_bridge_out)
}
pub fn evm_governance(
exodus_session: ExodusSession,
network_id: NetworkId,
target: EvmAddress,
action: GovernanceAction,
) -> Self {
let evm_governance = ExodusRequestType::EvmGovernance {
exodus_session,
network_id,
target,
action,
};
Self::default_request_for(evm_governance)
}
pub fn is_rotation(&self) -> bool {
match &self.r#type {
ExodusRequestType::EvmRotation { .. } | ExodusRequestType::UtxoRotation { .. } => true,
@ -478,255 +234,3 @@ where
Self { r#type: request_type, next_roast_session: Default::default() }
}
}
#[cfg(test)]
mod tests {
use super::*;
use sp_io::hashing::keccak_256;
#[test]
fn test_rotation_message_valid() {
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
let public_key = EvmBytes32::repeat_byte(0x11);
let session = 69u64;
let rotation_request = ExodusRequest::<u64, u128>::evm_rotation(
session,
public_key.clone(),
1,
);
let calldata = rotation_request.get_message(&mut buffer).unwrap();
assert_eq!(calldata.len(), 100);
let expected_hash = keccak_256("rotate(uint256,bytes32,uint8)".as_bytes());
assert_eq!(calldata[0..4], expected_hash[0..4]);
assert_eq!(calldata[35], 0x45);
assert_eq!(&calldata[4..35], &[0u8; 31]);
assert_eq!(&calldata[36..68], public_key.as_ref());
assert_eq!(calldata[99], 1);
assert_eq!(&calldata[68..99], &[0u8; 31]);
}
#[test]
fn test_bridge_out_message_valid() {
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
let receiver = EvmAddress::repeat_byte(0xAA);
let network_id = 420u64;
let session = 69u64;
let bridge_request = ExodusRequest::<u64, u128>::evm_bridge_out(
session,
network_id,
1_000_000u128,
sp_runtime::Perbill::from_percent(1),
receiver.clone()
);
let calldata = bridge_request.get_message(&mut buffer).unwrap();
assert_eq!(calldata.len(), 100);
let expected_hash = keccak_256("recall(uint256,uint256,uint256)".as_bytes());
assert_eq!(calldata[0..4], expected_hash[0..4]);
assert_eq!(calldata[35], 69);
assert_eq!(calldata[67], 0x40);
assert_eq!(calldata[66], 0x42);
assert_eq!(calldata[65], 0x0F);
let metadata_slot = &calldata[68..100];
assert_eq!(&metadata_slot[0..20], receiver.as_ref());
assert_eq!(metadata_slot[27], 0xA4);
assert_eq!(metadata_slot[26], 0x01);
assert_eq!(metadata_slot[31], 0x28);
assert_eq!(metadata_slot[30], 0x5C);
assert_eq!(metadata_slot[29], 0x8F);
assert_eq!(metadata_slot[28], 0x02);
}
#[test]
fn test_governance_message_valid() {
let mut buffer = [0u8; MAX_MESSAGE_SIZE as usize];
let target = EvmAddress::repeat_byte(0xAA);
let network_id = 420u64;
let session = 69u64;
let actions = vec![
GovernanceAction::SetDistributor { distributor: EvmAddress::repeat_byte(0x11) },
GovernanceAction::SetWarmupPeriod { warmup_period: 3600 },
GovernanceAction::UpdateGatekeeperAddress { new_gatekeeper: EvmAddress::repeat_byte(0x22) },
GovernanceAction::SetBounty { bounty: 500 },
GovernanceAction::AddPool { address: EvmAddress::repeat_byte(0x22) },
GovernanceAction::RemovePool { index: 2 },
GovernanceAction::SetAdjustment { rate: 10, target: 100, add: true },
GovernanceAction::Enable {
status: GovernanceStatus::ReserveDepositor,
address: EvmAddress::repeat_byte(0x33),
calculator: EvmAddress::repeat_byte(0x44)
},
GovernanceAction::Disable {
status: GovernanceStatus::ReserveToken,
address: EvmAddress::repeat_byte(0x55)
},
GovernanceAction::ForfeitReserves {
router: EvmAddress::repeat_byte(0x66),
liquidity: 5000,
destroyer_mode: false
},
GovernanceAction::RedeemReserves { router: EvmAddress::repeat_byte(0x77), amount: 10000 },
GovernanceAction::Withdraw { token: EvmAddress::repeat_byte(0x88), amount: 2500 },
GovernanceAction::AuditReserves,
GovernanceAction::Close { id: 99 },
GovernanceAction::Create {
market: [69, 420, 1337],
terms: [69, 420],
token: EvmAddress::repeat_byte(0x99),
intervals: [69, 1337],
booleans: [true, false],
},
];
for (index, action) in actions.into_iter().enumerate() {
let action_clone = action.clone();
let governance_request = ExodusRequest::<u64, u128>::evm_governance(
session,
network_id,
target,
action,
);
let message = governance_request
.get_message(&mut buffer)
.get_or_insert(&[])
.to_vec();
assert!(!message.is_empty(), "Failed to encode action at index {}", index);
let expected_master_hash = keccak_256("govern(uint256,uint256,bytes)".as_bytes());
assert_eq!(message[0..4], expected_master_hash[0..4]);
assert_eq!(message[35], 69);
assert_eq!(&message[4..35], &[0u8; 31]);
assert_eq!(message[43], 0xA4);
assert_eq!(message[42], 0x01);
assert_eq!(&message[44..64], target.as_ref());
assert_eq!(&message[64..68], &[0u8; 4]);
assert_eq!(message[99], 96);
let inner_payload_len = u32::from_be_bytes(message[128..132].try_into().unwrap()) as usize;
let inner_payload = &message[132..132 + inner_payload_len];
assert_eq!((message.len() - 4) % 32, 0);
match action_clone {
GovernanceAction::SetDistributor { distributor } => {
let hash = keccak_256("setDistributor(address)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(&inner_payload[16..36], distributor.as_ref());
},
GovernanceAction::SetWarmupPeriod { warmup_period } => {
let hash = keccak_256("setWarmupPeriod(uint256)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload[inner_payload.len() - 1], warmup_period as u8);
},
GovernanceAction::UpdateGatekeeperAddress { new_gatekeeper } => {
let hash = keccak_256("updateGatekeeperAddress(address)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(&inner_payload[16..36], new_gatekeeper.as_ref());
},
GovernanceAction::SetBounty { bounty } => {
let hash = keccak_256("setBounty(uint256)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload[inner_payload.len() - 1], bounty as u8);
},
GovernanceAction::AddPool { address } => {
let hash = keccak_256("addPool(address)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(&inner_payload[16..36], address.as_ref());
},
GovernanceAction::RemovePool { index } => {
let hash = keccak_256("removePool(uint256)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload[inner_payload.len() - 1], index as u8);
},
GovernanceAction::SetAdjustment { rate, target, add } => {
let hash = keccak_256("setAdjustment(uint256,uint256,bool)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload[35], rate as u8);
assert_eq!(inner_payload[67], target as u8);
assert_eq!(inner_payload[99], add as u8);
},
GovernanceAction::Enable { status, address, calculator } => {
let hash = keccak_256("enable(uint8,address,address)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload[35], status as u8);
assert_eq!(&inner_payload[48..68], address.as_ref());
assert_eq!(&inner_payload[80..100], calculator.as_ref());
},
GovernanceAction::Disable { status, address } => {
let hash = keccak_256("disable(uint8,address)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload[35], status as u8);
assert_eq!(&inner_payload[48..68], address.as_ref());
},
GovernanceAction::ForfeitReserves { router, liquidity, destroyer_mode } => {
let hash = keccak_256("forfeitReserves(address,uint256,bool)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(&inner_payload[16..36], router.as_ref());
assert_eq!(inner_payload[67], liquidity as u8);
assert_eq!(inner_payload[99], destroyer_mode as u8);
},
GovernanceAction::RedeemReserves { router, amount } => {
let hash = keccak_256("redeemReserve(address,uint256)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(&inner_payload[16..36], router.as_ref());
assert_eq!(inner_payload[67], amount as u8);
},
GovernanceAction::Withdraw { token, amount } => {
let hash = keccak_256("withdraw(address,uint256)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(&inner_payload[16..36], token.as_ref());
assert_eq!(inner_payload[67], amount as u8);
},
GovernanceAction::AuditReserves => {
let hash = keccak_256("auditReserves()".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload.len(), 4);
},
GovernanceAction::Close { id } => {
let hash = keccak_256("close(uint256)".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload[inner_payload.len() - 1], id as u8);
},
GovernanceAction::Create { market, terms, token, intervals, booleans } => {
let hash = keccak_256("create(uint256[3],uint256[2],address,uint32[2],bool[2])".as_bytes());
assert_eq!(inner_payload[0..4], hash[0..4]);
assert_eq!(inner_payload.len(), 324);
assert_eq!(inner_payload[35], 69);
assert_eq!(u128::from_be_bytes(inner_payload[20..36].try_into().unwrap()), market[0]);
assert_eq!(u128::from_be_bytes(inner_payload[52..68].try_into().unwrap()), market[1]);
assert_eq!(u128::from_be_bytes(inner_payload[84..100].try_into().unwrap()), market[2]);
assert_eq!(u128::from_be_bytes(inner_payload[116..132].try_into().unwrap()), terms[0]);
assert_eq!(u128::from_be_bytes(inner_payload[148..164].try_into().unwrap()), terms[1]);
assert_eq!(&inner_payload[176..196], token.as_ref());
assert_eq!(u32::from_be_bytes(inner_payload[224..228].try_into().unwrap()), intervals[0]);
assert_eq!(u32::from_be_bytes(inner_payload[256..260].try_into().unwrap()), intervals[1]);
assert_eq!(inner_payload[291], booleans[0] as u8);
assert_eq!(inner_payload[323], booleans[1] as u8);
}
}
}
}
}

View File

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

View File

@ -31,7 +31,7 @@ mod benchmarks {
evm_addr_bytes.copy_from_slice(&pubkey_hash.as_ref()[12..32]);
let dummy_evm_address = EvmAddress::from(evm_addr_bytes);
let target_index = max_proof_depth - 1;
let target_index = 0u32;
let claim_package_init = ClaimPackage {
shares: dummy_shares,
merkle_proof: Default::default(),
@ -40,8 +40,7 @@ mod benchmarks {
};
let preimage_init = claim_package_init.get_preimage(&dummy_evm_address, network_id);
let some_hash = SubstrateKeccakHasher::hash(&preimage_init);
let mut current_hash = some_hash;
let mut current_hash = SubstrateKeccakHasher::hash(&preimage_init);
let mut proof_hashes = Vec::with_capacity(max_proof_depth as usize);
let mut current_index = target_index as usize;
@ -49,15 +48,21 @@ mod benchmarks {
let hash_len = SubstrateKeccakHasher::hash_len();
let mut combined = sp_std::vec![0u8; hash_len * 2];
for _ in 0..max_proof_depth {
proof_hashes.push(some_hash);
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(&current_hash.to_fixed_bytes());
combined[hash_len..].copy_from_slice(&some_hash.to_fixed_bytes());
combined[..hash_len].copy_from_slice(hash_bytes);
combined[hash_len..].copy_from_slice(sibling_bytes_ref);
} else {
combined[..hash_len].copy_from_slice(&some_hash.to_fixed_bytes());
combined[hash_len..].copy_from_slice(&current_hash.to_fixed_bytes());
combined[..hash_len].copy_from_slice(sibling_bytes_ref);
combined[hash_len..].copy_from_slice(hash_bytes);
}
current_hash = SubstrateKeccakHasher::hash(&combined);
@ -84,7 +89,7 @@ mod benchmarks {
GlobalShares::<T>::put(global_state);
let claim_package = ClaimPackage {
index: target_index,
index: 0,
merkle_proof: BoundedVec::try_from(proof_hashes).unwrap(),
shares: dummy_shares,
token_id: 0

View File

@ -7,16 +7,16 @@
// Ghost Network is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Ghost Network. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `ghost_governance`
//! Autogenerated weights for `ghost_claims`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2026-09-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! DATE: 2024-08-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -28,12 +28,12 @@
// --chain=casper-dev
// --steps=50
// --repeat=20
// --pallet=ghost_governance
// --pallet=ghost_claims
// --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096
// --header=./file_header.txt
// --output=./runtime/casper/src/weights/ghost_governance.rs
// --output=./runtime/casper/src/weights/ghost_claims.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
@ -52,25 +52,26 @@ pub trait WeightInfo {
}
impl WeightInfo for () {
/// Storage: `GhostGovernance::MemberShares` (r:1 w:1)
/// Proof: `GhostGovernance::MemberShares` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostGovernance::ClaimedHashes` (r:1 w:1)
/// Proof: `GhostGovernance::ClaimedHashes` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostGovernance::NetworkShares` (r:1 w:1)
/// Proof: `GhostGovernance::NetworkShares` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostGovernance::GlobalShares` (r:1 w:1)
/// Proof: `GhostGovernance::GlobalShares` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `p` is `[1, 20]`.
fn claim(p: u32, ) -> Weight {
/// Storage: `System::Account` (r:2 w:2)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// Storage: `GhostClaims::Total` (r:1 w:1)
/// Proof: `GhostClaims::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `CultCollective::Members` (r:2 w:2)
/// Proof: `CultCollective::Members` (`max_values`: None, `max_size`: Some(42), added: 2517, mode: `MaxEncodedLen`)
/// Storage: `CultCollective::MemberCount` (r:6 w:6)
/// Proof: `CultCollective::MemberCount` (`max_values`: None, `max_size`: Some(14), added: 2489, mode: `MaxEncodedLen`)
/// Storage: `CultCollective::IdToIndex` (r:6 w:12)
/// Proof: `CultCollective::IdToIndex` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
/// Storage: `CultCollective::IndexToId` (r:0 w:6)
/// Proof: `CultCollective::IndexToId` (`max_values`: None, `max_size`: Some(54), added: 2529, mode: `MaxEncodedLen`)
fn claim(_p: u32) -> Weight {
// Proof Size summary in bytes:
// Measured: `283`
// Estimated: `3748`
// Minimum execution time: 216_452_000 picoseconds.
Weight::from_parts(217_152_474, 0)
.saturating_add(Weight::from_parts(0, 3748))
// Standard Error: 17_182
.saturating_add(Weight::from_parts(1_614_265, 0).saturating_mul(p.into()))
.saturating_add(RocksDbWeight::get().reads(4))
.saturating_add(RocksDbWeight::get().writes(4))
// Measured: `896`
// Estimated: `16164`
// Minimum execution time: 754_086_000 picoseconds.
Weight::from_parts(756_147_000, 0)
.saturating_add(Weight::from_parts(0, 16164))
.saturating_add(RocksDbWeight::get().reads(17))
.saturating_add(RocksDbWeight::get().writes(29))
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "ghost-networks"
version = "0.2.9"
version = "0.2.8"
description = "Registry and lifecycle management for external network metadata and cryptographic profiles."
license.workspace = true
authors.workspace = true

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `ghost_networks`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2026-09-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! DATE: 2026-02-26, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -30,7 +30,6 @@
// --repeat=20
// --pallet=ghost_networks
// --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096
// --header=./file_header.txt
// --output=./runtime/casper/src/weights/ghost_networks.rs
@ -58,63 +57,60 @@ pub trait WeightInfo {
fn update_network_type() -> Weight;
fn update_network_curve() -> Weight;
fn update_network_gatekeeper() -> Weight;
fn update_network_topic_name() -> Weight;
fn update_incoming_network_share() -> Weight;
fn update_outgoing_network_share() -> Weight;
fn update_avg_block_speed() -> Weight;
fn remove_network() -> Weight;
}
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`)
/// Storage: `GhostNetworks::NetworkIndexes` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkIndexes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkCurves` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkCurves` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkCurvesVec` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkCurvesVec` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// The range of component `i` is `[1, 65]`.
/// The range of component `j` is `[1, 128]`.
/// The range of component `k` is `[1, 10]`.
fn register_network(i: u32, j: u32, k: u32, ) -> Weight {
/// The range of component `i` is `[1, 20]`.
/// The range of component `j` is `[1, 150]`.
/// The range of component `k` is `[1, 20]`.
fn register_network(_i: u32, j: u32, k: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `6`
// Estimated: `3471`
// Minimum execution time: 60_167_000 picoseconds.
Weight::from_parts(56_015_384, 0)
.saturating_add(Weight::from_parts(0, 3471))
// Standard Error: 1_219
.saturating_add(Weight::from_parts(6_146, 0).saturating_mul(i.into()))
// Standard Error: 617
.saturating_add(Weight::from_parts(37_564, 0).saturating_mul(j.into()))
// Standard Error: 8_216
.saturating_add(Weight::from_parts(864_641, 0).saturating_mul(k.into()))
.saturating_add(RocksDbWeight::get().reads(4))
.saturating_add(RocksDbWeight::get().writes(4))
// Measured: `109`
// Estimated: `3574`
// Minimum execution time: 48_419_000 picoseconds.
Weight::from_parts(35_655_823, 0)
.saturating_add(Weight::from_parts(0, 3574))
// Standard Error: 1_212
.saturating_add(Weight::from_parts(96_762, 0).saturating_mul(j.into()))
// Standard Error: 9_235
.saturating_add(Weight::from_parts(1_460_410, 0).saturating_mul(k.into()))
.saturating_add(RocksDbWeight::get().reads(2))
.saturating_add(RocksDbWeight::get().writes(2))
}
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// The range of component `n` is `[1, 20]`.
fn update_network_selector() -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 43_957_000 picoseconds.
Weight::from_parts(44_541_000, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 48_422_000 picoseconds.
Weight::from_parts(49_987_541, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// The range of component `n` is `[1, 128]`.
/// The range of component `n` is `[1, 150]`.
fn update_network_endpoint(n: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 44_092_000 picoseconds.
Weight::from_parts(45_181_439, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Standard Error: 402
.saturating_add(Weight::from_parts(16_387, 0).saturating_mul(n.into()))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 48_651_000 picoseconds.
Weight::from_parts(50_776_912, 0)
.saturating_add(Weight::from_parts(0, 3804))
// Standard Error: 1_062
.saturating_add(Weight::from_parts(838, 0).saturating_mul(n.into()))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
@ -122,11 +118,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_finality_delay() -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 45_603_000 picoseconds.
Weight::from_parts(46_116_000, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 48_080_000 picoseconds.
Weight::from_parts(51_781_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
@ -134,11 +130,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_rate_limit_delay() -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 45_607_000 picoseconds.
Weight::from_parts(46_615_000, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 47_950_000 picoseconds.
Weight::from_parts(48_925_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
@ -146,11 +142,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_block_deviation() -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 43_510_000 picoseconds.
Weight::from_parts(43_840_000, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 48_324_000 picoseconds.
Weight::from_parts(50_801_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
@ -158,39 +154,38 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_type() -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 43_737_000 picoseconds.
Weight::from_parts(44_347_000, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 46_962_000 picoseconds.
Weight::from_parts(47_729_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
fn update_network_curve() -> Weight {
Default::default()
}
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_gatekeeper() -> Weight {
// Proof Size summary in bytes:
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 48_728_000 picoseconds.
Weight::from_parts(53_054_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkCurves` (r:2 w:2)
/// Proof: `GhostNetworks::NetworkCurves` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkCurvesVec` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkCurvesVec` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
fn update_network_curve() -> Weight {
fn update_network_topic_name() -> Weight {
// Proof Size summary in bytes:
// Measured: `179`
// Estimated: `6119`
// Minimum execution time: 85_784_000 picoseconds.
Weight::from_parts(86_768_000, 0)
.saturating_add(Weight::from_parts(0, 6119))
.saturating_add(RocksDbWeight::get().reads(4))
.saturating_add(RocksDbWeight::get().writes(4))
}
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_network_gatekeeper() -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 44_801_000 picoseconds.
Weight::from_parts(45_240_000, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 48_632_000 picoseconds.
Weight::from_parts(49_954_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
@ -198,11 +193,11 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_incoming_network_share() -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 45_404_000 picoseconds.
Weight::from_parts(46_161_000, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 47_660_000 picoseconds.
Weight::from_parts(53_763_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
@ -210,30 +205,38 @@ impl WeightInfo for () {
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_outgoing_network_share() -> Weight {
// Proof Size summary in bytes:
// Measured: `166`
// Estimated: `3631`
// Minimum execution time: 45_476_000 picoseconds.
Weight::from_parts(46_312_000, 0)
.saturating_add(Weight::from_parts(0, 3631))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 48_164_000 picoseconds.
Weight::from_parts(48_953_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkCurves` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkCurves` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn update_avg_block_speed() -> Weight {
// Proof Size summary in bytes:
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 47_789_000 picoseconds.
Weight::from_parts(52_131_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
}
/// Storage: `GhostNetworks::NetworkIndexes` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkIndexes` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkCurvesVec` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkCurvesVec` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::Networks` (r:1 w:1)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn remove_network() -> Weight {
// Proof Size summary in bytes:
// Measured: `179`
// Estimated: `3644`
// Minimum execution time: 78_480_000 picoseconds.
Weight::from_parts(79_105_000, 0)
.saturating_add(Weight::from_parts(0, 3644))
.saturating_add(RocksDbWeight::get().reads(4))
.saturating_add(RocksDbWeight::get().writes(4))
// Measured: `339`
// Estimated: `3804`
// Minimum execution time: 49_720_000 picoseconds.
Weight::from_parts(50_526_000, 0)
.saturating_add(Weight::from_parts(0, 3804))
.saturating_add(RocksDbWeight::get().reads(2))
.saturating_add(RocksDbWeight::get().writes(2))
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "ghost-nomination-pools"
version = "25.0.1"
version = "25.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package]
name = "ghost-sudo"
version = "0.0.3"
version = "0.0.2"
description = "Port of the sudo pallet because of dependencies issue"
license.workspace = true
authors.workspace = true

View File

@ -16,7 +16,7 @@
//! Autogenerated weights for `ghost_sudo`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2026-09-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! DATE: 2025-07-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
@ -28,7 +28,7 @@
// --chain=casper-dev
// --steps=50
// --repeat=20
// --pallet=ghost_sudo
// --pallet=ghost-sudo
// --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096
@ -57,14 +57,14 @@ pub trait WeightInfo {
/// Weight functions for `ghost_sudo`.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Storage: `GhostSudo::Key` (r:1 w:1)
/// Storage: `GhostSudo::Key` (r:1 w:1)
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn set_key() -> Weight {
// Proof Size summary in bytes:
// Measured: `98`
// Measured: `165`
// Estimated: `1517`
// Minimum execution time: 38_841_000 picoseconds.
Weight::from_parts(39_982_000, 0)
// Minimum execution time: 40_014_000 picoseconds.
Weight::from_parts(40_856_000, 0)
.saturating_add(Weight::from_parts(0, 1517))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
@ -73,10 +73,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn sudo() -> Weight {
// Proof Size summary in bytes:
// Measured: `98`
// Measured: `165`
// Estimated: `1517`
// Minimum execution time: 42_412_000 picoseconds.
Weight::from_parts(43_446_000, 0)
// Minimum execution time: 44_086_000 picoseconds.
Weight::from_parts(45_920_000, 0)
.saturating_add(Weight::from_parts(0, 1517))
.saturating_add(T::DbWeight::get().reads(1))
}
@ -84,10 +84,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn sudo_as() -> Weight {
// Proof Size summary in bytes:
// Measured: `98`
// Measured: `165`
// Estimated: `1517`
// Minimum execution time: 43_006_000 picoseconds.
Weight::from_parts(43_886_000, 0)
// Minimum execution time: 44_106_000 picoseconds.
Weight::from_parts(44_650_000, 0)
.saturating_add(Weight::from_parts(0, 1517))
.saturating_add(T::DbWeight::get().reads(1))
}
@ -95,10 +95,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn remove_key() -> Weight {
// Proof Size summary in bytes:
// Measured: `98`
// Measured: `165`
// Estimated: `1517`
// Minimum execution time: 35_731_000 picoseconds.
Weight::from_parts(36_443_000, 0)
// Minimum execution time: 36_416_000 picoseconds.
Weight::from_parts(37_373_000, 0)
.saturating_add(Weight::from_parts(0, 1517))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
@ -107,14 +107,14 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
// For backwards compatibility and tests.
impl WeightInfo for () {
/// Storage: `GhostSudo::Key` (r:1 w:1)
/// Storage: `GhostSudo::Key` (r:1 w:1)
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn set_key() -> Weight {
// Proof Size summary in bytes:
// Measured: `98`
// Measured: `165`
// Estimated: `1517`
// Minimum execution time: 38_841_000 picoseconds.
Weight::from_parts(39_982_000, 0)
// Minimum execution time: 40_014_000 picoseconds.
Weight::from_parts(40_856_000, 0)
.saturating_add(Weight::from_parts(0, 1517))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))
@ -123,10 +123,10 @@ impl WeightInfo for () {
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn sudo() -> Weight {
// Proof Size summary in bytes:
// Measured: `98`
// Measured: `165`
// Estimated: `1517`
// Minimum execution time: 42_412_000 picoseconds.
Weight::from_parts(43_446_000, 0)
// Minimum execution time: 44_086_000 picoseconds.
Weight::from_parts(45_920_000, 0)
.saturating_add(Weight::from_parts(0, 1517))
.saturating_add(RocksDbWeight::get().reads(1))
}
@ -134,10 +134,10 @@ impl WeightInfo for () {
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn sudo_as() -> Weight {
// Proof Size summary in bytes:
// Measured: `98`
// Measured: `165`
// Estimated: `1517`
// Minimum execution time: 43_006_000 picoseconds.
Weight::from_parts(43_886_000, 0)
// Minimum execution time: 44_106_000 picoseconds.
Weight::from_parts(44_650_000, 0)
.saturating_add(Weight::from_parts(0, 1517))
.saturating_add(RocksDbWeight::get().reads(1))
}
@ -145,10 +145,10 @@ impl WeightInfo for () {
/// Proof: `GhostSudo::Key` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`)
fn remove_key() -> Weight {
// Proof Size summary in bytes:
// Measured: `98`
// Measured: `165`
// Estimated: `1517`
// Minimum execution time: 35_731_000 picoseconds.
Weight::from_parts(36_443_000, 0)
// Minimum execution time: 36_416_000 picoseconds.
Weight::from_parts(37_373_000, 0)
.saturating_add(Weight::from_parts(0, 1517))
.saturating_add(RocksDbWeight::get().reads(1))
.saturating_add(RocksDbWeight::get().writes(1))

View File

@ -1,6 +1,6 @@
[package]
name = "ghost-traits"
version = "0.4.4"
version = "0.4.3"
description = "Shared traits including `GhostHasher`, `NetworkDataBasicHandler`, `BoundedBTreeMap`, `MerkleTree` and more."
license.workspace = true
authors.workspace = true

View File

@ -118,11 +118,3 @@ pub trait MerkleTreeBuilder<A, E>: IdentifierConverter<A, E> {
authority_index: A,
) -> Result<(), E>;
}
pub trait EvmGovernanceRegistrar<NetworkId, EvmAddress, GovernanceAction> {
fn register_evm_governance_action(
network_id: NetworkId,
target_address: EvmAddress,
governance_action: GovernanceAction
) -> frame_support::dispatch::DispatchResult;
}

8
pallets/types/Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "ghost-types"
version = "0.0.1"
license.workspace = true
authors.workspace = true
edition.workspace = true
homepage.workspace = true
repository.workspace = true

1
pallets/types/src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub

View File

@ -1,6 +1,6 @@
[package]
name = "ghost-weaver"
version = "0.0.3"
version = "0.0.2"
description = "Weaving a secure cryptographic tapestry across different external chains."
license.workspace = true
authors.workspace = true
@ -50,30 +50,30 @@ std = [
"frame-support/std",
"frame-system/std",
"frame-benchmarking?/std",
"sp-application-crypto/std",
"sp-runtime/std",
"sp-arithmetic/std",
"sp-keystore?/std",
"sp-core/std",
"sp-std/std",
"sp-io/std",
"ghost-networks/std",
"ghost-helpers/std",
"ghost-traits/std",
"pallet-balances/std",
"sp-application-crypto/std",
"sp-runtime/std",
"sp-arithmetic/std",
"sp-keystore?/std",
"sp-core/std",
"sp-std/std",
"sp-io/std",
"ghost-networks/std",
"ghost-helpers/std",
"ghost-traits/std",
"pallet-balances/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"ghost-networks/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"ghost-helpers/runtime-benchmarks",
"sp-keystore"
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"ghost-networks/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"ghost-helpers/runtime-benchmarks",
"sp-keystore"
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"ghost-networks/try-runtime",
"pallet-balances/try-runtime",
"frame-support/try-runtime",
"frame-system/try-runtime",
"ghost-networks/try-runtime",
"pallet-balances/try-runtime",
]

View File

@ -3,7 +3,6 @@
use super::*;
use frame_benchmarking::v2::*;
use frame_system::RawOrigin;
use sp_runtime::AccountId32;
use sp_std::vec;
use ghost_helpers::networks::NetworkDataBuilder;
@ -136,204 +135,185 @@ mod benchmarks {
#[benchmark]
fn pull_utxo_thread(
a: Linear<1, { crate::types::UTXO_MAX_HISTORY_DEPTH }>,
a: Linear<1, { T::MaxAuthorities::get() as u32 }>,
) -> Result<(), BenchmarkError> {
let session = 69;
let max_history_depth = a as usize;
let (network_id, _, _) = prepare_pallet::<T>(1);
// https://blockstream.info/tx/6fdcb55eaeddae87fdbbd3e6fd8c2b80c1e7e7c1214e1a6e35c06a70e5f21fba?expand
// NOTE: this is the best transaction that matches the max sizes I found,
// would be nice to find exact edge case
let historical_hashes = vec![
hex::decode("00a01520c1d508977a3787523a0f959e14a8df763dc87927c7910000000000000000000036303f2bcf94f752a1d4b0641d1adbc2d80aa89628feefd7f837a74792e26ab8bb276a6ad43a0217bece2e64").expect("Bytes32 from UTXO should be valid"),
hex::decode("0400e020702ff95ecc1b8575cff205bfc24592c87ba09280bd84000000000000000000008ca9c40d5ab762f160661635cade50fd14571dcf5fdf8c463b617caf9b07dc5a3b296a6ad43a02171340d661").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000345457ca4006ddc376db24b7a37db04dfa0b46c1d99267010000000000000000009409d64eb06a6dd83ae2937f70d07222d75505a07f12e756b61a27189851e3bbfe2c6a6ad43a0217a06575b5").expect("Bytes32 from UTXO should be valid"),
hex::decode("004007220e37af053c56a86899e1219107937fd5e83ff61aeb7800000000000000000000c0588f8b7a697ff9f367ec4a69a9998ef8f2552f808b5025b4b8f604d0a145c6123e6a6ad43a0217a662289d").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3feeae586d6f7215f48e857ed7fcf823b27117f2805fe000000000000000000000dcaa345e44c85be86da35ab0f25e2f089f04f66c1e3a3881a8455b1e42ba2500ad3e6a6ad43a0217b3810985").expect("Bytes32 from UTXO should be valid"),
hex::decode("00600520214f05f95e93d1d46c768a910fe0a15da3de556c2a7a01000000000000000000a129b7d281efd307700bff535137324aa0c5decc9829243bb7b29f1cafcbbd6c114b6a6ad43a0217cd209b45").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000df2d608f226bda092f6d8da18e92e3cbb41d5c99c7ddbf20010000000000000000009848dfe4f23c9211df920b37d571b2a4363afac3efb83d7cf4249b6491a6c8dfff4c6a6ad43a02174646c9ff").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000020c69aef55529fcbf6d18aea8a701177317483d63c32d1000000000000000000000c3551d009eb18b1cc5da8420c5e1268c1de482127623b11f74743d46f3f34ebf84e6a6ad43a021796234549").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800820d50e734c76e83a3d2658d1977034372b68362927c06b010000000000000000007b701acfc56d4ef6086eda92cde2c809d6960dca65ec9e617d53e0761f620bb72e506a6ad43a0217416f2f2b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00009f23d562db91d625b878e92f5d410c04775ed88006a18a0300000000000000000000a7b1bbad02565047b4428e2ef0cf3acbd0714c77934e44abc367451b85c3e56be3556a6ad43a0217c3b1aebd").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000003e8c4ec35b8fd1f07d6ff39de67c1ade69a25df69d84030100000000000000000033d4dab1c4958ae6d9cb853278362cbf74d25c1c3c7150889883c7fbdfa5004506566a6ad43a021751a2160f").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a00020dfde782b9446c17ae40a86dcb2e308d4c729a46c162500000000000000000000cadaf134229eba7775042b3d8689553ba93d0ea929f411d3a1a01693b923b1bf22586a6ad43a02172393ef65").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800c204ec04712a453ed72818b60cb9f74931cc5a59bbcac0d0100000000000000000059eb7a758ff3809a2a5010a3e849201314378120b02b6386490c8b11ad56be308d5c6a6ad43a02177bc26d48").expect("Bytes32 from UTXO should be valid"),
hex::decode("00801935e8c63aa1065f46a7d31bc5063be04108bdd3b18dd326020000000000000000009a3cfbb7b79d1d51f11ebd0a28ed2bf29e53d36ccefddff12322ca47d00665076c5d6a6ad43a0217dc5d92d8").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000003644663bcc00a79e38e833e4a16805ae72cc373cb7e51c01000000000000000000a33b3c0378b2a2d213aac062c7cd8b2c2b3a9c11aaeb4824a037863e7bd5fe7701636a6ad43a02173b36822e").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002a4a1da985bd4aa15be31a03fd3efbe77ad0ebabc392ff0100000000000000000077eb14d0e30b97aa2baff829fa7754de88a359e6a3711300f4e2e0c1ad1435829d6b6a6ad43a0217c8ef1999").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000024a4efb58211a7c804ef24ee11f5f9f9db2509be9bc5da010000000000000000001cc7ac2fe2e38bfd4582367690b0521e71c30f0083f68565fd948ad4ee124fb91b6c6a6ad43a0217851e16c0").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060e729537b191715a6f594c55e85574253c84580909a2fa72200000000000000000000fa2959118ac66e3569081e4645f87f9560742290b52ee54f7886b6fa5f83aa3d016d6a6ad43a021708a2ad64").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f6fe5befcf9e4c77cf03673076ff822740622f75cd74e010000000000000000008da0cd1fb34cfd4e58b5d3f1e20f6104e491320d5dc109fe16a455e3d385adb90d6f6a6ad43a02175c26ad30").expect("Bytes32 from UTXO should be valid"),
hex::decode("00204120cd2dba55f0867cff62ee5bab27b0ba85ac58c869f55c00000000000000000000a685eaec339dbb6e4fa52dacd2752291d5bb55dceb0b8b359e5ecbc0b2d1f884506f6a6ad43a0217de2f0c8c").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e01420a16b828d829748aa9602930d3ef1d4c983b86b39a20101000000000000000000d6e8aecebb3748113be25a6522f47e10e63c57fe95a09f35052fdabcc8a68ad819736a6ad43a021729b35edd").expect("Bytes32 from UTXO should be valid"),
hex::decode("008067269f4c1aaf3129211de19714c6a5bb9c5481ea34f044da00000000000000000000734b07e26a80d3345fa74d1450a1b68d95e0714c163dc7b2b3eb9a0aef8b50c934756a6ad43a02172eba7608").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0fc20ed544115339aa1a59249f02f62856feb602ea083f93300000000000000000000d30c9e1e276efd3be62b7cd7194aa7fb0b807f2fecb9a56074247887b2299882f5756a6ad43a021702a2b823").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000202d2c60af64f5b2a415bc46bca915042d5136b46929c501000000000000000000e0e3b49cd8b926a7468831c1b115e14838640cb735833561d551a804cf1a752cc3766a6ad43a0217d81e878d").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f3c41153e725b51dc793b18c0bfd9cfaf14cd091e000402000000000000000000ff9b55b7ed1dcff73f458e48dd2799ae141829586ce0a3902a783f00981c798bff776a6ad43a021700849f4b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200f237376e2f7ed32d9e0818617150255cc5c87bfc43d182c000000000000000000003c08d2ba07dda561bcb53f56fff0780c5d1046686c363743b17e1591de293a8538776a6ad43a02176fda963f").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800020f3ac5bb512764387873548d1cc0d4fef3b70077b6e700100000000000000000035accf350c72501ce6aedd556177cd99090cb4952c7b23fa424ac1f7a282c0315a786a6ad43a02174cf87729").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3fcee6362f1a42288aa20c3f21e9fcde46dcc1a9402d19010000000000000000006e40bfc29eb8859f30d083cefc45482f77946dcb429bcf1e064d1bcbd378f23c0c7b6a6ad43a02173d75f866").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002ae9ef834e71842c871391dd44a09960dd63990dd557e30100000000000000000052b6b1f008e5b0a5f38be6b2082ec17889619f0627f4064106e820364e1cc8072f7a6a6ad43a021740becfc5").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a0ab238496ac097daf6fee7acdd40ef1a503089d76db2256c400000000000000000000a6e564e0de9af79eb797a4b9afb26b5ad56395f3cbb7a9b4bde5a760d140aae8ba7a6a6ad43a021735b5f7f8").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200320e3d603f57832afb5e67c782aa5fd5d8e2d655230b50e020000000000000000005451ec2c708395b414a347863a8cb7ee4a7d8b0309086af4c329c3ba164be5930d7c6a6ad43a02171ffe7b21").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000720159f0a42d5afd3196d6bc4745786b08017e9f2fe65c4010000000000000000002204634460a10b17be10462c08d3a3247e8955da5ec01f525fd0d58b14a5e2ebab826a6ad43a021737c8b684").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000022030d1a71c70fe8d8e994e1dcddcda8c8c5798ea9bb20d000000000000000000005d5579d7b5cc4c5e43d45169c93abf90dc6f212cd462407a48fc144d8315efb35b836a6ad43a0217aeaa2b47").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000222a3e9205528e4d5618a7287d3d2370a41a6cd2d346fb0000000000000000000016d19ca5aad54bceea5245a221fddbaedb3f56fd6b8f12d59af65a167a7ab56aee836a6ad43a02173c540bc8").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3f9ddcd3ff85fdcd54b32df85a1eb8648b211b72a247870000000000000000000043b56016ddc1c29bd76c92a831b4de36a59cc0fb88d294b6faf24339afd8d64de6886a6ad43a0217126de83e").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060c424aa0dedbd17459541b2df58d403e78824d0b306e13888000000000000000000000d05d08f6044eb00963044e75b4dc14417fd7c3acf1f6d2f9eaf9432627d6a93c68a6a6ad43a0217971b219c").expect("Bytes32 from UTXO should be valid"),
hex::decode("00006c2235ade56a30b832a1d86a389853d9d7ef251dcd31d5de0000000000000000000028cbac80a576b4b03407029062c64268eae619201f84de43d65b6cc29d49945d598b6a6ad43a02178216ff0c").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060c924fee183b290d1e5ba0dd2a211888cb9a45ac3261128ca01000000000000000000c64693de6d95445e23df797f3591719428ea07754aad0c5c03707a1696a49316e48c6a6ad43a02172c70405e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c09c217b4715e06ee536c88f2b04f8da84c9be46bb89b337cb0000000000000000000035ed0514da32bff54f234681d567b7bb8bebd48c1981e88a480a0069cf19fae9318f6a6ad43a0217578cf0e8").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00f2089ef5721cd6bfe541cf56a30fe029e8b6a99d426b59b010000000000000000001cc5db1b35955722b2b072be5497665f2bcc0116021fc52ad106b86f85eb7a15ea8f6a6ad43a021726299c25").expect("Bytes32 from UTXO should be valid"),
hex::decode("00400a20b73d674783455e1728c82701ae1c5bab268563697aa001000000000000000000c7ef430a886118fb6bdd0536e867b9b6fc15cb198c7df4f4669c2fb94244445ebc916a6ad43a021757775d4f").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0012028d9ad98ee6302bffc27d2fc51e905e7ff1455e9ad9a000000000000000000005334bd5deb896d99d5f85f762ca5b5057bd8a11fb1f718f794ed67525ce5275639926a6ad43a021742a4ad22").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0982497ed444856620be9d4a2b3f2dd8385aef13794945fc4000000000000000000007a27f7d0b1a20ec5e2f5b69edb844ceb52acbe24cc44b1e486a86105591678c846926a6ad43a02176d3f1083").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800420a90444f33700b0a903d8dd28c7e4b00f1784a4f12c0801000000000000000000068f9295a349845eb2431428cfc318b72eff6d8b828b61533e5b9889be6a455f69926a6ad43a02176536c20e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3f9efdf00d718c728b94e39dde5c42b0450539b1e0d20a02000000000000000000fff04185f99913ff903e7fff46f04e0ae0f132677d10b8fa1537b98be859020c3f946a6ad43a021759b8976c").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002ecf497d98fdd70adce90e8ce350f3d9f14b735f7cd03c010000000000000000003e3c02c9fd4bf5cde2f4f0ef50570669aa586b3b12e1dff52507337198d3d879bc966a6ad43a0217d2822239").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000522c9273bf66ca7ea531cd3409f3b7fb9f228966e67149300000000000000000000ad5c81834cc230f4ea59cd148298080d22cd008a440a75e34d946ea646f94e7791976a6ad43a0217899d978e").expect("Bytes32 from UTXO should be valid"),
hex::decode("008003203404ad959ad7bc9787388e0035542ad5d540f5077130010000000000000000005082dd1fd7487596fe92f1c06261d3f1abd2da19c2116b175d62adc245ae9ccfcf976a6ad43a0217eafb7678").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3f6e2ede80814d029f614eca38ab9c9a15e9400a023d0200000000000000000000429fa6b33b892eb6544a11e0f3728d109acbeb0f9ad59a48ecd3d64e28543a4987986a6ad43a02179c1c0930").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a00820b709f5dde282465f55c4d7e66cb2ba6fc916c0d51c4c01000000000000000000eb37059a5ba1cdd3f3810607c8d194363679bc9f99dcd95652283a12d7603b29ed986a6ad43a02174b733dd8").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f4b173d1bc45aa63418b7bba7c0fa5a5acfe53d22eb1e01000000000000000000f745f6a23d5cc180ff74ad724e3a12bf2bdf6d5d8f1cbacac629b28634fdd3b71c9c6a6ad43a02174c304983").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002830ec33bdc09b86dd4d9e637a2c5c4811989d9bc33505010000000000000000008caab6a74d42b54943d5ab85c80a95f17bdabaaccf27f8e1d18923fe2ad0113c2f9d6a6ad43a0217a53735c3").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a04c25fb6183fac04e92b6a4b899c9ef156babf959dce7c7b600000000000000000000adae556e5b521d5c392f39d3c8695d5cc11dd3234a6c38c7c423ac430fe5d10f2b9f6a6ad43a0217fd964416").expect("Bytes32 from UTXO should be valid"),
hex::decode("00606b202e489dafa11d28ef8c748ed8da4a954c5affb25454bb01000000000000000000e3f9ee43488ffbb8b711222f0540d1fd61bbec8ffbb9ced960dc2352392eeee180a06a6ad43a02170208ea28").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a00b207940814db8828f2f99a835fec3507ac1e3c6b8c7aaf100000000000000000000a4986016840beba7d215510f02f5e88cd41fc4cfc9bee4069ea56a4a7a9cae8715a26a6ad43a02177d018b27").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e04325f4a84a1a7043948c2af0faa632f4735b8dd989f49c250100000000000000000072707db2fc682148e6aa27d4dbdf7c20009db65c848132f76bc1b3a31bcddcb57ca46a6ad43a021777dae935").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3fad0b6289eaa9c8932a76daadd7a5c3bef539fa19708b00000000000000000000dd2c965c6cea3dc01c21466b8b575c24f0b789a79c6e3f6ba7dcbe45740e1fbb9ea86a6ad43a02173bd6dce6").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000022064c18468116c4e6aa84afd708a1dc597a4aeb5e0d26001000000000000000000d0132ba263c4eb125280313ea30d4853b2201973b825588780c5e080eaaa8418c0a96a6ad43a0217d3de833b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00e25575e08652190884e0ce0e963d24dc654eeeb47c77f1900000000000000000000068daf8886ba4daec55638e8f7e06890a186b6e6aefb5e7912b360a5a644bf1704aa6a6ad43a0217693c1a54").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002ccb2e57d6fa6db31eb2fe4b099c98602747060080927a010000000000000000004ae5c82107d3b01d762bd7250842757420ab88bd9eafa531e45ddd5460ac1c4524aa6a6ad43a0217ae883618").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000420385cfb56a9c0aa212ad2d8cfc3be492cb768e7be66e801000000000000000000e47b35c93528a98e5ccc07f7a64120f10fe44a7d2add76f851f2ef1ff86fb35588aa6a6ad43a0217e74aa794").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002ae44f541085b616ee2b6b66143d45b8d9d005a13ee58601000000000000000000eb7efe30fbcae6ef197af5303e922d5f13af046afe6722a44a407de33cfb05ecd1aa6a6ad43a0217cc1c1fc5").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00220ddf782b16cfb698ec47c721caa0e043c6e3045bd7d3f010000000000000000008ebe86fc87779b0ab7b1eeda4f938fa6bff75fdf3f03326d4c3f0f212db1a5df24ac6a6ad43a021787917f4b").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000003a8e0ffb97a26cb108666a56d11cfa7e8083858aefd35c00000000000000000000f741327a673e2680ea856c80fe7c45f495f35c0809c79095d2aa49bdac42d8a91eae6a6ad43a0217ee19f61c").expect("Bytes32 from UTXO should be valid"),
hex::decode("0420a12a06c61bdd24754ca5788b5b98127fa4cad6bfc6b4943000000000000000000000c0bc9db8ba6c3cd5e4852713723ab9462ed8cdff9a8e7a59f106a7d1e5d9596223af6a6ad43a021752931fe7").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a0cd2bcda5fed994deb88252ba588292824dafbfed2be7bb8300000000000000000000b021ceecadb5f6f0fcdec2d4dc38cc9021bec331a411769cdbfa1f0d731756c55fb16a6ad43a02174c791b12").expect("Bytes32 from UTXO should be valid"),
hex::decode("04e05c24b1a2e59ea42a7424eea8fdb9b95d65865090c6745fec01000000000000000000d49392556462b7cc6a324f3297b95655e8558a842829fa4dbe42a8e8740029149ab16a6ad43a021794875146").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a037310cb4c38e4d2d46702721cf104e9adf7a2120c0ddf85e01000000000000000000309c7334a84c50b5274a7efcc0ee46380415322cb2215a0220d84b7db6f96e6ac3b16a6ad43a0217d06362de").expect("Bytes32 from UTXO should be valid"),
hex::decode("00001c2a5253d07fb8f9c845066cd8d88ae9cbe590f2239d323a010000000000000000002430bbca343667d2cee8a3d7a86901914c852f38a92dcc8142f694235c3d8bf334b26a6ad43a0217dd6db83c").expect("Bytes32 from UTXO should be valid"),
hex::decode("00805c22ab4c07fb2ce6a683075bde23e7d94f50b588e8f9aa9c00000000000000000000ae3e39b85b23c403d31143839b34cc074e7eef0ecb1bf27c54e324a5be96676d92b26a6ad43a02177008583b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c004200a2cd7ef7703ae1fb2093c550eb744c3ea18108ae7a800000000000000000000d0bada625a70a2fd6cfaa2aede6d72bf4bdd10b64a52289820832323519d62ef43b56a6ad43a021767cab9b1").expect("Bytes32 from UTXO should be valid"),
hex::decode("008000206d1cce7f0978d68ffdf92d43c7027bdb81b612641586010000000000000000008d818799a9cada0f4f9243f2cad85b8940125850a9ba37f7d1e6fd282c8c62e145b76a6ad43a02179e855276").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060af24e8f12bb06b4a71cf56a91e73a3966e14c17208a54d6501000000000000000000fbc1e7250797d3e71b49e1abaef047d8cf7e16f1c0ff9de688182d503d0cae67d6b86a6ad43a02171ebed5cc").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00220511c75e44d1d627b986749aead0f55ab37f04df146ad0100000000000000000037e94c77e2c639bbec32dc4dd570b31516ea25fd1497156602b5e149f8d391d682c06a6ad43a02176534c3d3").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f78fb96b3c3c7b29aa1915342bddc921bffd01bfbb63d010000000000000000007a5c1741944ca4332ef03742b971469c0c966655b31d10609a8ffbea38a94cfa2dc56a6ad43a0217a35c947e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e004204870e85ab18fcb38d67c35979efc5df4105490b6713f00000000000000000000c7714efab1a223e7fa21c6f87db62b32cdcd048d5b70e59def0d434de384b3e871c66a6ad43a02178f3d7140").expect("Bytes32 from UTXO should be valid"),
hex::decode("004005209f1f0b92d362f5d4f3b1cceab1a7b6e0d2e55e2c38e8010000000000000000000f4e65ca15db0700809fa074c96785754236d3429e2fcf909a0a0cd7e59a31e6c0ce6a6ad43a02172c31d37e").expect("Bytes32 from UTXO should be valid"),
hex::decode("0080e029852c36bc969233723d0d0c7b44c3820b1233edd53c0001000000000000000000b068c891e2d2e65e1d48a74cb19d5e2aba449403d0cc021cf49cec0175226499d5ce6a6ad43a02171413e6c3").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e00020947175283c53840a5fd95ff5fb52a69cbf049640600e00000000000000000000d4ffb8d309f3aaf7023d9e3df8587e63b672b2180b85c0d307cfbf3e334ddb1a5fd76a6ad43a0217d543d85a").expect("Bytes32 from UTXO should be valid"),
hex::decode("00801d21203bd017379dede3b30858ec121ad3afebe66093deaa00000000000000000000b15433a1853ef7eab266109f32e22af002690eea752fa0afcfd517c8c51957ed5ad76a6ad43a0217e750210f").expect("Bytes32 from UTXO should be valid"),
hex::decode("0040032083cc6f37b94764a79231d6aff125a14f964aa83aef2300000000000000000000605c53cb797ad5e44717e9345170a30375813712b4374440b7b2db0c916fcce34ddd6a6ad43a0217ac7dca95").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e00020d8f1948230933cf727b9d64f1e5786939d595727ca0c0000000000000000000064559da1901f51ddb2307790cd717cdb08421a0d596a119ea26c795695e91fb60ade6a6ad43a0217252accd0").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060e524ba12f94ea5504e31ef86e8cfaacd1dfde5f2981a0a1202000000000000000000b7768b6df326e64a6091b06c253adf3ad85d58b6900c9f0262ceeff036c65ae969df6a6ad43a02177e5d71b9").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200a2052a2caca7cbb37e81cafc0d37c29bb530ac9bbc42cc701000000000000000000d2b7cf8533ff1f8f67aa7a9278cea1885a1404465b8d42beee3c22572887406e7be36a6ad43a021723dfac06").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000220550058d8ed56d8640ee35b6684020f73610626342c900000000000000000000adfcd1ef1d32d7394be8a552ced86e00d4a1fecd68c78e047ea79bf6fc002b7a91e46a6ad43a0217ca6118f3").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0c02658c8f4dfd9d02cccdc514498243a7fefb91f9c49069400000000000000000000a48bf36c7ff5543f078df43076242f3992e00a7cf842e80af8f3e1699acb242db3e76a6ad43a0217637c9ff1").expect("Bytes32 from UTXO should be valid"),
hex::decode("002047242bfc14c46c37991c2cef140720b1b3081ef7d87db8d3010000000000000000007f4d937fe1cfa4629e958b43d638b2079ea77e57c9cef7606f07e2fe5e888b18c4e76a6ad43a02178d9c644f").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a091278a26924cfba43b61448a7a64c5b1fee904fb8e811cd70000000000000000000008abe2adedf7edfe2fab80f34a7a930b1267f123679414348649a39ff53230808def6a6ad43a021753c783de").expect("Bytes32 from UTXO should be valid"),
hex::decode("00004830337426f9ece788d4c8241e02589ffea33f898cbe09f501000000000000000000e2e8f5511c6553157451a89067fdcc790097d030bb4bc0690bc17014eef5d2c990f16a6ad43a0217a872716e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e02920546922cd52e7f92111d725d812c1532308eb59fa22ee00000000000000000000fe634310b53673fc6c018af12c64c19060157b1fc3b73d5a5c9caa03cf3565f2baf56a6ad43a0217c76fd370").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0c121fa38469efe9223b571f74e760c96df203d80b08f3b5600000000000000000000f33c1eea09c6d87bbc4d1d2321270c21454495f21ff525534f4e20c85138a592c1f56a6ad43a021792df7b16").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0a126df55ad5154bd8f45fbe0cdb9fc9722783ce4b7a535ac01000000000000000000c533cefab59d506f73176e595df8cea46363e9b5567dff08a163a3c465dc98d14ffc6a6ad43a0217c26d2516").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a09d2b81fd6f7a8e612d81d80d5b5d64859c1b2b2b101bd1fb00000000000000000000800989d2c31d1dc5a3308452b91b1ed40206a030839737953c9d21d6923786451efd6a6ad43a021749e04799").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0d729b34736f399b13a8a2fb7479954d43c2df771c757e23901000000000000000000f7c933bad214186ec2e49c9d1b1585937280868818f320803cf6436e09a8626973016b6ad43a02171b81e870").expect("Bytes32 from UTXO should be valid"),
hex::decode("00601521556ce1a2354410a18c80b0a67be6dc16257be28890ec010000000000000000003059a134b7eca83de9aca917fabb76ee41d97032583222d6840ef22da16b5b92dd016b6ad43a021725071a5b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00602e2064168b2c362c354444ea0828f36d7cdb3572169b615601000000000000000000a4aeaacb4c25d3a83b2f8ea594325d756ec78f290a73c4953f3cbfaff10e3a3792026b6ad43a02170bb4640f").expect("Bytes32 from UTXO should be valid"),
hex::decode("0040c82357a6c79e2fb6f4d4bf95724a4bcc29bde7b449debdec01000000000000000000fa99bac89c24d15717ad877fecfbf734eb0bc75f8fb578f9470a5db668dbb8fbc0046b6ad43a02174b869a7d").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000034395bcc21a6a2c2d3ccbc2773194d11a7ddfebf0e0919000000000000000000006f505e60f36ce9f73494bfbf0c0f058fee1e2e4822c1b0fa766fb9e3251fd9b38e056b6ad43a02172c4c0184").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800d20354b5388fb81effe12c3291a4cb50cc2adc5b98d079b00000000000000000000103e5e5b3d6d17e134cc0c76af0e91fe08d72591bf4c3ad7b6aa869d5d4cb02ba7066b6ad43a02172202f70c").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200e20b3001fb8573b91195cb7b9c1de390d9991f3c07978d3010000000000000000003e6addca9c34eee9459e631d9d08e77c2de70703f102ce7903838cc77208f595c7066b6ad43a02173fa4ae35").expect("Bytes32 from UTXO should be valid"),
hex::decode("006004209e4646297e4d4fd4f60548b0616a359650c35f1de7f30000000000000000000072aff40819e1e686905c68af2e73b9b951be3736437b416986cf18fd71fb8bd95a0b6b6ad43a021729d33887").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000022ee651093128e4598ff28ca297f351401d19696638b380000000000000000000038d529507d803dcf8080875cf2258aa8a551511c24f8b8ae3fa88423b0602748920b6b6ad43a02170846a89b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00608320be57374d6179c78ada919fffb2d9f908f5e18a74ff0501000000000000000000fa2f2dfb7b4d5235da7f1029804e23edbb7d3323af88199fc0ef1b79a1753459120c6b6ad43a02179a132a56").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a0d227a580e546e615e1c532f47d89de7368c30df20e2e781b01000000000000000000e12705f05a4bbf09b87493335471db4f833e12d99fd36d76c5b3279082dd096e580c6b6ad43a02177e704ef5").expect("Bytes32 from UTXO should be valid"),
hex::decode("00600f3912f664c2673dde9ab6886a85a2c9fc4efc177a0cbf4c01000000000000000000f1a81ddd80ef01b4a480de488f15402069ae8683ecc46770878b54fb7991c1a57d0d6b6ad43a0217bb384b12").expect("Bytes32 from UTXO should be valid"),
hex::decode("00803427b9cddcc2df57f4563ae0131adb3dd35bb9917139b95400000000000000000000c0b2ec9353f60fbdf5cf7da0ab0c17a78003bce2052a412c27d12665f76cb555fa136b6ad43a0217066d21e6").expect("Bytes32 from UTXO should be valid"),
hex::decode("0040ec33bb8f6fa5e2f2ed3cf60cf91d6e79fcf7cde05b11087e01000000000000000000e6075b19a084d7c5aaa8484aeff15d8b5db4db88ad69d5ee647a3d9f778fedda61146b6ad43a0217a27b3033").expect("Bytes32 from UTXO should be valid"),
hex::decode("10a0c2227eb8240f150309fcaad8a2be205ddcbf06429a508662010000000000000000007e17cf9282b77723437c083af1aa83482a73fee35c73f110303d402d88fa8bed4c156b6ad43a02174b470b31").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e00320cb4dec5b41a12bc19c29a6d424197f86c3b2ba025e25010000000000000000009d1a60c3889690294fc993f397a4dd1df48b3f9c4bdcb41306c3dedf033e4ee8461b6b6ad43a021763b89d28").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000022052e6e25c9112220845c4c3e7fd939340336d3d33cdb600000000000000000000bfc9920255dcbba49376571e9ce3bcafc87bd36045903ecf4076480d96614b7b051d6b6ad43a02172e1a9b25").expect("Bytes32 from UTXO should be valid"),
hex::decode("00209b22982e9a7ed287539bce7c3e603687aa2d3125079fb86a010000000000000000004102e56d0ce9029acb48c28745a9dce1783074391f3e70c695afdd392f6ad6d0ef1d6b6ad43a021722025f6d").expect("Bytes32 from UTXO should be valid"),
hex::decode("10e0ff3f1bb91d2d09c8f74d7245ec18f7e5b6810a7f461dcdc900000000000000000000ac2b5e4ba6695790ec04953ef4774ece540667da058dc6c0888363c4fe922e0dc81f6b6ad43a021760ea40d6").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0f731f4aa3d9f670eaece00ac84c4c19cc4e2a26ef07851220200000000000000000060ee14b2e84e0f736907009618bc2d8296194d66c7ca0a027c702569990b49090d206b6ad43a0217eeb19de9").expect("Bytes32 from UTXO should be valid"),
hex::decode("0020f92325a882bfdca063304e330248bdc067d51df8e92bcaf800000000000000000000c753e6732da8e5c98b3376480be610cbdf3cb16d836b59ab6362d2d228efedea29206b6ad43a0217c924f2a1").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a0a220f0dc827b72a458a9ce7550312c0a8750d4f068713efa01000000000000000000cc94b5a5e75437a7c856b29b12da804ddb02fe1353bb210da2606d8180ec6fb631206b6ad43a02174e9d590a").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000082063447f3bc8b428d461b82a070be3db9410ab1fc40f24000000000000000000008dc755c30eaa2c22cc7a4a5792e3656f4bf698d38c41ebc4c85165fb8c9c6ded79206b6ad43a02173e731a1f").expect("Bytes32 from UTXO should be valid"),
hex::decode("10c05729b6ea9fbe42fb1d9405e47116cb0424329411d017e1aa0000000000000000000076a747223eaa6d45d3f84e2f6828cdc487c0dbdbad42b08a9b8fffc27665a960a7216b6ad43a02174394d82b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a08520af579ef409a189ab162c788896ad825b38faea3641c401000000000000000000dee9be72bd60eda2ab12e0217e2ca16a8bcb34c32f4972b273b77a17440d00e70a226b6ad43a0217116884ce").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a00620482fd173f0a825fc34f487502c1566555f2862f0a02801000000000000000000bb5482aae60bfd220388693225362b18f72e82f9b5ceb9c6d2f9a61f2c28094fe0296b6ad43a0217fb407034").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00120e0e9282069496b464ef564a9ead03d37ce8e7a9f12c701000000000000000000975e9f48c1083438f32c873d67b2fddfc3c8e130ac9fbc1a53da01c01c3d46c8992a6b6ad43a0217ed908988").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200723899fc0d3576718c15a6719c4bc71a91bd3ccc96192ec0000000000000000000004fdb6ab38260ca750671d7a6637ef75a651448c82cfc14554d57e2748be2be9722e6b6ad43a02178a807416").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3fbf073df0898e0324336409d64b6b11987fd4465bd82900000000000000000000f4e8fc5a02f4d8f4311eb5fbf73592c88906b0bce6a08b6e321e6c7b19509dfe8f326b6ad43a02175cba391b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000b2080a47bfbe3066208d4fc39e065d584930a323adb645b0100000000000000000044ad1fa9768359f8528ddcbee3b5f1c773f184fabb6bf87d883e91b0f3f15b89d8316b6ad43a0217329de815").expect("Bytes32 from UTXO should be valid"),
hex::decode("006003204682f5d50b7c8bdea389f6c43515d3459584ab50c406010000000000000000003d441907ec00061b73368da7754ad305e6fd796cb4cf9d3410d5a65927d8e6ce74356b6ad43a02174b0fcdc3").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000d3255924665d3d5fe933b16e09b06dcdd3bf7cce977223690000000000000000000024f812c8d99a9596021d3934a646bd50db9ca98931f3228c236952ac222217d3fe356b6ad43a0217effcbbff").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f11bce3edc9ad7d6858a81f240977adb5517ef078ac5600000000000000000000a11d0de0146f427f426965160dbb0db66cebb6eb805bb3af11ee21924f2bdd71383c6b6ad43a0217936d08ca").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0002007bb096f631e7168dcda31d75201201e543037a0b43300000000000000000000a2a7803b593fbcd881866db771b59f2f98f5f69600460fb6ad553867a1e00a00323e6b6ad43a02170dbeda27").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000205a18258ccf12385ebd72c8f4f0aa2f5b5c5ec841ce10000000000000000000004a994b5f6c109f3cf616de3c0641711d1d4b848c7a04fe6e243765f67ec9cac875406b6ad43a02170d80ed5a").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0722b62395602530b6d60060a8fce332cd1908f21b30b8be4010000000000000000009508e51190aa63ec2298af3cb644eeb1498c0d83d67680efe30d5fd1f6a95d6d7e426b6ad43a02179c08e6e0").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a02320b4b25be6c2ba4576586b90f8c4c3732648680cc5c2d901000000000000000000e5865a3d45646d51b65855b4b9a972198fca36241574a652ecfbab67b3f6256f97456b6ad43a021715c30439").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000030ee8847f7a144b68c6e1e0bef2b4183db01bf825d6d05020000000000000000009798b0f81dc791ce7b17eec0d89ef9db7a2b541e9f582fb2387fd9b642418faa6e476b6ad43a0217a06ef431").expect("Bytes32 from UTXO should be valid"),
hex::decode("00804521440b70d25839dbc3dd0bccd37ef751d50e576188eaa500000000000000000000314ff0850863609b917541ec201a10cd9f47f69cd2d1bf267cdb19fe3e91238bcc486b6ad43a02175e15bd74").expect("Bytes32 from UTXO should be valid"),
hex::decode("000065337e07a76349f99f3eaedfbd7ec9b048ae462fc439cddf0100000000000000000000268bf66e3c00ffff66a507729af9df227492b86f436331ebad0241ad055fe97b516b6ad43a021729b64713").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000022b936d35a2f4a755778159e39d6d80b5946bbf15b7c0b01000000000000000000640504d1606de9fce2fd0be5304c553b7f7092bd5f18c291e3fb1c63a973194fc3566b6ad43a021725c6c2d8").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000020301ba83277f8012e1902f97eea3e53d0515ef73319f201000000000000000000f8a415b0a937ef5175c9715ac98e3373e373afad63cbc9c8541c51119d91115fca5b6b6ad43a02176c9b53e1").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800420ec8823f23684b5a607fa9d6194dc174497f8501a194301000000000000000000af001c7d8797bdc2f8f45149d1f4cd394903e12d59c1f8afbcdbdce3b9925436665d6b6ad43a021776224a13").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000020465a566082cb8faeeb44e097377a9174a11b65a051ff010000000000000000000b6ef86b33a25b37856c2e7c68543a5066dbe67c2a087c8f4199eb289357b17360616b6ad43a021776fc5e72").expect("Bytes32 from UTXO should be valid"),
hex::decode("10e0a02c5d89719ab4dce3ed69c543336776072cdcca1c26514301000000000000000000e860d743e10db71b2b7c5a1fadb2cea11ab7200ba04b4b776fd55d0939dc6cbc61616b6ad43a02171151725e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00606e31bb3cc5e304822bfdf4506cc3b2e0aeb98a7b21280a0f01000000000000000000c897183f710feca8271a8709df053983a6d4489610a73d85b9f0014f58dd770262636b6ad43a0217a723ee06").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0812002e5d76425f391738eac0c614d8afc795fde8c0dbf7d010000000000000000008c6bae74a46ad9f2905e5258d4adaf61af2bcf7c87e86a22f084f11710d58e2b36646b6ad43a021795ac6c1e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00601820856aed25759848cd1ad02caec25afdc0cf17e9ffa0aa01000000000000000000c17d5c0a7bf4af165552c3e91b4d98f4d2afa2938e7b1bdf0912f1e850680a1c53656b6ad43a0217193b3d87").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e02c3ade01a429e0f5c328824f4ee063b98f24ff3b0dc0db08000000000000000000009d0b402f41ab9c16e08f95de962044b206413f878608abca2015ee2074713078606d6b6ad43a0217c0650150").expect("Bytes32 from UTXO should be valid"),
hex::decode("00008f2604b952dcd44dfcb61080ad77c5b626efd760e5f8ac8401000000000000000000ee81697e6cf7f41db37b63a9680906d3023be7a905785ef1b5ebd03fd22dd8bb2d6f6b6ad43a0217287aa17f").expect("Bytes32 from UTXO should be valid"),
hex::decode("008017262c315a069a8896ec04d88ef423ff5cb3845320a6f123010000000000000000002d42d9519e62f5a48d4880b0ff0cd8021a38eadd469a2f7aabd0886061026a5026706b6ad43a02172ea14dd2").expect("Bytes32 from UTXO should be valid"),
];
let root_string =
hex::decode("00000000000000000000662f626dbc3c06161a324d879fadcd0293d8e0884a1d")
.expect("Bitcoin Root hex should be valid");
let expected_root = H256::from_slice(&root_string);
LoomStates::<T>::insert(&network_id, &session, expected_root);
let receiver_32: [u8; 32] =
hex::decode("6969696969696969696969696969696969696969696969696969696969696969")
.expect("Bytes32 from UTXO should be valid")
.try_into()
.expect("Receiver address must be exactly 32 bytes");
let receiver_account = sp_runtime::AccountId32::from(receiver_32);
let receiver_account = AccountId32::from(receiver_32);
let transfer_amount: BalanceOf<T> = 140_693u64.unique_saturated_into();
let ancestry_headers_vec: Vec<Vec<u8>> = historical_hashes
.iter()
.take(max_history_depth)
.cloned()
.collect();
let gettxproof_bytes = hex::decode("008008201643a05d24fe1f015bf472fdedd8ef39dd8247568d3901000000000000000000569ac8f0aed0c5b632dd1dcc031f3d826a170e13cd8176430a2873a33d4694c2501f6a6ad43a02178dbac0d66b1600000e88be94dbcedc3f32bce789eb4512c68b39b91b54c4f2913e84baf7bae21bdc466d954b10876c1e8ad6591461027236c9a471883f96c028a7d1f08deb833f56fa18f457a6faa9c41340be484af67e444f8565b03085e1392fa2d56962f89919c4fcfff99fc6e92be067d01028fb54e8dc1e8425f0ef6bf1cc64220a2ba22163666eb01f99648e8c2af1bb1a0e1ba297f0244a09aa6a6ff87092312b02e8d75aef61e5c08f5b59184a45855e987c5ea114e5da61e55337bfae99f3a2e9601e72ae6036633dc97631609813a30d1185f98e7d6effc4a0330db0394da388c0058e9a730a62d8c679c35bf8d270ca8b95cec7d848729cdfd94a284f060f353b379bfc36310ac78306183a056a04156efd7e77661ce7ba50a4ef9f9e6b3681dfb39d8d0161ad0d2ec46834b5f270b67aa63a8a5b69287e8606b8a438785f8a5af66f84a2641438ba4a5fa22029227e9c2ddb6f23867b112c027d2fc2cf031a46c874701768b5c4983959b98d98736a2ed5ab0dd064ee24e49a3a7dac63e8b857ad4c8b5aa0cf22a7eac3180f3a54630b486de928ecf590e807d2e821818e2fe7e86610187d6673a6f95c639af80a7a7710b0088d44057ca61bdf5f4d5ba68d46b88e4304ffb70000").expect("Bytes32 from UTXO should be valid");
let dynamic_trusted_root = if ancestry_headers_vec.is_empty() {
let first_sha = sp_io::hashing::sha2_256(&gettxproof_bytes[..80]);
let mut native_le = sp_io::hashing::sha2_256(&first_sha);
native_le.reverse();
H256::from(native_le)
} else {
let last_header = ancestry_headers_vec.last().unwrap();
let first_sha = sp_io::hashing::sha2_256(&last_header[..80]);
let mut native_le = sp_io::hashing::sha2_256(&first_sha);
native_le.reverse();
H256::from(native_le)
};
LoomStates::<T>::insert(&network_id, &session, dynamic_trusted_root);
let payload = ThreadPayload::new(12, transfer_amount, receiver_account);
let utxo_thread_proof = UtxoThreadProof::new(
1,
0,
transfer_amount,
payload,
gettxproof_bytes,
hex::decode("008008201643a05d24fe1f015bf472fdedd8ef39dd8247568d3901000000000000000000569ac8f0aed0c5b632dd1dcc031f3d826a170e13cd8176430a2873a33d4694c2501f6a6ad43a02178dbac0d66b1600000e88be94dbcedc3f32bce789eb4512c68b39b91b54c4f2913e84baf7bae21bdc466d954b10876c1e8ad6591461027236c9a471883f96c028a7d1f08deb833f56fa18f457a6faa9c41340be484af67e444f8565b03085e1392fa2d56962f89919c4fcfff99fc6e92be067d01028fb54e8dc1e8425f0ef6bf1cc64220a2ba22163666eb01f99648e8c2af1bb1a0e1ba297f0244a09aa6a6ff87092312b02e8d75aef61e5c08f5b59184a45855e987c5ea114e5da61e55337bfae99f3a2e9601e72ae6036633dc97631609813a30d1185f98e7d6effc4a0330db0394da388c0058e9a730a62d8c679c35bf8d270ca8b95cec7d848729cdfd94a284f060f353b379bfc36310ac78306183a056a04156efd7e77661ce7ba50a4ef9f9e6b3681dfb39d8d0161ad0d2ec46834b5f270b67aa63a8a5b69287e8606b8a438785f8a5af66f84a2641438ba4a5fa22029227e9c2ddb6f23867b112c027d2fc2cf031a46c874701768b5c4983959b98d98736a2ed5ab0dd064ee24e49a3a7dac63e8b857ad4c8b5aa0cf22a7eac3180f3a54630b486de928ecf590e807d2e821818e2fe7e86610187d6673a6f95c639af80a7a7710b0088d44057ca61bdf5f4d5ba68d46b88e4304ffb70000").expect("Bytes32 from UTXO should be valid"),
hex::decode("020000000001029ee4235efd4a3cb183d4c311ce858eeee7748263a28afd3d861bac1cb4a8d368010000000001000000d7c5869bfffaa1877d0ecd37e46dc70c232a16f7955e635d57f926d1b3e640bf0100000000ffffffff02ff490b0000000000160014f635b17877709ba3c5acbe153f38a47a733f5b169525020000000000160014c6e4e0f822c31540b4b05903ce3c67b6cff8e6d40247304402200f2f3763fad59d38b4e101b9675450c0a54d45fe17e2b1babde0d0ce6051ea5b0220643e71d66752c0f1bd30dc0897305da77f223d14c781e86063ac181ad7fb90b6012102aad4cca3dab6427bc754a5a123de32cd037e7177fade9f72d83088b00066cffc0247304402200c8f1ff8230813e5e4ab8ec802c614bc8705c407c5958d64dd79cc8422d85a6202203ea832d581c404200b5974fd1a11abfe1ebac213842083cb02eba3f253c8c2aa012102d70df1d4d58701adab82b4816e0640c27403d1fab859ca9f47cb6eccca3dd96200000000").expect("Bytes32 from UTXO should be valid"),
ancestry_headers_vec,
vec![
hex::decode("00a01520c1d508977a3787523a0f959e14a8df763dc87927c7910000000000000000000036303f2bcf94f752a1d4b0641d1adbc2d80aa89628feefd7f837a74792e26ab8bb276a6ad43a0217bece2e64").expect("Bytes32 from UTXO should be valid"),
hex::decode("0400e020702ff95ecc1b8575cff205bfc24592c87ba09280bd84000000000000000000008ca9c40d5ab762f160661635cade50fd14571dcf5fdf8c463b617caf9b07dc5a3b296a6ad43a02171340d661").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000345457ca4006ddc376db24b7a37db04dfa0b46c1d99267010000000000000000009409d64eb06a6dd83ae2937f70d07222d75505a07f12e756b61a27189851e3bbfe2c6a6ad43a0217a06575b5").expect("Bytes32 from UTXO should be valid"),
hex::decode("004007220e37af053c56a86899e1219107937fd5e83ff61aeb7800000000000000000000c0588f8b7a697ff9f367ec4a69a9998ef8f2552f808b5025b4b8f604d0a145c6123e6a6ad43a0217a662289d").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3feeae586d6f7215f48e857ed7fcf823b27117f2805fe000000000000000000000dcaa345e44c85be86da35ab0f25e2f089f04f66c1e3a3881a8455b1e42ba2500ad3e6a6ad43a0217b3810985").expect("Bytes32 from UTXO should be valid"),
hex::decode("00600520214f05f95e93d1d46c768a910fe0a15da3de556c2a7a01000000000000000000a129b7d281efd307700bff535137324aa0c5decc9829243bb7b29f1cafcbbd6c114b6a6ad43a0217cd209b45").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000df2d608f226bda092f6d8da18e92e3cbb41d5c99c7ddbf20010000000000000000009848dfe4f23c9211df920b37d571b2a4363afac3efb83d7cf4249b6491a6c8dfff4c6a6ad43a02174646c9ff").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000020c69aef55529fcbf6d18aea8a701177317483d63c32d1000000000000000000000c3551d009eb18b1cc5da8420c5e1268c1de482127623b11f74743d46f3f34ebf84e6a6ad43a021796234549").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800820d50e734c76e83a3d2658d1977034372b68362927c06b010000000000000000007b701acfc56d4ef6086eda92cde2c809d6960dca65ec9e617d53e0761f620bb72e506a6ad43a0217416f2f2b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00009f23d562db91d625b878e92f5d410c04775ed88006a18a0300000000000000000000a7b1bbad02565047b4428e2ef0cf3acbd0714c77934e44abc367451b85c3e56be3556a6ad43a0217c3b1aebd").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000003e8c4ec35b8fd1f07d6ff39de67c1ade69a25df69d84030100000000000000000033d4dab1c4958ae6d9cb853278362cbf74d25c1c3c7150889883c7fbdfa5004506566a6ad43a021751a2160f").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a00020dfde782b9446c17ae40a86dcb2e308d4c729a46c162500000000000000000000cadaf134229eba7775042b3d8689553ba93d0ea929f411d3a1a01693b923b1bf22586a6ad43a02172393ef65").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800c204ec04712a453ed72818b60cb9f74931cc5a59bbcac0d0100000000000000000059eb7a758ff3809a2a5010a3e849201314378120b02b6386490c8b11ad56be308d5c6a6ad43a02177bc26d48").expect("Bytes32 from UTXO should be valid"),
hex::decode("00801935e8c63aa1065f46a7d31bc5063be04108bdd3b18dd326020000000000000000009a3cfbb7b79d1d51f11ebd0a28ed2bf29e53d36ccefddff12322ca47d00665076c5d6a6ad43a0217dc5d92d8").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000003644663bcc00a79e38e833e4a16805ae72cc373cb7e51c01000000000000000000a33b3c0378b2a2d213aac062c7cd8b2c2b3a9c11aaeb4824a037863e7bd5fe7701636a6ad43a02173b36822e").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002a4a1da985bd4aa15be31a03fd3efbe77ad0ebabc392ff0100000000000000000077eb14d0e30b97aa2baff829fa7754de88a359e6a3711300f4e2e0c1ad1435829d6b6a6ad43a0217c8ef1999").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000024a4efb58211a7c804ef24ee11f5f9f9db2509be9bc5da010000000000000000001cc7ac2fe2e38bfd4582367690b0521e71c30f0083f68565fd948ad4ee124fb91b6c6a6ad43a0217851e16c0").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060e729537b191715a6f594c55e85574253c84580909a2fa72200000000000000000000fa2959118ac66e3569081e4645f87f9560742290b52ee54f7886b6fa5f83aa3d016d6a6ad43a021708a2ad64").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f6fe5befcf9e4c77cf03673076ff822740622f75cd74e010000000000000000008da0cd1fb34cfd4e58b5d3f1e20f6104e491320d5dc109fe16a455e3d385adb90d6f6a6ad43a02175c26ad30").expect("Bytes32 from UTXO should be valid"),
hex::decode("00204120cd2dba55f0867cff62ee5bab27b0ba85ac58c869f55c00000000000000000000a685eaec339dbb6e4fa52dacd2752291d5bb55dceb0b8b359e5ecbc0b2d1f884506f6a6ad43a0217de2f0c8c").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e01420a16b828d829748aa9602930d3ef1d4c983b86b39a20101000000000000000000d6e8aecebb3748113be25a6522f47e10e63c57fe95a09f35052fdabcc8a68ad819736a6ad43a021729b35edd").expect("Bytes32 from UTXO should be valid"),
hex::decode("008067269f4c1aaf3129211de19714c6a5bb9c5481ea34f044da00000000000000000000734b07e26a80d3345fa74d1450a1b68d95e0714c163dc7b2b3eb9a0aef8b50c934756a6ad43a02172eba7608").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0fc20ed544115339aa1a59249f02f62856feb602ea083f93300000000000000000000d30c9e1e276efd3be62b7cd7194aa7fb0b807f2fecb9a56074247887b2299882f5756a6ad43a021702a2b823").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000202d2c60af64f5b2a415bc46bca915042d5136b46929c501000000000000000000e0e3b49cd8b926a7468831c1b115e14838640cb735833561d551a804cf1a752cc3766a6ad43a0217d81e878d").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f3c41153e725b51dc793b18c0bfd9cfaf14cd091e000402000000000000000000ff9b55b7ed1dcff73f458e48dd2799ae141829586ce0a3902a783f00981c798bff776a6ad43a021700849f4b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200f237376e2f7ed32d9e0818617150255cc5c87bfc43d182c000000000000000000003c08d2ba07dda561bcb53f56fff0780c5d1046686c363743b17e1591de293a8538776a6ad43a02176fda963f").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800020f3ac5bb512764387873548d1cc0d4fef3b70077b6e700100000000000000000035accf350c72501ce6aedd556177cd99090cb4952c7b23fa424ac1f7a282c0315a786a6ad43a02174cf87729").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3fcee6362f1a42288aa20c3f21e9fcde46dcc1a9402d19010000000000000000006e40bfc29eb8859f30d083cefc45482f77946dcb429bcf1e064d1bcbd378f23c0c7b6a6ad43a02173d75f866").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002ae9ef834e71842c871391dd44a09960dd63990dd557e30100000000000000000052b6b1f008e5b0a5f38be6b2082ec17889619f0627f4064106e820364e1cc8072f7a6a6ad43a021740becfc5").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a0ab238496ac097daf6fee7acdd40ef1a503089d76db2256c400000000000000000000a6e564e0de9af79eb797a4b9afb26b5ad56395f3cbb7a9b4bde5a760d140aae8ba7a6a6ad43a021735b5f7f8").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200320e3d603f57832afb5e67c782aa5fd5d8e2d655230b50e020000000000000000005451ec2c708395b414a347863a8cb7ee4a7d8b0309086af4c329c3ba164be5930d7c6a6ad43a02171ffe7b21").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000720159f0a42d5afd3196d6bc4745786b08017e9f2fe65c4010000000000000000002204634460a10b17be10462c08d3a3247e8955da5ec01f525fd0d58b14a5e2ebab826a6ad43a021737c8b684").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000022030d1a71c70fe8d8e994e1dcddcda8c8c5798ea9bb20d000000000000000000005d5579d7b5cc4c5e43d45169c93abf90dc6f212cd462407a48fc144d8315efb35b836a6ad43a0217aeaa2b47").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000222a3e9205528e4d5618a7287d3d2370a41a6cd2d346fb0000000000000000000016d19ca5aad54bceea5245a221fddbaedb3f56fd6b8f12d59af65a167a7ab56aee836a6ad43a02173c540bc8").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3f9ddcd3ff85fdcd54b32df85a1eb8648b211b72a247870000000000000000000043b56016ddc1c29bd76c92a831b4de36a59cc0fb88d294b6faf24339afd8d64de6886a6ad43a0217126de83e").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060c424aa0dedbd17459541b2df58d403e78824d0b306e13888000000000000000000000d05d08f6044eb00963044e75b4dc14417fd7c3acf1f6d2f9eaf9432627d6a93c68a6a6ad43a0217971b219c").expect("Bytes32 from UTXO should be valid"),
hex::decode("00006c2235ade56a30b832a1d86a389853d9d7ef251dcd31d5de0000000000000000000028cbac80a576b4b03407029062c64268eae619201f84de43d65b6cc29d49945d598b6a6ad43a02178216ff0c").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060c924fee183b290d1e5ba0dd2a211888cb9a45ac3261128ca01000000000000000000c64693de6d95445e23df797f3591719428ea07754aad0c5c03707a1696a49316e48c6a6ad43a02172c70405e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c09c217b4715e06ee536c88f2b04f8da84c9be46bb89b337cb0000000000000000000035ed0514da32bff54f234681d567b7bb8bebd48c1981e88a480a0069cf19fae9318f6a6ad43a0217578cf0e8").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00f2089ef5721cd6bfe541cf56a30fe029e8b6a99d426b59b010000000000000000001cc5db1b35955722b2b072be5497665f2bcc0116021fc52ad106b86f85eb7a15ea8f6a6ad43a021726299c25").expect("Bytes32 from UTXO should be valid"),
hex::decode("00400a20b73d674783455e1728c82701ae1c5bab268563697aa001000000000000000000c7ef430a886118fb6bdd0536e867b9b6fc15cb198c7df4f4669c2fb94244445ebc916a6ad43a021757775d4f").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0012028d9ad98ee6302bffc27d2fc51e905e7ff1455e9ad9a000000000000000000005334bd5deb896d99d5f85f762ca5b5057bd8a11fb1f718f794ed67525ce5275639926a6ad43a021742a4ad22").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0982497ed444856620be9d4a2b3f2dd8385aef13794945fc4000000000000000000007a27f7d0b1a20ec5e2f5b69edb844ceb52acbe24cc44b1e486a86105591678c846926a6ad43a02176d3f1083").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800420a90444f33700b0a903d8dd28c7e4b00f1784a4f12c0801000000000000000000068f9295a349845eb2431428cfc318b72eff6d8b828b61533e5b9889be6a455f69926a6ad43a02176536c20e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3f9efdf00d718c728b94e39dde5c42b0450539b1e0d20a02000000000000000000fff04185f99913ff903e7fff46f04e0ae0f132677d10b8fa1537b98be859020c3f946a6ad43a021759b8976c").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002ecf497d98fdd70adce90e8ce350f3d9f14b735f7cd03c010000000000000000003e3c02c9fd4bf5cde2f4f0ef50570669aa586b3b12e1dff52507337198d3d879bc966a6ad43a0217d2822239").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000522c9273bf66ca7ea531cd3409f3b7fb9f228966e67149300000000000000000000ad5c81834cc230f4ea59cd148298080d22cd008a440a75e34d946ea646f94e7791976a6ad43a0217899d978e").expect("Bytes32 from UTXO should be valid"),
hex::decode("008003203404ad959ad7bc9787388e0035542ad5d540f5077130010000000000000000005082dd1fd7487596fe92f1c06261d3f1abd2da19c2116b175d62adc245ae9ccfcf976a6ad43a0217eafb7678").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3f6e2ede80814d029f614eca38ab9c9a15e9400a023d0200000000000000000000429fa6b33b892eb6544a11e0f3728d109acbeb0f9ad59a48ecd3d64e28543a4987986a6ad43a02179c1c0930").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a00820b709f5dde282465f55c4d7e66cb2ba6fc916c0d51c4c01000000000000000000eb37059a5ba1cdd3f3810607c8d194363679bc9f99dcd95652283a12d7603b29ed986a6ad43a02174b733dd8").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f4b173d1bc45aa63418b7bba7c0fa5a5acfe53d22eb1e01000000000000000000f745f6a23d5cc180ff74ad724e3a12bf2bdf6d5d8f1cbacac629b28634fdd3b71c9c6a6ad43a02174c304983").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002830ec33bdc09b86dd4d9e637a2c5c4811989d9bc33505010000000000000000008caab6a74d42b54943d5ab85c80a95f17bdabaaccf27f8e1d18923fe2ad0113c2f9d6a6ad43a0217a53735c3").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a04c25fb6183fac04e92b6a4b899c9ef156babf959dce7c7b600000000000000000000adae556e5b521d5c392f39d3c8695d5cc11dd3234a6c38c7c423ac430fe5d10f2b9f6a6ad43a0217fd964416").expect("Bytes32 from UTXO should be valid"),
hex::decode("00606b202e489dafa11d28ef8c748ed8da4a954c5affb25454bb01000000000000000000e3f9ee43488ffbb8b711222f0540d1fd61bbec8ffbb9ced960dc2352392eeee180a06a6ad43a02170208ea28").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a00b207940814db8828f2f99a835fec3507ac1e3c6b8c7aaf100000000000000000000a4986016840beba7d215510f02f5e88cd41fc4cfc9bee4069ea56a4a7a9cae8715a26a6ad43a02177d018b27").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e04325f4a84a1a7043948c2af0faa632f4735b8dd989f49c250100000000000000000072707db2fc682148e6aa27d4dbdf7c20009db65c848132f76bc1b3a31bcddcb57ca46a6ad43a021777dae935").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0ff3fad0b6289eaa9c8932a76daadd7a5c3bef539fa19708b00000000000000000000dd2c965c6cea3dc01c21466b8b575c24f0b789a79c6e3f6ba7dcbe45740e1fbb9ea86a6ad43a02173bd6dce6").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000022064c18468116c4e6aa84afd708a1dc597a4aeb5e0d26001000000000000000000d0132ba263c4eb125280313ea30d4853b2201973b825588780c5e080eaaa8418c0a96a6ad43a0217d3de833b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00e25575e08652190884e0ce0e963d24dc654eeeb47c77f1900000000000000000000068daf8886ba4daec55638e8f7e06890a186b6e6aefb5e7912b360a5a644bf1704aa6a6ad43a0217693c1a54").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002ccb2e57d6fa6db31eb2fe4b099c98602747060080927a010000000000000000004ae5c82107d3b01d762bd7250842757420ab88bd9eafa531e45ddd5460ac1c4524aa6a6ad43a0217ae883618").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000420385cfb56a9c0aa212ad2d8cfc3be492cb768e7be66e801000000000000000000e47b35c93528a98e5ccc07f7a64120f10fe44a7d2add76f851f2ef1ff86fb35588aa6a6ad43a0217e74aa794").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000002ae44f541085b616ee2b6b66143d45b8d9d005a13ee58601000000000000000000eb7efe30fbcae6ef197af5303e922d5f13af046afe6722a44a407de33cfb05ecd1aa6a6ad43a0217cc1c1fc5").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00220ddf782b16cfb698ec47c721caa0e043c6e3045bd7d3f010000000000000000008ebe86fc87779b0ab7b1eeda4f938fa6bff75fdf3f03326d4c3f0f212db1a5df24ac6a6ad43a021787917f4b").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000003a8e0ffb97a26cb108666a56d11cfa7e8083858aefd35c00000000000000000000f741327a673e2680ea856c80fe7c45f495f35c0809c79095d2aa49bdac42d8a91eae6a6ad43a0217ee19f61c").expect("Bytes32 from UTXO should be valid"),
hex::decode("0420a12a06c61bdd24754ca5788b5b98127fa4cad6bfc6b4943000000000000000000000c0bc9db8ba6c3cd5e4852713723ab9462ed8cdff9a8e7a59f106a7d1e5d9596223af6a6ad43a021752931fe7").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a0cd2bcda5fed994deb88252ba588292824dafbfed2be7bb8300000000000000000000b021ceecadb5f6f0fcdec2d4dc38cc9021bec331a411769cdbfa1f0d731756c55fb16a6ad43a02174c791b12").expect("Bytes32 from UTXO should be valid"),
hex::decode("04e05c24b1a2e59ea42a7424eea8fdb9b95d65865090c6745fec01000000000000000000d49392556462b7cc6a324f3297b95655e8558a842829fa4dbe42a8e8740029149ab16a6ad43a021794875146").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a037310cb4c38e4d2d46702721cf104e9adf7a2120c0ddf85e01000000000000000000309c7334a84c50b5274a7efcc0ee46380415322cb2215a0220d84b7db6f96e6ac3b16a6ad43a0217d06362de").expect("Bytes32 from UTXO should be valid"),
hex::decode("00001c2a5253d07fb8f9c845066cd8d88ae9cbe590f2239d323a010000000000000000002430bbca343667d2cee8a3d7a86901914c852f38a92dcc8142f694235c3d8bf334b26a6ad43a0217dd6db83c").expect("Bytes32 from UTXO should be valid"),
hex::decode("00805c22ab4c07fb2ce6a683075bde23e7d94f50b588e8f9aa9c00000000000000000000ae3e39b85b23c403d31143839b34cc074e7eef0ecb1bf27c54e324a5be96676d92b26a6ad43a02177008583b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c004200a2cd7ef7703ae1fb2093c550eb744c3ea18108ae7a800000000000000000000d0bada625a70a2fd6cfaa2aede6d72bf4bdd10b64a52289820832323519d62ef43b56a6ad43a021767cab9b1").expect("Bytes32 from UTXO should be valid"),
hex::decode("008000206d1cce7f0978d68ffdf92d43c7027bdb81b612641586010000000000000000008d818799a9cada0f4f9243f2cad85b8940125850a9ba37f7d1e6fd282c8c62e145b76a6ad43a02179e855276").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060af24e8f12bb06b4a71cf56a91e73a3966e14c17208a54d6501000000000000000000fbc1e7250797d3e71b49e1abaef047d8cf7e16f1c0ff9de688182d503d0cae67d6b86a6ad43a02171ebed5cc").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00220511c75e44d1d627b986749aead0f55ab37f04df146ad0100000000000000000037e94c77e2c639bbec32dc4dd570b31516ea25fd1497156602b5e149f8d391d682c06a6ad43a02176534c3d3").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f78fb96b3c3c7b29aa1915342bddc921bffd01bfbb63d010000000000000000007a5c1741944ca4332ef03742b971469c0c966655b31d10609a8ffbea38a94cfa2dc56a6ad43a0217a35c947e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e004204870e85ab18fcb38d67c35979efc5df4105490b6713f00000000000000000000c7714efab1a223e7fa21c6f87db62b32cdcd048d5b70e59def0d434de384b3e871c66a6ad43a02178f3d7140").expect("Bytes32 from UTXO should be valid"),
hex::decode("004005209f1f0b92d362f5d4f3b1cceab1a7b6e0d2e55e2c38e8010000000000000000000f4e65ca15db0700809fa074c96785754236d3429e2fcf909a0a0cd7e59a31e6c0ce6a6ad43a02172c31d37e").expect("Bytes32 from UTXO should be valid"),
hex::decode("0080e029852c36bc969233723d0d0c7b44c3820b1233edd53c0001000000000000000000b068c891e2d2e65e1d48a74cb19d5e2aba449403d0cc021cf49cec0175226499d5ce6a6ad43a02171413e6c3").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e00020947175283c53840a5fd95ff5fb52a69cbf049640600e00000000000000000000d4ffb8d309f3aaf7023d9e3df8587e63b672b2180b85c0d307cfbf3e334ddb1a5fd76a6ad43a0217d543d85a").expect("Bytes32 from UTXO should be valid"),
hex::decode("00801d21203bd017379dede3b30858ec121ad3afebe66093deaa00000000000000000000b15433a1853ef7eab266109f32e22af002690eea752fa0afcfd517c8c51957ed5ad76a6ad43a0217e750210f").expect("Bytes32 from UTXO should be valid"),
hex::decode("0040032083cc6f37b94764a79231d6aff125a14f964aa83aef2300000000000000000000605c53cb797ad5e44717e9345170a30375813712b4374440b7b2db0c916fcce34ddd6a6ad43a0217ac7dca95").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e00020d8f1948230933cf727b9d64f1e5786939d595727ca0c0000000000000000000064559da1901f51ddb2307790cd717cdb08421a0d596a119ea26c795695e91fb60ade6a6ad43a0217252accd0").expect("Bytes32 from UTXO should be valid"),
hex::decode("0060e524ba12f94ea5504e31ef86e8cfaacd1dfde5f2981a0a1202000000000000000000b7768b6df326e64a6091b06c253adf3ad85d58b6900c9f0262ceeff036c65ae969df6a6ad43a02177e5d71b9").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200a2052a2caca7cbb37e81cafc0d37c29bb530ac9bbc42cc701000000000000000000d2b7cf8533ff1f8f67aa7a9278cea1885a1404465b8d42beee3c22572887406e7be36a6ad43a021723dfac06").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000220550058d8ed56d8640ee35b6684020f73610626342c900000000000000000000adfcd1ef1d32d7394be8a552ced86e00d4a1fecd68c78e047ea79bf6fc002b7a91e46a6ad43a0217ca6118f3").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0c02658c8f4dfd9d02cccdc514498243a7fefb91f9c49069400000000000000000000a48bf36c7ff5543f078df43076242f3992e00a7cf842e80af8f3e1699acb242db3e76a6ad43a0217637c9ff1").expect("Bytes32 from UTXO should be valid"),
hex::decode("002047242bfc14c46c37991c2cef140720b1b3081ef7d87db8d3010000000000000000007f4d937fe1cfa4629e958b43d638b2079ea77e57c9cef7606f07e2fe5e888b18c4e76a6ad43a02178d9c644f").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a091278a26924cfba43b61448a7a64c5b1fee904fb8e811cd70000000000000000000008abe2adedf7edfe2fab80f34a7a930b1267f123679414348649a39ff53230808def6a6ad43a021753c783de").expect("Bytes32 from UTXO should be valid"),
hex::decode("00004830337426f9ece788d4c8241e02589ffea33f898cbe09f501000000000000000000e2e8f5511c6553157451a89067fdcc790097d030bb4bc0690bc17014eef5d2c990f16a6ad43a0217a872716e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e02920546922cd52e7f92111d725d812c1532308eb59fa22ee00000000000000000000fe634310b53673fc6c018af12c64c19060157b1fc3b73d5a5c9caa03cf3565f2baf56a6ad43a0217c76fd370").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0c121fa38469efe9223b571f74e760c96df203d80b08f3b5600000000000000000000f33c1eea09c6d87bbc4d1d2321270c21454495f21ff525534f4e20c85138a592c1f56a6ad43a021792df7b16").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0a126df55ad5154bd8f45fbe0cdb9fc9722783ce4b7a535ac01000000000000000000c533cefab59d506f73176e595df8cea46363e9b5567dff08a163a3c465dc98d14ffc6a6ad43a0217c26d2516").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a09d2b81fd6f7a8e612d81d80d5b5d64859c1b2b2b101bd1fb00000000000000000000800989d2c31d1dc5a3308452b91b1ed40206a030839737953c9d21d6923786451efd6a6ad43a021749e04799").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0d729b34736f399b13a8a2fb7479954d43c2df771c757e23901000000000000000000f7c933bad214186ec2e49c9d1b1585937280868818f320803cf6436e09a8626973016b6ad43a02171b81e870").expect("Bytes32 from UTXO should be valid"),
hex::decode("00601521556ce1a2354410a18c80b0a67be6dc16257be28890ec010000000000000000003059a134b7eca83de9aca917fabb76ee41d97032583222d6840ef22da16b5b92dd016b6ad43a021725071a5b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00602e2064168b2c362c354444ea0828f36d7cdb3572169b615601000000000000000000a4aeaacb4c25d3a83b2f8ea594325d756ec78f290a73c4953f3cbfaff10e3a3792026b6ad43a02170bb4640f").expect("Bytes32 from UTXO should be valid"),
hex::decode("0040c82357a6c79e2fb6f4d4bf95724a4bcc29bde7b449debdec01000000000000000000fa99bac89c24d15717ad877fecfbf734eb0bc75f8fb578f9470a5db668dbb8fbc0046b6ad43a02174b869a7d").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000034395bcc21a6a2c2d3ccbc2773194d11a7ddfebf0e0919000000000000000000006f505e60f36ce9f73494bfbf0c0f058fee1e2e4822c1b0fa766fb9e3251fd9b38e056b6ad43a02172c4c0184").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800d20354b5388fb81effe12c3291a4cb50cc2adc5b98d079b00000000000000000000103e5e5b3d6d17e134cc0c76af0e91fe08d72591bf4c3ad7b6aa869d5d4cb02ba7066b6ad43a02172202f70c").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200e20b3001fb8573b91195cb7b9c1de390d9991f3c07978d3010000000000000000003e6addca9c34eee9459e631d9d08e77c2de70703f102ce7903838cc77208f595c7066b6ad43a02173fa4ae35").expect("Bytes32 from UTXO should be valid"),
hex::decode("006004209e4646297e4d4fd4f60548b0616a359650c35f1de7f30000000000000000000072aff40819e1e686905c68af2e73b9b951be3736437b416986cf18fd71fb8bd95a0b6b6ad43a021729d33887").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000022ee651093128e4598ff28ca297f351401d19696638b380000000000000000000038d529507d803dcf8080875cf2258aa8a551511c24f8b8ae3fa88423b0602748920b6b6ad43a02170846a89b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00608320be57374d6179c78ada919fffb2d9f908f5e18a74ff0501000000000000000000fa2f2dfb7b4d5235da7f1029804e23edbb7d3323af88199fc0ef1b79a1753459120c6b6ad43a02179a132a56").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a0d227a580e546e615e1c532f47d89de7368c30df20e2e781b01000000000000000000e12705f05a4bbf09b87493335471db4f833e12d99fd36d76c5b3279082dd096e580c6b6ad43a02177e704ef5").expect("Bytes32 from UTXO should be valid"),
hex::decode("00600f3912f664c2673dde9ab6886a85a2c9fc4efc177a0cbf4c01000000000000000000f1a81ddd80ef01b4a480de488f15402069ae8683ecc46770878b54fb7991c1a57d0d6b6ad43a0217bb384b12").expect("Bytes32 from UTXO should be valid"),
hex::decode("00803427b9cddcc2df57f4563ae0131adb3dd35bb9917139b95400000000000000000000c0b2ec9353f60fbdf5cf7da0ab0c17a78003bce2052a412c27d12665f76cb555fa136b6ad43a0217066d21e6").expect("Bytes32 from UTXO should be valid"),
hex::decode("0040ec33bb8f6fa5e2f2ed3cf60cf91d6e79fcf7cde05b11087e01000000000000000000e6075b19a084d7c5aaa8484aeff15d8b5db4db88ad69d5ee647a3d9f778fedda61146b6ad43a0217a27b3033").expect("Bytes32 from UTXO should be valid"),
hex::decode("10a0c2227eb8240f150309fcaad8a2be205ddcbf06429a508662010000000000000000007e17cf9282b77723437c083af1aa83482a73fee35c73f110303d402d88fa8bed4c156b6ad43a02174b470b31").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e00320cb4dec5b41a12bc19c29a6d424197f86c3b2ba025e25010000000000000000009d1a60c3889690294fc993f397a4dd1df48b3f9c4bdcb41306c3dedf033e4ee8461b6b6ad43a021763b89d28").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000022052e6e25c9112220845c4c3e7fd939340336d3d33cdb600000000000000000000bfc9920255dcbba49376571e9ce3bcafc87bd36045903ecf4076480d96614b7b051d6b6ad43a02172e1a9b25").expect("Bytes32 from UTXO should be valid"),
hex::decode("00209b22982e9a7ed287539bce7c3e603687aa2d3125079fb86a010000000000000000004102e56d0ce9029acb48c28745a9dce1783074391f3e70c695afdd392f6ad6d0ef1d6b6ad43a021722025f6d").expect("Bytes32 from UTXO should be valid"),
hex::decode("10e0ff3f1bb91d2d09c8f74d7245ec18f7e5b6810a7f461dcdc900000000000000000000ac2b5e4ba6695790ec04953ef4774ece540667da058dc6c0888363c4fe922e0dc81f6b6ad43a021760ea40d6").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0f731f4aa3d9f670eaece00ac84c4c19cc4e2a26ef07851220200000000000000000060ee14b2e84e0f736907009618bc2d8296194d66c7ca0a027c702569990b49090d206b6ad43a0217eeb19de9").expect("Bytes32 from UTXO should be valid"),
hex::decode("0020f92325a882bfdca063304e330248bdc067d51df8e92bcaf800000000000000000000c753e6732da8e5c98b3376480be610cbdf3cb16d836b59ab6362d2d228efedea29206b6ad43a0217c924f2a1").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a0a220f0dc827b72a458a9ce7550312c0a8750d4f068713efa01000000000000000000cc94b5a5e75437a7c856b29b12da804ddb02fe1353bb210da2606d8180ec6fb631206b6ad43a02174e9d590a").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000082063447f3bc8b428d461b82a070be3db9410ab1fc40f24000000000000000000008dc755c30eaa2c22cc7a4a5792e3656f4bf698d38c41ebc4c85165fb8c9c6ded79206b6ad43a02173e731a1f").expect("Bytes32 from UTXO should be valid"),
hex::decode("10c05729b6ea9fbe42fb1d9405e47116cb0424329411d017e1aa0000000000000000000076a747223eaa6d45d3f84e2f6828cdc487c0dbdbad42b08a9b8fffc27665a960a7216b6ad43a02174394d82b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a08520af579ef409a189ab162c788896ad825b38faea3641c401000000000000000000dee9be72bd60eda2ab12e0217e2ca16a8bcb34c32f4972b273b77a17440d00e70a226b6ad43a0217116884ce").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a00620482fd173f0a825fc34f487502c1566555f2862f0a02801000000000000000000bb5482aae60bfd220388693225362b18f72e82f9b5ceb9c6d2f9a61f2c28094fe0296b6ad43a0217fb407034").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c00120e0e9282069496b464ef564a9ead03d37ce8e7a9f12c701000000000000000000975e9f48c1083438f32c873d67b2fddfc3c8e130ac9fbc1a53da01c01c3d46c8992a6b6ad43a0217ed908988").expect("Bytes32 from UTXO should be valid"),
hex::decode("00200723899fc0d3576718c15a6719c4bc71a91bd3ccc96192ec0000000000000000000004fdb6ab38260ca750671d7a6637ef75a651448c82cfc14554d57e2748be2be9722e6b6ad43a02178a807416").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3fbf073df0898e0324336409d64b6b11987fd4465bd82900000000000000000000f4e8fc5a02f4d8f4311eb5fbf73592c88906b0bce6a08b6e321e6c7b19509dfe8f326b6ad43a02175cba391b").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000b2080a47bfbe3066208d4fc39e065d584930a323adb645b0100000000000000000044ad1fa9768359f8528ddcbee3b5f1c773f184fabb6bf87d883e91b0f3f15b89d8316b6ad43a0217329de815").expect("Bytes32 from UTXO should be valid"),
hex::decode("006003204682f5d50b7c8bdea389f6c43515d3459584ab50c406010000000000000000003d441907ec00061b73368da7754ad305e6fd796cb4cf9d3410d5a65927d8e6ce74356b6ad43a02174b0fcdc3").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000d3255924665d3d5fe933b16e09b06dcdd3bf7cce977223690000000000000000000024f812c8d99a9596021d3934a646bd50db9ca98931f3228c236952ac222217d3fe356b6ad43a0217effcbbff").expect("Bytes32 from UTXO should be valid"),
hex::decode("0000ff3f11bce3edc9ad7d6858a81f240977adb5517ef078ac5600000000000000000000a11d0de0146f427f426965160dbb0db66cebb6eb805bb3af11ee21924f2bdd71383c6b6ad43a0217936d08ca").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e0002007bb096f631e7168dcda31d75201201e543037a0b43300000000000000000000a2a7803b593fbcd881866db771b59f2f98f5f69600460fb6ad553867a1e00a00323e6b6ad43a02170dbeda27").expect("Bytes32 from UTXO should be valid"),
hex::decode("000000205a18258ccf12385ebd72c8f4f0aa2f5b5c5ec841ce10000000000000000000004a994b5f6c109f3cf616de3c0641711d1d4b848c7a04fe6e243765f67ec9cac875406b6ad43a02170d80ed5a").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0722b62395602530b6d60060a8fce332cd1908f21b30b8be4010000000000000000009508e51190aa63ec2298af3cb644eeb1498c0d83d67680efe30d5fd1f6a95d6d7e426b6ad43a02179c08e6e0").expect("Bytes32 from UTXO should be valid"),
hex::decode("00a02320b4b25be6c2ba4576586b90f8c4c3732648680cc5c2d901000000000000000000e5865a3d45646d51b65855b4b9a972198fca36241574a652ecfbab67b3f6256f97456b6ad43a021715c30439").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000030ee8847f7a144b68c6e1e0bef2b4183db01bf825d6d05020000000000000000009798b0f81dc791ce7b17eec0d89ef9db7a2b541e9f582fb2387fd9b642418faa6e476b6ad43a0217a06ef431").expect("Bytes32 from UTXO should be valid"),
hex::decode("00804521440b70d25839dbc3dd0bccd37ef751d50e576188eaa500000000000000000000314ff0850863609b917541ec201a10cd9f47f69cd2d1bf267cdb19fe3e91238bcc486b6ad43a02175e15bd74").expect("Bytes32 from UTXO should be valid"),
hex::decode("000065337e07a76349f99f3eaedfbd7ec9b048ae462fc439cddf0100000000000000000000268bf66e3c00ffff66a507729af9df227492b86f436331ebad0241ad055fe97b516b6ad43a021729b64713").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000022b936d35a2f4a755778159e39d6d80b5946bbf15b7c0b01000000000000000000640504d1606de9fce2fd0be5304c553b7f7092bd5f18c291e3fb1c63a973194fc3566b6ad43a021725c6c2d8").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000020301ba83277f8012e1902f97eea3e53d0515ef73319f201000000000000000000f8a415b0a937ef5175c9715ac98e3373e373afad63cbc9c8541c51119d91115fca5b6b6ad43a02176c9b53e1").expect("Bytes32 from UTXO should be valid"),
hex::decode("00800420ec8823f23684b5a607fa9d6194dc174497f8501a194301000000000000000000af001c7d8797bdc2f8f45149d1f4cd394903e12d59c1f8afbcdbdce3b9925436665d6b6ad43a021776224a13").expect("Bytes32 from UTXO should be valid"),
hex::decode("00000020465a566082cb8faeeb44e097377a9174a11b65a051ff010000000000000000000b6ef86b33a25b37856c2e7c68543a5066dbe67c2a087c8f4199eb289357b17360616b6ad43a021776fc5e72").expect("Bytes32 from UTXO should be valid"),
hex::decode("10e0a02c5d89719ab4dce3ed69c543336776072cdcca1c26514301000000000000000000e860d743e10db71b2b7c5a1fadb2cea11ab7200ba04b4b776fd55d0939dc6cbc61616b6ad43a02171151725e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00606e31bb3cc5e304822bfdf4506cc3b2e0aeb98a7b21280a0f01000000000000000000c897183f710feca8271a8709df053983a6d4489610a73d85b9f0014f58dd770262636b6ad43a0217a723ee06").expect("Bytes32 from UTXO should be valid"),
hex::decode("00c0812002e5d76425f391738eac0c614d8afc795fde8c0dbf7d010000000000000000008c6bae74a46ad9f2905e5258d4adaf61af2bcf7c87e86a22f084f11710d58e2b36646b6ad43a021795ac6c1e").expect("Bytes32 from UTXO should be valid"),
hex::decode("00601820856aed25759848cd1ad02caec25afdc0cf17e9ffa0aa01000000000000000000c17d5c0a7bf4af165552c3e91b4d98f4d2afa2938e7b1bdf0912f1e850680a1c53656b6ad43a0217193b3d87").expect("Bytes32 from UTXO should be valid"),
hex::decode("00e02c3ade01a429e0f5c328824f4ee063b98f24ff3b0dc0db08000000000000000000009d0b402f41ab9c16e08f95de962044b206413f878608abca2015ee2074713078606d6b6ad43a0217c0650150").expect("Bytes32 from UTXO should be valid"),
hex::decode("00008f2604b952dcd44dfcb61080ad77c5b626efd760e5f8ac8401000000000000000000ee81697e6cf7f41db37b63a9680906d3023be7a905785ef1b5ebd03fd22dd8bb2d6f6b6ad43a0217287aa17f").expect("Bytes32 from UTXO should be valid"),
hex::decode("008017262c315a069a8896ec04d88ef423ff5cb3845320a6f123010000000000000000002d42d9519e62f5a48d4880b0ff0cd8021a38eadd469a2f7aabd0886061026a5026706b6ad43a02172ea14dd2").expect("Bytes32 from UTXO should be valid"),
]
);
let thread_proof = ThreadProof::UtxoThreadProof(utxo_thread_proof);
@ -375,40 +355,40 @@ mod benchmarks {
let proof = vec![
H256::from_slice(
&hex::decode("6dfb19f049f557abff273ce9efb9195924d41e5699b1b7755be2c515b25ef7b6")
.expect("Proof should be valid"),
.expect("Proof should be valid"),
),
H256::from_slice(
&hex::decode("9e0f9c5b8ffa146b74bb614482c0bc65a1ef961a8fa9a3a031a36c97f8c70733")
.expect("Proof should be valid"),
.expect("Proof should be valid"),
),
H256::from_slice(
&hex::decode("890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d")
.expect("Proof should be valid"),
.expect("Proof should be valid"),
),
H256::from_slice(
&hex::decode("3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd8")
.expect("Proof should be valid"),
.expect("Proof should be valid"),
),
H256::from_slice(
&hex::decode("ecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da")
.expect("Proof should be valid"),
.expect("Proof should be valid"),
),
H256::from_slice(
&hex::decode("defff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da5")
.expect("Proof should be valid"),
.expect("Proof should be valid"),
),
H256::from_slice(
&hex::decode("617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d7")
.expect("Proof should be valid"),
.expect("Proof should be valid"),
),
H256::from_slice(
&hex::decode("292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead")
.expect("Proof should be valid"),
.expect("Proof should be valid"),
),
];
let slots = vec![H256::from_slice(
&hex::decode("2e474dabf492786b3505d7b7cf0bf07c9dbce92c91982fa7344c77e24fd4310d")
.expect("Slot should be valid hex"),
.expect("Slot should be valid hex"),
)];
let payload = ThreadPayload::new(1, transfer_amount, receiver_account);

View File

@ -306,9 +306,7 @@ pub mod pallet {
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight((
T::WeightInfo::extend_warp(
Authorities::<T>::decode_len().unwrap_or(1) as u32,
),
T::WeightInfo::extend_warp(),
DispatchClass::Normal,
Pays::No,
))]
@ -361,9 +359,7 @@ pub mod pallet {
#[pallet::call_index(1)]
#[pallet::weight((
T::WeightInfo::weave_weft(
Authorities::<T>::decode_len().unwrap_or(1) as u32,
),
T::WeightInfo::weave_weft(),
DispatchClass::Normal,
Pays::No,
))]
@ -419,9 +415,7 @@ pub mod pallet {
#[pallet::call_index(2)]
#[pallet::weight((
match &thread_proof {
ThreadProof::UtxoThreadProof(thread) => T::WeightInfo::pull_utxo_thread(
thread.ancestry_headers_len(),
),
ThreadProof::UtxoThreadProof(_) => T::WeightInfo::pull_utxo_thread(),
ThreadProof::EvmThreadProof(_) => T::WeightInfo::pull_evm_thread(),
},
DispatchClass::Normal,

View File

@ -21,16 +21,11 @@ use crate::{ExternalBlockNumber, ThreadId, WeavingSession};
const EVM_MERKLE_DEPTH: u32 = 8;
const EVM_VALUES_DEPTH: u32 = 8;
const UTXO_MAX_HISTORY_DEPTH_VALUE: u32 = 144;
const UTXO_MAX_PROOF_BYTES: u32 = 1024;
const UTXO_MAX_HEADER_BYTES: u32 = 80;
const UTXO_MAX_HISTORY_DEPTH: u32 = 144;
const UTXO_MAX_TX_BYTES: u32 = ghost_helpers::utxo::MAX_TX_LEN as u32;
#[cfg(not(feature = "runtime-benchmarks"))]
const UTXO_MAX_HISTORY_DEPTH: u32 = UTXO_MAX_HISTORY_DEPTH_VALUE;
#[cfg(feature = "runtime-benchmarks")]
pub const UTXO_MAX_HISTORY_DEPTH: u32 = UTXO_MAX_HISTORY_DEPTH_VALUE;
pub enum WeavingOk<NetworkId> {
Block(ExternalBlockNumber, NetworkId),
Hash(ExternalBlockNumber, H256, WeavingSession, NetworkId),
@ -479,9 +474,6 @@ impl<Balance> UtxoThreadProof<Balance>
where
Balance: Copy + Clone + Eq + PartialEq + UniqueSaturatedInto<u128>,
{
pub fn ancestry_headers_len(&self) -> u32 {
self.ancestry_headers.len() as u32
}
pub fn amount(&self) -> Balance {
self.expected_amount
}
@ -495,7 +487,9 @@ where
pub fn verify_proof(&self, root_hash: H256, gatekeeper_ref: &[u8]) -> Option<AccountId32> {
use ghost_helpers::utxo::{Header, Transaction};
if self.gettxproof_bytes.len() < 85 { return None; }
if self.gettxproof_bytes.len() < 85 {
return None;
}
let header_bytes = &self.gettxproof_bytes[..80];
let is_chain_valid = verify_hash_ancestry::<UtxoSha2Hasher, _>(
@ -503,8 +497,9 @@ where
self.ancestry_headers.iter(),
root_hash,
);
if !is_chain_valid { return None; }
if !is_chain_valid {
return None;
}
let transaction =
Transaction::<UtxoSha2Hasher>::try_from(self.getrawtransaction_bytes.as_ref()).ok()?;

View File

@ -1,152 +1,23 @@
// This file is part of Ghost Network.
// Ghost Network is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Ghost Network is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Ghost Network. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `ghost_weaver`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0
//! DATE: 2026-09-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ghostown`, CPU: `Intel(R) Core(TM) i3-2310M CPU @ 2.10GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("casper-dev")`, DB CACHE: 1024
// Executed Command:
// ./target/release/ghost
// benchmark
// pallet
// --chain=casper-dev
// --steps=50
// --repeat=20
// --pallet=ghost_weaver
// --extrinsic=*
// --wasm-execution=compiled
// --heap-pages=4096
// --header=./file_header.txt
// --output=./runtime/casper/src/weights/ghost_weaver.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{
traits::Get,
weights::{Weight, constants::RocksDbWeight},
};
use core::marker::PhantomData;
use frame_support::weights::Weight;
pub trait WeightInfo {
fn extend_warp(a: u32,) -> Weight;
fn weave_weft(a: u32,) -> Weight;
fn extend_warp() -> Weight;
fn weave_weft() -> Weight;
fn pull_evm_thread() -> Weight;
fn pull_utxo_thread(a: u32) -> Weight;
fn pull_utxo_thread() -> Weight;
}
impl WeightInfo for () {
/// Storage: `GhostWeaver::DisabledAuthorities` (r:1 w:0)
/// Proof: `GhostWeaver::DisabledAuthorities` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::Authorities` (r:1 w:0)
/// Proof: `GhostWeaver::Authorities` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::TapestryDrafts` (r:1 w:0)
/// Proof: `GhostWeaver::TapestryDrafts` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::NetworkAttestations` (r:1 w:1)
/// Proof: `GhostWeaver::NetworkAttestations` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// The range of component `a` is `[1, 300]`.
fn extend_warp(a: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `223 + a * (32 ±0)`
// Estimated: `3687 + a * (32 ±0)`
// Minimum execution time: 215_336_000 picoseconds.
Weight::from_parts(218_119_120, 0)
.saturating_add(Weight::from_parts(0, 3687))
// Standard Error: 1_412
.saturating_add(Weight::from_parts(47_848, 0).saturating_mul(a.into()))
.saturating_add(RocksDbWeight::get().reads(5))
.saturating_add(RocksDbWeight::get().writes(1))
.saturating_add(Weight::from_parts(0, 32).saturating_mul(a.into()))
}
/// Storage: `GhostWeaver::DisabledAuthorities` (r:1 w:0)
/// Proof: `GhostWeaver::DisabledAuthorities` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::Authorities` (r:1 w:0)
/// Proof: `GhostWeaver::Authorities` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::TapestryDrafts` (r:1 w:0)
/// Proof: `GhostWeaver::TapestryDrafts` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::TapestryStrands` (r:1 w:1)
/// Proof: `GhostWeaver::TapestryStrands` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::WeavingStates` (r:1 w:1)
/// Proof: `GhostWeaver::WeavingStates` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// The range of component `a` is `[1, 300]`.
fn weave_weft(a: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `518 + a * (32 ±0)`
// Estimated: `3982 + a * (32 ±0)`
// Minimum execution time: 244_811_000 picoseconds.
Weight::from_parts(250_046_200, 0)
.saturating_add(Weight::from_parts(0, 3982))
// Standard Error: 1_958
.saturating_add(Weight::from_parts(26_347, 0).saturating_mul(a.into()))
.saturating_add(RocksDbWeight::get().reads(6))
.saturating_add(RocksDbWeight::get().writes(2))
.saturating_add(Weight::from_parts(0, 32).saturating_mul(a.into()))
}
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::LoomStates` (r:1 w:0)
/// Proof: `GhostWeaver::LoomStates` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::PulledThreads` (r:1 w:1)
/// Proof: `GhostWeaver::PulledThreads` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::GatekeeperAmounts` (r:1 w:1)
/// Proof: `GhostNetworks::GatekeeperAmounts` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkImbalance` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkImbalance` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `System::Account` (r:1 w:0)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
/// The range of component `a` is `[1, 300]`.
fn pull_utxo_thread(_a: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `358`
// Estimated: `3823`
// Minimum execution time: 650_006_000 picoseconds.
Weight::from_parts(663_001_690, 0)
.saturating_add(Weight::from_parts(0, 3823))
.saturating_add(RocksDbWeight::get().reads(6))
.saturating_add(RocksDbWeight::get().writes(3))
}
/// Storage: `GhostNetworks::Networks` (r:1 w:0)
/// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::LoomStates` (r:1 w:0)
/// Proof: `GhostWeaver::LoomStates` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostWeaver::PulledThreads` (r:1 w:1)
/// Proof: `GhostWeaver::PulledThreads` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::GatekeeperAmounts` (r:1 w:1)
/// Proof: `GhostNetworks::GatekeeperAmounts` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `GhostNetworks::NetworkImbalance` (r:1 w:1)
/// Proof: `GhostNetworks::NetworkImbalance` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `System::Account` (r:1 w:0)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn pull_evm_thread() -> Weight {
// Proof Size summary in bytes:
// Measured: `358`
// Estimated: `3823`
// Minimum execution time: 138_199_000 picoseconds.
Weight::from_parts(162_645_000, 0)
.saturating_add(Weight::from_parts(0, 3823))
.saturating_add(RocksDbWeight::get().reads(6))
.saturating_add(RocksDbWeight::get().writes(3))
}
fn extend_warp() -> Weight {
Default::default()
}
fn weave_weft() -> Weight {
Default::default()
}
fn pull_evm_thread() -> Weight {
Default::default()
}
fn pull_utxo_thread() -> Weight {
Default::default()
}
}

View File

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

View File

@ -1,6 +1,6 @@
[package]
name = "casper-runtime-constants"
version = "0.4.4"
version = "0.4.3"
authors.workspace = true
edition.workspace = true
homepage.workspace = true

View File

@ -37,19 +37,19 @@ use sp_core::parameter_types;
use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight};
parameter_types! {
// Time to execute an empty block.
// Calculated by multiplying the *Average* with `1.0` and adding `0`.
//
// Stats nanoseconds:
// Min, Max: 1_042_579, 1_101_962
// Average: 1_054_295
// Median: 1_051_534
// Std-Dev: 9476.68
//
// Percentiles nanoseconds:
// 99th: 1_091_162
// 95th: 1_069_117
// 75th: 1_057_964
/// Time to execute an empty block.
/// Calculated by multiplying the *Average* with `1.0` and adding `0`.
///
/// Stats nanoseconds:
/// Min, Max: 1_042_579, 1_101_962
/// Average: 1_054_295
/// Median: 1_051_534
/// Std-Dev: 9476.68
///
/// Percentiles nanoseconds:
/// 99th: 1_091_162
/// 95th: 1_069_117
/// 75th: 1_057_964
pub const BlockExecutionWeight: Weight =
Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(1_054_295), 0);
}

View File

@ -37,19 +37,19 @@ use sp_core::parameter_types;
use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight};
parameter_types! {
// Time to execute a NO-OP extrinsic, for example `System::remark`.
// Calculated by multiplying the *Average* with `1.0` and adding `0`.
//
// Stats nanoseconds:
// Min, Max: 378_590, 384_849
// Average: 380_658
// Median: 380_461
// Std-Dev: 1202.24
//
// Percentiles nanoseconds:
// 99th: 383_191
// 95th: 382_552
// 75th: 381_384
/// Time to execute a NO-OP extrinsic, for example `System::remark`.
/// Calculated by multiplying the *Average* with `1.0` and adding `0`.
///
/// Stats nanoseconds:
/// Min, Max: 378_590, 384_849
/// Average: 380_658
/// Median: 380_461
/// Std-Dev: 1202.24
///
/// Percentiles nanoseconds:
/// 99th: 383_191
/// 95th: 382_552
/// 75th: 381_384
pub const ExtrinsicBaseWeight: Weight =
Weight::from_parts(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(380_658), 0);
}

View File

@ -45,34 +45,34 @@ pub mod constants {
/// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights
/// are available for brave runtime engineers who may want to try this out as default.
pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight {
// Time to read one storage item.
// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`.
//
// Stats nanoseconds:
// Min, Max: 3_485, 2_000_385
// Average: 26_775
// Median: 4_870
// Std-Dev: 205784.16
//
// Percentiles nanoseconds:
// 99th: 2_000_385
// 95th: 6_002
// 75th: 5_246
/// Time to read one storage item.
/// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`.
///
/// Stats nanoseconds:
/// Min, Max: 3_485, 2_000_385
/// Average: 26_775
/// Median: 4_870
/// Std-Dev: 205784.16
///
/// Percentiles nanoseconds:
/// 99th: 2_000_385
/// 95th: 6_002
/// 75th: 5_246
read: 29_453 * constants::WEIGHT_REF_TIME_PER_NANOS,
// Time to write one storage item.
// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`.
//
// Stats nanoseconds:
// Min, Max: 16_322, 25_965_124
// Average: 308_302
// Median: 29_481
// Std-Dev: 2674917.65
//
// Percentiles nanoseconds:
// 99th: 25_965_124
// 95th: 42_210
// 75th: 33_525
/// Time to write one storage item.
/// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`.
///
/// Stats nanoseconds:
/// Min, Max: 16_322, 25_965_124
/// Average: 308_302
/// Median: 29_481
/// Std-Dev: 2674917.65
///
/// Percentiles nanoseconds:
/// 99th: 25_965_124
/// 95th: 42_210
/// 75th: 33_525
write: 339_133 * constants::WEIGHT_REF_TIME_PER_NANOS,
};
}

View File

@ -44,34 +44,34 @@ pub mod constants {
/// By default, Substrate uses `RocksDB`, so this will be the weight used throughout
/// the runtime.
pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight {
// Time to read one storage item.
// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`.
//
// Stats nanoseconds:
// Min, Max: 6_726, 2_902_682
// Average: 41_735
// Median: 10_059
// Std-Dev: 298297.77
//
// Percentiles nanoseconds:
// 99th: 2_902_682
// 95th: 14_199
// 75th: 11_422
/// Time to read one storage item.
/// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`.
///
/// Stats nanoseconds:
/// Min, Max: 6_726, 2_902_682
/// Average: 41_735
/// Median: 10_059
/// Std-Dev: 298297.77
///
/// Percentiles nanoseconds:
/// 99th: 2_902_682
/// 95th: 14_199
/// 75th: 11_422
read: 45_909 * constants::WEIGHT_REF_TIME_PER_NANOS,
// Time to write one storage item.
// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`.
//
// Stats nanoseconds:
// Min, Max: 31_214, 45_912_915
// Average: 545_878
// Median: 51_543
// Std-Dev: 4729852.98
//
// Percentiles nanoseconds:
// 99th: 45_912_915
// 95th: 68_658
// 75th: 58_683
/// Time to write one storage item.
/// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`.
///
/// Stats nanoseconds:
/// Min, Max: 31_214, 45_912_915
/// Average: 545_878
/// Median: 51_543
/// Std-Dev: 4729852.98
///
/// Percentiles nanoseconds:
/// 99th: 45_912_915
/// 95th: 68_658
/// 75th: 58_683
write: 600_466 * constants::WEIGHT_REF_TIME_PER_NANOS,
};
}

View File

@ -131,7 +131,7 @@ impl<T: frame_system::Config> ghost_weaver::WeightInfo for WeightInfo<T> {
/// Proof: `GhostNetworks::NetworkImbalance` (`max_values`: Some(1), `max_size`: None, mode: `Measured`)
/// Storage: `System::Account` (r:1 w:0)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn pull_evm_thread(_a: u32) -> Weight {
fn pull_evm_thread() -> Weight {
// Proof Size summary in bytes:
// Measured: `358`
// Estimated: `3823`

View File

@ -67,7 +67,7 @@ impl<T: frame_system::Config> pallet_babe::WeightInfo for WeightInfo<T> {
.saturating_add(T::DbWeight::get().writes((6_u64).saturating_mul(max_nominators_per_validator.into())))
.saturating_add(Weight::from_parts(0, 3774).saturating_mul(max_nominators_per_validator.into()));
// The range of component `x` is `[0, 1]`.
/// The range of component `x` is `[0, 1]`.
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`