fix: remove staking-score from relay chain, fix CI quick-checks

- Remove pezpallet_staking_score from relay chain runtime (noter model
  lives on People Chain only)
- Update welati mock to current staking-score Config trait
- Fix staking-score feature propagation (zepter: std, runtime-benchmarks)
- Format vendor subxt example files (rustfmt)
- Regenerate umbrella crate
- Update CRITICAL_STATE.md with noter delegation status
This commit is contained in:
2026-02-16 19:50:13 +03:00
parent 643c482611
commit 6bbbd683ab
26 changed files with 664 additions and 742 deletions
+12 -1
View File
@@ -1,6 +1,6 @@
# PEZKUWI MAİNNET KRİTİK DURUM # PEZKUWI MAİNNET KRİTİK DURUM
**Son Guncelleme:** 2026-02-15 UTC **Son Guncelleme:** 2026-02-16 UTC
**Bu dosyayi her oturum basinda OKU!** **Bu dosyayi her oturum basinda OKU!**
--- ---
@@ -149,11 +149,22 @@ Note: Mnemonic stored locally, NOT in repo. Check /home/mamostehp/res/
- [x] Zagros gereksiz validator servisleri temizlendi (~68GB kazanildi) - [x] Zagros gereksiz validator servisleri temizlendi (~68GB kazanildi)
- [x] Zagros collator'lara --rpc-cors all eklendi - [x] Zagros collator'lara --rpc-cors all eklendi
- [x] Zagros nginx Host header duzeltildi - [x] Zagros nginx Host header duzeltildi
- [x] Noter delegasyonu ile staking score sistemi (People Chain spec 1_020_007)
### Bekleyen Isler ### Bekleyen Isler
1. [ ] Nova Wallet uyumluluk testi (NominationPoolsApi eklenince) 1. [ ] Nova Wallet uyumluluk testi (NominationPoolsApi eklenince)
2. [ ] Zagros teyrchain'leri 1_020_004'e upgrade et (relay zaten 1_020_004) 2. [ ] Zagros teyrchain'leri 1_020_004'e upgrade et (relay zaten 1_020_004)
3. [ ] Public RPC endpointlerini test et ve dokumanla 3. [ ] Public RPC endpointlerini test et ve dokumanla
4. [ ] People Chain runtime upgrade 1_020_006 → 1_020_007 (noter delegasyonu deploy)
5. [ ] Relay Chain: pezpallet_staking_score'u runtime'dan cikar (sonraki relay upgrade'de)
### Onemli Not: Relay Chain pezpallet_staking_score Uyumsuzlugu
Relay Chain runtime'inda (`pezkuwi/runtime/pezkuwichain/src/lib.rs:596`) eski bir
`pezpallet_staking_score::Config` implementasyonu var (`type StakingInfo`). Bu trait
palet kaynaginda artik mevcut degil — noter delegasyonu modeline gecildi.
**Mainnet:** Halihazirda calisan runtime (spec 1_020_004) eski binary ile derlendi,
sorun yok. Bir sonraki Relay Chain runtime upgrade'inde bu palet cikarilir.
Ayrica `welati/src/mock.rs` da ayni sekilde guncellenmeli.
--- ---
Generated
-1
View File
@@ -14932,7 +14932,6 @@ dependencies = [
"pezpallet-session-benchmarking", "pezpallet-session-benchmarking",
"pezpallet-staking", "pezpallet-staking",
"pezpallet-staking-runtime-api", "pezpallet-staking-runtime-api",
"pezpallet-staking-score",
"pezpallet-state-trie-migration", "pezpallet-state-trie-migration",
"pezpallet-sudo", "pezpallet-sudo",
"pezpallet-timestamp", "pezpallet-timestamp",
@@ -27,12 +27,13 @@ serde = { version = "1.0.197", default-features = false, features = [
# PezkuwiChain primitives # PezkuwiChain primitives
pezkuwi-primitives = { workspace = true, default-features = false } pezkuwi-primitives = { workspace = true, default-features = false }
# dev / test dependencies (also used as optional for feature propagation)
pezpallet-balances = { workspace = true, default-features = false, optional = true }
pezsp-io = { workspace = true, default-features = false, optional = true }
[dev-dependencies] [dev-dependencies]
pezframe-support = { workspace = true, features = ["std"] }
pezframe-system = { workspace = true, features = ["std"] }
pezpallet-balances = { workspace = true, features = ["std"] } pezpallet-balances = { workspace = true, features = ["std"] }
pezsp-io = { workspace = true, features = ["std"] } pezsp-io = { workspace = true, features = ["std"] }
pezsp-runtime = { workspace = true, features = ["std"] }
[features] [features]
default = ["std"] default = ["std"]
@@ -41,7 +42,9 @@ std = [
"pezframe-benchmarking?/std", "pezframe-benchmarking?/std",
"pezframe-support/std", "pezframe-support/std",
"pezframe-system/std", "pezframe-system/std",
"pezpallet-balances?/std",
"pezkuwi-primitives/std", "pezkuwi-primitives/std",
"pezsp-io?/std",
"pezsp-runtime/std", "pezsp-runtime/std",
"pezsp-std/std", "pezsp-std/std",
"scale-info/std", "scale-info/std",
@@ -53,6 +56,8 @@ runtime-benchmarks = [
"pezframe-system/runtime-benchmarks", "pezframe-system/runtime-benchmarks",
"pezkuwi-primitives/runtime-benchmarks", "pezkuwi-primitives/runtime-benchmarks",
"pezsp-runtime/runtime-benchmarks", "pezsp-runtime/runtime-benchmarks",
"pezpallet-balances/runtime-benchmarks",
"pezsp-io/runtime-benchmarks",
] ]
try-runtime = [ try-runtime = [
"pezframe-benchmarking?/try-runtime", "pezframe-benchmarking?/try-runtime",
@@ -60,6 +65,7 @@ try-runtime = [
"pezframe-system/try-runtime", "pezframe-system/try-runtime",
"pezkuwi-primitives/try-runtime", "pezkuwi-primitives/try-runtime",
"pezsp-runtime/try-runtime", "pezsp-runtime/try-runtime",
"pezpallet-balances?/try-runtime"
] ]
serde = [ serde = [
"codec/serde", "codec/serde",
@@ -282,25 +282,12 @@ impl pezpallet_identity_kyc::Config for Test {
type DefaultReferrer = DefaultReferrerKyc; type DefaultReferrer = DefaultReferrerKyc;
} }
// Mock StakingInfo provider - SADECE BİR KEZ TANIMLA
pub struct MockStakingInfo;
impl pezpallet_staking_score::StakingInfoProvider<AccountId, Balance> for MockStakingInfo {
fn get_staking_details(
_account: &AccountId,
) -> Option<pezpallet_staking_score::StakingDetails<Balance>> {
Some(pezpallet_staking_score::StakingDetails {
staked_amount: 1000u128,
nominations_count: 0,
unlocking_chunks_count: 0,
})
}
}
// Staking Score Configuration // Staking Score Configuration
impl pezpallet_staking_score::Config for Test { impl pezpallet_staking_score::Config for Test {
type WeightInfo = ();
type Balance = Balance; type Balance = Balance;
type StakingInfo = MockStakingInfo; type OnStakingUpdate = ();
type WeightInfo = ();
type NoterChecker = ();
} }
// Referral Configuration // Referral Configuration
-4
View File
@@ -111,7 +111,6 @@ pezkuwi-runtime-teyrchains = { workspace = true }
pezkuwi-teyrchain-primitives = { workspace = true } pezkuwi-teyrchain-primitives = { workspace = true }
# Custom Pezkuwi Pallets # Custom Pezkuwi Pallets
pezpallet-staking-score = { workspace = true }
pezpallet-validator-pool = { workspace = true } pezpallet-validator-pool = { workspace = true }
xcm = { workspace = true } xcm = { workspace = true }
@@ -184,7 +183,6 @@ std = [
"pezpallet-session-benchmarking?/std", "pezpallet-session-benchmarking?/std",
"pezpallet-session/std", "pezpallet-session/std",
"pezpallet-staking-runtime-api/std", "pezpallet-staking-runtime-api/std",
"pezpallet-staking-score/std",
"pezpallet-staking/std", "pezpallet-staking/std",
"pezpallet-state-trie-migration/std", "pezpallet-state-trie-migration/std",
"pezpallet-sudo/std", "pezpallet-sudo/std",
@@ -277,7 +275,6 @@ runtime-benchmarks = [
"pezpallet-session-benchmarking/runtime-benchmarks", "pezpallet-session-benchmarking/runtime-benchmarks",
"pezpallet-session/runtime-benchmarks", "pezpallet-session/runtime-benchmarks",
"pezpallet-staking-runtime-api/runtime-benchmarks", "pezpallet-staking-runtime-api/runtime-benchmarks",
"pezpallet-staking-score/runtime-benchmarks",
"pezpallet-staking/runtime-benchmarks", "pezpallet-staking/runtime-benchmarks",
"pezpallet-state-trie-migration/runtime-benchmarks", "pezpallet-state-trie-migration/runtime-benchmarks",
"pezpallet-sudo/runtime-benchmarks", "pezpallet-sudo/runtime-benchmarks",
@@ -360,7 +357,6 @@ try-runtime = [
"pezpallet-scheduler/try-runtime", "pezpallet-scheduler/try-runtime",
"pezpallet-session-benchmarking?/try-runtime", "pezpallet-session-benchmarking?/try-runtime",
"pezpallet-session/try-runtime", "pezpallet-session/try-runtime",
"pezpallet-staking-score/try-runtime",
"pezpallet-staking/try-runtime", "pezpallet-staking/try-runtime",
"pezpallet-state-trie-migration/try-runtime", "pezpallet-state-trie-migration/try-runtime",
"pezpallet-sudo/try-runtime", "pezpallet-sudo/try-runtime",
-38
View File
@@ -565,40 +565,6 @@ impl pezpallet_staking::Config for Runtime {
type BenchmarkingConfig = PezkuwiStakingBenchmarkingConfig; type BenchmarkingConfig = PezkuwiStakingBenchmarkingConfig;
} }
// =====================================================
// STAKING SCORE CONFIGURATION
// =====================================================
/// Relay Chain StakingInfoProvider - reads directly from pezpallet_staking
/// This is the REAL implementation that accesses actual staking data
pub struct RelayStakingInfoProvider;
impl pezpallet_staking_score::StakingInfoProvider<AccountId, Balance> for RelayStakingInfoProvider {
fn get_staking_details(
who: &AccountId,
) -> Option<pezpallet_staking_score::StakingDetails<Balance>> {
// Get staking ledger from pezpallet_staking
let ledger = pezpallet_staking::Ledger::<Runtime>::get(who)?;
// Get nominations if any
let nominations_count = pezpallet_staking::Nominators::<Runtime>::get(who)
.map(|n| n.targets.len() as u32)
.unwrap_or(0);
Some(pezpallet_staking_score::StakingDetails {
staked_amount: ledger.active,
nominations_count,
unlocking_chunks_count: ledger.unlocking.len() as u32,
})
}
}
impl pezpallet_staking_score::Config for Runtime {
type Balance = Balance;
type StakingInfo = RelayStakingInfoProvider;
type WeightInfo = pezpallet_staking_score::weights::BizinikiwiWeight<Runtime>;
}
// ===================================================== // =====================================================
// FAST UNSTAKE CONFIGURATION // FAST UNSTAKE CONFIGURATION
// ===================================================== // =====================================================
@@ -1605,9 +1571,6 @@ construct_runtime! {
// TNPoS Validator Pool - Shadow Mode (runs parallel to NPoS) // TNPoS Validator Pool - Shadow Mode (runs parallel to NPoS)
ValidatorPool: pezpallet_validator_pool = 91, ValidatorPool: pezpallet_validator_pool = 91,
// Staking Score - Time-weighted staking reputation score
StakingScore: pezpallet_staking_score = 92,
// Root testing pezpallet. // Root testing pezpallet.
RootTesting: pezpallet_root_testing = 249, RootTesting: pezpallet_root_testing = 249,
@@ -1859,7 +1822,6 @@ mod benches {
[pezpallet_whitelist, Whitelist] [pezpallet_whitelist, Whitelist]
// Pezkuwichain Custom Pallets // Pezkuwichain Custom Pallets
[pezpallet_validator_pool, ValidatorPool] [pezpallet_validator_pool, ValidatorPool]
[pezpallet_staking_score, StakingScore]
// XCM // XCM
[pezpallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>] [pezpallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
[pezpallet_xcm_benchmarks::fungible, pezpallet_xcm_benchmarks::fungible::Pezpallet::<Runtime>] [pezpallet_xcm_benchmarks::fungible, pezpallet_xcm_benchmarks::fungible::Pezpallet::<Runtime>]
-1
View File
@@ -1,6 +1,5 @@
[package] [package]
name = "pezkuwi-sdk" name = "pezkuwi-sdk"
version = "0.0.0"
description = "Pezkuwi SDK umbrella crate." description = "Pezkuwi SDK umbrella crate."
license = "Apache-2.0" license = "Apache-2.0"
+13 -40
View File
@@ -23,7 +23,7 @@ const ASSET_HUB_PARA_ID: u32 = 1000;
// NominationPools pallet index on Asset Hub // NominationPools pallet index on Asset Hub
const NOM_POOLS_PALLET_INDEX: u8 = 81; // 0x51 const NOM_POOLS_PALLET_INDEX: u8 = 81; // 0x51
// set_configs call index // set_configs call index
const SET_CONFIGS_CALL_INDEX: u8 = 11; // 0x0b const SET_CONFIGS_CALL_INDEX: u8 = 11; // 0x0b
/// SCALE encode ConfigOp::Noop /// SCALE encode ConfigOp::Noop
@@ -74,9 +74,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let relay_url = let relay_url =
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string()); std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let min_join_hez: u128 = std::env::var("MIN_JOIN_BOND") let min_join_hez: u128 =
.unwrap_or_else(|_| "10".to_string()) std::env::var("MIN_JOIN_BOND").unwrap_or_else(|_| "10".to_string()).parse()?;
.parse()?;
let min_create_hez: u128 = std::env::var("MIN_CREATE_BOND") let min_create_hez: u128 = std::env::var("MIN_CREATE_BOND")
.unwrap_or_else(|_| "10000".to_string()) .unwrap_or_else(|_| "10000".to_string())
.parse()?; .parse()?;
@@ -87,10 +86,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Relay RPC: {}", relay_url); println!("Relay RPC: {}", relay_url);
println!("Asset Hub Para ID: {}", ASSET_HUB_PARA_ID); println!("Asset Hub Para ID: {}", ASSET_HUB_PARA_ID);
println!("MinJoinBond: {} HEZ ({} TYR)", min_join_hez, min_join_bond); println!("MinJoinBond: {} HEZ ({} TYR)", min_join_hez, min_join_bond);
println!( println!("MinCreateBond: {} HEZ ({} TYR)", min_create_hez, min_create_bond);
"MinCreateBond: {} HEZ ({} TYR)",
min_create_hez, min_create_bond
);
// Connect to relay chain // Connect to relay chain
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?; let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?;
@@ -105,11 +101,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Encode the NominationPools::set_configs call for Asset Hub // Encode the NominationPools::set_configs call for Asset Hub
let encoded_call = encode_set_configs_call(min_join_bond, min_create_bond); let encoded_call = encode_set_configs_call(min_join_bond, min_create_bond);
println!( println!("Encoded call: {} bytes (0x{})", encoded_call.len(), hex::encode(&encoded_call));
"Encoded call: {} bytes (0x{})",
encoded_call.len(),
hex::encode(&encoded_call)
);
// Build XCM destination: V3 MultiLocation { parents: 0, interior: X1(Teyrchain(1000)) } // Build XCM destination: V3 MultiLocation { parents: 0, interior: X1(Teyrchain(1000)) }
let dest = Value::unnamed_variant( let dest = Value::unnamed_variant(
@@ -136,23 +128,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Value::named_variant( Value::named_variant(
"UnpaidExecution", "UnpaidExecution",
[ [
( ("weight_limit", Value::unnamed_variant("Unlimited", vec![])),
"weight_limit", ("check_origin", Value::unnamed_variant("None", vec![])),
Value::unnamed_variant("Unlimited", vec![]),
),
(
"check_origin",
Value::unnamed_variant("None", vec![]),
),
], ],
), ),
Value::named_variant( Value::named_variant(
"Transact", "Transact",
[ [
( ("origin_kind", Value::unnamed_variant("Superuser", vec![])),
"origin_kind",
Value::unnamed_variant("Superuser", vec![]),
),
( (
"require_weight_at_most", "require_weight_at_most",
Value::named_composite([ Value::named_composite([
@@ -167,8 +150,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
); );
// Wrap in XcmPallet.send // Wrap in XcmPallet.send
let xcm_send = let xcm_send = pezkuwi_subxt::dynamic::tx("XcmPallet", "send", vec![dest, message]);
pezkuwi_subxt::dynamic::tx("XcmPallet", "send", vec![dest, message]);
// Wrap in sudo_unchecked_weight (no weight limit for sudo) // Wrap in sudo_unchecked_weight (no weight limit for sudo)
let sudo_call = pezkuwi_subxt::dynamic::tx( let sudo_call = pezkuwi_subxt::dynamic::tx(
@@ -188,15 +170,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Submit and watch // Submit and watch
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api let tx_progress =
.tx() api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await?;
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await?;
println!( println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
"TX hash: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
println!("Watching TX status..."); println!("Watching TX status...");
let mut progress = tx_progress; let mut progress = tx_progress;
@@ -212,11 +189,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" TX SUCCESS!"); println!(" TX SUCCESS!");
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!( println!(" Event: {}::{}", ev.pallet_name(), ev.variant_name());
" Event: {}::{}",
ev.pallet_name(),
ev.variant_name()
);
} }
} }
}, },
+15 -29
View File
@@ -28,10 +28,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.unwrap_or_else(|_| "499000".to_string()) .unwrap_or_else(|_| "499000".to_string())
.parse()?; .parse()?;
let bond_planck = bond_hez * PLANCKS_PER_HEZ; let bond_planck = bond_hez * PLANCKS_PER_HEZ;
let skip: usize = std::env::var("SKIP") let skip: usize =
.unwrap_or_else(|_| "0".to_string()) std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
.parse()
.unwrap_or(0);
println!("RPC: {}", url); println!("RPC: {}", url);
println!("Wallets file: {}", wallets_file); println!("Wallets file: {}", wallets_file);
@@ -90,33 +88,24 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" Account: {}", account); println!(" Account: {}", account);
// staking.bond_extra(max_additional: Balance) // staking.bond_extra(max_additional: Balance)
let bond_extra_tx = pezkuwi_subxt::dynamic::tx( let bond_extra_tx =
"Staking", pezkuwi_subxt::dynamic::tx("Staking", "bond_extra", vec![Value::u128(bond_planck)]);
"bond_extra",
vec![Value::u128(bond_planck)],
);
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let mut tx_ok = false; let mut tx_ok = false;
for attempt in 0..3 { for attempt in 0..3 {
let tx_progress = match api let tx_progress =
.tx() match api.tx().sign_and_submit_then_watch_default(&bond_extra_tx, &keypair).await {
.sign_and_submit_then_watch_default(&bond_extra_tx, &keypair) Ok(p) => p,
.await Err(e) => {
{ println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
Ok(p) => p, tokio::time::sleep(std::time::Duration::from_secs(12)).await;
Err(e) => { continue;
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e); },
tokio::time::sleep(std::time::Duration::from_secs(12)).await; };
continue;
},
};
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
loop { loop {
@@ -198,10 +187,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== RESULTS ==="); println!("\n=== RESULTS ===");
println!("Success: {}/{}", success_count, stash_wallets.len() - skip); println!("Success: {}/{}", success_count, stash_wallets.len() - skip);
println!("Failed: {}/{}", fail_count, stash_wallets.len() - skip); println!("Failed: {}/{}", fail_count, stash_wallets.len() - skip);
println!( println!("Total bonded: {} HEZ", bond_hez * success_count as u128);
"Total bonded: {} HEZ",
bond_hez * success_count as u128
);
Ok(()) Ok(())
} }
@@ -85,13 +85,7 @@ fn build_pool_configs(wallets: Vec<WalletInfo>) -> Vec<PoolConfig> {
.enumerate() .enumerate()
.map(|(i, w)| { .map(|(i, w)| {
let stake_hez = base_stake.saturating_sub(i as u128 * 10_000); let stake_hez = base_stake.saturating_sub(i as u128 * 10_000);
PoolConfig { PoolConfig { name: w.name, mnemonic: w.mnemonic, ss58: w.ss58, transfer_hez, stake_hez }
name: w.name,
mnemonic: w.mnemonic,
ss58: w.ss58,
transfer_hez,
stake_hez,
}
}) })
.collect() .collect()
} }
@@ -104,26 +98,20 @@ async fn wait_for_success(
loop { loop {
let status = progress.next().await; let status = progress.next().await;
match status { match status {
Some(Ok(TxStatus::InBestBlock(details))) => { Some(Ok(TxStatus::InBestBlock(details))) => match details.wait_for_success().await {
match details.wait_for_success().await { Ok(events) => {
Ok(events) => { println!(" {} SUCCESS!", label);
println!(" {} SUCCESS!", label); for event in events.iter() {
for event in events.iter() { if let Ok(ev) = event {
if let Ok(ev) = event { println!(" {}::{}", ev.pallet_name(), ev.variant_name());
println!(
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
}
} }
return Ok(true); }
}, return Ok(true);
Err(e) => { },
println!(" {} DISPATCH ERROR: {}", label, e); Err(e) => {
return Ok(false); println!(" {} DISPATCH ERROR: {}", label, e);
}, return Ok(false);
} },
}, },
Some(Ok(TxStatus::Error { message })) => { Some(Ok(TxStatus::Error { message })) => {
println!(" {} TX ERROR: {}", label, message); println!(" {} TX ERROR: {}", label, message);
@@ -158,13 +146,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Parse CLI args // Parse CLI args
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let phase = args.get(1).map(|s| s.as_str()).unwrap_or("all"); let phase = args.get(1).map(|s| s.as_str()).unwrap_or("all");
let skip: usize = std::env::var("SKIP") let skip: usize =
.unwrap_or_else(|_| "0".to_string()) std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
.parse()
.unwrap_or(0);
let rpc = let rpc = std::env::var("ASSET_HUB_RPC").unwrap_or_else(|_| DEFAULT_ASSET_HUB_RPC.to_string());
std::env::var("ASSET_HUB_RPC").unwrap_or_else(|_| DEFAULT_ASSET_HUB_RPC.to_string());
println!("=== NOMINATION POOL CREATOR ==="); println!("=== NOMINATION POOL CREATOR ===");
println!("Asset Hub RPC: {}", rpc); println!("Asset Hub RPC: {}", rpc);
@@ -182,10 +167,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let founder_mn = Mnemonic::from_str(&founder_mnemonic())?; let founder_mn = Mnemonic::from_str(&founder_mnemonic())?;
let founder_keypair = Keypair::from_phrase(&founder_mn, None)?; let founder_keypair = Keypair::from_phrase(&founder_mn, None)?;
println!( println!("Founder: {}\n", founder_keypair.public_key().to_account_id());
"Founder: {}\n",
founder_keypair.public_key().to_account_id()
);
for (i, pool) in pool_configs.iter().enumerate().skip(skip) { for (i, pool) in pool_configs.iter().enumerate().skip(skip) {
println!( println!(
@@ -228,10 +210,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}, },
}; };
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
tx_ok = wait_for_success(tx_progress, "TRANSFER").await?; tx_ok = wait_for_success(tx_progress, "TRANSFER").await?;
if tx_ok { if tx_ok {
@@ -314,10 +293,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}, },
}; };
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
create_ok = wait_for_success(tx_progress, "CREATE_POOL").await?; create_ok = wait_for_success(tx_progress, "CREATE_POOL").await?;
if create_ok { if create_ok {
@@ -335,15 +311,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
tokio::time::sleep(std::time::Duration::from_secs(12)).await; tokio::time::sleep(std::time::Duration::from_secs(12)).await;
// Query LastPoolId to get the pool_id // Query LastPoolId to get the pool_id
let last_pool_query = pezkuwi_subxt::dynamic::storage::<(), Value>( let last_pool_query =
"NominationPools", pezkuwi_subxt::dynamic::storage::<(), Value>("NominationPools", "LastPoolId");
"LastPoolId",
);
let storage_client = api.storage().at_latest().await?; let storage_client = api.storage().at_latest().await?;
let last_pool = storage_client let last_pool = storage_client.entry(last_pool_query)?.try_fetch(()).await?;
.entry(last_pool_query)?
.try_fetch(())
.await?;
let pool_id = match last_pool { let pool_id = match last_pool {
Some(val) => { Some(val) => {
@@ -369,10 +340,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let metadata_tx = pezkuwi_subxt::dynamic::tx( let metadata_tx = pezkuwi_subxt::dynamic::tx(
"NominationPools", "NominationPools",
"set_metadata", "set_metadata",
vec![ vec![Value::u128(pool_id as u128), Value::from_bytes(&name_bytes)],
Value::u128(pool_id as u128),
Value::from_bytes(&name_bytes),
],
); );
let tx_progress = match api let tx_progress = match api
@@ -387,10 +355,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}, },
}; };
println!( println!(" METADATA TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" METADATA TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let ok = wait_for_success(tx_progress, "SET_METADATA").await?; let ok = wait_for_success(tx_progress, "SET_METADATA").await?;
if ok { if ok {
@@ -401,7 +366,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
} }
println!(" Pool '{}' (ID: {}) created with {} HEZ\n", pool.name, pool_id, pool.stake_hez); println!(
" Pool '{}' (ID: {}) created with {} HEZ\n",
pool.name, pool_id, pool.stake_hez
);
// Wait between pools // Wait between pools
if i + 1 < pool_configs.len() { if i + 1 < pool_configs.len() {
+8 -29
View File
@@ -28,20 +28,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Sudo account: {}\n", keypair.public_key().to_account_id()); println!("Sudo account: {}\n", keypair.public_key().to_account_id());
// Staking::ForceEra storage key (verified twox128) // Staking::ForceEra storage key (verified twox128)
let force_era_key = hex::decode( let force_era_key =
"5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3", hex::decode("5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3")?;
)?;
// NotForcing = enum variant 0 = 0x00 // NotForcing = enum variant 0 = 0x00
let not_forcing_value = vec![0x00u8]; let not_forcing_value = vec![0x00u8];
println!( println!("Storage key: 0x{}", hex::encode(&force_era_key));
"Storage key: 0x{}", println!("New value: 0x{} (NotForcing)", hex::encode(&not_forcing_value));
hex::encode(&force_era_key)
);
println!(
"New value: 0x{} (NotForcing)",
hex::encode(&not_forcing_value)
);
// Build: system.setStorage(items: Vec<(Key, Value)>) // Build: system.setStorage(items: Vec<(Key, Value)>)
let set_storage_call = pezkuwi_subxt::dynamic::tx( let set_storage_call = pezkuwi_subxt::dynamic::tx(
@@ -54,24 +47,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
); );
// Wrap in sudo // Wrap in sudo
let sudo_call = pezkuwi_subxt::dynamic::tx( let sudo_call = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![set_storage_call.into_value()]);
"Sudo",
"sudo",
vec![set_storage_call.into_value()],
);
println!("\nSubmitting sudo(system.setStorage)..."); println!("\nSubmitting sudo(system.setStorage)...");
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api let tx_progress = api.tx().sign_and_submit_then_watch_default(&sudo_call, &keypair).await?;
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &keypair)
.await?;
println!( println!("TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
"TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
loop { loop {
@@ -83,11 +66,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut sudid = false; let mut sudid = false;
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!( println!(" Event: {}::{}", ev.pallet_name(), ev.variant_name());
" Event: {}::{}",
ev.pallet_name(),
ev.variant_name()
);
if ev.pallet_name() == "Sudo" && ev.variant_name() == "Sudid" { if ev.pallet_name() == "Sudo" && ev.variant_name() == "Sudid" {
sudid = true; sudid = true;
} }
+11 -36
View File
@@ -20,7 +20,7 @@ const PEOPLE_CHAIN_PARA_ID: u32 = 1004;
// Tiki pallet index on People Chain // Tiki pallet index on People Chain
const TIKI_PALLET_INDEX: u8 = 61; // 0x3d const TIKI_PALLET_INDEX: u8 = 61; // 0x3d
// force_mint_citizen_nft call index // force_mint_citizen_nft call index
const FORCE_MINT_CALL_INDEX: u8 = 2; // 0x02 const FORCE_MINT_CALL_INDEX: u8 = 2; // 0x02
/// Encode Tiki::force_mint_citizen_nft(dest) for People Chain /// Encode Tiki::force_mint_citizen_nft(dest) for People Chain
@@ -61,23 +61,14 @@ fn build_xcm_sudo_transact(encoded_call: &[u8]) -> (Value, Value) {
Value::named_variant( Value::named_variant(
"UnpaidExecution", "UnpaidExecution",
[ [
( ("weight_limit", Value::unnamed_variant("Unlimited", vec![])),
"weight_limit", ("check_origin", Value::unnamed_variant("None", vec![])),
Value::unnamed_variant("Unlimited", vec![]),
),
(
"check_origin",
Value::unnamed_variant("None", vec![]),
),
], ],
), ),
Value::named_variant( Value::named_variant(
"Transact", "Transact",
[ [
( ("origin_kind", Value::unnamed_variant("Superuser", vec![])),
"origin_kind",
Value::unnamed_variant("Superuser", vec![]),
),
( (
"require_weight_at_most", "require_weight_at_most",
Value::named_composite([ Value::named_composite([
@@ -127,10 +118,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string()); std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
// Skip first N validators (already minted) // Skip first N validators (already minted)
let skip: usize = std::env::var("SKIP") let skip: usize =
.unwrap_or_else(|_| "0".to_string()) std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
.parse()
.unwrap_or(0);
println!("Relay RPC: {}", relay_url); println!("Relay RPC: {}", relay_url);
println!("People Chain Para ID: {}", PEOPLE_CHAIN_PARA_ID); println!("People Chain Para ID: {}", PEOPLE_CHAIN_PARA_ID);
@@ -175,8 +164,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (dest, message) = build_xcm_sudo_transact(&encoded_call); let (dest, message) = build_xcm_sudo_transact(&encoded_call);
// Wrap in xcmPallet.send then sudo // Wrap in xcmPallet.send then sudo
let xcm_send = let xcm_send = pezkuwi_subxt::dynamic::tx("XcmPallet", "send", vec![dest, message]);
pezkuwi_subxt::dynamic::tx("XcmPallet", "send", vec![dest, message]);
let sudo_call = pezkuwi_subxt::dynamic::tx( let sudo_call = pezkuwi_subxt::dynamic::tx(
"Sudo", "Sudo",
@@ -196,11 +184,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Retry up to 3 times on submit error // Retry up to 3 times on submit error
let mut tx_progress_opt = None; let mut tx_progress_opt = None;
for attempt in 0..3 { for attempt in 0..3 {
match api match api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await {
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await
{
Ok(p) => { Ok(p) => {
tx_progress_opt = Some(p); tx_progress_opt = Some(p);
break; break;
@@ -220,10 +204,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}, },
}; };
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
let mut tx_ok = false; let mut tx_ok = false;
@@ -237,9 +218,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut has_sent = false; let mut has_sent = false;
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
if ev.pallet_name() == "Sudo" if ev.pallet_name() == "Sudo" && ev.variant_name() == "Sudid" {
&& ev.variant_name() == "Sudid"
{
has_sudid = true; has_sudid = true;
} }
if ev.pallet_name() == "XcmPallet" if ev.pallet_name() == "XcmPallet"
@@ -256,11 +235,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" WARNING: Missing expected events"); println!(" WARNING: Missing expected events");
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!( println!(" {}::{}", ev.pallet_name(), ev.variant_name());
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
} }
} }
} }
+66 -53
View File
@@ -6,66 +6,79 @@ use std::str::FromStr;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string()); let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let message = std::env::var("MESSAGE").expect("MESSAGE env var required"); let message = std::env::var("MESSAGE").expect("MESSAGE env var required");
println!("RPC: {}", url); println!("RPC: {}", url);
println!("Message: {}", message); println!("Message: {}", message);
println!("Message bytes: {}", message.len()); println!("Message bytes: {}", message.len());
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?; let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?;
println!("Connected!"); println!("Connected!");
let mnemonic_str = std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC required"); let mnemonic_str = std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC required");
let mnemonic = Mnemonic::from_str(&mnemonic_str)?; let mnemonic = Mnemonic::from_str(&mnemonic_str)?;
let keypair = Keypair::from_phrase(&mnemonic, None)?; let keypair = Keypair::from_phrase(&mnemonic, None)?;
println!("Account: {}\n", keypair.public_key().to_account_id()); println!("Account: {}\n", keypair.public_key().to_account_id());
let remark_tx = pezkuwi_subxt::dynamic::tx( let remark_tx = pezkuwi_subxt::dynamic::tx(
"System", "System",
"remark_with_event", "remark_with_event",
vec![Value::from_bytes(message.as_bytes())], vec![Value::from_bytes(message.as_bytes())],
); );
println!("Submitting remarkWithEvent..."); println!("Submitting remarkWithEvent...");
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api.tx() let tx_progress = api.tx().sign_and_submit_then_watch_default(&remark_tx, &keypair).await?;
.sign_and_submit_then_watch_default(&remark_tx, &keypair)
.await?;
println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref())); println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
let mut progress = tx_progress; let mut progress = tx_progress;
loop { loop {
let status = progress.next().await; let status = progress.next().await;
match status { match status {
Some(Ok(TxStatus::Validated)) => println!(" Validated"), Some(Ok(TxStatus::Validated)) => println!(" Validated"),
Some(Ok(TxStatus::Broadcasted)) => println!(" Broadcasted"), Some(Ok(TxStatus::Broadcasted)) => println!(" Broadcasted"),
Some(Ok(TxStatus::InBestBlock(details))) => { Some(Ok(TxStatus::InBestBlock(details))) => {
println!(" InBestBlock {:?}", details.block_hash()); println!(" InBestBlock {:?}", details.block_hash());
match details.wait_for_success().await { match details.wait_for_success().await {
Ok(events) => { Ok(events) => {
println!(" SUCCESS!"); println!(" SUCCESS!");
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!(" {}::{}", ev.pallet_name(), ev.variant_name()); println!(" {}::{}", ev.pallet_name(), ev.variant_name());
} }
} }
}, },
Err(e) => println!(" Error: {}", e), Err(e) => println!(" Error: {}", e),
} }
break; break;
}, },
Some(Ok(TxStatus::Error { message })) => { println!(" ERROR: {}", message); break; }, Some(Ok(TxStatus::Error { message })) => {
Some(Ok(TxStatus::Invalid { message })) => { println!(" INVALID: {}", message); break; }, println!(" ERROR: {}", message);
Some(Ok(TxStatus::Dropped { message })) => { println!(" DROPPED: {}", message); break; }, break;
Some(Err(e)) => { println!(" Error: {}", e); break; }, },
None => { println!(" Stream ended"); break; }, Some(Ok(TxStatus::Invalid { message })) => {
_ => {}, println!(" INVALID: {}", message);
} break;
} },
Some(Ok(TxStatus::Dropped { message })) => {
println!(" DROPPED: {}", message);
break;
},
Some(Err(e)) => {
println!(" Error: {}", e);
break;
},
None => {
println!(" Stream ended");
break;
},
_ => {},
}
}
println!("\nDone."); println!("\nDone.");
Ok(()) Ok(())
} }
+112 -48
View File
@@ -33,27 +33,111 @@ struct ValidatorInfo {
fn validators() -> Vec<ValidatorInfo> { fn validators() -> Vec<ValidatorInfo> {
vec![ vec![
ValidatorInfo { name: "Çiyager (Cihat Türkan)", ss58: "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i", staked_hez: 499_100 }, ValidatorInfo {
ValidatorInfo { name: "Mehmet Tunç", ss58: "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk", staked_hez: 499_100 }, name: "Çiyager (Cihat Türkan)",
ValidatorInfo { name: "Nagihan Akarsel", ss58: "5CrB5BWJfLNWEZAsAXDKXdJUGzFMXKvYnwRX4DVMcgBwxSdx", staked_hez: 499_100 }, ss58: "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i",
ValidatorInfo { name: "Sait Çürükkaya (Doktor Süleyman)", ss58: "5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp", staked_hez: 499_100 }, staked_hez: 499_100,
ValidatorInfo { name: "Evdile Koçer", ss58: "5GCZQNjRdHofEHPvVq4ePrfDYcjRzQ1HQ2awHMX6AawpRYuM", staked_hez: 499_100 }, },
ValidatorInfo { name: "Mam Zeki", ss58: "5H8jTzi4Gm4rbFtXw6h5enhLhgsuhNAqR5K2itmPiz83ymWy", staked_hez: 499_100 }, ValidatorInfo {
ValidatorInfo { name: "Kakaî Falah", ss58: "5Fs3P5tHuL9cvwPQojsheViRRAjFkMMFa32jAkDSwW9mbTfU", staked_hez: 499_100 }, name: "Mehmet Tunç",
ValidatorInfo { name: "Feryad Fazil Ömer", ss58: "5DXgq7uDXog6zcubT3wgtaYosoibjudz4w5ScPW2phLuAy3V", staked_hez: 499_100 }, ss58: "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk",
ValidatorInfo { name: "Mevlud Afand", ss58: "5FyFwbGLgPXun3azh6Gx83wCuUt5FTavb2WAVDYrjziVB9rN", staked_hez: 499_100 }, staked_hez: 499_100,
ValidatorInfo { name: "Şêrko Fatih Şivandî", ss58: "5HEcuuypLDeJaSj6ZgH57aXhuviyeLNdw9QrCDJ8u6gsnjnL", staked_hez: 499_100 }, },
ValidatorInfo { name: "Ramin Hüseyin Penahi", ss58: "5EpmpTXbMXpz6ixy3WhutdzcexzPbvybNKv4eiiN1kvTnQH5", staked_hez: 499_100 }, ValidatorInfo {
ValidatorInfo { name: "Zanyar Moradi", ss58: "5DFsm3BBEgHmSEZkvwGKB7c7tiH2avhfuQE1SEjfMDGuczsW", staked_hez: 499_100 }, name: "Nagihan Akarsel",
ValidatorInfo { name: "Heidar Ghorbani", ss58: "5HePVUXjGSM2hVZ1YMz2V3KoX6EdQNEmmzUnUvpfGV95ofUR", staked_hez: 499_100 }, ss58: "5CrB5BWJfLNWEZAsAXDKXdJUGzFMXKvYnwRX4DVMcgBwxSdx",
ValidatorInfo { name: "Farhad Salimi", ss58: "5GP4nAcwtETTg1oAHQNvevmmhG8GEstGQeCirKEhaDTwpFgx", staked_hez: 499_100 }, staked_hez: 499_100,
ValidatorInfo { name: "Vafa Azarbar", ss58: "5FYoCM3oeEGeoFY94EgXBhmABkRCabvPp72ur5bJNG3cK619", staked_hez: 499_100 }, },
ValidatorInfo { name: "Dr. Aziz Mihemed", ss58: "5GspwkKF6aYzFkmAyBBQg7coSCSgDCore79fbW8uxJNAH347", staked_hez: 499_100 }, ValidatorInfo {
ValidatorInfo { name: "Arîn Mîrkan", ss58: "5GmuX11pN2fC4Fyq1V7MuiYt3aevZcVQs3HZWKyzmap9bKfe", staked_hez: 499_100 }, name: "Sait Çürükkaya (Doktor Süleyman)",
ValidatorInfo { name: "Ebu Leyla", ss58: "5FQptVCtM1qsxkLbQkATkw4Kio4M9LxWvM6TwgEo3QjmTXF3", staked_hez: 499_100 }, ss58: "5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp",
ValidatorInfo { name: "Rêvan Kobanê", ss58: "5E7VD2qmso1yRfyq3t9u2qhauAgtmjZTybVsCARF5Zz9bXy6", staked_hez: 499_100 }, staked_hez: 499_100,
ValidatorInfo { name: "Amanj Babani", ss58: "5Ccz5W7Q21g4UPCytzHxD3VSMLJ1BbbWSkJKFwsNtYRk3HkX", staked_hez: 499_100 }, },
ValidatorInfo { name: "Xosrow Gulan", ss58: "5D7WPmK1SAJyYDdCtgqEzGJpWXQe3Lj9FqWL8z9waLTkUNv3", staked_hez: 499_100 }, ValidatorInfo {
name: "Evdile Koçer",
ss58: "5GCZQNjRdHofEHPvVq4ePrfDYcjRzQ1HQ2awHMX6AawpRYuM",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Mam Zeki",
ss58: "5H8jTzi4Gm4rbFtXw6h5enhLhgsuhNAqR5K2itmPiz83ymWy",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Kakaî Falah",
ss58: "5Fs3P5tHuL9cvwPQojsheViRRAjFkMMFa32jAkDSwW9mbTfU",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Feryad Fazil Ömer",
ss58: "5DXgq7uDXog6zcubT3wgtaYosoibjudz4w5ScPW2phLuAy3V",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Mevlud Afand",
ss58: "5FyFwbGLgPXun3azh6Gx83wCuUt5FTavb2WAVDYrjziVB9rN",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Şêrko Fatih Şivandî",
ss58: "5HEcuuypLDeJaSj6ZgH57aXhuviyeLNdw9QrCDJ8u6gsnjnL",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Ramin Hüseyin Penahi",
ss58: "5EpmpTXbMXpz6ixy3WhutdzcexzPbvybNKv4eiiN1kvTnQH5",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Zanyar Moradi",
ss58: "5DFsm3BBEgHmSEZkvwGKB7c7tiH2avhfuQE1SEjfMDGuczsW",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Heidar Ghorbani",
ss58: "5HePVUXjGSM2hVZ1YMz2V3KoX6EdQNEmmzUnUvpfGV95ofUR",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Farhad Salimi",
ss58: "5GP4nAcwtETTg1oAHQNvevmmhG8GEstGQeCirKEhaDTwpFgx",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Vafa Azarbar",
ss58: "5FYoCM3oeEGeoFY94EgXBhmABkRCabvPp72ur5bJNG3cK619",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Dr. Aziz Mihemed",
ss58: "5GspwkKF6aYzFkmAyBBQg7coSCSgDCore79fbW8uxJNAH347",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Arîn Mîrkan",
ss58: "5GmuX11pN2fC4Fyq1V7MuiYt3aevZcVQs3HZWKyzmap9bKfe",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Ebu Leyla",
ss58: "5FQptVCtM1qsxkLbQkATkw4Kio4M9LxWvM6TwgEo3QjmTXF3",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Rêvan Kobanê",
ss58: "5E7VD2qmso1yRfyq3t9u2qhauAgtmjZTybVsCARF5Zz9bXy6",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Amanj Babani",
ss58: "5Ccz5W7Q21g4UPCytzHxD3VSMLJ1BbbWSkJKFwsNtYRk3HkX",
staked_hez: 499_100,
},
ValidatorInfo {
name: "Xosrow Gulan",
ss58: "5D7WPmK1SAJyYDdCtgqEzGJpWXQe3Lj9FqWL8z9waLTkUNv3",
staked_hez: 499_100,
},
] ]
} }
@@ -143,10 +227,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let relay_url = let relay_url =
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string()); std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let skip: usize = std::env::var("SKIP") let skip: usize =
.unwrap_or_else(|_| "0".to_string()) std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
.parse()
.unwrap_or(0);
let vals = validators(); let vals = validators();
println!("Relay RPC: {}", relay_url); println!("Relay RPC: {}", relay_url);
@@ -155,10 +237,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to relay chain // Connect to relay chain
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?; let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?;
println!( println!("Connected! specVersion: {}\n", api.runtime_version().spec_version);
"Connected! specVersion: {}\n",
api.runtime_version().spec_version
);
// Load sudo keypair // Load sudo keypair
let mnemonic_str = let mnemonic_str =
@@ -196,11 +275,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
0, 0,
0, 0,
); );
println!( println!(" Call: {} bytes (0x{}...)", call.len(), hex::encode(&call[..6]));
" Call: {} bytes (0x{}...)",
call.len(),
hex::encode(&call[..6])
);
// Build XCM message // Build XCM message
let (dest, message) = build_xcm_values(&call); let (dest, message) = build_xcm_values(&call);
@@ -224,11 +299,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let mut tx_progress_opt = None; let mut tx_progress_opt = None;
for attempt in 0..3 { for attempt in 0..3 {
match api match api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await {
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await
{
Ok(p) => { Ok(p) => {
tx_progress_opt = Some(p); tx_progress_opt = Some(p);
break; break;
@@ -249,10 +320,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}, },
}; };
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
let mut tx_ok = false; let mut tx_ok = false;
@@ -283,11 +351,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" WARNING: Events:"); println!(" WARNING: Events:");
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!( println!(" {}::{}", ev.pallet_name(), ev.variant_name());
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
} }
} }
} }
+14 -36
View File
@@ -48,12 +48,9 @@ fn load_wallets() -> Vec<WalletInfo> {
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== SET POOL METADATA ===\n"); println!("=== SET POOL METADATA ===\n");
let start_id: u32 = std::env::var("START_ID") let start_id: u32 = std::env::var("START_ID").unwrap_or_else(|_| "1".to_string()).parse()?;
.unwrap_or_else(|_| "1".to_string())
.parse()?;
let rpc = let rpc = std::env::var("ASSET_HUB_RPC").unwrap_or_else(|_| DEFAULT_ASSET_HUB_RPC.to_string());
std::env::var("ASSET_HUB_RPC").unwrap_or_else(|_| DEFAULT_ASSET_HUB_RPC.to_string());
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&rpc).await?; let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&rpc).await?;
println!("Connected to Asset Hub!\n"); println!("Connected to Asset Hub!\n");
@@ -66,23 +63,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
if let Some(val) = last_pool { if let Some(val) = last_pool {
let decoded = val.decode()?; let decoded = val.decode()?;
println!("LastPoolId raw value: {:?}", decoded); println!("LastPoolId raw value: {:?}", decoded);
println!( println!("LastPoolId as_u128: {:?}", decoded.as_u128());
"LastPoolId as_u128: {:?}",
decoded.as_u128()
);
} }
let wallets = load_wallets(); let wallets = load_wallets();
for (i, wallet) in wallets.iter().enumerate() { for (i, wallet) in wallets.iter().enumerate() {
let pool_id = start_id + i as u32; let pool_id = start_id + i as u32;
println!( println!("--- [{}/{}] Pool {} -> '{}' ---", i + 1, wallets.len(), pool_id, wallet.name);
"--- [{}/{}] Pool {} -> '{}' ---",
i + 1,
wallets.len(),
pool_id,
wallet.name
);
let mnemonic = Mnemonic::from_str(&wallet.mnemonic)?; let mnemonic = Mnemonic::from_str(&wallet.mnemonic)?;
let keypair = Keypair::from_phrase(&mnemonic, None)?; let keypair = Keypair::from_phrase(&mnemonic, None)?;
@@ -102,22 +90,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
tokio::time::sleep(std::time::Duration::from_secs(18)).await; tokio::time::sleep(std::time::Duration::from_secs(18)).await;
} }
let tx_progress = match api let tx_progress =
.tx() match api.tx().sign_and_submit_then_watch_default(&metadata_tx, &keypair).await {
.sign_and_submit_then_watch_default(&metadata_tx, &keypair) Ok(p) => p,
.await Err(e) => {
{ println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
Ok(p) => p, continue;
Err(e) => { },
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e); };
continue;
},
};
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let mut progress = tx_progress; let mut progress = tx_progress;
@@ -130,11 +112,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" SUCCESS!"); println!(" SUCCESS!");
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!( println!(" {}::{}", ev.pallet_name(), ev.variant_name());
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
} }
} }
ok = true; ok = true;
@@ -0,0 +1,130 @@
//! Test start_score_tracking on People Chain
//!
//! 1. Transfer small amount from founder to validator on People Chain
//! 2. Call start_score_tracking() from validator account
//! 3. Verify StakingStartBlock was set
//!
//! FOUNDER_MNEMONIC="..." VALIDATOR_MNEMONIC="..." cargo run --release -p pezkuwi-subxt --example test_start_tracking
#![allow(missing_docs)]
use pezkuwi_subxt::dynamic::Value;
use pezkuwi_subxt::utils::AccountId32;
use pezkuwi_subxt::{OnlineClient, PezkuwiConfig};
use pezkuwi_subxt_signer::bip39::Mnemonic;
use pezkuwi_subxt_signer::sr25519::Keypair;
use std::str::FromStr;
const PEOPLE_RPC: &str = "ws://217.77.6.126:41944";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== TEST: start_score_tracking on People Chain ===\n");
let founder_mnemonic_str =
std::env::var("FOUNDER_MNEMONIC").expect("FOUNDER_MNEMONIC env var required");
let validator_mnemonic_str =
std::env::var("VALIDATOR_MNEMONIC").expect("VALIDATOR_MNEMONIC env var required");
let founder_mnemonic = Mnemonic::from_str(&founder_mnemonic_str)?;
let founder_keypair = Keypair::from_phrase(&founder_mnemonic, None)?;
let founder_account = AccountId32(founder_keypair.public_key().0);
let validator_mnemonic = Mnemonic::from_str(&validator_mnemonic_str)?;
let validator_keypair = Keypair::from_phrase(&validator_mnemonic, None)?;
let validator_account = AccountId32(validator_keypair.public_key().0);
println!("Founder: {}", founder_account);
println!("Validator: {}", validator_account);
println!("\nConnecting to People Chain: {}", PEOPLE_RPC);
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(PEOPLE_RPC).await?;
println!("Connected (spec_version: {})\n", api.runtime_version().spec_version);
// Step 1: Transfer 10 HEZ from founder to validator for tx fees
let transfer_amount: u128 = 10_000_000_000_000; // 10 HEZ
println!("--- Step 1: Transfer 10 HEZ to validator for fees ---");
let transfer = pezkuwi_subxt::dynamic::tx(
"Balances",
"transfer_keep_alive",
vec![
Value::unnamed_variant("Id", [Value::from_bytes(&validator_account.0)]),
Value::u128(transfer_amount),
],
);
let progress = api.tx().sign_and_submit_then_watch_default(&transfer, &founder_keypair).await?;
println!("TX: 0x{}", hex::encode(progress.extrinsic_hash().as_ref()));
let events = progress.wait_for_finalized_success().await?;
println!("Transfer finalized!");
for ev in events.iter() {
if let Ok(ev) = ev {
if ev.pallet_name() == "Balances" {
println!(" {}::{}", ev.pallet_name(), ev.variant_name());
}
}
}
// Step 2: Call start_score_tracking from validator
println!("\n--- Step 2: start_score_tracking() ---");
let start_tracking =
pezkuwi_subxt::dynamic::tx("StakingScore", "start_score_tracking", Vec::<Value>::new());
let progress = api
.tx()
.sign_and_submit_then_watch_default(&start_tracking, &validator_keypair)
.await?;
println!("TX: 0x{}", hex::encode(progress.extrinsic_hash().as_ref()));
match progress.wait_for_finalized_success().await {
Ok(events) => {
println!("start_score_tracking SUCCESS!");
for ev in events.iter() {
if let Ok(ev) = ev {
let p = ev.pallet_name();
if p == "StakingScore" || p == "Trust" || p == "System" {
println!(" {}::{}", p, ev.variant_name());
}
}
}
},
Err(e) => {
println!("start_score_tracking FAILED: {:?}", e);
},
}
// Step 3: Verify StakingStartBlock was set
println!("\n--- Step 3: Verify StakingStartBlock ---");
let query = pezkuwi_subxt::dynamic::storage::<(AccountId32,), Value>(
"StakingScore",
"StakingStartBlock",
);
let storage = api.storage().at_latest().await?;
match storage.entry(query)?.try_fetch((validator_account.clone(),)).await? {
Some(val) => {
let decoded = val.decode()?;
println!("StakingStartBlock for validator: {:?}", decoded);
},
None => {
println!("StakingStartBlock: NOT SET (ERROR!)");
},
}
// Step 4: Check TrustScore
println!("\n--- Step 4: Check TrustScore ---");
let query = pezkuwi_subxt::dynamic::storage::<(AccountId32,), Value>("Trust", "TrustScores");
match storage.entry(query)?.try_fetch((validator_account.clone(),)).await? {
Some(val) => {
let decoded = val.decode()?;
println!("TrustScore for validator: {:?}", decoded);
},
None => {
println!("TrustScore: NOT SET (may need on_initialize cycle)");
},
}
println!("\n=== TEST COMPLETE ===");
Ok(())
}
+16 -31
View File
@@ -44,14 +44,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
]; ];
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string()); let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let amount_hez: u128 = std::env::var("AMOUNT_HEZ") let amount_hez: u128 =
.unwrap_or_else(|_| "500000".to_string()) std::env::var("AMOUNT_HEZ").unwrap_or_else(|_| "500000".to_string()).parse()?;
.parse()?;
let amount_planck = amount_hez * PLANCKS_PER_HEZ; let amount_planck = amount_hez * PLANCKS_PER_HEZ;
let skip: usize = std::env::var("SKIP") let skip: usize =
.unwrap_or_else(|_| "0".to_string()) std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
.parse()
.unwrap_or(0);
println!("RPC: {}", url); println!("RPC: {}", url);
println!("Amount per validator: {} HEZ ({} TYR)", amount_hez, amount_planck); println!("Amount per validator: {} HEZ ({} TYR)", amount_hez, amount_planck);
@@ -100,23 +97,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut tx_ok = false; let mut tx_ok = false;
for attempt in 0..3 { for attempt in 0..3 {
let tx_progress = match api let tx_progress =
.tx() match api.tx().sign_and_submit_then_watch_default(&transfer_tx, &keypair).await {
.sign_and_submit_then_watch_default(&transfer_tx, &keypair) Ok(p) => p,
.await Err(e) => {
{ println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
Ok(p) => p, tokio::time::sleep(std::time::Duration::from_secs(12)).await;
Err(e) => { continue;
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e); },
tokio::time::sleep(std::time::Duration::from_secs(12)).await; };
continue;
},
};
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
loop { loop {
@@ -130,10 +121,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
if ev.pallet_name() == "Balances" if ev.pallet_name() == "Balances"
&& ev.variant_name() == "Transfer" && ev.variant_name() == "Transfer"
{ {
println!( println!(" SUCCESS: {} HEZ transferred", amount_hez);
" SUCCESS: {} HEZ transferred",
amount_hez
);
tx_ok = true; tx_ok = true;
} }
} }
@@ -200,10 +188,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\n=== RESULTS ==="); println!("\n=== RESULTS ===");
println!("Success: {}/{}", success_count, validators.len() - skip); println!("Success: {}/{}", success_count, validators.len() - skip);
println!("Failed: {}/{}", fail_count, validators.len() - skip); println!("Failed: {}/{}", fail_count, validators.len() - skip);
println!( println!("Total transferred: {} HEZ", amount_hez * success_count as u128);
"Total transferred: {} HEZ",
amount_hez * success_count as u128
);
Ok(()) Ok(())
} }
+90 -43
View File
@@ -44,27 +44,90 @@ struct ValidatorInfo {
fn validators() -> Vec<ValidatorInfo> { fn validators() -> Vec<ValidatorInfo> {
vec![ vec![
ValidatorInfo { name: "Çiyager (Cihat Türkan)", ss58: "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i" }, ValidatorInfo {
ValidatorInfo { name: "Mehmet Tunç", ss58: "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk" }, name: "Çiyager (Cihat Türkan)",
ValidatorInfo { name: "Nagihan Akarsel", ss58: "5CrB5BWJfLNWEZAsAXDKXdJUGzFMXKvYnwRX4DVMcgBwxSdx" }, ss58: "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i",
ValidatorInfo { name: "Sait Çürükkaya (Doktor Süleyman)", ss58: "5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp" }, },
ValidatorInfo { name: "Evdile Koçer", ss58: "5GCZQNjRdHofEHPvVq4ePrfDYcjRzQ1HQ2awHMX6AawpRYuM" }, ValidatorInfo {
ValidatorInfo { name: "Mam Zeki", ss58: "5H8jTzi4Gm4rbFtXw6h5enhLhgsuhNAqR5K2itmPiz83ymWy" }, name: "Mehmet Tunç",
ValidatorInfo { name: "Kakaî Falah", ss58: "5Fs3P5tHuL9cvwPQojsheViRRAjFkMMFa32jAkDSwW9mbTfU" }, ss58: "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk",
ValidatorInfo { name: "Feryad Fazil Ömer", ss58: "5DXgq7uDXog6zcubT3wgtaYosoibjudz4w5ScPW2phLuAy3V" }, },
ValidatorInfo { name: "Mevlud Afand", ss58: "5FyFwbGLgPXun3azh6Gx83wCuUt5FTavb2WAVDYrjziVB9rN" }, ValidatorInfo {
ValidatorInfo { name: "Şêrko Fatih Şivandî", ss58: "5HEcuuypLDeJaSj6ZgH57aXhuviyeLNdw9QrCDJ8u6gsnjnL" }, name: "Nagihan Akarsel",
ValidatorInfo { name: "Ramin Hüseyin Penahi", ss58: "5EpmpTXbMXpz6ixy3WhutdzcexzPbvybNKv4eiiN1kvTnQH5" }, ss58: "5CrB5BWJfLNWEZAsAXDKXdJUGzFMXKvYnwRX4DVMcgBwxSdx",
ValidatorInfo { name: "Zanyar Moradi", ss58: "5DFsm3BBEgHmSEZkvwGKB7c7tiH2avhfuQE1SEjfMDGuczsW" }, },
ValidatorInfo { name: "Heidar Ghorbani", ss58: "5HePVUXjGSM2hVZ1YMz2V3KoX6EdQNEmmzUnUvpfGV95ofUR" }, ValidatorInfo {
ValidatorInfo { name: "Farhad Salimi", ss58: "5GP4nAcwtETTg1oAHQNvevmmhG8GEstGQeCirKEhaDTwpFgx" }, name: "Sait Çürükkaya (Doktor Süleyman)",
ValidatorInfo { name: "Vafa Azarbar", ss58: "5FYoCM3oeEGeoFY94EgXBhmABkRCabvPp72ur5bJNG3cK619" }, ss58: "5ELgySrX5ZyK7EWXjj6bAedyTCcTNWDANbiiipsT5gnpoCEp",
ValidatorInfo { name: "Dr. Aziz Mihemed", ss58: "5GspwkKF6aYzFkmAyBBQg7coSCSgDCore79fbW8uxJNAH347" }, },
ValidatorInfo { name: "Arîn Mîrkan", ss58: "5GmuX11pN2fC4Fyq1V7MuiYt3aevZcVQs3HZWKyzmap9bKfe" }, ValidatorInfo {
ValidatorInfo { name: "Ebu Leyla", ss58: "5FQptVCtM1qsxkLbQkATkw4Kio4M9LxWvM6TwgEo3QjmTXF3" }, name: "Evdile Koçer",
ValidatorInfo { name: "Rêvan Kobanê", ss58: "5E7VD2qmso1yRfyq3t9u2qhauAgtmjZTybVsCARF5Zz9bXy6" }, ss58: "5GCZQNjRdHofEHPvVq4ePrfDYcjRzQ1HQ2awHMX6AawpRYuM",
ValidatorInfo { name: "Amanj Babani", ss58: "5Ccz5W7Q21g4UPCytzHxD3VSMLJ1BbbWSkJKFwsNtYRk3HkX" }, },
ValidatorInfo { name: "Xosrow Gulan", ss58: "5D7WPmK1SAJyYDdCtgqEzGJpWXQe3Lj9FqWL8z9waLTkUNv3" }, ValidatorInfo {
name: "Mam Zeki",
ss58: "5H8jTzi4Gm4rbFtXw6h5enhLhgsuhNAqR5K2itmPiz83ymWy",
},
ValidatorInfo {
name: "Kakaî Falah",
ss58: "5Fs3P5tHuL9cvwPQojsheViRRAjFkMMFa32jAkDSwW9mbTfU",
},
ValidatorInfo {
name: "Feryad Fazil Ömer",
ss58: "5DXgq7uDXog6zcubT3wgtaYosoibjudz4w5ScPW2phLuAy3V",
},
ValidatorInfo {
name: "Mevlud Afand",
ss58: "5FyFwbGLgPXun3azh6Gx83wCuUt5FTavb2WAVDYrjziVB9rN",
},
ValidatorInfo {
name: "Şêrko Fatih Şivandî",
ss58: "5HEcuuypLDeJaSj6ZgH57aXhuviyeLNdw9QrCDJ8u6gsnjnL",
},
ValidatorInfo {
name: "Ramin Hüseyin Penahi",
ss58: "5EpmpTXbMXpz6ixy3WhutdzcexzPbvybNKv4eiiN1kvTnQH5",
},
ValidatorInfo {
name: "Zanyar Moradi",
ss58: "5DFsm3BBEgHmSEZkvwGKB7c7tiH2avhfuQE1SEjfMDGuczsW",
},
ValidatorInfo {
name: "Heidar Ghorbani",
ss58: "5HePVUXjGSM2hVZ1YMz2V3KoX6EdQNEmmzUnUvpfGV95ofUR",
},
ValidatorInfo {
name: "Farhad Salimi",
ss58: "5GP4nAcwtETTg1oAHQNvevmmhG8GEstGQeCirKEhaDTwpFgx",
},
ValidatorInfo {
name: "Vafa Azarbar",
ss58: "5FYoCM3oeEGeoFY94EgXBhmABkRCabvPp72ur5bJNG3cK619",
},
ValidatorInfo {
name: "Dr. Aziz Mihemed",
ss58: "5GspwkKF6aYzFkmAyBBQg7coSCSgDCore79fbW8uxJNAH347",
},
ValidatorInfo {
name: "Arîn Mîrkan",
ss58: "5GmuX11pN2fC4Fyq1V7MuiYt3aevZcVQs3HZWKyzmap9bKfe",
},
ValidatorInfo {
name: "Ebu Leyla",
ss58: "5FQptVCtM1qsxkLbQkATkw4Kio4M9LxWvM6TwgEo3QjmTXF3",
},
ValidatorInfo {
name: "Rêvan Kobanê",
ss58: "5E7VD2qmso1yRfyq3t9u2qhauAgtmjZTybVsCARF5Zz9bXy6",
},
ValidatorInfo {
name: "Amanj Babani",
ss58: "5Ccz5W7Q21g4UPCytzHxD3VSMLJ1BbbWSkJKFwsNtYRk3HkX",
},
ValidatorInfo {
name: "Xosrow Gulan",
ss58: "5D7WPmK1SAJyYDdCtgqEzGJpWXQe3Lj9FqWL8z9waLTkUNv3",
},
] ]
} }
@@ -207,10 +270,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let relay_url = let relay_url =
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string()); std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
let skip: usize = std::env::var("SKIP") let skip: usize =
.unwrap_or_else(|_| "0".to_string()) std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
.parse()
.unwrap_or(0);
let vals = validators(); let vals = validators();
println!("Relay RPC: {}", relay_url); println!("Relay RPC: {}", relay_url);
@@ -223,10 +284,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to relay chain // Connect to relay chain
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?; let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?;
println!( println!("Connected! specVersion: {}\n", api.runtime_version().spec_version);
"Connected! specVersion: {}\n",
api.runtime_version().spec_version
);
// Load sudo keypair // Load sudo keypair
let mnemonic_str = let mnemonic_str =
@@ -281,11 +339,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let mut tx_progress_opt = None; let mut tx_progress_opt = None;
for attempt in 0..3 { for attempt in 0..3 {
match api match api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await {
.tx()
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await
{
Ok(p) => { Ok(p) => {
tx_progress_opt = Some(p); tx_progress_opt = Some(p);
break; break;
@@ -306,10 +360,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}, },
}; };
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
let mut tx_ok = false; let mut tx_ok = false;
@@ -340,11 +391,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" WARNING: Events:"); println!(" WARNING: Events:");
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!( println!(" {}::{}", ev.pallet_name(), ev.variant_name());
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
} }
} }
} }
+6 -22
View File
@@ -74,11 +74,7 @@ async fn submit_and_watch(
tokio::time::sleep(std::time::Duration::from_secs(18)).await; tokio::time::sleep(std::time::Duration::from_secs(18)).await;
} }
let tx_progress = match api let tx_progress = match api.tx().sign_and_submit_then_watch_default(&tx, signer).await {
.tx()
.sign_and_submit_then_watch_default(&tx, signer)
.await
{
Ok(p) => p, Ok(p) => p,
Err(e) => { Err(e) => {
println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e); println!(" SUBMIT ERROR (attempt {}): {}", attempt + 1, e);
@@ -86,10 +82,7 @@ async fn submit_and_watch(
}, },
}; };
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
loop { loop {
@@ -101,11 +94,7 @@ async fn submit_and_watch(
println!(" {} SUCCESS!", label); println!(" {} SUCCESS!", label);
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!( println!(" {}::{}", ev.pallet_name(), ev.variant_name());
" {}::{}",
ev.pallet_name(),
ev.variant_name()
);
} }
} }
return Ok(true); return Ok(true);
@@ -148,10 +137,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ws = load_wallets(); let ws = load_wallets();
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let phase = args.get(1).map(|s| s.as_str()).unwrap_or("all"); let phase = args.get(1).map(|s| s.as_str()).unwrap_or("all");
let skip: usize = std::env::var("SKIP") let skip: usize =
.unwrap_or_else(|_| "0".to_string()) std::env::var("SKIP").unwrap_or_else(|_| "0".to_string()).parse().unwrap_or(0);
.parse()
.unwrap_or(0);
let rpc = std::env::var("PEOPLE_RPC").unwrap_or_else(|_| DEFAULT_PEOPLE_RPC.to_string()); let rpc = std::env::var("PEOPLE_RPC").unwrap_or_else(|_| DEFAULT_PEOPLE_RPC.to_string());
println!("=== WELATI CITIZENSHIP WORKFLOW ==="); println!("=== WELATI CITIZENSHIP WORKFLOW ===");
@@ -222,10 +209,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let tx = pezkuwi_subxt::dynamic::tx( let tx = pezkuwi_subxt::dynamic::tx(
"IdentityKyc", "IdentityKyc",
"apply_for_citizenship", "apply_for_citizenship",
vec![ vec![Value::from_bytes(&identity_hash), Value::unnamed_variant("None", vec![])],
Value::from_bytes(&identity_hash),
Value::unnamed_variant("None", vec![]),
],
); );
let ok = submit_and_watch(&api, tx, &keypair, "APPLY").await?; let ok = submit_and_watch(&api, tx, &keypair, "APPLY").await?;
+16 -59
View File
@@ -45,9 +45,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== ZAGROS: VALIDATOR DEREGISTRATION ===\n"); println!("=== ZAGROS: VALIDATOR DEREGISTRATION ===\n");
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string()); let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string());
let keep: usize = std::env::var("KEEP") let keep: usize = std::env::var("KEEP").unwrap_or_else(|_| "2".to_string()).parse()?;
.unwrap_or_else(|_| "2".to_string())
.parse()?;
let execute = std::env::var("EXECUTE").unwrap_or_default() == "1"; let execute = std::env::var("EXECUTE").unwrap_or_default() == "1";
println!("RPC: {}", url); println!("RPC: {}", url);
@@ -61,15 +59,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// QueuedKeys = Vec<(ValidatorId, Keys)> // QueuedKeys = Vec<(ValidatorId, Keys)>
// Storage key: twox128("Session") + twox128("QueuedKeys") // Storage key: twox128("Session") + twox128("QueuedKeys")
let queued_keys_key = let queued_keys_key =
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903") hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903").unwrap();
.unwrap();
let raw_data = api let raw_data = api.storage().at_latest().await?.fetch_raw(queued_keys_key).await?;
.storage()
.at_latest()
.await?
.fetch_raw(queued_keys_key)
.await?;
if raw_data.is_empty() { if raw_data.is_empty() {
println!("ERROR: QueuedKeys storage is empty!"); println!("ERROR: QueuedKeys storage is empty!");
@@ -95,33 +87,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// But we need to verify this. Let's compute expected total size: // But we need to verify this. Let's compute expected total size:
let expected_entry_size = 32 + (32 * 6 + 33); // 257 let expected_entry_size = 32 + (32 * 6 + 33); // 257
let expected_total = 1 + (count * expected_entry_size); // 1 byte compact + entries let expected_total = 1 + (count * expected_entry_size); // 1 byte compact + entries
println!( println!("Expected data size: {} bytes, actual: {} bytes", expected_total, raw_data.len());
"Expected data size: {} bytes, actual: {} bytes",
expected_total,
raw_data.len()
);
if raw_data.len() < offset + count * expected_entry_size { if raw_data.len() < offset + count * expected_entry_size {
// Try without beefy (older runtime might not have it) // Try without beefy (older runtime might not have it)
let entry_no_beefy = 32 + (32 * 6); // 224 let entry_no_beefy = 32 + (32 * 6); // 224
let expected_no_beefy = 1 + (count * entry_no_beefy); let expected_no_beefy = 1 + (count * entry_no_beefy);
println!( println!("Without beefy: expected {} bytes", expected_no_beefy);
"Without beefy: expected {} bytes",
expected_no_beefy
);
if raw_data.len() >= offset + count * entry_no_beefy { if raw_data.len() >= offset + count * entry_no_beefy {
println!("Using SessionKeys without Beefy (6 keys x 32 bytes)"); println!("Using SessionKeys without Beefy (6 keys x 32 bytes)");
extract_and_process( extract_and_process(&raw_data, offset, count, entry_no_beefy, keep, execute, &api)
&raw_data, .await?;
offset,
count,
entry_no_beefy,
keep,
execute,
&api,
)
.await?;
} else { } else {
// Auto-detect entry size // Auto-detect entry size
let remaining = raw_data.len() - offset; let remaining = raw_data.len() - offset;
@@ -130,21 +107,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
"Auto-detected entry size: {} bytes (remaining={}, count={})", "Auto-detected entry size: {} bytes (remaining={}, count={})",
entry_size, remaining, count entry_size, remaining, count
); );
extract_and_process(&raw_data, offset, count, entry_size, keep, execute, &api) extract_and_process(&raw_data, offset, count, entry_size, keep, execute, &api).await?;
.await?;
} }
} else { } else {
println!("Using SessionKeys with Beefy (6 keys x 32 + 33 beefy)"); println!("Using SessionKeys with Beefy (6 keys x 32 + 33 beefy)");
extract_and_process( extract_and_process(&raw_data, offset, count, expected_entry_size, keep, execute, &api)
&raw_data, .await?;
offset,
count,
expected_entry_size,
keep,
execute,
&api,
)
.await?;
} }
Ok(()) Ok(())
@@ -202,22 +170,16 @@ async fn extract_and_process(
vec![Value::unnamed_composite(validators_value)], vec![Value::unnamed_composite(validators_value)],
); );
let sudo_call = let sudo_call = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![deregister_call.into_value()]);
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![deregister_call.into_value()]);
println!("Submitting sudo(validatorManager.deregister_validators)...\n"); println!("Submitting sudo(validatorManager.deregister_validators)...\n");
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api let tx_progress =
.tx() api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await?;
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await?;
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
let mut success = false; let mut success = false;
@@ -237,9 +199,7 @@ async fn extract_and_process(
if ev.pallet_name() == "ValidatorManager" if ev.pallet_name() == "ValidatorManager"
&& ev.variant_name() == "ValidatorsDeregistered" && ev.variant_name() == "ValidatorsDeregistered"
{ {
println!( println!(" >>> ValidatorsDeregistered event confirmed!");
" >>> ValidatorsDeregistered event confirmed!"
);
} }
} }
} }
@@ -273,10 +233,7 @@ async fn extract_and_process(
} }
if success { if success {
println!( println!("\nSUCCESS! {} validators queued for deregistration.", to_remove.len());
"\nSUCCESS! {} validators queued for deregistration.",
to_remove.len()
);
println!("The change will take effect at current_session + 2."); println!("The change will take effect at current_session + 2.");
println!("Monitor GRANDPA authorities to confirm."); println!("Monitor GRANDPA authorities to confirm.");
} else { } else {
+17 -40
View File
@@ -26,11 +26,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Storage keys // Storage keys
let queued_keys_key = let queued_keys_key =
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903") hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903").unwrap();
.unwrap();
let validators_to_retire_key = let validators_to_retire_key =
hex::decode("084e7f70a295a190e2e33fd3f8cdfcc2b664fa73499821e43a617aa0e82b17b1") hex::decode("084e7f70a295a190e2e33fd3f8cdfcc2b664fa73499821e43a617aa0e82b17b1").unwrap();
.unwrap();
// Step 1: Check ValidatorsToRetire BEFORE // Step 1: Check ValidatorsToRetire BEFORE
println!("=== STEP 1: Check ValidatorsToRetire BEFORE deregister ==="); println!("=== STEP 1: Check ValidatorsToRetire BEFORE deregister ===");
@@ -43,20 +41,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
if retire_before.is_empty() { if retire_before.is_empty() {
println!(" ValidatorsToRetire: EMPTY (as expected)\n"); println!(" ValidatorsToRetire: EMPTY (as expected)\n");
} else { } else {
println!( println!(" ValidatorsToRetire: {} bytes (already has data!)\n", retire_before.len());
" ValidatorsToRetire: {} bytes (already has data!)\n",
retire_before.len()
);
} }
// Step 2: Get validator #5 from QueuedKeys // Step 2: Get validator #5 from QueuedKeys
println!("=== STEP 2: Get test validator from QueuedKeys ==="); println!("=== STEP 2: Get test validator from QueuedKeys ===");
let raw_data = api let raw_data = api.storage().at_latest().await?.fetch_raw(queued_keys_key).await?;
.storage()
.at_latest()
.await?
.fetch_raw(queued_keys_key)
.await?;
let count = (raw_data[0] >> 2) as usize; let count = (raw_data[0] >> 2) as usize;
let remaining = raw_data.len() - 1; let remaining = raw_data.len() - 1;
let entry_size = remaining / count; let entry_size = remaining / count;
@@ -70,10 +60,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Get validator #5 (index 4, the first one to remove) // Get validator #5 (index 4, the first one to remove)
let test_offset = 1 + 4 * entry_size; let test_offset = 1 + 4 * entry_size;
let test_validator = raw_data[test_offset..test_offset + 32].to_vec(); let test_validator = raw_data[test_offset..test_offset + 32].to_vec();
println!( println!(" Test validator (index 5): 0x{}\n", hex::encode(&test_validator));
" Test validator (index 5): 0x{}\n",
hex::encode(&test_validator)
);
// Step 3: Load sudo key and submit deregister for ONE validator // Step 3: Load sudo key and submit deregister for ONE validator
println!("=== STEP 3: Submit deregister for ONE validator ==="); println!("=== STEP 3: Submit deregister for ONE validator ===");
@@ -81,10 +68,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC environment variable required"); std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC environment variable required");
let mnemonic = Mnemonic::from_str(&mnemonic_str)?; let mnemonic = Mnemonic::from_str(&mnemonic_str)?;
let sudo_keypair = Keypair::from_phrase(&mnemonic, None)?; let sudo_keypair = Keypair::from_phrase(&mnemonic, None)?;
println!( println!(" Sudo account: {}", sudo_keypair.public_key().to_account_id());
" Sudo account: {}",
sudo_keypair.public_key().to_account_id()
);
// Try TWO different encoding approaches // Try TWO different encoding approaches
@@ -110,22 +94,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Print the encoded call data to debug // Print the encoded call data to debug
println!("\n Deregister call value: {:?}", deregister_call.call_data()); println!("\n Deregister call value: {:?}", deregister_call.call_data());
let sudo_call = let sudo_call = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![deregister_call.into_value()]);
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![deregister_call.into_value()]);
println!("\n Submitting sudo(validatorManager.deregister_validators([1 validator]))..."); println!("\n Submitting sudo(validatorManager.deregister_validators([1 validator]))...");
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api let tx_progress =
.tx() api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await?;
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await?;
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
let mut success = false; let mut success = false;
@@ -146,11 +124,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
&& ev.variant_name() == "ValidatorsDeregistered" && ev.variant_name() == "ValidatorsDeregistered"
{ {
// Try to decode the event data // Try to decode the event data
println!( println!(" >>> ValidatorsDeregistered event!");
" >>> ValidatorsDeregistered event!"
);
let bytes = ev.field_bytes(); let bytes = ev.field_bytes();
println!(" >>> Event field bytes ({} bytes): 0x{}", bytes.len(), hex::encode(&bytes[..std::cmp::min(bytes.len(), 128)])); println!(
" >>> Event field bytes ({} bytes): 0x{}",
bytes.len(),
hex::encode(&bytes[..std::cmp::min(bytes.len(), 128)])
);
} }
} }
} }
@@ -204,10 +184,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" ValidatorsToRetire: EMPTY !!! (deregister didn't populate storage!)"); println!(" ValidatorsToRetire: EMPTY !!! (deregister didn't populate storage!)");
println!(" THIS IS THE BUG!"); println!(" THIS IS THE BUG!");
} else { } else {
println!( println!(" ValidatorsToRetire: {} bytes", retire_after.len());
" ValidatorsToRetire: {} bytes",
retire_after.len()
);
println!(" Raw hex: 0x{}", hex::encode(&retire_after)); println!(" Raw hex: 0x{}", hex::encode(&retire_after));
// Decode it // Decode it
@@ -32,8 +32,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let force_era_call = let force_era_call =
pezkuwi_subxt::dynamic::tx("Staking", "force_new_era", Vec::<Value>::new()); pezkuwi_subxt::dynamic::tx("Staking", "force_new_era", Vec::<Value>::new());
let sudo_tx = let sudo_tx = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![force_era_call.into_value()]);
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![force_era_call.into_value()]);
let tx_hash = api.tx().sign_and_submit_default(&sudo_tx, &sudo_keypair).await?; let tx_hash = api.tx().sign_and_submit_default(&sudo_tx, &sudo_keypair).await?;
println!("Submitted! TX hash: 0x{}", hex::encode(tx_hash.as_ref())); println!("Submitted! TX hash: 0x{}", hex::encode(tx_hash.as_ref()));
@@ -21,9 +21,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== ZAGROS VALIDATOR COUNT REDUCTION ===\n"); println!("=== ZAGROS VALIDATOR COUNT REDUCTION ===\n");
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string()); let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string());
let new_count: u32 = std::env::var("VALIDATOR_COUNT") let new_count: u32 =
.unwrap_or_else(|_| "4".to_string()) std::env::var("VALIDATOR_COUNT").unwrap_or_else(|_| "4".to_string()).parse()?;
.parse()?;
println!("RPC: {}", url); println!("RPC: {}", url);
println!("Target validator count: {}", new_count); println!("Target validator count: {}", new_count);
@@ -43,12 +42,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Step 1: sudo(staking.setValidatorCount(new_count)) // Step 1: sudo(staking.setValidatorCount(new_count))
println!("[1/2] Setting validator count to {}...", new_count); println!("[1/2] Setting validator count to {}...", new_count);
let set_count_call = pezkuwi_subxt::dynamic::tx("Staking", "set_validator_count", vec![ let set_count_call = pezkuwi_subxt::dynamic::tx(
Value::u128(new_count as u128), "Staking",
]); "set_validator_count",
vec![Value::u128(new_count as u128)],
);
let sudo_tx_1 = let sudo_tx_1 = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![set_count_call.into_value()]);
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![set_count_call.into_value()]);
// Use sign_and_submit_default (does NOT wait for finalization) // Use sign_and_submit_default (does NOT wait for finalization)
let tx_hash_1 = api.tx().sign_and_submit_default(&sudo_tx_1, &sudo_keypair).await?; let tx_hash_1 = api.tx().sign_and_submit_default(&sudo_tx_1, &sudo_keypair).await?;
@@ -64,8 +64,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let force_era_call = let force_era_call =
pezkuwi_subxt::dynamic::tx("Staking", "force_new_era", Vec::<Value>::new()); pezkuwi_subxt::dynamic::tx("Staking", "force_new_era", Vec::<Value>::new());
let sudo_tx_2 = let sudo_tx_2 = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![force_era_call.into_value()]);
pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![force_era_call.into_value()]);
let tx_hash_2 = api.tx().sign_and_submit_default(&sudo_tx_2, &sudo_keypair).await?; let tx_hash_2 = api.tx().sign_and_submit_default(&sudo_tx_2, &sudo_keypair).await?;
println!(" Submitted! TX hash: 0x{}", hex::encode(tx_hash_2.as_ref())); println!(" Submitted! TX hash: 0x{}", hex::encode(tx_hash_2.as_ref()));
+14 -51
View File
@@ -30,24 +30,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== ZAGROS: SET ValidatorsToRetire via setStorage ===\n"); println!("=== ZAGROS: SET ValidatorsToRetire via setStorage ===\n");
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string()); let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string());
let keep: usize = std::env::var("KEEP") let keep: usize = std::env::var("KEEP").unwrap_or_else(|_| "4".to_string()).parse()?;
.unwrap_or_else(|_| "4".to_string())
.parse()?;
println!("RPC: {}", url); println!("RPC: {}", url);
println!("Keep: {} validators\n", keep); println!("Keep: {} validators\n", keep);
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?; let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?;
println!( println!("Connected! specVersion: {}\n", api.runtime_version().spec_version);
"Connected! specVersion: {}\n",
api.runtime_version().spec_version
);
// Verify genesis hash (Zagros = 0xbb4a61ab...) // Verify genesis hash (Zagros = 0xbb4a61ab...)
let genesis = format!( let genesis = format!("0x{}", hex::encode(api.genesis_hash().as_ref()));
"0x{}",
hex::encode(api.genesis_hash().as_ref())
);
println!("Genesis: {}", genesis); println!("Genesis: {}", genesis);
if !genesis.starts_with("0xbb4a61ab") { if !genesis.starts_with("0xbb4a61ab") {
println!("ERROR: This is NOT Zagros! Aborting."); println!("ERROR: This is NOT Zagros! Aborting.");
@@ -57,15 +49,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read QueuedKeys to get all validator AccountIds // Read QueuedKeys to get all validator AccountIds
let queued_keys_key = let queued_keys_key =
hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903") hex::decode("cec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903").unwrap();
.unwrap();
let raw_data = api let raw_data = api.storage().at_latest().await?.fetch_raw(queued_keys_key).await?;
.storage()
.at_latest()
.await?
.fetch_raw(queued_keys_key)
.await?;
let count = (raw_data[0] >> 2) as usize; let count = (raw_data[0] >> 2) as usize;
let remaining = raw_data.len() - 1; let remaining = raw_data.len() - 1;
@@ -101,10 +87,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
for v in to_remove { for v in to_remove {
encoded_retire.extend_from_slice(v); encoded_retire.extend_from_slice(v);
} }
println!( println!("\nSCALE-encoded ValidatorsToRetire: {} bytes", encoded_retire.len());
"\nSCALE-encoded ValidatorsToRetire: {} bytes",
encoded_retire.len()
);
println!( println!(
" compact_length: 0x{} (count={})", " compact_length: 0x{} (count={})",
hex::encode(&encode_compact(to_remove.len())), hex::encode(&encode_compact(to_remove.len())),
@@ -113,13 +96,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Storage key for ValidatorsToRetire // Storage key for ValidatorsToRetire
let validators_to_retire_key = let validators_to_retire_key =
hex::decode("084e7f70a295a190e2e33fd3f8cdfcc2b664fa73499821e43a617aa0e82b17b1") hex::decode("084e7f70a295a190e2e33fd3f8cdfcc2b664fa73499821e43a617aa0e82b17b1").unwrap();
.unwrap();
println!( println!("\nStorage key: 0x{}", hex::encode(&validators_to_retire_key));
"\nStorage key: 0x{}",
hex::encode(&validators_to_retire_key)
);
println!( println!(
"Storage value: 0x{}...({} bytes)", "Storage value: 0x{}...({} bytes)",
hex::encode(&encoded_retire[..std::cmp::min(encoded_retire.len(), 40)]), hex::encode(&encoded_retire[..std::cmp::min(encoded_retire.len(), 40)]),
@@ -131,10 +110,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC environment variable required"); std::env::var("SUDO_MNEMONIC").expect("SUDO_MNEMONIC environment variable required");
let mnemonic = Mnemonic::from_str(&mnemonic_str)?; let mnemonic = Mnemonic::from_str(&mnemonic_str)?;
let sudo_keypair = Keypair::from_phrase(&mnemonic, None)?; let sudo_keypair = Keypair::from_phrase(&mnemonic, None)?;
println!( println!("\nSudo account: {}", sudo_keypair.public_key().to_account_id());
"\nSudo account: {}",
sudo_keypair.public_key().to_account_id()
);
// Build sudo(system.setStorage(items)) // Build sudo(system.setStorage(items))
let set_storage_tx = pezkuwi_subxt::dynamic::tx( let set_storage_tx = pezkuwi_subxt::dynamic::tx(
@@ -152,15 +128,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
let tx_progress = api let tx_progress =
.tx() api.tx().sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair).await?;
.sign_and_submit_then_watch_default(&sudo_call, &sudo_keypair)
.await?;
println!( println!(" TX: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
let mut success = false; let mut success = false;
@@ -230,19 +201,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
{ {
Ok(data) => { Ok(data) => {
let stored_count = (data[0] >> 2) as usize; let stored_count = (data[0] >> 2) as usize;
println!( println!("ValidatorsToRetire: {} entries ({} bytes)", stored_count, data.len());
"ValidatorsToRetire: {} entries ({} bytes)",
stored_count,
data.len()
);
if stored_count == to_remove.len() { if stored_count == to_remove.len() {
println!("COUNT MATCHES! Storage write successful."); println!("COUNT MATCHES! Storage write successful.");
} else { } else {
println!( println!("COUNT MISMATCH! Expected {}, got {}", to_remove.len(), stored_count);
"COUNT MISMATCH! Expected {}, got {}",
to_remove.len(),
stored_count
);
} }
// Show first few // Show first few
let mut off = 1; let mut off = 1;
+32 -37
View File
@@ -30,13 +30,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let inner_call = match call_name.as_str() { let inner_call = match call_name.as_str() {
"setValidatorCount" => { "setValidatorCount" => {
let count: u32 = std::env::var("COUNT") let count: u32 = std::env::var("COUNT").unwrap_or_else(|_| "4".to_string()).parse()?;
.unwrap_or_else(|_| "4".to_string())
.parse()?;
println!("Setting validator count to {}", count); println!("Setting validator count to {}", count);
pezkuwi_subxt::dynamic::tx("Staking", "set_validator_count", vec![Value::u128( pezkuwi_subxt::dynamic::tx(
count as u128, "Staking",
)]) "set_validator_count",
vec![Value::u128(count as u128)],
)
}, },
"forceNewEra" => { "forceNewEra" => {
println!("Forcing new era"); println!("Forcing new era");
@@ -48,9 +48,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}, },
"setStakingConfigs" => { "setStakingConfigs" => {
// Set min_validator_count to 1 via set_staking_configs // Set min_validator_count to 1 via set_staking_configs
let min_count: u32 = std::env::var("MIN_COUNT") let min_count: u32 =
.unwrap_or_else(|_| "1".to_string()) std::env::var("MIN_COUNT").unwrap_or_else(|_| "1".to_string()).parse().unwrap();
.parse().unwrap();
println!("Setting staking configs: min_nominator_bond=Noop, min_validator_bond=Noop, max_nominator_count=Noop, max_validator_count=Noop, chill_threshold=Noop, min_commission=Noop"); println!("Setting staking configs: min_nominator_bond=Noop, min_validator_bond=Noop, max_nominator_count=Noop, max_validator_count=Noop, chill_threshold=Noop, min_commission=Noop");
// Actually we need to set min_validator_count directly // Actually we need to set min_validator_count directly
// Let's use a different approach - call set_staking_configs with all Noop except what we need // Let's use a different approach - call set_staking_configs with all Noop except what we need
@@ -61,9 +60,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::process::exit(1); std::process::exit(1);
}, },
"setMinValidatorCount" => { "setMinValidatorCount" => {
let min_count: u32 = std::env::var("MIN_COUNT") let min_count: u32 =
.unwrap_or_else(|_| "1".to_string()) std::env::var("MIN_COUNT").unwrap_or_else(|_| "1".to_string()).parse().unwrap();
.parse().unwrap();
println!("Setting minimum validator count to {}", min_count); println!("Setting minimum validator count to {}", min_count);
// Staking::set_staking_configs sets all params at once // Staking::set_staking_configs sets all params at once
// Instead we should check if there's a direct setter // Instead we should check if there's a direct setter
@@ -72,22 +70,24 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// ConfigOp: Noop=unnamed_variant("Noop",[]), Set=unnamed_variant("Set",[Value::u128(x)]) // ConfigOp: Noop=unnamed_variant("Noop",[]), Set=unnamed_variant("Set",[Value::u128(x)])
let noop = Value::unnamed_variant("Noop", Vec::<Value>::new()); let noop = Value::unnamed_variant("Noop", Vec::<Value>::new());
let set_val = Value::unnamed_variant("Set", vec![Value::u128(min_count as u128)]); let set_val = Value::unnamed_variant("Set", vec![Value::u128(min_count as u128)]);
pezkuwi_subxt::dynamic::tx("Staking", "set_staking_configs", vec![ pezkuwi_subxt::dynamic::tx(
noop.clone(), // min_nominator_bond "Staking",
noop.clone(), // min_validator_bond "set_staking_configs",
noop.clone(), // max_nominator_count vec![
noop.clone(), // max_validator_count noop.clone(), // min_nominator_bond
noop.clone(), // chill_threshold noop.clone(), // min_validator_bond
noop.clone(), // min_commission noop.clone(), // max_nominator_count
noop.clone(), // max_staked_rewards (if exists) noop.clone(), // max_validator_count
]) noop.clone(), // chill_threshold
noop.clone(), // min_commission
noop.clone(), // max_staked_rewards (if exists)
],
)
}, },
"setStorage" => { "setStorage" => {
// Set arbitrary storage via sudo(system.setStorage) // Set arbitrary storage via sudo(system.setStorage)
let key_hex = let key_hex = std::env::var("STORAGE_KEY").expect("STORAGE_KEY env var required");
std::env::var("STORAGE_KEY").expect("STORAGE_KEY env var required"); let value_hex = std::env::var("STORAGE_VALUE").expect("STORAGE_VALUE env var required");
let value_hex =
std::env::var("STORAGE_VALUE").expect("STORAGE_VALUE env var required");
println!("Setting storage key={} value={}", key_hex, value_hex); println!("Setting storage key={} value={}", key_hex, value_hex);
let key_bytes = hex::decode(key_hex.trim_start_matches("0x")).unwrap(); let key_bytes = hex::decode(key_hex.trim_start_matches("0x")).unwrap();
@@ -98,9 +98,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Value::from_bytes(&key_bytes), Value::from_bytes(&key_bytes),
Value::from_bytes(&value_bytes), Value::from_bytes(&value_bytes),
]); ]);
pezkuwi_subxt::dynamic::tx("System", "set_storage", vec![ pezkuwi_subxt::dynamic::tx(
Value::unnamed_composite([item]), "System",
]) "set_storage",
vec![Value::unnamed_composite([item])],
)
}, },
_ => { _ => {
eprintln!("Unknown call: {}", call_name); eprintln!("Unknown call: {}", call_name);
@@ -113,10 +115,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\nSubmitting..."); println!("\nSubmitting...");
// Use sign_and_submit_then_watch to see TX lifecycle // Use sign_and_submit_then_watch to see TX lifecycle
let tx_progress = api let tx_progress = api.tx().sign_and_submit_then_watch_default(&sudo_tx, &sudo_keypair).await?;
.tx()
.sign_and_submit_then_watch_default(&sudo_tx, &sudo_keypair)
.await?;
println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref())); println!("TX hash: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
println!("Watching TX status (Ctrl+C to abort)..."); println!("Watching TX status (Ctrl+C to abort)...");
@@ -137,11 +136,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!(" TX SUCCESS!"); println!(" TX SUCCESS!");
for event in events.iter() { for event in events.iter() {
if let Ok(ev) = event { if let Ok(ev) = event {
println!( println!(" Event: {}::{}", ev.pallet_name(), ev.variant_name());
" Event: {}::{}",
ev.pallet_name(),
ev.variant_name()
);
} }
} }
}, },
+32 -42
View File
@@ -22,9 +22,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string()); let url = std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9948".to_string());
let wasm_path = std::env::var("WASM_FILE").expect("WASM_FILE environment variable required"); let wasm_path = std::env::var("WASM_FILE").expect("WASM_FILE environment variable required");
let new_validator_count: u32 = std::env::var("VALIDATOR_COUNT") let new_validator_count: u32 =
.unwrap_or_else(|_| "2".to_string()) std::env::var("VALIDATOR_COUNT").unwrap_or_else(|_| "2".to_string()).parse()?;
.parse()?;
println!("RPC: {}", url); println!("RPC: {}", url);
println!("WASM: {}", wasm_path); println!("WASM: {}", wasm_path);
@@ -32,7 +31,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load WASM // Load WASM
let wasm_data = std::fs::read(&wasm_path)?; let wasm_data = std::fs::read(&wasm_path)?;
println!("WASM size: {} bytes ({:.2} MB)", wasm_data.len(), wasm_data.len() as f64 / 1_048_576.0); println!(
"WASM size: {} bytes ({:.2} MB)",
wasm_data.len(),
wasm_data.len() as f64 / 1_048_576.0
);
// Connect // Connect
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?; let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&url).await?;
@@ -58,13 +61,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
vec![Value::from_bytes(&wasm_data)], vec![Value::from_bytes(&wasm_data)],
); );
let sudo_upgrade = pezkuwi_subxt::dynamic::tx("Sudo", "sudo_unchecked_weight", vec![ let sudo_upgrade = pezkuwi_subxt::dynamic::tx(
set_code.into_value(), "Sudo",
Value::named_composite([ "sudo_unchecked_weight",
("ref_time", Value::u128(1u128)), vec![
("proof_size", Value::u128(1u128)), set_code.into_value(),
]), Value::named_composite([
]); ("ref_time", Value::u128(1u128)),
("proof_size", Value::u128(1u128)),
]),
],
);
use pezkuwi_subxt::tx::TxStatus; use pezkuwi_subxt::tx::TxStatus;
@@ -73,10 +80,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.sign_and_submit_then_watch_default(&sudo_upgrade, &sudo_keypair) .sign_and_submit_then_watch_default(&sudo_upgrade, &sudo_keypair)
.await?; .await?;
println!( println!(" TX submitted: 0x{}", hex::encode(tx_progress.extrinsic_hash().as_ref()));
" TX submitted: 0x{}",
hex::encode(tx_progress.extrinsic_hash().as_ref())
);
let mut progress = tx_progress; let mut progress = tx_progress;
let mut upgrade_ok = false; let mut upgrade_ok = false;
@@ -152,11 +156,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Staking::ForceEra: 0x5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3 // Staking::ForceEra: 0x5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3
let validator_count_key = let validator_count_key =
hex::decode("5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1") hex::decode("5f3e4907f716ac89b6347d15ececedca138e71612491192d68deab7e6f563fe1").unwrap();
.unwrap();
let force_era_key = let force_era_key =
hex::decode("5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3") hex::decode("5f3e4907f716ac89b6347d15ececedcaf7dad0317324aecae8744b87fc95f2f3").unwrap();
.unwrap();
// ValidatorCount is u32 LE // ValidatorCount is u32 LE
let validator_count_value = new_validator_count.to_le_bytes().to_vec(); let validator_count_value = new_validator_count.to_le_bytes().to_vec();
@@ -166,8 +168,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Setting ValidatorCount = {}", new_validator_count); println!("Setting ValidatorCount = {}", new_validator_count);
println!("Setting ForceEra = ForceNew (0x01)"); println!("Setting ForceEra = ForceNew (0x01)");
let set_storage_tx = pezkuwi_subxt::dynamic::tx("System", "set_storage", vec![ let set_storage_tx = pezkuwi_subxt::dynamic::tx(
Value::unnamed_composite(vec![ "System",
"set_storage",
vec![Value::unnamed_composite(vec![
Value::unnamed_composite(vec![ Value::unnamed_composite(vec![
Value::from_bytes(&validator_count_key), Value::from_bytes(&validator_count_key),
Value::from_bytes(&validator_count_value), Value::from_bytes(&validator_count_value),
@@ -176,22 +180,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Value::from_bytes(&force_era_key), Value::from_bytes(&force_era_key),
Value::from_bytes(&force_era_value), Value::from_bytes(&force_era_value),
]), ]),
]), ])],
]); );
let sudo_storage = pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![ let sudo_storage =
set_storage_tx.into_value(), pezkuwi_subxt::dynamic::tx("Sudo", "sudo", vec![set_storage_tx.into_value()]);
]);
let tx_progress2 = api2 let tx_progress2 = api2
.tx() .tx()
.sign_and_submit_then_watch_default(&sudo_storage, &sudo_keypair) .sign_and_submit_then_watch_default(&sudo_storage, &sudo_keypair)
.await?; .await?;
println!( println!(" TX submitted: 0x{}", hex::encode(tx_progress2.extrinsic_hash().as_ref()));
" TX submitted: 0x{}",
hex::encode(tx_progress2.extrinsic_hash().as_ref())
);
let mut progress2 = tx_progress2; let mut progress2 = tx_progress2;
let mut storage_ok = false; let mut storage_ok = false;
@@ -256,23 +256,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("specVersion: {}", rv3.spec_version); println!("specVersion: {}", rv3.spec_version);
// Read back storage to verify // Read back storage to verify
let vc_bytes = api3 let vc_bytes = api3.storage().at_latest().await?.fetch_raw(validator_count_key).await?;
.storage()
.at_latest()
.await?
.fetch_raw(validator_count_key)
.await?;
if vc_bytes.len() >= 4 { if vc_bytes.len() >= 4 {
let vc = u32::from_le_bytes([vc_bytes[0], vc_bytes[1], vc_bytes[2], vc_bytes[3]]); let vc = u32::from_le_bytes([vc_bytes[0], vc_bytes[1], vc_bytes[2], vc_bytes[3]]);
println!("ValidatorCount: {}", vc); println!("ValidatorCount: {}", vc);
} }
let fe_bytes = api3 let fe_bytes = api3.storage().at_latest().await?.fetch_raw(force_era_key).await?;
.storage()
.at_latest()
.await?
.fetch_raw(force_era_key)
.await?;
if !fe_bytes.is_empty() { if !fe_bytes.is_empty() {
let fe_name = match fe_bytes[0] { let fe_name = match fe_bytes[0] {
0x00 => "NotForcing", 0x00 => "NotForcing",