From 1496880641a7be7ff471c159fceb000aba2b4d97 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Sun, 30 Aug 2026 01:37:40 +0800 Subject: [PATCH 1/7] feat(multisig): resubmit the proposal's inner call on execute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regenerates the metadata and subxt bindings against the runtime from chain PR #675 and passes the proposal's stored call to `multisig.execute`, so the signer signs the call that dispatches instead of an opaque proposal id. Cold wallets get this for free: `submit_transaction` already routes them through `sign_and_submit_cold`, and the payload it builds now carries the inner call. Unlike `approve`, execute takes a `Box` — inline, no length prefix — so the stored bytes are decoded back into a call rather than passed through. `decode_proposal_call` rejects bytes this build cannot decode instead of submitting a call the chain would reject, and `handle_approve` now shares the proposal fetch with it. Codegen derives codec's Decode/Encode for the call surface, which that decode needs. The regenerated metadata also trims the runtime surface: - pallet-recovery is gone: the `recovery` command, its exercise phase, its example scripts and its README section go with it. - Treasury `set_treasury_portion` and the `TreasuryPortion` storage item are gone, so `tech-referenda submit-treasury-portion` goes and `treasury info` drops the portion line. The governance exercise re-sets the treasury account to its current value instead, so it still enacts a real root call. - Balances `force_*`/`upgrade_accounts` and every Utility call but `batch_all` are gone. The utility phase now covers both halves of `batch_all`: every item applies on success, none apply when one fails. - `ReversibleTransfers::GuardianIndex` is gone. `fetch_entrusted_accounts` replaces it by iterating `HighSecurityAccounts` and keeping the entries naming the guardian; `high-security` and `wallet list` now share it. Tests: the stored bytes round-trip through decode/encode; undecodable and trailing bytes are rejected; execute is asserted to encode its inner call inline; and the cold-signing payload is asserted to carry the executed call, so the hardware flow shows it. --- README.md | 23 +- regenerate_metadata.sh | 8 +- scripts/high_security_example.sh | 16 - scripts/recovery_examples.sh | 48 - src/chain/quantus_subxt.rs | 7841 ++++++++-------------- src/cli/cold_signing.rs | 36 + src/cli/exercise/mod.rs | 13 +- src/cli/exercise/scenarios/balances.rs | 10 - src/cli/exercise/scenarios/fuzz.rs | 2 +- src/cli/exercise/scenarios/governance.rs | 13 +- src/cli/exercise/scenarios/mod.rs | 1 - src/cli/exercise/scenarios/multisig.rs | 7 +- src/cli/exercise/scenarios/reads.rs | 9 +- src/cli/exercise/scenarios/recovery.rs | 206 - src/cli/exercise/scenarios/reversible.rs | 4 +- src/cli/exercise/scenarios/utility.rs | 147 +- src/cli/exercise/scenarios/vesting.rs | 10 +- src/cli/high_security.rs | 36 +- src/cli/mod.rs | 7 - src/cli/multisig.rs | 122 +- src/cli/recovery.rs | 573 -- src/cli/tech_referenda.rs | 116 - src/cli/treasury.rs | 9 +- src/cli/wallet.rs | 64 +- src/quantus_metadata.scale | Bin 122987 -> 112719 bytes 25 files changed, 3014 insertions(+), 6307 deletions(-) delete mode 100644 scripts/recovery_examples.sh delete mode 100644 src/cli/exercise/scenarios/recovery.rs delete mode 100644 src/cli/recovery.rs diff --git a/README.md b/README.md index 5ffa002..b17699b 100644 --- a/README.md +++ b/README.md @@ -540,23 +540,6 @@ quantus high-security entrusted --from alice --- -### Account Recovery - -Social recovery using trusted friends. - -```bash -# Initiate recovery -quantus recovery initiate --rescuer bob --lost alice - -# Friend vouches -quantus recovery vouch --friend charlie --lost alice --rescuer bob - -# Claim after threshold met -quantus recovery claim --rescuer bob --lost alice -``` - ---- - ### Treasury Treasury is the account that receives a configurable portion of mining rewards. No special spend/proposal flow — just view its state. @@ -677,7 +660,7 @@ quantus call \ ### Chain Exercise Suite `quantus exercise` runs a live-node smoke/fuzz suite against a node — reads, balances, -utility, reversible transfers, multisig, recovery, preimage, governance, vesting, negative +utility, reversible transfers, multisig, preimage, governance, vesting, negative cases, a seeded fuzz loop, and wormhole round-trips. It derives a handful of ephemeral accounts, funds them from a **root account**, drives each pallet, and verifies on-chain state as it goes. Intended for CI and post-upgrade validation. @@ -736,10 +719,10 @@ actually spent — and fails if the cap was exceeded. It is a ceiling, not an allocation. Ephemeral accounts are funded with what the chain's own deposits and fees require, not with a share of the cap, and the phases that fund dedicated -accounts — `recovery` and `wormhole` — sweep them back into the root account when they are +accounts — `wormhole` — sweep them back into the root account when they are done, so their funding is borrowed rather than spent. Discretionary test transfers are scaled down by a fixed factor on top of that; chain-imposed amounts (existential deposit, multisig, -recovery, vesting and governance deposits) are read from the chain and never scaled. +vesting and governance deposits) are read from the chain and never scaled. > **Notes:** > - `governance` submits two referenda whose chain-fixed deposits stay locked for the whole diff --git a/regenerate_metadata.sh b/regenerate_metadata.sh index 69db0a7..95161ea 100755 --- a/regenerate_metadata.sh +++ b/regenerate_metadata.sh @@ -30,7 +30,13 @@ echo "Updating metadata file at src/quantus_metadata.scale..." subxt metadata --url "$NODE_URL" > src/quantus_metadata.scale echo "Generating SubXT types to src/chain/quantus_subxt.rs..." -subxt codegen --url "$NODE_URL" > src/chain/quantus_subxt.rs +# `multisig.execute` carries a RuntimeCall, and the CLI decodes the proposal's stored +# bytes back into one and re-encodes it, so the call surface needs codec's Decode and +# Encode alongside DecodeAsType/EncodeAsType. +subxt codegen --url "$NODE_URL" \ + --derive-for-type quantus_runtime::RuntimeCall=codec::Decode,recursive \ + --derive-for-type quantus_runtime::RuntimeCall=codec::Encode,recursive \ + > src/chain/quantus_subxt.rs echo "Formatting generated code..." # Generated SubXT code may require nightly rustfmt. diff --git a/scripts/high_security_example.sh b/scripts/high_security_example.sh index 9478328..f199c5a 100644 --- a/scripts/high_security_example.sh +++ b/scripts/high_security_example.sh @@ -3,7 +3,6 @@ # High Security Example Script # This script demonstrates the high security features of the Quantus blockchain. # It sets up a guardian for an account and demonstrates the reversible transfer functionality. -# It also demonstrates the recovery pallet functionality. # set this to your binary alias quantus="./target/release/quantus --node-url ws://127.0.0.1:9944" @@ -39,18 +38,3 @@ quantus reversible cancel --tx-id 0xb8ee1f940e13fbc171481d1b06967760bf1d39f06dbc quantus balance --address crystal_alice quantus balance --address crystal_bob quantus balance --address crystal_charlie - -# activate the recovery first vouch then claim. -ququantus recovery initiate --rescuer crystal_charlie --lost crystal_alice -quantus recovery active --rescuer crystal_charlie --lost crystal_alice -quantus recovery vouch --rescuer crystal_charlie --lost crystal_alice --friend crystal_charlie -quantus recovery claim --rescuer crystal_charlie --lost crystal_alice -quantus recovery proxy-of --rescuer crystal_charlie - -# Charlie pulls all money from Alice's account -quantus recovery recover-all --rescuer crystal_charlie --lost crystal_alice --dest crystal_charlie - -# Check balances of Alice, Bob, and Charlie -quantus balance --address crystal_alice -quantus balance --address crystal_bob -quantus balance --address crystal_charlie \ No newline at end of file diff --git a/scripts/recovery_examples.sh b/scripts/recovery_examples.sh deleted file mode 100644 index 89f9006..0000000 --- a/scripts/recovery_examples.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -# Recovery pallet is pretty intricate, this script contains most all the functions for high security -# and recovery. - -# Set up dev accounts before using this script -# quantus developer create-test-wallets - -echo "# Complete High Security + Recovery Flow Commands - -## 1. Setup High Security (Alice with Bob as Interceptor) -quantus high-security set --from crystal_alice --interceptor crystal_bob --delay-seconds 3600 - -## 2. Check High Security Status -quantus high-security status --account crystal_alice - -## 3. Check Alice's Recovery Configuration -quantus recovery config --account crystal_alice - -## 4. Bob Initiates Recovery for Alice -quantus recovery initiate --rescuer crystal_bob --lost crystal_alice - -## 5. Bob Vouches for His Own Recovery Attempt -quantus recovery vouch --friend crystal_bob --lost crystal_alice --rescuer crystal_bob - -## 6. Bob Claims Recovery (Proxy Setup) -quantus recovery claim --rescuer crystal_bob --lost crystal_alice - -## 7. Verify Bob's Proxy Status -quantus recovery proxy-of --rescuer crystal_bob - -## 8. Send Funds to Alice for Testing -quantus send --from crystal_bob --to crystal_alice --amount 100 - -## 9. Recover Specific Amount (10 QUAN) -quantus recovery recover-amount --rescuer crystal_bob --lost crystal_alice --dest crystal_charlie --amount-quan 10 - -## 10. Recover All Funds -quantus recovery recover-all --rescuer crystal_bob --lost crystal_alice --dest crystal_charlie - -## 11. Check Balances Throughout Process -quantus balance --address crystal_alice -quantus balance --address crystal_bob -quantus balance --address crystal_charlie - -## 12. Query Recovery Status -quantus recovery active --lost crystal_alice --rescuer crystal_bob -quantus recovery proxy-of --rescuer crystal_bob" \ No newline at end of file diff --git a/src/chain/quantus_subxt.rs b/src/chain/quantus_subxt.rs index dbbc429..746e40c 100644 --- a/src/chain/quantus_subxt.rs +++ b/src/chain/quantus_subxt.rs @@ -6,7 +6,7 @@ pub mod api { mod root_mod { pub use super::*; } - pub static PALLETS: [&str; 18usize] = [ + pub static PALLETS: [&str; 17usize] = [ "System", "Timestamp", "Balances", @@ -20,7 +20,6 @@ pub mod api { "TechCollective", "TechReferenda", "TreasuryPallet", - "Recovery", "Multisig", "Wormhole", "ZkTree", @@ -193,7 +192,7 @@ pub mod api { pub struct Version {} pub mod execute_block { use super::runtime_types; - pub type Block = runtime_types :: sp_runtime :: generic :: block :: LazyBlock < runtime_types :: qp_header :: Header < :: core :: primitive :: u32 > , :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > > ; + pub type Block = runtime_types :: sp_runtime :: generic :: block :: LazyBlock < runtime_types :: qp_header :: Header < :: core :: primitive :: u32 > , :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: frame_system :: extensions :: weight_reclaim :: WeightReclaim ,) > > ; pub mod output { use super::runtime_types; pub type Output = (); @@ -462,7 +461,7 @@ pub mod api { use super::runtime_types; pub mod apply_extrinsic { use super::runtime_types; - pub type Extrinsic = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > ; + pub type Extrinsic = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: frame_system :: extensions :: weight_reclaim :: WeightReclaim ,) > ; pub mod output { use super::runtime_types; pub type Output = :: core :: result :: Result < :: core :: result :: Result < () , runtime_types :: sp_runtime :: DispatchError > , runtime_types :: sp_runtime :: transaction_validity :: TransactionValidityError > ; @@ -506,7 +505,7 @@ pub mod api { pub type Inherent = runtime_types::sp_inherents::InherentData; pub mod output { use super::runtime_types; - pub type Output = :: subxt :: ext :: subxt_core :: alloc :: vec :: Vec < :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > > ; + pub type Output = :: subxt :: ext :: subxt_core :: alloc :: vec :: Vec < :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: frame_system :: extensions :: weight_reclaim :: WeightReclaim ,) > > ; } } #[derive( @@ -525,7 +524,7 @@ pub mod api { } pub mod check_inherents { use super::runtime_types; - pub type Block = runtime_types :: sp_runtime :: generic :: block :: LazyBlock < runtime_types :: qp_header :: Header < :: core :: primitive :: u32 > , :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > > ; + pub type Block = runtime_types :: sp_runtime :: generic :: block :: LazyBlock < runtime_types :: qp_header :: Header < :: core :: primitive :: u32 > , :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: frame_system :: extensions :: weight_reclaim :: WeightReclaim ,) > > ; pub type Data = runtime_types::sp_inherents::InherentData; pub mod output { use super::runtime_types; @@ -591,7 +590,7 @@ pub mod api { use super::runtime_types; pub type Source = runtime_types::sp_runtime::transaction_validity::TransactionSource; - pub type Tx = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > ; + pub type Tx = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: frame_system :: extensions :: weight_reclaim :: WeightReclaim ,) > ; pub type BlockHash = ::subxt::ext::subxt_core::utils::H256; pub mod output { use super::runtime_types; @@ -1447,7 +1446,7 @@ pub mod api { use super::runtime_types; pub mod query_info { use super::runtime_types; - pub type Uxt = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > ; + pub type Uxt = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: frame_system :: extensions :: weight_reclaim :: WeightReclaim ,) > ; pub type Len = ::core::primitive::u32; pub mod output { use super::runtime_types; @@ -1475,7 +1474,7 @@ pub mod api { } pub mod query_fee_details { use super::runtime_types; - pub type Uxt = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension ,) > ; + pub type Uxt = :: subxt :: ext :: subxt_core :: utils :: UncheckedExtrinsic < :: subxt :: ext :: subxt_core :: utils :: MultiAddress < :: subxt :: ext :: subxt_core :: utils :: AccountId32 , () > , runtime_types :: quantus_runtime :: RuntimeCall , runtime_types :: qp_dilithium_crypto :: types :: DilithiumSignatureScheme , (runtime_types :: frame_system :: extensions :: check_non_zero_sender :: CheckNonZeroSender , runtime_types :: frame_system :: extensions :: check_spec_version :: CheckSpecVersion , runtime_types :: frame_system :: extensions :: check_tx_version :: CheckTxVersion , runtime_types :: frame_system :: extensions :: check_genesis :: CheckGenesis , runtime_types :: frame_system :: extensions :: check_mortality :: CheckMortality , runtime_types :: frame_system :: extensions :: check_nonce :: CheckNonce , runtime_types :: frame_system :: extensions :: check_weight :: CheckWeight , runtime_types :: quantus_runtime :: transaction_extensions :: ReversibleTransactionExtension , runtime_types :: quantus_runtime :: transaction_extensions :: WormholeProofRecorderExtension , runtime_types :: pallet_transaction_payment :: ChargeTransactionPayment , runtime_types :: frame_metadata_hash_extension :: CheckMetadataHash , runtime_types :: frame_system :: extensions :: weight_reclaim :: WeightReclaim ,) > ; pub type Len = ::core::primitive::u32; pub mod output { use super::runtime_types; @@ -1564,9 +1563,10 @@ pub mod api { "query_call_info", types::QueryCallInfo { call, len }, [ - 34u8, 114u8, 111u8, 194u8, 37u8, 90u8, 202u8, 63u8, 204u8, 19u8, 153u8, - 211u8, 45u8, 27u8, 127u8, 106u8, 35u8, 239u8, 110u8, 164u8, 190u8, - 17u8, 147u8, 31u8, 48u8, 90u8, 56u8, 94u8, 210u8, 89u8, 92u8, 226u8, + 33u8, 109u8, 175u8, 85u8, 20u8, 153u8, 151u8, 189u8, 126u8, 196u8, + 149u8, 212u8, 162u8, 199u8, 191u8, 186u8, 212u8, 236u8, 156u8, 228u8, + 186u8, 107u8, 35u8, 45u8, 42u8, 211u8, 162u8, 216u8, 60u8, 118u8, 1u8, + 57u8, ], ) } @@ -1584,10 +1584,10 @@ pub mod api { "query_call_fee_details", types::QueryCallFeeDetails { call, len }, [ - 194u8, 91u8, 39u8, 188u8, 82u8, 91u8, 27u8, 107u8, 55u8, 59u8, 69u8, - 246u8, 236u8, 221u8, 138u8, 88u8, 210u8, 238u8, 2u8, 182u8, 250u8, - 110u8, 142u8, 192u8, 156u8, 6u8, 132u8, 147u8, 42u8, 247u8, 65u8, - 128u8, + 24u8, 88u8, 218u8, 4u8, 208u8, 93u8, 194u8, 26u8, 151u8, 224u8, 30u8, + 60u8, 203u8, 199u8, 216u8, 240u8, 23u8, 63u8, 103u8, 167u8, 119u8, + 116u8, 247u8, 178u8, 176u8, 26u8, 13u8, 144u8, 159u8, 70u8, 93u8, + 203u8, ], ) } @@ -1939,9 +1939,6 @@ pub mod api { pub fn tech_referenda(&self) -> tech_referenda::constants::ConstantsApi { tech_referenda::constants::ConstantsApi } - pub fn recovery(&self) -> recovery::constants::ConstantsApi { - recovery::constants::ConstantsApi - } pub fn multisig(&self) -> multisig::constants::ConstantsApi { multisig::constants::ConstantsApi } @@ -1990,9 +1987,6 @@ pub mod api { pub fn treasury_pallet(&self) -> treasury_pallet::storage::StorageApi { treasury_pallet::storage::StorageApi } - pub fn recovery(&self) -> recovery::storage::StorageApi { - recovery::storage::StorageApi - } pub fn multisig(&self) -> multisig::storage::StorageApi { multisig::storage::StorageApi } @@ -2035,9 +2029,6 @@ pub mod api { pub fn treasury_pallet(&self) -> treasury_pallet::calls::TransactionApi { treasury_pallet::calls::TransactionApi } - pub fn recovery(&self) -> recovery::calls::TransactionApi { - recovery::calls::TransactionApi - } pub fn multisig(&self) -> multisig::calls::TransactionApi { multisig::calls::TransactionApi } @@ -2059,9 +2050,9 @@ pub mod api { .hash(); runtime_metadata_hash == [ - 96u8, 163u8, 153u8, 76u8, 33u8, 139u8, 46u8, 0u8, 123u8, 149u8, 105u8, 82u8, 217u8, - 235u8, 13u8, 191u8, 114u8, 11u8, 192u8, 179u8, 21u8, 254u8, 20u8, 137u8, 47u8, - 12u8, 40u8, 230u8, 148u8, 153u8, 220u8, 204u8, + 242u8, 240u8, 161u8, 192u8, 242u8, 107u8, 204u8, 96u8, 136u8, 211u8, 182u8, 7u8, + 219u8, 19u8, 152u8, 31u8, 252u8, 248u8, 142u8, 12u8, 102u8, 87u8, 171u8, 13u8, + 85u8, 174u8, 223u8, 78u8, 90u8, 165u8, 158u8, 228u8, ] } pub mod system { @@ -3189,10 +3180,10 @@ pub mod api { "Events", (), [ - 110u8, 113u8, 86u8, 197u8, 130u8, 3u8, 9u8, 135u8, 26u8, 148u8, 137u8, - 179u8, 230u8, 223u8, 8u8, 231u8, 20u8, 157u8, 180u8, 41u8, 253u8, - 148u8, 227u8, 231u8, 245u8, 2u8, 112u8, 252u8, 213u8, 104u8, 139u8, - 93u8, + 145u8, 196u8, 168u8, 220u8, 39u8, 202u8, 204u8, 242u8, 110u8, 160u8, + 206u8, 102u8, 64u8, 203u8, 40u8, 180u8, 196u8, 63u8, 66u8, 122u8, + 119u8, 47u8, 219u8, 160u8, 184u8, 119u8, 71u8, 227u8, 7u8, 152u8, + 224u8, 121u8, ], ) } @@ -3767,41 +3758,6 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Exactly as `transfer_allow_death`, except the origin must be root and the source account"] - #[doc = "may be specified."] - pub struct ForceTransfer { - pub source: force_transfer::Source, - pub dest: force_transfer::Dest, - #[codec(compact)] - pub value: force_transfer::Value, - } - pub mod force_transfer { - use super::runtime_types; - pub type Source = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - pub type Dest = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - pub type Value = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ForceTransfer { - const PALLET: &'static str = "Balances"; - const CALL: &'static str = "force_transfer"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] #[doc = "Same as the [`transfer_allow_death`] call, but with a check that the transfer will not"] #[doc = "kill the origin account."] #[doc = ""] @@ -3878,129 +3834,6 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Unreserve some balance from a user by force."] - #[doc = ""] - #[doc = "Can only be called by ROOT."] - pub struct ForceUnreserve { - pub who: force_unreserve::Who, - pub amount: force_unreserve::Amount, - } - pub mod force_unreserve { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - pub type Amount = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ForceUnreserve { - const PALLET: &'static str = "Balances"; - const CALL: &'static str = "force_unreserve"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Upgrade a specified account."] - #[doc = ""] - #[doc = "- `origin`: Must be `Signed`."] - #[doc = "- `who`: The account to be upgraded."] - #[doc = ""] - #[doc = "This will waive the transaction fee if at least all but 10% of the accounts needed to"] - #[doc = "be upgraded. (We let some not have to be upgraded just in order to allow for the"] - #[doc = "possibility of churn)."] - pub struct UpgradeAccounts { - pub who: upgrade_accounts::Who, - } - pub mod upgrade_accounts { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::alloc::vec::Vec< - ::subxt::ext::subxt_core::utils::AccountId32, - >; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for UpgradeAccounts { - const PALLET: &'static str = "Balances"; - const CALL: &'static str = "upgrade_accounts"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Set the regular balance of a given account."] - #[doc = ""] - #[doc = "The dispatch origin for this call is `root`."] - pub struct ForceSetBalance { - pub who: force_set_balance::Who, - #[codec(compact)] - pub new_free: force_set_balance::NewFree, - } - pub mod force_set_balance { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - pub type NewFree = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ForceSetBalance { - const PALLET: &'static str = "Balances"; - const CALL: &'static str = "force_set_balance"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Adjust the total issuance in a saturating way."] - #[doc = ""] - #[doc = "Can only be called by root and always needs a positive `delta`."] - #[doc = ""] - #[doc = "# Example"] - pub struct ForceAdjustTotalIssuance { - pub direction: force_adjust_total_issuance::Direction, - #[codec(compact)] - pub delta: force_adjust_total_issuance::Delta, - } - pub mod force_adjust_total_issuance { - use super::runtime_types; - pub type Direction = runtime_types::pallet_balances::types::AdjustmentDirection; - pub type Delta = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ForceAdjustTotalIssuance { - const PALLET: &'static str = "Balances"; - const CALL: &'static str = "force_adjust_total_issuance"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] #[doc = "Burn the specified liquid free balance from the origin account."] #[doc = ""] #[doc = "If the origin's account ends up below the existential deposit as a result"] @@ -4050,26 +3883,6 @@ pub mod api { ], ) } - #[doc = "Exactly as `transfer_allow_death`, except the origin must be root and the source account"] - #[doc = "may be specified."] - pub fn force_transfer( - &self, - source: types::force_transfer::Source, - dest: types::force_transfer::Dest, - value: types::force_transfer::Value, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Balances", - "force_transfer", - types::ForceTransfer { source, dest, value }, - [ - 154u8, 93u8, 222u8, 27u8, 12u8, 248u8, 63u8, 213u8, 224u8, 86u8, 250u8, - 153u8, 249u8, 102u8, 83u8, 160u8, 79u8, 125u8, 105u8, 222u8, 77u8, - 180u8, 90u8, 105u8, 81u8, 217u8, 60u8, 25u8, 213u8, 51u8, 185u8, 96u8, - ], - ) - } #[doc = "Same as the [`transfer_allow_death`] call, but with a check that the transfer will not"] #[doc = "kill the origin account."] #[doc = ""] @@ -4124,95 +3937,6 @@ pub mod api { ], ) } - #[doc = "Unreserve some balance from a user by force."] - #[doc = ""] - #[doc = "Can only be called by ROOT."] - pub fn force_unreserve( - &self, - who: types::force_unreserve::Who, - amount: types::force_unreserve::Amount, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Balances", - "force_unreserve", - types::ForceUnreserve { who, amount }, - [ - 142u8, 151u8, 64u8, 205u8, 46u8, 64u8, 62u8, 122u8, 108u8, 49u8, 223u8, - 140u8, 120u8, 153u8, 35u8, 165u8, 187u8, 38u8, 157u8, 200u8, 123u8, - 199u8, 198u8, 168u8, 208u8, 159u8, 39u8, 134u8, 92u8, 103u8, 84u8, - 171u8, - ], - ) - } - #[doc = "Upgrade a specified account."] - #[doc = ""] - #[doc = "- `origin`: Must be `Signed`."] - #[doc = "- `who`: The account to be upgraded."] - #[doc = ""] - #[doc = "This will waive the transaction fee if at least all but 10% of the accounts needed to"] - #[doc = "be upgraded. (We let some not have to be upgraded just in order to allow for the"] - #[doc = "possibility of churn)."] - pub fn upgrade_accounts( - &self, - who: types::upgrade_accounts::Who, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Balances", - "upgrade_accounts", - types::UpgradeAccounts { who }, - [ - 66u8, 200u8, 179u8, 104u8, 65u8, 2u8, 101u8, 56u8, 130u8, 161u8, 224u8, - 233u8, 255u8, 124u8, 70u8, 122u8, 8u8, 49u8, 103u8, 178u8, 68u8, 47u8, - 214u8, 166u8, 217u8, 116u8, 178u8, 50u8, 212u8, 164u8, 98u8, 226u8, - ], - ) - } - #[doc = "Set the regular balance of a given account."] - #[doc = ""] - #[doc = "The dispatch origin for this call is `root`."] - pub fn force_set_balance( - &self, - who: types::force_set_balance::Who, - new_free: types::force_set_balance::NewFree, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Balances", - "force_set_balance", - types::ForceSetBalance { who, new_free }, - [ - 114u8, 229u8, 59u8, 204u8, 180u8, 83u8, 17u8, 4u8, 59u8, 4u8, 55u8, - 39u8, 151u8, 196u8, 124u8, 60u8, 209u8, 65u8, 193u8, 11u8, 44u8, 164u8, - 116u8, 93u8, 169u8, 30u8, 199u8, 165u8, 55u8, 231u8, 223u8, 43u8, - ], - ) - } - #[doc = "Adjust the total issuance in a saturating way."] - #[doc = ""] - #[doc = "Can only be called by root and always needs a positive `delta`."] - #[doc = ""] - #[doc = "# Example"] - pub fn force_adjust_total_issuance( - &self, - direction: types::force_adjust_total_issuance::Direction, - delta: types::force_adjust_total_issuance::Delta, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< - types::ForceAdjustTotalIssuance, - > { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Balances", - "force_adjust_total_issuance", - types::ForceAdjustTotalIssuance { direction, delta }, - [ - 208u8, 134u8, 56u8, 133u8, 232u8, 164u8, 10u8, 213u8, 53u8, 193u8, - 190u8, 63u8, 236u8, 186u8, 96u8, 122u8, 104u8, 87u8, 173u8, 38u8, 58u8, - 176u8, 21u8, 78u8, 42u8, 106u8, 46u8, 248u8, 251u8, 190u8, 150u8, - 202u8, - ], - ) - } #[doc = "Burn the specified liquid free balance from the origin account."] #[doc = ""] #[doc = "If the origin's account ends up below the existential deposit as a result"] @@ -4731,27 +4455,6 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The `TotalIssuance` was forcefully changed."] - pub struct TotalIssuanceForced { - pub old: total_issuance_forced::Old, - pub new: total_issuance_forced::New, - } - pub mod total_issuance_forced { - use super::runtime_types; - pub type Old = ::core::primitive::u128; - pub type New = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TotalIssuanceForced { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "TotalIssuanceForced"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] #[doc = "Some balance was placed on hold."] pub struct Held { pub reason: held::Reason, @@ -5759,17 +5462,17 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Rewards were sent to Treasury when no miner was specified"] - pub struct TreasuryRewarded { - pub reward: treasury_rewarded::Reward, + #[doc = "No miner in the digest; the credit stays in [`CollectedFees`] for the next block."] + pub struct PayoutDeferred { + pub amount: payout_deferred::Amount, } - pub mod treasury_rewarded { + pub mod payout_deferred { use super::runtime_types; - pub type Reward = ::core::primitive::u128; + pub type Amount = ::core::primitive::u128; } - impl ::subxt::ext::subxt_core::events::StaticEvent for TreasuryRewarded { + impl ::subxt::ext::subxt_core::events::StaticEvent for PayoutDeferred { const PALLET: &'static str = "MiningRewards"; - const EVENT: &'static str = "TreasuryRewarded"; + const EVENT: &'static str = "PayoutDeferred"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -5778,38 +5481,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Miner reward was redirected to treasury due to mint failure"] - pub struct MinerRewardRedirected { - pub miner: miner_reward_redirected::Miner, - pub reward: miner_reward_redirected::Reward, + #[doc = "Miner mint failed; the credit stays in [`CollectedFees`] for retry."] + pub struct MinerMintFailed { + pub miner: miner_mint_failed::Miner, + pub reward: miner_mint_failed::Reward, } - pub mod miner_reward_redirected { + pub mod miner_mint_failed { use super::runtime_types; pub type Miner = ::subxt::ext::subxt_core::utils::AccountId32; pub type Reward = ::core::primitive::u128; } - impl ::subxt::ext::subxt_core::events::StaticEvent for MinerRewardRedirected { - const PALLET: &'static str = "MiningRewards"; - const EVENT: &'static str = "MinerRewardRedirected"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Treasury mint failed; amount retained in [`CollectedFees`] for retry."] - pub struct TreasuryMintFailed { - pub reward: treasury_mint_failed::Reward, - } - pub mod treasury_mint_failed { - use super::runtime_types; - pub type Reward = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TreasuryMintFailed { + impl ::subxt::ext::subxt_core::events::StaticEvent for MinerMintFailed { const PALLET: &'static str = "MiningRewards"; - const EVENT: &'static str = "TreasuryMintFailed"; + const EVENT: &'static str = "MinerMintFailed"; } } pub mod storage { @@ -6995,7 +6679,8 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Send a batch of dispatch calls."] + #[doc = "Send a batch of dispatch calls and atomically execute them."] + #[doc = "The whole transaction will rollback and fail if any of the calls failed."] #[doc = ""] #[doc = "May be called from any origin except `None`."] #[doc = ""] @@ -7008,72 +6693,24 @@ pub mod api { #[doc = "## Complexity"] #[doc = "- O(C) where C is the number of calls to be batched."] #[doc = ""] - #[doc = "This will return `Ok` in all circumstances. To determine the success of the batch, an"] - #[doc = "event is deposited. If a call failed and the batch was interrupted, then the"] - #[doc = "`BatchInterrupted` event is deposited, along with the number of successful calls made"] - #[doc = "and the error of the failed call. If all were successful, then the `BatchCompleted`"] - #[doc = "event is deposited."] - pub struct Batch { - pub calls: batch::Calls, + #[doc = "Call index 2 is preserved from the upstream utility pallet so existing"] + #[doc = "`batch_all` encodings keep decoding after the other combinators were removed."] + pub struct BatchAll { + pub calls: batch_all::Calls, } - pub mod batch { + pub mod batch_all { use super::runtime_types; pub type Calls = ::subxt::ext::subxt_core::alloc::vec::Vec< runtime_types::quantus_runtime::RuntimeCall, >; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Batch { - const PALLET: &'static str = "Utility"; - const CALL: &'static str = "batch"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Send a call through an indexed pseudonym of the sender."] - #[doc = ""] - #[doc = "Filter from origin are passed along. The call will be dispatched with an origin which"] - #[doc = "use the same filter as the origin of this call."] - #[doc = ""] - #[doc = "NOTE: If you need to ensure that any account-based filtering is not honored (i.e."] - #[doc = "because you expect `proxy` to have been used prior in the call stack and you do not want"] - #[doc = "the call restrictions to apply to any sub-accounts), then use `as_multi_threshold_1`"] - #[doc = "in the Multisig pallet instead."] - #[doc = ""] - #[doc = "NOTE: Prior to version *12, this was called `as_limited_sub`."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - pub struct AsDerivative { - pub index: as_derivative::Index, - pub call: ::subxt::ext::subxt_core::alloc::boxed::Box, - } - pub mod as_derivative { - use super::runtime_types; - pub type Index = ::core::primitive::u16; - pub type Call = runtime_types::quantus_runtime::RuntimeCall; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for AsDerivative { + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for BatchAll { const PALLET: &'static str = "Utility"; - const CALL: &'static str = "as_derivative"; + const CALL: &'static str = "batch_all"; } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] + } + pub struct TransactionApi; + impl TransactionApi { #[doc = "Send a batch of dispatch calls and atomically execute them."] #[doc = "The whole transaction will rollback and fail if any of the calls failed."] #[doc = ""] @@ -7087,50 +6724,93 @@ pub mod api { #[doc = ""] #[doc = "## Complexity"] #[doc = "- O(C) where C is the number of calls to be batched."] - pub struct BatchAll { - pub calls: batch_all::Calls, - } - pub mod batch_all { - use super::runtime_types; - pub type Calls = ::subxt::ext::subxt_core::alloc::vec::Vec< - runtime_types::quantus_runtime::RuntimeCall, - >; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for BatchAll { - const PALLET: &'static str = "Utility"; - const CALL: &'static str = "batch_all"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Dispatches a function call with a provided origin."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] - pub struct DispatchAs { - pub as_origin: - ::subxt::ext::subxt_core::alloc::boxed::Box, - pub call: ::subxt::ext::subxt_core::alloc::boxed::Box, - } - pub mod dispatch_as { - use super::runtime_types; - pub type AsOrigin = runtime_types::quantus_runtime::OriginCaller; - pub type Call = runtime_types::quantus_runtime::RuntimeCall; + #[doc = "Call index 2 is preserved from the upstream utility pallet so existing"] + #[doc = "`batch_all` encodings keep decoding after the other combinators were removed."] + pub fn batch_all( + &self, + calls: types::batch_all::Calls, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { + ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + "Utility", + "batch_all", + types::BatchAll { calls }, + [ + 120u8, 103u8, 239u8, 120u8, 123u8, 60u8, 116u8, 102u8, 54u8, 213u8, + 153u8, 164u8, 181u8, 162u8, 53u8, 227u8, 52u8, 6u8, 232u8, 210u8, 11u8, + 135u8, 155u8, 249u8, 131u8, 170u8, 84u8, 116u8, 115u8, 71u8, 185u8, + 231u8, + ], + ) } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for DispatchAs { - const PALLET: &'static str = "Utility"; - const CALL: &'static str = "dispatch_as"; + } + } + #[doc = "The `Event` enum of this pallet"] + pub type Event = runtime_types::pallet_utility::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "Batch of dispatches completed fully with no error."] + pub struct BatchCompleted; + impl ::subxt::ext::subxt_core::events::StaticEvent for BatchCompleted { + const PALLET: &'static str = "Utility"; + const EVENT: &'static str = "BatchCompleted"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "A single item within a Batch of dispatches has completed with no error."] + pub struct ItemCompleted; + impl ::subxt::ext::subxt_core::events::StaticEvent for ItemCompleted { + const PALLET: &'static str = "Utility"; + const EVENT: &'static str = "ItemCompleted"; + } + } + pub mod constants { + use super::runtime_types; + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " The limit on the number of batched calls."] + pub fn batched_calls_limit( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "Utility", + "batched_calls_limit", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) } + } + } + } + pub mod reversible_transfers { + use super::{root_mod, runtime_types}; + #[doc = "The `Error` enum of this pallet."] + pub type Error = runtime_types::pallet_reversible_transfers::pallet::Error; + #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] + pub type Call = runtime_types::pallet_reversible_transfers::pallet::Call; + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + pub mod types { + use super::runtime_types; #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, @@ -7142,31 +6822,71 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Send a batch of dispatch calls."] - #[doc = "Unlike `batch`, it allows errors and won't interrupt."] + #[doc = "Enable high-security for the calling account with a specified"] + #[doc = "reversibility delay."] #[doc = ""] - #[doc = "May be called from any origin except `None`."] + #[doc = "Once an account is set as high security it can only make reversible"] + #[doc = "transfers. It is not allowed any other calls."] #[doc = ""] - #[doc = "- `calls`: The calls to be dispatched from the same origin. The number of call must not"] - #[doc = " exceed the constant: `batched_calls_limit` (available in constant metadata)."] + #[doc = "# Warning: Permanent and Irreversible"] #[doc = ""] - #[doc = "If origin is root then the calls are dispatch without checking origin filter. (This"] - #[doc = "includes bypassing `frame_system::Config::BaseCallFilter`)."] + #[doc = "**Enabling high security mode is a one-way operation that cannot be undone.**"] #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(C) where C is the number of calls to be batched."] - pub struct ForceBatch { - pub calls: force_batch::Calls, + #[doc = "Once this function is called successfully, the account is permanently restricted"] + #[doc = "to only the following operations:"] + #[doc = "- [`schedule_transfer`](Self::schedule_transfer) - Schedule delayed native token"] + #[doc = " transfers"] + #[doc = "- [`cancel`](Self::cancel) - Cancel pending transfers"] + #[doc = "- [`recover_funds`](Self::recover_funds) - Guardian-initiated emergency fund recovery"] + #[doc = ""] + #[doc = "There is no mechanism to disable high security mode or restore normal account"] + #[doc = "functionality. This design is intentional to provide maximum security guarantees:"] + #[doc = "an attacker who gains access to the account cannot simply disable the protections."] + #[doc = ""] + #[doc = "This permanence also ensures that any funds subsequently sent to a compromised"] + #[doc = "account (e.g., from pending payments, contracts, or accidental deposits) remain"] + #[doc = "protected and can be recovered by the guardian via"] + #[doc = "[`recover_funds`](Self::recover_funds). The guardian can call `recover_funds`"] + #[doc = "repeatedly as needed."] + #[doc = ""] + #[doc = "Users who no longer wish to use high-security features can simply transfer their"] + #[doc = "funds to a different account using [`schedule_transfer`](Self::schedule_transfer)."] + #[doc = ""] + #[doc = "# Parameters"] + #[doc = ""] + #[doc = "- `delay`: The reversibility time for any transfer made by the high-security account."] + #[doc = "- `guardian`: The guardian account that can cancel pending transfers and recover funds"] + #[doc = " from this high-security account."] + #[doc = ""] + #[doc = "# Choose the guardian carefully"] + #[doc = ""] + #[doc = "The guardian holds instant, total seizure power: `recover_funds`"] + #[doc = "sweeps every hold plus the entire free balance to the guardian,"] + #[doc = "with no delay, no second approver, and no way to change the"] + #[doc = "relationship afterwards. A single-key guardian is therefore a"] + #[doc = "single point of failure for the whole scheme. **Use a multisig"] + #[doc = "address as the guardian**: `pallet_multisig` dispatches calls as"] + #[doc = "its derived address, so a multisig can cancel and recover exactly"] + #[doc = "like a plain account."] + #[doc = ""] + #[doc = "Guardianship is discoverable offchain (e.g. Subsquid) via the"] + #[doc = "`HighSecuritySet` event; there is deliberately no on-chain"] + #[doc = "guardian index to fill up or grief."] + pub struct SetHighSecurity { + pub delay: set_high_security::Delay, + pub guardian: set_high_security::Guardian, } - pub mod force_batch { + pub mod set_high_security { use super::runtime_types; - pub type Calls = ::subxt::ext::subxt_core::alloc::vec::Vec< - runtime_types::quantus_runtime::RuntimeCall, + pub type Delay = runtime_types::qp_scheduler::BlockNumberOrTimestamp< + ::core::primitive::u32, + ::core::primitive::u64, >; + pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ForceBatch { - const PALLET: &'static str = "Utility"; - const CALL: &'static str = "force_batch"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetHighSecurity { + const PALLET: &'static str = "ReversibleTransfers"; + const CALL: &'static str = "set_high_security"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7179,24 +6899,19 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Dispatch a function call with a specified weight."] - #[doc = ""] - #[doc = "This function does not check the weight of the call, and instead allows the"] - #[doc = "Root origin to specify the weight of the call."] + #[doc = "Cancel a pending reversible transaction scheduled by the caller."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] - pub struct WithWeight { - pub call: ::subxt::ext::subxt_core::alloc::boxed::Box, - pub weight: with_weight::Weight, + #[doc = "- `tx_id`: The unique identifier of the transaction to cancel."] + pub struct Cancel { + pub tx_id: cancel::TxId, } - pub mod with_weight { + pub mod cancel { use super::runtime_types; - pub type Call = runtime_types::quantus_runtime::RuntimeCall; - pub type Weight = runtime_types::sp_weights::weight_v2::Weight; + pub type TxId = ::subxt::ext::subxt_core::utils::H256; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for WithWeight { - const PALLET: &'static str = "Utility"; - const CALL: &'static str = "with_weight"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Cancel { + const PALLET: &'static str = "ReversibleTransfers"; + const CALL: &'static str = "cancel"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7209,41 +6924,69 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Dispatch a fallback call in the event the main call fails to execute."] - #[doc = "May be called from any origin except `None`."] + #[doc = "Executes a previously scheduled transfer after the delay period has elapsed."] + #[doc = ""] + #[doc = "This extrinsic is called automatically by the Scheduler pallet when the"] + #[doc = "delay period expires. It must be signed by this pallet's account (not a user)."] + #[doc = "The pallet account is set as the origin when scheduling via"] + #[doc = "[`do_schedule_transfer_inner`](Self::do_schedule_transfer_inner)."] #[doc = ""] - #[doc = "This function first attempts to dispatch the `main` call."] - #[doc = "If the `main` call fails, the `fallback` is attemted."] - #[doc = "if the fallback is successfully dispatched, the weights of both calls"] - #[doc = "are accumulated and an event containing the main call error is deposited."] + #[doc = "# Parameters"] #[doc = ""] - #[doc = "In the event of a fallback failure the whole call fails"] - #[doc = "with the weights returned."] + #[doc = "- `tx_id`: The unique identifier of the pending transfer to execute."] #[doc = ""] - #[doc = "- `main`: The main call to be dispatched. This is the primary action to execute."] - #[doc = "- `fallback`: The fallback call to be dispatched in case the `main` call fails."] + #[doc = "Execution uses `transfer_allow_death` so a sender who spent their leftover"] + #[doc = "free balance during the delay still completes. A failed inner transfer (e.g."] + #[doc = "dest overflow, or `amount < ED` to a new account) does not fail this"] + #[doc = "extrinsic: the hold is already released and the pending transfer is already"] + #[doc = "removed. Propagating that error would roll back those writes (FRAME"] + #[doc = "dispatchables are transactional) while Scheduler terminally drops the named"] + #[doc = "task, freezing the funds with no retry. The inner result is still recorded on"] + #[doc = "[`Event::TransactionExecuted`]."] #[doc = ""] - #[doc = "## Dispatch Logic"] - #[doc = "- If the origin is `root`, both the main and fallback calls are executed without"] - #[doc = " applying any origin filters."] - #[doc = "- If the origin is not `root`, the origin filter is applied to both the `main` and"] - #[doc = " `fallback` calls."] + #[doc = "# Errors"] #[doc = ""] - #[doc = "## Use Case"] - #[doc = "- Some use cases might involve submitting a `batch` type call in either main, fallback"] - #[doc = " or both."] - pub struct IfElse { - pub main: ::subxt::ext::subxt_core::alloc::boxed::Box, - pub fallback: ::subxt::ext::subxt_core::alloc::boxed::Box, + #[doc = "- [`InvalidSchedulerOrigin`](Error::InvalidSchedulerOrigin): Called by an account other"] + #[doc = " than this pallet's account."] + #[doc = "- [`PendingTxNotFound`](Error::PendingTxNotFound): No pending transfer with this ID."] + pub struct ExecuteTransfer { + pub tx_id: execute_transfer::TxId, } - pub mod if_else { + pub mod execute_transfer { use super::runtime_types; - pub type Main = runtime_types::quantus_runtime::RuntimeCall; - pub type Fallback = runtime_types::quantus_runtime::RuntimeCall; + pub type TxId = ::subxt::ext::subxt_core::utils::H256; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for IfElse { - const PALLET: &'static str = "Utility"; - const CALL: &'static str = "if_else"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ExecuteTransfer { + const PALLET: &'static str = "ReversibleTransfers"; + const CALL: &'static str = "execute_transfer"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "Schedule a transaction for delayed execution."] + pub struct ScheduleTransfer { + pub dest: schedule_transfer::Dest, + pub amount: schedule_transfer::Amount, + } + pub mod schedule_transfer { + use super::runtime_types; + pub type Dest = ::subxt::ext::subxt_core::utils::MultiAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + (), + >; + pub type Amount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ScheduleTransfer { + const PALLET: &'static str = "ReversibleTransfers"; + const CALL: &'static str = "schedule_transfer"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7256,276 +6999,320 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Dispatches a function call with a provided origin."] + #[doc = "Schedule a transaction for delayed execution with a custom, one-time delay."] #[doc = ""] - #[doc = "Almost the same as [`Pallet::dispatch_as`] but forwards any error of the inner call."] + #[doc = "This can only be used by accounts that have *not* set up a persistent"] + #[doc = "reversibility configuration with `set_high_security`."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] - pub struct DispatchAsFallible { - pub as_origin: - ::subxt::ext::subxt_core::alloc::boxed::Box, - pub call: - ::subxt::ext::subxt_core::alloc::boxed::Box, + #[doc = "- `delay`: The time (in blocks or milliseconds) before the transaction executes."] + pub struct ScheduleTransferWithDelay { + pub dest: schedule_transfer_with_delay::Dest, + pub amount: schedule_transfer_with_delay::Amount, + pub delay: schedule_transfer_with_delay::Delay, } - pub mod dispatch_as_fallible { + pub mod schedule_transfer_with_delay { use super::runtime_types; - pub type AsOrigin = runtime_types::quantus_runtime::OriginCaller; - pub type Call = runtime_types::quantus_runtime::RuntimeCall; + pub type Dest = ::subxt::ext::subxt_core::utils::MultiAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + (), + >; + pub type Amount = ::core::primitive::u128; + pub type Delay = runtime_types::qp_scheduler::BlockNumberOrTimestamp< + ::core::primitive::u32, + ::core::primitive::u64, + >; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for DispatchAsFallible { - const PALLET: &'static str = "Utility"; - const CALL: &'static str = "dispatch_as_fallible"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ScheduleTransferWithDelay { + const PALLET: &'static str = "ReversibleTransfers"; + const CALL: &'static str = "schedule_transfer_with_delay"; } - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Send a batch of dispatch calls."] + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "Allows the guardian to recover all funds from a high-security account"] + #[doc = "by transferring the entire balance to themselves."] #[doc = ""] - #[doc = "May be called from any origin except `None`."] + #[doc = "This is an emergency function for when the high-security account may be compromised."] + #[doc = "It cancels all pending transfers first (applying volume fees), then transfers"] + #[doc = "the remaining free balance to the guardian."] #[doc = ""] - #[doc = "- `calls`: The calls to be dispatched from the same origin. The number of call must not"] - #[doc = " exceed the constant: `batched_calls_limit` (available in constant metadata)."] + #[doc = "# Cancel vs recovery authority"] #[doc = ""] - #[doc = "If origin is root then the calls are dispatched without checking origin filter. (This"] - #[doc = "includes bypassing `frame_system::Config::BaseCallFilter`)."] + #[doc = "Per-transfer `cancel` freezes authority in `pending.guardian` at schedule time"] + #[doc = "(so a later `set_high_security` cannot rewrite cancel rights on pre-enrollment"] + #[doc = "one-time transfers). `recover_funds` does **not** use that freeze: it authorizes"] + #[doc = "against the *live* high-security guardian and seizes every pending hold on the"] + #[doc = "account (volume fee applied). That asymmetry is intentional — recovery is"] + #[doc = "seize-the-account, not a batch of frozen cancel policies."] #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(C) where C is the number of calls to be batched."] + #[doc = "# Repeated Recovery"] #[doc = ""] - #[doc = "This will return `Ok` in all circumstances. To determine the success of the batch, an"] - #[doc = "event is deposited. If a call failed and the batch was interrupted, then the"] - #[doc = "`BatchInterrupted` event is deposited, along with the number of successful calls made"] - #[doc = "and the error of the failed call. If all were successful, then the `BatchCompleted`"] - #[doc = "event is deposited."] - pub fn batch( - &self, - calls: types::batch::Calls, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Utility", - "batch", - types::Batch { calls }, - [ - 152u8, 40u8, 62u8, 45u8, 150u8, 26u8, 154u8, 136u8, 95u8, 156u8, 129u8, - 181u8, 179u8, 30u8, 144u8, 103u8, 22u8, 224u8, 184u8, 182u8, 186u8, - 178u8, 232u8, 255u8, 252u8, 117u8, 42u8, 191u8, 164u8, 140u8, 57u8, - 189u8, - ], - ) + #[doc = "This function can be called multiple times on the same account. The high-security"] + #[doc = "status and guardian relationship are intentionally preserved after recovery, ensuring"] + #[doc = "that any funds subsequently deposited to the account (e.g., from pending payments,"] + #[doc = "contracts, or accidental deposits) remain protected and recoverable."] + #[doc = ""] + #[doc = "# Error Handling"] + #[doc = ""] + #[doc = "If releasing held funds fails for any transfer, that transfer is skipped (metadata"] + #[doc = "preserved for manual retry via `cancel`) and a `TransferRecoveryFailed` event is"] + #[doc = "emitted. Other transfers continue to be processed."] + #[doc = ""] + #[doc = "The closing free-balance sweep to the guardian is likewise best-effort: if it"] + #[doc = "fails (e.g. the guardian cannot receive the funds), the call still succeeds and"] + #[doc = "all cancellations performed above remain in effect — they must not be rolled"] + #[doc = "back, or the pending transfers would be re-armed and execute at their scheduled"] + #[doc = "time. A `RecoverySweepFailed` event is emitted instead of `FundsRecovered`, and"] + #[doc = "the guardian can call `recover_funds` again to retry the sweep."] + pub struct RecoverFunds { + pub account: recover_funds::Account, + } + pub mod recover_funds { + use super::runtime_types; + pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for RecoverFunds { + const PALLET: &'static str = "ReversibleTransfers"; + const CALL: &'static str = "recover_funds"; } - #[doc = "Send a call through an indexed pseudonym of the sender."] + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Enable high-security for the calling account with a specified"] + #[doc = "reversibility delay."] #[doc = ""] - #[doc = "Filter from origin are passed along. The call will be dispatched with an origin which"] - #[doc = "use the same filter as the origin of this call."] + #[doc = "Once an account is set as high security it can only make reversible"] + #[doc = "transfers. It is not allowed any other calls."] #[doc = ""] - #[doc = "NOTE: If you need to ensure that any account-based filtering is not honored (i.e."] - #[doc = "because you expect `proxy` to have been used prior in the call stack and you do not want"] - #[doc = "the call restrictions to apply to any sub-accounts), then use `as_multi_threshold_1`"] - #[doc = "in the Multisig pallet instead."] + #[doc = "# Warning: Permanent and Irreversible"] #[doc = ""] - #[doc = "NOTE: Prior to version *12, this was called `as_limited_sub`."] + #[doc = "**Enabling high security mode is a one-way operation that cannot be undone.**"] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - pub fn as_derivative( - &self, - index: types::as_derivative::Index, - call: types::as_derivative::Call, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Utility", - "as_derivative", - types::AsDerivative { - index, - call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), - }, - [ - 153u8, 154u8, 46u8, 242u8, 195u8, 157u8, 10u8, 76u8, 165u8, 224u8, - 61u8, 82u8, 211u8, 225u8, 146u8, 136u8, 129u8, 113u8, 205u8, 162u8, - 220u8, 146u8, 64u8, 185u8, 254u8, 83u8, 150u8, 152u8, 8u8, 216u8, 81u8, - 220u8, - ], - ) - } - #[doc = "Send a batch of dispatch calls and atomically execute them."] - #[doc = "The whole transaction will rollback and fail if any of the calls failed."] + #[doc = "Once this function is called successfully, the account is permanently restricted"] + #[doc = "to only the following operations:"] + #[doc = "- [`schedule_transfer`](Self::schedule_transfer) - Schedule delayed native token"] + #[doc = " transfers"] + #[doc = "- [`cancel`](Self::cancel) - Cancel pending transfers"] + #[doc = "- [`recover_funds`](Self::recover_funds) - Guardian-initiated emergency fund recovery"] #[doc = ""] - #[doc = "May be called from any origin except `None`."] + #[doc = "There is no mechanism to disable high security mode or restore normal account"] + #[doc = "functionality. This design is intentional to provide maximum security guarantees:"] + #[doc = "an attacker who gains access to the account cannot simply disable the protections."] #[doc = ""] - #[doc = "- `calls`: The calls to be dispatched from the same origin. The number of call must not"] - #[doc = " exceed the constant: `batched_calls_limit` (available in constant metadata)."] + #[doc = "This permanence also ensures that any funds subsequently sent to a compromised"] + #[doc = "account (e.g., from pending payments, contracts, or accidental deposits) remain"] + #[doc = "protected and can be recovered by the guardian via"] + #[doc = "[`recover_funds`](Self::recover_funds). The guardian can call `recover_funds`"] + #[doc = "repeatedly as needed."] #[doc = ""] - #[doc = "If origin is root then the calls are dispatched without checking origin filter. (This"] - #[doc = "includes bypassing `frame_system::Config::BaseCallFilter`)."] + #[doc = "Users who no longer wish to use high-security features can simply transfer their"] + #[doc = "funds to a different account using [`schedule_transfer`](Self::schedule_transfer)."] #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(C) where C is the number of calls to be batched."] - pub fn batch_all( + #[doc = "# Parameters"] + #[doc = ""] + #[doc = "- `delay`: The reversibility time for any transfer made by the high-security account."] + #[doc = "- `guardian`: The guardian account that can cancel pending transfers and recover funds"] + #[doc = " from this high-security account."] + #[doc = ""] + #[doc = "# Choose the guardian carefully"] + #[doc = ""] + #[doc = "The guardian holds instant, total seizure power: `recover_funds`"] + #[doc = "sweeps every hold plus the entire free balance to the guardian,"] + #[doc = "with no delay, no second approver, and no way to change the"] + #[doc = "relationship afterwards. A single-key guardian is therefore a"] + #[doc = "single point of failure for the whole scheme. **Use a multisig"] + #[doc = "address as the guardian**: `pallet_multisig` dispatches calls as"] + #[doc = "its derived address, so a multisig can cancel and recover exactly"] + #[doc = "like a plain account."] + #[doc = ""] + #[doc = "Guardianship is discoverable offchain (e.g. Subsquid) via the"] + #[doc = "`HighSecuritySet` event; there is deliberately no on-chain"] + #[doc = "guardian index to fill up or grief."] + pub fn set_high_security( &self, - calls: types::batch_all::Calls, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { + delay: types::set_high_security::Delay, + guardian: types::set_high_security::Guardian, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Utility", - "batch_all", - types::BatchAll { calls }, + "ReversibleTransfers", + "set_high_security", + types::SetHighSecurity { delay, guardian }, [ - 67u8, 14u8, 126u8, 36u8, 158u8, 4u8, 63u8, 67u8, 42u8, 200u8, 35u8, - 113u8, 81u8, 154u8, 135u8, 29u8, 243u8, 115u8, 94u8, 99u8, 179u8, - 126u8, 120u8, 187u8, 75u8, 166u8, 42u8, 176u8, 123u8, 161u8, 250u8, - 142u8, + 103u8, 202u8, 28u8, 11u8, 249u8, 80u8, 142u8, 200u8, 55u8, 4u8, 141u8, + 72u8, 94u8, 199u8, 229u8, 102u8, 246u8, 113u8, 190u8, 84u8, 95u8, + 193u8, 96u8, 171u8, 144u8, 120u8, 235u8, 208u8, 65u8, 183u8, 4u8, 44u8, ], ) } - #[doc = "Dispatches a function call with a provided origin."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] + #[doc = "Cancel a pending reversible transaction scheduled by the caller."] #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] - pub fn dispatch_as( + #[doc = "- `tx_id`: The unique identifier of the transaction to cancel."] + pub fn cancel( &self, - as_origin: types::dispatch_as::AsOrigin, - call: types::dispatch_as::Call, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { + tx_id: types::cancel::TxId, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Utility", - "dispatch_as", - types::DispatchAs { - as_origin: ::subxt::ext::subxt_core::alloc::boxed::Box::new(as_origin), - call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), - }, + "ReversibleTransfers", + "cancel", + types::Cancel { tx_id }, [ - 125u8, 188u8, 120u8, 16u8, 118u8, 133u8, 154u8, 235u8, 75u8, 174u8, - 97u8, 244u8, 44u8, 167u8, 172u8, 140u8, 94u8, 7u8, 23u8, 83u8, 202u8, - 238u8, 153u8, 170u8, 176u8, 179u8, 105u8, 160u8, 62u8, 35u8, 30u8, - 161u8, + 228u8, 150u8, 194u8, 119u8, 243u8, 126u8, 112u8, 227u8, 70u8, 160u8, + 132u8, 82u8, 146u8, 162u8, 195u8, 149u8, 236u8, 98u8, 18u8, 44u8, + 151u8, 249u8, 193u8, 176u8, 186u8, 98u8, 224u8, 103u8, 191u8, 165u8, + 37u8, 47u8, ], ) } - #[doc = "Send a batch of dispatch calls."] - #[doc = "Unlike `batch`, it allows errors and won't interrupt."] + #[doc = "Executes a previously scheduled transfer after the delay period has elapsed."] #[doc = ""] - #[doc = "May be called from any origin except `None`."] + #[doc = "This extrinsic is called automatically by the Scheduler pallet when the"] + #[doc = "delay period expires. It must be signed by this pallet's account (not a user)."] + #[doc = "The pallet account is set as the origin when scheduling via"] + #[doc = "[`do_schedule_transfer_inner`](Self::do_schedule_transfer_inner)."] #[doc = ""] - #[doc = "- `calls`: The calls to be dispatched from the same origin. The number of call must not"] - #[doc = " exceed the constant: `batched_calls_limit` (available in constant metadata)."] + #[doc = "# Parameters"] #[doc = ""] - #[doc = "If origin is root then the calls are dispatch without checking origin filter. (This"] - #[doc = "includes bypassing `frame_system::Config::BaseCallFilter`)."] + #[doc = "- `tx_id`: The unique identifier of the pending transfer to execute."] #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(C) where C is the number of calls to be batched."] - pub fn force_batch( + #[doc = "Execution uses `transfer_allow_death` so a sender who spent their leftover"] + #[doc = "free balance during the delay still completes. A failed inner transfer (e.g."] + #[doc = "dest overflow, or `amount < ED` to a new account) does not fail this"] + #[doc = "extrinsic: the hold is already released and the pending transfer is already"] + #[doc = "removed. Propagating that error would roll back those writes (FRAME"] + #[doc = "dispatchables are transactional) while Scheduler terminally drops the named"] + #[doc = "task, freezing the funds with no retry. The inner result is still recorded on"] + #[doc = "[`Event::TransactionExecuted`]."] + #[doc = ""] + #[doc = "# Errors"] + #[doc = ""] + #[doc = "- [`InvalidSchedulerOrigin`](Error::InvalidSchedulerOrigin): Called by an account other"] + #[doc = " than this pallet's account."] + #[doc = "- [`PendingTxNotFound`](Error::PendingTxNotFound): No pending transfer with this ID."] + pub fn execute_transfer( &self, - calls: types::force_batch::Calls, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { + tx_id: types::execute_transfer::TxId, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Utility", - "force_batch", - types::ForceBatch { calls }, + "ReversibleTransfers", + "execute_transfer", + types::ExecuteTransfer { tx_id }, [ - 203u8, 178u8, 130u8, 171u8, 96u8, 102u8, 14u8, 111u8, 117u8, 173u8, - 215u8, 140u8, 144u8, 26u8, 126u8, 41u8, 236u8, 112u8, 85u8, 251u8, - 227u8, 13u8, 66u8, 130u8, 163u8, 16u8, 185u8, 159u8, 230u8, 210u8, - 174u8, 167u8, + 164u8, 38u8, 166u8, 81u8, 63u8, 235u8, 167u8, 178u8, 97u8, 80u8, 62u8, + 147u8, 3u8, 163u8, 129u8, 25u8, 98u8, 59u8, 17u8, 137u8, 6u8, 183u8, + 189u8, 51u8, 24u8, 211u8, 157u8, 108u8, 229u8, 253u8, 37u8, 78u8, ], ) } - #[doc = "Dispatch a function call with a specified weight."] - #[doc = ""] - #[doc = "This function does not check the weight of the call, and instead allows the"] - #[doc = "Root origin to specify the weight of the call."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] - pub fn with_weight( + #[doc = "Schedule a transaction for delayed execution."] + pub fn schedule_transfer( &self, - call: types::with_weight::Call, - weight: types::with_weight::Weight, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { + dest: types::schedule_transfer::Dest, + amount: types::schedule_transfer::Amount, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Utility", - "with_weight", - types::WithWeight { - call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), - weight, - }, + "ReversibleTransfers", + "schedule_transfer", + types::ScheduleTransfer { dest, amount }, [ - 116u8, 78u8, 64u8, 24u8, 29u8, 217u8, 248u8, 92u8, 141u8, 29u8, 105u8, - 177u8, 80u8, 47u8, 60u8, 167u8, 193u8, 248u8, 59u8, 171u8, 248u8, 51u8, - 158u8, 29u8, 94u8, 16u8, 201u8, 163u8, 105u8, 181u8, 221u8, 158u8, + 38u8, 219u8, 206u8, 56u8, 252u8, 195u8, 52u8, 74u8, 113u8, 125u8, + 107u8, 35u8, 236u8, 39u8, 31u8, 18u8, 250u8, 177u8, 174u8, 154u8, + 149u8, 122u8, 183u8, 50u8, 45u8, 111u8, 100u8, 249u8, 102u8, 82u8, + 72u8, 130u8, ], ) } - #[doc = "Dispatch a fallback call in the event the main call fails to execute."] - #[doc = "May be called from any origin except `None`."] - #[doc = ""] - #[doc = "This function first attempts to dispatch the `main` call."] - #[doc = "If the `main` call fails, the `fallback` is attemted."] - #[doc = "if the fallback is successfully dispatched, the weights of both calls"] - #[doc = "are accumulated and an event containing the main call error is deposited."] - #[doc = ""] - #[doc = "In the event of a fallback failure the whole call fails"] - #[doc = "with the weights returned."] - #[doc = ""] - #[doc = "- `main`: The main call to be dispatched. This is the primary action to execute."] - #[doc = "- `fallback`: The fallback call to be dispatched in case the `main` call fails."] + #[doc = "Schedule a transaction for delayed execution with a custom, one-time delay."] #[doc = ""] - #[doc = "## Dispatch Logic"] - #[doc = "- If the origin is `root`, both the main and fallback calls are executed without"] - #[doc = " applying any origin filters."] - #[doc = "- If the origin is not `root`, the origin filter is applied to both the `main` and"] - #[doc = " `fallback` calls."] + #[doc = "This can only be used by accounts that have *not* set up a persistent"] + #[doc = "reversibility configuration with `set_high_security`."] #[doc = ""] - #[doc = "## Use Case"] - #[doc = "- Some use cases might involve submitting a `batch` type call in either main, fallback"] - #[doc = " or both."] - pub fn if_else( + #[doc = "- `delay`: The time (in blocks or milliseconds) before the transaction executes."] + pub fn schedule_transfer_with_delay( &self, - main: types::if_else::Main, - fallback: types::if_else::Fallback, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { + dest: types::schedule_transfer_with_delay::Dest, + amount: types::schedule_transfer_with_delay::Amount, + delay: types::schedule_transfer_with_delay::Delay, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< + types::ScheduleTransferWithDelay, + > { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Utility", - "if_else", - types::IfElse { - main: ::subxt::ext::subxt_core::alloc::boxed::Box::new(main), - fallback: ::subxt::ext::subxt_core::alloc::boxed::Box::new(fallback), - }, + "ReversibleTransfers", + "schedule_transfer_with_delay", + types::ScheduleTransferWithDelay { dest, amount, delay }, [ - 102u8, 142u8, 173u8, 252u8, 18u8, 218u8, 15u8, 178u8, 147u8, 70u8, - 62u8, 220u8, 19u8, 99u8, 15u8, 108u8, 57u8, 252u8, 164u8, 200u8, 164u8, - 247u8, 20u8, 87u8, 212u8, 93u8, 24u8, 142u8, 184u8, 234u8, 46u8, 53u8, + 254u8, 158u8, 173u8, 217u8, 107u8, 80u8, 229u8, 252u8, 123u8, 46u8, + 177u8, 40u8, 25u8, 15u8, 32u8, 22u8, 224u8, 52u8, 242u8, 48u8, 242u8, + 84u8, 242u8, 143u8, 111u8, 12u8, 82u8, 161u8, 129u8, 86u8, 161u8, + 216u8, ], ) } - #[doc = "Dispatches a function call with a provided origin."] + #[doc = "Allows the guardian to recover all funds from a high-security account"] + #[doc = "by transferring the entire balance to themselves."] #[doc = ""] - #[doc = "Almost the same as [`Pallet::dispatch_as`] but forwards any error of the inner call."] + #[doc = "This is an emergency function for when the high-security account may be compromised."] + #[doc = "It cancels all pending transfers first (applying volume fees), then transfers"] + #[doc = "the remaining free balance to the guardian."] + #[doc = ""] + #[doc = "# Cancel vs recovery authority"] + #[doc = ""] + #[doc = "Per-transfer `cancel` freezes authority in `pending.guardian` at schedule time"] + #[doc = "(so a later `set_high_security` cannot rewrite cancel rights on pre-enrollment"] + #[doc = "one-time transfers). `recover_funds` does **not** use that freeze: it authorizes"] + #[doc = "against the *live* high-security guardian and seizes every pending hold on the"] + #[doc = "account (volume fee applied). That asymmetry is intentional — recovery is"] + #[doc = "seize-the-account, not a batch of frozen cancel policies."] + #[doc = ""] + #[doc = "# Repeated Recovery"] + #[doc = ""] + #[doc = "This function can be called multiple times on the same account. The high-security"] + #[doc = "status and guardian relationship are intentionally preserved after recovery, ensuring"] + #[doc = "that any funds subsequently deposited to the account (e.g., from pending payments,"] + #[doc = "contracts, or accidental deposits) remain protected and recoverable."] + #[doc = ""] + #[doc = "# Error Handling"] + #[doc = ""] + #[doc = "If releasing held funds fails for any transfer, that transfer is skipped (metadata"] + #[doc = "preserved for manual retry via `cancel`) and a `TransferRecoveryFailed` event is"] + #[doc = "emitted. Other transfers continue to be processed."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] - pub fn dispatch_as_fallible( + #[doc = "The closing free-balance sweep to the guardian is likewise best-effort: if it"] + #[doc = "fails (e.g. the guardian cannot receive the funds), the call still succeeds and"] + #[doc = "all cancellations performed above remain in effect — they must not be rolled"] + #[doc = "back, or the pending transfers would be re-armed and execute at their scheduled"] + #[doc = "time. A `RecoverySweepFailed` event is emitted instead of `FundsRecovered`, and"] + #[doc = "the guardian can call `recover_funds` again to retry the sweep."] + pub fn recover_funds( &self, - as_origin: types::dispatch_as_fallible::AsOrigin, - call: types::dispatch_as_fallible::Call, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { + account: types::recover_funds::Account, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Utility", - "dispatch_as_fallible", - types::DispatchAsFallible { - as_origin: ::subxt::ext::subxt_core::alloc::boxed::Box::new(as_origin), - call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), - }, + "ReversibleTransfers", + "recover_funds", + types::RecoverFunds { account }, [ - 34u8, 34u8, 48u8, 74u8, 11u8, 42u8, 167u8, 235u8, 222u8, 39u8, 40u8, - 131u8, 10u8, 170u8, 225u8, 231u8, 58u8, 176u8, 126u8, 184u8, 132u8, - 19u8, 15u8, 122u8, 152u8, 13u8, 32u8, 135u8, 225u8, 250u8, 213u8, 19u8, + 94u8, 241u8, 255u8, 110u8, 4u8, 169u8, 1u8, 45u8, 236u8, 88u8, 167u8, + 180u8, 240u8, 70u8, 111u8, 99u8, 185u8, 143u8, 153u8, 33u8, 101u8, + 30u8, 203u8, 103u8, 229u8, 39u8, 162u8, 76u8, 49u8, 125u8, 247u8, + 220u8, ], ) } } } #[doc = "The `Event` enum of this pallet"] - pub type Event = runtime_types::pallet_utility::pallet::Event; + pub type Event = runtime_types::pallet_reversible_transfers::pallet::Event; pub mod events { use super::runtime_types; #[derive( @@ -7535,33 +7322,24 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Batch of dispatches did not complete fully. Index of first failing dispatch given, as"] - #[doc = "well as the error."] - pub struct BatchInterrupted { - pub index: batch_interrupted::Index, - pub error: batch_interrupted::Error, + #[doc = "A user has enabled their high-security settings."] + pub struct HighSecuritySet { + pub who: high_security_set::Who, + pub guardian: high_security_set::Guardian, + pub delay: high_security_set::Delay, } - pub mod batch_interrupted { + pub mod high_security_set { use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Error = runtime_types::sp_runtime::DispatchError; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for BatchInterrupted { - const PALLET: &'static str = "Utility"; - const EVENT: &'static str = "BatchInterrupted"; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Delay = runtime_types::qp_scheduler::BlockNumberOrTimestamp< + ::core::primitive::u32, + ::core::primitive::u64, + >; } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Batch of dispatches completed fully with no error."] - pub struct BatchCompleted; - impl ::subxt::ext::subxt_core::events::StaticEvent for BatchCompleted { - const PALLET: &'static str = "Utility"; - const EVENT: &'static str = "BatchCompleted"; + impl ::subxt::ext::subxt_core::events::StaticEvent for HighSecuritySet { + const PALLET: &'static str = "ReversibleTransfers"; + const EVENT: &'static str = "HighSecuritySet"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7570,11 +7348,32 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Batch of dispatches completed but has errors."] - pub struct BatchCompletedWithErrors; - impl ::subxt::ext::subxt_core::events::StaticEvent for BatchCompletedWithErrors { - const PALLET: &'static str = "Utility"; - const EVENT: &'static str = "BatchCompletedWithErrors"; + #[doc = "A transaction has been scheduled for delayed execution."] + pub struct TransactionScheduled { + pub from: transaction_scheduled::From, + pub to: transaction_scheduled::To, + pub guardian: transaction_scheduled::Guardian, + pub asset_id: transaction_scheduled::AssetId, + pub amount: transaction_scheduled::Amount, + pub tx_id: transaction_scheduled::TxId, + pub execute_at: transaction_scheduled::ExecuteAt, + } + pub mod transaction_scheduled { + use super::runtime_types; + pub type From = ::subxt::ext::subxt_core::utils::AccountId32; + pub type To = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; + pub type AssetId = ::core::option::Option<::core::primitive::u32>; + pub type Amount = ::core::primitive::u128; + pub type TxId = ::subxt::ext::subxt_core::utils::H256; + pub type ExecuteAt = runtime_types::qp_scheduler::DispatchTime< + ::core::primitive::u32, + ::core::primitive::u64, + >; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for TransactionScheduled { + const PALLET: &'static str = "ReversibleTransfers"; + const EVENT: &'static str = "TransactionScheduled"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7583,11 +7382,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A single item within a Batch of dispatches has completed with no error."] - pub struct ItemCompleted; - impl ::subxt::ext::subxt_core::events::StaticEvent for ItemCompleted { - const PALLET: &'static str = "Utility"; - const EVENT: &'static str = "ItemCompleted"; + #[doc = "A scheduled transaction has been successfully cancelled."] + pub struct TransactionCancelled { + pub who: transaction_cancelled::Who, + pub tx_id: transaction_cancelled::TxId, + } + pub mod transaction_cancelled { + use super::runtime_types; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type TxId = ::subxt::ext::subxt_core::utils::H256; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for TransactionCancelled { + const PALLET: &'static str = "ReversibleTransfers"; + const EVENT: &'static str = "TransactionCancelled"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7596,17 +7403,24 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A single item within a Batch of dispatches has completed with error."] - pub struct ItemFailed { - pub error: item_failed::Error, + #[doc = "A scheduled transaction was executed by the scheduler."] + pub struct TransactionExecuted { + pub tx_id: transaction_executed::TxId, + pub result: transaction_executed::Result, } - pub mod item_failed { + pub mod transaction_executed { use super::runtime_types; - pub type Error = runtime_types::sp_runtime::DispatchError; + pub type TxId = ::subxt::ext::subxt_core::utils::H256; + pub type Result = ::core::result::Result< + runtime_types::frame_support::dispatch::PostDispatchInfo, + runtime_types::sp_runtime::DispatchErrorWithPostInfo< + runtime_types::frame_support::dispatch::PostDispatchInfo, + >, + >; } - impl ::subxt::ext::subxt_core::events::StaticEvent for ItemFailed { - const PALLET: &'static str = "Utility"; - const EVENT: &'static str = "ItemFailed"; + impl ::subxt::ext::subxt_core::events::StaticEvent for TransactionExecuted { + const PALLET: &'static str = "ReversibleTransfers"; + const EVENT: &'static str = "TransactionExecuted"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7615,18 +7429,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A call was dispatched."] - pub struct DispatchedAs { - pub result: dispatched_as::Result, + #[doc = "All funds were recovered from a high-security account by its guardian."] + pub struct FundsRecovered { + pub account: funds_recovered::Account, + pub guardian: funds_recovered::Guardian, } - pub mod dispatched_as { + pub mod funds_recovered { use super::runtime_types; - pub type Result = - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>; + pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; } - impl ::subxt::ext::subxt_core::events::StaticEvent for DispatchedAs { - const PALLET: &'static str = "Utility"; - const EVENT: &'static str = "DispatchedAs"; + impl ::subxt::ext::subxt_core::events::StaticEvent for FundsRecovered { + const PALLET: &'static str = "ReversibleTransfers"; + const EVENT: &'static str = "FundsRecovered"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7635,11 +7450,18 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Main call was dispatched."] - pub struct IfElseMainSuccess; - impl ::subxt::ext::subxt_core::events::StaticEvent for IfElseMainSuccess { - const PALLET: &'static str = "Utility"; - const EVENT: &'static str = "IfElseMainSuccess"; + #[doc = "Failed to release held funds during recovery. The transfer metadata is preserved"] + #[doc = "for manual retry via `cancel`."] + pub struct TransferRecoveryFailed { + pub tx_id: transfer_recovery_failed::TxId, + } + pub mod transfer_recovery_failed { + use super::runtime_types; + pub type TxId = ::subxt::ext::subxt_core::utils::H256; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for TransferRecoveryFailed { + const PALLET: &'static str = "ReversibleTransfers"; + const EVENT: &'static str = "TransferRecoveryFailed"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -7648,981 +7470,345 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The fallback call was dispatched."] - pub struct IfElseFallbackCalled { - pub main_error: if_else_fallback_called::MainError, + #[doc = "The final free-balance sweep of `recover_funds` failed. All pending-transfer"] + #[doc = "cancellations performed by the same call remain in effect; the guardian can"] + #[doc = "retry `recover_funds` to sweep the free balance once the cause is resolved."] + pub struct RecoverySweepFailed { + pub account: recovery_sweep_failed::Account, + pub guardian: recovery_sweep_failed::Guardian, } - pub mod if_else_fallback_called { + pub mod recovery_sweep_failed { use super::runtime_types; - pub type MainError = runtime_types::sp_runtime::DispatchError; + pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; } - impl ::subxt::ext::subxt_core::events::StaticEvent for IfElseFallbackCalled { - const PALLET: &'static str = "Utility"; - const EVENT: &'static str = "IfElseFallbackCalled"; + impl ::subxt::ext::subxt_core::events::StaticEvent for RecoverySweepFailed { + const PALLET: &'static str = "ReversibleTransfers"; + const EVENT: &'static str = "RecoverySweepFailed"; } } - pub mod constants { + pub mod storage { use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " The limit on the number of batched calls."] - pub fn batched_calls_limit( - &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u32, - > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "Utility", - "batched_calls_limit", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - } - } - } - pub mod reversible_transfers { - use super::{root_mod, runtime_types}; - #[doc = "The `Error` enum of this pallet."] - pub type Error = runtime_types::pallet_reversible_transfers::pallet::Error; - #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] - pub type Call = runtime_types::pallet_reversible_transfers::pallet::Call; - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; pub mod types { use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Enable high-security for the calling account with a specified"] - #[doc = "reversibility delay."] - #[doc = ""] - #[doc = "Once an account is set as high security it can only make reversible"] - #[doc = "transfers. It is not allowed any other calls."] - #[doc = ""] - #[doc = "# Warning: Permanent and Irreversible"] - #[doc = ""] - #[doc = "**Enabling high security mode is a one-way operation that cannot be undone.**"] - #[doc = ""] - #[doc = "Once this function is called successfully, the account is permanently restricted"] - #[doc = "to only the following operations:"] - #[doc = "- [`schedule_transfer`](Self::schedule_transfer) - Schedule delayed native token"] - #[doc = " transfers"] - #[doc = "- [`cancel`](Self::cancel) - Cancel pending transfers"] - #[doc = "- [`recover_funds`](Self::recover_funds) - Guardian-initiated emergency fund recovery"] - #[doc = ""] - #[doc = "There is no mechanism to disable high security mode or restore normal account"] - #[doc = "functionality. This design is intentional to provide maximum security guarantees:"] - #[doc = "an attacker who gains access to the account cannot simply disable the protections."] - #[doc = ""] - #[doc = "This permanence also ensures that any funds subsequently sent to a compromised"] - #[doc = "account (e.g., from pending payments, contracts, or accidental deposits) remain"] - #[doc = "protected and can be recovered by the guardian via"] - #[doc = "[`recover_funds`](Self::recover_funds). The guardian can call `recover_funds`"] - #[doc = "repeatedly as needed."] - #[doc = ""] - #[doc = "Users who no longer wish to use high-security features can simply transfer their"] - #[doc = "funds to a different account using [`schedule_transfer`](Self::schedule_transfer)."] - #[doc = ""] - #[doc = "# Parameters"] - #[doc = ""] - #[doc = "- `delay`: The reversibility time for any transfer made by the high-security account."] - #[doc = "- `guardian`: The guardian account that can cancel pending transfers and recover funds"] - #[doc = " from this high-security account."] - pub struct SetHighSecurity { - pub delay: set_high_security::Delay, - pub guardian: set_high_security::Guardian, - } - pub mod set_high_security { + pub mod high_security_accounts { use super::runtime_types; - pub type Delay = runtime_types::qp_scheduler::BlockNumberOrTimestamp< - ::core::primitive::u32, - ::core::primitive::u64, - >; - pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; + pub type HighSecurityAccounts = + runtime_types::pallet_reversible_transfers::HighSecurityAccountData< + ::subxt::ext::subxt_core::utils::AccountId32, + runtime_types::qp_scheduler::BlockNumberOrTimestamp< + ::core::primitive::u32, + ::core::primitive::u64, + >, + >; + pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetHighSecurity { - const PALLET: &'static str = "ReversibleTransfers"; - const CALL: &'static str = "set_high_security"; + pub mod high_security_tx_quota { + use super::runtime_types; + pub type HighSecurityTxQuota = + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u32, + >; + pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Cancel a pending reversible transaction scheduled by the caller."] - #[doc = ""] - #[doc = "- `tx_id`: The unique identifier of the transaction to cancel."] - pub struct Cancel { - pub tx_id: cancel::TxId, + pub mod pending_transfers { + use super::runtime_types; + pub type PendingTransfers = + runtime_types::pallet_reversible_transfers::PendingTransfer< + ::subxt::ext::subxt_core::utils::AccountId32, + ::core::primitive::u128, + ::core::primitive::u32, + >; + pub type Param0 = ::subxt::ext::subxt_core::utils::H256; } - pub mod cancel { + pub mod pending_transfers_by_sender { use super::runtime_types; - pub type TxId = ::subxt::ext::subxt_core::utils::H256; + pub type PendingTransfersBySender = + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::subxt::ext::subxt_core::utils::H256, + >; + pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Cancel { - const PALLET: &'static str = "ReversibleTransfers"; - const CALL: &'static str = "cancel"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Executes a previously scheduled transfer after the delay period has elapsed."] - #[doc = ""] - #[doc = "This extrinsic is called automatically by the Scheduler pallet when the"] - #[doc = "delay period expires. It must be signed by this pallet's account (not a user)."] - #[doc = "The pallet account is set as the origin when scheduling via"] - #[doc = "[`do_schedule_transfer_inner`](Self::do_schedule_transfer_inner)."] - #[doc = ""] - #[doc = "# Parameters"] - #[doc = ""] - #[doc = "- `tx_id`: The unique identifier of the pending transfer to execute."] - #[doc = ""] - #[doc = "# Errors"] - #[doc = ""] - #[doc = "- [`InvalidSchedulerOrigin`](Error::InvalidSchedulerOrigin): Called by an account other"] - #[doc = " than this pallet's account."] - #[doc = "- [`PendingTxNotFound`](Error::PendingTxNotFound): No pending transfer with this ID."] - pub struct ExecuteTransfer { - pub tx_id: execute_transfer::TxId, - } - pub mod execute_transfer { - use super::runtime_types; - pub type TxId = ::subxt::ext::subxt_core::utils::H256; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ExecuteTransfer { - const PALLET: &'static str = "ReversibleTransfers"; - const CALL: &'static str = "execute_transfer"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Schedule a transaction for delayed execution."] - pub struct ScheduleTransfer { - pub dest: schedule_transfer::Dest, - pub amount: schedule_transfer::Amount, - } - pub mod schedule_transfer { - use super::runtime_types; - pub type Dest = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - pub type Amount = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ScheduleTransfer { - const PALLET: &'static str = "ReversibleTransfers"; - const CALL: &'static str = "schedule_transfer"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Schedule a transaction for delayed execution with a custom, one-time delay."] - #[doc = ""] - #[doc = "This can only be used by accounts that have *not* set up a persistent"] - #[doc = "reversibility configuration with `set_high_security`."] - #[doc = ""] - #[doc = "- `delay`: The time (in blocks or milliseconds) before the transaction executes."] - pub struct ScheduleTransferWithDelay { - pub dest: schedule_transfer_with_delay::Dest, - pub amount: schedule_transfer_with_delay::Amount, - pub delay: schedule_transfer_with_delay::Delay, - } - pub mod schedule_transfer_with_delay { - use super::runtime_types; - pub type Dest = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - pub type Amount = ::core::primitive::u128; - pub type Delay = runtime_types::qp_scheduler::BlockNumberOrTimestamp< - ::core::primitive::u32, - ::core::primitive::u64, - >; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ScheduleTransferWithDelay { - const PALLET: &'static str = "ReversibleTransfers"; - const CALL: &'static str = "schedule_transfer_with_delay"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Allows the guardian to recover all funds from a high-security account"] - #[doc = "by transferring the entire balance to themselves."] - #[doc = ""] - #[doc = "This is an emergency function for when the high-security account may be compromised."] - #[doc = "It cancels all pending transfers first (applying volume fees), then transfers"] - #[doc = "the remaining free balance to the guardian."] - #[doc = ""] - #[doc = "# Cancel vs recovery authority"] - #[doc = ""] - #[doc = "Per-transfer `cancel` freezes authority in `pending.guardian` at schedule time"] - #[doc = "(so a later `set_high_security` cannot rewrite cancel rights on pre-enrollment"] - #[doc = "one-time transfers). `recover_funds` does **not** use that freeze: it authorizes"] - #[doc = "against the *live* high-security guardian and seizes every pending hold on the"] - #[doc = "account (volume fee applied). That asymmetry is intentional — recovery is"] - #[doc = "seize-the-account, not a batch of frozen cancel policies."] - #[doc = ""] - #[doc = "# Repeated Recovery"] - #[doc = ""] - #[doc = "This function can be called multiple times on the same account. The high-security"] - #[doc = "status and guardian relationship are intentionally preserved after recovery, ensuring"] - #[doc = "that any funds subsequently deposited to the account (e.g., from pending payments,"] - #[doc = "contracts, or accidental deposits) remain protected and recoverable."] - #[doc = ""] - #[doc = "# Error Handling"] - #[doc = ""] - #[doc = "If releasing held funds fails for any transfer, that transfer is skipped (metadata"] - #[doc = "preserved for manual retry via `cancel`) and a `TransferRecoveryFailed` event is"] - #[doc = "emitted. Other transfers continue to be processed."] - #[doc = ""] - #[doc = "The closing free-balance sweep to the guardian is likewise best-effort: if it"] - #[doc = "fails (e.g. the guardian cannot receive the funds), the call still succeeds and"] - #[doc = "all cancellations performed above remain in effect — they must not be rolled"] - #[doc = "back, or the pending transfers would be re-armed and execute at their scheduled"] - #[doc = "time. A `RecoverySweepFailed` event is emitted instead of `FundsRecovered`, and"] - #[doc = "the guardian can call `recover_funds` again to retry the sweep."] - pub struct RecoverFunds { - pub account: recover_funds::Account, - } - pub mod recover_funds { + pub mod next_transaction_id { use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for RecoverFunds { - const PALLET: &'static str = "ReversibleTransfers"; - const CALL: &'static str = "recover_funds"; + pub type NextTransactionId = ::core::primitive::u64; } } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Enable high-security for the calling account with a specified"] - #[doc = "reversibility delay."] - #[doc = ""] - #[doc = "Once an account is set as high security it can only make reversible"] - #[doc = "transfers. It is not allowed any other calls."] - #[doc = ""] - #[doc = "# Warning: Permanent and Irreversible"] - #[doc = ""] - #[doc = "**Enabling high security mode is a one-way operation that cannot be undone.**"] - #[doc = ""] - #[doc = "Once this function is called successfully, the account is permanently restricted"] - #[doc = "to only the following operations:"] - #[doc = "- [`schedule_transfer`](Self::schedule_transfer) - Schedule delayed native token"] - #[doc = " transfers"] - #[doc = "- [`cancel`](Self::cancel) - Cancel pending transfers"] - #[doc = "- [`recover_funds`](Self::recover_funds) - Guardian-initiated emergency fund recovery"] - #[doc = ""] - #[doc = "There is no mechanism to disable high security mode or restore normal account"] - #[doc = "functionality. This design is intentional to provide maximum security guarantees:"] - #[doc = "an attacker who gains access to the account cannot simply disable the protections."] - #[doc = ""] - #[doc = "This permanence also ensures that any funds subsequently sent to a compromised"] - #[doc = "account (e.g., from pending payments, contracts, or accidental deposits) remain"] - #[doc = "protected and can be recovered by the guardian via"] - #[doc = "[`recover_funds`](Self::recover_funds). The guardian can call `recover_funds`"] - #[doc = "repeatedly as needed."] - #[doc = ""] - #[doc = "Users who no longer wish to use high-security features can simply transfer their"] - #[doc = "funds to a different account using [`schedule_transfer`](Self::schedule_transfer)."] - #[doc = ""] - #[doc = "# Parameters"] - #[doc = ""] - #[doc = "- `delay`: The reversibility time for any transfer made by the high-security account."] - #[doc = "- `guardian`: The guardian account that can cancel pending transfers and recover funds"] - #[doc = " from this high-security account."] - pub fn set_high_security( + pub struct StorageApi; + impl StorageApi { + #[doc = " Maps accounts to their chosen reversibility delay period (in milliseconds)."] + #[doc = " Accounts present in this map have reversibility enabled."] + pub fn high_security_accounts_iter( &self, - delay: types::set_high_security::Delay, - guardian: types::set_high_security::Guardian, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::high_security_accounts::HighSecurityAccounts, + (), + (), + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( "ReversibleTransfers", - "set_high_security", - types::SetHighSecurity { delay, guardian }, + "HighSecurityAccounts", + (), [ - 103u8, 202u8, 28u8, 11u8, 249u8, 80u8, 142u8, 200u8, 55u8, 4u8, 141u8, - 72u8, 94u8, 199u8, 229u8, 102u8, 246u8, 113u8, 190u8, 84u8, 95u8, - 193u8, 96u8, 171u8, 144u8, 120u8, 235u8, 208u8, 65u8, 183u8, 4u8, 44u8, + 110u8, 63u8, 150u8, 254u8, 213u8, 163u8, 141u8, 156u8, 66u8, 201u8, + 162u8, 30u8, 141u8, 204u8, 209u8, 159u8, 120u8, 240u8, 230u8, 239u8, + 228u8, 129u8, 130u8, 181u8, 6u8, 193u8, 157u8, 239u8, 131u8, 35u8, + 29u8, 79u8, ], ) } - #[doc = "Cancel a pending reversible transaction scheduled by the caller."] - #[doc = ""] - #[doc = "- `tx_id`: The unique identifier of the transaction to cancel."] - pub fn cancel( + #[doc = " Maps accounts to their chosen reversibility delay period (in milliseconds)."] + #[doc = " Accounts present in this map have reversibility enabled."] + pub fn high_security_accounts( &self, - tx_id: types::cancel::TxId, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + _0: types::high_security_accounts::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::high_security_accounts::Param0, + >, + types::high_security_accounts::HighSecurityAccounts, + ::subxt::ext::subxt_core::utils::Yes, + (), + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( "ReversibleTransfers", - "cancel", - types::Cancel { tx_id }, + "HighSecurityAccounts", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 228u8, 150u8, 194u8, 119u8, 243u8, 126u8, 112u8, 227u8, 70u8, 160u8, - 132u8, 82u8, 146u8, 162u8, 195u8, 149u8, 236u8, 98u8, 18u8, 44u8, - 151u8, 249u8, 193u8, 176u8, 186u8, 98u8, 224u8, 103u8, 191u8, 165u8, - 37u8, 47u8, + 110u8, 63u8, 150u8, 254u8, 213u8, 163u8, 141u8, 156u8, 66u8, 201u8, + 162u8, 30u8, 141u8, 204u8, 209u8, 159u8, 120u8, 240u8, 230u8, 239u8, + 228u8, 129u8, 130u8, 181u8, 6u8, 193u8, 157u8, 239u8, 131u8, 35u8, + 29u8, 79u8, ], ) } - #[doc = "Executes a previously scheduled transfer after the delay period has elapsed."] - #[doc = ""] - #[doc = "This extrinsic is called automatically by the Scheduler pallet when the"] - #[doc = "delay period expires. It must be signed by this pallet's account (not a user)."] - #[doc = "The pallet account is set as the origin when scheduling via"] - #[doc = "[`do_schedule_transfer_inner`](Self::do_schedule_transfer_inner)."] - #[doc = ""] - #[doc = "# Parameters"] + #[doc = " Rolling window of included signed extrinsics for each high-security account."] #[doc = ""] - #[doc = "- `tx_id`: The unique identifier of the pending transfer to execute."] - #[doc = ""] - #[doc = "# Errors"] + #[doc = " Oldest block number is at index 0. Recording a tx is O(1): compare"] + #[doc = " `now - oldest` to [`Config::HighSecurityTxWindowBlocks`], maybe evict"] + #[doc = " that one head, then push. Normal accounts are not stored here."] + pub fn high_security_tx_quota_iter( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::high_security_tx_quota::HighSecurityTxQuota, + (), + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "ReversibleTransfers", + "HighSecurityTxQuota", + (), + [ + 39u8, 137u8, 109u8, 86u8, 121u8, 238u8, 179u8, 144u8, 120u8, 35u8, + 108u8, 28u8, 54u8, 170u8, 203u8, 187u8, 135u8, 61u8, 243u8, 93u8, + 165u8, 144u8, 225u8, 88u8, 204u8, 206u8, 35u8, 162u8, 16u8, 154u8, 6u8, + 79u8, + ], + ) + } + #[doc = " Rolling window of included signed extrinsics for each high-security account."] #[doc = ""] - #[doc = "- [`InvalidSchedulerOrigin`](Error::InvalidSchedulerOrigin): Called by an account other"] - #[doc = " than this pallet's account."] - #[doc = "- [`PendingTxNotFound`](Error::PendingTxNotFound): No pending transfer with this ID."] - pub fn execute_transfer( + #[doc = " Oldest block number is at index 0. Recording a tx is O(1): compare"] + #[doc = " `now - oldest` to [`Config::HighSecurityTxWindowBlocks`], maybe evict"] + #[doc = " that one head, then push. Normal accounts are not stored here."] + pub fn high_security_tx_quota( &self, - tx_id: types::execute_transfer::TxId, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + _0: types::high_security_tx_quota::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::high_security_tx_quota::Param0, + >, + types::high_security_tx_quota::HighSecurityTxQuota, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( "ReversibleTransfers", - "execute_transfer", - types::ExecuteTransfer { tx_id }, + "HighSecurityTxQuota", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 164u8, 38u8, 166u8, 81u8, 63u8, 235u8, 167u8, 178u8, 97u8, 80u8, 62u8, - 147u8, 3u8, 163u8, 129u8, 25u8, 98u8, 59u8, 17u8, 137u8, 6u8, 183u8, - 189u8, 51u8, 24u8, 211u8, 157u8, 108u8, 229u8, 253u8, 37u8, 78u8, + 39u8, 137u8, 109u8, 86u8, 121u8, 238u8, 179u8, 144u8, 120u8, 35u8, + 108u8, 28u8, 54u8, 170u8, 203u8, 187u8, 135u8, 61u8, 243u8, 93u8, + 165u8, 144u8, 225u8, 88u8, 204u8, 206u8, 35u8, 162u8, 16u8, 154u8, 6u8, + 79u8, ], ) } - #[doc = "Schedule a transaction for delayed execution."] - pub fn schedule_transfer( + #[doc = " Stores the details of pending transactions scheduled for delayed execution."] + #[doc = " Keyed by the unique transaction ID."] + pub fn pending_transfers_iter( &self, - dest: types::schedule_transfer::Dest, - amount: types::schedule_transfer::Amount, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::pending_transfers::PendingTransfers, + (), + (), + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( "ReversibleTransfers", - "schedule_transfer", - types::ScheduleTransfer { dest, amount }, + "PendingTransfers", + (), [ - 38u8, 219u8, 206u8, 56u8, 252u8, 195u8, 52u8, 74u8, 113u8, 125u8, - 107u8, 35u8, 236u8, 39u8, 31u8, 18u8, 250u8, 177u8, 174u8, 154u8, - 149u8, 122u8, 183u8, 50u8, 45u8, 111u8, 100u8, 249u8, 102u8, 82u8, - 72u8, 130u8, + 138u8, 155u8, 227u8, 133u8, 16u8, 122u8, 128u8, 60u8, 245u8, 159u8, + 244u8, 82u8, 244u8, 113u8, 189u8, 149u8, 179u8, 30u8, 48u8, 31u8, + 174u8, 124u8, 28u8, 33u8, 190u8, 217u8, 193u8, 129u8, 39u8, 122u8, + 141u8, 188u8, ], ) } - #[doc = "Schedule a transaction for delayed execution with a custom, one-time delay."] - #[doc = ""] - #[doc = "This can only be used by accounts that have *not* set up a persistent"] - #[doc = "reversibility configuration with `set_high_security`."] - #[doc = ""] - #[doc = "- `delay`: The time (in blocks or milliseconds) before the transaction executes."] - pub fn schedule_transfer_with_delay( + #[doc = " Stores the details of pending transactions scheduled for delayed execution."] + #[doc = " Keyed by the unique transaction ID."] + pub fn pending_transfers( &self, - dest: types::schedule_transfer_with_delay::Dest, - amount: types::schedule_transfer_with_delay::Amount, - delay: types::schedule_transfer_with_delay::Delay, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< - types::ScheduleTransferWithDelay, + _0: types::pending_transfers::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::pending_transfers::Param0, + >, + types::pending_transfers::PendingTransfers, + ::subxt::ext::subxt_core::utils::Yes, + (), + (), > { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( "ReversibleTransfers", - "schedule_transfer_with_delay", - types::ScheduleTransferWithDelay { dest, amount, delay }, + "PendingTransfers", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 254u8, 158u8, 173u8, 217u8, 107u8, 80u8, 229u8, 252u8, 123u8, 46u8, - 177u8, 40u8, 25u8, 15u8, 32u8, 22u8, 224u8, 52u8, 242u8, 48u8, 242u8, - 84u8, 242u8, 143u8, 111u8, 12u8, 82u8, 161u8, 129u8, 86u8, 161u8, - 216u8, + 138u8, 155u8, 227u8, 133u8, 16u8, 122u8, 128u8, 60u8, 245u8, 159u8, + 244u8, 82u8, 244u8, 113u8, 189u8, 149u8, 179u8, 30u8, 48u8, 31u8, + 174u8, 124u8, 28u8, 33u8, 190u8, 217u8, 193u8, 129u8, 39u8, 122u8, + 141u8, 188u8, ], ) } - #[doc = "Allows the guardian to recover all funds from a high-security account"] - #[doc = "by transferring the entire balance to themselves."] - #[doc = ""] - #[doc = "This is an emergency function for when the high-security account may be compromised."] - #[doc = "It cancels all pending transfers first (applying volume fees), then transfers"] - #[doc = "the remaining free balance to the guardian."] - #[doc = ""] - #[doc = "# Cancel vs recovery authority"] - #[doc = ""] - #[doc = "Per-transfer `cancel` freezes authority in `pending.guardian` at schedule time"] - #[doc = "(so a later `set_high_security` cannot rewrite cancel rights on pre-enrollment"] - #[doc = "one-time transfers). `recover_funds` does **not** use that freeze: it authorizes"] - #[doc = "against the *live* high-security guardian and seizes every pending hold on the"] - #[doc = "account (volume fee applied). That asymmetry is intentional — recovery is"] - #[doc = "seize-the-account, not a batch of frozen cancel policies."] - #[doc = ""] - #[doc = "# Repeated Recovery"] - #[doc = ""] - #[doc = "This function can be called multiple times on the same account. The high-security"] - #[doc = "status and guardian relationship are intentionally preserved after recovery, ensuring"] - #[doc = "that any funds subsequently deposited to the account (e.g., from pending payments,"] - #[doc = "contracts, or accidental deposits) remain protected and recoverable."] - #[doc = ""] - #[doc = "# Error Handling"] - #[doc = ""] - #[doc = "If releasing held funds fails for any transfer, that transfer is skipped (metadata"] - #[doc = "preserved for manual retry via `cancel`) and a `TransferRecoveryFailed` event is"] - #[doc = "emitted. Other transfers continue to be processed."] - #[doc = ""] - #[doc = "The closing free-balance sweep to the guardian is likewise best-effort: if it"] - #[doc = "fails (e.g. the guardian cannot receive the funds), the call still succeeds and"] - #[doc = "all cancellations performed above remain in effect — they must not be rolled"] - #[doc = "back, or the pending transfers would be re-armed and execute at their scheduled"] - #[doc = "time. A `RecoverySweepFailed` event is emitted instead of `FundsRecovered`, and"] - #[doc = "the guardian can call `recover_funds` again to retry the sweep."] - pub fn recover_funds( + #[doc = " Maps sender accounts to their list of pending transaction IDs."] + pub fn pending_transfers_by_sender_iter( &self, - account: types::recover_funds::Account, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::pending_transfers_by_sender::PendingTransfersBySender, + (), + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( "ReversibleTransfers", - "recover_funds", - types::RecoverFunds { account }, + "PendingTransfersBySender", + (), [ - 94u8, 241u8, 255u8, 110u8, 4u8, 169u8, 1u8, 45u8, 236u8, 88u8, 167u8, - 180u8, 240u8, 70u8, 111u8, 99u8, 185u8, 143u8, 153u8, 33u8, 101u8, - 30u8, 203u8, 103u8, 229u8, 39u8, 162u8, 76u8, 49u8, 125u8, 247u8, - 220u8, + 183u8, 43u8, 139u8, 203u8, 182u8, 219u8, 60u8, 129u8, 67u8, 30u8, 65u8, + 47u8, 105u8, 196u8, 228u8, 154u8, 26u8, 74u8, 84u8, 72u8, 154u8, 220u8, + 216u8, 134u8, 207u8, 240u8, 7u8, 190u8, 236u8, 242u8, 184u8, 224u8, + ], + ) + } + #[doc = " Maps sender accounts to their list of pending transaction IDs."] + pub fn pending_transfers_by_sender( + &self, + _0: types::pending_transfers_by_sender::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::pending_transfers_by_sender::Param0, + >, + types::pending_transfers_by_sender::PendingTransfersBySender, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "ReversibleTransfers", + "PendingTransfersBySender", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + [ + 183u8, 43u8, 139u8, 203u8, 182u8, 219u8, 60u8, 129u8, 67u8, 30u8, 65u8, + 47u8, 105u8, 196u8, 228u8, 154u8, 26u8, 74u8, 84u8, 72u8, 154u8, 220u8, + 216u8, 134u8, 207u8, 240u8, 7u8, 190u8, 236u8, 242u8, 184u8, 224u8, + ], + ) + } + #[doc = " Monotonically increasing counter used to generate unique transaction IDs."] + #[doc = " Each scheduled transfer increments this value to ensure no two transfers"] + #[doc = " produce the same `tx_id`, even if they have identical parameters."] + pub fn next_transaction_id( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::next_transaction_id::NextTransactionId, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "ReversibleTransfers", + "NextTransactionId", + (), + [ + 42u8, 56u8, 195u8, 140u8, 101u8, 56u8, 175u8, 152u8, 210u8, 167u8, + 61u8, 134u8, 152u8, 191u8, 216u8, 58u8, 73u8, 109u8, 130u8, 125u8, + 189u8, 186u8, 142u8, 68u8, 222u8, 141u8, 16u8, 250u8, 85u8, 8u8, 196u8, + 188u8, ], ) } } } - #[doc = "The `Event` enum of this pallet"] - pub type Event = runtime_types::pallet_reversible_transfers::pallet::Event; - pub mod events { + pub mod constants { use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A user has enabled their high-security settings."] - pub struct HighSecuritySet { - pub who: high_security_set::Who, - pub guardian: high_security_set::Guardian, - pub delay: high_security_set::Delay, - } - pub mod high_security_set { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Delay = runtime_types::qp_scheduler::BlockNumberOrTimestamp< - ::core::primitive::u32, - ::core::primitive::u64, - >; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for HighSecuritySet { - const PALLET: &'static str = "ReversibleTransfers"; - const EVENT: &'static str = "HighSecuritySet"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A transaction has been scheduled for delayed execution."] - pub struct TransactionScheduled { - pub from: transaction_scheduled::From, - pub to: transaction_scheduled::To, - pub guardian: transaction_scheduled::Guardian, - pub asset_id: transaction_scheduled::AssetId, - pub amount: transaction_scheduled::Amount, - pub tx_id: transaction_scheduled::TxId, - pub execute_at: transaction_scheduled::ExecuteAt, - } - pub mod transaction_scheduled { - use super::runtime_types; - pub type From = ::subxt::ext::subxt_core::utils::AccountId32; - pub type To = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; - pub type AssetId = ::core::option::Option<::core::primitive::u32>; - pub type Amount = ::core::primitive::u128; - pub type TxId = ::subxt::ext::subxt_core::utils::H256; - pub type ExecuteAt = runtime_types::qp_scheduler::DispatchTime< - ::core::primitive::u32, - ::core::primitive::u64, - >; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TransactionScheduled { - const PALLET: &'static str = "ReversibleTransfers"; - const EVENT: &'static str = "TransactionScheduled"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A scheduled transaction has been successfully cancelled."] - pub struct TransactionCancelled { - pub who: transaction_cancelled::Who, - pub tx_id: transaction_cancelled::TxId, - } - pub mod transaction_cancelled { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type TxId = ::subxt::ext::subxt_core::utils::H256; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TransactionCancelled { - const PALLET: &'static str = "ReversibleTransfers"; - const EVENT: &'static str = "TransactionCancelled"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A scheduled transaction was executed by the scheduler."] - pub struct TransactionExecuted { - pub tx_id: transaction_executed::TxId, - pub result: transaction_executed::Result, - } - pub mod transaction_executed { - use super::runtime_types; - pub type TxId = ::subxt::ext::subxt_core::utils::H256; - pub type Result = ::core::result::Result< - runtime_types::frame_support::dispatch::PostDispatchInfo, - runtime_types::sp_runtime::DispatchErrorWithPostInfo< - runtime_types::frame_support::dispatch::PostDispatchInfo, - >, - >; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TransactionExecuted { - const PALLET: &'static str = "ReversibleTransfers"; - const EVENT: &'static str = "TransactionExecuted"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "All funds were recovered from a high-security account by its guardian."] - pub struct FundsRecovered { - pub account: funds_recovered::Account, - pub guardian: funds_recovered::Guardian, - } - pub mod funds_recovered { - use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for FundsRecovered { - const PALLET: &'static str = "ReversibleTransfers"; - const EVENT: &'static str = "FundsRecovered"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Failed to release held funds during recovery. The transfer metadata is preserved"] - #[doc = "for manual retry via `cancel`."] - pub struct TransferRecoveryFailed { - pub tx_id: transfer_recovery_failed::TxId, - } - pub mod transfer_recovery_failed { - use super::runtime_types; - pub type TxId = ::subxt::ext::subxt_core::utils::H256; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TransferRecoveryFailed { - const PALLET: &'static str = "ReversibleTransfers"; - const EVENT: &'static str = "TransferRecoveryFailed"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The final free-balance sweep of `recover_funds` failed. All pending-transfer"] - #[doc = "cancellations performed by the same call remain in effect; the guardian can"] - #[doc = "retry `recover_funds` to sweep the free balance once the cause is resolved."] - pub struct RecoverySweepFailed { - pub account: recovery_sweep_failed::Account, - pub guardian: recovery_sweep_failed::Guardian, - } - pub mod recovery_sweep_failed { - use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Guardian = ::subxt::ext::subxt_core::utils::AccountId32; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for RecoverySweepFailed { - const PALLET: &'static str = "ReversibleTransfers"; - const EVENT: &'static str = "RecoverySweepFailed"; - } - } - pub mod storage { - use super::runtime_types; - pub mod types { - use super::runtime_types; - pub mod high_security_accounts { - use super::runtime_types; - pub type HighSecurityAccounts = - runtime_types::pallet_reversible_transfers::HighSecurityAccountData< - ::subxt::ext::subxt_core::utils::AccountId32, - runtime_types::qp_scheduler::BlockNumberOrTimestamp< - ::core::primitive::u32, - ::core::primitive::u64, - >, - >; - pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; - } - pub mod pending_transfers { - use super::runtime_types; - pub type PendingTransfers = - runtime_types::pallet_reversible_transfers::PendingTransfer< - ::subxt::ext::subxt_core::utils::AccountId32, - ::core::primitive::u128, - ::core::primitive::u32, - >; - pub type Param0 = ::subxt::ext::subxt_core::utils::H256; - } - pub mod pending_transfers_by_sender { - use super::runtime_types; - pub type PendingTransfersBySender = - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::subxt::ext::subxt_core::utils::H256, - >; - pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; - } - pub mod guardian_index { - use super::runtime_types; - pub type GuardianIndex = - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::subxt::ext::subxt_core::utils::AccountId32, - >; - pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; - } - pub mod next_transaction_id { - use super::runtime_types; - pub type NextTransactionId = ::core::primitive::u64; - } - } - pub struct StorageApi; - impl StorageApi { - #[doc = " Maps accounts to their chosen reversibility delay period (in milliseconds)."] - #[doc = " Accounts present in this map have reversibility enabled."] - pub fn high_security_accounts_iter( + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " Maximum pending reversible transactions allowed per account."] + pub fn max_pending_per_account( &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::high_security_accounts::HighSecurityAccounts, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( "ReversibleTransfers", - "HighSecurityAccounts", - (), + "MaxPendingPerAccount", [ - 110u8, 63u8, 150u8, 254u8, 213u8, 163u8, 141u8, 156u8, 66u8, 201u8, - 162u8, 30u8, 141u8, 204u8, 209u8, 159u8, 120u8, 240u8, 230u8, 239u8, - 228u8, 129u8, 130u8, 181u8, 6u8, 193u8, 157u8, 239u8, 131u8, 35u8, - 29u8, 79u8, + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, ], ) } - #[doc = " Maps accounts to their chosen reversibility delay period (in milliseconds)."] - #[doc = " Accounts present in this map have reversibility enabled."] - pub fn high_security_accounts( + #[doc = " Maximum signed extrinsics a high-security account may include in one"] + #[doc = " rolling window. Update of the quota ring is O(1)."] + pub fn max_high_security_txs_per_window( &self, - _0: types::high_security_accounts::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::high_security_accounts::Param0, - >, - types::high_security_accounts::HighSecurityAccounts, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( "ReversibleTransfers", - "HighSecurityAccounts", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + "MaxHighSecurityTxsPerWindow", [ - 110u8, 63u8, 150u8, 254u8, 213u8, 163u8, 141u8, 156u8, 66u8, 201u8, - 162u8, 30u8, 141u8, 204u8, 209u8, 159u8, 120u8, 240u8, 230u8, 239u8, - 228u8, 129u8, 130u8, 181u8, 6u8, 193u8, 157u8, 239u8, 131u8, 35u8, - 29u8, 79u8, + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, ], ) } - #[doc = " Stores the details of pending transactions scheduled for delayed execution."] - #[doc = " Keyed by the unique transaction ID."] - pub fn pending_transfers_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::pending_transfers::PendingTransfers, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "ReversibleTransfers", - "PendingTransfers", - (), - [ - 138u8, 155u8, 227u8, 133u8, 16u8, 122u8, 128u8, 60u8, 245u8, 159u8, - 244u8, 82u8, 244u8, 113u8, 189u8, 149u8, 179u8, 30u8, 48u8, 31u8, - 174u8, 124u8, 28u8, 33u8, 190u8, 217u8, 193u8, 129u8, 39u8, 122u8, - 141u8, 188u8, - ], - ) - } - #[doc = " Stores the details of pending transactions scheduled for delayed execution."] - #[doc = " Keyed by the unique transaction ID."] - pub fn pending_transfers( - &self, - _0: types::pending_transfers::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::pending_transfers::Param0, - >, - types::pending_transfers::PendingTransfers, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "ReversibleTransfers", - "PendingTransfers", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 138u8, 155u8, 227u8, 133u8, 16u8, 122u8, 128u8, 60u8, 245u8, 159u8, - 244u8, 82u8, 244u8, 113u8, 189u8, 149u8, 179u8, 30u8, 48u8, 31u8, - 174u8, 124u8, 28u8, 33u8, 190u8, 217u8, 193u8, 129u8, 39u8, 122u8, - 141u8, 188u8, - ], - ) - } - #[doc = " Maps sender accounts to their list of pending transaction IDs."] - pub fn pending_transfers_by_sender_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::pending_transfers_by_sender::PendingTransfersBySender, - (), - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "ReversibleTransfers", - "PendingTransfersBySender", - (), - [ - 183u8, 43u8, 139u8, 203u8, 182u8, 219u8, 60u8, 129u8, 67u8, 30u8, 65u8, - 47u8, 105u8, 196u8, 228u8, 154u8, 26u8, 74u8, 84u8, 72u8, 154u8, 220u8, - 216u8, 134u8, 207u8, 240u8, 7u8, 190u8, 236u8, 242u8, 184u8, 224u8, - ], - ) - } - #[doc = " Maps sender accounts to their list of pending transaction IDs."] - pub fn pending_transfers_by_sender( - &self, - _0: types::pending_transfers_by_sender::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::pending_transfers_by_sender::Param0, - >, - types::pending_transfers_by_sender::PendingTransfersBySender, - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "ReversibleTransfers", - "PendingTransfersBySender", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 183u8, 43u8, 139u8, 203u8, 182u8, 219u8, 60u8, 129u8, 67u8, 30u8, 65u8, - 47u8, 105u8, 196u8, 228u8, 154u8, 26u8, 74u8, 84u8, 72u8, 154u8, 220u8, - 216u8, 134u8, 207u8, 240u8, 7u8, 190u8, 236u8, 242u8, 184u8, 224u8, - ], - ) - } - #[doc = " Maps guardian accounts to the list of accounts they protect."] - #[doc = " This allows the UI to efficiently query all accounts for which a given account is a"] - #[doc = " guardian."] - pub fn guardian_index_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::guardian_index::GuardianIndex, - (), - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "ReversibleTransfers", - "GuardianIndex", - (), - [ - 112u8, 32u8, 227u8, 175u8, 221u8, 116u8, 83u8, 105u8, 108u8, 132u8, - 254u8, 61u8, 178u8, 251u8, 179u8, 127u8, 14u8, 12u8, 144u8, 204u8, - 38u8, 98u8, 154u8, 10u8, 202u8, 254u8, 230u8, 126u8, 149u8, 161u8, - 13u8, 110u8, - ], - ) - } - #[doc = " Maps guardian accounts to the list of accounts they protect."] - #[doc = " This allows the UI to efficiently query all accounts for which a given account is a"] - #[doc = " guardian."] - pub fn guardian_index( - &self, - _0: types::guardian_index::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::guardian_index::Param0, - >, - types::guardian_index::GuardianIndex, - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "ReversibleTransfers", - "GuardianIndex", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 112u8, 32u8, 227u8, 175u8, 221u8, 116u8, 83u8, 105u8, 108u8, 132u8, - 254u8, 61u8, 178u8, 251u8, 179u8, 127u8, 14u8, 12u8, 144u8, 204u8, - 38u8, 98u8, 154u8, 10u8, 202u8, 254u8, 230u8, 126u8, 149u8, 161u8, - 13u8, 110u8, - ], - ) - } - #[doc = " Monotonically increasing counter used to generate unique transaction IDs."] - #[doc = " Each scheduled transfer increments this value to ensure no two transfers"] - #[doc = " produce the same `tx_id`, even if they have identical parameters."] - pub fn next_transaction_id( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::next_transaction_id::NextTransactionId, - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "ReversibleTransfers", - "NextTransactionId", - (), - [ - 42u8, 56u8, 195u8, 140u8, 101u8, 56u8, 175u8, 152u8, 210u8, 167u8, - 61u8, 134u8, 152u8, 191u8, 216u8, 58u8, 73u8, 109u8, 130u8, 125u8, - 189u8, 186u8, 142u8, 68u8, 222u8, 141u8, 16u8, 250u8, 85u8, 8u8, 196u8, - 188u8, - ], - ) - } - } - } - pub mod constants { - use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " Maximum number of accounts a single guardian can protect. Used for BoundedVec."] - pub fn max_guardian_accounts( - &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u32, - > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "ReversibleTransfers", - "MaxGuardianAccounts", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - #[doc = " Maximum pending reversible transactions allowed per account."] - pub fn max_pending_per_account( + #[doc = " Length of the high-security extrinsic quota window, in blocks."] + #[doc = " At the runtime's 12s target this is one day (`DAYS`)."] + pub fn high_security_tx_window_blocks( &self, ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< ::core::primitive::u32, > { ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( "ReversibleTransfers", - "MaxPendingPerAccount", + "HighSecurityTxWindowBlocks", [ 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, @@ -9126,1295 +8312,7 @@ pub mod api { #[doc = "The `Event` enum of this pallet"] pub type Event = runtime_types::pallet_ranked_collective::pallet::Event; pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A member `who` has been added."] - pub struct MemberAdded { - pub who: member_added::Who, - } - pub mod member_added { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for MemberAdded { - const PALLET: &'static str = "TechCollective"; - const EVENT: &'static str = "MemberAdded"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The member `who`se rank has been changed to the given `rank`."] - pub struct RankChanged { - pub who: rank_changed::Who, - pub rank: rank_changed::Rank, - } - pub mod rank_changed { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Rank = ::core::primitive::u16; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for RankChanged { - const PALLET: &'static str = "TechCollective"; - const EVENT: &'static str = "RankChanged"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The member `who` of given `rank` has been removed from the collective."] - pub struct MemberRemoved { - pub who: member_removed::Who, - pub rank: member_removed::Rank, - } - pub mod member_removed { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Rank = ::core::primitive::u16; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for MemberRemoved { - const PALLET: &'static str = "TechCollective"; - const EVENT: &'static str = "MemberRemoved"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The member `who` has voted for the `poll` with the given `vote` leading to an updated"] - #[doc = "`tally`."] - pub struct Voted { - pub who: voted::Who, - pub poll: voted::Poll, - pub vote: voted::Vote, - pub tally: voted::Tally, - } - pub mod voted { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Poll = ::core::primitive::u32; - pub type Vote = runtime_types::pallet_ranked_collective::VoteRecord; - pub type Tally = runtime_types::pallet_ranked_collective::Tally; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for Voted { - const PALLET: &'static str = "TechCollective"; - const EVENT: &'static str = "Voted"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The member `who` had their `AccountId` changed to `new_who`."] - pub struct MemberExchanged { - pub who: member_exchanged::Who, - pub new_who: member_exchanged::NewWho, - } - pub mod member_exchanged { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type NewWho = ::subxt::ext::subxt_core::utils::AccountId32; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for MemberExchanged { - const PALLET: &'static str = "TechCollective"; - const EVENT: &'static str = "MemberExchanged"; - } - } - pub mod storage { - use super::runtime_types; - pub mod types { - use super::runtime_types; - pub mod member_count { - use super::runtime_types; - pub type MemberCount = ::core::primitive::u32; - pub type Param0 = ::core::primitive::u16; - } - pub mod members { - use super::runtime_types; - pub type Members = runtime_types::pallet_ranked_collective::MemberRecord; - pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; - } - pub mod id_to_index { - use super::runtime_types; - pub type IdToIndex = ::core::primitive::u32; - pub type Param0 = ::core::primitive::u16; - pub type Param1 = ::subxt::ext::subxt_core::utils::AccountId32; - } - pub mod index_to_id { - use super::runtime_types; - pub type IndexToId = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Param0 = ::core::primitive::u16; - pub type Param1 = ::core::primitive::u32; - } - pub mod voting { - use super::runtime_types; - pub type Voting = runtime_types::pallet_ranked_collective::VoteRecord; - pub type Param0 = ::core::primitive::u32; - pub type Param1 = ::subxt::ext::subxt_core::utils::AccountId32; - } - pub mod voting_cleanup { - use super::runtime_types; - pub type VotingCleanup = - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >; - pub type Param0 = ::core::primitive::u32; - } - } - pub struct StorageApi; - impl StorageApi { - #[doc = " The number of members in the collective who have at least the rank according to the index"] - #[doc = " of the vec."] - pub fn member_count_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::member_count::MemberCount, - (), - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "MemberCount", - (), - [ - 0u8, 141u8, 66u8, 91u8, 155u8, 74u8, 17u8, 191u8, 143u8, 41u8, 231u8, - 56u8, 123u8, 219u8, 145u8, 27u8, 197u8, 62u8, 118u8, 237u8, 30u8, 7u8, - 107u8, 96u8, 95u8, 17u8, 242u8, 206u8, 246u8, 79u8, 53u8, 214u8, - ], - ) - } - #[doc = " The number of members in the collective who have at least the rank according to the index"] - #[doc = " of the vec."] - pub fn member_count( - &self, - _0: types::member_count::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::member_count::Param0, - >, - types::member_count::MemberCount, - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "MemberCount", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 0u8, 141u8, 66u8, 91u8, 155u8, 74u8, 17u8, 191u8, 143u8, 41u8, 231u8, - 56u8, 123u8, 219u8, 145u8, 27u8, 197u8, 62u8, 118u8, 237u8, 30u8, 7u8, - 107u8, 96u8, 95u8, 17u8, 242u8, 206u8, 246u8, 79u8, 53u8, 214u8, - ], - ) - } - #[doc = " The current members of the collective."] - pub fn members_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::members::Members, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "Members", - (), - [ - 101u8, 183u8, 36u8, 241u8, 67u8, 8u8, 252u8, 116u8, 110u8, 153u8, - 117u8, 210u8, 128u8, 80u8, 130u8, 163u8, 38u8, 76u8, 230u8, 107u8, - 112u8, 90u8, 102u8, 24u8, 217u8, 2u8, 244u8, 197u8, 103u8, 215u8, - 247u8, 133u8, - ], - ) - } - #[doc = " The current members of the collective."] - pub fn members( - &self, - _0: types::members::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::members::Param0, - >, - types::members::Members, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "Members", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 101u8, 183u8, 36u8, 241u8, 67u8, 8u8, 252u8, 116u8, 110u8, 153u8, - 117u8, 210u8, 128u8, 80u8, 130u8, 163u8, 38u8, 76u8, 230u8, 107u8, - 112u8, 90u8, 102u8, 24u8, 217u8, 2u8, 244u8, 197u8, 103u8, 215u8, - 247u8, 133u8, - ], - ) - } - #[doc = " The index of each ranks's member into the group of members who have at least that rank."] - pub fn id_to_index_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::id_to_index::IdToIndex, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "IdToIndex", - (), - [ - 121u8, 225u8, 69u8, 131u8, 194u8, 3u8, 82u8, 27u8, 129u8, 152u8, 157u8, - 45u8, 39u8, 47u8, 166u8, 28u8, 42u8, 92u8, 217u8, 189u8, 160u8, 102u8, - 153u8, 196u8, 94u8, 48u8, 248u8, 113u8, 164u8, 111u8, 27u8, 9u8, - ], - ) - } - #[doc = " The index of each ranks's member into the group of members who have at least that rank."] - pub fn id_to_index_iter1( - &self, - _0: types::id_to_index::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::id_to_index::Param0, - >, - types::id_to_index::IdToIndex, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "IdToIndex", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 121u8, 225u8, 69u8, 131u8, 194u8, 3u8, 82u8, 27u8, 129u8, 152u8, 157u8, - 45u8, 39u8, 47u8, 166u8, 28u8, 42u8, 92u8, 217u8, 189u8, 160u8, 102u8, - 153u8, 196u8, 94u8, 48u8, 248u8, 113u8, 164u8, 111u8, 27u8, 9u8, - ], - ) - } - #[doc = " The index of each ranks's member into the group of members who have at least that rank."] - pub fn id_to_index( - &self, - _0: types::id_to_index::Param0, - _1: types::id_to_index::Param1, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ( - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::id_to_index::Param0, - >, - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::id_to_index::Param1, - >, - ), - types::id_to_index::IdToIndex, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "IdToIndex", - ( - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_1), - ), - [ - 121u8, 225u8, 69u8, 131u8, 194u8, 3u8, 82u8, 27u8, 129u8, 152u8, 157u8, - 45u8, 39u8, 47u8, 166u8, 28u8, 42u8, 92u8, 217u8, 189u8, 160u8, 102u8, - 153u8, 196u8, 94u8, 48u8, 248u8, 113u8, 164u8, 111u8, 27u8, 9u8, - ], - ) - } - #[doc = " The members in the collective by index. All indices in the range `0..MemberCount` will"] - #[doc = " return `Some`, however a member's index is not guaranteed to remain unchanged over time."] - pub fn index_to_id_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::index_to_id::IndexToId, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "IndexToId", - (), - [ - 110u8, 48u8, 214u8, 224u8, 56u8, 195u8, 186u8, 24u8, 111u8, 37u8, 15u8, - 153u8, 245u8, 101u8, 229u8, 149u8, 216u8, 185u8, 7u8, 242u8, 196u8, - 29u8, 205u8, 243u8, 162u8, 92u8, 71u8, 253u8, 102u8, 152u8, 137u8, - 70u8, - ], - ) - } - #[doc = " The members in the collective by index. All indices in the range `0..MemberCount` will"] - #[doc = " return `Some`, however a member's index is not guaranteed to remain unchanged over time."] - pub fn index_to_id_iter1( - &self, - _0: types::index_to_id::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::index_to_id::Param0, - >, - types::index_to_id::IndexToId, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "IndexToId", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 110u8, 48u8, 214u8, 224u8, 56u8, 195u8, 186u8, 24u8, 111u8, 37u8, 15u8, - 153u8, 245u8, 101u8, 229u8, 149u8, 216u8, 185u8, 7u8, 242u8, 196u8, - 29u8, 205u8, 243u8, 162u8, 92u8, 71u8, 253u8, 102u8, 152u8, 137u8, - 70u8, - ], - ) - } - #[doc = " The members in the collective by index. All indices in the range `0..MemberCount` will"] - #[doc = " return `Some`, however a member's index is not guaranteed to remain unchanged over time."] - pub fn index_to_id( - &self, - _0: types::index_to_id::Param0, - _1: types::index_to_id::Param1, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ( - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::index_to_id::Param0, - >, - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::index_to_id::Param1, - >, - ), - types::index_to_id::IndexToId, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "IndexToId", - ( - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_1), - ), - [ - 110u8, 48u8, 214u8, 224u8, 56u8, 195u8, 186u8, 24u8, 111u8, 37u8, 15u8, - 153u8, 245u8, 101u8, 229u8, 149u8, 216u8, 185u8, 7u8, 242u8, 196u8, - 29u8, 205u8, 243u8, 162u8, 92u8, 71u8, 253u8, 102u8, 152u8, 137u8, - 70u8, - ], - ) - } - #[doc = " Votes on a given proposal, if it is ongoing."] - pub fn voting_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::voting::Voting, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "Voting", - (), - [ - 180u8, 146u8, 236u8, 178u8, 30u8, 50u8, 161u8, 50u8, 140u8, 110u8, - 220u8, 1u8, 109u8, 209u8, 17u8, 94u8, 234u8, 223u8, 222u8, 177u8, - 243u8, 194u8, 246u8, 48u8, 178u8, 86u8, 30u8, 185u8, 56u8, 206u8, - 175u8, 18u8, - ], - ) - } - #[doc = " Votes on a given proposal, if it is ongoing."] - pub fn voting_iter1( - &self, - _0: types::voting::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::voting::Param0, - >, - types::voting::Voting, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "Voting", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 180u8, 146u8, 236u8, 178u8, 30u8, 50u8, 161u8, 50u8, 140u8, 110u8, - 220u8, 1u8, 109u8, 209u8, 17u8, 94u8, 234u8, 223u8, 222u8, 177u8, - 243u8, 194u8, 246u8, 48u8, 178u8, 86u8, 30u8, 185u8, 56u8, 206u8, - 175u8, 18u8, - ], - ) - } - #[doc = " Votes on a given proposal, if it is ongoing."] - pub fn voting( - &self, - _0: types::voting::Param0, - _1: types::voting::Param1, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ( - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::voting::Param0, - >, - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::voting::Param1, - >, - ), - types::voting::Voting, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "Voting", - ( - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_1), - ), - [ - 180u8, 146u8, 236u8, 178u8, 30u8, 50u8, 161u8, 50u8, 140u8, 110u8, - 220u8, 1u8, 109u8, 209u8, 17u8, 94u8, 234u8, 223u8, 222u8, 177u8, - 243u8, 194u8, 246u8, 48u8, 178u8, 86u8, 30u8, 185u8, 56u8, 206u8, - 175u8, 18u8, - ], - ) - } - pub fn voting_cleanup_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::voting_cleanup::VotingCleanup, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "VotingCleanup", - (), - [ - 223u8, 130u8, 79u8, 104u8, 94u8, 221u8, 222u8, 72u8, 187u8, 95u8, - 231u8, 59u8, 28u8, 119u8, 191u8, 63u8, 40u8, 186u8, 58u8, 254u8, 14u8, - 233u8, 152u8, 36u8, 2u8, 231u8, 120u8, 13u8, 120u8, 211u8, 232u8, 11u8, - ], - ) - } - pub fn voting_cleanup( - &self, - _0: types::voting_cleanup::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::voting_cleanup::Param0, - >, - types::voting_cleanup::VotingCleanup, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechCollective", - "VotingCleanup", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 223u8, 130u8, 79u8, 104u8, 94u8, 221u8, 222u8, 72u8, 187u8, 95u8, - 231u8, 59u8, 28u8, 119u8, 191u8, 63u8, 40u8, 186u8, 58u8, 254u8, 14u8, - 233u8, 152u8, 36u8, 2u8, 231u8, 120u8, 13u8, 120u8, 211u8, 232u8, 11u8, - ], - ) - } - } - } - } - pub mod tech_referenda { - use super::{root_mod, runtime_types}; - #[doc = "The `Error` enum of this pallet."] - pub type Error = runtime_types::pallet_referenda::pallet::Error; - #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] - pub type Call = runtime_types::pallet_referenda::pallet::Call; - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - pub mod types { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Propose a referendum on a privileged action."] - #[doc = ""] - #[doc = "- `origin`: must be `SubmitOrigin` and the account must have `SubmissionDeposit` funds"] - #[doc = " available."] - #[doc = "- `proposal_origin`: The origin from which the proposal should be executed."] - #[doc = "- `proposal`: The proposal."] - #[doc = "- `enactment_moment`: The moment that the proposal should be enacted."] - #[doc = ""] - #[doc = "Emits `Submitted`."] - pub struct Submit { - pub proposal_origin: - ::subxt::ext::subxt_core::alloc::boxed::Box, - pub proposal: submit::Proposal, - pub enactment_moment: submit::EnactmentMoment, - } - pub mod submit { - use super::runtime_types; - pub type ProposalOrigin = runtime_types::quantus_runtime::OriginCaller; - pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::quantus_runtime::RuntimeCall, - runtime_types::sp_runtime::traits::BlakeTwo256, - >; - pub type EnactmentMoment = - runtime_types::frame_support::traits::schedule::DispatchTime< - ::core::primitive::u32, - >; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Submit { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "submit"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Post the Decision Deposit for a referendum."] - #[doc = ""] - #[doc = "- `origin`: must be `Signed` and the account must have funds available for the"] - #[doc = " referendum's track's Decision Deposit."] - #[doc = "- `index`: The index of the submitted referendum whose Decision Deposit is yet to be"] - #[doc = " posted."] - #[doc = ""] - #[doc = "Emits `DecisionDepositPlaced`."] - pub struct PlaceDecisionDeposit { - pub index: place_decision_deposit::Index, - } - pub mod place_decision_deposit { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for PlaceDecisionDeposit { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "place_decision_deposit"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Refund the Decision Deposit for a closed referendum back to the depositor."] - #[doc = ""] - #[doc = "- `origin`: must be `Signed` or `Root`."] - #[doc = "- `index`: The index of a closed referendum whose Decision Deposit has not yet been"] - #[doc = " refunded."] - #[doc = ""] - #[doc = "Emits `DecisionDepositRefunded`."] - pub struct RefundDecisionDeposit { - pub index: refund_decision_deposit::Index, - } - pub mod refund_decision_deposit { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for RefundDecisionDeposit { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "refund_decision_deposit"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Cancel an ongoing referendum."] - #[doc = ""] - #[doc = "- `origin`: must be the `CancelOrigin`."] - #[doc = "- `index`: The index of the referendum to be cancelled."] - #[doc = ""] - #[doc = "Emits `Cancelled`."] - pub struct Cancel { - pub index: cancel::Index, - } - pub mod cancel { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Cancel { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "cancel"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Cancel an ongoing referendum and slash the deposits."] - #[doc = ""] - #[doc = "- `origin`: must be the `KillOrigin`."] - #[doc = "- `index`: The index of the referendum to be cancelled."] - #[doc = ""] - #[doc = "Emits `Killed` and `DepositSlashed`."] - pub struct Kill { - pub index: kill::Index, - } - pub mod kill { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Kill { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "kill"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Advance a referendum onto its next logical state. Only used internally."] - #[doc = ""] - #[doc = "- `origin`: must be `Root`."] - #[doc = "- `index`: the referendum to be advanced."] - pub struct NudgeReferendum { - pub index: nudge_referendum::Index, - } - pub mod nudge_referendum { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for NudgeReferendum { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "nudge_referendum"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Advance a track onto its next logical state. Only used internally."] - #[doc = ""] - #[doc = "- `origin`: must be `Root`."] - #[doc = "- `track`: the track to be advanced."] - #[doc = ""] - #[doc = "Action item for when there is now one fewer referendum in the deciding phase and the"] - #[doc = "`DecidingCount` is not yet updated. This means that we should either:"] - #[doc = "- begin deciding another referendum (and leave `DecidingCount` alone); or"] - #[doc = "- decrement `DecidingCount`."] - pub struct OneFewerDeciding { - pub track: one_fewer_deciding::Track, - } - pub mod one_fewer_deciding { - use super::runtime_types; - pub type Track = ::core::primitive::u16; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for OneFewerDeciding { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "one_fewer_deciding"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Refund the Submission Deposit for a closed referendum back to the depositor."] - #[doc = ""] - #[doc = "- `origin`: must be `Signed` or `Root`."] - #[doc = "- `index`: The index of a closed referendum whose Submission Deposit has not yet been"] - #[doc = " refunded."] - #[doc = ""] - #[doc = "Emits `SubmissionDepositRefunded`."] - pub struct RefundSubmissionDeposit { - pub index: refund_submission_deposit::Index, - } - pub mod refund_submission_deposit { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for RefundSubmissionDeposit { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "refund_submission_deposit"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Set or clear metadata of a referendum."] - #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `origin`: Must be `Signed` by a creator of a referendum or by anyone to clear a"] - #[doc = " metadata of a finished referendum."] - #[doc = "- `index`: The index of a referendum to set or clear metadata for."] - #[doc = "- `maybe_hash`: The hash of an on-chain stored preimage. `None` to clear a metadata."] - pub struct SetMetadata { - pub index: set_metadata::Index, - pub maybe_hash: set_metadata::MaybeHash, - } - pub mod set_metadata { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type MaybeHash = - ::core::option::Option<::subxt::ext::subxt_core::utils::H256>; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetMetadata { - const PALLET: &'static str = "TechReferenda"; - const CALL: &'static str = "set_metadata"; - } - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Propose a referendum on a privileged action."] - #[doc = ""] - #[doc = "- `origin`: must be `SubmitOrigin` and the account must have `SubmissionDeposit` funds"] - #[doc = " available."] - #[doc = "- `proposal_origin`: The origin from which the proposal should be executed."] - #[doc = "- `proposal`: The proposal."] - #[doc = "- `enactment_moment`: The moment that the proposal should be enacted."] - #[doc = ""] - #[doc = "Emits `Submitted`."] - pub fn submit( - &self, - proposal_origin: types::submit::ProposalOrigin, - proposal: types::submit::Proposal, - enactment_moment: types::submit::EnactmentMoment, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "submit", - types::Submit { - proposal_origin: ::subxt::ext::subxt_core::alloc::boxed::Box::new( - proposal_origin, - ), - proposal, - enactment_moment, - }, - [ - 0u8, 18u8, 14u8, 253u8, 33u8, 212u8, 33u8, 173u8, 241u8, 29u8, 88u8, - 160u8, 111u8, 21u8, 6u8, 234u8, 249u8, 230u8, 222u8, 119u8, 161u8, - 114u8, 43u8, 126u8, 164u8, 140u8, 199u8, 39u8, 2u8, 64u8, 132u8, 34u8, - ], - ) - } - #[doc = "Post the Decision Deposit for a referendum."] - #[doc = ""] - #[doc = "- `origin`: must be `Signed` and the account must have funds available for the"] - #[doc = " referendum's track's Decision Deposit."] - #[doc = "- `index`: The index of the submitted referendum whose Decision Deposit is yet to be"] - #[doc = " posted."] - #[doc = ""] - #[doc = "Emits `DecisionDepositPlaced`."] - pub fn place_decision_deposit( - &self, - index: types::place_decision_deposit::Index, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "place_decision_deposit", - types::PlaceDecisionDeposit { index }, - [ - 247u8, 158u8, 55u8, 191u8, 188u8, 200u8, 3u8, 47u8, 20u8, 175u8, 86u8, - 203u8, 52u8, 253u8, 91u8, 131u8, 21u8, 213u8, 56u8, 68u8, 40u8, 84u8, - 184u8, 30u8, 9u8, 193u8, 63u8, 182u8, 178u8, 241u8, 247u8, 220u8, - ], - ) - } - #[doc = "Refund the Decision Deposit for a closed referendum back to the depositor."] - #[doc = ""] - #[doc = "- `origin`: must be `Signed` or `Root`."] - #[doc = "- `index`: The index of a closed referendum whose Decision Deposit has not yet been"] - #[doc = " refunded."] - #[doc = ""] - #[doc = "Emits `DecisionDepositRefunded`."] - pub fn refund_decision_deposit( - &self, - index: types::refund_decision_deposit::Index, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< - types::RefundDecisionDeposit, - > { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "refund_decision_deposit", - types::RefundDecisionDeposit { index }, - [ - 159u8, 19u8, 35u8, 216u8, 114u8, 105u8, 18u8, 42u8, 148u8, 151u8, - 136u8, 92u8, 117u8, 30u8, 29u8, 41u8, 238u8, 58u8, 195u8, 91u8, 115u8, - 135u8, 96u8, 99u8, 154u8, 233u8, 8u8, 249u8, 145u8, 165u8, 77u8, 164u8, - ], - ) - } - #[doc = "Cancel an ongoing referendum."] - #[doc = ""] - #[doc = "- `origin`: must be the `CancelOrigin`."] - #[doc = "- `index`: The index of the referendum to be cancelled."] - #[doc = ""] - #[doc = "Emits `Cancelled`."] - pub fn cancel( - &self, - index: types::cancel::Index, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "cancel", - types::Cancel { index }, - [ - 55u8, 206u8, 119u8, 156u8, 238u8, 165u8, 193u8, 73u8, 242u8, 13u8, - 212u8, 75u8, 136u8, 156u8, 151u8, 14u8, 35u8, 41u8, 156u8, 107u8, 60u8, - 190u8, 39u8, 216u8, 8u8, 74u8, 213u8, 130u8, 160u8, 131u8, 237u8, - 122u8, - ], - ) - } - #[doc = "Cancel an ongoing referendum and slash the deposits."] - #[doc = ""] - #[doc = "- `origin`: must be the `KillOrigin`."] - #[doc = "- `index`: The index of the referendum to be cancelled."] - #[doc = ""] - #[doc = "Emits `Killed` and `DepositSlashed`."] - pub fn kill( - &self, - index: types::kill::Index, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "kill", - types::Kill { index }, - [ - 50u8, 89u8, 57u8, 0u8, 87u8, 129u8, 113u8, 140u8, 179u8, 178u8, 126u8, - 198u8, 92u8, 92u8, 189u8, 64u8, 123u8, 232u8, 57u8, 227u8, 223u8, - 219u8, 73u8, 217u8, 179u8, 44u8, 210u8, 125u8, 180u8, 10u8, 143u8, - 48u8, - ], - ) - } - #[doc = "Advance a referendum onto its next logical state. Only used internally."] - #[doc = ""] - #[doc = "- `origin`: must be `Root`."] - #[doc = "- `index`: the referendum to be advanced."] - pub fn nudge_referendum( - &self, - index: types::nudge_referendum::Index, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "nudge_referendum", - types::NudgeReferendum { index }, - [ - 75u8, 99u8, 172u8, 30u8, 170u8, 150u8, 211u8, 229u8, 249u8, 128u8, - 194u8, 246u8, 100u8, 142u8, 193u8, 184u8, 232u8, 81u8, 29u8, 17u8, - 99u8, 91u8, 236u8, 85u8, 230u8, 226u8, 57u8, 115u8, 45u8, 170u8, 54u8, - 213u8, - ], - ) - } - #[doc = "Advance a track onto its next logical state. Only used internally."] - #[doc = ""] - #[doc = "- `origin`: must be `Root`."] - #[doc = "- `track`: the track to be advanced."] - #[doc = ""] - #[doc = "Action item for when there is now one fewer referendum in the deciding phase and the"] - #[doc = "`DecidingCount` is not yet updated. This means that we should either:"] - #[doc = "- begin deciding another referendum (and leave `DecidingCount` alone); or"] - #[doc = "- decrement `DecidingCount`."] - pub fn one_fewer_deciding( - &self, - track: types::one_fewer_deciding::Track, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "one_fewer_deciding", - types::OneFewerDeciding { track }, - [ - 15u8, 84u8, 79u8, 231u8, 21u8, 239u8, 244u8, 143u8, 183u8, 215u8, - 181u8, 25u8, 225u8, 195u8, 95u8, 171u8, 17u8, 156u8, 182u8, 128u8, - 111u8, 40u8, 151u8, 102u8, 196u8, 55u8, 36u8, 212u8, 89u8, 190u8, - 131u8, 167u8, - ], - ) - } - #[doc = "Refund the Submission Deposit for a closed referendum back to the depositor."] - #[doc = ""] - #[doc = "- `origin`: must be `Signed` or `Root`."] - #[doc = "- `index`: The index of a closed referendum whose Submission Deposit has not yet been"] - #[doc = " refunded."] - #[doc = ""] - #[doc = "Emits `SubmissionDepositRefunded`."] - pub fn refund_submission_deposit( - &self, - index: types::refund_submission_deposit::Index, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< - types::RefundSubmissionDeposit, - > { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "refund_submission_deposit", - types::RefundSubmissionDeposit { index }, - [ - 20u8, 217u8, 115u8, 6u8, 1u8, 60u8, 54u8, 136u8, 35u8, 41u8, 38u8, - 23u8, 85u8, 100u8, 141u8, 126u8, 30u8, 160u8, 61u8, 46u8, 134u8, 98u8, - 82u8, 38u8, 211u8, 124u8, 208u8, 222u8, 210u8, 10u8, 155u8, 122u8, - ], - ) - } - #[doc = "Set or clear metadata of a referendum."] - #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `origin`: Must be `Signed` by a creator of a referendum or by anyone to clear a"] - #[doc = " metadata of a finished referendum."] - #[doc = "- `index`: The index of a referendum to set or clear metadata for."] - #[doc = "- `maybe_hash`: The hash of an on-chain stored preimage. `None` to clear a metadata."] - pub fn set_metadata( - &self, - index: types::set_metadata::Index, - maybe_hash: types::set_metadata::MaybeHash, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TechReferenda", - "set_metadata", - types::SetMetadata { index, maybe_hash }, - [ - 207u8, 29u8, 146u8, 233u8, 219u8, 205u8, 88u8, 118u8, 106u8, 61u8, - 124u8, 101u8, 2u8, 41u8, 169u8, 70u8, 114u8, 189u8, 162u8, 118u8, 1u8, - 108u8, 234u8, 98u8, 245u8, 245u8, 183u8, 126u8, 89u8, 13u8, 112u8, - 88u8, - ], - ) - } - } - } - #[doc = "The `Event` enum of this pallet"] - pub type Event = runtime_types::pallet_referenda::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A referendum has been submitted."] - pub struct Submitted { - pub index: submitted::Index, - pub track: submitted::Track, - pub proposal: submitted::Proposal, - } - pub mod submitted { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Track = ::core::primitive::u16; - pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::quantus_runtime::RuntimeCall, - runtime_types::sp_runtime::traits::BlakeTwo256, - >; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for Submitted { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "Submitted"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The decision deposit has been placed."] - pub struct DecisionDepositPlaced { - pub index: decision_deposit_placed::Index, - pub who: decision_deposit_placed::Who, - pub amount: decision_deposit_placed::Amount, - } - pub mod decision_deposit_placed { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Amount = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for DecisionDepositPlaced { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "DecisionDepositPlaced"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The decision deposit has been refunded."] - pub struct DecisionDepositRefunded { - pub index: decision_deposit_refunded::Index, - pub who: decision_deposit_refunded::Who, - pub amount: decision_deposit_refunded::Amount, - } - pub mod decision_deposit_refunded { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Amount = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for DecisionDepositRefunded { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "DecisionDepositRefunded"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A deposit has been slashed."] - pub struct DepositSlashed { - pub who: deposit_slashed::Who, - pub amount: deposit_slashed::Amount, - } - pub mod deposit_slashed { - use super::runtime_types; - pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Amount = ::core::primitive::u128; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for DepositSlashed { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "DepositSlashed"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A referendum has moved into the deciding phase."] - pub struct DecisionStarted { - pub index: decision_started::Index, - pub track: decision_started::Track, - pub proposal: decision_started::Proposal, - pub tally: decision_started::Tally, - } - pub mod decision_started { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Track = ::core::primitive::u16; - pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::quantus_runtime::RuntimeCall, - runtime_types::sp_runtime::traits::BlakeTwo256, - >; - pub type Tally = runtime_types::pallet_ranked_collective::Tally; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for DecisionStarted { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "DecisionStarted"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct ConfirmStarted { - pub index: confirm_started::Index, - } - pub mod confirm_started { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for ConfirmStarted { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "ConfirmStarted"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct ConfirmAborted { - pub index: confirm_aborted::Index, - } - pub mod confirm_aborted { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for ConfirmAborted { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "ConfirmAborted"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A referendum has ended its confirmation phase and is ready for approval."] - pub struct Confirmed { - pub index: confirmed::Index, - pub tally: confirmed::Tally, - } - pub mod confirmed { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Tally = runtime_types::pallet_ranked_collective::Tally; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for Confirmed { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "Confirmed"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A referendum has been approved and its proposal has been scheduled."] - pub struct Approved { - pub index: approved::Index, - } - pub mod approved { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for Approved { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "Approved"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A proposal has been rejected by referendum."] - pub struct Rejected { - pub index: rejected::Index, - pub tally: rejected::Tally, - } - pub mod rejected { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Tally = runtime_types::pallet_ranked_collective::Tally; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for Rejected { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "Rejected"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A referendum has been timed out without being decided."] - pub struct TimedOut { - pub index: timed_out::Index, - pub tally: timed_out::Tally, - } - pub mod timed_out { - use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Tally = runtime_types::pallet_ranked_collective::Tally; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TimedOut { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "TimedOut"; - } + use super::runtime_types; #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, @@ -10422,19 +8320,17 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A referendum has been cancelled."] - pub struct Cancelled { - pub index: cancelled::Index, - pub tally: cancelled::Tally, + #[doc = "A member `who` has been added."] + pub struct MemberAdded { + pub who: member_added::Who, } - pub mod cancelled { + pub mod member_added { use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Tally = runtime_types::pallet_ranked_collective::Tally; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; } - impl ::subxt::ext::subxt_core::events::StaticEvent for Cancelled { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "Cancelled"; + impl ::subxt::ext::subxt_core::events::StaticEvent for MemberAdded { + const PALLET: &'static str = "TechCollective"; + const EVENT: &'static str = "MemberAdded"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -10443,19 +8339,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A referendum has been killed."] - pub struct Killed { - pub index: killed::Index, - pub tally: killed::Tally, + #[doc = "The member `who`se rank has been changed to the given `rank`."] + pub struct RankChanged { + pub who: rank_changed::Who, + pub rank: rank_changed::Rank, } - pub mod killed { + pub mod rank_changed { use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Tally = runtime_types::pallet_ranked_collective::Tally; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Rank = ::core::primitive::u16; } - impl ::subxt::ext::subxt_core::events::StaticEvent for Killed { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "Killed"; + impl ::subxt::ext::subxt_core::events::StaticEvent for RankChanged { + const PALLET: &'static str = "TechCollective"; + const EVENT: &'static str = "RankChanged"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -10464,21 +8360,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The submission deposit has been refunded."] - pub struct SubmissionDepositRefunded { - pub index: submission_deposit_refunded::Index, - pub who: submission_deposit_refunded::Who, - pub amount: submission_deposit_refunded::Amount, + #[doc = "The member `who` of given `rank` has been removed from the collective."] + pub struct MemberRemoved { + pub who: member_removed::Who, + pub rank: member_removed::Rank, } - pub mod submission_deposit_refunded { + pub mod member_removed { use super::runtime_types; - pub type Index = ::core::primitive::u32; pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Amount = ::core::primitive::u128; + pub type Rank = ::core::primitive::u16; } - impl ::subxt::ext::subxt_core::events::StaticEvent for SubmissionDepositRefunded { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "SubmissionDepositRefunded"; + impl ::subxt::ext::subxt_core::events::StaticEvent for MemberRemoved { + const PALLET: &'static str = "TechCollective"; + const EVENT: &'static str = "MemberRemoved"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -10487,19 +8381,24 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Metadata for a referendum has been set."] - pub struct MetadataSet { - pub index: metadata_set::Index, - pub hash: metadata_set::Hash, + #[doc = "The member `who` has voted for the `poll` with the given `vote` leading to an updated"] + #[doc = "`tally`."] + pub struct Voted { + pub who: voted::Who, + pub poll: voted::Poll, + pub vote: voted::Vote, + pub tally: voted::Tally, } - pub mod metadata_set { + pub mod voted { use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Hash = ::subxt::ext::subxt_core::utils::H256; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Poll = ::core::primitive::u32; + pub type Vote = runtime_types::pallet_ranked_collective::VoteRecord; + pub type Tally = runtime_types::pallet_ranked_collective::Tally; } - impl ::subxt::ext::subxt_core::events::StaticEvent for MetadataSet { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "MetadataSet"; + impl ::subxt::ext::subxt_core::events::StaticEvent for Voted { + const PALLET: &'static str = "TechCollective"; + const EVENT: &'static str = "Voted"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -10508,629 +8407,453 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Metadata for a referendum has been cleared."] - pub struct MetadataCleared { - pub index: metadata_cleared::Index, - pub hash: metadata_cleared::Hash, + #[doc = "The member `who` had their `AccountId` changed to `new_who`."] + pub struct MemberExchanged { + pub who: member_exchanged::Who, + pub new_who: member_exchanged::NewWho, } - pub mod metadata_cleared { + pub mod member_exchanged { use super::runtime_types; - pub type Index = ::core::primitive::u32; - pub type Hash = ::subxt::ext::subxt_core::utils::H256; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type NewWho = ::subxt::ext::subxt_core::utils::AccountId32; } - impl ::subxt::ext::subxt_core::events::StaticEvent for MetadataCleared { - const PALLET: &'static str = "TechReferenda"; - const EVENT: &'static str = "MetadataCleared"; + impl ::subxt::ext::subxt_core::events::StaticEvent for MemberExchanged { + const PALLET: &'static str = "TechCollective"; + const EVENT: &'static str = "MemberExchanged"; } } pub mod storage { use super::runtime_types; pub mod types { use super::runtime_types; - pub mod referendum_count { + pub mod member_count { use super::runtime_types; - pub type ReferendumCount = ::core::primitive::u32; + pub type MemberCount = ::core::primitive::u32; + pub type Param0 = ::core::primitive::u16; } - pub mod referendum_info_for { + pub mod members { use super::runtime_types; - pub type ReferendumInfoFor = - runtime_types::pallet_referenda::types::ReferendumInfo< - ::core::primitive::u16, - runtime_types::quantus_runtime::OriginCaller, - ::core::primitive::u32, - runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::quantus_runtime::RuntimeCall, - runtime_types::sp_runtime::traits::BlakeTwo256, - >, - ::core::primitive::u128, - runtime_types::pallet_ranked_collective::Tally, - ::subxt::ext::subxt_core::utils::AccountId32, - ( - runtime_types::qp_scheduler::BlockNumberOrTimestamp< - ::core::primitive::u32, - ::core::primitive::u64, - >, - ::core::primitive::u32, - ), - >; - pub type Param0 = ::core::primitive::u32; + pub type Members = runtime_types::pallet_ranked_collective::MemberRecord; + pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; } - pub mod track_queue { + pub mod id_to_index { use super::runtime_types; - pub type TrackQueue = - runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::core::primitive::u32, - ::core::primitive::u32, - )>; + pub type IdToIndex = ::core::primitive::u32; pub type Param0 = ::core::primitive::u16; + pub type Param1 = ::subxt::ext::subxt_core::utils::AccountId32; } - pub mod deciding_count { + pub mod index_to_id { use super::runtime_types; - pub type DecidingCount = ::core::primitive::u32; + pub type IndexToId = ::subxt::ext::subxt_core::utils::AccountId32; pub type Param0 = ::core::primitive::u16; + pub type Param1 = ::core::primitive::u32; } - pub mod metadata_of { + pub mod voting { use super::runtime_types; - pub type MetadataOf = ::subxt::ext::subxt_core::utils::H256; + pub type Voting = runtime_types::pallet_ranked_collective::VoteRecord; + pub type Param0 = ::core::primitive::u32; + pub type Param1 = ::subxt::ext::subxt_core::utils::AccountId32; + } + pub mod voting_cleanup { + use super::runtime_types; + pub type VotingCleanup = + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >; pub type Param0 = ::core::primitive::u32; } } pub struct StorageApi; impl StorageApi { - #[doc = " The next free referendum index, aka the number of referenda started so far."] - pub fn referendum_count( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::referendum_count::ReferendumCount, - ::subxt::ext::subxt_core::utils::Yes, - ::subxt::ext::subxt_core::utils::Yes, - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "ReferendumCount", - (), - [ - 64u8, 145u8, 232u8, 153u8, 121u8, 87u8, 128u8, 253u8, 170u8, 192u8, - 139u8, 18u8, 0u8, 33u8, 243u8, 11u8, 238u8, 222u8, 244u8, 5u8, 247u8, - 198u8, 149u8, 31u8, 122u8, 208u8, 86u8, 179u8, 166u8, 167u8, 93u8, - 67u8, - ], - ) - } - #[doc = " Information concerning any given referendum."] - pub fn referendum_info_for_iter( - &self, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::referendum_info_for::ReferendumInfoFor, - (), - (), - ::subxt::ext::subxt_core::utils::Yes, - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "ReferendumInfoFor", - (), - [ - 242u8, 125u8, 226u8, 99u8, 67u8, 226u8, 43u8, 159u8, 222u8, 238u8, - 72u8, 38u8, 45u8, 26u8, 95u8, 64u8, 141u8, 140u8, 37u8, 44u8, 101u8, - 67u8, 46u8, 66u8, 45u8, 93u8, 41u8, 156u8, 63u8, 59u8, 9u8, 29u8, - ], - ) - } - #[doc = " Information concerning any given referendum."] - pub fn referendum_info_for( - &self, - _0: types::referendum_info_for::Param0, - ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::referendum_info_for::Param0, - >, - types::referendum_info_for::ReferendumInfoFor, - ::subxt::ext::subxt_core::utils::Yes, - (), - (), - > { - ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "ReferendumInfoFor", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - [ - 242u8, 125u8, 226u8, 99u8, 67u8, 226u8, 43u8, 159u8, 222u8, 238u8, - 72u8, 38u8, 45u8, 26u8, 95u8, 64u8, 141u8, 140u8, 37u8, 44u8, 101u8, - 67u8, 46u8, 66u8, 45u8, 93u8, 41u8, 156u8, 63u8, 59u8, 9u8, 29u8, - ], - ) - } - #[doc = " The sorted list of referenda ready to be decided but not yet being decided, ordered by"] - #[doc = " conviction-weighted approvals."] - #[doc = ""] - #[doc = " This should be empty if `DecidingCount` is less than `TrackInfo::max_deciding`."] - pub fn track_queue_iter( + #[doc = " The number of members in the collective who have at least the rank according to the index"] + #[doc = " of the vec."] + pub fn member_count_iter( &self, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< (), - types::track_queue::TrackQueue, + types::member_count::MemberCount, (), ::subxt::ext::subxt_core::utils::Yes, ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "TrackQueue", + "TechCollective", + "MemberCount", (), [ - 187u8, 113u8, 225u8, 99u8, 159u8, 207u8, 182u8, 41u8, 116u8, 136u8, - 119u8, 196u8, 152u8, 50u8, 192u8, 22u8, 171u8, 182u8, 237u8, 228u8, - 80u8, 255u8, 227u8, 141u8, 155u8, 83u8, 71u8, 131u8, 118u8, 109u8, - 186u8, 65u8, + 0u8, 141u8, 66u8, 91u8, 155u8, 74u8, 17u8, 191u8, 143u8, 41u8, 231u8, + 56u8, 123u8, 219u8, 145u8, 27u8, 197u8, 62u8, 118u8, 237u8, 30u8, 7u8, + 107u8, 96u8, 95u8, 17u8, 242u8, 206u8, 246u8, 79u8, 53u8, 214u8, ], - ) - } - #[doc = " The sorted list of referenda ready to be decided but not yet being decided, ordered by"] - #[doc = " conviction-weighted approvals."] - #[doc = ""] - #[doc = " This should be empty if `DecidingCount` is less than `TrackInfo::max_deciding`."] - pub fn track_queue( + ) + } + #[doc = " The number of members in the collective who have at least the rank according to the index"] + #[doc = " of the vec."] + pub fn member_count( &self, - _0: types::track_queue::Param0, + _0: types::member_count::Param0, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::track_queue::Param0, + types::member_count::Param0, >, - types::track_queue::TrackQueue, + types::member_count::MemberCount, ::subxt::ext::subxt_core::utils::Yes, ::subxt::ext::subxt_core::utils::Yes, (), > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "TrackQueue", + "TechCollective", + "MemberCount", ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 187u8, 113u8, 225u8, 99u8, 159u8, 207u8, 182u8, 41u8, 116u8, 136u8, - 119u8, 196u8, 152u8, 50u8, 192u8, 22u8, 171u8, 182u8, 237u8, 228u8, - 80u8, 255u8, 227u8, 141u8, 155u8, 83u8, 71u8, 131u8, 118u8, 109u8, - 186u8, 65u8, + 0u8, 141u8, 66u8, 91u8, 155u8, 74u8, 17u8, 191u8, 143u8, 41u8, 231u8, + 56u8, 123u8, 219u8, 145u8, 27u8, 197u8, 62u8, 118u8, 237u8, 30u8, 7u8, + 107u8, 96u8, 95u8, 17u8, 242u8, 206u8, 246u8, 79u8, 53u8, 214u8, ], ) } - #[doc = " The number of referenda being decided currently."] - pub fn deciding_count_iter( + #[doc = " The current members of the collective."] + pub fn members_iter( &self, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< (), - types::deciding_count::DecidingCount, + types::members::Members, + (), (), - ::subxt::ext::subxt_core::utils::Yes, ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "DecidingCount", + "TechCollective", + "Members", (), [ - 203u8, 89u8, 158u8, 179u8, 194u8, 82u8, 248u8, 162u8, 93u8, 140u8, - 146u8, 51u8, 110u8, 232u8, 51u8, 1u8, 128u8, 212u8, 199u8, 14u8, 182u8, - 103u8, 47u8, 252u8, 126u8, 108u8, 166u8, 69u8, 252u8, 179u8, 126u8, - 245u8, + 101u8, 183u8, 36u8, 241u8, 67u8, 8u8, 252u8, 116u8, 110u8, 153u8, + 117u8, 210u8, 128u8, 80u8, 130u8, 163u8, 38u8, 76u8, 230u8, 107u8, + 112u8, 90u8, 102u8, 24u8, 217u8, 2u8, 244u8, 197u8, 103u8, 215u8, + 247u8, 133u8, ], ) } - #[doc = " The number of referenda being decided currently."] - pub fn deciding_count( + #[doc = " The current members of the collective."] + pub fn members( &self, - _0: types::deciding_count::Param0, + _0: types::members::Param0, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::deciding_count::Param0, + types::members::Param0, >, - types::deciding_count::DecidingCount, - ::subxt::ext::subxt_core::utils::Yes, + types::members::Members, ::subxt::ext::subxt_core::utils::Yes, (), + (), > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "DecidingCount", + "TechCollective", + "Members", ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 203u8, 89u8, 158u8, 179u8, 194u8, 82u8, 248u8, 162u8, 93u8, 140u8, - 146u8, 51u8, 110u8, 232u8, 51u8, 1u8, 128u8, 212u8, 199u8, 14u8, 182u8, - 103u8, 47u8, 252u8, 126u8, 108u8, 166u8, 69u8, 252u8, 179u8, 126u8, - 245u8, + 101u8, 183u8, 36u8, 241u8, 67u8, 8u8, 252u8, 116u8, 110u8, 153u8, + 117u8, 210u8, 128u8, 80u8, 130u8, 163u8, 38u8, 76u8, 230u8, 107u8, + 112u8, 90u8, 102u8, 24u8, 217u8, 2u8, 244u8, 197u8, 103u8, 215u8, + 247u8, 133u8, ], ) } - #[doc = " The metadata is a general information concerning the referendum."] - #[doc = " The `Hash` refers to the preimage of the `Preimages` provider which can be a JSON"] - #[doc = " dump or IPFS hash of a JSON file."] - #[doc = ""] - #[doc = " Consider a garbage collection for a metadata of finished referendums to `unrequest` (remove)"] - #[doc = " large preimages."] - pub fn metadata_of_iter( + #[doc = " The index of each ranks's member into the group of members who have at least that rank."] + pub fn id_to_index_iter( &self, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< (), - types::metadata_of::MetadataOf, + types::id_to_index::IdToIndex, (), (), ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "MetadataOf", + "TechCollective", + "IdToIndex", (), [ - 159u8, 250u8, 56u8, 189u8, 247u8, 165u8, 206u8, 166u8, 91u8, 139u8, - 124u8, 164u8, 25u8, 246u8, 199u8, 36u8, 159u8, 56u8, 227u8, 136u8, 4u8, - 45u8, 193u8, 72u8, 200u8, 164u8, 39u8, 207u8, 224u8, 124u8, 191u8, - 110u8, + 121u8, 225u8, 69u8, 131u8, 194u8, 3u8, 82u8, 27u8, 129u8, 152u8, 157u8, + 45u8, 39u8, 47u8, 166u8, 28u8, 42u8, 92u8, 217u8, 189u8, 160u8, 102u8, + 153u8, 196u8, 94u8, 48u8, 248u8, 113u8, 164u8, 111u8, 27u8, 9u8, ], ) } - #[doc = " The metadata is a general information concerning the referendum."] - #[doc = " The `Hash` refers to the preimage of the `Preimages` provider which can be a JSON"] - #[doc = " dump or IPFS hash of a JSON file."] - #[doc = ""] - #[doc = " Consider a garbage collection for a metadata of finished referendums to `unrequest` (remove)"] - #[doc = " large preimages."] - pub fn metadata_of( + #[doc = " The index of each ranks's member into the group of members who have at least that rank."] + pub fn id_to_index_iter1( &self, - _0: types::metadata_of::Param0, + _0: types::id_to_index::Param0, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::metadata_of::Param0, + types::id_to_index::Param0, >, - types::metadata_of::MetadataOf, - ::subxt::ext::subxt_core::utils::Yes, + types::id_to_index::IdToIndex, (), (), + ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TechReferenda", - "MetadataOf", + "TechCollective", + "IdToIndex", ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 159u8, 250u8, 56u8, 189u8, 247u8, 165u8, 206u8, 166u8, 91u8, 139u8, - 124u8, 164u8, 25u8, 246u8, 199u8, 36u8, 159u8, 56u8, 227u8, 136u8, 4u8, - 45u8, 193u8, 72u8, 200u8, 164u8, 39u8, 207u8, 224u8, 124u8, 191u8, - 110u8, + 121u8, 225u8, 69u8, 131u8, 194u8, 3u8, 82u8, 27u8, 129u8, 152u8, 157u8, + 45u8, 39u8, 47u8, 166u8, 28u8, 42u8, 92u8, 217u8, 189u8, 160u8, 102u8, + 153u8, 196u8, 94u8, 48u8, 248u8, 113u8, 164u8, 111u8, 27u8, 9u8, ], ) } - } - } - pub mod constants { - use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " The minimum amount to be used as a deposit for a public referendum proposal."] - pub fn submission_deposit( + #[doc = " The index of each ranks's member into the group of members who have at least that rank."] + pub fn id_to_index( &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u128, + _0: types::id_to_index::Param0, + _1: types::id_to_index::Param1, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ( + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::id_to_index::Param0, + >, + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::id_to_index::Param1, + >, + ), + types::id_to_index::IdToIndex, + ::subxt::ext::subxt_core::utils::Yes, + (), + (), > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "TechReferenda", - "SubmissionDeposit", + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechCollective", + "IdToIndex", + ( + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_1), + ), [ - 84u8, 157u8, 140u8, 4u8, 93u8, 57u8, 29u8, 133u8, 105u8, 200u8, 214u8, - 27u8, 144u8, 208u8, 218u8, 160u8, 130u8, 109u8, 101u8, 54u8, 210u8, - 136u8, 71u8, 63u8, 49u8, 237u8, 234u8, 15u8, 178u8, 98u8, 148u8, 156u8, + 121u8, 225u8, 69u8, 131u8, 194u8, 3u8, 82u8, 27u8, 129u8, 152u8, 157u8, + 45u8, 39u8, 47u8, 166u8, 28u8, 42u8, 92u8, 217u8, 189u8, 160u8, 102u8, + 153u8, 196u8, 94u8, 48u8, 248u8, 113u8, 164u8, 111u8, 27u8, 9u8, ], ) } - #[doc = " Maximum size of the referendum queue for a single track."] - pub fn max_queued( + #[doc = " The members in the collective by index. All indices in the range `0..MemberCount` will"] + #[doc = " return `Some`, however a member's index is not guaranteed to remain unchanged over time."] + pub fn index_to_id_iter( &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u32, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::index_to_id::IndexToId, + (), + (), + ::subxt::ext::subxt_core::utils::Yes, > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "TechReferenda", - "MaxQueued", + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechCollective", + "IndexToId", + (), [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, + 110u8, 48u8, 214u8, 224u8, 56u8, 195u8, 186u8, 24u8, 111u8, 37u8, 15u8, + 153u8, 245u8, 101u8, 229u8, 149u8, 216u8, 185u8, 7u8, 242u8, 196u8, + 29u8, 205u8, 243u8, 162u8, 92u8, 71u8, 253u8, 102u8, 152u8, 137u8, + 70u8, ], ) } - #[doc = " The number of blocks after submission that a referendum must begin being decided by."] - #[doc = " Once this passes, then anyone may cancel the referendum."] - pub fn undeciding_timeout( + #[doc = " The members in the collective by index. All indices in the range `0..MemberCount` will"] + #[doc = " return `Some`, however a member's index is not guaranteed to remain unchanged over time."] + pub fn index_to_id_iter1( &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u32, + _0: types::index_to_id::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::index_to_id::Param0, + >, + types::index_to_id::IndexToId, + (), + (), + ::subxt::ext::subxt_core::utils::Yes, > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "TechReferenda", - "UndecidingTimeout", + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechCollective", + "IndexToId", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, + 110u8, 48u8, 214u8, 224u8, 56u8, 195u8, 186u8, 24u8, 111u8, 37u8, 15u8, + 153u8, 245u8, 101u8, 229u8, 149u8, 216u8, 185u8, 7u8, 242u8, 196u8, + 29u8, 205u8, 243u8, 162u8, 92u8, 71u8, 253u8, 102u8, 152u8, 137u8, + 70u8, ], ) } - #[doc = " Quantization level for the referendum wakeup scheduler. A higher number will result in"] - #[doc = " fewer storage reads/writes needed for smaller voters, but also result in delays to the"] - #[doc = " automatic referendum status changes. Explicit servicing instructions are unaffected."] - pub fn alarm_interval( + #[doc = " The members in the collective by index. All indices in the range `0..MemberCount` will"] + #[doc = " return `Some`, however a member's index is not guaranteed to remain unchanged over time."] + pub fn index_to_id( &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u32, + _0: types::index_to_id::Param0, + _1: types::index_to_id::Param1, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ( + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::index_to_id::Param0, + >, + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::index_to_id::Param1, + >, + ), + types::index_to_id::IndexToId, + ::subxt::ext::subxt_core::utils::Yes, + (), + (), > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "TechReferenda", - "AlarmInterval", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechCollective", + "IndexToId", + ( + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_1), + ), + [ + 110u8, 48u8, 214u8, 224u8, 56u8, 195u8, 186u8, 24u8, 111u8, 37u8, 15u8, + 153u8, 245u8, 101u8, 229u8, 149u8, 216u8, 185u8, 7u8, 242u8, 196u8, + 29u8, 205u8, 243u8, 162u8, 92u8, 71u8, 253u8, 102u8, 152u8, 137u8, + 70u8, ], ) } - #[doc = " A list of tracks."] - #[doc = ""] - #[doc = " Note: if the tracks are dynamic, the value in the static metadata might be inaccurate."] - pub fn tracks( + #[doc = " Votes on a given proposal, if it is ongoing."] + pub fn voting_iter( &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::subxt::ext::subxt_core::alloc::vec::Vec<( - ::core::primitive::u16, - runtime_types::pallet_referenda::types::TrackDetails< - ::core::primitive::u128, - ::core::primitive::u32, - ::subxt::ext::subxt_core::alloc::string::String, - >, - )>, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::voting::Voting, + (), + (), + ::subxt::ext::subxt_core::utils::Yes, > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "TechReferenda", - "Tracks", + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechCollective", + "Voting", + (), [ - 35u8, 226u8, 207u8, 234u8, 184u8, 139u8, 187u8, 184u8, 128u8, 199u8, - 227u8, 15u8, 31u8, 196u8, 5u8, 207u8, 138u8, 174u8, 130u8, 201u8, - 200u8, 113u8, 86u8, 93u8, 221u8, 243u8, 229u8, 24u8, 18u8, 150u8, 56u8, - 159u8, + 180u8, 146u8, 236u8, 178u8, 30u8, 50u8, 161u8, 50u8, 140u8, 110u8, + 220u8, 1u8, 109u8, 209u8, 17u8, 94u8, 234u8, 223u8, 222u8, 177u8, + 243u8, 194u8, 246u8, 48u8, 178u8, 86u8, 30u8, 185u8, 56u8, 206u8, + 175u8, 18u8, ], ) } - } - } - } - pub mod treasury_pallet { - use super::{root_mod, runtime_types}; - #[doc = "The `Error` enum of this pallet."] - pub type Error = runtime_types::pallet_treasury::pallet::Error; - #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] - pub type Call = runtime_types::pallet_treasury::pallet::Call; - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - pub mod types { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Set the treasury account. Root only. Zero address is rejected (funds would be locked)."] - #[doc = ""] - #[doc = "**Important**: This only changes where *future* mining rewards are sent. Any balance"] - #[doc = "that has already accumulated in the current treasury account is NOT automatically"] - #[doc = "migrated to the new account. If you need to move existing funds, perform a separate"] - #[doc = "balance transfer (e.g., via governance proposal) after updating the account."] - pub struct SetTreasuryAccount { - pub account: set_treasury_account::Account, - } - pub mod set_treasury_account { - use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetTreasuryAccount { - const PALLET: &'static str = "TreasuryPallet"; - const CALL: &'static str = "set_treasury_account"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Set the treasury portion (Permill, 0–100%). Root only."] - pub struct SetTreasuryPortion { - pub portion: set_treasury_portion::Portion, - } - pub mod set_treasury_portion { - use super::runtime_types; - pub type Portion = runtime_types::sp_arithmetic::per_things::Permill; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetTreasuryPortion { - const PALLET: &'static str = "TreasuryPallet"; - const CALL: &'static str = "set_treasury_portion"; - } - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Set the treasury account. Root only. Zero address is rejected (funds would be locked)."] - #[doc = ""] - #[doc = "**Important**: This only changes where *future* mining rewards are sent. Any balance"] - #[doc = "that has already accumulated in the current treasury account is NOT automatically"] - #[doc = "migrated to the new account. If you need to move existing funds, perform a separate"] - #[doc = "balance transfer (e.g., via governance proposal) after updating the account."] - pub fn set_treasury_account( + #[doc = " Votes on a given proposal, if it is ongoing."] + pub fn voting_iter1( &self, - account: types::set_treasury_account::Account, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TreasuryPallet", - "set_treasury_account", - types::SetTreasuryAccount { account }, + _0: types::voting::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::voting::Param0, + >, + types::voting::Voting, + (), + (), + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechCollective", + "Voting", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 221u8, 22u8, 186u8, 39u8, 76u8, 65u8, 143u8, 149u8, 126u8, 244u8, - 227u8, 129u8, 16u8, 183u8, 56u8, 248u8, 82u8, 131u8, 255u8, 246u8, - 243u8, 145u8, 255u8, 5u8, 125u8, 142u8, 201u8, 38u8, 185u8, 124u8, - 76u8, 167u8, + 180u8, 146u8, 236u8, 178u8, 30u8, 50u8, 161u8, 50u8, 140u8, 110u8, + 220u8, 1u8, 109u8, 209u8, 17u8, 94u8, 234u8, 223u8, 222u8, 177u8, + 243u8, 194u8, 246u8, 48u8, 178u8, 86u8, 30u8, 185u8, 56u8, 206u8, + 175u8, 18u8, ], ) } - #[doc = "Set the treasury portion (Permill, 0–100%). Root only."] - pub fn set_treasury_portion( + #[doc = " Votes on a given proposal, if it is ongoing."] + pub fn voting( &self, - portion: types::set_treasury_portion::Portion, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "TreasuryPallet", - "set_treasury_portion", - types::SetTreasuryPortion { portion }, + _0: types::voting::Param0, + _1: types::voting::Param1, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ( + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::voting::Param0, + >, + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::voting::Param1, + >, + ), + types::voting::Voting, + ::subxt::ext::subxt_core::utils::Yes, + (), + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechCollective", + "Voting", + ( + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_1), + ), [ - 226u8, 74u8, 96u8, 96u8, 120u8, 14u8, 29u8, 33u8, 85u8, 192u8, 26u8, - 67u8, 86u8, 203u8, 21u8, 96u8, 127u8, 87u8, 217u8, 185u8, 8u8, 68u8, - 126u8, 227u8, 38u8, 172u8, 9u8, 97u8, 172u8, 27u8, 17u8, 199u8, + 180u8, 146u8, 236u8, 178u8, 30u8, 50u8, 161u8, 50u8, 140u8, 110u8, + 220u8, 1u8, 109u8, 209u8, 17u8, 94u8, 234u8, 223u8, 222u8, 177u8, + 243u8, 194u8, 246u8, 48u8, 178u8, 86u8, 30u8, 185u8, 56u8, 206u8, + 175u8, 18u8, ], ) } - } - } - #[doc = "The `Event` enum of this pallet"] - pub type Event = runtime_types::pallet_treasury::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The treasury account was updated."] - #[doc = ""] - #[doc = "Note: This only redirects where future mining rewards are sent. Any balance"] - #[doc = "accumulated in the old account remains there and is NOT automatically migrated."] - #[doc = "Use a separate balance transfer if funds need to be moved."] - pub struct TreasuryAccountUpdated { - pub old_account: treasury_account_updated::OldAccount, - pub new_account: treasury_account_updated::NewAccount, - } - pub mod treasury_account_updated { - use super::runtime_types; - pub type OldAccount = - ::core::option::Option<::subxt::ext::subxt_core::utils::AccountId32>; - pub type NewAccount = ::subxt::ext::subxt_core::utils::AccountId32; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TreasuryAccountUpdated { - const PALLET: &'static str = "TreasuryPallet"; - const EVENT: &'static str = "TreasuryAccountUpdated"; - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "The treasury portion (share of mining rewards) was updated."] - pub struct TreasuryPortionUpdated { - pub new_portion: treasury_portion_updated::NewPortion, - } - pub mod treasury_portion_updated { - use super::runtime_types; - pub type NewPortion = runtime_types::sp_arithmetic::per_things::Permill; - } - impl ::subxt::ext::subxt_core::events::StaticEvent for TreasuryPortionUpdated { - const PALLET: &'static str = "TreasuryPallet"; - const EVENT: &'static str = "TreasuryPortionUpdated"; - } - } - pub mod storage { - use super::runtime_types; - pub mod types { - use super::runtime_types; - pub mod treasury_account { - use super::runtime_types; - pub type TreasuryAccount = ::subxt::ext::subxt_core::utils::AccountId32; - } - pub mod treasury_portion { - use super::runtime_types; - pub type TreasuryPortion = runtime_types::sp_arithmetic::per_things::Permill; - } - } - pub struct StorageApi; - impl StorageApi { - #[doc = " The treasury account that receives mining rewards."] - pub fn treasury_account( + pub fn voting_cleanup_iter( &self, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< (), - types::treasury_account::TreasuryAccount, - ::subxt::ext::subxt_core::utils::Yes, + types::voting_cleanup::VotingCleanup, (), (), + ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TreasuryPallet", - "TreasuryAccount", + "TechCollective", + "VotingCleanup", (), [ - 25u8, 40u8, 39u8, 114u8, 80u8, 247u8, 49u8, 5u8, 9u8, 118u8, 249u8, - 36u8, 77u8, 73u8, 229u8, 167u8, 107u8, 254u8, 175u8, 199u8, 203u8, - 238u8, 166u8, 158u8, 155u8, 209u8, 155u8, 219u8, 191u8, 204u8, 237u8, - 227u8, + 223u8, 130u8, 79u8, 104u8, 94u8, 221u8, 222u8, 72u8, 187u8, 95u8, + 231u8, 59u8, 28u8, 119u8, 191u8, 63u8, 40u8, 186u8, 58u8, 254u8, 14u8, + 233u8, 152u8, 36u8, 2u8, 231u8, 120u8, 13u8, 120u8, 211u8, 232u8, 11u8, ], ) } - #[doc = " The portion of mining rewards that goes to treasury (Permill, 0–100%)."] - #[doc = " Uses OptionQuery so genesis is required. Permill allows fine granularity (e.g. 33.3%)."] - pub fn treasury_portion( + pub fn voting_cleanup( &self, + _0: types::voting_cleanup::Param0, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - (), - types::treasury_portion::TreasuryPortion, + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::voting_cleanup::Param0, + >, + types::voting_cleanup::VotingCleanup, ::subxt::ext::subxt_core::utils::Yes, (), (), > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "TreasuryPallet", - "TreasuryPortion", - (), + "TechCollective", + "VotingCleanup", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 27u8, 148u8, 61u8, 76u8, 110u8, 174u8, 202u8, 184u8, 62u8, 134u8, - 238u8, 169u8, 40u8, 112u8, 83u8, 192u8, 156u8, 67u8, 1u8, 145u8, 11u8, - 88u8, 249u8, 1u8, 37u8, 163u8, 238u8, 131u8, 242u8, 232u8, 20u8, 195u8, + 223u8, 130u8, 79u8, 104u8, 94u8, 221u8, 222u8, 72u8, 187u8, 95u8, + 231u8, 59u8, 28u8, 119u8, 191u8, 63u8, 40u8, 186u8, 58u8, 254u8, 14u8, + 233u8, 152u8, 36u8, 2u8, 231u8, 120u8, 13u8, 120u8, 211u8, 232u8, 11u8, ], ) } } } } - pub mod recovery { + pub mod tech_referenda { use super::{root_mod, runtime_types}; #[doc = "The `Error` enum of this pallet."] - pub type Error = runtime_types::pallet_recovery::pallet::Error; + pub type Error = runtime_types::pallet_referenda::pallet::Error; #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] - pub type Call = runtime_types::pallet_recovery::pallet::Call; + pub type Call = runtime_types::pallet_referenda::pallet::Call; pub mod calls { use super::{root_mod, runtime_types}; type DispatchError = runtime_types::sp_runtime::DispatchError; @@ -11147,29 +8870,36 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Send a call through a recovered account."] + #[doc = "Propose a referendum on a privileged action."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and registered to"] - #[doc = "be able to make calls on behalf of the recovered account."] + #[doc = "- `origin`: must be `SubmitOrigin` and the account must have `SubmissionDeposit` funds"] + #[doc = " available."] + #[doc = "- `proposal_origin`: The origin from which the proposal should be executed."] + #[doc = "- `proposal`: The proposal."] + #[doc = "- `enactment_moment`: The moment that the proposal should be enacted."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The recovered account you want to make a call on-behalf-of."] - #[doc = "- `call`: The call you want to make with the recovered account."] - pub struct AsRecovered { - pub account: as_recovered::Account, - pub call: ::subxt::ext::subxt_core::alloc::boxed::Box, + #[doc = "Emits `Submitted`."] + pub struct Submit { + pub proposal_origin: + ::subxt::ext::subxt_core::alloc::boxed::Box, + pub proposal: submit::Proposal, + pub enactment_moment: submit::EnactmentMoment, } - pub mod as_recovered { + pub mod submit { use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), + pub type ProposalOrigin = runtime_types::quantus_runtime::OriginCaller; + pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::quantus_runtime::RuntimeCall, + runtime_types::sp_runtime::traits::BlakeTwo256, >; - pub type Call = runtime_types::quantus_runtime::RuntimeCall; + pub type EnactmentMoment = + runtime_types::frame_support::traits::schedule::DispatchTime< + ::core::primitive::u32, + >; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for AsRecovered { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "as_recovered"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Submit { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "submit"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11182,32 +8912,24 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Allow ROOT to bypass the recovery process and set a rescuer account"] - #[doc = "for a lost account directly."] + #[doc = "Post the Decision Deposit for a referendum."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _ROOT_."] + #[doc = "- `origin`: must be `Signed` and the account must have funds available for the"] + #[doc = " referendum's track's Decision Deposit."] + #[doc = "- `index`: The index of the submitted referendum whose Decision Deposit is yet to be"] + #[doc = " posted."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `lost`: The \"lost account\" to be recovered."] - #[doc = "- `rescuer`: The \"rescuer account\" which can call as the lost account."] - pub struct SetRecovered { - pub lost: set_recovered::Lost, - pub rescuer: set_recovered::Rescuer, + #[doc = "Emits `DecisionDepositPlaced`."] + pub struct PlaceDecisionDeposit { + pub index: place_decision_deposit::Index, } - pub mod set_recovered { + pub mod place_decision_deposit { use super::runtime_types; - pub type Lost = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - pub type Rescuer = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; + pub type Index = ::core::primitive::u32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetRecovered { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "set_recovered"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for PlaceDecisionDeposit { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "place_decision_deposit"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11220,38 +8942,23 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Create a recovery configuration for your account. This makes your account recoverable."] - #[doc = ""] - #[doc = "Payment: `ConfigDepositBase` + `FriendDepositFactor` * #_of_friends balance"] - #[doc = "will be reserved for storing the recovery configuration. This deposit is returned"] - #[doc = "in full when the user calls `remove_recovery`."] + #[doc = "Refund the Decision Deposit for a closed referendum back to the depositor."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = "- `origin`: must be `Signed` or `Root`."] + #[doc = "- `index`: The index of a closed referendum whose Decision Deposit has not yet been"] + #[doc = " refunded."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `friends`: A list of friends you trust to vouch for recovery attempts. Should be"] - #[doc = " ordered and contain no duplicate values."] - #[doc = "- `threshold`: The number of friends that must vouch for a recovery attempt before the"] - #[doc = " account can be recovered. Should be less than or equal to the length of the list of"] - #[doc = " friends."] - #[doc = "- `delay_period`: The number of blocks after a recovery attempt is initialized that"] - #[doc = " needs to pass before the account can be recovered."] - pub struct CreateRecovery { - pub friends: create_recovery::Friends, - pub threshold: create_recovery::Threshold, - pub delay_period: create_recovery::DelayPeriod, - } - pub mod create_recovery { + #[doc = "Emits `DecisionDepositRefunded`."] + pub struct RefundDecisionDeposit { + pub index: refund_decision_deposit::Index, + } + pub mod refund_decision_deposit { use super::runtime_types; - pub type Friends = ::subxt::ext::subxt_core::alloc::vec::Vec< - ::subxt::ext::subxt_core::utils::AccountId32, - >; - pub type Threshold = ::core::primitive::u16; - pub type DelayPeriod = ::core::primitive::u32; + pub type Index = ::core::primitive::u32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for CreateRecovery { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "create_recovery"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for RefundDecisionDeposit { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "refund_decision_deposit"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11264,30 +8971,22 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Initiate the process for recovering a recoverable account."] - #[doc = ""] - #[doc = "Payment: `RecoveryDeposit` balance will be reserved for initiating the"] - #[doc = "recovery process. This deposit will always be repatriated to the account"] - #[doc = "trying to be recovered. See `close_recovery`."] + #[doc = "Cancel an ongoing referendum."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = "- `origin`: must be the `CancelOrigin`."] + #[doc = "- `index`: The index of the referendum to be cancelled."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The lost account that you want to recover. This account needs to be"] - #[doc = " recoverable (i.e. have a recovery configuration)."] - pub struct InitiateRecovery { - pub account: initiate_recovery::Account, + #[doc = "Emits `Cancelled`."] + pub struct Cancel { + pub index: cancel::Index, } - pub mod initiate_recovery { + pub mod cancel { use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; + pub type Index = ::core::primitive::u32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for InitiateRecovery { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "initiate_recovery"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Cancel { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "cancel"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11300,36 +8999,22 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Allow a \"friend\" of a recoverable account to vouch for an active recovery"] - #[doc = "process for that account."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a \"friend\""] - #[doc = "for the recoverable account."] + #[doc = "Cancel an ongoing referendum and slash the deposits."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `lost`: The lost account that you want to recover."] - #[doc = "- `rescuer`: The account trying to rescue the lost account that you want to vouch for."] + #[doc = "- `origin`: must be the `KillOrigin`."] + #[doc = "- `index`: The index of the referendum to be cancelled."] #[doc = ""] - #[doc = "The combination of these two parameters must point to an active recovery"] - #[doc = "process."] - pub struct VouchRecovery { - pub lost: vouch_recovery::Lost, - pub rescuer: vouch_recovery::Rescuer, + #[doc = "Emits `Killed` and `DepositSlashed`."] + pub struct Kill { + pub index: kill::Index, } - pub mod vouch_recovery { + pub mod kill { use super::runtime_types; - pub type Lost = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - pub type Rescuer = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; + pub type Index = ::core::primitive::u32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for VouchRecovery { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "vouch_recovery"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Kill { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "kill"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11342,28 +9027,20 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Allow a successful rescuer to claim their recovered account."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a \"rescuer\""] - #[doc = "who has successfully completed the account recovery process: collected"] - #[doc = "`threshold` or more vouches, waited `delay_period` blocks since initiation."] + #[doc = "Advance a referendum onto its next logical state. Only used internally."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The lost account that you want to claim has been successfully recovered by"] - #[doc = " you."] - pub struct ClaimRecovery { - pub account: claim_recovery::Account, + #[doc = "- `origin`: must be `Root`."] + #[doc = "- `index`: the referendum to be advanced."] + pub struct NudgeReferendum { + pub index: nudge_referendum::Index, } - pub mod claim_recovery { + pub mod nudge_referendum { use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; + pub type Index = ::core::primitive::u32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for ClaimRecovery { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "claim_recovery"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for NudgeReferendum { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "nudge_referendum"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11376,57 +9053,25 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "As the controller of a recoverable account, close an active recovery"] - #[doc = "process for your account."] - #[doc = ""] - #[doc = "Payment: By calling this function, the recoverable account will receive"] - #[doc = "the recovery deposit `RecoveryDeposit` placed by the rescuer."] + #[doc = "Advance a track onto its next logical state. Only used internally."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a"] - #[doc = "recoverable account with an active recovery process for it."] + #[doc = "- `origin`: must be `Root`."] + #[doc = "- `track`: the track to be advanced."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `rescuer`: The account trying to rescue this recoverable account."] - pub struct CloseRecovery { - pub rescuer: close_recovery::Rescuer, + #[doc = "Action item for when there is now one fewer referendum in the deciding phase and the"] + #[doc = "`DecidingCount` is not yet updated. This means that we should either:"] + #[doc = "- begin deciding another referendum (and leave `DecidingCount` alone); or"] + #[doc = "- decrement `DecidingCount`."] + pub struct OneFewerDeciding { + pub track: one_fewer_deciding::Track, } - pub mod close_recovery { + pub mod one_fewer_deciding { use super::runtime_types; - pub type Rescuer = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; - } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for CloseRecovery { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "close_recovery"; + pub type Track = ::core::primitive::u16; } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Remove the recovery process for your account. Recovered accounts are still accessible."] - #[doc = ""] - #[doc = "NOTE: The user must make sure to call `close_recovery` on all active"] - #[doc = "recovery attempts before calling this function else it will fail."] - #[doc = ""] - #[doc = "Payment: By calling this function the recoverable account will unreserve"] - #[doc = "their recovery configuration deposit."] - #[doc = "(`ConfigDepositBase` + `FriendDepositFactor` * #_of_friends)"] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a"] - #[doc = "recoverable account (i.e. has a recovery configuration)."] - pub struct RemoveRecovery; - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for RemoveRecovery { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "remove_recovery"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for OneFewerDeciding { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "one_fewer_deciding"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11439,26 +9084,23 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Cancel the ability to use `as_recovered` for `account`."] + #[doc = "Refund the Submission Deposit for a closed referendum back to the depositor."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and registered to"] - #[doc = "be able to make calls on behalf of the recovered account."] + #[doc = "- `origin`: must be `Signed` or `Root`."] + #[doc = "- `index`: The index of a closed referendum whose Submission Deposit has not yet been"] + #[doc = " refunded."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The recovered account you are able to call on-behalf-of."] - pub struct CancelRecovered { - pub account: cancel_recovered::Account, + #[doc = "Emits `SubmissionDepositRefunded`."] + pub struct RefundSubmissionDeposit { + pub index: refund_submission_deposit::Index, } - pub mod cancel_recovered { + pub mod refund_submission_deposit { use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >; + pub type Index = ::core::primitive::u32; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for CancelRecovered { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "cancel_recovered"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for RefundSubmissionDeposit { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "refund_submission_deposit"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11471,338 +9113,394 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Poke deposits for recovery configurations and / or active recoveries."] - #[doc = ""] - #[doc = "This can be used by accounts to possibly lower their locked amount."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = "Set or clear metadata of a referendum."] #[doc = ""] #[doc = "Parameters:"] - #[doc = "- `maybe_account`: Optional recoverable account for which you have an active recovery"] - #[doc = "and want to adjust the deposit for the active recovery."] - #[doc = ""] - #[doc = "This function checks both recovery configuration deposit and active recovery deposits"] - #[doc = "of the caller:"] - #[doc = "- If the caller has created a recovery configuration, checks and adjusts its deposit"] - #[doc = "- If the caller has initiated any active recoveries, and provides the account in"] - #[doc = "`maybe_account`, checks and adjusts those deposits"] - #[doc = ""] - #[doc = "If any deposit is updated, the difference will be reserved/unreserved from the caller's"] - #[doc = "account."] - #[doc = ""] - #[doc = "The transaction is made free if any deposit is updated and paid otherwise."] - #[doc = ""] - #[doc = "Emits `DepositPoked` if any deposit is updated."] - #[doc = "Multiple events may be emitted in case both types of deposits are updated."] - pub struct PokeDeposit { - pub maybe_account: poke_deposit::MaybeAccount, + #[doc = "- `origin`: Must be `Signed` by a creator of a referendum or by anyone to clear a"] + #[doc = " metadata of a finished referendum."] + #[doc = "- `index`: The index of a referendum to set or clear metadata for."] + #[doc = "- `maybe_hash`: The hash of an on-chain stored preimage. `None` to clear a metadata."] + pub struct SetMetadata { + pub index: set_metadata::Index, + pub maybe_hash: set_metadata::MaybeHash, } - pub mod poke_deposit { + pub mod set_metadata { use super::runtime_types; - pub type MaybeAccount = ::core::option::Option< - ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - >; + pub type Index = ::core::primitive::u32; + pub type MaybeHash = + ::core::option::Option<::subxt::ext::subxt_core::utils::H256>; } - impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for PokeDeposit { - const PALLET: &'static str = "Recovery"; - const CALL: &'static str = "poke_deposit"; + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetMetadata { + const PALLET: &'static str = "TechReferenda"; + const CALL: &'static str = "set_metadata"; } } pub struct TransactionApi; impl TransactionApi { - #[doc = "Send a call through a recovered account."] + #[doc = "Propose a referendum on a privileged action."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and registered to"] - #[doc = "be able to make calls on behalf of the recovered account."] + #[doc = "- `origin`: must be `SubmitOrigin` and the account must have `SubmissionDeposit` funds"] + #[doc = " available."] + #[doc = "- `proposal_origin`: The origin from which the proposal should be executed."] + #[doc = "- `proposal`: The proposal."] + #[doc = "- `enactment_moment`: The moment that the proposal should be enacted."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The recovered account you want to make a call on-behalf-of."] - #[doc = "- `call`: The call you want to make with the recovered account."] - pub fn as_recovered( + #[doc = "Emits `Submitted`."] + pub fn submit( &self, - account: types::as_recovered::Account, - call: types::as_recovered::Call, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { + proposal_origin: types::submit::ProposalOrigin, + proposal: types::submit::Proposal, + enactment_moment: types::submit::EnactmentMoment, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "as_recovered", - types::AsRecovered { - account, - call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), + "TechReferenda", + "submit", + types::Submit { + proposal_origin: ::subxt::ext::subxt_core::alloc::boxed::Box::new( + proposal_origin, + ), + proposal, + enactment_moment, }, [ - 54u8, 163u8, 62u8, 168u8, 48u8, 149u8, 86u8, 254u8, 235u8, 163u8, - 127u8, 221u8, 43u8, 126u8, 67u8, 193u8, 52u8, 44u8, 39u8, 231u8, 198u8, - 6u8, 203u8, 17u8, 99u8, 130u8, 226u8, 37u8, 57u8, 71u8, 127u8, 66u8, + 0u8, 18u8, 14u8, 253u8, 33u8, 212u8, 33u8, 173u8, 241u8, 29u8, 88u8, + 160u8, 111u8, 21u8, 6u8, 234u8, 249u8, 230u8, 222u8, 119u8, 161u8, + 114u8, 43u8, 126u8, 164u8, 140u8, 199u8, 39u8, 2u8, 64u8, 132u8, 34u8, ], ) } - #[doc = "Allow ROOT to bypass the recovery process and set a rescuer account"] - #[doc = "for a lost account directly."] + #[doc = "Post the Decision Deposit for a referendum."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _ROOT_."] + #[doc = "- `origin`: must be `Signed` and the account must have funds available for the"] + #[doc = " referendum's track's Decision Deposit."] + #[doc = "- `index`: The index of the submitted referendum whose Decision Deposit is yet to be"] + #[doc = " posted."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `lost`: The \"lost account\" to be recovered."] - #[doc = "- `rescuer`: The \"rescuer account\" which can call as the lost account."] - pub fn set_recovered( + #[doc = "Emits `DecisionDepositPlaced`."] + pub fn place_decision_deposit( &self, - lost: types::set_recovered::Lost, - rescuer: types::set_recovered::Rescuer, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { - ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "set_recovered", - types::SetRecovered { lost, rescuer }, - [ - 194u8, 147u8, 14u8, 197u8, 132u8, 185u8, 122u8, 81u8, 61u8, 14u8, 10u8, - 177u8, 74u8, 184u8, 150u8, 217u8, 246u8, 149u8, 26u8, 165u8, 196u8, - 83u8, 230u8, 195u8, 213u8, 40u8, 51u8, 180u8, 23u8, 90u8, 3u8, 14u8, - ], - ) - } - #[doc = "Create a recovery configuration for your account. This makes your account recoverable."] - #[doc = ""] - #[doc = "Payment: `ConfigDepositBase` + `FriendDepositFactor` * #_of_friends balance"] - #[doc = "will be reserved for storing the recovery configuration. This deposit is returned"] - #[doc = "in full when the user calls `remove_recovery`."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `friends`: A list of friends you trust to vouch for recovery attempts. Should be"] - #[doc = " ordered and contain no duplicate values."] - #[doc = "- `threshold`: The number of friends that must vouch for a recovery attempt before the"] - #[doc = " account can be recovered. Should be less than or equal to the length of the list of"] - #[doc = " friends."] - #[doc = "- `delay_period`: The number of blocks after a recovery attempt is initialized that"] - #[doc = " needs to pass before the account can be recovered."] - pub fn create_recovery( - &self, - friends: types::create_recovery::Friends, - threshold: types::create_recovery::Threshold, - delay_period: types::create_recovery::DelayPeriod, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + index: types::place_decision_deposit::Index, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "create_recovery", - types::CreateRecovery { friends, threshold, delay_period }, + "TechReferenda", + "place_decision_deposit", + types::PlaceDecisionDeposit { index }, [ - 36u8, 175u8, 11u8, 85u8, 95u8, 170u8, 58u8, 193u8, 102u8, 18u8, 117u8, - 27u8, 199u8, 214u8, 70u8, 47u8, 129u8, 130u8, 109u8, 242u8, 240u8, - 255u8, 120u8, 176u8, 40u8, 243u8, 175u8, 71u8, 3u8, 91u8, 186u8, 220u8, + 247u8, 158u8, 55u8, 191u8, 188u8, 200u8, 3u8, 47u8, 20u8, 175u8, 86u8, + 203u8, 52u8, 253u8, 91u8, 131u8, 21u8, 213u8, 56u8, 68u8, 40u8, 84u8, + 184u8, 30u8, 9u8, 193u8, 63u8, 182u8, 178u8, 241u8, 247u8, 220u8, ], ) } - #[doc = "Initiate the process for recovering a recoverable account."] - #[doc = ""] - #[doc = "Payment: `RecoveryDeposit` balance will be reserved for initiating the"] - #[doc = "recovery process. This deposit will always be repatriated to the account"] - #[doc = "trying to be recovered. See `close_recovery`."] + #[doc = "Refund the Decision Deposit for a closed referendum back to the depositor."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = "- `origin`: must be `Signed` or `Root`."] + #[doc = "- `index`: The index of a closed referendum whose Decision Deposit has not yet been"] + #[doc = " refunded."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The lost account that you want to recover. This account needs to be"] - #[doc = " recoverable (i.e. have a recovery configuration)."] - pub fn initiate_recovery( + #[doc = "Emits `DecisionDepositRefunded`."] + pub fn refund_decision_deposit( &self, - account: types::initiate_recovery::Account, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { + index: types::refund_decision_deposit::Index, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< + types::RefundDecisionDeposit, + > { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "initiate_recovery", - types::InitiateRecovery { account }, + "TechReferenda", + "refund_decision_deposit", + types::RefundDecisionDeposit { index }, [ - 60u8, 243u8, 229u8, 176u8, 221u8, 52u8, 44u8, 224u8, 233u8, 14u8, 89u8, - 100u8, 174u8, 74u8, 38u8, 32u8, 97u8, 48u8, 53u8, 74u8, 30u8, 242u8, - 19u8, 114u8, 145u8, 74u8, 69u8, 125u8, 227u8, 214u8, 144u8, 58u8, + 159u8, 19u8, 35u8, 216u8, 114u8, 105u8, 18u8, 42u8, 148u8, 151u8, + 136u8, 92u8, 117u8, 30u8, 29u8, 41u8, 238u8, 58u8, 195u8, 91u8, 115u8, + 135u8, 96u8, 99u8, 154u8, 233u8, 8u8, 249u8, 145u8, 165u8, 77u8, 164u8, ], ) } - #[doc = "Allow a \"friend\" of a recoverable account to vouch for an active recovery"] - #[doc = "process for that account."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a \"friend\""] - #[doc = "for the recoverable account."] + #[doc = "Cancel an ongoing referendum."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `lost`: The lost account that you want to recover."] - #[doc = "- `rescuer`: The account trying to rescue the lost account that you want to vouch for."] + #[doc = "- `origin`: must be the `CancelOrigin`."] + #[doc = "- `index`: The index of the referendum to be cancelled."] #[doc = ""] - #[doc = "The combination of these two parameters must point to an active recovery"] - #[doc = "process."] - pub fn vouch_recovery( + #[doc = "Emits `Cancelled`."] + pub fn cancel( &self, - lost: types::vouch_recovery::Lost, - rescuer: types::vouch_recovery::Rescuer, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { + index: types::cancel::Index, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "vouch_recovery", - types::VouchRecovery { lost, rescuer }, + "TechReferenda", + "cancel", + types::Cancel { index }, [ - 97u8, 190u8, 60u8, 15u8, 191u8, 117u8, 1u8, 217u8, 62u8, 40u8, 210u8, - 1u8, 237u8, 111u8, 48u8, 196u8, 180u8, 154u8, 198u8, 12u8, 108u8, 42u8, - 6u8, 234u8, 2u8, 113u8, 163u8, 111u8, 80u8, 146u8, 6u8, 73u8, + 55u8, 206u8, 119u8, 156u8, 238u8, 165u8, 193u8, 73u8, 242u8, 13u8, + 212u8, 75u8, 136u8, 156u8, 151u8, 14u8, 35u8, 41u8, 156u8, 107u8, 60u8, + 190u8, 39u8, 216u8, 8u8, 74u8, 213u8, 130u8, 160u8, 131u8, 237u8, + 122u8, ], ) } - #[doc = "Allow a successful rescuer to claim their recovered account."] + #[doc = "Cancel an ongoing referendum and slash the deposits."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a \"rescuer\""] - #[doc = "who has successfully completed the account recovery process: collected"] - #[doc = "`threshold` or more vouches, waited `delay_period` blocks since initiation."] + #[doc = "- `origin`: must be the `KillOrigin`."] + #[doc = "- `index`: The index of the referendum to be cancelled."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The lost account that you want to claim has been successfully recovered by"] - #[doc = " you."] - pub fn claim_recovery( + #[doc = "Emits `Killed` and `DepositSlashed`."] + pub fn kill( &self, - account: types::claim_recovery::Account, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { + index: types::kill::Index, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "claim_recovery", - types::ClaimRecovery { account }, + "TechReferenda", + "kill", + types::Kill { index }, [ - 41u8, 47u8, 162u8, 88u8, 13u8, 166u8, 130u8, 146u8, 218u8, 162u8, - 166u8, 33u8, 89u8, 129u8, 177u8, 178u8, 68u8, 128u8, 161u8, 229u8, - 207u8, 3u8, 57u8, 35u8, 211u8, 208u8, 74u8, 155u8, 183u8, 173u8, 74u8, - 56u8, + 50u8, 89u8, 57u8, 0u8, 87u8, 129u8, 113u8, 140u8, 179u8, 178u8, 126u8, + 198u8, 92u8, 92u8, 189u8, 64u8, 123u8, 232u8, 57u8, 227u8, 223u8, + 219u8, 73u8, 217u8, 179u8, 44u8, 210u8, 125u8, 180u8, 10u8, 143u8, + 48u8, ], ) } - #[doc = "As the controller of a recoverable account, close an active recovery"] - #[doc = "process for your account."] - #[doc = ""] - #[doc = "Payment: By calling this function, the recoverable account will receive"] - #[doc = "the recovery deposit `RecoveryDeposit` placed by the rescuer."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a"] - #[doc = "recoverable account with an active recovery process for it."] + #[doc = "Advance a referendum onto its next logical state. Only used internally."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `rescuer`: The account trying to rescue this recoverable account."] - pub fn close_recovery( + #[doc = "- `origin`: must be `Root`."] + #[doc = "- `index`: the referendum to be advanced."] + pub fn nudge_referendum( &self, - rescuer: types::close_recovery::Rescuer, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + index: types::nudge_referendum::Index, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "close_recovery", - types::CloseRecovery { rescuer }, + "TechReferenda", + "nudge_referendum", + types::NudgeReferendum { index }, [ - 161u8, 178u8, 117u8, 209u8, 119u8, 164u8, 135u8, 41u8, 25u8, 108u8, - 194u8, 175u8, 221u8, 65u8, 184u8, 137u8, 171u8, 97u8, 204u8, 61u8, - 159u8, 39u8, 192u8, 53u8, 246u8, 69u8, 113u8, 16u8, 170u8, 232u8, - 163u8, 10u8, + 75u8, 99u8, 172u8, 30u8, 170u8, 150u8, 211u8, 229u8, 249u8, 128u8, + 194u8, 246u8, 100u8, 142u8, 193u8, 184u8, 232u8, 81u8, 29u8, 17u8, + 99u8, 91u8, 236u8, 85u8, 230u8, 226u8, 57u8, 115u8, 45u8, 170u8, 54u8, + 213u8, ], ) } - #[doc = "Remove the recovery process for your account. Recovered accounts are still accessible."] - #[doc = ""] - #[doc = "NOTE: The user must make sure to call `close_recovery` on all active"] - #[doc = "recovery attempts before calling this function else it will fail."] + #[doc = "Advance a track onto its next logical state. Only used internally."] #[doc = ""] - #[doc = "Payment: By calling this function the recoverable account will unreserve"] - #[doc = "their recovery configuration deposit."] - #[doc = "(`ConfigDepositBase` + `FriendDepositFactor` * #_of_friends)"] + #[doc = "- `origin`: must be `Root`."] + #[doc = "- `track`: the track to be advanced."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a"] - #[doc = "recoverable account (i.e. has a recovery configuration)."] - pub fn remove_recovery( + #[doc = "Action item for when there is now one fewer referendum in the deciding phase and the"] + #[doc = "`DecidingCount` is not yet updated. This means that we should either:"] + #[doc = "- begin deciding another referendum (and leave `DecidingCount` alone); or"] + #[doc = "- decrement `DecidingCount`."] + pub fn one_fewer_deciding( &self, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + track: types::one_fewer_deciding::Track, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "remove_recovery", - types::RemoveRecovery {}, + "TechReferenda", + "one_fewer_deciding", + types::OneFewerDeciding { track }, [ - 11u8, 38u8, 133u8, 172u8, 212u8, 252u8, 57u8, 216u8, 42u8, 202u8, - 206u8, 91u8, 115u8, 91u8, 242u8, 123u8, 95u8, 196u8, 172u8, 243u8, - 164u8, 1u8, 69u8, 180u8, 40u8, 68u8, 208u8, 221u8, 161u8, 250u8, 8u8, - 72u8, + 15u8, 84u8, 79u8, 231u8, 21u8, 239u8, 244u8, 143u8, 183u8, 215u8, + 181u8, 25u8, 225u8, 195u8, 95u8, 171u8, 17u8, 156u8, 182u8, 128u8, + 111u8, 40u8, 151u8, 102u8, 196u8, 55u8, 36u8, 212u8, 89u8, 190u8, + 131u8, 167u8, ], ) } - #[doc = "Cancel the ability to use `as_recovered` for `account`."] + #[doc = "Refund the Submission Deposit for a closed referendum back to the depositor."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and registered to"] - #[doc = "be able to make calls on behalf of the recovered account."] + #[doc = "- `origin`: must be `Signed` or `Root`."] + #[doc = "- `index`: The index of a closed referendum whose Submission Deposit has not yet been"] + #[doc = " refunded."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The recovered account you are able to call on-behalf-of."] - pub fn cancel_recovered( + #[doc = "Emits `SubmissionDepositRefunded`."] + pub fn refund_submission_deposit( &self, - account: types::cancel_recovered::Account, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload - { + index: types::refund_submission_deposit::Index, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload< + types::RefundSubmissionDeposit, + > { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "cancel_recovered", - types::CancelRecovered { account }, + "TechReferenda", + "refund_submission_deposit", + types::RefundSubmissionDeposit { index }, [ - 100u8, 222u8, 80u8, 226u8, 187u8, 188u8, 111u8, 58u8, 190u8, 5u8, - 178u8, 144u8, 37u8, 98u8, 71u8, 145u8, 28u8, 248u8, 222u8, 188u8, 53u8, - 21u8, 127u8, 176u8, 249u8, 166u8, 250u8, 59u8, 170u8, 33u8, 251u8, - 239u8, + 20u8, 217u8, 115u8, 6u8, 1u8, 60u8, 54u8, 136u8, 35u8, 41u8, 38u8, + 23u8, 85u8, 100u8, 141u8, 126u8, 30u8, 160u8, 61u8, 46u8, 134u8, 98u8, + 82u8, 38u8, 211u8, 124u8, 208u8, 222u8, 210u8, 10u8, 155u8, 122u8, ], ) } - #[doc = "Poke deposits for recovery configurations and / or active recoveries."] - #[doc = ""] - #[doc = "This can be used by accounts to possibly lower their locked amount."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = "Set or clear metadata of a referendum."] #[doc = ""] #[doc = "Parameters:"] - #[doc = "- `maybe_account`: Optional recoverable account for which you have an active recovery"] - #[doc = "and want to adjust the deposit for the active recovery."] - #[doc = ""] - #[doc = "This function checks both recovery configuration deposit and active recovery deposits"] - #[doc = "of the caller:"] - #[doc = "- If the caller has created a recovery configuration, checks and adjusts its deposit"] - #[doc = "- If the caller has initiated any active recoveries, and provides the account in"] - #[doc = "`maybe_account`, checks and adjusts those deposits"] - #[doc = ""] - #[doc = "If any deposit is updated, the difference will be reserved/unreserved from the caller's"] - #[doc = "account."] - #[doc = ""] - #[doc = "The transaction is made free if any deposit is updated and paid otherwise."] - #[doc = ""] - #[doc = "Emits `DepositPoked` if any deposit is updated."] - #[doc = "Multiple events may be emitted in case both types of deposits are updated."] - pub fn poke_deposit( + #[doc = "- `origin`: Must be `Signed` by a creator of a referendum or by anyone to clear a"] + #[doc = " metadata of a finished referendum."] + #[doc = "- `index`: The index of a referendum to set or clear metadata for."] + #[doc = "- `maybe_hash`: The hash of an on-chain stored preimage. `None` to clear a metadata."] + pub fn set_metadata( &self, - maybe_account: types::poke_deposit::MaybeAccount, - ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { + index: types::set_metadata::Index, + maybe_hash: types::set_metadata::MaybeHash, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( - "Recovery", - "poke_deposit", - types::PokeDeposit { maybe_account }, + "TechReferenda", + "set_metadata", + types::SetMetadata { index, maybe_hash }, [ - 177u8, 98u8, 53u8, 15u8, 228u8, 36u8, 173u8, 55u8, 125u8, 3u8, 234u8, - 70u8, 147u8, 147u8, 124u8, 86u8, 31u8, 101u8, 171u8, 56u8, 148u8, - 180u8, 87u8, 149u8, 11u8, 113u8, 195u8, 35u8, 56u8, 32u8, 251u8, 56u8, + 207u8, 29u8, 146u8, 233u8, 219u8, 205u8, 88u8, 118u8, 106u8, 61u8, + 124u8, 101u8, 2u8, 41u8, 169u8, 70u8, 114u8, 189u8, 162u8, 118u8, 1u8, + 108u8, 234u8, 98u8, 245u8, 245u8, 183u8, 126u8, 89u8, 13u8, 112u8, + 88u8, ], ) } } - } - #[doc = "Events type."] - pub type Event = runtime_types::pallet_recovery::pallet::Event; - pub mod events { - use super::runtime_types; + } + #[doc = "The `Event` enum of this pallet"] + pub type Event = runtime_types::pallet_referenda::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "A referendum has been submitted."] + pub struct Submitted { + pub index: submitted::Index, + pub track: submitted::Track, + pub proposal: submitted::Proposal, + } + pub mod submitted { + use super::runtime_types; + pub type Index = ::core::primitive::u32; + pub type Track = ::core::primitive::u16; + pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::quantus_runtime::RuntimeCall, + runtime_types::sp_runtime::traits::BlakeTwo256, + >; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for Submitted { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "Submitted"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "The decision deposit has been placed."] + pub struct DecisionDepositPlaced { + pub index: decision_deposit_placed::Index, + pub who: decision_deposit_placed::Who, + pub amount: decision_deposit_placed::Amount, + } + pub mod decision_deposit_placed { + use super::runtime_types; + pub type Index = ::core::primitive::u32; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Amount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for DecisionDepositPlaced { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "DecisionDepositPlaced"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "The decision deposit has been refunded."] + pub struct DecisionDepositRefunded { + pub index: decision_deposit_refunded::Index, + pub who: decision_deposit_refunded::Who, + pub amount: decision_deposit_refunded::Amount, + } + pub mod decision_deposit_refunded { + use super::runtime_types; + pub type Index = ::core::primitive::u32; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Amount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for DecisionDepositRefunded { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "DecisionDepositRefunded"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "A deposit has been slashed."] + pub struct DepositSlashed { + pub who: deposit_slashed::Who, + pub amount: deposit_slashed::Amount, + } + pub mod deposit_slashed { + use super::runtime_types; + pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Amount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for DepositSlashed { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "DepositSlashed"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "A referendum has moved into the deciding phase."] + pub struct DecisionStarted { + pub index: decision_started::Index, + pub track: decision_started::Track, + pub proposal: decision_started::Proposal, + pub tally: decision_started::Tally, + } + pub mod decision_started { + use super::runtime_types; + pub type Index = ::core::primitive::u32; + pub type Track = ::core::primitive::u16; + pub type Proposal = runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::quantus_runtime::RuntimeCall, + runtime_types::sp_runtime::traits::BlakeTwo256, + >; + pub type Tally = runtime_types::pallet_ranked_collective::Tally; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for DecisionStarted { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "DecisionStarted"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + pub struct ConfirmStarted { + pub index: confirm_started::Index, + } + pub mod confirm_started { + use super::runtime_types; + pub type Index = ::core::primitive::u32; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for ConfirmStarted { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "ConfirmStarted"; + } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, @@ -11810,17 +9508,37 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A recovery process has been set up for an account."] - pub struct RecoveryCreated { - pub account: recovery_created::Account, + pub struct ConfirmAborted { + pub index: confirm_aborted::Index, } - pub mod recovery_created { + pub mod confirm_aborted { use super::runtime_types; - pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Index = ::core::primitive::u32; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for ConfirmAborted { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "ConfirmAborted"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "A referendum has ended its confirmation phase and is ready for approval."] + pub struct Confirmed { + pub index: confirmed::Index, + pub tally: confirmed::Tally, + } + pub mod confirmed { + use super::runtime_types; + pub type Index = ::core::primitive::u32; + pub type Tally = runtime_types::pallet_ranked_collective::Tally; } - impl ::subxt::ext::subxt_core::events::StaticEvent for RecoveryCreated { - const PALLET: &'static str = "Recovery"; - const EVENT: &'static str = "RecoveryCreated"; + impl ::subxt::ext::subxt_core::events::StaticEvent for Confirmed { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "Confirmed"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11829,19 +9547,17 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A recovery process has been initiated for lost account by rescuer account."] - pub struct RecoveryInitiated { - pub lost_account: recovery_initiated::LostAccount, - pub rescuer_account: recovery_initiated::RescuerAccount, + #[doc = "A referendum has been approved and its proposal has been scheduled."] + pub struct Approved { + pub index: approved::Index, } - pub mod recovery_initiated { + pub mod approved { use super::runtime_types; - pub type LostAccount = ::subxt::ext::subxt_core::utils::AccountId32; - pub type RescuerAccount = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Index = ::core::primitive::u32; } - impl ::subxt::ext::subxt_core::events::StaticEvent for RecoveryInitiated { - const PALLET: &'static str = "Recovery"; - const EVENT: &'static str = "RecoveryInitiated"; + impl ::subxt::ext::subxt_core::events::StaticEvent for Approved { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "Approved"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11850,21 +9566,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A recovery process for lost account by rescuer account has been vouched for by sender."] - pub struct RecoveryVouched { - pub lost_account: recovery_vouched::LostAccount, - pub rescuer_account: recovery_vouched::RescuerAccount, - pub sender: recovery_vouched::Sender, + #[doc = "A proposal has been rejected by referendum."] + pub struct Rejected { + pub index: rejected::Index, + pub tally: rejected::Tally, } - pub mod recovery_vouched { + pub mod rejected { use super::runtime_types; - pub type LostAccount = ::subxt::ext::subxt_core::utils::AccountId32; - pub type RescuerAccount = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Sender = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Index = ::core::primitive::u32; + pub type Tally = runtime_types::pallet_ranked_collective::Tally; } - impl ::subxt::ext::subxt_core::events::StaticEvent for RecoveryVouched { - const PALLET: &'static str = "Recovery"; - const EVENT: &'static str = "RecoveryVouched"; + impl ::subxt::ext::subxt_core::events::StaticEvent for Rejected { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "Rejected"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11873,19 +9587,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A recovery process for lost account by rescuer account has been closed."] - pub struct RecoveryClosed { - pub lost_account: recovery_closed::LostAccount, - pub rescuer_account: recovery_closed::RescuerAccount, + #[doc = "A referendum has been timed out without being decided."] + pub struct TimedOut { + pub index: timed_out::Index, + pub tally: timed_out::Tally, } - pub mod recovery_closed { + pub mod timed_out { use super::runtime_types; - pub type LostAccount = ::subxt::ext::subxt_core::utils::AccountId32; - pub type RescuerAccount = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Index = ::core::primitive::u32; + pub type Tally = runtime_types::pallet_ranked_collective::Tally; } - impl ::subxt::ext::subxt_core::events::StaticEvent for RecoveryClosed { - const PALLET: &'static str = "Recovery"; - const EVENT: &'static str = "RecoveryClosed"; + impl ::subxt::ext::subxt_core::events::StaticEvent for TimedOut { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "TimedOut"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11894,19 +9608,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Lost account has been successfully recovered by rescuer account."] - pub struct AccountRecovered { - pub lost_account: account_recovered::LostAccount, - pub rescuer_account: account_recovered::RescuerAccount, + #[doc = "A referendum has been cancelled."] + pub struct Cancelled { + pub index: cancelled::Index, + pub tally: cancelled::Tally, } - pub mod account_recovered { + pub mod cancelled { use super::runtime_types; - pub type LostAccount = ::subxt::ext::subxt_core::utils::AccountId32; - pub type RescuerAccount = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Index = ::core::primitive::u32; + pub type Tally = runtime_types::pallet_ranked_collective::Tally; } - impl ::subxt::ext::subxt_core::events::StaticEvent for AccountRecovered { - const PALLET: &'static str = "Recovery"; - const EVENT: &'static str = "AccountRecovered"; + impl ::subxt::ext::subxt_core::events::StaticEvent for Cancelled { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "Cancelled"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11915,17 +9629,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A recovery process has been removed for an account."] - pub struct RecoveryRemoved { - pub lost_account: recovery_removed::LostAccount, + #[doc = "A referendum has been killed."] + pub struct Killed { + pub index: killed::Index, + pub tally: killed::Tally, } - pub mod recovery_removed { + pub mod killed { use super::runtime_types; - pub type LostAccount = ::subxt::ext::subxt_core::utils::AccountId32; + pub type Index = ::core::primitive::u32; + pub type Tally = runtime_types::pallet_ranked_collective::Tally; } - impl ::subxt::ext::subxt_core::events::StaticEvent for RecoveryRemoved { - const PALLET: &'static str = "Recovery"; - const EVENT: &'static str = "RecoveryRemoved"; + impl ::subxt::ext::subxt_core::events::StaticEvent for Killed { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "Killed"; } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -11934,243 +9650,432 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A deposit has been updated."] - pub struct DepositPoked { - pub who: deposit_poked::Who, - pub kind: deposit_poked::Kind, - pub old_deposit: deposit_poked::OldDeposit, - pub new_deposit: deposit_poked::NewDeposit, - } - pub mod deposit_poked { + #[doc = "The submission deposit has been refunded."] + pub struct SubmissionDepositRefunded { + pub index: submission_deposit_refunded::Index, + pub who: submission_deposit_refunded::Who, + pub amount: submission_deposit_refunded::Amount, + } + pub mod submission_deposit_refunded { use super::runtime_types; + pub type Index = ::core::primitive::u32; pub type Who = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Kind = runtime_types::pallet_recovery::DepositKind< - runtime_types::quantus_runtime::Runtime, - >; - pub type OldDeposit = ::core::primitive::u128; - pub type NewDeposit = ::core::primitive::u128; + pub type Amount = ::core::primitive::u128; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for SubmissionDepositRefunded { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "SubmissionDepositRefunded"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "Metadata for a referendum has been set."] + pub struct MetadataSet { + pub index: metadata_set::Index, + pub hash: metadata_set::Hash, + } + pub mod metadata_set { + use super::runtime_types; + pub type Index = ::core::primitive::u32; + pub type Hash = ::subxt::ext::subxt_core::utils::H256; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for MetadataSet { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "MetadataSet"; + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "Metadata for a referendum has been cleared."] + pub struct MetadataCleared { + pub index: metadata_cleared::Index, + pub hash: metadata_cleared::Hash, + } + pub mod metadata_cleared { + use super::runtime_types; + pub type Index = ::core::primitive::u32; + pub type Hash = ::subxt::ext::subxt_core::utils::H256; } - impl ::subxt::ext::subxt_core::events::StaticEvent for DepositPoked { - const PALLET: &'static str = "Recovery"; - const EVENT: &'static str = "DepositPoked"; + impl ::subxt::ext::subxt_core::events::StaticEvent for MetadataCleared { + const PALLET: &'static str = "TechReferenda"; + const EVENT: &'static str = "MetadataCleared"; } } pub mod storage { use super::runtime_types; pub mod types { use super::runtime_types; - pub mod recoverable { + pub mod referendum_count { use super::runtime_types; - pub type Recoverable = runtime_types::pallet_recovery::RecoveryConfig< - ::core::primitive::u32, - ::core::primitive::u128, - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::subxt::ext::subxt_core::utils::AccountId32, - >, - >; + pub type ReferendumCount = ::core::primitive::u32; + } + pub mod active_referenda_count { + use super::runtime_types; + pub type ActiveReferendaCount = ::core::primitive::u32; + } + pub mod active_submission_count { + use super::runtime_types; + pub type ActiveSubmissionCount = ::core::primitive::u32; pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; } - pub mod active_recoveries { + pub mod referendum_info_for { use super::runtime_types; - pub type ActiveRecoveries = runtime_types::pallet_recovery::ActiveRecovery< - ::core::primitive::u32, - ::core::primitive::u128, - runtime_types::bounded_collections::bounded_vec::BoundedVec< + pub type ReferendumInfoFor = + runtime_types::pallet_referenda::types::ReferendumInfo< + ::core::primitive::u16, + runtime_types::quantus_runtime::OriginCaller, + ::core::primitive::u32, + runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::quantus_runtime::RuntimeCall, + runtime_types::sp_runtime::traits::BlakeTwo256, + >, + ::core::primitive::u128, + runtime_types::pallet_ranked_collective::Tally, ::subxt::ext::subxt_core::utils::AccountId32, - >, - >; - pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Param1 = ::subxt::ext::subxt_core::utils::AccountId32; + ( + runtime_types::qp_scheduler::BlockNumberOrTimestamp< + ::core::primitive::u32, + ::core::primitive::u64, + >, + ::core::primitive::u32, + ), + >; + pub type Param0 = ::core::primitive::u32; + } + pub mod track_queue { + use super::runtime_types; + pub type TrackQueue = + runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::core::primitive::u32, + ::core::primitive::u32, + )>; + pub type Param0 = ::core::primitive::u16; + } + pub mod deciding_count { + use super::runtime_types; + pub type DecidingCount = ::core::primitive::u32; + pub type Param0 = ::core::primitive::u16; + } + pub mod metadata_of { + use super::runtime_types; + pub type MetadataOf = ::subxt::ext::subxt_core::utils::H256; + pub type Param0 = ::core::primitive::u32; + } + } + pub struct StorageApi; + impl StorageApi { + #[doc = " The next free referendum index, aka the number of referenda started so far."] + pub fn referendum_count( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::referendum_count::ReferendumCount, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechReferenda", + "ReferendumCount", + (), + [ + 64u8, 145u8, 232u8, 153u8, 121u8, 87u8, 128u8, 253u8, 170u8, 192u8, + 139u8, 18u8, 0u8, 33u8, 243u8, 11u8, 238u8, 222u8, 244u8, 5u8, 247u8, + 198u8, 149u8, 31u8, 122u8, 208u8, 86u8, 179u8, 166u8, 167u8, 93u8, + 67u8, + ], + ) + } + #[doc = " The number of referenda currently in the `Ongoing` state, across all tracks."] + #[doc = ""] + #[doc = " Incremented on `submit` and decremented whenever a referendum reaches a terminal"] + #[doc = " state (approved, rejected, timed out, cancelled or killed). Bounds admissions at"] + #[doc = " [`Config::MaxActive`]."] + pub fn active_referenda_count( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::active_referenda_count::ActiveReferendaCount, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechReferenda", + "ActiveReferendaCount", + (), + [ + 229u8, 55u8, 193u8, 246u8, 144u8, 201u8, 79u8, 20u8, 129u8, 168u8, + 178u8, 105u8, 41u8, 247u8, 164u8, 167u8, 19u8, 98u8, 97u8, 11u8, 141u8, + 21u8, 166u8, 99u8, 183u8, 155u8, 112u8, 105u8, 60u8, 201u8, 94u8, + 175u8, + ], + ) + } + #[doc = " The number of referenda currently in the `Ongoing` state per submitter."] + #[doc = ""] + #[doc = " Maintained alongside [`ActiveReferendaCount`] (incremented on `submit`, decremented"] + #[doc = " on every terminal transition) and bounds each account's admissions at"] + #[doc = " [`Config::MaxActivePerAccount`], so no single submitter can exhaust the shared"] + #[doc = " [`Config::MaxActive`] capacity."] + pub fn active_submission_count_iter( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::active_submission_count::ActiveSubmissionCount, + (), + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechReferenda", + "ActiveSubmissionCount", + (), + [ + 149u8, 176u8, 221u8, 181u8, 160u8, 161u8, 122u8, 184u8, 222u8, 242u8, + 163u8, 6u8, 68u8, 253u8, 192u8, 215u8, 124u8, 71u8, 101u8, 226u8, 47u8, + 168u8, 246u8, 19u8, 143u8, 99u8, 140u8, 169u8, 50u8, 177u8, 218u8, + 98u8, + ], + ) } - pub mod proxy { - use super::runtime_types; - pub type Proxy = ::subxt::ext::subxt_core::utils::AccountId32; - pub type Param0 = ::subxt::ext::subxt_core::utils::AccountId32; + #[doc = " The number of referenda currently in the `Ongoing` state per submitter."] + #[doc = ""] + #[doc = " Maintained alongside [`ActiveReferendaCount`] (incremented on `submit`, decremented"] + #[doc = " on every terminal transition) and bounds each account's admissions at"] + #[doc = " [`Config::MaxActivePerAccount`], so no single submitter can exhaust the shared"] + #[doc = " [`Config::MaxActive`] capacity."] + pub fn active_submission_count( + &self, + _0: types::active_submission_count::Param0, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::active_submission_count::Param0, + >, + types::active_submission_count::ActiveSubmissionCount, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechReferenda", + "ActiveSubmissionCount", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + [ + 149u8, 176u8, 221u8, 181u8, 160u8, 161u8, 122u8, 184u8, 222u8, 242u8, + 163u8, 6u8, 68u8, 253u8, 192u8, 215u8, 124u8, 71u8, 101u8, 226u8, 47u8, + 168u8, 246u8, 19u8, 143u8, 99u8, 140u8, 169u8, 50u8, 177u8, 218u8, + 98u8, + ], + ) } - } - pub struct StorageApi; - impl StorageApi { - #[doc = " The set of recoverable accounts and their recovery configuration."] - pub fn recoverable_iter( + #[doc = " Information concerning any given referendum."] + pub fn referendum_info_for_iter( &self, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< (), - types::recoverable::Recoverable, + types::referendum_info_for::ReferendumInfoFor, (), (), ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Recovery", - "Recoverable", + "TechReferenda", + "ReferendumInfoFor", (), [ - 112u8, 7u8, 56u8, 46u8, 138u8, 197u8, 63u8, 234u8, 140u8, 123u8, 145u8, - 106u8, 189u8, 190u8, 247u8, 61u8, 250u8, 67u8, 107u8, 42u8, 170u8, - 79u8, 54u8, 168u8, 33u8, 214u8, 91u8, 227u8, 5u8, 107u8, 38u8, 26u8, + 242u8, 125u8, 226u8, 99u8, 67u8, 226u8, 43u8, 159u8, 222u8, 238u8, + 72u8, 38u8, 45u8, 26u8, 95u8, 64u8, 141u8, 140u8, 37u8, 44u8, 101u8, + 67u8, 46u8, 66u8, 45u8, 93u8, 41u8, 156u8, 63u8, 59u8, 9u8, 29u8, ], ) } - #[doc = " The set of recoverable accounts and their recovery configuration."] - pub fn recoverable( + #[doc = " Information concerning any given referendum."] + pub fn referendum_info_for( &self, - _0: types::recoverable::Param0, + _0: types::referendum_info_for::Param0, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::recoverable::Param0, + types::referendum_info_for::Param0, >, - types::recoverable::Recoverable, + types::referendum_info_for::ReferendumInfoFor, ::subxt::ext::subxt_core::utils::Yes, (), (), > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Recovery", - "Recoverable", + "TechReferenda", + "ReferendumInfoFor", ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 112u8, 7u8, 56u8, 46u8, 138u8, 197u8, 63u8, 234u8, 140u8, 123u8, 145u8, - 106u8, 189u8, 190u8, 247u8, 61u8, 250u8, 67u8, 107u8, 42u8, 170u8, - 79u8, 54u8, 168u8, 33u8, 214u8, 91u8, 227u8, 5u8, 107u8, 38u8, 26u8, + 242u8, 125u8, 226u8, 99u8, 67u8, 226u8, 43u8, 159u8, 222u8, 238u8, + 72u8, 38u8, 45u8, 26u8, 95u8, 64u8, 141u8, 140u8, 37u8, 44u8, 101u8, + 67u8, 46u8, 66u8, 45u8, 93u8, 41u8, 156u8, 63u8, 59u8, 9u8, 29u8, ], ) } - #[doc = " Active recovery attempts."] + #[doc = " The sorted list of referenda ready to be decided but not yet being decided, ordered by"] + #[doc = " conviction-weighted approvals."] #[doc = ""] - #[doc = " First account is the account to be recovered, and the second account"] - #[doc = " is the user trying to recover the account."] - pub fn active_recoveries_iter( + #[doc = " This should be empty if `DecidingCount` is less than `TrackInfo::max_deciding`."] + pub fn track_queue_iter( &self, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< (), - types::active_recoveries::ActiveRecoveries, - (), + types::track_queue::TrackQueue, (), ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Recovery", - "ActiveRecoveries", + "TechReferenda", + "TrackQueue", (), [ - 104u8, 252u8, 28u8, 142u8, 48u8, 26u8, 91u8, 201u8, 184u8, 163u8, - 180u8, 197u8, 189u8, 71u8, 144u8, 88u8, 225u8, 13u8, 183u8, 84u8, - 244u8, 41u8, 164u8, 212u8, 153u8, 247u8, 191u8, 25u8, 162u8, 25u8, - 91u8, 123u8, + 187u8, 113u8, 225u8, 99u8, 159u8, 207u8, 182u8, 41u8, 116u8, 136u8, + 119u8, 196u8, 152u8, 50u8, 192u8, 22u8, 171u8, 182u8, 237u8, 228u8, + 80u8, 255u8, 227u8, 141u8, 155u8, 83u8, 71u8, 131u8, 118u8, 109u8, + 186u8, 65u8, ], ) } - #[doc = " Active recovery attempts."] + #[doc = " The sorted list of referenda ready to be decided but not yet being decided, ordered by"] + #[doc = " conviction-weighted approvals."] #[doc = ""] - #[doc = " First account is the account to be recovered, and the second account"] - #[doc = " is the user trying to recover the account."] - pub fn active_recoveries_iter1( + #[doc = " This should be empty if `DecidingCount` is less than `TrackInfo::max_deciding`."] + pub fn track_queue( &self, - _0: types::active_recoveries::Param0, + _0: types::track_queue::Param0, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::active_recoveries::Param0, + types::track_queue::Param0, >, - types::active_recoveries::ActiveRecoveries, + types::track_queue::TrackQueue, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TechReferenda", + "TrackQueue", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + [ + 187u8, 113u8, 225u8, 99u8, 159u8, 207u8, 182u8, 41u8, 116u8, 136u8, + 119u8, 196u8, 152u8, 50u8, 192u8, 22u8, 171u8, 182u8, 237u8, 228u8, + 80u8, 255u8, 227u8, 141u8, 155u8, 83u8, 71u8, 131u8, 118u8, 109u8, + 186u8, 65u8, + ], + ) + } + #[doc = " The number of referenda being decided currently."] + pub fn deciding_count_iter( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< (), + types::deciding_count::DecidingCount, (), ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Recovery", - "ActiveRecoveries", - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), + "TechReferenda", + "DecidingCount", + (), [ - 104u8, 252u8, 28u8, 142u8, 48u8, 26u8, 91u8, 201u8, 184u8, 163u8, - 180u8, 197u8, 189u8, 71u8, 144u8, 88u8, 225u8, 13u8, 183u8, 84u8, - 244u8, 41u8, 164u8, 212u8, 153u8, 247u8, 191u8, 25u8, 162u8, 25u8, - 91u8, 123u8, + 203u8, 89u8, 158u8, 179u8, 194u8, 82u8, 248u8, 162u8, 93u8, 140u8, + 146u8, 51u8, 110u8, 232u8, 51u8, 1u8, 128u8, 212u8, 199u8, 14u8, 182u8, + 103u8, 47u8, 252u8, 126u8, 108u8, 166u8, 69u8, 252u8, 179u8, 126u8, + 245u8, ], ) } - #[doc = " Active recovery attempts."] - #[doc = ""] - #[doc = " First account is the account to be recovered, and the second account"] - #[doc = " is the user trying to recover the account."] - pub fn active_recoveries( + #[doc = " The number of referenda being decided currently."] + pub fn deciding_count( &self, - _0: types::active_recoveries::Param0, - _1: types::active_recoveries::Param1, + _0: types::deciding_count::Param0, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< - ( - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::active_recoveries::Param0, - >, - ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::active_recoveries::Param1, - >, - ), - types::active_recoveries::ActiveRecoveries, + ::subxt::ext::subxt_core::storage::address::StaticStorageKey< + types::deciding_count::Param0, + >, + types::deciding_count::DecidingCount, + ::subxt::ext::subxt_core::utils::Yes, ::subxt::ext::subxt_core::utils::Yes, - (), (), > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Recovery", - "ActiveRecoveries", - ( - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), - ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_1), - ), + "TechReferenda", + "DecidingCount", + ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 104u8, 252u8, 28u8, 142u8, 48u8, 26u8, 91u8, 201u8, 184u8, 163u8, - 180u8, 197u8, 189u8, 71u8, 144u8, 88u8, 225u8, 13u8, 183u8, 84u8, - 244u8, 41u8, 164u8, 212u8, 153u8, 247u8, 191u8, 25u8, 162u8, 25u8, - 91u8, 123u8, + 203u8, 89u8, 158u8, 179u8, 194u8, 82u8, 248u8, 162u8, 93u8, 140u8, + 146u8, 51u8, 110u8, 232u8, 51u8, 1u8, 128u8, 212u8, 199u8, 14u8, 182u8, + 103u8, 47u8, 252u8, 126u8, 108u8, 166u8, 69u8, 252u8, 179u8, 126u8, + 245u8, ], ) } - #[doc = " The list of allowed proxy accounts."] + #[doc = " The metadata is a general information concerning the referendum."] + #[doc = " The `Hash` refers to the preimage of the `Preimages` provider which can be a JSON"] + #[doc = " dump or IPFS hash of a JSON file."] #[doc = ""] - #[doc = " Map from the user who can access it to the recovered account."] - pub fn proxy_iter( + #[doc = " Consider a garbage collection for a metadata of finished referendums to `unrequest` (remove)"] + #[doc = " large preimages."] + pub fn metadata_of_iter( &self, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< (), - types::proxy::Proxy, + types::metadata_of::MetadataOf, (), (), ::subxt::ext::subxt_core::utils::Yes, > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Recovery", - "Proxy", + "TechReferenda", + "MetadataOf", (), [ - 161u8, 242u8, 17u8, 183u8, 161u8, 47u8, 87u8, 110u8, 201u8, 177u8, - 199u8, 157u8, 30u8, 131u8, 49u8, 89u8, 182u8, 86u8, 152u8, 19u8, 199u8, - 33u8, 12u8, 138u8, 51u8, 215u8, 130u8, 5u8, 251u8, 115u8, 69u8, 159u8, + 159u8, 250u8, 56u8, 189u8, 247u8, 165u8, 206u8, 166u8, 91u8, 139u8, + 124u8, 164u8, 25u8, 246u8, 199u8, 36u8, 159u8, 56u8, 227u8, 136u8, 4u8, + 45u8, 193u8, 72u8, 200u8, 164u8, 39u8, 207u8, 224u8, 124u8, 191u8, + 110u8, ], ) } - #[doc = " The list of allowed proxy accounts."] + #[doc = " The metadata is a general information concerning the referendum."] + #[doc = " The `Hash` refers to the preimage of the `Preimages` provider which can be a JSON"] + #[doc = " dump or IPFS hash of a JSON file."] #[doc = ""] - #[doc = " Map from the user who can access it to the recovered account."] - pub fn proxy( + #[doc = " Consider a garbage collection for a metadata of finished referendums to `unrequest` (remove)"] + #[doc = " large preimages."] + pub fn metadata_of( &self, - _0: types::proxy::Param0, + _0: types::metadata_of::Param0, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< ::subxt::ext::subxt_core::storage::address::StaticStorageKey< - types::proxy::Param0, + types::metadata_of::Param0, >, - types::proxy::Proxy, + types::metadata_of::MetadataOf, ::subxt::ext::subxt_core::utils::Yes, (), (), > { ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( - "Recovery", - "Proxy", + "TechReferenda", + "MetadataOf", ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 161u8, 242u8, 17u8, 183u8, 161u8, 47u8, 87u8, 110u8, 201u8, 177u8, - 199u8, 157u8, 30u8, 131u8, 49u8, 89u8, 182u8, 86u8, 152u8, 19u8, 199u8, - 33u8, 12u8, 138u8, 51u8, 215u8, 130u8, 5u8, 251u8, 115u8, 69u8, 159u8, + 159u8, 250u8, 56u8, 189u8, 247u8, 165u8, 206u8, 166u8, 91u8, 139u8, + 124u8, 164u8, 25u8, 246u8, 199u8, 36u8, 159u8, 56u8, 227u8, 136u8, 4u8, + 45u8, 193u8, 72u8, 200u8, 164u8, 39u8, 207u8, 224u8, 124u8, 191u8, + 110u8, ], ) } @@ -12180,18 +10085,15 @@ pub mod api { use super::runtime_types; pub struct ConstantsApi; impl ConstantsApi { - #[doc = " The base amount of currency needed to reserve for creating a recovery configuration."] - #[doc = ""] - #[doc = " This is held for an additional storage item whose value size is"] - #[doc = " `2 + sizeof(BlockNumber, Balance)` bytes."] - pub fn config_deposit_base( + #[doc = " The minimum amount to be used as a deposit for a public referendum proposal."] + pub fn submission_deposit( &self, ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< ::core::primitive::u128, > { ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "Recovery", - "ConfigDepositBase", + "TechReferenda", + "SubmissionDeposit", [ 84u8, 157u8, 140u8, 4u8, 93u8, 57u8, 29u8, 133u8, 105u8, 200u8, 214u8, 27u8, 144u8, 208u8, 218u8, 160u8, 130u8, 109u8, 101u8, 54u8, 210u8, @@ -12199,67 +10101,293 @@ pub mod api { ], ) } - #[doc = " The amount of currency needed per additional user when creating a recovery"] - #[doc = " configuration."] + #[doc = " Maximum size of the referendum queue for a single track."] + pub fn max_queued( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "TechReferenda", + "MaxQueued", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " Maximum number of referenda that may be `Ongoing` at once, across all tracks."] #[doc = ""] - #[doc = " This is held for adding `sizeof(AccountId)` bytes more into a pre-existing storage"] - #[doc = " value."] - pub fn friend_deposit_factor( + #[doc = " This is a global admission bound enforced in `submit`. It also covers referenda"] + #[doc = " that never receive a decision deposit and therefore occupy neither a deciding"] + #[doc = " slot nor a `TrackQueue` entry, yet hold storage and a scheduler agenda slot"] + #[doc = " until the `UndecidingTimeout`."] + #[doc = ""] + #[doc = " Must be at least `MaxQueued` plus the sum of all tracks' `max_deciding` plus one,"] + #[doc = " so that the deciding slots and track queues remain fully utilizable (checked by"] + #[doc = " `integrity_test`)."] + pub fn max_active( &self, ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u128, + ::core::primitive::u32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "TechReferenda", + "MaxActive", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " The maximum number of referenda any one account may have in the `Ongoing` state"] + #[doc = " at once."] + #[doc = ""] + #[doc = " [`Config::MaxActive`] is a shared resource: without a per-account cap, any"] + #[doc = " single account passing `SubmitOrigin` could fill it with refundable-deposit"] + #[doc = " referenda and freeze submission for everyone — including the very referendum"] + #[doc = " needed to intervene — until the `UndecidingTimeout` (renewably). Size it so"] + #[doc = " that no plausible coalition of submitters can reach `MaxActive`:"] + #[doc = " `MaxActivePerAccount` × (maximum concurrent submitters) < `MaxActive`."] + pub fn max_active_per_account( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "TechReferenda", + "MaxActivePerAccount", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " Maximum encoded length of a `Lookup` proposal accepted by `submit`."] + #[doc = ""] + #[doc = " `submit` `request`s the preimage so a later `unnote_preimage` cannot delete the"] + #[doc = " bytes before enactment; that request also lets the noter reclaim their storage"] + #[doc = " deposit while the bytes stay pinned until the referendum ends. Without a size"] + #[doc = " bound, `MaxActive` × 4 MiB of deposit-free state can accumulate against only"] + #[doc = " the refundable [`Config::SubmissionDeposit`]. Size this so that the preimage"] + #[doc = " deposit for a max-sized blob does not exceed `SubmissionDeposit` — then even"] + #[doc = " after `unnote` the submission deposit still collateralizes the held bytes."] + pub fn max_proposal_size( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "TechReferenda", + "MaxProposalSize", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " The number of blocks after submission that a referendum must begin being decided by."] + #[doc = " Once this passes, then anyone may cancel the referendum."] + pub fn undeciding_timeout( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "TechReferenda", + "UndecidingTimeout", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " Quantization level for the referendum wakeup scheduler. A higher number will result in"] + #[doc = " fewer storage reads/writes needed for smaller voters, but also result in delays to the"] + #[doc = " automatic referendum status changes. Explicit servicing instructions are unaffected."] + pub fn alarm_interval( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::core::primitive::u32, + > { + ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( + "TechReferenda", + "AlarmInterval", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " A list of tracks."] + #[doc = ""] + #[doc = " Note: if the tracks are dynamic, the value in the static metadata might be inaccurate."] + pub fn tracks( + &self, + ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< + ::subxt::ext::subxt_core::alloc::vec::Vec<( + ::core::primitive::u16, + runtime_types::pallet_referenda::types::TrackDetails< + ::core::primitive::u128, + ::core::primitive::u32, + ::subxt::ext::subxt_core::alloc::string::String, + >, + )>, > { ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "Recovery", - "FriendDepositFactor", + "TechReferenda", + "Tracks", [ - 84u8, 157u8, 140u8, 4u8, 93u8, 57u8, 29u8, 133u8, 105u8, 200u8, 214u8, - 27u8, 144u8, 208u8, 218u8, 160u8, 130u8, 109u8, 101u8, 54u8, 210u8, - 136u8, 71u8, 63u8, 49u8, 237u8, 234u8, 15u8, 178u8, 98u8, 148u8, 156u8, + 35u8, 226u8, 207u8, 234u8, 184u8, 139u8, 187u8, 184u8, 128u8, 199u8, + 227u8, 15u8, 31u8, 196u8, 5u8, 207u8, 138u8, 174u8, 130u8, 201u8, + 200u8, 113u8, 86u8, 93u8, 221u8, 243u8, 229u8, 24u8, 18u8, 150u8, 56u8, + 159u8, ], ) } - #[doc = " The maximum amount of friends allowed in a recovery configuration."] + } + } + } + pub mod treasury_pallet { + use super::{root_mod, runtime_types}; + #[doc = "The `Error` enum of this pallet."] + pub type Error = runtime_types::pallet_treasury::pallet::Error; + #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] + pub type Call = runtime_types::pallet_treasury::pallet::Call; + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + pub mod types { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "Set the treasury account. Root only. Zero address is rejected (funds would be locked)."] + #[doc = ""] + #[doc = "**Important**: This only changes where *future* treasury credits are sent. Any balance"] + #[doc = "that has already accumulated in the current treasury account is NOT automatically"] + #[doc = "migrated to the new account. If you need to move existing funds, perform a separate"] + #[doc = "balance transfer (e.g., via governance proposal) after updating the account."] + pub struct SetTreasuryAccount { + pub account: set_treasury_account::Account, + } + pub mod set_treasury_account { + use super::runtime_types; + pub type Account = ::subxt::ext::subxt_core::utils::AccountId32; + } + impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for SetTreasuryAccount { + const PALLET: &'static str = "TreasuryPallet"; + const CALL: &'static str = "set_treasury_account"; + } + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Set the treasury account. Root only. Zero address is rejected (funds would be locked)."] #[doc = ""] - #[doc = " NOTE: The threshold programmed in this Pallet uses u16, so it does"] - #[doc = " not really make sense to have a limit here greater than u16::MAX."] - #[doc = " But also, that is a lot more than you should probably set this value"] - #[doc = " to anyway..."] - pub fn max_friends( + #[doc = "**Important**: This only changes where *future* treasury credits are sent. Any balance"] + #[doc = "that has already accumulated in the current treasury account is NOT automatically"] + #[doc = "migrated to the new account. If you need to move existing funds, perform a separate"] + #[doc = "balance transfer (e.g., via governance proposal) after updating the account."] + pub fn set_treasury_account( &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u32, - > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "Recovery", - "MaxFriends", + account: types::set_treasury_account::Account, + ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload + { + ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( + "TreasuryPallet", + "set_treasury_account", + types::SetTreasuryAccount { account }, [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, + 221u8, 22u8, 186u8, 39u8, 76u8, 65u8, 143u8, 149u8, 126u8, 244u8, + 227u8, 129u8, 16u8, 183u8, 56u8, 248u8, 82u8, 131u8, 255u8, 246u8, + 243u8, 145u8, 255u8, 5u8, 125u8, 142u8, 201u8, 38u8, 185u8, 124u8, + 76u8, 167u8, ], ) } - #[doc = " The base amount of currency needed to reserve for starting a recovery."] - #[doc = ""] - #[doc = " This is primarily held for deterring malicious recovery attempts, and should"] - #[doc = " have a value large enough that a bad actor would choose not to place this"] - #[doc = " deposit. It also acts to fund additional storage item whose value size is"] - #[doc = " `sizeof(BlockNumber, Balance + T * AccountId)` bytes. Where T is a configurable"] - #[doc = " threshold."] - pub fn recovery_deposit( + } + } + #[doc = "The `Event` enum of this pallet"] + pub type Event = runtime_types::pallet_treasury::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] + #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] + #[doc = "The treasury account was updated."] + #[doc = ""] + #[doc = "Note: This only redirects where future treasury credits are sent. Any balance"] + #[doc = "accumulated in the old account remains there and is NOT automatically migrated."] + #[doc = "Use a separate balance transfer if funds need to be moved."] + pub struct TreasuryAccountUpdated { + pub old_account: treasury_account_updated::OldAccount, + pub new_account: treasury_account_updated::NewAccount, + } + pub mod treasury_account_updated { + use super::runtime_types; + pub type OldAccount = + ::core::option::Option<::subxt::ext::subxt_core::utils::AccountId32>; + pub type NewAccount = ::subxt::ext::subxt_core::utils::AccountId32; + } + impl ::subxt::ext::subxt_core::events::StaticEvent for TreasuryAccountUpdated { + const PALLET: &'static str = "TreasuryPallet"; + const EVENT: &'static str = "TreasuryAccountUpdated"; + } + } + pub mod storage { + use super::runtime_types; + pub mod types { + use super::runtime_types; + pub mod treasury_account { + use super::runtime_types; + pub type TreasuryAccount = ::subxt::ext::subxt_core::utils::AccountId32; + } + } + pub struct StorageApi; + impl StorageApi { + #[doc = " The treasury account that holds treasury funds."] + pub fn treasury_account( &self, - ) -> ::subxt::ext::subxt_core::constants::address::StaticAddress< - ::core::primitive::u128, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::treasury_account::TreasuryAccount, + ::subxt::ext::subxt_core::utils::Yes, + (), + (), > { - ::subxt::ext::subxt_core::constants::address::StaticAddress::new_static( - "Recovery", - "RecoveryDeposit", + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "TreasuryPallet", + "TreasuryAccount", + (), [ - 84u8, 157u8, 140u8, 4u8, 93u8, 57u8, 29u8, 133u8, 105u8, 200u8, 214u8, - 27u8, 144u8, 208u8, 218u8, 160u8, 130u8, 109u8, 101u8, 54u8, 210u8, - 136u8, 71u8, 63u8, 49u8, 237u8, 234u8, 15u8, 178u8, 98u8, 148u8, 156u8, + 25u8, 40u8, 39u8, 114u8, 80u8, 247u8, 49u8, 5u8, 9u8, 118u8, 249u8, + 36u8, 77u8, 73u8, 229u8, 167u8, 107u8, 254u8, 175u8, 199u8, 203u8, + 238u8, 166u8, 158u8, 155u8, 209u8, 155u8, 219u8, 191u8, 204u8, 237u8, + 227u8, ], ) } @@ -12298,7 +10426,8 @@ pub mod api { #[doc = "The multisig address is deterministically derived from:"] #[doc = "hash(pallet_id || sorted_signers || threshold || nonce)"] #[doc = ""] - #[doc = "Signers are automatically sorted before hashing, so order doesn't matter."] + #[doc = "Signers are sorted before hashing, so order doesn't matter."] + #[doc = "Duplicate accounts are rejected."] #[doc = ""] #[doc = "Economic costs:"] #[doc = "- MultisigFee: burned immediately (spam prevention)"] @@ -12523,26 +10652,39 @@ pub mod api { #[doc = "Can be called by any signer of the multisig once the proposal has reached"] #[doc = "the approval threshold (status = Approved). The proposal must not be expired."] #[doc = ""] + #[doc = "The executor resubmits the proposal's inner call; execution proceeds only"] + #[doc = "if it is byte-equal to the payload stored at `proposal_id` — the same"] + #[doc = "binding `approve` enforces. This serves two purposes:"] + #[doc = "- **Clearsigning:** the executor's (hardware) wallet displays and signs the actual call"] + #[doc = " being dispatched, not an opaque proposal id."] + #[doc = "- **Self-describing weight:** the executing extrinsic carries the inner call, so its"] + #[doc = " declared weight carries the inner call's own declared weight (refunded to actuals"] + #[doc = " post-dispatch) instead of reserving a flat `MaxInnerCallWeight`, and runtime"] + #[doc = " transaction extensions can inspect the inner call and price its side effects"] + #[doc = " (account-reap cleanup, transfer-proof recording) exactly as they do for directly"] + #[doc = " submitted calls. Nothing about the dispatch is invisible to pre-dispatch admission or"] + #[doc = " fees. (Only the bookkeeping term is reserved at `MaxCallSize`, since the stored bytes'"] + #[doc = " length is unknown pre-dispatch; the unused remainder is refunded.)"] + #[doc = ""] #[doc = "On execution:"] - #[doc = "- The call is decoded and dispatched as the multisig account"] + #[doc = "- The call is dispatched as the multisig account"] #[doc = "- Proposal is removed from storage"] #[doc = "- Deposit is returned to the proposer"] #[doc = ""] #[doc = "Parameters:"] #[doc = "- `multisig_address`: The multisig account"] #[doc = "- `proposal_id`: ID (nonce) of the proposal to execute"] - #[doc = ""] - #[doc = "Note: The weight charged includes both multisig bookkeeping and MaxInnerCallWeight."] - #[doc = "Actual weight is refunded based on the inner call's post-dispatch info."] - #[doc = "The inner call's weight is validated against MaxInnerCallWeight at propose time."] + #[doc = "- `call`: The proposal's inner call, byte-equal to the stored payload"] pub struct Execute { pub multisig_address: execute::MultisigAddress, pub proposal_id: execute::ProposalId, + pub call: ::subxt::ext::subxt_core::alloc::boxed::Box, } pub mod execute { use super::runtime_types; pub type MultisigAddress = ::subxt::ext::subxt_core::utils::AccountId32; pub type ProposalId = ::core::primitive::u32; + pub type Call = runtime_types::quantus_runtime::RuntimeCall; } impl ::subxt::ext::subxt_core::blocks::StaticExtrinsic for Execute { const PALLET: &'static str = "Multisig"; @@ -12561,7 +10703,8 @@ pub mod api { #[doc = "The multisig address is deterministically derived from:"] #[doc = "hash(pallet_id || sorted_signers || threshold || nonce)"] #[doc = ""] - #[doc = "Signers are automatically sorted before hashing, so order doesn't matter."] + #[doc = "Signers are sorted before hashing, so order doesn't matter."] + #[doc = "Duplicate accounts are rejected."] #[doc = ""] #[doc = "Economic costs:"] #[doc = "- MultisigFee: burned immediately (spam prevention)"] @@ -12735,31 +10878,47 @@ pub mod api { #[doc = "Can be called by any signer of the multisig once the proposal has reached"] #[doc = "the approval threshold (status = Approved). The proposal must not be expired."] #[doc = ""] + #[doc = "The executor resubmits the proposal's inner call; execution proceeds only"] + #[doc = "if it is byte-equal to the payload stored at `proposal_id` — the same"] + #[doc = "binding `approve` enforces. This serves two purposes:"] + #[doc = "- **Clearsigning:** the executor's (hardware) wallet displays and signs the actual call"] + #[doc = " being dispatched, not an opaque proposal id."] + #[doc = "- **Self-describing weight:** the executing extrinsic carries the inner call, so its"] + #[doc = " declared weight carries the inner call's own declared weight (refunded to actuals"] + #[doc = " post-dispatch) instead of reserving a flat `MaxInnerCallWeight`, and runtime"] + #[doc = " transaction extensions can inspect the inner call and price its side effects"] + #[doc = " (account-reap cleanup, transfer-proof recording) exactly as they do for directly"] + #[doc = " submitted calls. Nothing about the dispatch is invisible to pre-dispatch admission or"] + #[doc = " fees. (Only the bookkeeping term is reserved at `MaxCallSize`, since the stored bytes'"] + #[doc = " length is unknown pre-dispatch; the unused remainder is refunded.)"] + #[doc = ""] #[doc = "On execution:"] - #[doc = "- The call is decoded and dispatched as the multisig account"] + #[doc = "- The call is dispatched as the multisig account"] #[doc = "- Proposal is removed from storage"] #[doc = "- Deposit is returned to the proposer"] #[doc = ""] #[doc = "Parameters:"] #[doc = "- `multisig_address`: The multisig account"] #[doc = "- `proposal_id`: ID (nonce) of the proposal to execute"] - #[doc = ""] - #[doc = "Note: The weight charged includes both multisig bookkeeping and MaxInnerCallWeight."] - #[doc = "Actual weight is refunded based on the inner call's post-dispatch info."] - #[doc = "The inner call's weight is validated against MaxInnerCallWeight at propose time."] + #[doc = "- `call`: The proposal's inner call, byte-equal to the stored payload"] pub fn execute( &self, multisig_address: types::execute::MultisigAddress, proposal_id: types::execute::ProposalId, + call: types::execute::Call, ) -> ::subxt::ext::subxt_core::tx::payload::StaticPayload { ::subxt::ext::subxt_core::tx::payload::StaticPayload::new_static( "Multisig", "execute", - types::Execute { multisig_address, proposal_id }, + types::Execute { + multisig_address, + proposal_id, + call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), + }, [ - 209u8, 110u8, 225u8, 231u8, 188u8, 230u8, 192u8, 42u8, 43u8, 233u8, - 158u8, 149u8, 58u8, 203u8, 142u8, 44u8, 40u8, 27u8, 211u8, 194u8, 26u8, - 7u8, 7u8, 254u8, 29u8, 245u8, 230u8, 195u8, 82u8, 108u8, 1u8, 27u8, + 167u8, 47u8, 21u8, 112u8, 52u8, 132u8, 255u8, 119u8, 118u8, 198u8, + 164u8, 58u8, 36u8, 95u8, 126u8, 165u8, 255u8, 146u8, 87u8, 66u8, 2u8, + 29u8, 233u8, 114u8, 13u8, 99u8, 107u8, 78u8, 75u8, 197u8, 239u8, 60u8, ], ) } @@ -13821,17 +11980,17 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A new leaf was inserted into the tree."] + #[doc = "A new leaf was inserted into the tree. The root including this leaf is"] + #[doc = "computed at the end of the block and published in the block header. The"] + #[doc = "leaf hash is deliberately not included: it is derivable from `Leaves`"] + #[doc = "(and served by the RPC), and hashing it here would double the per-leaf"] + #[doc = "Poseidon work the batched settlement saves."] pub struct LeafInserted { pub index: leaf_inserted::Index, - pub leaf_hash: leaf_inserted::LeafHash, - pub new_root: leaf_inserted::NewRoot, } pub mod leaf_inserted { use super::runtime_types; pub type Index = ::core::primitive::u64; - pub type LeafHash = [::core::primitive::u8; 32usize]; - pub type NewRoot = [::core::primitive::u8; 32usize]; } impl ::subxt::ext::subxt_core::events::StaticEvent for LeafInserted { const PALLET: &'static str = "ZkTree"; @@ -13887,6 +12046,10 @@ pub mod api { use super::runtime_types; pub type Root = [::core::primitive::u8; 32usize]; } + pub mod unprocessed_leaves { + use super::runtime_types; + pub type UnprocessedLeaves = ::core::primitive::u64; + } } pub struct StorageApi; impl StorageApi { @@ -14029,6 +12192,10 @@ pub mod api { ) } #[doc = " Current root hash of the tree."] + #[doc = ""] + #[doc = " Covers exactly the first `LeafCount - UnprocessedLeaves` leaves: root"] + #[doc = " recomputation is batched once per block in `on_finalize`, so during block"] + #[doc = " execution this is the root as of the end of the previous block."] pub fn root( &self, ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< @@ -14049,6 +12216,28 @@ pub mod api { ], ) } + #[doc = " Number of trailing leaves appended this block but not yet folded into"] + #[doc = " `Nodes`/`Root`. Always drained back to 0 by `on_finalize`."] + pub fn unprocessed_leaves( + &self, + ) -> ::subxt::ext::subxt_core::storage::address::StaticAddress< + (), + types::unprocessed_leaves::UnprocessedLeaves, + ::subxt::ext::subxt_core::utils::Yes, + ::subxt::ext::subxt_core::utils::Yes, + (), + > { + ::subxt::ext::subxt_core::storage::address::StaticAddress::new_static( + "ZkTree", + "UnprocessedLeaves", + (), + [ + 41u8, 228u8, 77u8, 158u8, 143u8, 146u8, 87u8, 14u8, 29u8, 31u8, 164u8, + 212u8, 73u8, 140u8, 188u8, 91u8, 107u8, 147u8, 190u8, 145u8, 41u8, + 84u8, 37u8, 7u8, 148u8, 34u8, 42u8, 235u8, 182u8, 200u8, 45u8, 159u8, + ], + ) + } } } } @@ -14077,7 +12266,9 @@ pub mod api { #[doc = "Pay the largest valid claim on `schedule_id` to its beneficiary. Payouts are"] #[doc = "rounded down to [`Config::PayoutQuantum`], must meet [`Config::MinimumPayout`],"] #[doc = "and reserve at least one minimum-sized final claim unless the schedule is fully"] - #[doc = "vested."] + #[doc = "vested. Non-final payouts are further rounded down to"] + #[doc = "[`NON_FINAL_PAYOUT_QUANTA`] leaf quanta; the leftover stays on the schedule"] + #[doc = "until a later claim or the exact final payout."] #[doc = ""] #[doc = "Permissionless: any signed account may call this for any schedule; the payout"] #[doc = "always goes to the stored beneficiary. This is the only claim path for"] @@ -14136,13 +12327,11 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "End a schedule early: the still-unpaid vested part (rounded down to a"] - #[doc = "[`Config::PayoutQuantum`] multiple) goes to the beneficiary, everything else"] - #[doc = "this schedule still holds — the unvested remainder plus any sub-quantum"] - #[doc = "vested dust — returns to the treasury, and the schedule is removed. The"] - #[doc = "treasury is signature-controlled and needs no wormhole leaf, so dust is safe"] - #[doc = "there but would be stranded on a keyless beneficiary. A non-zero beneficiary"] - #[doc = "payout below [`Config::MinimumPayout`] is rejected without ending the schedule."] + #[doc = "End a schedule early: the still-unpaid vested part (rounded to the nearest"] + #[doc = "[`Config::PayoutQuantum`]) goes to the beneficiary if it meets"] + #[doc = "[`Config::MinimumPayout`]; otherwise that sliver is refunded with the"] + #[doc = "unvested remainder. The treasury is signature-controlled and needs no"] + #[doc = "wormhole leaf, so the refund is not quantized and never blocks ending."] pub struct EndSchedule { pub schedule_id: end_schedule::ScheduleId, } @@ -14165,8 +12354,12 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Settle any payout a permissionless claim could currently force, then change the"] - #[doc = "beneficiary. This makes retargeting independent of claim transaction ordering."] + #[doc = "Change the schedule's beneficiary without paying anything out. A retarget"] + #[doc = "replaces the wallet of the *same* grantee (lost-key remedy): the old address"] + #[doc = "may be lost or stolen, so settling it would burn funds or pay the thief."] + #[doc = "Everything vested but unclaimed stays on the schedule and goes to the new"] + #[doc = "wallet at its next claim. (A permissionless claim landing before the"] + #[doc = "retarget still pays the old address, so rotate promptly.)"] pub struct RetargetSchedule { pub schedule_id: retarget_schedule::ScheduleId, pub new_beneficiary: retarget_schedule::NewBeneficiary, @@ -14186,7 +12379,9 @@ pub mod api { #[doc = "Pay the largest valid claim on `schedule_id` to its beneficiary. Payouts are"] #[doc = "rounded down to [`Config::PayoutQuantum`], must meet [`Config::MinimumPayout`],"] #[doc = "and reserve at least one minimum-sized final claim unless the schedule is fully"] - #[doc = "vested."] + #[doc = "vested. Non-final payouts are further rounded down to"] + #[doc = "[`NON_FINAL_PAYOUT_QUANTA`] leaf quanta; the leftover stays on the schedule"] + #[doc = "until a later claim or the exact final payout."] #[doc = ""] #[doc = "Permissionless: any signed account may call this for any schedule; the payout"] #[doc = "always goes to the stored beneficiary. This is the only claim path for"] @@ -14228,13 +12423,11 @@ pub mod api { ], ) } - #[doc = "End a schedule early: the still-unpaid vested part (rounded down to a"] - #[doc = "[`Config::PayoutQuantum`] multiple) goes to the beneficiary, everything else"] - #[doc = "this schedule still holds — the unvested remainder plus any sub-quantum"] - #[doc = "vested dust — returns to the treasury, and the schedule is removed. The"] - #[doc = "treasury is signature-controlled and needs no wormhole leaf, so dust is safe"] - #[doc = "there but would be stranded on a keyless beneficiary. A non-zero beneficiary"] - #[doc = "payout below [`Config::MinimumPayout`] is rejected without ending the schedule."] + #[doc = "End a schedule early: the still-unpaid vested part (rounded to the nearest"] + #[doc = "[`Config::PayoutQuantum`]) goes to the beneficiary if it meets"] + #[doc = "[`Config::MinimumPayout`]; otherwise that sliver is refunded with the"] + #[doc = "unvested remainder. The treasury is signature-controlled and needs no"] + #[doc = "wormhole leaf, so the refund is not quantized and never blocks ending."] pub fn end_schedule( &self, schedule_id: types::end_schedule::ScheduleId, @@ -14251,8 +12444,12 @@ pub mod api { ], ) } - #[doc = "Settle any payout a permissionless claim could currently force, then change the"] - #[doc = "beneficiary. This makes retargeting independent of claim transaction ordering."] + #[doc = "Change the schedule's beneficiary without paying anything out. A retarget"] + #[doc = "replaces the wallet of the *same* grantee (lost-key remedy): the old address"] + #[doc = "may be lost or stolen, so settling it would burn funds or pay the thief."] + #[doc = "Everything vested but unclaimed stays on the schedule and goes to the new"] + #[doc = "wallet at its next claim. (A permissionless claim landing before the"] + #[doc = "retarget still pays the old address, so rotate promptly.)"] pub fn retarget_schedule( &self, schedule_id: types::retarget_schedule::ScheduleId, @@ -14361,19 +12558,19 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "A schedule's beneficiary was changed after settling any currently claimable payout."] + #[doc = "A schedule's beneficiary was changed. Nothing was paid out: the retarget"] + #[doc = "replaces the same grantee's wallet, so the accrued entitlement follows the"] + #[doc = "schedule to the new address."] pub struct ScheduleRetargeted { pub schedule_id: schedule_retargeted::ScheduleId, pub old_beneficiary: schedule_retargeted::OldBeneficiary, pub new_beneficiary: schedule_retargeted::NewBeneficiary, - pub vested_paid: schedule_retargeted::VestedPaid, } pub mod schedule_retargeted { use super::runtime_types; pub type ScheduleId = ::core::primitive::u64; pub type OldBeneficiary = ::subxt::ext::subxt_core::utils::AccountId32; pub type NewBeneficiary = ::subxt::ext::subxt_core::utils::AccountId32; - pub type VestedPaid = ::core::primitive::u128; } impl ::subxt::ext::subxt_core::events::StaticEvent for ScheduleRetargeted { const PALLET: &'static str = "Vesting"; @@ -14572,6 +12769,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -14699,6 +12898,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -14725,6 +12926,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -14757,6 +12960,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -14963,6 +13168,21 @@ pub mod api { )] pub struct CheckWeight; } + pub mod weight_reclaim { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub struct WeightReclaim; + } } pub mod limits { use super::runtime_types; @@ -15027,6 +13247,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -15306,6 +13528,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -15331,21 +13555,6 @@ pub mod api { #[codec(compact)] value: ::core::primitive::u128, }, - #[codec(index = 2)] - #[doc = "Exactly as `transfer_allow_death`, except the origin must be root and the source account"] - #[doc = "may be specified."] - force_transfer { - source: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - dest: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - #[codec(compact)] - value: ::core::primitive::u128, - }, #[codec(index = 3)] #[doc = "Same as the [`transfer_allow_death`] call, but with a check that the transfer will not"] #[doc = "kill the origin account."] @@ -15384,54 +13593,6 @@ pub mod api { >, keep_alive: ::core::primitive::bool, }, - #[codec(index = 5)] - #[doc = "Unreserve some balance from a user by force."] - #[doc = ""] - #[doc = "Can only be called by ROOT."] - force_unreserve { - who: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - #[doc = "Upgrade a specified account."] - #[doc = ""] - #[doc = "- `origin`: Must be `Signed`."] - #[doc = "- `who`: The account to be upgraded."] - #[doc = ""] - #[doc = "This will waive the transaction fee if at least all but 10% of the accounts needed to"] - #[doc = "be upgraded. (We let some not have to be upgraded just in order to allow for the"] - #[doc = "possibility of churn)."] - upgrade_accounts { - who: ::subxt::ext::subxt_core::alloc::vec::Vec< - ::subxt::ext::subxt_core::utils::AccountId32, - >, - }, - #[codec(index = 8)] - #[doc = "Set the regular balance of a given account."] - #[doc = ""] - #[doc = "The dispatch origin for this call is `root`."] - force_set_balance { - who: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - #[codec(index = 9)] - #[doc = "Adjust the total issuance in a saturating way."] - #[doc = ""] - #[doc = "Can only be called by root and always needs a positive `delta`."] - #[doc = ""] - #[doc = "# Example"] - force_adjust_total_issuance { - direction: runtime_types::pallet_balances::types::AdjustmentDirection, - #[codec(compact)] - delta: ::core::primitive::u128, - }, #[codec(index = 10)] #[doc = "Burn the specified liquid free balance from the origin account."] #[doc = ""] @@ -15489,12 +13650,6 @@ pub mod api { #[codec(index = 9)] #[doc = "Number of freezes exceed `MaxFreezes`."] TooManyFreezes, - #[codec(index = 10)] - #[doc = "The issuance cannot be modified since it is already deactivated."] - IssuanceDeactivated, - #[codec(index = 11)] - #[doc = "The delta cannot be zero."] - DeltaZero, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -15639,26 +13794,20 @@ pub mod api { amount: ::core::primitive::u128, }, #[codec(index = 23)] - #[doc = "The `TotalIssuance` was forcefully changed."] - TotalIssuanceForced { - old: ::core::primitive::u128, - new: ::core::primitive::u128, - }, - #[codec(index = 24)] #[doc = "Some balance was placed on hold."] Held { reason: runtime_types::quantus_runtime::RuntimeHoldReason, who: ::subxt::ext::subxt_core::utils::AccountId32, amount: ::core::primitive::u128, }, - #[codec(index = 25)] + #[codec(index = 24)] #[doc = "Held balance was burned from an account."] BurnedHeld { reason: runtime_types::quantus_runtime::RuntimeHoldReason, who: ::subxt::ext::subxt_core::utils::AccountId32, amount: ::core::primitive::u128, }, - #[codec(index = 26)] + #[codec(index = 25)] #[doc = "A transfer of `amount` on hold from `source` to `dest` was initiated."] TransferOnHold { reason: runtime_types::quantus_runtime::RuntimeHoldReason, @@ -15666,7 +13815,7 @@ pub mod api { dest: ::subxt::ext::subxt_core::utils::AccountId32, amount: ::core::primitive::u128, }, - #[codec(index = 27)] + #[codec(index = 26)] #[doc = "The `transferred` balance is placed on hold at the `dest` account."] TransferAndHold { reason: runtime_types::quantus_runtime::RuntimeHoldReason, @@ -15674,14 +13823,14 @@ pub mod api { dest: ::subxt::ext::subxt_core::utils::AccountId32, transferred: ::core::primitive::u128, }, - #[codec(index = 28)] + #[codec(index = 27)] #[doc = "Some balance was released from hold."] Released { reason: runtime_types::quantus_runtime::RuntimeHoldReason, who: ::subxt::ext::subxt_core::utils::AccountId32, amount: ::core::primitive::u128, }, - #[codec(index = 29)] + #[codec(index = 28)] #[doc = "An unexpected/defensive event was triggered."] Unexpected(runtime_types::pallet_balances::pallet::UnexpectedKind), } @@ -15733,23 +13882,6 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - pub enum AdjustmentDirection { - #[codec(index = 0)] - Increase, - #[codec(index = 1)] - Decrease, - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] pub struct BalanceLock<_0> { pub id: [::core::primitive::u8; 8usize], pub amount: _0, @@ -15833,17 +13965,14 @@ pub mod api { total: ::core::primitive::u128, }, #[codec(index = 2)] - #[doc = "Rewards were sent to Treasury when no miner was specified"] - TreasuryRewarded { reward: ::core::primitive::u128 }, + #[doc = "No miner in the digest; the credit stays in [`CollectedFees`] for the next block."] + PayoutDeferred { amount: ::core::primitive::u128 }, #[codec(index = 3)] - #[doc = "Miner reward was redirected to treasury due to mint failure"] - MinerRewardRedirected { + #[doc = "Miner mint failed; the credit stays in [`CollectedFees`] for retry."] + MinerMintFailed { miner: ::subxt::ext::subxt_core::utils::AccountId32, reward: ::core::primitive::u128, }, - #[codec(index = 4)] - #[doc = "Treasury mint failed; amount retained in [`CollectedFees`] for retry."] - TreasuryMintFailed { reward: ::core::primitive::u128 }, } } } @@ -15855,6 +13984,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -15875,7 +14006,8 @@ pub mod api { #[doc = "The multisig address is deterministically derived from:"] #[doc = "hash(pallet_id || sorted_signers || threshold || nonce)"] #[doc = ""] - #[doc = "Signers are automatically sorted before hashing, so order doesn't matter."] + #[doc = "Signers are sorted before hashing, so order doesn't matter."] + #[doc = "Duplicate accounts are rejected."] #[doc = ""] #[doc = "Economic costs:"] #[doc = "- MultisigFee: burned immediately (spam prevention)"] @@ -15984,21 +14116,35 @@ pub mod api { #[doc = "Can be called by any signer of the multisig once the proposal has reached"] #[doc = "the approval threshold (status = Approved). The proposal must not be expired."] #[doc = ""] + #[doc = "The executor resubmits the proposal's inner call; execution proceeds only"] + #[doc = "if it is byte-equal to the payload stored at `proposal_id` — the same"] + #[doc = "binding `approve` enforces. This serves two purposes:"] + #[doc = "- **Clearsigning:** the executor's (hardware) wallet displays and signs the actual call"] + #[doc = " being dispatched, not an opaque proposal id."] + #[doc = "- **Self-describing weight:** the executing extrinsic carries the inner call, so its"] + #[doc = " declared weight carries the inner call's own declared weight (refunded to actuals"] + #[doc = " post-dispatch) instead of reserving a flat `MaxInnerCallWeight`, and runtime"] + #[doc = " transaction extensions can inspect the inner call and price its side effects"] + #[doc = " (account-reap cleanup, transfer-proof recording) exactly as they do for directly"] + #[doc = " submitted calls. Nothing about the dispatch is invisible to pre-dispatch admission or"] + #[doc = " fees. (Only the bookkeeping term is reserved at `MaxCallSize`, since the stored bytes'"] + #[doc = " length is unknown pre-dispatch; the unused remainder is refunded.)"] + #[doc = ""] #[doc = "On execution:"] - #[doc = "- The call is decoded and dispatched as the multisig account"] + #[doc = "- The call is dispatched as the multisig account"] #[doc = "- Proposal is removed from storage"] #[doc = "- Deposit is returned to the proposer"] #[doc = ""] #[doc = "Parameters:"] #[doc = "- `multisig_address`: The multisig account"] #[doc = "- `proposal_id`: ID (nonce) of the proposal to execute"] - #[doc = ""] - #[doc = "Note: The weight charged includes both multisig bookkeeping and MaxInnerCallWeight."] - #[doc = "Actual weight is refunded based on the inner call's post-dispatch info."] - #[doc = "The inner call's weight is validated against MaxInnerCallWeight at propose time."] + #[doc = "- `call`: The proposal's inner call, byte-equal to the stored payload"] execute { multisig_address: ::subxt::ext::subxt_core::utils::AccountId32, proposal_id: ::core::primitive::u32, + call: ::subxt::ext::subxt_core::alloc::boxed::Box< + runtime_types::quantus_runtime::RuntimeCall, + >, }, } #[derive( @@ -16093,6 +14239,9 @@ pub mod api { #[codec(index = 25)] #[doc = "Provided call does not match the stored proposal payload"] CallMismatch, + #[codec(index = 26)] + #[doc = "Signer list contains the same account more than once"] + DuplicateSigners, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -16231,6 +14380,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -16251,287 +14402,29 @@ pub mod api { #[codec(index = 1)] #[doc = "Clear an unrequested preimage from the runtime storage."] #[doc = ""] - #[doc = "If `len` is provided, then it will be a much cheaper operation."] - #[doc = ""] - #[doc = "- `hash`: The hash of the preimage to be removed from the store."] - #[doc = "- `len`: The length of the preimage of `hash`."] - unnote_preimage { hash: ::subxt::ext::subxt_core::utils::H256 }, - #[codec(index = 2)] - #[doc = "Request a preimage be uploaded to the chain without paying any fees or deposits."] - #[doc = ""] - #[doc = "If the preimage requests has already been provided on-chain, we unreserve any deposit"] - #[doc = "a user may have paid, and take the control of the preimage out of their hands."] - request_preimage { hash: ::subxt::ext::subxt_core::utils::H256 }, - #[codec(index = 3)] - #[doc = "Clear a previously made request for a preimage."] - #[doc = ""] - #[doc = "NOTE: THIS MUST NOT BE CALLED ON `hash` MORE TIMES THAN `request_preimage`."] - unrequest_preimage { hash: ::subxt::ext::subxt_core::utils::H256 }, - #[codec(index = 4)] - #[doc = "Ensure that the bulk of pre-images is upgraded."] - #[doc = ""] - #[doc = "The caller pays no fee if at least 90% of pre-images were successfully updated."] - ensure_updated { - hashes: ::subxt::ext::subxt_core::alloc::vec::Vec< - ::subxt::ext::subxt_core::utils::H256, - >, - }, - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "The `Error` enum of this pallet."] - pub enum Error { - #[codec(index = 0)] - #[doc = "Preimage is too large to store on-chain."] - TooBig, - #[codec(index = 1)] - #[doc = "Preimage has already been noted on-chain."] - AlreadyNoted, - #[codec(index = 2)] - #[doc = "The user is not authorized to perform this action."] - NotAuthorized, - #[codec(index = 3)] - #[doc = "The preimage cannot be removed since it has not yet been noted."] - NotNoted, - #[codec(index = 4)] - #[doc = "A preimage may not be removed when there are outstanding requests."] - Requested, - #[codec(index = 5)] - #[doc = "The preimage request cannot be removed since no outstanding requests exist."] - NotRequested, - #[codec(index = 6)] - #[doc = "More than `MAX_HASH_UPGRADE_BULK_COUNT` hashes were requested to be upgraded at once."] - TooMany, - #[codec(index = 7)] - #[doc = "Too few hashes were requested to be upgraded (i.e. zero)."] - TooFew, - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "The `Event` enum of this pallet"] - pub enum Event { - #[codec(index = 0)] - #[doc = "A preimage has been noted."] - Noted { hash: ::subxt::ext::subxt_core::utils::H256 }, - #[codec(index = 1)] - #[doc = "A preimage has been requested."] - Requested { hash: ::subxt::ext::subxt_core::utils::H256 }, - #[codec(index = 2)] - #[doc = "A preimage has ben cleared."] - Cleared { hash: ::subxt::ext::subxt_core::utils::H256 }, - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - pub enum HoldReason { - #[codec(index = 0)] - Preimage, - } - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub enum OldRequestStatus<_0, _1> { - #[codec(index = 0)] - Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, - #[codec(index = 1)] - Requested { - deposit: ::core::option::Option<(_0, _1)>, - count: ::core::primitive::u32, - len: ::core::option::Option<::core::primitive::u32>, - }, - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub enum RequestStatus<_0, _1> { - #[codec(index = 0)] - Unrequested { ticket: (_0, _1), len: ::core::primitive::u32 }, - #[codec(index = 1)] - Requested { - maybe_ticket: ::core::option::Option<(_0, _1)>, - count: ::core::primitive::u32, - maybe_len: ::core::option::Option<::core::primitive::u32>, - }, - } - } - pub mod pallet_qpow { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "The `Event` enum of this pallet"] - pub enum Event { - #[codec(index = 0)] - ProofSubmitted { - nonce: [::core::primitive::u8; 64usize], - difficulty: runtime_types::primitive_types::U512, - hash_achieved: runtime_types::primitive_types::U512, - }, - #[codec(index = 1)] - DifficultyAdjusted { - old_difficulty: runtime_types::primitive_types::U512, - new_difficulty: runtime_types::primitive_types::U512, - observed_block_time: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_ranked_collective { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" - )] - #[encode_as_type( - crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" - )] - #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] - pub enum Call { - #[codec(index = 0)] - #[doc = "Introduce a new member."] - #[doc = ""] - #[doc = "- `origin`: Must be the `AddOrigin`."] - #[doc = "- `who`: Account of non-member which will become a member."] - #[doc = ""] - #[doc = "Weight: `O(1)`"] - add_member { - who: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - }, - #[codec(index = 1)] - #[doc = "Increment the rank of an existing member by one."] - #[doc = ""] - #[doc = "- `origin`: Must be the `PromoteOrigin`."] - #[doc = "- `who`: Account of existing member."] - #[doc = ""] - #[doc = "Weight: `O(1)`"] - promote_member { - who: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - }, - #[codec(index = 2)] - #[doc = "Decrement the rank of an existing member by one. If the member is already at rank zero,"] - #[doc = "then they are removed entirely."] - #[doc = ""] - #[doc = "- `origin`: Must be the `DemoteOrigin`."] - #[doc = "- `who`: Account of existing member of rank greater than zero."] - #[doc = ""] - #[doc = "Weight: `O(1)`, less if the member's index is highest in its rank."] - demote_member { - who: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - }, - #[codec(index = 3)] - #[doc = "Remove the member entirely."] - #[doc = ""] - #[doc = "- `origin`: Must be the `RemoveOrigin`."] - #[doc = "- `who`: Account of existing member of rank greater than zero."] - #[doc = "- `min_rank`: The rank of the member or greater."] - #[doc = ""] - #[doc = "Weight: `O(min_rank)`."] - remove_member { - who: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - min_rank: ::core::primitive::u16, - }, - #[codec(index = 4)] - #[doc = "Add an aye or nay vote for the sender to the given proposal."] - #[doc = ""] - #[doc = "- `origin`: Must be `Signed` by a member account."] - #[doc = "- `poll`: Index of a poll which is ongoing."] - #[doc = "- `aye`: `true` if the vote is to approve the proposal, `false` otherwise."] - #[doc = ""] - #[doc = "Transaction fees are be waived if the member is voting on any particular proposal"] - #[doc = "for the first time and the call is successful. Subsequent vote changes will charge a"] - #[doc = "fee."] - #[doc = ""] - #[doc = "Weight: `O(1)`, less if there was no previous vote on the poll by the member."] - vote { poll: ::core::primitive::u32, aye: ::core::primitive::bool }, - #[codec(index = 5)] - #[doc = "Remove votes from the given poll. It must have ended."] + #[doc = "If `len` is provided, then it will be a much cheaper operation."] #[doc = ""] - #[doc = "- `origin`: Must be `Signed` by any account."] - #[doc = "- `poll_index`: Index of a poll which is completed and for which votes continue to"] - #[doc = " exist."] - #[doc = "- `max`: Maximum number of vote items from remove in this call."] + #[doc = "- `hash`: The hash of the preimage to be removed from the store."] + #[doc = "- `len`: The length of the preimage of `hash`."] + unnote_preimage { hash: ::subxt::ext::subxt_core::utils::H256 }, + #[codec(index = 2)] + #[doc = "Request a preimage be uploaded to the chain without paying any fees or deposits."] #[doc = ""] - #[doc = "Transaction fees are waived if the operation is successful."] + #[doc = "If the preimage requests has already been provided on-chain, we unreserve any deposit"] + #[doc = "a user may have paid, and take the control of the preimage out of their hands."] + request_preimage { hash: ::subxt::ext::subxt_core::utils::H256 }, + #[codec(index = 3)] + #[doc = "Clear a previously made request for a preimage."] #[doc = ""] - #[doc = "Weight `O(max)` (less if there are fewer items to remove than `max`)."] - cleanup_poll { poll_index: ::core::primitive::u32, max: ::core::primitive::u32 }, - #[codec(index = 6)] - #[doc = "Exchanges a member with a new account and the same existing rank."] + #[doc = "NOTE: THIS MUST NOT BE CALLED ON `hash` MORE TIMES THAN `request_preimage`."] + unrequest_preimage { hash: ::subxt::ext::subxt_core::utils::H256 }, + #[codec(index = 4)] + #[doc = "Ensure that the bulk of pre-images is upgraded."] #[doc = ""] - #[doc = "- `origin`: Must be the `ExchangeOrigin`."] - #[doc = "- `who`: Account of existing member of rank greater than zero to be exchanged."] - #[doc = "- `new_who`: New Account of existing member of rank greater than zero to exchanged to."] - exchange_member { - who: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - new_who: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), + #[doc = "The caller pays no fee if at least 90% of pre-images were successfully updated."] + ensure_updated { + hashes: ::subxt::ext::subxt_core::alloc::vec::Vec< + ::subxt::ext::subxt_core::utils::H256, >, }, } @@ -16549,38 +14442,29 @@ pub mod api { #[doc = "The `Error` enum of this pallet."] pub enum Error { #[codec(index = 0)] - #[doc = "Account is already a member."] - AlreadyMember, + #[doc = "Preimage is too large to store on-chain."] + TooBig, #[codec(index = 1)] - #[doc = "Account is not a member."] - NotMember, + #[doc = "Preimage has already been noted on-chain."] + AlreadyNoted, #[codec(index = 2)] - #[doc = "The given poll index is unknown or has closed."] - NotPolling, + #[doc = "The user is not authorized to perform this action."] + NotAuthorized, #[codec(index = 3)] - #[doc = "The given poll is still ongoing."] - Ongoing, + #[doc = "The preimage cannot be removed since it has not yet been noted."] + NotNoted, #[codec(index = 4)] - #[doc = "There are no further records to be removed."] - NoneRemaining, + #[doc = "A preimage may not be removed when there are outstanding requests."] + Requested, #[codec(index = 5)] - #[doc = "Unexpected error in state."] - Corruption, + #[doc = "The preimage request cannot be removed since no outstanding requests exist."] + NotRequested, #[codec(index = 6)] - #[doc = "The member's rank is too low to vote."] - RankTooLow, + #[doc = "More than `MAX_HASH_UPGRADE_BULK_COUNT` hashes were requested to be upgraded at once."] + TooMany, #[codec(index = 7)] - #[doc = "The information provided is incorrect."] - InvalidWitness, - #[codec(index = 8)] - #[doc = "The origin is not sufficiently privileged to do the operation."] - NoPermission, - #[codec(index = 9)] - #[doc = "The new member to exchange is the same as the old member"] - SameMember, - #[codec(index = 10)] - #[doc = "The max member count for the rank has been reached."] - TooManyMembers, + #[doc = "Too few hashes were requested to be upgraded (i.e. zero)."] + TooFew, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -16596,35 +14480,29 @@ pub mod api { #[doc = "The `Event` enum of this pallet"] pub enum Event { #[codec(index = 0)] - #[doc = "A member `who` has been added."] - MemberAdded { who: ::subxt::ext::subxt_core::utils::AccountId32 }, + #[doc = "A preimage has been noted."] + Noted { hash: ::subxt::ext::subxt_core::utils::H256 }, #[codec(index = 1)] - #[doc = "The member `who`se rank has been changed to the given `rank`."] - RankChanged { - who: ::subxt::ext::subxt_core::utils::AccountId32, - rank: ::core::primitive::u16, - }, + #[doc = "A preimage has been requested."] + Requested { hash: ::subxt::ext::subxt_core::utils::H256 }, #[codec(index = 2)] - #[doc = "The member `who` of given `rank` has been removed from the collective."] - MemberRemoved { - who: ::subxt::ext::subxt_core::utils::AccountId32, - rank: ::core::primitive::u16, - }, - #[codec(index = 3)] - #[doc = "The member `who` has voted for the `poll` with the given `vote` leading to an updated"] - #[doc = "`tally`."] - Voted { - who: ::subxt::ext::subxt_core::utils::AccountId32, - poll: ::core::primitive::u32, - vote: runtime_types::pallet_ranked_collective::VoteRecord, - tally: runtime_types::pallet_ranked_collective::Tally, - }, - #[codec(index = 4)] - #[doc = "The member `who` had their `AccountId` changed to `new_who`."] - MemberExchanged { - who: ::subxt::ext::subxt_core::utils::AccountId32, - new_who: ::subxt::ext::subxt_core::utils::AccountId32, - }, + #[doc = "A preimage has ben cleared."] + Cleared { hash: ::subxt::ext::subxt_core::utils::H256 }, + } + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub enum HoldReason { + #[codec(index = 0)] + Preimage, } } #[derive( @@ -16634,20 +14512,15 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct MemberRecord { - pub rank: ::core::primitive::u16, - } - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct Tally { - pub bare_ayes: ::core::primitive::u32, - pub ayes: ::core::primitive::u32, - pub nays: ::core::primitive::u32, + pub enum OldRequestStatus<_0, _1> { + #[codec(index = 0)] + Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, + #[codec(index = 1)] + Requested { + deposit: ::core::option::Option<(_0, _1)>, + count: ::core::primitive::u32, + len: ::core::option::Option<::core::primitive::u32>, + }, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -16656,14 +14529,50 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub enum VoteRecord { + pub enum RequestStatus<_0, _1> { #[codec(index = 0)] - Aye(::core::primitive::u32), + Unrequested { ticket: (_0, _1), len: ::core::primitive::u32 }, #[codec(index = 1)] - Nay(::core::primitive::u32), + Requested { + maybe_ticket: ::core::option::Option<(_0, _1)>, + count: ::core::primitive::u32, + maybe_len: ::core::option::Option<::core::primitive::u32>, + }, + } + } + pub mod pallet_qpow { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + #[doc = "The `Event` enum of this pallet"] + pub enum Event { + #[codec(index = 0)] + ProofSubmitted { + nonce: [::core::primitive::u8; 64usize], + difficulty: runtime_types::primitive_types::U512, + hash_achieved: runtime_types::primitive_types::U512, + }, + #[codec(index = 1)] + DifficultyAdjusted { + old_difficulty: runtime_types::primitive_types::U512, + new_difficulty: runtime_types::primitive_types::U512, + observed_block_time: ::core::primitive::u64, + }, + } } } - pub mod pallet_recovery { + pub mod pallet_ranked_collective { use super::runtime_types; pub mod pallet { use super::runtime_types; @@ -16671,6 +14580,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -16681,198 +14592,99 @@ pub mod api { #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] pub enum Call { #[codec(index = 0)] - #[doc = "Send a call through a recovered account."] + #[doc = "Introduce a new member."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and registered to"] - #[doc = "be able to make calls on behalf of the recovered account."] + #[doc = "- `origin`: Must be the `AddOrigin`."] + #[doc = "- `who`: Account of non-member which will become a member."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The recovered account you want to make a call on-behalf-of."] - #[doc = "- `call`: The call you want to make with the recovered account."] - as_recovered { - account: ::subxt::ext::subxt_core::utils::MultiAddress< + #[doc = "Weight: `O(1)`"] + add_member { + who: ::subxt::ext::subxt_core::utils::MultiAddress< ::subxt::ext::subxt_core::utils::AccountId32, (), >, - call: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::RuntimeCall, - >, }, #[codec(index = 1)] - #[doc = "Allow ROOT to bypass the recovery process and set a rescuer account"] - #[doc = "for a lost account directly."] + #[doc = "Increment the rank of an existing member by one."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _ROOT_."] + #[doc = "- `origin`: Must be the `PromoteOrigin`."] + #[doc = "- `who`: Account of existing member."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `lost`: The \"lost account\" to be recovered."] - #[doc = "- `rescuer`: The \"rescuer account\" which can call as the lost account."] - set_recovered { - lost: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - rescuer: ::subxt::ext::subxt_core::utils::MultiAddress< + #[doc = "Weight: `O(1)`"] + promote_member { + who: ::subxt::ext::subxt_core::utils::MultiAddress< ::subxt::ext::subxt_core::utils::AccountId32, (), >, }, #[codec(index = 2)] - #[doc = "Create a recovery configuration for your account. This makes your account recoverable."] - #[doc = ""] - #[doc = "Payment: `ConfigDepositBase` + `FriendDepositFactor` * #_of_friends balance"] - #[doc = "will be reserved for storing the recovery configuration. This deposit is returned"] - #[doc = "in full when the user calls `remove_recovery`."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `friends`: A list of friends you trust to vouch for recovery attempts. Should be"] - #[doc = " ordered and contain no duplicate values."] - #[doc = "- `threshold`: The number of friends that must vouch for a recovery attempt before the"] - #[doc = " account can be recovered. Should be less than or equal to the length of the list of"] - #[doc = " friends."] - #[doc = "- `delay_period`: The number of blocks after a recovery attempt is initialized that"] - #[doc = " needs to pass before the account can be recovered."] - create_recovery { - friends: ::subxt::ext::subxt_core::alloc::vec::Vec< - ::subxt::ext::subxt_core::utils::AccountId32, - >, - threshold: ::core::primitive::u16, - delay_period: ::core::primitive::u32, - }, - #[codec(index = 3)] - #[doc = "Initiate the process for recovering a recoverable account."] - #[doc = ""] - #[doc = "Payment: `RecoveryDeposit` balance will be reserved for initiating the"] - #[doc = "recovery process. This deposit will always be repatriated to the account"] - #[doc = "trying to be recovered. See `close_recovery`."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The lost account that you want to recover. This account needs to be"] - #[doc = " recoverable (i.e. have a recovery configuration)."] - initiate_recovery { - account: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - }, - #[codec(index = 4)] - #[doc = "Allow a \"friend\" of a recoverable account to vouch for an active recovery"] - #[doc = "process for that account."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a \"friend\""] - #[doc = "for the recoverable account."] - #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `lost`: The lost account that you want to recover."] - #[doc = "- `rescuer`: The account trying to rescue the lost account that you want to vouch for."] - #[doc = ""] - #[doc = "The combination of these two parameters must point to an active recovery"] - #[doc = "process."] - vouch_recovery { - lost: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - rescuer: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - }, - #[codec(index = 5)] - #[doc = "Allow a successful rescuer to claim their recovered account."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a \"rescuer\""] - #[doc = "who has successfully completed the account recovery process: collected"] - #[doc = "`threshold` or more vouches, waited `delay_period` blocks since initiation."] - #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The lost account that you want to claim has been successfully recovered by"] - #[doc = " you."] - claim_recovery { - account: ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, - }, - #[codec(index = 6)] - #[doc = "As the controller of a recoverable account, close an active recovery"] - #[doc = "process for your account."] - #[doc = ""] - #[doc = "Payment: By calling this function, the recoverable account will receive"] - #[doc = "the recovery deposit `RecoveryDeposit` placed by the rescuer."] + #[doc = "Decrement the rank of an existing member by one. If the member is already at rank zero,"] + #[doc = "then they are removed entirely."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a"] - #[doc = "recoverable account with an active recovery process for it."] + #[doc = "- `origin`: Must be the `DemoteOrigin`."] + #[doc = "- `who`: Account of existing member of rank greater than zero."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `rescuer`: The account trying to rescue this recoverable account."] - close_recovery { - rescuer: ::subxt::ext::subxt_core::utils::MultiAddress< + #[doc = "Weight: `O(1)`, less if the member's index is highest in its rank."] + demote_member { + who: ::subxt::ext::subxt_core::utils::MultiAddress< ::subxt::ext::subxt_core::utils::AccountId32, (), >, }, - #[codec(index = 7)] - #[doc = "Remove the recovery process for your account. Recovered accounts are still accessible."] - #[doc = ""] - #[doc = "NOTE: The user must make sure to call `close_recovery` on all active"] - #[doc = "recovery attempts before calling this function else it will fail."] - #[doc = ""] - #[doc = "Payment: By calling this function the recoverable account will unreserve"] - #[doc = "their recovery configuration deposit."] - #[doc = "(`ConfigDepositBase` + `FriendDepositFactor` * #_of_friends)"] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and must be a"] - #[doc = "recoverable account (i.e. has a recovery configuration)."] - remove_recovery, - #[codec(index = 8)] - #[doc = "Cancel the ability to use `as_recovered` for `account`."] + #[codec(index = 3)] + #[doc = "Remove the member entirely."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_ and registered to"] - #[doc = "be able to make calls on behalf of the recovered account."] + #[doc = "- `origin`: Must be the `RemoveOrigin`."] + #[doc = "- `who`: Account of existing member of rank greater than zero."] + #[doc = "- `min_rank`: The rank of the member or greater."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `account`: The recovered account you are able to call on-behalf-of."] - cancel_recovered { - account: ::subxt::ext::subxt_core::utils::MultiAddress< + #[doc = "Weight: `O(min_rank)`."] + remove_member { + who: ::subxt::ext::subxt_core::utils::MultiAddress< ::subxt::ext::subxt_core::utils::AccountId32, (), >, + min_rank: ::core::primitive::u16, }, - #[codec(index = 9)] - #[doc = "Poke deposits for recovery configurations and / or active recoveries."] + #[codec(index = 4)] + #[doc = "Add an aye or nay vote for the sender to the given proposal."] #[doc = ""] - #[doc = "This can be used by accounts to possibly lower their locked amount."] + #[doc = "- `origin`: Must be `Signed` by a member account."] + #[doc = "- `poll`: Index of a poll which is ongoing."] + #[doc = "- `aye`: `true` if the vote is to approve the proposal, `false` otherwise."] #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = "Transaction fees are be waived if the member is voting on any particular proposal"] + #[doc = "for the first time and the call is successful. Subsequent vote changes will charge a"] + #[doc = "fee."] #[doc = ""] - #[doc = "Parameters:"] - #[doc = "- `maybe_account`: Optional recoverable account for which you have an active recovery"] - #[doc = "and want to adjust the deposit for the active recovery."] + #[doc = "Weight: `O(1)`, less if there was no previous vote on the poll by the member."] + vote { poll: ::core::primitive::u32, aye: ::core::primitive::bool }, + #[codec(index = 5)] + #[doc = "Remove votes from the given poll. It must have ended."] #[doc = ""] - #[doc = "This function checks both recovery configuration deposit and active recovery deposits"] - #[doc = "of the caller:"] - #[doc = "- If the caller has created a recovery configuration, checks and adjusts its deposit"] - #[doc = "- If the caller has initiated any active recoveries, and provides the account in"] - #[doc = "`maybe_account`, checks and adjusts those deposits"] + #[doc = "- `origin`: Must be `Signed` by any account."] + #[doc = "- `poll_index`: Index of a poll which is completed and for which votes continue to"] + #[doc = " exist."] + #[doc = "- `max`: Maximum number of vote items from remove in this call."] #[doc = ""] - #[doc = "If any deposit is updated, the difference will be reserved/unreserved from the caller's"] - #[doc = "account."] + #[doc = "Transaction fees are waived if the operation is successful."] #[doc = ""] - #[doc = "The transaction is made free if any deposit is updated and paid otherwise."] + #[doc = "Weight `O(max)` (less if there are fewer items to remove than `max`)."] + cleanup_poll { poll_index: ::core::primitive::u32, max: ::core::primitive::u32 }, + #[codec(index = 6)] + #[doc = "Exchanges a member with a new account and the same existing rank."] #[doc = ""] - #[doc = "Emits `DepositPoked` if any deposit is updated."] - #[doc = "Multiple events may be emitted in case both types of deposits are updated."] - poke_deposit { - maybe_account: ::core::option::Option< - ::subxt::ext::subxt_core::utils::MultiAddress< - ::subxt::ext::subxt_core::utils::AccountId32, - (), - >, + #[doc = "- `origin`: Must be the `ExchangeOrigin`."] + #[doc = "- `who`: Account of existing member of rank greater than zero to be exchanged."] + #[doc = "- `new_who`: New Account of existing member of rank greater than zero to exchanged to."] + exchange_member { + who: ::subxt::ext::subxt_core::utils::MultiAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + (), + >, + new_who: ::subxt::ext::subxt_core::utils::MultiAddress< + ::subxt::ext::subxt_core::utils::AccountId32, + (), >, }, } @@ -16890,56 +14702,38 @@ pub mod api { #[doc = "The `Error` enum of this pallet."] pub enum Error { #[codec(index = 0)] - #[doc = "User is not allowed to make a call on behalf of this account"] - NotAllowed, + #[doc = "Account is already a member."] + AlreadyMember, #[codec(index = 1)] - #[doc = "Call is not allowed for a high-security account"] - CallNotAllowedForHighSecurity, + #[doc = "Account is not a member."] + NotMember, #[codec(index = 2)] - #[doc = "Threshold must be greater than zero"] - ZeroThreshold, + #[doc = "The given poll index is unknown or has closed."] + NotPolling, #[codec(index = 3)] - #[doc = "Friends list must be greater than zero and threshold"] - NotEnoughFriends, + #[doc = "The given poll is still ongoing."] + Ongoing, #[codec(index = 4)] - #[doc = "Friends list must be less than max friends"] - MaxFriends, + #[doc = "There are no further records to be removed."] + NoneRemaining, #[codec(index = 5)] - #[doc = "Friends list must be sorted and free of duplicates"] - NotSorted, + #[doc = "Unexpected error in state."] + Corruption, #[codec(index = 6)] - #[doc = "This account is not set up for recovery"] - NotRecoverable, + #[doc = "The member's rank is too low to vote."] + RankTooLow, #[codec(index = 7)] - #[doc = "This account is already set up for recovery"] - AlreadyRecoverable, + #[doc = "The information provided is incorrect."] + InvalidWitness, #[codec(index = 8)] - #[doc = "A recovery process has already started for this account"] - AlreadyStarted, + #[doc = "The origin is not sufficiently privileged to do the operation."] + NoPermission, #[codec(index = 9)] - #[doc = "A recovery process has not started for this rescuer"] - NotStarted, + #[doc = "The new member to exchange is the same as the old member"] + SameMember, #[codec(index = 10)] - #[doc = "This account is not a friend who can vouch"] - NotFriend, - #[codec(index = 11)] - #[doc = "The friend must wait until the delay period to vouch for this recovery"] - DelayPeriod, - #[codec(index = 12)] - #[doc = "This user has already vouched for this recovery"] - AlreadyVouched, - #[codec(index = 13)] - #[doc = "The threshold for recovering this account has not been met"] - Threshold, - #[codec(index = 14)] - #[doc = "There are still active recovery attempts that need to be closed"] - StillActive, - #[codec(index = 15)] - #[doc = "This account is already set up for recovery"] - AlreadyProxy, - #[codec(index = 16)] - #[doc = "Some internal state is broken."] - BadState, + #[doc = "The max member count for the rank has been reached."] + TooManyMembers, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -16952,48 +14746,37 @@ pub mod api { #[encode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" )] - #[doc = "Events type."] + #[doc = "The `Event` enum of this pallet"] pub enum Event { #[codec(index = 0)] - #[doc = "A recovery process has been set up for an account."] - RecoveryCreated { account: ::subxt::ext::subxt_core::utils::AccountId32 }, + #[doc = "A member `who` has been added."] + MemberAdded { who: ::subxt::ext::subxt_core::utils::AccountId32 }, #[codec(index = 1)] - #[doc = "A recovery process has been initiated for lost account by rescuer account."] - RecoveryInitiated { - lost_account: ::subxt::ext::subxt_core::utils::AccountId32, - rescuer_account: ::subxt::ext::subxt_core::utils::AccountId32, + #[doc = "The member `who`se rank has been changed to the given `rank`."] + RankChanged { + who: ::subxt::ext::subxt_core::utils::AccountId32, + rank: ::core::primitive::u16, }, #[codec(index = 2)] - #[doc = "A recovery process for lost account by rescuer account has been vouched for by sender."] - RecoveryVouched { - lost_account: ::subxt::ext::subxt_core::utils::AccountId32, - rescuer_account: ::subxt::ext::subxt_core::utils::AccountId32, - sender: ::subxt::ext::subxt_core::utils::AccountId32, + #[doc = "The member `who` of given `rank` has been removed from the collective."] + MemberRemoved { + who: ::subxt::ext::subxt_core::utils::AccountId32, + rank: ::core::primitive::u16, }, #[codec(index = 3)] - #[doc = "A recovery process for lost account by rescuer account has been closed."] - RecoveryClosed { - lost_account: ::subxt::ext::subxt_core::utils::AccountId32, - rescuer_account: ::subxt::ext::subxt_core::utils::AccountId32, + #[doc = "The member `who` has voted for the `poll` with the given `vote` leading to an updated"] + #[doc = "`tally`."] + Voted { + who: ::subxt::ext::subxt_core::utils::AccountId32, + poll: ::core::primitive::u32, + vote: runtime_types::pallet_ranked_collective::VoteRecord, + tally: runtime_types::pallet_ranked_collective::Tally, }, #[codec(index = 4)] - #[doc = "Lost account has been successfully recovered by rescuer account."] - AccountRecovered { - lost_account: ::subxt::ext::subxt_core::utils::AccountId32, - rescuer_account: ::subxt::ext::subxt_core::utils::AccountId32, - }, - #[codec(index = 5)] - #[doc = "A recovery process has been removed for an account."] - RecoveryRemoved { lost_account: ::subxt::ext::subxt_core::utils::AccountId32 }, - #[codec(index = 6)] - #[doc = "A deposit has been updated."] - DepositPoked { + #[doc = "The member `who` had their `AccountId` changed to `new_who`."] + MemberExchanged { who: ::subxt::ext::subxt_core::utils::AccountId32, - kind: runtime_types::pallet_recovery::DepositKind< - runtime_types::quantus_runtime::Runtime, - >, - old_deposit: ::core::primitive::u128, - new_deposit: ::core::primitive::u128, + new_who: ::subxt::ext::subxt_core::utils::AccountId32, }, } } @@ -17004,10 +14787,8 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct ActiveRecovery<_0, _1, _2> { - pub created: _0, - pub deposit: _1, - pub friends: _2, + pub struct MemberRecord { + pub rank: ::core::primitive::u16, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -17016,12 +14797,10 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub enum DepositKind<_0> { - #[codec(index = 0)] - RecoveryConfig, - #[codec(index = 1)] - ActiveRecoveryFor(::subxt::ext::subxt_core::utils::AccountId32), - __Ignore(::core::marker::PhantomData<_0>), + pub struct Tally { + pub bare_ayes: ::core::primitive::u32, + pub ayes: ::core::primitive::u32, + pub nays: ::core::primitive::u32, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -17030,11 +14809,11 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct RecoveryConfig<_0, _1, _2> { - pub delay_period: _0, - pub deposit: _1, - pub friends: _2, - pub threshold: ::core::primitive::u16, + pub enum VoteRecord { + #[codec(index = 0)] + Aye(::core::primitive::u32), + #[codec(index = 1)] + Nay(::core::primitive::u32), } } pub mod pallet_referenda { @@ -17045,6 +14824,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -17209,6 +14990,15 @@ pub mod api { #[codec(index = 14)] #[doc = "The referendum's wake-up alarm could not be scheduled."] AlarmSchedulingFailed, + #[codec(index = 15)] + #[doc = "There are already the maximum number of ongoing referenda."] + TooManyActive, + #[codec(index = 16)] + #[doc = "The submitter already has the maximum number of ongoing referenda."] + TooManyActiveBySubmitter, + #[codec(index = 17)] + #[doc = "The proposal's preimage is larger than [`Config::MaxProposalSize`]."] + PreimageTooBig, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -17514,6 +15304,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -17559,6 +15351,21 @@ pub mod api { #[doc = "- `delay`: The reversibility time for any transfer made by the high-security account."] #[doc = "- `guardian`: The guardian account that can cancel pending transfers and recover funds"] #[doc = " from this high-security account."] + #[doc = ""] + #[doc = "# Choose the guardian carefully"] + #[doc = ""] + #[doc = "The guardian holds instant, total seizure power: `recover_funds`"] + #[doc = "sweeps every hold plus the entire free balance to the guardian,"] + #[doc = "with no delay, no second approver, and no way to change the"] + #[doc = "relationship afterwards. A single-key guardian is therefore a"] + #[doc = "single point of failure for the whole scheme. **Use a multisig"] + #[doc = "address as the guardian**: `pallet_multisig` dispatches calls as"] + #[doc = "its derived address, so a multisig can cancel and recover exactly"] + #[doc = "like a plain account."] + #[doc = ""] + #[doc = "Guardianship is discoverable offchain (e.g. Subsquid) via the"] + #[doc = "`HighSecuritySet` event; there is deliberately no on-chain"] + #[doc = "guardian index to fill up or grief."] set_high_security { delay: runtime_types::qp_scheduler::BlockNumberOrTimestamp< ::core::primitive::u32, @@ -17583,6 +15390,15 @@ pub mod api { #[doc = ""] #[doc = "- `tx_id`: The unique identifier of the pending transfer to execute."] #[doc = ""] + #[doc = "Execution uses `transfer_allow_death` so a sender who spent their leftover"] + #[doc = "free balance during the delay still completes. A failed inner transfer (e.g."] + #[doc = "dest overflow, or `amount < ED` to a new account) does not fail this"] + #[doc = "extrinsic: the hold is already released and the pending transfer is already"] + #[doc = "removed. Propagating that error would roll back those writes (FRAME"] + #[doc = "dispatchables are transactional) while Scheduler terminally drops the named"] + #[doc = "task, freezing the funds with no retry. The inner result is still recorded on"] + #[doc = "[`Event::TransactionExecuted`]."] + #[doc = ""] #[doc = "# Errors"] #[doc = ""] #[doc = "- [`InvalidSchedulerOrigin`](Error::InvalidSchedulerOrigin): Called by an account other"] @@ -17708,12 +15524,9 @@ pub mod api { #[doc = "deterrence)"] AccountAlreadyReversibleCannotScheduleOneTime, #[codec(index = 13)] - #[doc = "The guardian has reached the maximum number of accounts they can protect."] - TooManyGuardianAccounts, - #[codec(index = 14)] #[doc = "Asset transfers are not supported."] AssetsNotSupported, - #[codec(index = 15)] + #[codec(index = 14)] #[doc = "Zero-amount transfers cannot be scheduled: there is nothing to hold,"] #[doc = "execute, or reverse."] ZeroAmount, @@ -18036,6 +15849,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -18181,6 +15996,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -18193,16 +16010,11 @@ pub mod api { #[codec(index = 0)] #[doc = "Set the treasury account. Root only. Zero address is rejected (funds would be locked)."] #[doc = ""] - #[doc = "**Important**: This only changes where *future* mining rewards are sent. Any balance"] + #[doc = "**Important**: This only changes where *future* treasury credits are sent. Any balance"] #[doc = "that has already accumulated in the current treasury account is NOT automatically"] #[doc = "migrated to the new account. If you need to move existing funds, perform a separate"] #[doc = "balance transfer (e.g., via governance proposal) after updating the account."] set_treasury_account { account: ::subxt::ext::subxt_core::utils::AccountId32 }, - #[codec(index = 1)] - #[doc = "Set the treasury portion (Permill, 0–100%). Root only."] - set_treasury_portion { - portion: runtime_types::sp_arithmetic::per_things::Permill, - }, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -18218,8 +16030,6 @@ pub mod api { #[doc = "The `Error` enum of this pallet."] pub enum Error { #[codec(index = 0)] - InvalidPortion, - #[codec(index = 1)] #[doc = "Treasury account cannot be zero address (funds would be permanently locked)."] InvalidTreasuryAccount, } @@ -18239,7 +16049,7 @@ pub mod api { #[codec(index = 0)] #[doc = "The treasury account was updated."] #[doc = ""] - #[doc = "Note: This only redirects where future mining rewards are sent. Any balance"] + #[doc = "Note: This only redirects where future treasury credits are sent. Any balance"] #[doc = "accumulated in the old account remains there and is NOT automatically migrated."] #[doc = "Use a separate balance transfer if funds need to be moved."] TreasuryAccountUpdated { @@ -18247,11 +16057,6 @@ pub mod api { ::core::option::Option<::subxt::ext::subxt_core::utils::AccountId32>, new_account: ::subxt::ext::subxt_core::utils::AccountId32, }, - #[codec(index = 1)] - #[doc = "The treasury portion (share of mining rewards) was updated."] - TreasuryPortionUpdated { - new_portion: runtime_types::sp_arithmetic::per_things::Permill, - }, } } } @@ -18263,6 +16068,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -18272,50 +16079,6 @@ pub mod api { )] #[doc = "Contains a variant per dispatchable extrinsic that this pallet has."] pub enum Call { - #[codec(index = 0)] - #[doc = "Send a batch of dispatch calls."] - #[doc = ""] - #[doc = "May be called from any origin except `None`."] - #[doc = ""] - #[doc = "- `calls`: The calls to be dispatched from the same origin. The number of call must not"] - #[doc = " exceed the constant: `batched_calls_limit` (available in constant metadata)."] - #[doc = ""] - #[doc = "If origin is root then the calls are dispatched without checking origin filter. (This"] - #[doc = "includes bypassing `frame_system::Config::BaseCallFilter`)."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(C) where C is the number of calls to be batched."] - #[doc = ""] - #[doc = "This will return `Ok` in all circumstances. To determine the success of the batch, an"] - #[doc = "event is deposited. If a call failed and the batch was interrupted, then the"] - #[doc = "`BatchInterrupted` event is deposited, along with the number of successful calls made"] - #[doc = "and the error of the failed call. If all were successful, then the `BatchCompleted`"] - #[doc = "event is deposited."] - batch { - calls: ::subxt::ext::subxt_core::alloc::vec::Vec< - runtime_types::quantus_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - #[doc = "Send a call through an indexed pseudonym of the sender."] - #[doc = ""] - #[doc = "Filter from origin are passed along. The call will be dispatched with an origin which"] - #[doc = "use the same filter as the origin of this call."] - #[doc = ""] - #[doc = "NOTE: If you need to ensure that any account-based filtering is not honored (i.e."] - #[doc = "because you expect `proxy` to have been used prior in the call stack and you do not want"] - #[doc = "the call restrictions to apply to any sub-accounts), then use `as_multi_threshold_1`"] - #[doc = "in the Multisig pallet instead."] - #[doc = ""] - #[doc = "NOTE: Prior to version *12, this was called `as_limited_sub`."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - as_derivative { - index: ::core::primitive::u16, - call: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::RuntimeCall, - >, - }, #[codec(index = 2)] #[doc = "Send a batch of dispatch calls and atomically execute them."] #[doc = "The whole transaction will rollback and fail if any of the calls failed."] @@ -18330,104 +16093,14 @@ pub mod api { #[doc = ""] #[doc = "## Complexity"] #[doc = "- O(C) where C is the number of calls to be batched."] - batch_all { - calls: ::subxt::ext::subxt_core::alloc::vec::Vec< - runtime_types::quantus_runtime::RuntimeCall, - >, - }, - #[codec(index = 3)] - #[doc = "Dispatches a function call with a provided origin."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] - dispatch_as { - as_origin: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::OriginCaller, - >, - call: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::RuntimeCall, - >, - }, - #[codec(index = 4)] - #[doc = "Send a batch of dispatch calls."] - #[doc = "Unlike `batch`, it allows errors and won't interrupt."] - #[doc = ""] - #[doc = "May be called from any origin except `None`."] - #[doc = ""] - #[doc = "- `calls`: The calls to be dispatched from the same origin. The number of call must not"] - #[doc = " exceed the constant: `batched_calls_limit` (available in constant metadata)."] - #[doc = ""] - #[doc = "If origin is root then the calls are dispatch without checking origin filter. (This"] - #[doc = "includes bypassing `frame_system::Config::BaseCallFilter`)."] #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(C) where C is the number of calls to be batched."] - force_batch { + #[doc = "Call index 2 is preserved from the upstream utility pallet so existing"] + #[doc = "`batch_all` encodings keep decoding after the other combinators were removed."] + batch_all { calls: ::subxt::ext::subxt_core::alloc::vec::Vec< runtime_types::quantus_runtime::RuntimeCall, >, }, - #[codec(index = 5)] - #[doc = "Dispatch a function call with a specified weight."] - #[doc = ""] - #[doc = "This function does not check the weight of the call, and instead allows the"] - #[doc = "Root origin to specify the weight of the call."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] - with_weight { - call: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::RuntimeCall, - >, - weight: runtime_types::sp_weights::weight_v2::Weight, - }, - #[codec(index = 6)] - #[doc = "Dispatch a fallback call in the event the main call fails to execute."] - #[doc = "May be called from any origin except `None`."] - #[doc = ""] - #[doc = "This function first attempts to dispatch the `main` call."] - #[doc = "If the `main` call fails, the `fallback` is attemted."] - #[doc = "if the fallback is successfully dispatched, the weights of both calls"] - #[doc = "are accumulated and an event containing the main call error is deposited."] - #[doc = ""] - #[doc = "In the event of a fallback failure the whole call fails"] - #[doc = "with the weights returned."] - #[doc = ""] - #[doc = "- `main`: The main call to be dispatched. This is the primary action to execute."] - #[doc = "- `fallback`: The fallback call to be dispatched in case the `main` call fails."] - #[doc = ""] - #[doc = "## Dispatch Logic"] - #[doc = "- If the origin is `root`, both the main and fallback calls are executed without"] - #[doc = " applying any origin filters."] - #[doc = "- If the origin is not `root`, the origin filter is applied to both the `main` and"] - #[doc = " `fallback` calls."] - #[doc = ""] - #[doc = "## Use Case"] - #[doc = "- Some use cases might involve submitting a `batch` type call in either main, fallback"] - #[doc = " or both."] - if_else { - main: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::RuntimeCall, - >, - fallback: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::RuntimeCall, - >, - }, - #[codec(index = 7)] - #[doc = "Dispatches a function call with a provided origin."] - #[doc = ""] - #[doc = "Almost the same as [`Pallet::dispatch_as`] but forwards any error of the inner call."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Root_."] - dispatch_as_fallible { - as_origin: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::OriginCaller, - >, - call: ::subxt::ext::subxt_core::alloc::boxed::Box< - runtime_types::quantus_runtime::RuntimeCall, - >, - }, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -18463,36 +16136,11 @@ pub mod api { #[doc = "The `Event` enum of this pallet"] pub enum Event { #[codec(index = 0)] - #[doc = "Batch of dispatches did not complete fully. Index of first failing dispatch given, as"] - #[doc = "well as the error."] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] #[doc = "Batch of dispatches completed fully with no error."] BatchCompleted, - #[codec(index = 2)] - #[doc = "Batch of dispatches completed but has errors."] - BatchCompletedWithErrors, - #[codec(index = 3)] + #[codec(index = 1)] #[doc = "A single item within a Batch of dispatches has completed with no error."] ItemCompleted, - #[codec(index = 4)] - #[doc = "A single item within a Batch of dispatches has completed with error."] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - #[doc = "A call was dispatched."] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 6)] - #[doc = "Main call was dispatched."] - IfElseMainSuccess, - #[codec(index = 7)] - #[doc = "The fallback call was dispatched."] - IfElseFallbackCalled { main_error: runtime_types::sp_runtime::DispatchError }, } } } @@ -18504,6 +16152,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -18517,7 +16167,9 @@ pub mod api { #[doc = "Pay the largest valid claim on `schedule_id` to its beneficiary. Payouts are"] #[doc = "rounded down to [`Config::PayoutQuantum`], must meet [`Config::MinimumPayout`],"] #[doc = "and reserve at least one minimum-sized final claim unless the schedule is fully"] - #[doc = "vested."] + #[doc = "vested. Non-final payouts are further rounded down to"] + #[doc = "[`NON_FINAL_PAYOUT_QUANTA`] leaf quanta; the leftover stays on the schedule"] + #[doc = "until a later claim or the exact final payout."] #[doc = ""] #[doc = "Permissionless: any signed account may call this for any schedule; the payout"] #[doc = "always goes to the stored beneficiary. This is the only claim path for"] @@ -18534,17 +16186,19 @@ pub mod api { total: ::core::primitive::u128, }, #[codec(index = 2)] - #[doc = "End a schedule early: the still-unpaid vested part (rounded down to a"] - #[doc = "[`Config::PayoutQuantum`] multiple) goes to the beneficiary, everything else"] - #[doc = "this schedule still holds — the unvested remainder plus any sub-quantum"] - #[doc = "vested dust — returns to the treasury, and the schedule is removed. The"] - #[doc = "treasury is signature-controlled and needs no wormhole leaf, so dust is safe"] - #[doc = "there but would be stranded on a keyless beneficiary. A non-zero beneficiary"] - #[doc = "payout below [`Config::MinimumPayout`] is rejected without ending the schedule."] + #[doc = "End a schedule early: the still-unpaid vested part (rounded to the nearest"] + #[doc = "[`Config::PayoutQuantum`]) goes to the beneficiary if it meets"] + #[doc = "[`Config::MinimumPayout`]; otherwise that sliver is refunded with the"] + #[doc = "unvested remainder. The treasury is signature-controlled and needs no"] + #[doc = "wormhole leaf, so the refund is not quantized and never blocks ending."] end_schedule { schedule_id: ::core::primitive::u64 }, #[codec(index = 3)] - #[doc = "Settle any payout a permissionless claim could currently force, then change the"] - #[doc = "beneficiary. This makes retargeting independent of claim transaction ordering."] + #[doc = "Change the schedule's beneficiary without paying anything out. A retarget"] + #[doc = "replaces the wallet of the *same* grantee (lost-key remedy): the old address"] + #[doc = "may be lost or stolen, so settling it would burn funds or pay the thief."] + #[doc = "Everything vested but unclaimed stays on the schedule and goes to the new"] + #[doc = "wallet at its next claim. (A permissionless claim landing before the"] + #[doc = "retarget still pays the old address, so rotate promptly.)"] retarget_schedule { schedule_id: ::core::primitive::u64, new_beneficiary: ::subxt::ext::subxt_core::utils::AccountId32, @@ -18583,17 +16237,19 @@ pub mod api { #[doc = "entire remainder has vested."] ClaimWouldLeaveDust, #[codec(index = 5)] - #[doc = "Ending now would emit a non-zero beneficiary payout below the minimum."] - PayoutBelowMinimum, - #[codec(index = 6)] #[doc = "The treasury account is not configured or aliases the vesting pot."] TreasuryNotConfigured, - #[codec(index = 7)] + #[codec(index = 6)] #[doc = "The pot does not hold its existential-deposit buffer; endow it first."] PotUnderfunded, - #[codec(index = 8)] + #[codec(index = 7)] #[doc = "The beneficiary must not be the pot, and retargeting must change the account."] InvalidBeneficiary, + #[codec(index = 8)] + #[doc = "The proof recorder reported the payout credit as dropped: no wormhole leaf"] + #[doc = "was created, so the payout is rolled back rather than finalized without the"] + #[doc = "proof material a keyless beneficiary needs to exit."] + PayoutProofNotRecorded, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -18635,12 +16291,13 @@ pub mod api { unvested_returned: ::core::primitive::u128, }, #[codec(index = 3)] - #[doc = "A schedule's beneficiary was changed after settling any currently claimable payout."] + #[doc = "A schedule's beneficiary was changed. Nothing was paid out: the retarget"] + #[doc = "replaces the same grantee's wallet, so the accrued entitlement follows the"] + #[doc = "schedule to the new address."] ScheduleRetargeted { schedule_id: ::core::primitive::u64, old_beneficiary: ::subxt::ext::subxt_core::utils::AccountId32, new_beneficiary: ::subxt::ext::subxt_core::utils::AccountId32, - vested_paid: ::core::primitive::u128, }, } #[derive( @@ -18673,6 +16330,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" @@ -18726,9 +16385,9 @@ pub mod api { #[doc = "proof does)."] NullifierAlreadyUsed, #[codec(index = 2)] - #[doc = "The bundle contains only dummy (all-zero) padding segments, so there is"] - #[doc = "nothing to exit. Distinct from [`Error::NullifierAlreadyUsed`], which is a"] - #[doc = "replay of real segments."] + #[doc = "The bundle has nothing to settle: only dummy (all-zero) padding, or"] + #[doc = "every valid segment exits zero. Distinct from [`Error::NullifierAlreadyUsed`],"] + #[doc = "which is a replay of real segments."] NoValidSegments, #[codec(index = 3)] BlockNotFound, @@ -18854,6 +16513,10 @@ pub mod api { #[codec(index = 1)] #[doc = "Leaf not found."] LeafNotFound, + #[codec(index = 2)] + #[doc = "Leaf was appended this block and is not yet folded into the root; it"] + #[doc = "becomes provable once the block is finalized."] + LeafNotYetSettled, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -18869,12 +16532,12 @@ pub mod api { #[doc = "The `Event` enum of this pallet"] pub enum Event { #[codec(index = 0)] - #[doc = "A new leaf was inserted into the tree."] - LeafInserted { - index: ::core::primitive::u64, - leaf_hash: [::core::primitive::u8; 32usize], - new_root: [::core::primitive::u8; 32usize], - }, + #[doc = "A new leaf was inserted into the tree. The root including this leaf is"] + #[doc = "computed at the end of the block and published in the block header. The"] + #[doc = "leaf hash is deliberately not included: it is derivable from `Leaves`"] + #[doc = "(and served by the RPC), and hashing it here would double the per-leaf"] + #[doc = "Poseidon work the batched settlement saves."] + LeafInserted { index: ::core::primitive::u64 }, #[codec(index = 1)] #[doc = "Tree depth increased."] TreeGrew { new_depth: ::core::primitive::u8 }, @@ -19001,6 +16664,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] @@ -19077,6 +16742,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] @@ -19092,14 +16759,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, - )] - #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] - #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - pub struct Runtime; - #[derive( - :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, - :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, - Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] @@ -19122,8 +16783,6 @@ pub mod api { TechReferenda(runtime_types::pallet_referenda::pallet::Call), #[codec(index = 15)] TreasuryPallet(runtime_types::pallet_treasury::pallet::Call), - #[codec(index = 16)] - Recovery(runtime_types::pallet_recovery::pallet::Call), #[codec(index = 19)] Multisig(runtime_types::pallet_multisig::pallet::Call), #[codec(index = 20)] @@ -19157,8 +16816,6 @@ pub mod api { TechReferenda(runtime_types::pallet_referenda::pallet::Error), #[codec(index = 15)] TreasuryPallet(runtime_types::pallet_treasury::pallet::Error), - #[codec(index = 16)] - Recovery(runtime_types::pallet_recovery::pallet::Error), #[codec(index = 19)] Multisig(runtime_types::pallet_multisig::pallet::Error), #[codec(index = 20)] @@ -19200,8 +16857,6 @@ pub mod api { TechReferenda(runtime_types::pallet_referenda::pallet::Event), #[codec(index = 15)] TreasuryPallet(runtime_types::pallet_treasury::pallet::Event), - #[codec(index = 16)] - Recovery(runtime_types::pallet_recovery::pallet::Event), #[codec(index = 19)] Multisig(runtime_types::pallet_multisig::pallet::Event), #[codec(index = 20)] @@ -20032,6 +17687,8 @@ pub mod api { :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, Debug, + codec :: Decode, + codec :: Encode, )] #[decode_as_type( crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" diff --git a/src/cli/cold_signing.rs b/src/cli/cold_signing.rs index 4dd5619..f7c42ff 100644 --- a/src/cli/cold_signing.rs +++ b/src/cli/cold_signing.rs @@ -582,6 +582,42 @@ mod tests { .transfer_allow_death(MultiAddress::Id(dest), 1_000_000_000_000u128) } + fn multisig_execute_call(inner_amount: u128) -> impl subxt::tx::Payload { + let dest: subxt::utils::AccountId32 = + subxt::utils::AccountId32(*b"01234567890123456789012345678901"); + let inner = api::runtime_types::quantus_runtime::RuntimeCall::Balances( + api::runtime_types::pallet_balances::pallet::Call::transfer_allow_death { + dest: MultiAddress::Id(dest), + value: inner_amount, + }, + ); + api::tx().multisig().execute(subxt::utils::AccountId32([0x99u8; 32]), 7, inner) + } + + /// The hardware flow signs whatever `build_raw_signer_payload` produces, so the + /// executed call has to be inside it for the device to display it. + #[test] + fn test_cold_payload_carries_the_executed_call() { + let raw = build_raw_signer_payload( + &test_client_state(), + &multisig_execute_call(1_000_000_000_000), + &test_ctx(), + ) + .unwrap(); + + assert_eq!(raw[0], 19, "Multisig pallet index"); + assert_eq!(raw[1], 6, "execute call index"); + assert_eq!(&raw[2..34], &[0x99u8; 32], "multisig address"); + assert_eq!(&raw[34..38], 7u32.to_le_bytes(), "proposal id"); + + // The inner call follows inline — no compact length prefix, unlike approve. + assert_eq!(raw[38], 2, "Balances pallet index"); + assert_eq!(raw[39], 0, "transfer_allow_death call index"); + assert_eq!(raw[40], 0, "MultiAddress::Id tag"); + assert_eq!(&raw[41..73], b"01234567890123456789012345678901"); + assert_eq!(&raw[73..79], &[0x07u8, 0x00, 0x10, 0xa5, 0xd4, 0xe8], "compact amount"); + } + /// The raw payload must follow the exact field layout the cold-wallet /// parsers expect (see quantus_payload_parser.dart / Keystone parser.rs). #[test] diff --git a/src/cli/exercise/mod.rs b/src/cli/exercise/mod.rs index 89f2d7c..4f09e4d 100644 --- a/src/cli/exercise/mod.rs +++ b/src/cli/exercise/mod.rs @@ -17,7 +17,7 @@ use std::path::PathBuf; /// Divisor applied to every *discretionary* token amount the scenarios move (transfers, multisig /// funding, …) so the suite runs on a small budget. Fixed, chain-imposed amounts (existential -/// deposit, recovery/multisig/vesting/governance deposits) are read from the chain and never +/// deposit, multisig/vesting/governance deposits) are read from the chain and never /// scaled — nor is the wormhole amount, which the chain puts a floor under. pub(crate) const DISCRETIONARY_SCALE: u128 = 100; @@ -106,7 +106,6 @@ pub enum Phase { Utility, Reversible, Multisig, - Recovery, Preimage, Governance, Vesting, @@ -124,7 +123,6 @@ impl Phase { Phase::Utility, Phase::Reversible, Phase::Multisig, - Phase::Recovery, Phase::Preimage, Phase::Governance, Phase::Vesting, @@ -141,7 +139,6 @@ impl Phase { Phase::Utility => "utility", Phase::Reversible => "reversible", Phase::Multisig => "multisig", - Phase::Recovery => "recovery", Phase::Preimage => "preimage", Phase::Governance => "governance", Phase::Vesting => "vesting", @@ -299,7 +296,6 @@ async fn run_phases( Phase::Utility => scenarios::utility::run(ctx, report, &label).await?, Phase::Reversible => scenarios::reversible::run(ctx, report, &label).await?, Phase::Multisig => scenarios::multisig::run(ctx, report, &label).await?, - Phase::Recovery => scenarios::recovery::run(ctx, report, &label).await?, Phase::Preimage => scenarios::preimage::run(ctx, report, &label).await?, Phase::Governance => { let before = ctx.free_balance(&ctx.root_ss58).await?; @@ -430,13 +426,6 @@ async fn setup( )?); culprits.push("vesting"); } - if phases.contains(&Phase::Recovery) { - let recovery = - scenarios::recovery::account_funding(&client, existential_deposit, test_unit)? - .saturating_mul(scenarios::recovery::LIFECYCLE_ACCOUNTS); - returned = returned.max(recovery); - culprits.push("recovery"); - } if phases.contains(&Phase::Wormhole) { returned = returned.max(scenarios::wormhole::required_funding(unit)); culprits.push("wormhole"); diff --git a/src/cli/exercise/scenarios/balances.rs b/src/cli/exercise/scenarios/balances.rs index ee571a6..e5e68a0 100644 --- a/src/cli/exercise/scenarios/balances.rs +++ b/src/cli/exercise/scenarios/balances.rs @@ -21,7 +21,6 @@ pub async fn run(ctx: &mut ExerciseCtx, report: &mut Report, phase: &str) -> Res exercise_step!(report, phase, "transfer_keep_alive", transfer_keep_alive(ctx)); exercise_step!(report, phase, "transfer_all", transfer_all(ctx)); exercise_step!(report, phase, "burn", burn(ctx)); - exercise_step!(report, phase, "upgrade_accounts", upgrade_accounts(ctx)); exercise_step!( report, phase, @@ -246,12 +245,3 @@ async fn burn(ctx: &mut ExerciseCtx) -> Result { } Ok(format!("Balances::burn destroyed {amount} raw units (balance delta {delta} incl. fee)")) } - -/// `upgrade_accounts` is permissionless maintenance; a no-op call must still dispatch. -async fn upgrade_accounts(ctx: &mut ExerciseCtx) -> Result { - let sender = ctx.eph[1].clone(); - let target = account_id_of(&ctx.bob)?; - let call = quantus_subxt::api::tx().balances().upgrade_accounts(vec![target]); - let hash = submit_ok(ctx, &sender, call).await?; - Ok(format!("Balances::upgrade_accounts included ({hash:?})")) -} diff --git a/src/cli/exercise/scenarios/fuzz.rs b/src/cli/exercise/scenarios/fuzz.rs index f2fc2b8..a31943c 100644 --- a/src/cli/exercise/scenarios/fuzz.rs +++ b/src/cli/exercise/scenarios/fuzz.rs @@ -144,7 +144,7 @@ async fn fuzz_batch(ctx: &mut ExerciseCtx) -> Result { value: amount, })); } - let call = quantus_subxt::api::tx().utility().batch(calls); + let call = quantus_subxt::api::tx().utility().batch_all(calls); let result = crate::cli::common::submit_transaction( &ctx.client, &crate::wallet::WalletSigner::Hot(sender.clone()), diff --git a/src/cli/exercise/scenarios/governance.rs b/src/cli/exercise/scenarios/governance.rs index 437f8a2..859607c 100644 --- a/src/cli/exercise/scenarios/governance.rs +++ b/src/cli/exercise/scenarios/governance.rs @@ -44,12 +44,15 @@ async fn referendum_flow(ctx: &mut ExerciseCtx) -> Result { let latest = ctx.client.get_latest_block().await?; let storage_at = ctx.client.client().storage().at(latest); - let portion_addr = quantus_subxt::api::storage().treasury_pallet().treasury_portion(); - let current_portion = storage_at.fetch(&portion_addr).await?.map(|p| p.0).unwrap_or(0); + // Re-set the treasury account to its current value: the referendum has to enact a real + // root call, but the exercise must not change chain state it does not own. + let account_addr = quantus_subxt::api::storage().treasury_pallet().treasury_account(); + let current_account = storage_at + .fetch(&account_addr) + .await? + .ok_or_else(|| QuantusError::Generic("treasury account not set".to_string()))?; - let portion = - quantus_subxt::api::runtime_types::sp_arithmetic::per_things::Permill(current_portion); - let inner = quantus_subxt::api::tx().treasury_pallet().set_treasury_portion(portion); + let inner = quantus_subxt::api::tx().treasury_pallet().set_treasury_account(current_account); let encoded = inner .encode_call_data(&ctx.client.client().metadata()) .map_err(|e| QuantusError::Generic(format!("failed to encode call: {e:?}")))?; diff --git a/src/cli/exercise/scenarios/mod.rs b/src/cli/exercise/scenarios/mod.rs index 2a97364..2000999 100644 --- a/src/cli/exercise/scenarios/mod.rs +++ b/src/cli/exercise/scenarios/mod.rs @@ -7,7 +7,6 @@ pub mod multisig; pub mod negative; pub mod preimage; pub mod reads; -pub mod recovery; pub mod reversible; pub mod upgrade; pub mod utility; diff --git a/src/cli/exercise/scenarios/multisig.rs b/src/cli/exercise/scenarios/multisig.rs index 065ed06..6f38bb6 100644 --- a/src/cli/exercise/scenarios/multisig.rs +++ b/src/cli/exercise/scenarios/multisig.rs @@ -89,8 +89,11 @@ async fn lifecycle(ctx: &mut ExerciseCtx) -> Result { ); submit_ok(ctx, &signer_b, approve_call).await?; - let execute_call = - quantus_subxt::api::tx().multisig().execute(multisig_id.clone(), proposal_id); + let execute_call = quantus_subxt::api::tx().multisig().execute( + multisig_id.clone(), + proposal_id, + crate::cli::multisig::decode_proposal_call(&call_data)?, + ); submit_ok(ctx, &signer_c, execute_call).await?; let recipient_balance = ctx.free_balance(&recipient_ss58).await?; diff --git a/src/cli/exercise/scenarios/reads.rs b/src/cli/exercise/scenarios/reads.rs index 6e1fe41..8979444 100644 --- a/src/cli/exercise/scenarios/reads.rs +++ b/src/cli/exercise/scenarios/reads.rs @@ -93,17 +93,10 @@ async fn treasury_info(ctx: &ExerciseCtx) -> Result { .await? .ok_or_else(|| QuantusError::Generic("treasury account not set".to_string()))?; - let portion_addr = quantus_subxt::api::storage().treasury_pallet().treasury_portion(); - let portion = storage_at.fetch(&portion_addr).await?.map(|p| p.0).unwrap_or(0); - let balance_addr = quantus_subxt::api::storage().system().account(account); let info = storage_at.fetch_or_default(&balance_addr).await?; - Ok(format!( - "portion {:.2}%, free balance {} raw units", - portion as f64 / 10_000.0, - info.data.free - )) + Ok(format!("free balance {} raw units", info.data.free)) } async fn high_security_status(ctx: &ExerciseCtx) -> Result { diff --git a/src/cli/exercise/scenarios/recovery.rs b/src/cli/exercise/scenarios/recovery.rs deleted file mode 100644 index b30c3e6..0000000 --- a/src/cli/exercise/scenarios/recovery.rs +++ /dev/null @@ -1,206 +0,0 @@ -//! Recovery scenarios: full social-recovery lifecycle plus negative checks. - -use crate::{ - chain::quantus_subxt, - cli::exercise::{ - report::Report, - runner::{account_id_of, submit_expect_failure, submit_ok, ExerciseCtx}, - }, - error::{QuantusError, Result}, - exercise_step, - wallet::QuantumKeyPair, -}; -use subxt::ext::subxt_core::utils::MultiAddress; - -/// Dedicated accounts the lifecycle funds: the lost account, the rescuer and one friend. -pub const LIFECYCLE_ACCOUNTS: u128 = 3; - -/// What each of those accounts needs, sized from the chain's own recovery deposits (the config -/// deposit for one friend, and the rescuer's recovery deposit) so the phase fits the run budget -/// on any chain. All of it is swept back to the root account once the deposits are released. -pub fn account_funding( - client: &crate::chain::client::QuantusClient, - existential_deposit: u128, - test_unit: u128, -) -> Result { - let constants = client.client().constants(); - let config_deposit = constants - .at(&quantus_subxt::api::constants().recovery().config_deposit_base())? - .saturating_add( - constants.at(&quantus_subxt::api::constants().recovery().friend_deposit_factor())?, - ); - let recovery_deposit = - constants.at(&quantus_subxt::api::constants().recovery().recovery_deposit())?; - Ok(config_deposit - .max(recovery_deposit) - .saturating_add(existential_deposit) - .saturating_add(20 * test_unit)) -} - -pub async fn run(ctx: &mut ExerciseCtx, report: &mut Report, phase: &str) -> Result<()> { - exercise_step!(report, phase, "config_reads", config_reads(ctx)); - exercise_step!(report, phase, "initiate_not_recoverable", initiate_not_recoverable(ctx)); - exercise_step!(report, phase, "full_lifecycle", full_lifecycle(ctx)); - Ok(()) -} - -async fn config_reads(ctx: &mut ExerciseCtx) -> Result { - let root = account_id_of(&ctx.root)?; - let latest = ctx.client.get_latest_block().await?; - let storage_at = ctx.client.client().storage().at(latest); - - let recoverable = storage_at - .fetch(&quantus_subxt::api::storage().recovery().recoverable(root.clone())) - .await?; - let proxy = storage_at.fetch(&quantus_subxt::api::storage().recovery().proxy(root)).await?; - - Ok(format!( - "recovery storage decodes: root recoverable={}, proxy={}", - recoverable.is_some(), - proxy.is_some() - )) -} - -async fn initiate_not_recoverable(ctx: &mut ExerciseCtx) -> Result { - let lost = account_id_of(&ctx.bob)?; - let call = quantus_subxt::api::tx().recovery().initiate_recovery(MultiAddress::Id(lost)); - let rescuer = ctx.eph[0].clone(); - submit_expect_failure(ctx, &rescuer, call, &["NotRecoverable"]).await -} - -/// Whether `who` currently has a recovery `Proxy` entry pointing at some account. -async fn has_proxy(ctx: &ExerciseCtx, who: &QuantumKeyPair) -> Result { - let account = account_id_of(who)?; - let latest = ctx.client.get_latest_block().await?; - let storage_at = ctx.client.client().storage().at(latest); - Ok(storage_at - .fetch(&quantus_subxt::api::storage().recovery().proxy(account)) - .await? - .is_some()) -} - -/// create → initiate → vouch → claim → as_recovered → cancel_recovered → -/// close_recovery → poke_deposit → remove_recovery, with storage checks. -async fn full_lifecycle(ctx: &mut ExerciseCtx) -> Result { - // Dedicated accounts so recovery deposits/config never collide with the - // shared ephemeral senders used by other phases. - let lost = ctx.fresh_keypair()?; - let rescuer = ctx.fresh_keypair()?; - let friend = ctx.fresh_keypair()?; - - let funding = account_funding(&ctx.client, ctx.existential_deposit, ctx.test_unit)?; - let transfers = vec![ - (lost.try_to_account_id_ss58check()?, funding), - (rescuer.try_to_account_id_ss58check()?, funding), - (friend.try_to_account_id_ss58check()?, funding), - ]; - ctx.batch_fund_from_root(transfers).await?; - - let lost_id = account_id_of(&lost)?; - let rescuer_id = account_id_of(&rescuer)?; - let friend_id = account_id_of(&friend)?; - - // 1. Make `lost` recoverable: one friend, threshold 1, no claim delay. - let create = quantus_subxt::api::tx() - .recovery() - .create_recovery(vec![friend_id.clone()], 1, 0); - submit_ok(ctx, &lost, create).await?; - - // 2. Rescuer starts recovery; 3. friend vouches. - let initiate = quantus_subxt::api::tx() - .recovery() - .initiate_recovery(MultiAddress::Id(lost_id.clone())); - submit_ok(ctx, &rescuer, initiate).await?; - - let vouch = quantus_subxt::api::tx() - .recovery() - .vouch_recovery(MultiAddress::Id(lost_id.clone()), MultiAddress::Id(rescuer_id.clone())); - submit_ok(ctx, &friend, vouch).await?; - - // 4. Threshold met and delay elapsed (0 blocks): claim the account. - let claim = quantus_subxt::api::tx() - .recovery() - .claim_recovery(MultiAddress::Id(lost_id.clone())); - submit_ok(ctx, &rescuer, claim).await?; - - if !has_proxy(ctx, &rescuer).await? { - return Err(QuantusError::Generic( - "claim_recovery succeeded but no recovery proxy entry exists".to_string(), - )); - } - - // 5. Dispatch as the recovered account: move funds out of `lost`. - // The rescuer signs and pays fees, so the *lost* account's balance is the - // one that changes by exactly the transferred amount. - let drained = 10 * ctx.test_unit; - let lost_ss58 = lost.try_to_account_id_ss58check()?; - let lost_before = ctx.free_balance(&lost_ss58).await?; - let inner = { - use quantus_subxt::api::runtime_types::{ - pallet_balances::pallet::Call as BalancesCall, quantus_runtime::RuntimeCall, - }; - RuntimeCall::Balances(BalancesCall::transfer_allow_death { - dest: MultiAddress::Id(rescuer_id.clone()), - value: drained, - }) - }; - let as_recovered = quantus_subxt::api::tx() - .recovery() - .as_recovered(MultiAddress::Id(lost_id.clone()), inner); - submit_ok(ctx, &rescuer, as_recovered).await?; - - let lost_after = ctx.free_balance(&lost_ss58).await?; - if lost_after != lost_before - drained { - return Err(QuantusError::Generic(format!( - "as_recovered transfer not reflected: lost account went {lost_before} -> {lost_after}, expected -{drained}" - ))); - } - - // 6. Rescuer gives up proxy access. - let cancel = quantus_subxt::api::tx() - .recovery() - .cancel_recovered(MultiAddress::Id(lost_id.clone())); - submit_ok(ctx, &rescuer, cancel).await?; - if has_proxy(ctx, &rescuer).await? { - return Err(QuantusError::Generic( - "cancel_recovered succeeded but the proxy entry is still present".to_string(), - )); - } - - // 7. Owner closes the (claimed) recovery attempt and collects the deposit. - let close = quantus_subxt::api::tx() - .recovery() - .close_recovery(MultiAddress::Id(rescuer_id.clone())); - submit_ok(ctx, &lost, close).await?; - - // 8. Deposit poke is a paid no-op when nothing changed; must still dispatch. - let poke = quantus_subxt::api::tx().recovery().poke_deposit(None); - submit_ok(ctx, &lost, poke).await?; - - // 9. Remove the recovery configuration entirely. - let remove = quantus_subxt::api::tx().recovery().remove_recovery(); - submit_ok(ctx, &lost, remove).await?; - - let latest = ctx.client.get_latest_block().await?; - let recoverable = ctx - .client - .client() - .storage() - .at(latest) - .fetch(&quantus_subxt::api::storage().recovery().recoverable(lost_id)) - .await?; - if recoverable.is_some() { - return Err(QuantusError::Generic( - "remove_recovery succeeded but the recovery config is still present".to_string(), - )); - } - - // All deposits are released by now; hand the funding back to the run budget. - for account in [&lost, &rescuer, &friend] { - ctx.sweep_to_root(account).await?; - } - - Ok("full recovery lifecycle: create, initiate, vouch, claim, as_recovered \ - (funds drained), cancel_recovered, close, poke_deposit, remove — storage verified" - .to_string()) -} diff --git a/src/cli/exercise/scenarios/reversible.rs b/src/cli/exercise/scenarios/reversible.rs index 785a612..82b05ee 100644 --- a/src/cli/exercise/scenarios/reversible.rs +++ b/src/cli/exercise/scenarios/reversible.rs @@ -200,8 +200,8 @@ async fn guardian_recover_funds(ctx: &mut ExerciseCtx) -> Result { .set_high_security(Delay::BlockNumber(50), guardian); submit_ok(ctx, &account, enroll).await?; - // Leave a pending transfer behind so recovery also exercises the - // cancel-all-pending-holds path. + // Leave a pending transfer behind so the guardian cancel path is exercised + // with a hold outstanding. let recipient = ctx.fresh_keypair()?.try_to_account_id_ss58check()?; crate::cli::reversible::schedule_transfer( &ctx.client, diff --git a/src/cli/exercise/scenarios/utility.rs b/src/cli/exercise/scenarios/utility.rs index 431d21c..cd35e9a 100644 --- a/src/cli/exercise/scenarios/utility.rs +++ b/src/cli/exercise/scenarios/utility.rs @@ -1,8 +1,8 @@ -//! Utility pallet scenarios: force_batch, if_else, as_derivative. +//! Utility pallet scenarios. //! -//! `Utility::batch` is covered by the fuzz phase and `batch_all` backs every -//! CLI batch transfer; `dispatch_as`, `dispatch_as_fallible`, and `with_weight` -//! are root-only and unreachable from the outside. +//! `batch_all` is the pallet's only dispatchable, and it backs every CLI batch +//! transfer. Both halves of its contract are exercised: all items apply on +//! success, and none apply when any item fails. use crate::{ chain::quantus_subxt, @@ -13,16 +13,14 @@ use crate::{ error::{QuantusError, Result}, exercise_step, }; -use codec::Encode; use quantus_subxt::api::runtime_types::{ pallet_balances::pallet::Call as BalancesCall, quantus_runtime::RuntimeCall, }; use subxt::ext::subxt_core::utils::MultiAddress; pub async fn run(ctx: &mut ExerciseCtx, report: &mut Report, phase: &str) -> Result<()> { - exercise_step!(report, phase, "force_batch_partial_failure", force_batch_partial(ctx)); - exercise_step!(report, phase, "if_else_fallback", if_else_fallback(ctx)); - exercise_step!(report, phase, "as_derivative", as_derivative(ctx)); + exercise_step!(report, phase, "batch_all_applies_every_item", batch_all_applies(ctx)); + exercise_step!(report, phase, "batch_all_rolls_back_on_failure", batch_all_rolls_back(ctx)); Ok(()) } @@ -37,119 +35,54 @@ fn transfer_call(dest: crate::cli::common::SubxtAccountId32, value: u128) -> Run /// syntactically valid. const ABSURD_AMOUNT: u128 = u128::MAX / 2; -/// `force_batch` keeps executing after an item fails; the good item must land. -async fn force_batch_partial(ctx: &mut ExerciseCtx) -> Result { +/// Every item of a successful `batch_all` must apply. +async fn batch_all_applies(ctx: &mut ExerciseCtx) -> Result { let sender = ctx.eph[0].clone(); - let good_recipient = ctx.fresh_keypair()?; - let good_ss58 = good_recipient.try_to_account_id_ss58check()?; - let failing_recipient = ctx.fresh_keypair()?; + let first = ctx.fresh_keypair()?; + let second = ctx.fresh_keypair()?; + let first_ss58 = first.try_to_account_id_ss58check()?; + let second_ss58 = second.try_to_account_id_ss58check()?; let amount = ctx.test_unit; let calls = vec![ - transfer_call(account_id_of(&good_recipient)?, amount), - transfer_call(account_id_of(&failing_recipient)?, ABSURD_AMOUNT), + transfer_call(account_id_of(&first)?, amount), + transfer_call(account_id_of(&second)?, amount), ]; - let call = quantus_subxt::api::tx().utility().force_batch(calls); + let call = quantus_subxt::api::tx().utility().batch_all(calls); submit_ok(ctx, &sender, call).await?; - let good_balance = ctx.free_balance(&good_ss58).await?; - if good_balance != amount { - return Err(QuantusError::Generic(format!( - "force_batch good item not applied: recipient has {good_balance}, expected {amount}" - ))); + for (ss58, label) in [(&first_ss58, "first"), (&second_ss58, "second")] { + let balance = ctx.free_balance(ss58).await?; + if balance != amount { + return Err(QuantusError::Generic(format!( + "batch_all {label} item not applied: recipient has {balance}, expected {amount}" + ))); + } } - let failing_balance = - ctx.free_balance(&failing_recipient.try_to_account_id_ss58check()?).await?; - if failing_balance != 0 { - return Err(QuantusError::Generic(format!( - "force_batch failing item unexpectedly transferred {failing_balance}" - ))); - } - Ok("Utility::force_batch survived a failing item; good transfer verified".to_string()) + Ok("Utility::batch_all applied both transfers and both were verified".to_string()) } -/// `if_else` dispatches the fallback when the main call fails. -async fn if_else_fallback(ctx: &mut ExerciseCtx) -> Result { +/// `batch_all` is atomic: a failing item must roll back the items before it. +async fn batch_all_rolls_back(ctx: &mut ExerciseCtx) -> Result { let sender = ctx.eph[1].clone(); - let recipient = ctx.fresh_keypair()?; - let recipient_ss58 = recipient.try_to_account_id_ss58check()?; - let amount = ctx.test_unit; - - let main = transfer_call(account_id_of(&recipient)?, ABSURD_AMOUNT); - let fallback = transfer_call(account_id_of(&recipient)?, amount); - let call = quantus_subxt::api::tx().utility().if_else(main, fallback); - submit_ok(ctx, &sender, call).await?; - - let balance = ctx.free_balance(&recipient_ss58).await?; - if balance != amount { - return Err(QuantusError::Generic(format!( - "if_else fallback not applied: recipient has {balance}, expected {amount}" - ))); - } - Ok("Utility::if_else main call failed, fallback transfer executed and verified".to_string()) -} + let good = ctx.fresh_keypair()?; + let good_ss58 = good.try_to_account_id_ss58check()?; + let doomed = ctx.fresh_keypair()?; -/// Derivative (pseudonym) account of `who` at `index`, as computed by -/// `pallet_utility::derivative_account_id`. -fn derivative_account( - who: &crate::cli::common::SubxtAccountId32, - index: u16, -) -> crate::cli::common::SubxtAccountId32 { - let who_bytes: &[u8; 32] = who.as_ref(); - let entropy = sp_core::hashing::blake2_256(&(b"modlpy/utilisuba", who_bytes, index).encode()); - crate::cli::common::SubxtAccountId32::from(entropy) -} - -fn to_ss58(account: &crate::cli::common::SubxtAccountId32) -> String { - use sp_core::crypto::Ss58Codec; - let bytes: [u8; 32] = *account.as_ref(); - sp_core::crypto::AccountId32::from(bytes) - .to_ss58check_with_version(sp_core::crypto::Ss58AddressFormat::custom(189)) -} - -/// `as_derivative` must dispatch the inner call from the caller's derivative -/// account, not from the caller itself. -async fn as_derivative(ctx: &mut ExerciseCtx) -> Result { - let sender = ctx.eph[2].clone(); - let index: u16 = 42; - let derivative = derivative_account(&account_id_of(&sender)?, index); - let derivative_ss58 = to_ss58(&derivative); - - // The derivative account has to hold the funds the inner call moves. - let funding = 5 * ctx.test_unit; - crate::cli::send::transfer( - &ctx.client, - &sender.as_signer(), - &derivative_ss58, - funding, - None, - ctx.wait_mode(), - ) - .await?; - - let recipient = ctx.fresh_keypair()?; - let recipient_ss58 = recipient.try_to_account_id_ss58check()?; - let amount = 2 * ctx.test_unit; - let inner = transfer_call(account_id_of(&recipient)?, amount); - let call = quantus_subxt::api::tx().utility().as_derivative(index, inner); - submit_ok(ctx, &sender, call).await?; + let calls = vec![ + transfer_call(account_id_of(&good)?, ctx.test_unit), + transfer_call(account_id_of(&doomed)?, ABSURD_AMOUNT), + ]; + let call = quantus_subxt::api::tx().utility().batch_all(calls); + // The extrinsic is included; the batch itself dispatches an error, so the + // state change from the first item must not survive. + let _ = submit_ok(ctx, &sender, call).await; - let received = ctx.free_balance(&recipient_ss58).await?; - if received != amount { - return Err(QuantusError::Generic(format!( - "as_derivative transfer not applied: recipient has {received}, expected {amount}" - ))); - } - let derivative_after = ctx.free_balance(&derivative_ss58).await?; - if derivative_after != funding - amount { + let good_balance = ctx.free_balance(&good_ss58).await?; + if good_balance != 0 { return Err(QuantusError::Generic(format!( - "derivative account balance is {derivative_after}, expected {} — the inner \ - call did not draw from the derivative account", - funding - amount + "batch_all did not roll back: recipient has {good_balance}, expected 0" ))); } - Ok(format!( - "Utility::as_derivative (index {index}) transferred from the derivative account; \ - both balances verified" - )) + Ok("Utility::batch_all rolled back the successful item when a later item failed".to_string()) } diff --git a/src/cli/exercise/scenarios/vesting.rs b/src/cli/exercise/scenarios/vesting.rs index cf5ab17..357a7cb 100644 --- a/src/cli/exercise/scenarios/vesting.rs +++ b/src/cli/exercise/scenarios/vesting.rs @@ -443,12 +443,18 @@ async fn admin_dispatch( let approve = quantus_subxt::api::tx().multisig().approve( treasury.clone(), proposal_id, - quantus_subxt::api::runtime_types::bounded_collections::bounded_vec::BoundedVec(call_data), + quantus_subxt::api::runtime_types::bounded_collections::bounded_vec::BoundedVec( + call_data.clone(), + ), ); ctx.submit_budgeted(&bob, approve, 0).await?; let charlie = ctx.charlie.clone(); - let execute = quantus_subxt::api::tx().multisig().execute(treasury.clone(), proposal_id); + let execute = quantus_subxt::api::tx().multisig().execute( + treasury.clone(), + proposal_id, + crate::cli::multisig::decode_proposal_call(&call_data)?, + ); ctx.submit_budgeted(&charlie, execute, 0).await?; Ok(()) } diff --git a/src/cli/high_security.rs b/src/cli/high_security.rs index 0087c8d..c5f2943 100644 --- a/src/cli/high_security.rs +++ b/src/cli/high_security.rs @@ -197,36 +197,18 @@ pub async fn handle_high_security_command( // Convert guardian to Quantus SS58 format let guardian_ss58 = guardian_account.to_quantus_ss58(); - // Query storage for entrusted accounts - let storage_addr = quantus_subxt::api::storage() - .reversible_transfers() - .guardian_index(guardian_account); - let latest = quantus_client.get_latest_block().await?; - let value = quantus_client - .client() - .storage() - .at(latest) - .fetch(&storage_addr) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!("Fetch error: {e:?}")) - })?; - log_print!("🛡️ Guardian: {}", guardian_ss58.bright_cyan()); - if let Some(entrusted_accounts) = value { - if entrusted_accounts.0.is_empty() { - log_print!("📋 No entrusted accounts found."); - } else { - log_success!("✅ Found {} entrusted account(s):", entrusted_accounts.0.len()); - - for (index, account_id) in entrusted_accounts.0.iter().enumerate() { - let account_ss58 = account_id.to_quantus_ss58(); - log_print!(" {}. {}", index + 1, account_ss58.bright_green()); - } - } - } else { + let entrusted_accounts = + crate::cli::wallet::fetch_entrusted_accounts(&quantus_client, &guardian_ss58) + .await?; + if entrusted_accounts.is_empty() { log_print!("📋 No entrusted accounts found."); + } else { + log_success!("✅ Found {} entrusted account(s):", entrusted_accounts.len()); + for (index, account_ss58) in entrusted_accounts.iter().enumerate() { + log_print!(" {}. {}", index + 1, account_ss58.bright_green()); + } } Ok(()) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 030b900..af2e922 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -15,7 +15,6 @@ pub mod metadata; pub mod multisend; pub mod multisig; pub mod preimage; -pub mod recovery; pub mod reversible; pub mod runtime; pub mod scheduler; @@ -109,10 +108,6 @@ pub enum Commands { #[command(subcommand)] HighSecurity(high_security::HighSecurityCommands), - /// Recovery commands - #[command(subcommand)] - Recovery(recovery::RecoveryCommands), - /// Multisig commands (multi-signature wallets) #[command(subcommand)] Multisig(multisig::MultisigCommands), @@ -406,8 +401,6 @@ pub async fn execute_command( reversible::handle_reversible_command(reversible_cmd, node_url, execution_mode).await, Commands::HighSecurity(hs_cmd) => high_security::handle_high_security_command(hs_cmd, node_url, execution_mode).await, - Commands::Recovery(recovery_cmd) => - recovery::handle_recovery_command(recovery_cmd, node_url, execution_mode).await, Commands::Multisig(multisig_cmd) => multisig::handle_multisig_command(multisig_cmd, node_url, execution_mode).await, Commands::Scheduler(scheduler_cmd) => diff --git a/src/cli/multisig.rs b/src/cli/multisig.rs index 96cbd0d..3fbc288 100644 --- a/src/cli/multisig.rs +++ b/src/cli/multisig.rs @@ -1793,19 +1793,7 @@ async fn handle_approve( )); } - // Check if proposal exists - let proposal_query = quantus_subxt::api::storage() - .multisig() - .proposals(multisig_address.clone(), proposal_id); - let proposal_data = storage_at.fetch(&proposal_query).await?; - if proposal_data.is_none() { - log_error!("❌ Proposal {} not found", proposal_id); - return Err(crate::error::QuantusError::Generic(format!( - "Proposal {} does not exist", - proposal_id - ))); - } - let proposal = proposal_data.unwrap(); + let proposal = fetch_proposal(&storage_at, &multisig_address, proposal_id).await?; // Check if already approved by this signer if proposal.approvals.0.contains(&approver_account_id) { @@ -1845,6 +1833,46 @@ async fn handle_approve( Ok(()) } +/// Decodes a proposal's stored call bytes into the runtime call they encode. +/// +/// `execute` resubmits the call itself rather than its bytes, so bytes this build cannot +/// decode must fail here rather than produce a call the chain rejects. +pub(crate) fn decode_proposal_call( + bytes: &[u8], +) -> crate::error::Result { + use codec::Decode; + let mut cursor = bytes; + let call = quantus_subxt::api::runtime_types::quantus_runtime::RuntimeCall::decode(&mut cursor) + .map_err(|e| { + crate::error::QuantusError::Generic(format!("Could not decode the proposal call: {e}")) + })?; + if !cursor.is_empty() { + return Err(crate::error::QuantusError::Generic(format!( + "{} trailing bytes after the proposal call", + cursor.len() + ))); + } + Ok(call) +} + +/// Fetches the stored proposal, whose call bytes `approve` and `execute` are both bound to. +async fn fetch_proposal( + storage_at: &subxt::storage::Storage< + crate::chain::client::ChainConfig, + subxt::OnlineClient, + >, + multisig_account_id: &subxt::ext::subxt_core::utils::AccountId32, + proposal_id: u32, +) -> crate::error::Result { + let query = quantus_subxt::api::storage() + .multisig() + .proposals(multisig_account_id.clone(), proposal_id); + storage_at.fetch(&query).await?.ok_or_else(|| { + log_error!("❌ Proposal {} not found", proposal_id); + crate::error::QuantusError::Generic(format!("Proposal {} does not exist", proposal_id)) + }) +} + /// Execute an approved proposal (any signer) async fn handle_execute( multisig_address: String, @@ -1903,8 +1931,15 @@ async fn handle_execute( )); } - // Build transaction - let execute_tx = quantus_subxt::api::tx().multisig().execute(multisig_account_id, proposal_id); + // The chain dispatches the submitted call only when it re-encodes to the stored + // proposal, so resubmit exactly those bytes — that is what makes execute clearsignable. + let proposal = fetch_proposal(&storage_at, &multisig_account_id, proposal_id).await?; + let inner_call = decode_proposal_call(&proposal.call.0)?; + + let execute_tx = + quantus_subxt::api::tx() + .multisig() + .execute(multisig_account_id, proposal_id, inner_call); let exec_execution_mode = ExecutionMode { wait_for_transaction: true, ..execution_mode }; @@ -3250,3 +3285,60 @@ mod tests { assert_eq!(selected, Some(ss58(&wanted_address))); } } + +#[cfg(test)] +mod execute_call_tests { + use super::*; + use codec::Encode; + use quantus_subxt::api::runtime_types::{ + pallet_balances::pallet::Call as BalancesCall, quantus_runtime::RuntimeCall, + }; + use subxt::ext::subxt_core::utils::MultiAddress; + + fn transfer_call() -> RuntimeCall { + RuntimeCall::Balances(BalancesCall::transfer_allow_death { + dest: MultiAddress::Id(subxt::ext::subxt_core::utils::AccountId32([0x77u8; 32])), + value: 42_000_000_000u128, + }) + } + + #[test] + fn decode_proposal_call_round_trips_the_stored_bytes() { + let bytes = transfer_call().encode(); + let decoded = decode_proposal_call(&bytes).expect("decodes"); + // The chain only dispatches a call that re-encodes to the stored payload. + assert_eq!(decoded.encode(), bytes); + } + + #[test] + fn decode_proposal_call_rejects_undecodable_bytes() { + assert!(decode_proposal_call(&[0xff, 0xff]).is_err()); + } + + #[test] + fn decode_proposal_call_rejects_trailing_bytes() { + let mut bytes = transfer_call().encode(); + bytes.push(0x00); + let err = decode_proposal_call(&bytes).unwrap_err().to_string(); + assert!(err.contains("trailing bytes"), "{err}"); + } + + /// `approve` carries `BoundedVec` (compact length prefix); `execute` carries + /// `Box` inline. Getting this backwards produces a call the chain rejects. + #[test] + fn execute_encodes_the_inner_call_inline() { + let inner = transfer_call(); + let inner_bytes = inner.encode(); + + let execute = quantus_subxt::api::runtime_types::pallet_multisig::pallet::Call::execute { + multisig_address: subxt::ext::subxt_core::utils::AccountId32([0x99u8; 32]), + proposal_id: 7, + call: ::std::boxed::Box::new(inner), + } + .encode(); + + // call index + 32-byte address + u32 proposal id, then the inner call verbatim. + assert_eq!(&execute[execute.len() - inner_bytes.len()..], inner_bytes.as_slice()); + assert_eq!(execute.len(), 1 + 32 + 4 + inner_bytes.len()); + } +} diff --git a/src/cli/recovery.rs b/src/cli/recovery.rs deleted file mode 100644 index f4f619d..0000000 --- a/src/cli/recovery.rs +++ /dev/null @@ -1,573 +0,0 @@ -use crate::{ - chain::quantus_subxt, - cli::common::{resolve_address_with_subxt_account_id, resolve_to_subxt_account_id}, - log_error, log_print, log_success, -}; -use clap::Subcommand; -// no colored output needed here -use sp_core::crypto::{AccountId32 as SpAccountId32, Ss58Codec}; - -// Base unit (QUAN) decimals for amount conversions -const QUAN_DECIMALS: u128 = 1_000_000_000_000; // 10^12 - -/// Recovery-related commands -#[derive(Subcommand, Debug)] -pub enum RecoveryCommands { - /// Initiate recovery (rescuer starts) - Initiate { - /// Rescuer wallet name - #[arg(long)] - rescuer: String, - /// Lost account (SS58 or wallet name) - #[arg(long)] - lost: String, - /// Password for rescuer wallet - #[arg(short, long, hide = true)] - password: Option, - /// Read password from file (for scripting) - #[arg(long)] - password_file: Option, - }, - - /// Vouch for a recovery attempt (friend) - Vouch { - /// Friend wallet name (who vouches) - #[arg(long)] - friend: String, - /// Lost account (SS58 or wallet name) - #[arg(long)] - lost: String, - /// Rescuer account (SS58 or wallet name) - #[arg(long)] - rescuer: String, - /// Password for friend wallet - #[arg(short, long, hide = true)] - password: Option, - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Claim recovery (rescuer claims after threshold and delay) - Claim { - /// Rescuer wallet name - #[arg(long)] - rescuer: String, - /// Lost account (SS58 or wallet name) - #[arg(long)] - lost: String, - /// Password for rescuer wallet - #[arg(short, long, hide = true)] - password: Option, - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Close an active recovery (lost account stops a malicious attempt) - Close { - /// Lost wallet name (the recoverable account) - #[arg(long)] - lost: String, - /// Rescuer account (SS58 or wallet name) - #[arg(long)] - rescuer: String, - /// Password for lost wallet - #[arg(short, long, hide = true)] - password: Option, - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Cancel recovered proxy (rescuer disables their own proxy) - CancelProxy { - /// Rescuer wallet name - #[arg(long)] - rescuer: String, - /// Lost account (SS58 or wallet name) - #[arg(long)] - lost: String, - /// Password for rescuer wallet - #[arg(short, long, hide = true)] - password: Option, - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Query: active recovery info - Active { - /// Lost account (SS58 or wallet name) - #[arg(long)] - lost: String, - /// Rescuer account (SS58 or wallet name) - #[arg(long)] - rescuer: String, - }, - - /// Query: proxy-of (rescuer -> lost) - ProxyOf { - /// Rescuer account (SS58 or wallet name) - #[arg(long)] - rescuer: String, - }, - - /// Query: recovery config (recoverable) - Config { - /// Account to query (SS58 or wallet name) - #[arg(long)] - account: String, - }, - - /// Recover all funds from the lost account to a destination - RecoverAll { - /// Rescuer wallet name - #[arg(long)] - rescuer: String, - /// Lost account (SS58 or wallet name) - #[arg(long)] - lost: String, - /// Destination to receive the recovered funds - #[arg(long)] - dest: String, - /// Keep the lost account alive - #[arg(long, default_value_t = true)] - keep_alive: bool, - /// Password for rescuer wallet - #[arg(short, long, hide = true)] - password: Option, - /// Read password from file - #[arg(long)] - password_file: Option, - }, - - /// Recover a specific amount (in QUAN units) from the lost account to destination - RecoverAmount { - /// Rescuer wallet name - #[arg(long)] - rescuer: String, - /// Lost account (SS58 or wallet name) - #[arg(long)] - lost: String, - /// Destination to receive the recovered funds - #[arg(long)] - dest: String, - /// Amount in QUAN (human units) - multiplied by chain decimals - #[arg(long, value_name = "AMOUNT_QUAN")] - amount_quan: u128, - /// Keep the lost account alive - #[arg(long, default_value_t = true)] - keep_alive: bool, - /// Password for rescuer wallet - #[arg(short, long, hide = true)] - password: Option, - /// Read password from file - #[arg(long)] - password_file: Option, - }, -} - -pub async fn handle_recovery_command( - command: RecoveryCommands, - node_url: &str, - execution_mode: crate::cli::common::ExecutionMode, -) -> crate::error::Result<()> { - let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?; - - match command { - RecoveryCommands::Initiate { rescuer, lost, password, password_file } => { - let signer = crate::wallet::load_signer_from_wallet(&rescuer, password, password_file)?; - let rescuer_addr = signer.try_account_id_ss58check()?; - log_print!("🔑 Rescuer: {}", rescuer); - log_print!("🔑 Rescuer address: {}", rescuer_addr); - let lost_id = resolve_to_subxt_account_id(&lost)?; - let call = quantus_subxt::api::tx() - .recovery() - .initiate_recovery(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id)); - - let tx_hash = crate::cli::common::submit_transaction( - &quantus_client, - &signer, - call, - None, - execution_mode, - ) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!( - "Failed to submit initiate_recovery transaction: {e}" - )) - })?; - log_success!("✅ Initiate recovery submitted successfully {:?}", tx_hash); - }, - - RecoveryCommands::Vouch { friend, lost, rescuer, password, password_file } => { - let signer = crate::wallet::load_signer_from_wallet(&friend, password, password_file)?; - let lost_id = resolve_to_subxt_account_id(&lost)?; - let rescuer_id = resolve_to_subxt_account_id(&rescuer)?; - let call = quantus_subxt::api::tx().recovery().vouch_recovery( - subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id), - subxt::ext::subxt_core::utils::MultiAddress::Id(rescuer_id), - ); - let tx_hash = crate::cli::common::submit_transaction( - &quantus_client, - &signer, - call, - None, - execution_mode, - ) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!( - "Failed to submit vouch_recovery transaction: {e}" - )) - })?; - log_success!("✅ Vouch submitted successfully {:?}", tx_hash); - }, - - RecoveryCommands::Claim { rescuer, lost, password, password_file } => { - let signer = crate::wallet::load_signer_from_wallet(&rescuer, password, password_file)?; - let lost_id = resolve_to_subxt_account_id(&lost)?; - let call = quantus_subxt::api::tx() - .recovery() - .claim_recovery(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id)); - let tx_hash = crate::cli::common::submit_transaction( - &quantus_client, - &signer, - call, - None, - execution_mode, - ) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!( - "Failed to submit claim_recovery transaction: {e}" - )) - })?; - - log_success!("✅ Claim submitted successfully {:?}", tx_hash); - }, - - RecoveryCommands::RecoverAll { - rescuer, - lost, - dest, - keep_alive, - password, - password_file, - } => { - use quantus_subxt::api::runtime_types::pallet_balances::pallet::Call as BalancesCall; - - let signer = crate::wallet::load_signer_from_wallet(&rescuer, password, password_file)?; - let rescuer_addr = signer.try_account_id_ss58check()?; - log_print!("🔑 Rescuer: {}", rescuer); - log_print!("🔑 Rescuer address: {}", rescuer_addr); - - let (lost_resolved, lost_id) = resolve_address_with_subxt_account_id(&lost)?; - let (dest_resolved, dest_id) = resolve_address_with_subxt_account_id(&dest)?; - log_print!("🆘 Lost input: {} -> {}", lost, lost_resolved); - log_print!("🎯 Dest input: {} -> {}", dest, dest_resolved); - log_print!("🛟 keep_alive: {}", keep_alive); - - // Check proxy mapping for rescuer - let rescuer_id = resolve_to_subxt_account_id(&rescuer_addr)?; - let proxy_storage = quantus_subxt::api::storage().recovery().proxy(rescuer_id); - let latest = quantus_client.get_latest_block().await?; - let proxy_result = - quantus_client.client().storage().at(latest).fetch(&proxy_storage).await; - let proxy_of = match proxy_result { - Ok(Some(proxy)) => { - let proxy_bytes: &[u8; 32] = proxy.as_ref(); - let proxy_sp = SpAccountId32::from(*proxy_bytes); - log_print!("🧩 Proxy mapping: rescuer proxies -> {}", proxy_sp.to_ss58check()); - Some(proxy) - }, - Ok(None) => { - log_error!( - "❌ No proxy mapping found for rescuer - recovery not set up properly" - ); - return Err(crate::error::QuantusError::Generic( - "Rescuer has no proxy mapping. Recovery process may not be properly set up." - .to_string(), - )); - }, - Err(e) => { - log_error!("❌ Proxy mapping fetch error: {:?}", e); - return Err(crate::error::QuantusError::NetworkError(format!( - "Failed to check proxy mapping: {e:?}" - ))); - }, - }; - - // Validate that the proxy points to the correct lost account - if let Some(proxy) = proxy_of { - let proxy_bytes: &[u8; 32] = proxy.as_ref(); - let proxy_sp = SpAccountId32::from(*proxy_bytes); - let proxy_addr = proxy_sp.to_ss58check(); - if proxy_addr != lost_resolved { - log_error!( - "❌ Proxy mismatch! Rescuer proxies {} but we're trying to recover {}", - proxy_addr, - lost_resolved - ); - return Err(crate::error::QuantusError::Generic(format!( - "Proxy mismatch: rescuer proxies {proxy_addr} but target is {lost_resolved}" - ))); - } - log_print!("✅ Proxy validation successful"); - } - - let inner_call = quantus_subxt::api::Call::Balances(BalancesCall::transfer_all { - dest: subxt::ext::subxt_core::utils::MultiAddress::Id(dest_id), - keep_alive, - }); - log_print!("🧱 Inner call: Balances.transfer_all(keep_alive={})", keep_alive); - - let call = quantus_subxt::api::tx() - .recovery() - .as_recovered(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id), inner_call); - - let tx_hash = match crate::cli::common::submit_transaction( - &quantus_client, - &signer, - call, - None, - execution_mode, - ) - .await - { - Ok(h) => h, - Err(e) => { - log_error!("❌ Submit error (recover_all): {:?}", e); - return Err(e); - }, - }; - log_success!("✅ recover_all submitted successfully {:?}", tx_hash); - }, - - RecoveryCommands::RecoverAmount { - rescuer, - lost, - dest, - amount_quan, - keep_alive, - password, - password_file, - } => { - use quantus_subxt::api::runtime_types::pallet_balances::pallet::Call as BalancesCall; - - let signer = crate::wallet::load_signer_from_wallet(&rescuer, password, password_file)?; - - let rescuer_addr = signer.try_account_id_ss58check()?; - log_print!("🔑 Rescuer: {}", rescuer); - log_print!("🔑 Rescuer address: {}", rescuer_addr); - - let (lost_resolved, lost_id) = resolve_address_with_subxt_account_id(&lost)?; - let (dest_resolved, dest_id) = resolve_address_with_subxt_account_id(&dest)?; - log_print!("🆘 Lost input: {} -> {}", lost, lost_resolved); - log_print!("🎯 Dest input: {} -> {}", dest, dest_resolved); - log_print!("💵 amount_quan: {} (QUAN_DECIMALS={})", amount_quan, QUAN_DECIMALS); - log_print!("🛟 keep_alive: {}", keep_alive); - - let amount_plancks = amount_quan.saturating_mul(QUAN_DECIMALS); - log_print!("💵 amount_plancks: {}", amount_plancks); - - let latest = quantus_client.get_latest_block().await?; - - // Check account balance before attempting transfer - log_print!("💰 Checking lost account balance..."); - let balance_result = quantus_client - .client() - .storage() - .at(latest) - .fetch(&quantus_subxt::api::storage().system().account(lost_id.clone())) - .await; - - let account_info = match balance_result { - Ok(Some(info)) => info, - Ok(None) => { - log_error!("❌ Lost account not found in storage"); - return Err(crate::error::QuantusError::Generic( - "Lost account not found in storage".to_string(), - )); - }, - Err(e) => { - log_error!("❌ Failed to fetch account balance: {:?}", e); - return Err(crate::error::QuantusError::NetworkError(format!( - "Failed to fetch account balance: {e:?}" - ))); - }, - }; - - let available_balance = account_info.data.free; - log_print!("💰 Available balance: {} plancks", available_balance); - - if available_balance < amount_plancks { - log_error!( - "❌ Insufficient funds! Account has {} plancks but needs {} plancks", - available_balance, - amount_plancks - ); - return Err(crate::error::QuantusError::Generic(format!( - "Insufficient funds: account has {available_balance} plancks but transfer requires {amount_plancks} plancks" - ))); - } - - log_print!("✅ Balance validation successful - sufficient funds available"); - - let inner_call = - quantus_subxt::api::Call::Balances(BalancesCall::transfer_keep_alive { - dest: subxt::ext::subxt_core::utils::MultiAddress::Id(dest_id), - value: amount_plancks, - }); - - let call = quantus_subxt::api::tx() - .recovery() - .as_recovered(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id), inner_call); - - let tx_hash = match crate::cli::common::submit_transaction( - &quantus_client, - &signer, - call, - None, - execution_mode, - ) - .await - { - Ok(h) => h, - Err(e) => { - log_error!("❌ Submit error (recover_amount): {:?}", e); - return Err(e); - }, - }; - log_success!("✅ recover_amount submitted successfully {:?}", tx_hash); - }, - - RecoveryCommands::Close { lost, rescuer, password, password_file } => { - let signer = crate::wallet::load_signer_from_wallet(&lost, password, password_file)?; - let rescuer_id = resolve_to_subxt_account_id(&rescuer)?; - let call = quantus_subxt::api::tx() - .recovery() - .close_recovery(subxt::ext::subxt_core::utils::MultiAddress::Id(rescuer_id)); - let tx_hash = crate::cli::common::submit_transaction( - &quantus_client, - &signer, - call, - None, - execution_mode, - ) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!( - "Failed to submit close_recovery transaction: {e}" - )) - })?; - - log_print!("📋 Transaction submitted: 0x{}", hex::encode(tx_hash.as_ref())); - log_success!("✅ close_recovery submitted successfully"); - }, - - RecoveryCommands::CancelProxy { rescuer, lost, password, password_file } => { - let signer = crate::wallet::load_signer_from_wallet(&rescuer, password, password_file)?; - let lost_id = resolve_to_subxt_account_id(&lost)?; - let call = quantus_subxt::api::tx() - .recovery() - .cancel_recovered(subxt::ext::subxt_core::utils::MultiAddress::Id(lost_id)); - let tx_hash = crate::cli::common::submit_transaction( - &quantus_client, - &signer, - call, - None, - execution_mode, - ) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!( - "Failed to submit cancel_recovered transaction: {e}" - )) - })?; - - log_success!("✅ cancel_recovered submitted successfully {:?}", tx_hash); - }, - - RecoveryCommands::Active { lost, rescuer } => { - let lost_id = resolve_to_subxt_account_id(&lost)?; - let rescuer_id = resolve_to_subxt_account_id(&rescuer)?; - let storage_addr = - quantus_subxt::api::storage().recovery().active_recoveries(lost_id, rescuer_id); - let latest = quantus_client.get_latest_block().await?; - let value = quantus_client - .client() - .storage() - .at(latest) - .fetch(&storage_addr) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!("Fetch error: {e:?}")) - })?; - if let Some(active) = value { - log_print!( - "{}", - serde_json::json!({ - "created": active.created, - "deposit": active.deposit, - "friends_vouched": active.friends.0.len(), - }) - ); - } else { - log_print!("{}", serde_json::json!({"active": false})); - } - }, - - RecoveryCommands::ProxyOf { rescuer } => { - let rescuer_id = resolve_to_subxt_account_id(&rescuer)?; - let storage_addr = quantus_subxt::api::storage().recovery().proxy(rescuer_id); - let latest = quantus_client.get_latest_block().await?; - let value = quantus_client - .client() - .storage() - .at(latest) - .fetch(&storage_addr) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!("Fetch error: {e:?}")) - })?; - if let Some(lost_id) = value { - log_print!("{}", serde_json::json!({"lost": format!("{}", lost_id)})); - } else { - log_print!("{}", serde_json::json!({"lost": null})); - } - }, - - RecoveryCommands::Config { account } => { - let account_id = resolve_to_subxt_account_id(&account)?; - let storage_addr = quantus_subxt::api::storage().recovery().recoverable(account_id); - let latest = quantus_client.get_latest_block().await?; - let value = quantus_client - .client() - .storage() - .at(latest) - .fetch(&storage_addr) - .await - .map_err(|e| { - crate::error::QuantusError::NetworkError(format!("Fetch error: {e:?}")) - })?; - if let Some(cfg) = value { - log_print!( - "{}", - serde_json::json!({ - "delay_period": cfg.delay_period, - "deposit": cfg.deposit, - "friends": cfg.friends.0.iter().map(|f| format!("{f}")).collect::>(), - "threshold": cfg.threshold, - }) - ); - } else { - log_print!("{}", serde_json::json!({"recoverable": false})); - } - }, - }; - - Ok(()) -} diff --git a/src/cli/tech_referenda.rs b/src/cli/tech_referenda.rs index bd1b4ff..a379e84 100644 --- a/src/cli/tech_referenda.rs +++ b/src/cli/tech_referenda.rs @@ -52,29 +52,6 @@ pub enum TechReferendaCommands { password_file: Option, }, - /// Propose a new Treasury portion (% of block rewards sent to treasury) - /// - /// Creates the preimage and submits the referendum in one step. - #[command( - arg_required_else_help = true, - after_help = "Examples:\n quantus tech-referenda submit-treasury-portion --portion-permill 500000 --from alice # 50%\n quantus tech-referenda submit-treasury-portion --portion-permill 100000 --from alice # 10%" - )] - SubmitTreasuryPortion { - /// New treasury portion in Permill (parts per million, 0-1000000). 500000 = 50% - #[arg(long, value_name = "PERMILL", value_parser = clap::value_parser!(u32).range(0..=1_000_000))] - portion_permill: u32, - - /// Wallet name to sign with (must be a Tech Collective member) - #[arg(short, long, value_name = "WALLET")] - from: String, - - #[arg(short, long, hide = true)] - password: Option, - - #[arg(long)] - password_file: Option, - }, - /// List all Tech Referenda proposals and their current status List, @@ -190,21 +167,6 @@ pub async fn handle_tech_referenda_command( execution_mode, ) .await, - TechReferendaCommands::SubmitTreasuryPortion { - portion_permill, - from, - password, - password_file, - } => - submit_treasury_portion_with_preimage( - &quantus_client, - portion_permill, - &from, - password, - password_file, - execution_mode, - ) - .await, TechReferendaCommands::List => list_proposals(&quantus_client).await, TechReferendaCommands::Get { index } => get_proposal_details(&quantus_client, index).await, TechReferendaCommands::Status { index } => @@ -352,84 +314,6 @@ async fn submit_runtime_upgrade_with_preimage( Ok(()) } -/// Submit a Tech Referenda proposal to set the Treasury portion (creates preimage first) -async fn submit_treasury_portion_with_preimage( - quantus_client: &crate::chain::client::QuantusClient, - portion_permill: u32, - from: &str, - password: Option, - password_file: Option, - execution_mode: crate::cli::common::ExecutionMode, -) -> crate::error::Result<()> { - use sp_runtime::traits::{BlakeTwo256, Hash}; - - log_print!("📝 Submitting Treasury Portion Update Proposal to Tech Referenda"); - log_print!(" 📊 New portion (Permill): {}", portion_permill.to_string().bright_cyan()); - log_print!( - " 📊 New portion (%): {}", - format!("{:.2}%", (portion_permill as f64) / 10000.0).bright_cyan() - ); - log_print!(" 🔑 Submitted by: {}", from.bright_yellow()); - - // Load wallet signer - let signer = crate::wallet::load_signer_from_wallet(from, password, password_file)?; - - // Build a static payload for TreasuryPallet::set_treasury_portion and encode full call data - // Note: runtime_types::Permill is a tuple struct (u32 parts-per-million). - let portion = - quantus_subxt::api::runtime_types::sp_arithmetic::per_things::Permill(portion_permill); - let set_portion_payload = - quantus_subxt::api::tx().treasury_pallet().set_treasury_portion(portion); - - let metadata = quantus_client.client().metadata(); - let encoded_call = <_ as subxt::tx::Payload>::encode_call_data(&set_portion_payload, &metadata) - .map_err(|e| QuantusError::Generic(format!("Failed to encode call data: {:?}", e)))?; - - log_verbose!("📝 Encoded call size: {} bytes", encoded_call.len()); - - // Must match `frame_system::Config::Hashing` (BlakeTwo256) — same key as `pallet_preimage`. - let preimage_hash: sp_core::H256 = BlakeTwo256::hash(&encoded_call); - log_print!("🔗 Preimage hash: {:?}", preimage_hash); - - let call_len = encoded_call.len() as u32; - crate::cli::common::submit_preimage(quantus_client, &signer, encoded_call, execution_mode) - .await?; - - // Build TechReferenda::submit call using Lookup preimage reference - type ProposalBounded = - quantus_subxt::api::runtime_types::frame_support::traits::preimages::Bounded< - quantus_subxt::api::runtime_types::quantus_runtime::RuntimeCall, - quantus_subxt::api::runtime_types::sp_runtime::traits::BlakeTwo256, - >; - - let preimage_hash_subxt: subxt::utils::H256 = preimage_hash; - let proposal: ProposalBounded = - ProposalBounded::Lookup { hash: preimage_hash_subxt, len: call_len }; - - let raw_origin_root = - quantus_subxt::api::runtime_types::frame_support::dispatch::RawOrigin::Root; - let origin_caller = - quantus_subxt::api::runtime_types::quantus_runtime::OriginCaller::system(raw_origin_root); - - let enactment = - quantus_subxt::api::runtime_types::frame_support::traits::schedule::DispatchTime::After( - 0u32, - ); - - log_print!("🔧 Submitting TechReferenda::submit..."); - let submit_call = - quantus_subxt::api::tx() - .tech_referenda() - .submit(origin_caller, proposal, enactment); - - let tx_hash = - submit_transaction(quantus_client, &signer, submit_call, None, execution_mode).await?; - log_success!("Treasury portion proposal submitted! Hash: {:?}", tx_hash); - - log_print!("💡 Use 'quantus tech-referenda list' to see active proposals"); - Ok(()) -} - /// List recent Tech Referenda proposals async fn list_proposals( quantus_client: &crate::chain::client::QuantusClient, diff --git a/src/cli/treasury.rs b/src/cli/treasury.rs index 638162d..8457a43 100644 --- a/src/cli/treasury.rs +++ b/src/cli/treasury.rs @@ -1,6 +1,6 @@ //! `quantus treasury` subcommand – Treasury account info //! -//! The chain Treasury is a single account that receives a configurable portion of mining rewards. +//! The chain Treasury is a single account that receives a portion of mining rewards. //! This command shows the treasury account and its balance. use crate::{chain::quantus_subxt, cli::address_format::QuantusSS58, log_print}; use clap::Subcommand; @@ -42,10 +42,6 @@ async fn show_treasury_info( crate::error::QuantusError::Generic("Treasury account not set in storage".to_string()) })?; - // Portion of mining rewards that goes to treasury (Permill: parts per million) - let portion_addr = quantus_subxt::api::storage().treasury_pallet().treasury_portion(); - let portion = storage_at.fetch(&portion_addr).await?.map(|p| p.0).unwrap_or(0); - // Account balance let account_storage = quantus_subxt::api::storage().system().account(treasury_account.clone()); let account_info = storage_at.fetch(&account_storage).await?.ok_or_else(|| { @@ -61,9 +57,6 @@ async fn show_treasury_info( let account_ss58 = treasury_account.to_quantus_ss58(); log_print!("📍 Account: {}", account_ss58.bright_yellow()); - // Permill is parts per million, so divide by 10000 to get percentage - let portion_percent = portion as f64 / 10000.0; - log_print!("📊 Reward portion: {:.2}%", portion_percent.to_string().bright_cyan()); log_print!("💰 Free: {}", formatted_free); log_print!("💰 Reserved: {}", formatted_reserved); diff --git a/src/cli/wallet.rs b/src/cli/wallet.rs index 6d11fb2..6ffd379 100644 --- a/src/cli/wallet.rs +++ b/src/cli/wallet.rs @@ -276,37 +276,45 @@ async fn fetch_high_security_status( Ok(Some((guardian_ss58, delay_str))) } -/// Fetch list of accounts for which this account is guardian (guardian_index). -/// Returns an empty vec when the storage entry is absent (`None`), and an error on failure. -async fn fetch_guardian_for_list( +/// Accounts that entrust [`guardian_ss58`] as their high-security guardian. +/// +/// The runtime keeps no guardian -> accounts reverse index, so this walks the +/// `HighSecurityAccounts` map and keeps the entries naming this guardian. +pub(crate) async fn fetch_entrusted_accounts( quantus_client: &crate::chain::client::QuantusClient, - account_ss58: &str, + guardian_ss58: &str, ) -> crate::error::Result> { - let account_id_sp = SpAccountId32::from_ss58check(account_ss58) - .map_err(|e| QuantusError::Generic(format!("Invalid SS58 for guardian_index: {e:?}")))?; - let account_bytes: [u8; 32] = *account_id_sp.as_ref(); - let account_id = subxt::ext::subxt_core::utils::AccountId32::from(account_bytes); + let guardian_sp = SpAccountId32::from_ss58check(guardian_ss58) + .map_err(|e| QuantusError::Generic(format!("Invalid SS58 for guardian: {e:?}")))?; + let guardian_bytes: [u8; 32] = *guardian_sp.as_ref(); + let guardian = subxt::ext::subxt_core::utils::AccountId32::from(guardian_bytes); - let storage_addr = - quantus_subxt::api::storage().reversible_transfers().guardian_index(account_id); let latest = quantus_client.get_latest_block().await?; - let value = quantus_client - .client() - .storage() - .at(latest) - .fetch(&storage_addr) - .await - .map_err(|e| QuantusError::NetworkError(format!("Fetch guardian_index: {e:?}")))?; - - let list: Vec = value - .map(|bounded| { - bounded - .0 - .iter() - .map(|a: &subxt::ext::subxt_core::utils::AccountId32| a.to_quantus_ss58()) - .collect() - }) - .unwrap_or_default(); + let query = quantus_subxt::api::storage() + .reversible_transfers() + .high_security_accounts_iter(); + let mut entries = + quantus_client.client().storage().at(latest).iter(query).await.map_err(|e| { + QuantusError::NetworkError(format!("Iter high_security_accounts: {e:?}")) + })?; + + let mut list = Vec::new(); + while let Some(entry) = entries.next().await { + let entry = entry.map_err(|e| { + QuantusError::NetworkError(format!("Read high_security_accounts: {e:?}")) + })?; + if entry.value.guardian != guardian { + continue; + } + // Blake2_128Concat: the storage key ends with the unhashed AccountId32. + let key = entry.key_bytes; + let account_bytes: [u8; 32] = key[key.len() - 32..].try_into().map_err(|_| { + QuantusError::Generic("high_security_accounts key shorter than an account".to_string()) + })?; + list.push( + subxt::ext::subxt_core::utils::AccountId32::from(account_bytes).to_quantus_ss58(), + ); + } Ok(list) } @@ -604,7 +612,7 @@ pub async fn handle_wallet_command( // Guardian for: accounts that have this wallet as their interceptor if let Ok(entrusted) = - fetch_guardian_for_list(&quantus_client, &wallet_info.address) + fetch_entrusted_accounts(&quantus_client, &wallet_info.address) .await { if entrusted.is_empty() { diff --git a/src/quantus_metadata.scale b/src/quantus_metadata.scale index 9b2ea80a2335b8eb79da60f10223c2e9897f1b39..4109e13967cdd7541590958ce567c24d15ec33e0 100644 GIT binary patch delta 16348 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 delta 23885 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 From 2dfa0a03a875da2fc1a804ba3589900c37ab6ab8 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Sun, 30 Aug 2026 09:05:06 +0800 Subject: [PATCH 2/7] feat(multisig): cap the call a proposal may carry at 2 KiB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A call a signer cannot review is one they cannot meaningfully approve, so bound what propose and execute will put in front of one. Sized by the largest call we ever expect to put through a multisig: a `batch_all` of 32 transfers (double the 16 a batch is expected to carry). At the worst-case encoding of every field that is 1667 bytes, or 1707 inside a multisig wrapper, so 2 KiB leaves headroom — asserted against the constant at compile time. The chain's own `MaxCallSize` is 10 KiB; this is deliberately tighter. The five propose call sites now share one `build_propose_tx` that enforces it, and `decode_proposal_call` enforces it on the approve and execute paths. --- src/cli/multisig.rs | 85 ++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/src/cli/multisig.rs b/src/cli/multisig.rs index 3fbc288..226d3c9 100644 --- a/src/cli/multisig.rs +++ b/src/cli/multisig.rs @@ -638,11 +638,7 @@ pub async fn propose_transfer( Compact(amount).encode_to(&mut call_data); // Build propose transaction - let propose_tx = quantus_subxt::api::tx().multisig().propose( - multisig_address, - quantus_subxt::api::runtime_types::bounded_collections::bounded_vec::BoundedVec(call_data), - expiry, - ); + let propose_tx = build_propose_tx(multisig_address, call_data, expiry)?; // Submit transaction let execution_mode = ExecutionMode { finalized: false, wait_for_transaction: false }; @@ -671,11 +667,7 @@ pub async fn propose_custom( expiry: u32, ) -> crate::error::Result { // Build propose transaction - let propose_tx = quantus_subxt::api::tx().multisig().propose( - multisig_address, - quantus_subxt::api::runtime_types::bounded_collections::bounded_vec::BoundedVec(call_data), - expiry, - ); + let propose_tx = build_propose_tx(multisig_address, call_data, expiry)?; // Submit transaction let execution_mode = ExecutionMode { finalized: false, wait_for_transaction: false }; @@ -1639,11 +1631,7 @@ async fn handle_propose( let signer = crate::wallet::load_signer_from_wallet(&from, password, password_file)?; // Build transaction - let propose_tx = quantus_subxt::api::tx().multisig().propose( - multisig_address.clone(), - quantus_subxt::api::runtime_types::bounded_collections::bounded_vec::BoundedVec(call_data), - expiry, - ); + let propose_tx = build_propose_tx(multisig_address.clone(), call_data, expiry)?; // Always wait for transaction confirmation let propose_execution_mode = ExecutionMode { wait_for_transaction: true, ..execution_mode }; @@ -1708,11 +1696,7 @@ async fn handle_propose_with_call_data( let signer = crate::wallet::load_signer_from_wallet(&from, password, password_file)?; // Build transaction - let propose_tx = quantus_subxt::api::tx().multisig().propose( - multisig_account_id, - quantus_subxt::api::runtime_types::bounded_collections::bounded_vec::BoundedVec(call_data), - expiry, - ); + let propose_tx = build_propose_tx(multisig_account_id, call_data, expiry)?; // Always wait for transaction confirmation let propose_execution_mode = ExecutionMode { wait_for_transaction: true, ..execution_mode }; @@ -1833,6 +1817,46 @@ async fn handle_approve( Ok(()) } +/// Largest encoded call a multisig proposal may carry. +/// +/// Sized by the biggest call we ever expect to put through a multisig: a `batch_all` of 32 +/// transfers — double the 16 a batch is expected to carry — which is 1667 bytes at the +/// worst-case encoding of every field, or 1707 inside a multisig wrapper. The chain's own +/// `MaxCallSize` is 10 KiB; this is deliberately tighter, because a call a signer cannot +/// review is one they cannot meaningfully approve. +pub(crate) const MAX_CALL_BYTES: usize = 2 * 1024; + +/// The limit has to clear the call it was sized for, or it is not the limit we documented. +const _: () = assert!(MAX_CALL_BYTES > 1707); + +/// Rejects a proposal call larger than a signer will review. +pub(crate) fn check_call_size(len: usize) -> crate::error::Result<()> { + if len > MAX_CALL_BYTES { + return Err(crate::error::QuantusError::Generic(format!( + "Call is {len} bytes, over the {MAX_CALL_BYTES} byte review limit" + ))); + } + Ok(()) +} + +/// Builds `multisig.propose`, refusing a call a signer could not review. +fn build_propose_tx( + multisig_address: subxt::ext::subxt_core::utils::AccountId32, + call_data: Vec, + expiry: u32, +) -> crate::error::Result< + subxt::ext::subxt_core::tx::payload::StaticPayload< + quantus_subxt::api::multisig::calls::types::Propose, + >, +> { + check_call_size(call_data.len())?; + Ok(quantus_subxt::api::tx().multisig().propose( + multisig_address, + quantus_subxt::api::runtime_types::bounded_collections::bounded_vec::BoundedVec(call_data), + expiry, + )) +} + /// Decodes a proposal's stored call bytes into the runtime call they encode. /// /// `execute` resubmits the call itself rather than its bytes, so bytes this build cannot @@ -1841,6 +1865,7 @@ pub(crate) fn decode_proposal_call( bytes: &[u8], ) -> crate::error::Result { use codec::Decode; + check_call_size(bytes.len())?; let mut cursor = bytes; let call = quantus_subxt::api::runtime_types::quantus_runtime::RuntimeCall::decode(&mut cursor) .map_err(|e| { @@ -3177,11 +3202,7 @@ async fn handle_high_security_set( let signer = crate::wallet::load_signer_from_wallet(&from, password, password_file)?; // Build propose transaction - let propose_tx = quantus_subxt::api::tx().multisig().propose( - multisig_account_id, - quantus_subxt::api::runtime_types::bounded_collections::bounded_vec::BoundedVec(call_data), - expiry, - ); + let propose_tx = build_propose_tx(multisig_account_id, call_data, expiry)?; // Always wait for transaction confirmation let propose_execution_mode = ExecutionMode { wait_for_transaction: true, ..execution_mode }; @@ -3310,6 +3331,20 @@ mod execute_call_tests { assert_eq!(decoded.encode(), bytes); } + #[test] + fn decode_proposal_call_rejects_a_call_over_the_review_limit() { + let oversized = vec![0u8; MAX_CALL_BYTES + 1]; + let err = decode_proposal_call(&oversized).unwrap_err().to_string(); + assert!(err.contains("review limit"), "{err}"); + } + + #[test] + fn propose_refuses_a_call_over_the_review_limit() { + let address = subxt::ext::subxt_core::utils::AccountId32([0x99u8; 32]); + assert!(build_propose_tx(address.clone(), vec![0u8; MAX_CALL_BYTES + 1], 5000).is_err()); + assert!(build_propose_tx(address, transfer_call().encode(), 5000).is_ok()); + } + #[test] fn decode_proposal_call_rejects_undecodable_bytes() { assert!(decode_proposal_call(&[0xff, 0xff]).is_err()); From 6b27907ae4a2eacdd83854c4706b29d1ddc50677 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Sun, 30 Aug 2026 18:58:37 +0800 Subject: [PATCH 3/7] refactor(multisig): mirror the chain's MaxCallSize instead of a tighter limit A client limit below the chain's refuses proposals the chain accepts, leaving a multisig no signer can act on. Use the chain's number: 10 KiB, from `pallet_multisig::Config::MaxCallSize`. --- src/cli/multisig.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/cli/multisig.rs b/src/cli/multisig.rs index 226d3c9..cd99ed6 100644 --- a/src/cli/multisig.rs +++ b/src/cli/multisig.rs @@ -1817,17 +1817,12 @@ async fn handle_approve( Ok(()) } -/// Largest encoded call a multisig proposal may carry. +/// Largest inner call a multisig proposal may carry, mirroring the runtime's +/// `pallet_multisig::Config::MaxCallSize` (`BoundedVec`, 10 KiB). /// -/// Sized by the biggest call we ever expect to put through a multisig: a `batch_all` of 32 -/// transfers — double the 16 a batch is expected to carry — which is 1667 bytes at the -/// worst-case encoding of every field, or 1707 inside a multisig wrapper. The chain's own -/// `MaxCallSize` is 10 KiB; this is deliberately tighter, because a call a signer cannot -/// review is one they cannot meaningfully approve. -pub(crate) const MAX_CALL_BYTES: usize = 2 * 1024; - -/// The limit has to clear the call it was sized for, or it is not the limit we documented. -const _: () = assert!(MAX_CALL_BYTES > 1707); +/// Deliberately the chain's number rather than a tighter one of our own: a limit below it +/// would refuse proposals the chain accepts, leaving a multisig no signer could act on. +pub(crate) const MAX_CALL_BYTES: usize = 10 * 1024; /// Rejects a proposal call larger than a signer will review. pub(crate) fn check_call_size(len: usize) -> crate::error::Result<()> { From 2cdc1a983d484b9fc335bc371f7904fe6af6f990 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Sun, 30 Aug 2026 19:59:54 +0800 Subject: [PATCH 4/7] feat(qr): add a generator for the cold signing QR fixture corpus Builds a signing request per supported call, encodes it through the bundled chain metadata, wraps it in the wallet envelope, UR-encodes it and writes the QR frames as SVG plus a viewer page. The output is committed in quantus-apps under cold-wallet-app/test/fixtures/qr and is parsed by tests in both wallets. SVG rather than PNG so the corpus needs no image toolchain, and horizontal runs are merged into one path so a frame is about 5 KB instead of 100 KB. --- examples/generate_qr_fixtures.rs | 408 +++++++++++++++++++++++++++++++ src/cli/wallet.rs | 5 +- src/cli/wormhole.rs | 5 +- src/qr/scanner.rs | 5 +- 4 files changed, 417 insertions(+), 6 deletions(-) create mode 100644 examples/generate_qr_fixtures.rs diff --git a/examples/generate_qr_fixtures.rs b/examples/generate_qr_fixtures.rs new file mode 100644 index 0000000..b9647e4 --- /dev/null +++ b/examples/generate_qr_fixtures.rs @@ -0,0 +1,408 @@ +//! Generates the cold-signing QR fixture corpus used to test wallet parsing. +//! +//! Each fixture is a complete signing payload (call + signed extensions) wrapped in the +//! `{"v":1,"signer":...,"payload":"0x.."}` envelope and UR-encoded into QR frames, which is +//! exactly what a cold wallet scans. Every consumer of the corpus — the Keystone firmware +//! parser, the cold wallet app, the reference parser — reads the same bytes. +//! +//! Run: cargo run --example generate_qr_fixtures -- + +use codec::{Compact, Encode}; +use qrcode::{types::Color, EcLevel, QrCode}; +use quantus_cli::chain::quantus_subxt::api; +use std::{fs, path::Path}; + +/// Planck, so the firmware's `KNOWN_NETWORKS` check accepts these payloads. +const PLANCK_GENESIS: [u8; 32] = [ + 0x49, 0x01, 0xbf, 0x5c, 0x57, 0xfd, 0x3f, 0x9e, 0x72, 0x6a, 0xf3, 0x99, 0xc7, 0x63, 0xde, 0x66, + 0x70, 0xdb, 0xdb, 0x11, 0x5a, 0x91, 0xc0, 0x23, 0x7e, 0x17, 0x3f, 0x16, 0xee, 0xf6, 0x5e, 0x72, +]; +const SPEC_VERSION: u32 = 147; +const TRANSACTION_VERSION: u32 = 6; + +/// The signer the request is addressed to. Any valid Quantus address works; the wallet only +/// signs when it holds this account. +const SIGNER_SS58: &str = "qzn9sph6ZoQxwseSFyrdfTUEWmozsex7hhCJQPG29nbgesGei"; + +const DEST: [u8; 32] = [0x77; 32]; +const MULTISIG: [u8; 32] = [0x99; 32]; +const SIGNER_A: [u8; 32] = [0xaa; 32]; +const SIGNER_B: [u8; 32] = [0xbb; 32]; +const SIGNER_C: [u8; 32] = [0xcc; 32]; + +const UNIT: u128 = 1_000_000_000_000; + +struct Fixture { + slug: &'static str, + pallet_call: &'static str, + /// The call a wallet must show nested inside this one, if any. + inner_call: Option<&'static str>, + description: &'static str, + call: Vec, +} + +fn dest( +) -> subxt::ext::subxt_core::utils::MultiAddress { + subxt::ext::subxt_core::utils::MultiAddress::Id(subxt::ext::subxt_core::utils::AccountId32( + DEST, + )) +} + +fn account(bytes: [u8; 32]) -> subxt::ext::subxt_core::utils::AccountId32 { + subxt::ext::subxt_core::utils::AccountId32(bytes) +} + +/// Call bytes, encoded through the same metadata the CLI signs with. +fn call_data(metadata: &subxt::Metadata, call: &C) -> Vec { + call.encode_call_data(metadata) + .expect("call encodes against the bundled metadata") +} + +fn transfer_call(metadata: &subxt::Metadata, amount: u128) -> Vec { + call_data(metadata, &api::tx().balances().transfer_allow_death(dest(), amount)) +} + +/// The `TxExtension` bytes that follow the call: explicit parts, then the implicit ones. +fn extension_suffix(nonce: u32, tip: u128) -> Vec { + let mut v = Vec::new(); + v.push(0); // era: immortal + v.extend(Compact(nonce).encode()); + v.extend(Compact(tip).encode()); + v.push(0); // CheckMetadataHash mode: disabled + v.extend_from_slice(&SPEC_VERSION.to_le_bytes()); + v.extend_from_slice(&TRANSACTION_VERSION.to_le_bytes()); + v.extend_from_slice(&PLANCK_GENESIS); + v.extend_from_slice(&[0x11; 32]); // block hash, immortal so not checked + v.push(0); // metadata hash: None + v +} + +fn signing_payload(call: &[u8], nonce: u32, tip: u128) -> Vec { + let mut payload = call.to_vec(); + payload.extend(extension_suffix(nonce, tip)); + payload +} + +fn envelope(payload: &[u8]) -> String { + format!(r#"{{"v":1,"signer":"{}","payload":"0x{}"}}"#, SIGNER_SS58, hex::encode(payload)) +} + +/// A QR frame as standalone SVG, so the corpus needs no image toolchain and works offline. +/// +/// One module per unit with a viewBox, and horizontal runs merged into a single path, which +/// keeps a frame around 5 KB instead of 100 KB of individual rects. +fn frame_svg(part: &str) -> String { + const QUIET: usize = 4; + let code = QrCode::with_error_correction_level(part.as_bytes(), EcLevel::L) + .expect("UR part fits in a QR code"); + let width = code.width(); + let modules = code.to_colors(); + let size = width + QUIET * 2; + + let mut path = String::new(); + for y in 0..width { + let mut x = 0; + while x < width { + if modules[y * width + x] != Color::Dark { + x += 1; + continue; + } + let start = x; + while x < width && modules[y * width + x] == Color::Dark { + x += 1; + } + let run = x - start; + path.push_str(&format!("M{} {}h{run}v1h-{run}z", start + QUIET, y + QUIET)); + } + } + + format!( + r##""##, + px = size * 8 + ) +} + +/// A page that cycles the frames, for holding up to the simulator or a device camera. +fn viewer_html(slug: &str, description: &str, frames: usize) -> String { + format!( + r#" + +{slug} + + +

{description}

+

{slug} — frame 1/{frames} — 200ms + (←/→ to change speed)

+ +"# + ) +} + +/// Landing page listing every case, so a tester can pick one and show it to a camera. +fn index_html(links: &[String]) -> String { + format!( + r#" + +Cold signing QR fixtures + +

Cold signing QR fixtures

+

Reduced set: the calls the Keystone firmware parses today. Open one, then point the + device or simulator at the animated QR.

+
    +{} +
+"#, + links.join("\n") + ) +} + +fn build_fixtures(metadata: &subxt::Metadata) -> Vec { + let inner_transfer = transfer_call(metadata, 42 * UNIT); + + let reversible_with_delay = call_data( + metadata, + &api::tx().reversible_transfers().schedule_transfer_with_delay( + dest(), + 5 * UNIT, + api::runtime_types::qp_scheduler::BlockNumberOrTimestamp::Timestamp(3_600_000), + ), + ); + + vec![ + Fixture { + slug: "01-transfer-allow-death", + inner_call: None, + pallet_call: "balances.transfer_allow_death", + description: "Plain transfer of 1 QUAN.", + call: transfer_call(metadata, UNIT), + }, + Fixture { + slug: "02-transfer-keep-alive", + inner_call: None, + pallet_call: "balances.transfer_keep_alive", + description: "Transfer of 2.5 QUAN that leaves the account above existential deposit.", + call: call_data( + metadata, + &api::tx().balances().transfer_keep_alive(dest(), 2_500_000_000_000u128), + ), + }, + Fixture { + slug: "03-schedule-transfer", + inner_call: None, + pallet_call: "reversible_transfers.schedule_transfer", + description: "Reversible transfer of 3 QUAN using the account's configured delay.", + call: call_data( + metadata, + &api::tx().reversible_transfers().schedule_transfer(dest(), 3 * UNIT), + ), + }, + Fixture { + slug: "04-schedule-transfer-with-delay", + inner_call: None, + pallet_call: "reversible_transfers.schedule_transfer_with_delay", + description: "Reversible transfer of 5 QUAN with an explicit one-hour reversal window.", + call: reversible_with_delay, + }, + Fixture { + slug: "05-multisig-create", + inner_call: None, + pallet_call: "multisig.create_multisig", + description: "Create a 2-of-3 multisig.", + call: call_data( + metadata, + &api::tx().multisig().create_multisig( + vec![account(SIGNER_A), account(SIGNER_B), account(SIGNER_C)], + 2, + 0, + ), + ), + }, + Fixture { + slug: "06-multisig-propose-transfer", + inner_call: Some("balances.transfer_allow_death"), + pallet_call: "multisig.propose", + description: "Propose a 42 QUAN transfer from the multisig.", + call: call_data( + metadata, + &api::tx().multisig().propose( + account(MULTISIG), + api::runtime_types::bounded_collections::bounded_vec::BoundedVec( + inner_transfer.clone(), + ), + 5_000_000, + ), + ), + }, + Fixture { + slug: "07-multisig-approve-transfer", + inner_call: Some("balances.transfer_allow_death"), + pallet_call: "multisig.approve", + description: "Approve proposal 7, which carries the 42 QUAN transfer being approved.", + call: call_data( + metadata, + &api::tx().multisig().approve( + account(MULTISIG), + 7, + api::runtime_types::bounded_collections::bounded_vec::BoundedVec( + inner_transfer.clone(), + ), + ), + ), + }, + Fixture { + slug: "08-multisig-execute-transfer", + inner_call: Some("balances.transfer_allow_death"), + pallet_call: "multisig.execute", + description: "Execute proposal 7, which carries the 42 QUAN transfer being dispatched.", + call: call_data( + metadata, + &api::tx().multisig().execute( + account(MULTISIG), + 7, + api::runtime_types::quantus_runtime::RuntimeCall::Balances( + api::runtime_types::pallet_balances::pallet::Call::transfer_allow_death { + dest: dest(), + value: 42 * UNIT, + }, + ), + ), + ), + }, + Fixture { + slug: "09-multisig-execute-reversible", + inner_call: Some("reversible_transfers.schedule_transfer"), + pallet_call: "multisig.execute", + description: + "Execute a proposal whose inner call is a reversible transfer, not a plain one.", + call: call_data( + metadata, + &api::tx().multisig().execute( + account(MULTISIG), + 8, + api::runtime_types::quantus_runtime::RuntimeCall::ReversibleTransfers( + api::runtime_types::pallet_reversible_transfers::pallet::Call::schedule_transfer { + dest: dest(), + amount: 5 * UNIT, + }, + ), + ), + ), + }, + ] +} + +fn main() { + let out_dir = std::env::args() + .nth(1) + .unwrap_or_else(|| panic!("usage: generate_qr_fixtures ")); + let root = Path::new(&out_dir); + + let metadata_bytes: &[u8] = include_bytes!("../src/quantus_metadata.scale"); + let metadata = ::decode(&mut &metadata_bytes[..]) + .expect("bundled metadata decodes"); + + let reduced = root.join("reduced"); + fs::create_dir_all(&reduced).expect("create fixture dir"); + + let mut manifest = Vec::new(); + let mut links = Vec::new(); + for fixture in build_fixtures(&metadata) { + let payload = signing_payload(&fixture.call, 0, 0); + let request = envelope(&payload); + let parts = quantus_ur::encode_bytes(request.as_bytes()).expect("UR encodes"); + + let dir = reduced.join(fixture.slug); + let frames_dir = dir.join("frames"); + fs::create_dir_all(&frames_dir).expect("create case dir"); + + for (i, part) in parts.iter().enumerate() { + fs::write(frames_dir.join(format!("frame-{i:03}.svg")), frame_svg(part)) + .expect("write frame"); + } + fs::write(dir.join("ur.txt"), format!("{}\n", parts.join("\n"))).expect("write ur"); + fs::write(dir.join("payload.hex"), format!("0x{}\n", hex::encode(&payload))) + .expect("write payload"); + fs::write(dir.join("request.json"), format!("{request}\n")).expect("write request"); + fs::write( + dir.join("index.html"), + viewer_html(fixture.slug, fixture.description, parts.len()), + ) + .expect("write viewer"); + + println!( + "{:<34} call {:>5}B payload {:>5}B {:>3} frames", + fixture.slug, + fixture.call.len(), + payload.len(), + parts.len() + ); + + links.push(format!( + r#"
  • {} {} · {} frames
  • "#, + fixture.slug, + fixture.slug, + fixture.pallet_call, + parts.len() + )); + + manifest.push(format!( + r#" {{ + "slug": "{}", + "call": "{}", + "description": "{}", + "innerCall": {}, + "signer": "{}", + "callBytes": {}, + "payloadBytes": {}, + "frames": {} + }}"#, + fixture.slug, + fixture.pallet_call, + fixture.description, + fixture + .inner_call + .map(|c| format!("\"{c}\"")) + .unwrap_or_else(|| "null".to_string()), + SIGNER_SS58, + fixture.call.len(), + payload.len(), + parts.len() + )); + } + + let manifest = format!( + "{{\n \"specVersion\": {SPEC_VERSION},\n \"transactionVersion\": {TRANSACTION_VERSION},\n \"network\": \"Planck\",\n \"cases\": [\n{}\n ]\n}}\n", + manifest.join(",\n") + ); + fs::write(reduced.join("manifest.json"), manifest).expect("write manifest"); + fs::write(reduced.join("index.html"), index_html(&links)).expect("write index"); + println!("\nwrote fixtures to {}", reduced.display()); +} diff --git a/src/cli/wallet.rs b/src/cli/wallet.rs index 6ffd379..4ea825d 100644 --- a/src/cli/wallet.rs +++ b/src/cli/wallet.rs @@ -1236,8 +1236,9 @@ mod tests { ]) .expect("ml-dsa-87 must parse"); match parsed.command { - crate::cli::Commands::Wallet(WalletCommands::Create { scheme, .. }) => - assert_eq!(scheme, DilithiumScheme::MlDsa87), + crate::cli::Commands::Wallet(WalletCommands::Create { scheme, .. }) => { + assert_eq!(scheme, DilithiumScheme::MlDsa87) + }, other => panic!("expected Wallet(Create), got {other:?}"), } diff --git a/src/cli/wormhole.rs b/src/cli/wormhole.rs index de4cae6..e0f7e61 100644 --- a/src/cli/wormhole.rs +++ b/src/cli/wormhole.rs @@ -5362,8 +5362,9 @@ mod tests { ); match load_multiround_wallet("crystal_alice", None, None) { - Ok(_) => - panic!("wallet without mnemonic must error instead of generating an ephemeral one"), + Ok(_) => { + panic!("wallet without mnemonic must error instead of generating an ephemeral one") + }, Err(err) => { let msg = err.to_string(); assert!( diff --git a/src/qr/scanner.rs b/src/qr/scanner.rs index df91314..3c0fb36 100644 --- a/src/qr/scanner.rs +++ b/src/qr/scanner.rs @@ -562,8 +562,9 @@ mod camera { } st.parts.push(part); let line = match (seq, st.total) { - (Some((s, _)), Some(t)) => - format!("📥 Part {s}/{t} — {}/{t} collected", st.seqs.len()), + (Some((s, _)), Some(t)) => { + format!("📥 Part {s}/{t} — {}/{t} collected", st.seqs.len()) + }, _ => format!("📥 UR part captured ({} total)", st.parts.len()), }; progress.println(line); From 1ee52ef9bd48890ec4389e88c6cd2dcca8b164e1 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 1 Sep 2026 16:21:37 +0800 Subject: [PATCH 5/7] fix(exercise): assert the batch_all rollback step actually failed on chain The rollback step discarded the submit error. An RPC error or a pool rejection also leaves the recipient at zero, so the step reported a successful rollback even when the batch never ran. It now uses submit_expect_failure and requires the insufficient-funds dispatch error, which only comes from the ExtrinsicFailed event and so proves the extrinsic was included. The expected error fragments move to a shared constant, reused by the negative over-balance step. --- src/cli/exercise/runner.rs | 3 +++ src/cli/exercise/scenarios/negative.rs | 4 ++-- src/cli/exercise/scenarios/utility.rs | 15 ++++++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/cli/exercise/runner.rs b/src/cli/exercise/runner.rs index dc12686..df0409b 100644 --- a/src/cli/exercise/runner.rs +++ b/src/cli/exercise/runner.rs @@ -215,6 +215,9 @@ where .await } +/// Error fragments a balances transfer beyond the sender's spendable balance fails with. +pub const INSUFFICIENT_FUNDS_ERRORS: &[&str] = &["FundsUnavailable", "InsufficientBalance"]; + pub async fn submit_expect_failure( ctx: &ExerciseCtx, from: &QuantumKeyPair, diff --git a/src/cli/exercise/scenarios/negative.rs b/src/cli/exercise/scenarios/negative.rs index 0f29569..975d1f4 100644 --- a/src/cli/exercise/scenarios/negative.rs +++ b/src/cli/exercise/scenarios/negative.rs @@ -4,7 +4,7 @@ use crate::{ chain::quantus_subxt, cli::exercise::{ report::Report, - runner::{account_id_of, submit_expect_failure, ExerciseCtx}, + runner::{account_id_of, submit_expect_failure, ExerciseCtx, INSUFFICIENT_FUNDS_ERRORS}, }, error::{QuantusError, Result}, exercise_step, @@ -43,7 +43,7 @@ async fn transfer_over_balance(ctx: &mut ExerciseCtx) -> Result { let recipient = ctx.fresh_keypair()?; let balance = ctx.free_balance(&sender.try_to_account_id_ss58check()?).await?; let call = transfer_call(account_id_of(&recipient)?, balance.saturating_mul(2)); - submit_expect_failure(ctx, &sender, call, &["FundsUnavailable", "InsufficientBalance"]).await + submit_expect_failure(ctx, &sender, call, INSUFFICIENT_FUNDS_ERRORS).await } async fn transfer_below_ed(ctx: &mut ExerciseCtx) -> Result { diff --git a/src/cli/exercise/scenarios/utility.rs b/src/cli/exercise/scenarios/utility.rs index cd35e9a..fd759e8 100644 --- a/src/cli/exercise/scenarios/utility.rs +++ b/src/cli/exercise/scenarios/utility.rs @@ -8,7 +8,9 @@ use crate::{ chain::quantus_subxt, cli::exercise::{ report::Report, - runner::{account_id_of, submit_ok, ExerciseCtx}, + runner::{ + account_id_of, submit_expect_failure, submit_ok, ExerciseCtx, INSUFFICIENT_FUNDS_ERRORS, + }, }, error::{QuantusError, Result}, exercise_step, @@ -74,9 +76,10 @@ async fn batch_all_rolls_back(ctx: &mut ExerciseCtx) -> Result { transfer_call(account_id_of(&doomed)?, ABSURD_AMOUNT), ]; let call = quantus_subxt::api::tx().utility().batch_all(calls); - // The extrinsic is included; the batch itself dispatches an error, so the - // state change from the first item must not survive. - let _ = submit_ok(ctx, &sender, call).await; + // The extrinsic must be included and fail on the second item. Anything else + // (an RPC error, a pool rejection) would leave the balance at zero too, so + // the dispatch error is checked before the balance is read as evidence. + let rejection = submit_expect_failure(ctx, &sender, call, INSUFFICIENT_FUNDS_ERRORS).await?; let good_balance = ctx.free_balance(&good_ss58).await?; if good_balance != 0 { @@ -84,5 +87,7 @@ async fn batch_all_rolls_back(ctx: &mut ExerciseCtx) -> Result { "batch_all did not roll back: recipient has {good_balance}, expected 0" ))); } - Ok("Utility::batch_all rolled back the successful item when a later item failed".to_string()) + Ok(format!( + "Utility::batch_all rolled back the successful item when a later item failed ({rejection})" + )) } From 4e6fbb84cf7dc1588410d7d13687cae76134e433 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Tue, 1 Sep 2026 17:42:07 +0800 Subject: [PATCH 6/7] feat(chain): sign extrinsics under the QUANTUS_EXTRINSIC context The chain binds on-chain signatures to a FIPS 204 ML-DSA context (chain commit 85296439). ML-DSA sign and verify always took a ctx argument, and the published qp-dilithium-crypto still passes None, so sp_core::Pair::sign produces a signature the node rejects with "Transaction has a bad signature". Reproduced against a live v0.11.1 dev node before this change. New src/chain/signing.rs signs and verifies under that context, going straight to qp-rusty-crystals-dilithium, which does expose ctx. Every extrinsic signature the CLI makes or checks goes through it: the three subxt Signer impls, the cold-sign-sim device simulator, and the QR response check. litep2p node identity is not involved and is unchanged. Also regenerates the bindings for the released spec-148 runtime. Spec 148 adds Origins to the recursive OriginCaller and RuntimeCall shape, so the spec-147 bindings failed static subxt validation on v0.11.1, including the multisig.execute payload that now carries a RuntimeCall. (148, 6) joins COMPATIBLE_RUNTIMES and the QR fixture generator moves to spec 148. The batch_all rollback exercise asserted an insufficient-funds error but used an amount near u128::MAX, which underflows the balance arithmetic first. It now sends twice the sender's balance, so the failure is the one the step asserts. 49 of 50 exercise steps passed against a live v0.11.1 node before the rollback amount fix; the utility phase is 5 of 5 after it. --- examples/generate_qr_fixtures.rs | 2 +- src/chain/client.rs | 43 +++------ src/chain/mod.rs | 1 + src/chain/quantus_subxt.rs | 131 +++++++++++++++----------- src/chain/signing.rs | 99 +++++++++++++++++++ src/cli/cold_signing.rs | 16 +--- src/cli/exercise/scenarios/utility.rs | 12 ++- src/config/mod.rs | 4 + src/quantus_metadata.scale | Bin 112719 -> 113082 bytes 9 files changed, 209 insertions(+), 99 deletions(-) create mode 100644 src/chain/signing.rs diff --git a/examples/generate_qr_fixtures.rs b/examples/generate_qr_fixtures.rs index b9647e4..960535c 100644 --- a/examples/generate_qr_fixtures.rs +++ b/examples/generate_qr_fixtures.rs @@ -17,7 +17,7 @@ const PLANCK_GENESIS: [u8; 32] = [ 0x49, 0x01, 0xbf, 0x5c, 0x57, 0xfd, 0x3f, 0x9e, 0x72, 0x6a, 0xf3, 0x99, 0xc7, 0x63, 0xde, 0x66, 0x70, 0xdb, 0xdb, 0x11, 0x5a, 0x91, 0xc0, 0x23, 0x7e, 0x17, 0x3f, 0x16, 0xee, 0xf6, 0x5e, 0x72, ]; -const SPEC_VERSION: u32 = 147; +const SPEC_VERSION: u32 = 148; const TRANSACTION_VERSION: u32 = 6; /// The signer the request is addressed to. Any valid Quantus address works; the wallet only diff --git a/src/chain/client.rs b/src/chain/client.rs index 168353d..032bf04 100644 --- a/src/chain/client.rs +++ b/src/chain/client.rs @@ -351,24 +351,13 @@ impl subxt::tx::Signer for QuantusSigner { } fn sign(&self, signer_payload: &[u8]) -> ::Signature { - use sp_core::Pair; match self { - Self::MlDsa65(pair) => { - let signature_with_public = - ::sign( - pair, - signer_payload, - ); - DilithiumSignatureScheme::Dilithium65(signature_with_public) - }, - Self::MlDsa87(pair) => { - let signature_with_public = - ::sign( - pair, - signer_payload, - ); - DilithiumSignatureScheme::Dilithium87(signature_with_public) - }, + Self::MlDsa65(pair) => DilithiumSignatureScheme::Dilithium65( + crate::chain::signing::sign_ml_dsa_65(pair, signer_payload), + ), + Self::MlDsa87(pair) => DilithiumSignatureScheme::Dilithium87( + crate::chain::signing::sign_ml_dsa_87(pair, signer_payload), + ), } } } @@ -382,12 +371,10 @@ impl subxt::tx::Signer for qp_dilithium_crypto::types::Dilithium87P } fn sign(&self, signer_payload: &[u8]) -> ::Signature { - let signature_with_public = - ::sign( - self, - signer_payload, - ); - DilithiumSignatureScheme::Dilithium87(signature_with_public) + DilithiumSignatureScheme::Dilithium87(crate::chain::signing::sign_ml_dsa_87( + self, + signer_payload, + )) } } @@ -400,12 +387,10 @@ impl subxt::tx::Signer for qp_dilithium_crypto::types::Dilithium65P } fn sign(&self, signer_payload: &[u8]) -> ::Signature { - let signature_with_public = - ::sign( - self, - signer_payload, - ); - DilithiumSignatureScheme::Dilithium65(signature_with_public) + DilithiumSignatureScheme::Dilithium65(crate::chain::signing::sign_ml_dsa_65( + self, + signer_payload, + )) } } diff --git a/src/chain/mod.rs b/src/chain/mod.rs index ede57a3..babfbcb 100644 --- a/src/chain/mod.rs +++ b/src/chain/mod.rs @@ -7,3 +7,4 @@ /// - Managing RPC connections pub mod client; pub mod quantus_subxt; +pub mod signing; diff --git a/src/chain/quantus_subxt.rs b/src/chain/quantus_subxt.rs index 746e40c..3cde670 100644 --- a/src/chain/quantus_subxt.rs +++ b/src/chain/quantus_subxt.rs @@ -6,7 +6,7 @@ pub mod api { mod root_mod { pub use super::*; } - pub static PALLETS: [&str; 17usize] = [ + pub static PALLETS: [&str; 18usize] = [ "System", "Timestamp", "Balances", @@ -24,6 +24,7 @@ pub mod api { "Wormhole", "ZkTree", "Vesting", + "Origins", ]; pub static RUNTIME_APIS: [&str; 12usize] = [ "Core", @@ -1563,10 +1564,10 @@ pub mod api { "query_call_info", types::QueryCallInfo { call, len }, [ - 33u8, 109u8, 175u8, 85u8, 20u8, 153u8, 151u8, 189u8, 126u8, 196u8, - 149u8, 212u8, 162u8, 199u8, 191u8, 186u8, 212u8, 236u8, 156u8, 228u8, - 186u8, 107u8, 35u8, 45u8, 42u8, 211u8, 162u8, 216u8, 60u8, 118u8, 1u8, - 57u8, + 12u8, 157u8, 57u8, 49u8, 239u8, 52u8, 103u8, 58u8, 85u8, 132u8, 31u8, + 91u8, 207u8, 48u8, 250u8, 51u8, 254u8, 177u8, 134u8, 227u8, 206u8, + 215u8, 171u8, 181u8, 61u8, 206u8, 39u8, 27u8, 229u8, 251u8, 140u8, + 40u8, ], ) } @@ -1584,10 +1585,9 @@ pub mod api { "query_call_fee_details", types::QueryCallFeeDetails { call, len }, [ - 24u8, 88u8, 218u8, 4u8, 208u8, 93u8, 194u8, 26u8, 151u8, 224u8, 30u8, - 60u8, 203u8, 199u8, 216u8, 240u8, 23u8, 63u8, 103u8, 167u8, 119u8, - 116u8, 247u8, 178u8, 176u8, 26u8, 13u8, 144u8, 159u8, 70u8, 93u8, - 203u8, + 143u8, 71u8, 61u8, 109u8, 233u8, 212u8, 170u8, 7u8, 109u8, 202u8, 95u8, + 64u8, 92u8, 188u8, 81u8, 236u8, 213u8, 134u8, 88u8, 241u8, 167u8, 12u8, + 197u8, 20u8, 0u8, 248u8, 250u8, 20u8, 30u8, 35u8, 251u8, 235u8, ], ) } @@ -2050,9 +2050,9 @@ pub mod api { .hash(); runtime_metadata_hash == [ - 242u8, 240u8, 161u8, 192u8, 242u8, 107u8, 204u8, 96u8, 136u8, 211u8, 182u8, 7u8, - 219u8, 19u8, 152u8, 31u8, 252u8, 248u8, 142u8, 12u8, 102u8, 87u8, 171u8, 13u8, - 85u8, 174u8, 223u8, 78u8, 90u8, 165u8, 158u8, 228u8, + 104u8, 196u8, 70u8, 218u8, 94u8, 164u8, 163u8, 152u8, 189u8, 155u8, 196u8, 185u8, + 189u8, 151u8, 104u8, 118u8, 115u8, 242u8, 115u8, 237u8, 14u8, 237u8, 29u8, 140u8, + 142u8, 27u8, 239u8, 20u8, 232u8, 27u8, 158u8, 180u8, ] } pub mod system { @@ -2284,7 +2284,7 @@ pub mod api { #[doc = "Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied"] #[doc = "later."] #[doc = ""] - #[doc = "This call requires Root origin."] + #[doc = "This call requires `Config::AuthorizeUpgradeOrigin` (Root by default)."] pub struct AuthorizeUpgrade { pub code_hash: authorize_upgrade::CodeHash, } @@ -2509,7 +2509,7 @@ pub mod api { #[doc = "Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied"] #[doc = "later."] #[doc = ""] - #[doc = "This call requires Root origin."] + #[doc = "This call requires `Config::AuthorizeUpgradeOrigin` (Root by default)."] pub fn authorize_upgrade( &self, code_hash: types::authorize_upgrade::CodeHash, @@ -5462,7 +5462,7 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "No miner in the digest; the credit stays in [`CollectedFees`] for the next block."] + #[doc = "No miner in the digest; the credit stays in `CollectedFees` for the next block."] pub struct PayoutDeferred { pub amount: payout_deferred::Amount, } @@ -5481,7 +5481,7 @@ pub mod api { )] #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] - #[doc = "Miner mint failed; the credit stays in [`CollectedFees`] for retry."] + #[doc = "Miner mint failed; the credit stays in `CollectedFees` for retry."] pub struct MinerMintFailed { pub miner: miner_mint_failed::Miner, pub reward: miner_mint_failed::Reward, @@ -6467,10 +6467,10 @@ pub mod api { "Agenda", (), [ - 30u8, 205u8, 116u8, 231u8, 62u8, 200u8, 225u8, 69u8, 50u8, 106u8, - 175u8, 47u8, 182u8, 175u8, 231u8, 114u8, 176u8, 58u8, 24u8, 230u8, - 81u8, 228u8, 217u8, 72u8, 171u8, 222u8, 251u8, 218u8, 73u8, 28u8, - 239u8, 137u8, + 236u8, 151u8, 101u8, 220u8, 138u8, 113u8, 158u8, 157u8, 32u8, 123u8, + 20u8, 193u8, 254u8, 54u8, 115u8, 166u8, 242u8, 66u8, 163u8, 35u8, + 233u8, 20u8, 39u8, 45u8, 203u8, 77u8, 235u8, 206u8, 90u8, 242u8, 246u8, + 248u8, ], ) } @@ -6492,10 +6492,10 @@ pub mod api { "Agenda", ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 30u8, 205u8, 116u8, 231u8, 62u8, 200u8, 225u8, 69u8, 50u8, 106u8, - 175u8, 47u8, 182u8, 175u8, 231u8, 114u8, 176u8, 58u8, 24u8, 230u8, - 81u8, 228u8, 217u8, 72u8, 171u8, 222u8, 251u8, 218u8, 73u8, 28u8, - 239u8, 137u8, + 236u8, 151u8, 101u8, 220u8, 138u8, 113u8, 158u8, 157u8, 32u8, 123u8, + 20u8, 193u8, 254u8, 54u8, 115u8, 166u8, 242u8, 66u8, 163u8, 35u8, + 233u8, 20u8, 39u8, 45u8, 203u8, 77u8, 235u8, 206u8, 90u8, 242u8, 246u8, + 248u8, ], ) } @@ -6736,10 +6736,9 @@ pub mod api { "batch_all", types::BatchAll { calls }, [ - 120u8, 103u8, 239u8, 120u8, 123u8, 60u8, 116u8, 102u8, 54u8, 213u8, - 153u8, 164u8, 181u8, 162u8, 53u8, 227u8, 52u8, 6u8, 232u8, 210u8, 11u8, - 135u8, 155u8, 249u8, 131u8, 170u8, 84u8, 116u8, 115u8, 71u8, 185u8, - 231u8, + 247u8, 236u8, 10u8, 207u8, 195u8, 134u8, 5u8, 127u8, 88u8, 61u8, 50u8, + 171u8, 93u8, 203u8, 242u8, 77u8, 28u8, 56u8, 112u8, 139u8, 74u8, 202u8, + 140u8, 11u8, 59u8, 5u8, 219u8, 50u8, 163u8, 140u8, 156u8, 98u8, ], ) } @@ -6929,7 +6928,7 @@ pub mod api { #[doc = "This extrinsic is called automatically by the Scheduler pallet when the"] #[doc = "delay period expires. It must be signed by this pallet's account (not a user)."] #[doc = "The pallet account is set as the origin when scheduling via"] - #[doc = "[`do_schedule_transfer_inner`](Self::do_schedule_transfer_inner)."] + #[doc = "`do_schedule_transfer_inner`."] #[doc = ""] #[doc = "# Parameters"] #[doc = ""] @@ -7177,7 +7176,7 @@ pub mod api { #[doc = "This extrinsic is called automatically by the Scheduler pallet when the"] #[doc = "delay period expires. It must be signed by this pallet's account (not a user)."] #[doc = "The pallet account is set as the origin when scheduling via"] - #[doc = "[`do_schedule_transfer_inner`](Self::do_schedule_transfer_inner)."] + #[doc = "`do_schedule_transfer_inner`."] #[doc = ""] #[doc = "# Parameters"] #[doc = ""] @@ -9163,9 +9162,10 @@ pub mod api { enactment_moment, }, [ - 0u8, 18u8, 14u8, 253u8, 33u8, 212u8, 33u8, 173u8, 241u8, 29u8, 88u8, - 160u8, 111u8, 21u8, 6u8, 234u8, 249u8, 230u8, 222u8, 119u8, 161u8, - 114u8, 43u8, 126u8, 164u8, 140u8, 199u8, 39u8, 2u8, 64u8, 132u8, 34u8, + 77u8, 138u8, 116u8, 64u8, 111u8, 244u8, 178u8, 158u8, 153u8, 237u8, + 196u8, 161u8, 37u8, 232u8, 110u8, 248u8, 57u8, 0u8, 51u8, 95u8, 106u8, + 137u8, 251u8, 132u8, 74u8, 235u8, 128u8, 96u8, 123u8, 206u8, 144u8, + 253u8, ], ) } @@ -9892,9 +9892,10 @@ pub mod api { "ReferendumInfoFor", (), [ - 242u8, 125u8, 226u8, 99u8, 67u8, 226u8, 43u8, 159u8, 222u8, 238u8, - 72u8, 38u8, 45u8, 26u8, 95u8, 64u8, 141u8, 140u8, 37u8, 44u8, 101u8, - 67u8, 46u8, 66u8, 45u8, 93u8, 41u8, 156u8, 63u8, 59u8, 9u8, 29u8, + 168u8, 40u8, 151u8, 146u8, 101u8, 43u8, 126u8, 25u8, 73u8, 166u8, + 190u8, 90u8, 228u8, 58u8, 28u8, 12u8, 61u8, 36u8, 23u8, 149u8, 126u8, + 255u8, 146u8, 186u8, 228u8, 231u8, 220u8, 236u8, 60u8, 100u8, 82u8, + 155u8, ], ) } @@ -9916,9 +9917,10 @@ pub mod api { "ReferendumInfoFor", ::subxt::ext::subxt_core::storage::address::StaticStorageKey::new(_0), [ - 242u8, 125u8, 226u8, 99u8, 67u8, 226u8, 43u8, 159u8, 222u8, 238u8, - 72u8, 38u8, 45u8, 26u8, 95u8, 64u8, 141u8, 140u8, 37u8, 44u8, 101u8, - 67u8, 46u8, 66u8, 45u8, 93u8, 41u8, 156u8, 63u8, 59u8, 9u8, 29u8, + 168u8, 40u8, 151u8, 146u8, 101u8, 43u8, 126u8, 25u8, 73u8, 166u8, + 190u8, 90u8, 228u8, 58u8, 28u8, 12u8, 61u8, 36u8, 23u8, 149u8, 126u8, + 255u8, 146u8, 186u8, 228u8, 231u8, 220u8, 236u8, 60u8, 100u8, 82u8, + 155u8, ], ) } @@ -10916,9 +10918,9 @@ pub mod api { call: ::subxt::ext::subxt_core::alloc::boxed::Box::new(call), }, [ - 167u8, 47u8, 21u8, 112u8, 52u8, 132u8, 255u8, 119u8, 118u8, 198u8, - 164u8, 58u8, 36u8, 95u8, 126u8, 165u8, 255u8, 146u8, 87u8, 66u8, 2u8, - 29u8, 233u8, 114u8, 13u8, 99u8, 107u8, 78u8, 75u8, 197u8, 239u8, 60u8, + 117u8, 4u8, 99u8, 249u8, 60u8, 156u8, 233u8, 92u8, 234u8, 175u8, 145u8, + 14u8, 31u8, 130u8, 227u8, 177u8, 181u8, 127u8, 108u8, 148u8, 159u8, + 5u8, 118u8, 164u8, 87u8, 109u8, 74u8, 253u8, 34u8, 206u8, 25u8, 193u8, ], ) } @@ -12742,6 +12744,9 @@ pub mod api { } } } + pub mod origins { + use super::{root_mod, runtime_types}; + } pub mod runtime_types { use super::runtime_types; pub mod bounded_collections { @@ -13314,7 +13319,7 @@ pub mod api { #[doc = "Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied"] #[doc = "later."] #[doc = ""] - #[doc = "This call requires Root origin."] + #[doc = "This call requires `Config::AuthorizeUpgradeOrigin` (Root by default)."] authorize_upgrade { code_hash: ::subxt::ext::subxt_core::utils::H256 }, #[codec(index = 10)] #[doc = "Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied"] @@ -13965,10 +13970,10 @@ pub mod api { total: ::core::primitive::u128, }, #[codec(index = 2)] - #[doc = "No miner in the digest; the credit stays in [`CollectedFees`] for the next block."] + #[doc = "No miner in the digest; the credit stays in `CollectedFees` for the next block."] PayoutDeferred { amount: ::core::primitive::u128 }, #[codec(index = 3)] - #[doc = "Miner mint failed; the credit stays in [`CollectedFees`] for retry."] + #[doc = "Miner mint failed; the credit stays in `CollectedFees` for retry."] MinerMintFailed { miner: ::subxt::ext::subxt_core::utils::AccountId32, reward: ::core::primitive::u128, @@ -15384,7 +15389,7 @@ pub mod api { #[doc = "This extrinsic is called automatically by the Scheduler pallet when the"] #[doc = "delay period expires. It must be signed by this pallet's account (not a user)."] #[doc = "The pallet account is set as the origin when scheduling via"] - #[doc = "[`do_schedule_transfer_inner`](Self::do_schedule_transfer_inner)."] + #[doc = "`do_schedule_transfer_inner`."] #[doc = ""] #[doc = "# Parameters"] #[doc = ""] @@ -15530,6 +15535,9 @@ pub mod api { #[doc = "Zero-amount transfers cannot be scheduled: there is nothing to hold,"] #[doc = "execute, or reverse."] ZeroAmount, + #[codec(index = 15)] + #[doc = "The high-security account already used its transaction quota for the current window."] + HighSecurityTxQuotaExceeded, } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, @@ -16710,6 +16718,29 @@ pub mod api { pub amount: ::core::primitive::u128, } } + pub mod origins { + use super::runtime_types; + pub mod pallet_custom_origins { + use super::runtime_types; + #[derive( + :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, + :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, + Debug, + codec :: Decode, + codec :: Encode, + )] + #[decode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode" + )] + #[encode_as_type( + crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode" + )] + pub enum Origin { + #[codec(index = 0)] + FastUpgrade, + } + } + } } pub mod transaction_extensions { use super::runtime_types; @@ -16748,13 +16779,7 @@ pub mod api { #[decode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_decode")] #[encode_as_type(crate_path = ":: subxt :: ext :: subxt_core :: ext :: scale_encode")] pub enum OriginCaller { - #[codec(index = 0)] - system( - runtime_types::frame_support::dispatch::RawOrigin< - ::subxt::ext::subxt_core::utils::AccountId32, - >, - ), - } + # [codec (index = 0)] system (runtime_types :: frame_support :: dispatch :: RawOrigin < :: subxt :: ext :: subxt_core :: utils :: AccountId32 > ,) , # [codec (index = 23)] Origins (runtime_types :: quantus_runtime :: governance :: origins :: pallet_custom_origins :: Origin ,) , } #[derive( :: subxt :: ext :: subxt_core :: ext :: scale_decode :: DecodeAsType, :: subxt :: ext :: subxt_core :: ext :: scale_encode :: EncodeAsType, diff --git a/src/chain/signing.rs b/src/chain/signing.rs new file mode 100644 index 0000000..4aaa705 --- /dev/null +++ b/src/chain/signing.rs @@ -0,0 +1,99 @@ +//! FIPS 204 context binding for Quantus extrinsic signatures. +//! +//! The runtime signs and verifies extrinsics under [`EXTRINSIC`]. `sp_core::Pair::sign` in the +//! published `qp-dilithium-crypto` still passes no context, and the chain rejects what it +//! produces as "Transaction has a bad signature". Every extrinsic signature the CLI makes or +//! checks goes through this module instead. + +use qp_dilithium_crypto::types::{ + Dilithium65Pair, Dilithium65Signature, Dilithium65SignatureWithPublic, Dilithium87Pair, + Dilithium87Signature, Dilithium87SignatureWithPublic, +}; +use sp_core::{ByteArray, Pair}; + +/// The FIPS 204 context the runtime binds extrinsic signatures to. Mirrors +/// `qp_dilithium_crypto::signing_context::EXTRINSIC` in the chain. +pub const EXTRINSIC: &[u8] = b"QUANTUS_EXTRINSIC"; + +macro_rules! context_sign { + ($sign:ident, $pair:ty, $signature:ty, $sig_with_public:ty, $module:ident) => { + /// Sign `message` under [`EXTRINSIC`], the way the runtime expects. + pub fn $sign(pair: &$pair, message: &[u8]) -> $sig_with_public { + let secret = + qp_rusty_crystals_dilithium::$module::SecretKey::from_bytes(pair.secret_bytes()) + .expect("wallet secret key must parse"); + let signature = secret + .sign(message, Some(EXTRINSIC), None) + .expect("EXTRINSIC context is well-formed"); + let signature = <$signature as TryFrom<&[u8]>>::try_from(signature.as_ref()) + .expect("signature length is fixed"); + <$sig_with_public>::new(signature, pair.public()) + } + }; +} + +context_sign!( + sign_ml_dsa_87, + Dilithium87Pair, + Dilithium87Signature, + Dilithium87SignatureWithPublic, + ml_dsa_87 +); +context_sign!( + sign_ml_dsa_65, + Dilithium65Pair, + Dilithium65Signature, + Dilithium65SignatureWithPublic, + ml_dsa_65 +); + +/// Whether `sig_with_public` signs `message` under [`EXTRINSIC`]. Cold wallets sign ML-DSA-87 +/// only, so that is the only response the CLI checks. +pub fn verify_ml_dsa_87(sig_with_public: &Dilithium87SignatureWithPublic, message: &[u8]) -> bool { + let Ok(public) = qp_rusty_crystals_dilithium::ml_dsa_87::PublicKey::from_bytes( + sig_with_public.public().as_slice(), + ) else { + return false; + }; + public.verify(message, sig_with_public.signature().as_slice(), Some(EXTRINSIC)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ml_dsa_87_signature_verifies_under_the_extrinsic_context() { + let alice = qp_dilithium_crypto::crystal_alice(); + let signature = sign_ml_dsa_87(&alice, b"payload"); + assert!(verify_ml_dsa_87(&signature, b"payload")); + assert!(!verify_ml_dsa_87(&signature, b"a different payload")); + } + + #[test] + fn ml_dsa_65_signature_verifies_under_the_extrinsic_context() { + let pair = Dilithium65Pair::from_seed(&[7u8; 32]).expect("seed is well-formed"); + let signature = sign_ml_dsa_65(&pair, b"payload"); + let public = qp_rusty_crystals_dilithium::ml_dsa_65::PublicKey::from_bytes( + signature.public().as_slice(), + ) + .expect("public key must parse"); + let sig = signature.signature(); + assert!(public.verify(b"payload", sig.as_slice(), Some(EXTRINSIC))); + assert!(!public.verify(b"payload", sig.as_slice(), None)); + } + + /// The context is what the chain checks. A signature made the old way, with no context, is + /// what a node rejects as "Transaction has a bad signature". + #[test] + fn an_empty_context_signature_is_not_a_valid_extrinsic_signature() { + let alice = qp_dilithium_crypto::crystal_alice(); + let empty_context = ::sign(&alice, b"payload"); + assert!(!verify_ml_dsa_87(&empty_context, b"payload")); + assert_ne!( + empty_context.to_bytes(), + sign_ml_dsa_87(&alice, b"payload").to_bytes(), + "signing must not fall back to the empty context" + ); + } +} diff --git a/src/cli/cold_signing.rs b/src/cli/cold_signing.rs index b3ed672..c5763cc 100644 --- a/src/cli/cold_signing.rs +++ b/src/cli/cold_signing.rs @@ -255,10 +255,8 @@ fn validate_signature_response( return Err(ResponseError::WrongSigner { got: derived_account.to_quantus_ss58() }); } - use sp_runtime::traits::Verify; let msg = signable_payload(raw_payload); - let scheme = DilithiumSignatureScheme::Dilithium87(sig_with_public.clone()); - if !scheme.verify(&msg[..], expected_account) { + if !crate::chain::signing::verify_ml_dsa_87(&sig_with_public, &msg) { return Err(ResponseError::BadSignature); } @@ -515,8 +513,7 @@ pub async fn handle_cold_sign_sim( } let pair = keypair.to_resonance_pair()?; let msg = signable_payload(&payload); - let sig_with_public = - ::sign(&pair, &msg); + let sig_with_public = crate::chain::signing::sign_ml_dsa_87(&pair, &msg); // 3. Emit the response UR. let parts = quantus_ur::encode_bytes(&sig_with_public.to_bytes()) @@ -699,7 +696,7 @@ mod tests { // Simulate the cold wallet: sign the signable form with alice's key let alice = qp_dilithium_crypto::crystal_alice(); let msg = signable_payload(&raw); - let swp = ::sign(&alice, &msg); + let swp = crate::chain::signing::sign_ml_dsa_87(&alice, &msg); let response = swp.to_bytes(); assert_eq!(response.len(), SIGNATURE_RESPONSE_LEN); @@ -717,7 +714,7 @@ mod tests { // Signed by a different key → WrongSigner (abort) let bob = qp_dilithium_crypto::dilithium_bob(); - let bob_swp = ::sign(&bob, &msg); + let bob_swp = crate::chain::signing::sign_ml_dsa_87(&bob, &msg); let err = validate_signature_response(&raw, &bob_swp.to_bytes(), &alice_account()) .err() .unwrap(); @@ -760,10 +757,7 @@ mod tests { // Cold wallet signs and answers over UR let alice = qp_dilithium_crypto::crystal_alice(); - let swp = ::sign( - &alice, - &signable_payload(&received), - ); + let swp = crate::chain::signing::sign_ml_dsa_87(&alice, &signable_payload(&received)); let response_parts = quantus_ur::encode_bytes(&swp.to_bytes()).unwrap(); assert!(response_parts.len() > 1, "7219-byte response must be multi-part"); diff --git a/src/cli/exercise/scenarios/utility.rs b/src/cli/exercise/scenarios/utility.rs index fd759e8..c7403aa 100644 --- a/src/cli/exercise/scenarios/utility.rs +++ b/src/cli/exercise/scenarios/utility.rs @@ -33,10 +33,6 @@ fn transfer_call(dest: crate::cli::common::SubxtAccountId32, value: u128) -> Run }) } -/// An impossible transfer amount, guaranteeing the call fails while staying -/// syntactically valid. -const ABSURD_AMOUNT: u128 = u128::MAX / 2; - /// Every item of a successful `batch_all` must apply. async fn batch_all_applies(ctx: &mut ExerciseCtx) -> Result { let sender = ctx.eph[0].clone(); @@ -70,10 +66,16 @@ async fn batch_all_rolls_back(ctx: &mut ExerciseCtx) -> Result { let good = ctx.fresh_keypair()?; let good_ss58 = good.try_to_account_id_ss58check()?; let doomed = ctx.fresh_keypair()?; + // Twice what the sender holds. An amount near `u128::MAX` underflows the balance + // arithmetic instead, which is a different failure than the one asserted below. + let beyond_balance = ctx + .free_balance(&sender.try_to_account_id_ss58check()?) + .await? + .saturating_mul(2); let calls = vec![ transfer_call(account_id_of(&good)?, ctx.test_unit), - transfer_call(account_id_of(&doomed)?, ABSURD_AMOUNT), + transfer_call(account_id_of(&doomed)?, beyond_balance), ]; let call = quantus_subxt::api::tx().utility().batch_all(calls); // The extrinsic must be included and fail on the second item. Anything else diff --git a/src/config/mod.rs b/src/config/mod.rs index da5e19b..68239d3 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -27,6 +27,7 @@ pub const COMPATIBLE_RUNTIMES: &[CompatibleRuntime] = &[ CompatibleRuntime { spec_version: 145, transaction_version: 4, supports_ml_dsa_65: true }, CompatibleRuntime { spec_version: 146, transaction_version: 5, supports_ml_dsa_65: true }, CompatibleRuntime { spec_version: 147, transaction_version: 6, supports_ml_dsa_65: true }, + CompatibleRuntime { spec_version: 148, transaction_version: 6, supports_ml_dsa_65: true }, ]; /// Highest `spec_version` listed in [`COMPATIBLE_RUNTIMES`]. @@ -141,6 +142,8 @@ mod tests { .expect("the current runtime must be accepted"); validate_runtime_identity(EXPECTED_RUNTIME_SPEC_NAME, 147, 6) .expect("the fast-upgrade runtime must be accepted"); + validate_runtime_identity(EXPECTED_RUNTIME_SPEC_NAME, 148, 6) + .expect("the runtime this build bundles metadata for must be accepted"); } /// Pinned to the spec name the real Quantus runtime declares @@ -215,6 +218,7 @@ mod tests { assert!(runtime_supports_ml_dsa_65(142, 3)); assert!(runtime_supports_ml_dsa_65(143, 3)); assert!(runtime_supports_ml_dsa_65(147, 6)); + assert!(runtime_supports_ml_dsa_65(148, 6)); assert!(!runtime_supports_ml_dsa_65(142, 2), "unknown tx version must not match"); assert!( runtime_supports_ml_dsa_65(max_compatible_spec_version() + 1, 3), diff --git a/src/quantus_metadata.scale b/src/quantus_metadata.scale index 4109e13967cdd7541590958ce567c24d15ec33e0..5d9ff087600ba1d6f35c69739730650510123a9b 100644 GIT binary patch delta 7200 zcmai34O~>mwV(gJcL^xyB44`-vM8t^APDG+pb|tS1{DR38pRc^vJrM+KcZ-i@g?S| zFT{@#Cm3lpjj0+mn$@h@*hpJ{jjcA))+RQ!hWBD3X_G)36K(Xh=kBf|+V^|>F89uy zIdjgLGiT1n><3*zr~V!kRI9oy`n01#)jI6vcHIl|9vtWOx+nSUAd}o0XtxK&y|q#Rq9NKb-C5H z#57{I-R?3iZ7@}-%Pj61SF)$0@1db^@ol4GJr_rP9fOVh%+wLs;pv>ZCIqi|)Y6{; z!Fdbh>q zayu&=Zkx+mtBzQ1e_D0eEVfEDHZZg7-_kP#$U#Y+VsW|xYhm=ak-s-5126HeIU}%@ z8_V*jJ-2Kqwu&|d8T{g{0oXw((foI1^Y98ES)Pd9o>}Du687-h?FN2uUJ_pST%5OB z!hXJfafD~_f*}g_d)6<$)bEkk8Iu&YzlT(-XHV@Z8ApUZ9Wfq9{nAHxeM2noT9qQ5 z0B>wa;Q0;xr8D6A)g}duo!~bblDKGy$GhCykk$8H#^kJ6#zNT{8kvk=@Z8l|A-^DK zVL$Dt%3BhV$p?Ygsb{AMv#>8F|Z^VIhA)XpzIh*q=P- z*BsH~6B-yB`6*0gxw$j!q))~^Wh}_duKQ+mykz3D8dLbl#w2v{(#9G1hVN-C!A<^E zV}768(3jY&Xv%Hs#`Ch5O%lM}FDFVm_@*CwIT0cJ^2?bB<9)X*=^qB97F1T+X%{D3 zTo!(N%OKvgWqx=#FrsLc%VC*PV_EKGES&#yO9rBN#@2MR5iAr2o83`ssWAdd8AGbQ zPIXvZR=e#UD6!UJtFpN4js`ytGxD8Vry!1B*_t{y0mz%HR_0B%E?1qdVwYMwfw2Tq zvy=puL@2SmaN8gx^NMYw=)GlIim#o(Ki-zJE}8ITg)AnNrD;<#!7>q?vCLtqRV$ng zPNJ4t^t5Vo%~mVzj;dg#2stDr@<{B+x@wD4?FJ%eX$^)*Rm04oWfU>d2J8|2`@+EA*fA6r_^)=9p`FJ!W#BTOMei$oeN#F* z`4M`5$*(pg5nJ8PLOGxIG`u;ISL~dMV*cZurT`?ub7f~M2(r`Y~3*b6?G%4O;Q)2twcS>PbSMv3n+=|6un- zEb{z$H|f{H-)%K|(ta>phUzKbdngE2{_OrjK4t${U+YER+sFqW*mtj$&ifv8XuX3g z;pX2STq>)GOmDN_VhN=y`<#0MS@biZU)B7)n z=Y_7kMg|w)~`W(u>5FR zfAZkuSSwv>)f82AF5&x*{t!A|^!A8{MxK2;m24)z)yQvM?aM!S`#jmsZqFxZ=G%@N z1_PKhvrao?d1V&oiWy|?6Ub&MNRZcW;cp+y^&@IWKIr)7p3cGJPxN$R-*NSH4!+~* z>8$iFF*nmvl;9dOYk^{z?V}t_M@LU*sF;FA@XQqo)6+^B`7DRRiV2;bz2I%87(VR8 zIqdUvo!AZ>;Lo3$p^(D&^S?}u<9|E#wQ>}w=8xG1dj9znuS5vmpC;iDzw*-;GmiG+ zb)1eOPTysAoXFqhcG}PFIN9kSe)zovoa7hZi_Pk>< nuOWqmCfg6zlM5wx$na4T4Dy#jb&e}ZB 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 E1;g`hc>n+a delta 6979 zcmb7JeOy#k`aj=$F9eD@ybKP=t4e@@G6^~&FQQH$lh$T_PH~t5bYno&u2dOp8K5V zJkN8U_jBgu%YpB72L{%tZnG}6EwDNOo4GyU5qUe>d2PTVK07c$-rGCw3XI2oPfuW% z!kdRAcm{>+A2l@q3zt;d%Uu=KYGs{OEq6Q3HdmGEEVtNfs&mQWlsT%kDm(kXqojKN zI_}bNJi^bsrRVS87LN6v&u@D$7#ls+rEdTVzhzFE#8&btTMc~2oKooc+2{29p0a5C zp4XM7;BmgAEQiJ)l#QbCPi0f3^?sE3bMMAReqiosY!*E+FnBJ`O_i`+98G|MkDH%_ zo&3jlvpj#8UnF6-=fpi(3cUi$PY%6lCu5Src5B42SL{fpwYjz@W!n3h+J>8OfZx+l zgcteF2BY*Uc=PfE1&qDOmoHD^G0Wp|i03RHKll)1^7t6WLfES`Q;4Jdb%Gux=$Z%( z`X*0Y7sVqV%)nc|(UJ#m;nN?C=6fDY=8w_)lLtrQJ>Sg8hi(pjA0b6fGh^?2N*_9) z!-u|!5o_Wi&LE*IJNquXtwLq&3}b;N_OWlWYE1&p^WUwxi$A(%4F73O61w?6zKP)l zYmNAdzq~e{Z&(|5(|6F7*eg};SUZxRTAP3$_`lbV26)1{JOuFabw&j9rgclggMqYy ziVAz3&0T1AlOVz1$9oJsX8ru3Lx7Z`dNTZUtNDJ{hV>(O%X$MsdH&WYo^e5M(u0M- zV6!`G%vL>Fw2UFm?ogd(x5aL|4jNr!wpE(lc4vbhhv|7t({w2cy!4?6Uf(nvv3z|~ z#GqKxwUh{!=%09_X(W>PlnseIaKljlXpq8mb5yf6h-nk^B9dr@tT0XKsoLUnuyp?H zhWKnF$$}gbF2Yf5cBvPEh*{czAwqpXwYiNXY!QROZFg8IT#I0sr&i>Yl{5V!oJXD|NtLe&(BK-p-@Zz)x@^R�N1gzncHX6~ymu}2J3*WxcDD8qk9uoMa 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 Date: Tue, 1 Sep 2026 18:06:17 +0800 Subject: [PATCH 7/7] fix(chain): pick the signing context from the connected runtime Signing every extrinsic under QUANTUS_EXTRINSIC broke the pre-148 runtimes the CLI still accepts. FIPS 204 contexts are domain separated, so specs 134 to 147, which verify with no context at all, reject a contextful signature exactly as spec 148 rejects a contextless one. COMPATIBLE_RUNTIMES gains binds_signing_context, false up to spec 147 and true from 148. The context is now a property of the connected runtime rather than a constant: - context_for_runtime maps a runtime version to its context, and assumes newer unlisted specs keep it. - QuantusClient::signing_context reads the runtime version subxt already cached at connect, so it costs no RPC. - QuantusSigner carries the context, because it is not a property of the key: the same wallet signs both ways depending on the chain. - Cold response verification uses the connected runtime's context. The cold-sign simulator stays on QUANTUS_EXTRINSIC, which is what Keystone firmware does. Drops the two bare-pair subxt Signer impls. Nothing used them and they had nowhere to carry a context. Tests sign for spec 147 and spec 148 and assert each verifies under its own context and fails across the boundary, and pin the pre-148 path byte-for-byte against sp_core::Pair::sign. 315 lib tests pass. 25 of 25 exercise steps pass against a live v0.11.1 node, including both multisig steps and both ML-DSA schemes. --- src/chain/client.rs | 74 +++++++++++-------------- src/chain/signing.rs | 118 ++++++++++++++++++++++++++++++---------- src/cli/cold_signing.rs | 40 +++++++++----- src/cli/common.rs | 4 +- src/cli/send.rs | 2 +- src/config/mod.rs | 113 ++++++++++++++++++++++++++++++++++---- src/wallet/keystore.rs | 27 +++++---- 7 files changed, 269 insertions(+), 109 deletions(-) diff --git a/src/chain/client.rs b/src/chain/client.rs index 032bf04..a72874a 100644 --- a/src/chain/client.rs +++ b/src/chain/client.rs @@ -165,6 +165,16 @@ impl QuantusClient { } /// Get reference to the underlying SubXT client + /// The FIPS 204 context the connected runtime verifies extrinsic signatures under. Read from + /// the runtime version subxt already cached at connect, so this costs no RPC. + pub fn signing_context(&self) -> Option<&'static [u8]> { + let version = self.client.runtime_version(); + crate::chain::signing::context_for_runtime( + version.spec_version, + version.transaction_version, + ) + } + pub fn client(&self) -> &OnlineClient { &self.client } @@ -330,20 +340,34 @@ impl QuantusClient { /// /// Pairs are boxed: Dilithium secret material is multi‑KB, and an unboxed enum /// trips `clippy::large_enum_variant`. -pub enum QuantusSigner { +pub enum SignerPair { MlDsa65(Box), MlDsa87(Box), } +/// A key plus the FIPS 204 context the connected runtime verifies under. The context is part of +/// the signer because it is not a property of the key: the same wallet signs with no context for +/// a pre-148 runtime and under `QUANTUS_EXTRINSIC` from spec 148 on. +pub struct QuantusSigner { + pub pair: SignerPair, + context: Option<&'static [u8]>, +} + +impl QuantusSigner { + pub fn new(pair: SignerPair, context: Option<&'static [u8]>) -> Self { + Self { pair, context } + } +} + impl subxt::tx::Signer for QuantusSigner { fn account_id(&self) -> ::AccountId { use sp_core::Pair; - match self { - Self::MlDsa65(pair) => + match &self.pair { + SignerPair::MlDsa65(pair) => ::into_account( pair.public(), ), - Self::MlDsa87(pair) => + SignerPair::MlDsa87(pair) => ::into_account( pair.public(), ), @@ -351,49 +375,17 @@ impl subxt::tx::Signer for QuantusSigner { } fn sign(&self, signer_payload: &[u8]) -> ::Signature { - match self { - Self::MlDsa65(pair) => DilithiumSignatureScheme::Dilithium65( - crate::chain::signing::sign_ml_dsa_65(pair, signer_payload), + match &self.pair { + SignerPair::MlDsa65(pair) => DilithiumSignatureScheme::Dilithium65( + crate::chain::signing::sign_ml_dsa_65(pair, signer_payload, self.context), ), - Self::MlDsa87(pair) => DilithiumSignatureScheme::Dilithium87( - crate::chain::signing::sign_ml_dsa_87(pair, signer_payload), + SignerPair::MlDsa87(pair) => DilithiumSignatureScheme::Dilithium87( + crate::chain::signing::sign_ml_dsa_87(pair, signer_payload, self.context), ), } } } -impl subxt::tx::Signer for qp_dilithium_crypto::types::Dilithium87Pair { - fn account_id(&self) -> ::AccountId { - use sp_core::Pair; - ::into_account( - self.public(), - ) - } - - fn sign(&self, signer_payload: &[u8]) -> ::Signature { - DilithiumSignatureScheme::Dilithium87(crate::chain::signing::sign_ml_dsa_87( - self, - signer_payload, - )) - } -} - -impl subxt::tx::Signer for qp_dilithium_crypto::types::Dilithium65Pair { - fn account_id(&self) -> ::AccountId { - use sp_core::Pair; - ::into_account( - self.public(), - ) - } - - fn sign(&self, signer_payload: &[u8]) -> ::Signature { - DilithiumSignatureScheme::Dilithium65(crate::chain::signing::sign_ml_dsa_65( - self, - signer_payload, - )) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/chain/signing.rs b/src/chain/signing.rs index 4aaa705..4385366 100644 --- a/src/chain/signing.rs +++ b/src/chain/signing.rs @@ -1,9 +1,13 @@ //! FIPS 204 context binding for Quantus extrinsic signatures. //! -//! The runtime signs and verifies extrinsics under [`EXTRINSIC`]. `sp_core::Pair::sign` in the -//! published `qp-dilithium-crypto` still passes no context, and the chain rejects what it -//! produces as "Transaction has a bad signature". Every extrinsic signature the CLI makes or +//! Runtimes from spec 148 on sign and verify extrinsics under [`EXTRINSIC`]. `sp_core::Pair::sign` +//! in the published `qp-dilithium-crypto` still passes no context, and those runtimes reject what +//! it produces as "Transaction has a bad signature". Every extrinsic signature the CLI makes or //! checks goes through this module instead. +//! +//! FIPS 204 contexts are domain separated, so the context is not a free upgrade: signing under +//! [`EXTRINSIC`] for a pre-148 runtime is rejected just as surely. [`context_for_runtime`] picks +//! the one the connected runtime actually verifies with. use qp_dilithium_crypto::types::{ Dilithium65Pair, Dilithium65Signature, Dilithium65SignatureWithPublic, Dilithium87Pair, @@ -11,20 +15,26 @@ use qp_dilithium_crypto::types::{ }; use sp_core::{ByteArray, Pair}; -/// The FIPS 204 context the runtime binds extrinsic signatures to. Mirrors +/// The FIPS 204 context runtimes from spec 148 bind extrinsic signatures to. Mirrors /// `qp_dilithium_crypto::signing_context::EXTRINSIC` in the chain. pub const EXTRINSIC: &[u8] = b"QUANTUS_EXTRINSIC"; +/// The context a given runtime verifies extrinsic signatures under. `None` for the pre-148 +/// runtimes, which verify with no context at all. +pub fn context_for_runtime(spec_version: u32, transaction_version: u32) -> Option<&'static [u8]> { + crate::config::runtime_binds_signing_context(spec_version, transaction_version) + .then_some(EXTRINSIC) +} + macro_rules! context_sign { ($sign:ident, $pair:ty, $signature:ty, $sig_with_public:ty, $module:ident) => { - /// Sign `message` under [`EXTRINSIC`], the way the runtime expects. - pub fn $sign(pair: &$pair, message: &[u8]) -> $sig_with_public { + /// Sign `message` under `context`, the way the connected runtime expects. + pub fn $sign(pair: &$pair, message: &[u8], context: Option<&[u8]>) -> $sig_with_public { let secret = qp_rusty_crystals_dilithium::$module::SecretKey::from_bytes(pair.secret_bytes()) .expect("wallet secret key must parse"); - let signature = secret - .sign(message, Some(EXTRINSIC), None) - .expect("EXTRINSIC context is well-formed"); + let signature = + secret.sign(message, context, None).expect("the context is well-formed"); let signature = <$signature as TryFrom<&[u8]>>::try_from(signature.as_ref()) .expect("signature length is fixed"); <$sig_with_public>::new(signature, pair.public()) @@ -47,53 +57,103 @@ context_sign!( ml_dsa_65 ); -/// Whether `sig_with_public` signs `message` under [`EXTRINSIC`]. Cold wallets sign ML-DSA-87 -/// only, so that is the only response the CLI checks. -pub fn verify_ml_dsa_87(sig_with_public: &Dilithium87SignatureWithPublic, message: &[u8]) -> bool { +/// Whether `sig_with_public` signs `message` under `context`. Cold wallets sign ML-DSA-87 only, +/// so that is the only response the CLI checks. +pub fn verify_ml_dsa_87( + sig_with_public: &Dilithium87SignatureWithPublic, + message: &[u8], + context: Option<&[u8]>, +) -> bool { let Ok(public) = qp_rusty_crystals_dilithium::ml_dsa_87::PublicKey::from_bytes( sig_with_public.public().as_slice(), ) else { return false; }; - public.verify(message, sig_with_public.signature().as_slice(), Some(EXTRINSIC)) + public.verify(message, sig_with_public.signature().as_slice(), context) } #[cfg(test)] mod tests { use super::*; + const CTX: Option<&[u8]> = Some(EXTRINSIC); + #[test] - fn ml_dsa_87_signature_verifies_under_the_extrinsic_context() { + fn ml_dsa_87_signature_verifies_under_the_context_it_was_made_with() { let alice = qp_dilithium_crypto::crystal_alice(); - let signature = sign_ml_dsa_87(&alice, b"payload"); - assert!(verify_ml_dsa_87(&signature, b"payload")); - assert!(!verify_ml_dsa_87(&signature, b"a different payload")); + let signature = sign_ml_dsa_87(&alice, b"payload", CTX); + assert!(verify_ml_dsa_87(&signature, b"payload", CTX)); + assert!(!verify_ml_dsa_87(&signature, b"a different payload", CTX)); } #[test] - fn ml_dsa_65_signature_verifies_under_the_extrinsic_context() { + fn ml_dsa_65_signature_verifies_under_the_context_it_was_made_with() { let pair = Dilithium65Pair::from_seed(&[7u8; 32]).expect("seed is well-formed"); - let signature = sign_ml_dsa_65(&pair, b"payload"); + let signature = sign_ml_dsa_65(&pair, b"payload", CTX); let public = qp_rusty_crystals_dilithium::ml_dsa_65::PublicKey::from_bytes( signature.public().as_slice(), ) .expect("public key must parse"); let sig = signature.signature(); - assert!(public.verify(b"payload", sig.as_slice(), Some(EXTRINSIC))); + assert!(public.verify(b"payload", sig.as_slice(), CTX)); assert!(!public.verify(b"payload", sig.as_slice(), None)); } - /// The context is what the chain checks. A signature made the old way, with no context, is - /// what a node rejects as "Transaction has a bad signature". + /// FIPS 204 contexts are domain separated, so this cuts both ways: a spec-148 node rejects a + /// contextless signature, and a pre-148 node rejects a contextful one. Either mismatch is the + /// "Transaction has a bad signature" pool rejection. + #[test] + fn a_signature_does_not_verify_under_the_other_context() { + let alice = qp_dilithium_crypto::crystal_alice(); + let with_context = sign_ml_dsa_87(&alice, b"payload", CTX); + let without_context = sign_ml_dsa_87(&alice, b"payload", None); + + assert!(!verify_ml_dsa_87(&with_context, b"payload", None)); + assert!(!verify_ml_dsa_87(&without_context, b"payload", CTX)); + assert_ne!(with_context.to_bytes(), without_context.to_bytes()); + } + + /// The pre-148 runtimes verify with no context at all, so the CLI must keep signing for them + /// the old way. `sp_core::Pair::sign` in the published `qp-dilithium-crypto` is that old way. #[test] - fn an_empty_context_signature_is_not_a_valid_extrinsic_signature() { + fn pre_148_runtimes_get_the_contextless_signature_pair_sign_makes() { let alice = qp_dilithium_crypto::crystal_alice(); - let empty_context = ::sign(&alice, b"payload"); - assert!(!verify_ml_dsa_87(&empty_context, b"payload")); - assert_ne!( - empty_context.to_bytes(), - sign_ml_dsa_87(&alice, b"payload").to_bytes(), - "signing must not fall back to the empty context" + assert_eq!( + sign_ml_dsa_87(&alice, b"payload", None).to_bytes(), + ::sign(&alice, b"payload").to_bytes() ); } + + #[test] + fn the_context_follows_the_runtime() { + assert_eq!(context_for_runtime(147, 6), None, "spec 147 verifies with no context"); + assert_eq!(context_for_runtime(145, 4), None, "spec 145 verifies with no context"); + assert_eq!(context_for_runtime(134, 2), None, "the oldest listed pair predates it too"); + assert_eq!(context_for_runtime(148, 6), Some(EXTRINSIC), "spec 148 introduced it"); + assert_eq!( + context_for_runtime(149, 7), + Some(EXTRINSIC), + "newer unlisted runtimes are assumed to keep it" + ); + } + + /// A signature made for the runtime the CLI is talking to verifies for that runtime, whichever + /// side of the spec-148 boundary it sits on. + #[test] + fn signing_for_a_runtime_verifies_for_that_runtime() { + let alice = qp_dilithium_crypto::crystal_alice(); + for (spec, tx) in [(147u32, 6u32), (148, 6)] { + let context = context_for_runtime(spec, tx); + let signature = sign_ml_dsa_87(&alice, b"payload", context); + assert!( + verify_ml_dsa_87(&signature, b"payload", context), + "spec {spec} signature must verify under its own context" + ); + let other = context_for_runtime(if spec == 148 { 147 } else { 148 }, tx); + assert!( + !verify_ml_dsa_87(&signature, b"payload", other), + "spec {spec} signature must not verify across the boundary" + ); + } + } } diff --git a/src/cli/cold_signing.rs b/src/cli/cold_signing.rs index c5763cc..280f118 100644 --- a/src/cli/cold_signing.rs +++ b/src/cli/cold_signing.rs @@ -241,6 +241,7 @@ fn validate_signature_response( raw_payload: &[u8], response: &[u8], expected_account: &AccountId32, + context: Option<&[u8]>, ) -> std::result::Result { if response.len() != SIGNATURE_RESPONSE_LEN { return Err(ResponseError::BadLength(response.len())); @@ -256,7 +257,7 @@ fn validate_signature_response( } let msg = signable_payload(raw_payload); - if !crate::chain::signing::verify_ml_dsa_87(&sig_with_public, &msg) { + if !crate::chain::signing::verify_ml_dsa_87(&sig_with_public, &msg, context) { return Err(ResponseError::BadSignature); } @@ -381,7 +382,12 @@ pub async fn sign_and_submit_cold( let response = scan_ur(&source, RESPONSE_TIMEOUT).await?; log_verbose!("📥 Received {} response bytes", response.len()); - match validate_signature_response(&raw_payload, &response, &account) { + match validate_signature_response( + &raw_payload, + &response, + &account, + client.signing_context(), + ) { Ok(swp) => break swp, Err(err) => { let msg = err.message(wallet_name); @@ -513,7 +519,10 @@ pub async fn handle_cold_sign_sim( } let pair = keypair.to_resonance_pair()?; let msg = signable_payload(&payload); - let sig_with_public = crate::chain::signing::sign_ml_dsa_87(&pair, &msg); + // Mirrors the device: Keystone firmware always signs under the extrinsic context, so a + // simulated signature is only good for a runtime that verifies with it. + let sig_with_public = + crate::chain::signing::sign_ml_dsa_87(&pair, &msg, Some(crate::chain::signing::EXTRINSIC)); // 3. Emit the response UR. let parts = quantus_ur::encode_bytes(&sig_with_public.to_bytes()) @@ -538,6 +547,9 @@ pub async fn handle_cold_sign_sim( #[cfg(test)] mod tests { use super::*; + + /// The context a spec-148 runtime verifies under; what the device signs with. + const CTX: Option<&[u8]> = Some(crate::chain::signing::EXTRINSIC); use crate::chain::quantus_subxt::api; use subxt::{client::ClientState, config::substrate::H256, utils::MultiAddress, OfflineClient}; @@ -696,17 +708,18 @@ mod tests { // Simulate the cold wallet: sign the signable form with alice's key let alice = qp_dilithium_crypto::crystal_alice(); let msg = signable_payload(&raw); - let swp = crate::chain::signing::sign_ml_dsa_87(&alice, &msg); + let swp = crate::chain::signing::sign_ml_dsa_87(&alice, &msg, CTX); let response = swp.to_bytes(); assert_eq!(response.len(), SIGNATURE_RESPONSE_LEN); // Valid response verifies - let validated = - validate_signature_response(&raw, &response, &alice_account()).ok().unwrap(); + let validated = validate_signature_response(&raw, &response, &alice_account(), CTX) + .ok() + .unwrap(); assert_eq!(validated.to_bytes(), response); // Truncated response → BadLength (rescan-safe) - let err = validate_signature_response(&raw, &response[..1000], &alice_account()) + let err = validate_signature_response(&raw, &response[..1000], &alice_account(), CTX) .err() .unwrap(); assert!(err.rescan_safe()); @@ -714,8 +727,8 @@ mod tests { // Signed by a different key → WrongSigner (abort) let bob = qp_dilithium_crypto::dilithium_bob(); - let bob_swp = crate::chain::signing::sign_ml_dsa_87(&bob, &msg); - let err = validate_signature_response(&raw, &bob_swp.to_bytes(), &alice_account()) + let bob_swp = crate::chain::signing::sign_ml_dsa_87(&bob, &msg, CTX); + let err = validate_signature_response(&raw, &bob_swp.to_bytes(), &alice_account(), CTX) .err() .unwrap(); assert!(!err.rescan_safe()); @@ -725,7 +738,7 @@ mod tests { let mut other_ctx = test_ctx(); other_ctx.nonce = 8; let other_raw = build_raw_signer_payload(&state, &call, &other_ctx).unwrap(); - let err = validate_signature_response(&other_raw, &response, &alice_account()) + let err = validate_signature_response(&other_raw, &response, &alice_account(), CTX) .err() .unwrap(); assert!(!err.rescan_safe()); @@ -757,14 +770,15 @@ mod tests { // Cold wallet signs and answers over UR let alice = qp_dilithium_crypto::crystal_alice(); - let swp = crate::chain::signing::sign_ml_dsa_87(&alice, &signable_payload(&received)); + let swp = crate::chain::signing::sign_ml_dsa_87(&alice, &signable_payload(&received), CTX); let response_parts = quantus_ur::encode_bytes(&swp.to_bytes()).unwrap(); assert!(response_parts.len() > 1, "7219-byte response must be multi-part"); // CLI decodes, validates, assembles let response = quantus_ur::decode_bytes(&response_parts).unwrap(); - let validated = - validate_signature_response(&raw, &response, &alice_account()).ok().unwrap(); + let validated = validate_signature_response(&raw, &response, &alice_account(), CTX) + .ok() + .unwrap(); let client = OfflineClient::::new( state.genesis_hash, diff --git a/src/cli/common.rs b/src/cli/common.rs index 5bbba6e..7690cea 100644 --- a/src/cli/common.rs +++ b/src/cli/common.rs @@ -529,7 +529,7 @@ where .await, }; ensure_keypair_scheme_supported(quantus_client, from_keypair).await?; - let signer = from_keypair.to_subxt_signer().map_err(|e| { + let signer = from_keypair.to_subxt_signer(quantus_client.signing_context()).map_err(|e| { crate::error::QuantusError::NetworkError(format!("Failed to convert keypair: {e:?}")) })?; @@ -712,7 +712,7 @@ where .map(|(tx_hash, _included_in)| tx_hash), }; ensure_keypair_scheme_supported(quantus_client, from_keypair).await?; - let signer = from_keypair.to_subxt_signer().map_err(|e| { + let signer = from_keypair.to_subxt_signer(quantus_client.signing_context()).map_err(|e| { crate::error::QuantusError::NetworkError(format!("Failed to convert keypair: {e:?}")) })?; diff --git a/src/cli/send.rs b/src/cli/send.rs index 782d529..05c0225 100644 --- a/src/cli/send.rs +++ b/src/cli/send.rs @@ -308,7 +308,7 @@ where )); } let from_keypair = signer.as_hot().expect("cold arm returned above"); - let signer = from_keypair.to_subxt_signer().map_err(|e| { + let signer = from_keypair.to_subxt_signer(quantus_client.signing_context()).map_err(|e| { crate::error::QuantusError::NetworkError(format!("Failed to convert keypair: {e:?}")) })?; diff --git a/src/config/mod.rs b/src/config/mod.rs index 68239d3..b7d2184 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -9,6 +9,10 @@ pub struct CompatibleRuntime { /// Whether the runtime's extrinsic signature enum includes ML-DSA-65 /// (`DilithiumSignatureScheme::Dilithium65`). Specs 134–136 only accept ML-DSA-87. pub supports_ml_dsa_65: bool, + /// Whether the runtime verifies extrinsic signatures under the `QUANTUS_EXTRINSIC` FIPS 204 + /// context. Specs up to 147 verify with no context, and FIPS 204 contexts are domain + /// separated, so signing for the wrong one is rejected as a bad signature. + pub binds_signing_context: bool, } /// Expected runtime spec name for Quantus nodes, as declared by the runtime's @@ -17,17 +21,72 @@ pub const EXPECTED_RUNTIME_SPEC_NAME: &str = "quantus-runtime"; /// Supported runtime / transaction version pairs. pub const COMPATIBLE_RUNTIMES: &[CompatibleRuntime] = &[ - CompatibleRuntime { spec_version: 134, transaction_version: 2, supports_ml_dsa_65: false }, - CompatibleRuntime { spec_version: 135, transaction_version: 2, supports_ml_dsa_65: false }, - CompatibleRuntime { spec_version: 135, transaction_version: 3, supports_ml_dsa_65: false }, - CompatibleRuntime { spec_version: 136, transaction_version: 3, supports_ml_dsa_65: false }, - CompatibleRuntime { spec_version: 142, transaction_version: 3, supports_ml_dsa_65: true }, - CompatibleRuntime { spec_version: 143, transaction_version: 3, supports_ml_dsa_65: true }, - CompatibleRuntime { spec_version: 144, transaction_version: 3, supports_ml_dsa_65: true }, - CompatibleRuntime { spec_version: 145, transaction_version: 4, supports_ml_dsa_65: true }, - CompatibleRuntime { spec_version: 146, transaction_version: 5, supports_ml_dsa_65: true }, - CompatibleRuntime { spec_version: 147, transaction_version: 6, supports_ml_dsa_65: true }, - CompatibleRuntime { spec_version: 148, transaction_version: 6, supports_ml_dsa_65: true }, + CompatibleRuntime { + spec_version: 134, + transaction_version: 2, + supports_ml_dsa_65: false, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 135, + transaction_version: 2, + supports_ml_dsa_65: false, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 135, + transaction_version: 3, + supports_ml_dsa_65: false, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 136, + transaction_version: 3, + supports_ml_dsa_65: false, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 142, + transaction_version: 3, + supports_ml_dsa_65: true, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 143, + transaction_version: 3, + supports_ml_dsa_65: true, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 144, + transaction_version: 3, + supports_ml_dsa_65: true, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 145, + transaction_version: 4, + supports_ml_dsa_65: true, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 146, + transaction_version: 5, + supports_ml_dsa_65: true, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 147, + transaction_version: 6, + supports_ml_dsa_65: true, + binds_signing_context: false, + }, + CompatibleRuntime { + spec_version: 148, + transaction_version: 6, + supports_ml_dsa_65: true, + binds_signing_context: true, + }, ]; /// Highest `spec_version` listed in [`COMPATIBLE_RUNTIMES`]. @@ -68,6 +127,19 @@ pub fn runtime_supports_ml_dsa_65(spec_version: u32, transaction_version: u32) - COMPATIBLE_RUNTIMES.iter().any(|runtime| runtime.supports_ml_dsa_65) } +/// Whether a runtime binds extrinsic signatures to the `QUANTUS_EXTRINSIC` context. +/// +/// Exact table matches use [`CompatibleRuntime::binds_signing_context`]. Newer unlisted specs are +/// assumed to keep the context (introduced at spec 148). +pub fn runtime_binds_signing_context(spec_version: u32, transaction_version: u32) -> bool { + if let Some(runtime) = COMPATIBLE_RUNTIMES.iter().find(|runtime| { + runtime.spec_version == spec_version && runtime.transaction_version == transaction_version + }) { + return runtime.binds_signing_context; + } + is_newer_unlisted_runtime(spec_version) +} + /// Validate that a connected node's runtime identity is a Quantus runtime this CLI can talk to. /// /// Rejects wrong `specName` values and older/unknown version pairs outside @@ -209,6 +281,25 @@ mod tests { assert!(validate_runtime_version_value(&value).is_err()); } + /// FIPS 204 contexts are domain separated, so this table decides which signature a runtime + /// accepts. Getting a row wrong means every extrinsic against that chain is rejected as a bad + /// signature. Spec 148 introduced the context; everything before it verifies without one. + #[test] + fn signing_context_bound_only_on_runtimes_that_declare_it() { + assert!(!runtime_binds_signing_context(134, 2)); + assert!(!runtime_binds_signing_context(145, 4)); + assert!(!runtime_binds_signing_context(147, 6)); + assert!(runtime_binds_signing_context(148, 6)); + assert!( + !runtime_binds_signing_context(148, 5), + "an unknown tx version must not inherit the context" + ); + assert!( + runtime_binds_signing_context(max_compatible_spec_version() + 1, 6), + "newer unlisted specs are assumed to keep the context" + ); + } + #[test] fn ml_dsa_65_supported_only_on_runtimes_that_declare_it() { assert!(!runtime_supports_ml_dsa_65(134, 2)); diff --git a/src/wallet/keystore.rs b/src/wallet/keystore.rs index 9439078..db53767 100644 --- a/src/wallet/keystore.rs +++ b/src/wallet/keystore.rs @@ -375,15 +375,18 @@ impl QuantumKeyPair { } /// Convert to a scheme-aware subxt signer. - pub fn to_subxt_signer(&self) -> Result { - match self.scheme { - DilithiumScheme::MlDsa87 => Ok(crate::chain::client::QuantusSigner::MlDsa87(Box::new( - self.to_resonance_pair()?, - ))), - DilithiumScheme::MlDsa65 => Ok(crate::chain::client::QuantusSigner::MlDsa65(Box::new( - self.to_dilithium65_pair()?, - ))), - } + /// `context` is the FIPS 204 context the target runtime verifies under; get it from + /// [`crate::chain::client::QuantusClient::signing_context`]. + pub fn to_subxt_signer( + &self, + context: Option<&'static [u8]>, + ) -> Result { + use crate::chain::client::{QuantusSigner, SignerPair}; + let pair = match self.scheme { + DilithiumScheme::MlDsa87 => SignerPair::MlDsa87(Box::new(self.to_resonance_pair()?)), + DilithiumScheme::MlDsa65 => SignerPair::MlDsa65(Box::new(self.to_dilithium65_pair()?)), + }; + Ok(QuantusSigner::new(pair, context)) } #[allow(dead_code)] @@ -1215,9 +1218,9 @@ mod tests { assert_eq!(quantum.private_key.len(), 4032); let restored = quantum.to_dilithium65_pair().expect("65 pair"); assert_eq!(pair.public().as_ref(), restored.public().as_ref()); - let signer = quantum.to_subxt_signer().expect("signer"); - match signer { - crate::chain::client::QuantusSigner::MlDsa65(_) => {}, + let signer = quantum.to_subxt_signer(None).expect("signer"); + match signer.pair { + crate::chain::client::SignerPair::MlDsa65(_) => {}, _ => panic!("expected MlDsa65 signer"), } assert!(quantum.try_to_account_id_ss58check().is_ok());