From c5168b15be77ddd880945de8c4d79a9987363f5b Mon Sep 17 00:00:00 2001 From: girazoki Date: Mon, 29 Jun 2026 09:28:10 +0200 Subject: [PATCH 01/58] change pallet limit orders to support ledger kind of signatures --- pallets/limit-orders/src/benchmarking.rs | 17 ++-- pallets/limit-orders/src/lib.rs | 32 ++++++-- pallets/limit-orders/src/tests/auxiliary.rs | 86 +++++++++++++++++--- pallets/limit-orders/src/tests/extrinsics.rs | 6 +- pallets/limit-orders/src/tests/mock.rs | 14 +++- 5 files changed, 125 insertions(+), 30 deletions(-) diff --git a/pallets/limit-orders/src/benchmarking.rs b/pallets/limit-orders/src/benchmarking.rs index 79bc60f516..8a7124d419 100644 --- a/pallets/limit-orders/src/benchmarking.rs +++ b/pallets/limit-orders/src/benchmarking.rs @@ -21,12 +21,17 @@ fn sign_order( public: sp_core::sr25519::Public, order: &crate::VersionedOrder, ) -> crate::SignedOrder { - let sig = sp_io::crypto::sr25519_sign( - sp_core::crypto::key_types::ACCOUNT, - &public, - &order.encode(), - ) - .unwrap(); + // Mirror the on-chain check in `is_order_valid`: the signed message is the + // ``-wrapped blake2_256 hash of the SCALE-encoded order. + let order_hash = sp_io::hashing::blake2_256(&order.encode()); + let payload = [ + b"".as_slice(), + &order_hash, + b"".as_slice(), + ] + .concat(); + let sig = sp_io::crypto::sr25519_sign(sp_core::crypto::key_types::ACCOUNT, &public, &payload) + .unwrap(); crate::SignedOrder { order: order.clone(), signature: MultiSignature::Sr25519(sig), diff --git a/pallets/limit-orders/src/lib.rs b/pallets/limit-orders/src/lib.rs index 1d5548c529..b6d1065de7 100644 --- a/pallets/limit-orders/src/lib.rs +++ b/pallets/limit-orders/src/lib.rs @@ -131,18 +131,20 @@ impl VersionedOrd } /// The envelope the admin submits on-chain: the versioned order payload plus -/// the user's signature over the SCALE-encoded `VersionedOrder`. +/// the user's signature over the order hash. /// /// Signature verification is performed against `order.inner().signer` (the AccountId) -/// directly. Only sr25519 signatures are accepted; ed25519 and ecdsa variants -/// of `MultiSignature` are rejected at validation time. +/// directly. The signed message is the blake2_256 hash of the SCALE-encoded +/// `VersionedOrder` (i.e. the `OrderId`), wrapped in the `` +/// envelope used by `signRaw` (Polkadot.js, Ledger). Both sr25519 and ed25519 +/// signatures are accepted; ecdsa is rejected at validation time. #[freeze_struct("9dd5a8ac812dc504")] #[derive( Encode, Decode, DecodeWithMemTracking, TypeInfo, MaxEncodedLen, Clone, PartialEq, Eq, Debug, )] pub struct SignedOrder { pub order: VersionedOrder, - /// Sr25519 signature over `SCALE_ENCODE(VersionedOrder)`. + /// Sr25519 or ed25519 signature over `` + `blake2_256(SCALE_ENCODE(VersionedOrder))` + ``. pub signature: MultiSignature, /// Whether we want a partial fill for this order pub partial_fill: Option, @@ -613,11 +615,25 @@ pub mod pallet { order.chain_id == T::ChainId::get(), Error::::ChainIdMismatch ); + // The signed message is the order hash (`order_id` is `blake2_256` over + // the SCALE-encoded order, see `derive_order_id`), wrapped in the + // `` envelope that `signRaw` (Polkadot.js / Ledger) prepends + // and appends to raw payloads. Signing a fixed-size hash rather than the + // full payload keeps the message within Ledger's signing limits. Both + // sr25519 and ed25519 are accepted; ecdsa is rejected. + let payload = [ + b"".as_slice(), + order_id.as_bytes(), + b"".as_slice(), + ] + .concat(); ensure!( - matches!(signed_order.signature, MultiSignature::Sr25519(_)) - && signed_order - .signature - .verify(signed_order.order.encode().as_slice(), &order.signer), + matches!( + signed_order.signature, + MultiSignature::Sr25519(_) | MultiSignature::Ed25519(_) + ) && signed_order + .signature + .verify(payload.as_slice(), &order.signer), Error::::InvalidSignature ); let order_status = Orders::::get(order_id); diff --git a/pallets/limit-orders/src/tests/auxiliary.rs b/pallets/limit-orders/src/tests/auxiliary.rs index 1049c84f74..be79787e83 100644 --- a/pallets/limit-orders/src/tests/auxiliary.rs +++ b/pallets/limit-orders/src/tests/auxiliary.rs @@ -435,7 +435,9 @@ fn validate_and_classify_stores_effective_swap_limit_for_buy() { o }; let versioned = crate::VersionedOrder::V1(new_inner.clone()); - let sig = AccountKeyring::Alice.pair().sign(&versioned.encode()); + let sig = AccountKeyring::Alice + .pair() + .sign(&order_signing_payload(&versioned)); let signed_with_slippage = crate::SignedOrder { order: versioned, signature: sp_runtime::MultiSignature::Sr25519(sig), @@ -478,7 +480,9 @@ fn validate_and_classify_stores_effective_swap_limit_for_sell() { partial_fills_enabled: false, }; let versioned = crate::VersionedOrder::V1(new_inner); - let sig = AccountKeyring::Alice.pair().sign(&versioned.encode()); + let sig = AccountKeyring::Alice + .pair() + .sign(&order_signing_payload(&versioned)); let signed = crate::SignedOrder { order: versioned, signature: sp_runtime::MultiSignature::Sr25519(sig), @@ -1430,7 +1434,7 @@ fn make_valid_signed_order() -> (crate::SignedOrder, sp_core::H256) { partial_fills_enabled: false, }); let id = H256(sp_io::hashing::blake2_256(&order.encode())); - let sig = keyring.pair().sign(&order.encode()); + let sig = keyring.pair().sign(&order_signing_payload(&order)); let signed = crate::SignedOrder { order, signature: MultiSignature::Sr25519(sig), @@ -1462,8 +1466,10 @@ fn is_order_valid_invalid_signature_returns_error() { MockTime::set(1_000_000); MockSwap::set_price(1.0); let (mut signed, id) = make_valid_signed_order(); - // Replace with a signature from a different key. - let wrong_sig = AccountKeyring::Bob.pair().sign(&signed.order.encode()); + // Replace with a signature over the correct payload but from a different key. + let wrong_sig = AccountKeyring::Bob + .pair() + .sign(&order_signing_payload(&signed.order)); signed.signature = MultiSignature::Sr25519(wrong_sig); let price = MockSwap::current_alpha_price(netuid()); assert_noop!( @@ -1474,14 +1480,70 @@ fn is_order_valid_invalid_signature_returns_error() { } #[test] -fn is_order_valid_non_sr25519_signature_returns_error() { +fn is_order_valid_accepts_ed25519_signature() { new_test_ext().execute_with(|| { MockTime::set(1_000_000); MockSwap::set_price(1.0); - let (mut signed, id) = make_valid_signed_order(); + + // The `signer` field must match the ed25519 public key, so derive the + // AccountId from the ed25519 pair rather than reusing Alice's sr25519 key. let ed_pair = sp_core::ed25519::Pair::from_legacy_string("//Alice", None); - let ed_sig = ed_pair.sign(&signed.order.encode()); - signed.signature = MultiSignature::Ed25519(ed_sig); + let ed_signer = AccountId::from(ed_pair.public()); + + let order = crate::VersionedOrder::V1(crate::Order { + signer: ed_signer, + hotkey: AccountKeyring::Bob.to_account_id(), + netuid: netuid(), + order_type: OrderType::LimitBuy, + amount: 1_000, + limit_price: u64::MAX, + expiry: u64::MAX, + fee_rate: Perbill::zero(), + fee_recipient: fee_recipient(), + relayer: None, + max_slippage: None, + chain_id: 945, + partial_fills_enabled: false, + }); + let id = H256(sp_io::hashing::blake2_256(&order.encode())); + let ed_sig = ed_pair.sign(&order_signing_payload(&order)); + let signed = crate::SignedOrder { + order, + signature: MultiSignature::Ed25519(ed_sig), + partial_fill: None, + }; + + let price = MockSwap::current_alpha_price(netuid()); + assert_ok!(LimitOrders::::is_order_valid( + &signed, + id, + 1_000_000, + price, + &bob() + )); + }); +} + +#[test] +fn is_order_valid_rejects_ecdsa_signature() { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + // Even a valid ecdsa signature over the correct payload must be rejected: + // only sr25519 and ed25519 are accepted. + let (order, id) = { + let (signed, id) = make_valid_signed_order(); + (signed.order, id) + }; + let ecdsa_pair = sp_core::ecdsa::Pair::from_legacy_string("//Alice", None); + let ecdsa_sig = ecdsa_pair.sign(&order_signing_payload(&order)); + let signed = crate::SignedOrder { + order, + signature: MultiSignature::Ecdsa(ecdsa_sig), + partial_fill: None, + }; + let price = MockSwap::current_alpha_price(netuid()); assert_noop!( LimitOrders::::is_order_valid(&signed, id, 1_000_000, price, &bob()), @@ -1518,7 +1580,7 @@ fn is_order_valid_expired_order_returns_error() { ..signed.order.inner().clone() }); let id2 = H256(sp_io::hashing::blake2_256(&order.encode())); - let sig = keyring.pair().sign(&order.encode()); + let sig = keyring.pair().sign(&order_signing_payload(&order)); let signed2 = crate::SignedOrder { order, signature: MultiSignature::Sr25519(sig), @@ -1555,7 +1617,7 @@ fn is_order_valid_price_condition_not_met_returns_error() { partial_fills_enabled: false, }); let id = H256(sp_io::hashing::blake2_256(&order.encode())); - let sig = keyring.pair().sign(&order.encode()); + let sig = keyring.pair().sign(&order_signing_payload(&order)); let signed = crate::SignedOrder { order, signature: MultiSignature::Sr25519(sig), @@ -1581,7 +1643,7 @@ fn is_order_valid_wrong_chain_id_returns_error() { ..make_valid_signed_order().0.order.inner().clone() }); let id = H256(sp_io::hashing::blake2_256(&order.encode())); - let sig = keyring.pair().sign(&order.encode()); + let sig = keyring.pair().sign(&order_signing_payload(&order)); let signed = crate::SignedOrder { order, signature: MultiSignature::Sr25519(sig), diff --git a/pallets/limit-orders/src/tests/extrinsics.rs b/pallets/limit-orders/src/tests/extrinsics.rs index 43a85a1db1..3c50570e09 100644 --- a/pallets/limit-orders/src/tests/extrinsics.rs +++ b/pallets/limit-orders/src/tests/extrinsics.rs @@ -2182,7 +2182,7 @@ fn make_signed_order_with_slippage( chain_id: 945, partial_fills_enabled: false, }); - let sig = keyring.pair().sign(&order.encode()); + let sig = keyring.pair().sign(&order_signing_payload(&order)); crate::SignedOrder { order, signature: sp_runtime::MultiSignature::Sr25519(sig), @@ -2983,7 +2983,9 @@ fn execute_orders_partial_fill_without_relayer_skipped() { partial_fills_enabled: true, }; let versioned = VersionedOrder::V1(inner); - let sig = AccountKeyring::Alice.pair().sign(&versioned.encode()); + let sig = AccountKeyring::Alice + .pair() + .sign(&order_signing_payload(&versioned)); let signed = crate::SignedOrder { order: versioned, signature: sp_runtime::MultiSignature::Sr25519(sig), diff --git a/pallets/limit-orders/src/tests/mock.rs b/pallets/limit-orders/src/tests/mock.rs index 2834c54afe..bfc4c4714a 100644 --- a/pallets/limit-orders/src/tests/mock.rs +++ b/pallets/limit-orders/src/tests/mock.rs @@ -559,6 +559,16 @@ pub fn netuid() -> NetUid { pub const FAR_FUTURE: u64 = u64::MAX; +/// Build the raw payload that the order's `signer` must sign. +/// +/// Mirrors the production logic in `is_order_valid`: the signed message is the +/// `` `signRaw` envelope wrapped around the 32-byte order hash +/// (`blake2_256(SCALE_ENCODE(VersionedOrder))`, i.e. the `OrderId`). +pub fn order_signing_payload(order: &crate::VersionedOrder) -> Vec { + let id = sp_io::hashing::blake2_256(&order.encode()); + [b"".as_slice(), &id, b"".as_slice()].concat() +} + #[allow(clippy::too_many_arguments)] pub fn make_signed_order( keyring: AccountKeyring, @@ -588,7 +598,7 @@ pub fn make_signed_order( chain_id: 945, partial_fills_enabled: false, }); - let sig = keyring.pair().sign(&order.encode()); + let sig = keyring.pair().sign(&order_signing_payload(&order)); crate::SignedOrder { order, signature: MultiSignature::Sr25519(sig), @@ -626,7 +636,7 @@ pub fn make_partial_fill_order( chain_id: 945, partial_fills_enabled: true, }); - let sig = keyring.pair().sign(&order.encode()); + let sig = keyring.pair().sign(&order_signing_payload(&order)); crate::SignedOrder { order, signature: MultiSignature::Sr25519(sig), From d507ead1675bf369bbfbfaa9162470ec85f26acf Mon Sep 17 00:00:00 2001 From: girazoki Date: Mon, 29 Jun 2026 10:15:46 +0200 Subject: [PATCH 02/58] support both ledger and non-ledger sig formats --- pallets/limit-orders/src/lib.rs | 78 ++++++--- pallets/limit-orders/src/tests/auxiliary.rs | 148 ++++++++++++++++++ pallets/limit-orders/src/tests/extrinsics.rs | 1 - runtime/tests/limit_orders.rs | 99 +++++++++++- .../test-execute-orders-ed25519-wrapped.ts | 116 ++++++++++++++ ts-tests/utils/limit-orders.ts | 63 +++++++- 6 files changed, 464 insertions(+), 41 deletions(-) create mode 100644 ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-ed25519-wrapped.ts diff --git a/pallets/limit-orders/src/lib.rs b/pallets/limit-orders/src/lib.rs index b6d1065de7..2cafdeca7c 100644 --- a/pallets/limit-orders/src/lib.rs +++ b/pallets/limit-orders/src/lib.rs @@ -131,20 +131,22 @@ impl VersionedOrd } /// The envelope the admin submits on-chain: the versioned order payload plus -/// the user's signature over the order hash. +/// the user's signature over the order. /// /// Signature verification is performed against `order.inner().signer` (the AccountId) -/// directly. The signed message is the blake2_256 hash of the SCALE-encoded -/// `VersionedOrder` (i.e. the `OrderId`), wrapped in the `` -/// envelope used by `signRaw` (Polkadot.js, Ledger). Both sr25519 and ed25519 -/// signatures are accepted; ecdsa is rejected at validation time. -#[freeze_struct("9dd5a8ac812dc504")] +/// directly, and either signing form is accepted (see `verify_order` / `verify_wrapped`): +/// - raw: the SCALE-encoded `VersionedOrder`, or +/// - wrapped: `` + `blake2_256(SCALE_ENCODE(VersionedOrder))` (the `OrderId`) + ``, +/// the `signRaw` envelope used by Polkadot.js / Ledger. +/// Both sr25519 and ed25519 signatures are accepted; ecdsa is rejected at validation time. +#[freeze_struct("969452eb68f33c4")] #[derive( Encode, Decode, DecodeWithMemTracking, TypeInfo, MaxEncodedLen, Clone, PartialEq, Eq, Debug, )] pub struct SignedOrder { pub order: VersionedOrder, - /// Sr25519 or ed25519 signature over `` + `blake2_256(SCALE_ENCODE(VersionedOrder))` + ``. + /// Sr25519 or ed25519 signature over either the raw SCALE-encoded `VersionedOrder` + /// or the ``-wrapped order hash (see `verify_order` / `verify_wrapped`). pub signature: MultiSignature, /// Whether we want a partial fill for this order pub partial_fill: Option, @@ -598,6 +600,41 @@ pub mod pallet { T::SwapInterface::transfer_tao(signer, recipient, fee_tao) } + /// Verify the signature over the **raw** SCALE-encoded order — the original, + /// non-Ledger form a software wallet signing arbitrary bytes produces. + /// Accepts sr25519 and ed25519; rejects ecdsa. + pub(crate) fn verify_order(signed_order: &SignedOrder) -> bool { + let order = signed_order.order.inner(); + matches!( + signed_order.signature, + MultiSignature::Sr25519(_) | MultiSignature::Ed25519(_) + ) && signed_order + .signature + .verify(signed_order.order.encode().as_slice(), &order.signer) + } + + /// Verify the signature over the **wrapped order hash** — the Ledger/`signRaw` + /// form: `` + `blake2_256(SCALE_ENCODE(order))` (i.e. `order_id`) + ``. + /// Signing a fixed-size hash keeps the message within Ledger's signing limits, + /// and the `` envelope is what `signRaw` (Polkadot.js / Ledger) + /// wraps around raw payloads. Accepts sr25519 and ed25519; rejects ecdsa. + pub(crate) fn verify_wrapped( + signed_order: &SignedOrder, + order_id: H256, + ) -> bool { + let order = signed_order.order.inner(); + let payload = [ + b"".as_slice(), + order_id.as_bytes(), + b"".as_slice(), + ] + .concat(); + matches!( + signed_order.signature, + MultiSignature::Sr25519(_) | MultiSignature::Ed25519(_) + ) && signed_order.signature.verify(payload.as_slice(), &order.signer) + } + /// Validates all execution preconditions for a signed order. /// Checks that the order's netuid is not root (0), that the signature is valid, /// the order has not been processed, is not expired, and the price condition is met. @@ -615,25 +652,16 @@ pub mod pallet { order.chain_id == T::ChainId::get(), Error::::ChainIdMismatch ); - // The signed message is the order hash (`order_id` is `blake2_256` over - // the SCALE-encoded order, see `derive_order_id`), wrapped in the - // `` envelope that `signRaw` (Polkadot.js / Ledger) prepends - // and appends to raw payloads. Signing a fixed-size hash rather than the - // full payload keeps the message within Ledger's signing limits. Both - // sr25519 and ed25519 are accepted; ecdsa is rejected. - let payload = [ - b"".as_slice(), - order_id.as_bytes(), - b"".as_slice(), - ] - .concat(); + // Accept either signing form: the legacy raw form (`verify_order`, + // signature directly over the SCALE-encoded order) or the Ledger/`signRaw` + // form (`verify_wrapped`, signature over the ``-wrapped order + // hash). Both are checked so software wallets signing raw bytes and hardware + // wallets that can only sign wrapped messages are simultaneously supported. + // The raw form is checked first: it short-circuits the common relayer flow, + // and an order signed in the wrapped form falls through to a second verify, + // which is the two-verification worst case the weights must account for. ensure!( - matches!( - signed_order.signature, - MultiSignature::Sr25519(_) | MultiSignature::Ed25519(_) - ) && signed_order - .signature - .verify(payload.as_slice(), &order.signer), + Self::verify_order(signed_order) || Self::verify_wrapped(signed_order, order_id), Error::::InvalidSignature ); let order_status = Orders::::get(order_id); diff --git a/pallets/limit-orders/src/tests/auxiliary.rs b/pallets/limit-orders/src/tests/auxiliary.rs index be79787e83..9d75e93790 100644 --- a/pallets/limit-orders/src/tests/auxiliary.rs +++ b/pallets/limit-orders/src/tests/auxiliary.rs @@ -1657,6 +1657,154 @@ fn is_order_valid_wrong_chain_id_returns_error() { }); } +#[test] +fn is_order_valid_accepts_raw_sr25519_signature() { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + // Legacy raw form: sign the SCALE-encoded order directly (NOT the + // ``-wrapped hash). This exercises the `verify_order` + // branch of the `verify_order(..) || verify_wrapped(..)` check. + let keyring = AccountKeyring::Alice; + let order = crate::VersionedOrder::V1(crate::Order { + signer: keyring.to_account_id(), + hotkey: AccountKeyring::Bob.to_account_id(), + netuid: netuid(), + order_type: OrderType::LimitBuy, + amount: 1_000, + limit_price: u64::MAX, + expiry: u64::MAX, + fee_rate: Perbill::zero(), + fee_recipient: fee_recipient(), + relayer: None, + max_slippage: None, + chain_id: 945, + partial_fills_enabled: false, + }); + let id = H256(sp_io::hashing::blake2_256(&order.encode())); + // Sign the raw encoded order, not the wrapped payload. + let sig = keyring.pair().sign(&order.encode()); + let signed = crate::SignedOrder { + order, + signature: MultiSignature::Sr25519(sig), + partial_fill: None, + }; + + let price = MockSwap::current_alpha_price(netuid()); + assert_ok!(LimitOrders::::is_order_valid( + &signed, + id, + 1_000_000, + price, + &bob() + )); + }); +} + +#[test] +fn is_order_valid_accepts_raw_ed25519_signature() { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + // ed25519 signer over the RAW encoded order (legacy form). The `signer` + // field must be the ed25519 public key for verification to succeed. + let ed_pair = sp_core::ed25519::Pair::from_legacy_string("//Alice", None); + let ed_signer = AccountId::from(ed_pair.public()); + + let order = crate::VersionedOrder::V1(crate::Order { + signer: ed_signer, + hotkey: AccountKeyring::Bob.to_account_id(), + netuid: netuid(), + order_type: OrderType::LimitBuy, + amount: 1_000, + limit_price: u64::MAX, + expiry: u64::MAX, + fee_rate: Perbill::zero(), + fee_recipient: fee_recipient(), + relayer: None, + max_slippage: None, + chain_id: 945, + partial_fills_enabled: false, + }); + let id = H256(sp_io::hashing::blake2_256(&order.encode())); + // Sign the raw encoded order, not the wrapped payload. + let ed_sig = ed_pair.sign(&order.encode()); + let signed = crate::SignedOrder { + order, + signature: MultiSignature::Ed25519(ed_sig), + partial_fill: None, + }; + + let price = MockSwap::current_alpha_price(netuid()); + assert_ok!(LimitOrders::::is_order_valid( + &signed, + id, + 1_000_000, + price, + &bob() + )); + }); +} + +#[test] +fn verify_order_and_verify_wrapped_unit() { + new_test_ext().execute_with(|| { + let keyring = AccountKeyring::Alice; + let order = crate::VersionedOrder::V1(crate::Order { + signer: keyring.to_account_id(), + hotkey: AccountKeyring::Bob.to_account_id(), + netuid: netuid(), + order_type: OrderType::LimitBuy, + amount: 1_000, + limit_price: u64::MAX, + expiry: u64::MAX, + fee_rate: Perbill::zero(), + fee_recipient: fee_recipient(), + relayer: None, + max_slippage: None, + chain_id: 945, + partial_fills_enabled: false, + }); + let id = H256(sp_io::hashing::blake2_256(&order.encode())); + + // Raw-signed order: signature over `order.encode()`. + // verify_order must accept it; verify_wrapped must reject it. + let raw_sig = keyring.pair().sign(&order.encode()); + let raw_signed = crate::SignedOrder { + order: order.clone(), + signature: MultiSignature::Sr25519(raw_sig), + partial_fill: None, + }; + assert!( + LimitOrders::::verify_order(&raw_signed), + "raw-signed order must pass verify_order" + ); + assert!( + !LimitOrders::::verify_wrapped(&raw_signed, id), + "raw-signed order must NOT pass verify_wrapped" + ); + + // Wrapped-signed order: signature over the `` payload. + // verify_wrapped must accept it; verify_order must reject it. + let wrapped_sig = keyring.pair().sign(&order_signing_payload(&order)); + let wrapped_signed = crate::SignedOrder { + order, + signature: MultiSignature::Sr25519(wrapped_sig), + partial_fill: None, + }; + assert!( + !LimitOrders::::verify_order(&wrapped_signed), + "wrapped-signed order must NOT pass verify_order" + ); + assert!( + LimitOrders::::verify_wrapped(&wrapped_signed, id), + "wrapped-signed order must pass verify_wrapped" + ); + }); +} + // ───────────────────────────────────────────────────────────────────────────── // compute_order_status // ───────────────────────────────────────────────────────────────────────────── diff --git a/pallets/limit-orders/src/tests/extrinsics.rs b/pallets/limit-orders/src/tests/extrinsics.rs index 3c50570e09..1859f1015f 100644 --- a/pallets/limit-orders/src/tests/extrinsics.rs +++ b/pallets/limit-orders/src/tests/extrinsics.rs @@ -5,7 +5,6 @@ //! and event emission are all verified. SwapInterface calls are handled by //! `MockSwap`, which records calls and maintains in-memory balance ledgers. -use codec::Encode; use frame_support::{BoundedVec, assert_noop, assert_ok}; use sp_core::Pair; use sp_keyring::Sr25519Keyring as AccountKeyring; diff --git a/runtime/tests/limit_orders.rs b/runtime/tests/limit_orders.rs index f68191fa29..274ccd44bf 100644 --- a/runtime/tests/limit_orders.rs +++ b/runtime/tests/limit_orders.rs @@ -294,11 +294,12 @@ fn cancel_order_works() { }); } -/// An order signed with an Ed25519 key is rejected at validation time even -/// though the signature itself is cryptographically valid. The order must not -/// appear in the Orders storage map after the batch runs. +/// An order signed with an ECDSA key is rejected at validation time even though +/// the signature itself is cryptographically valid: `is_order_valid` accepts +/// sr25519 and ed25519 but rejects ecdsa. The order must not appear in the +/// Orders storage map after the batch runs. #[test] -fn execute_orders_ed25519_signature_rejected() { +fn execute_orders_ecdsa_signature_rejected() { new_test_ext().execute_with(|| { let alice_id = Sr25519Keyring::Alice.to_account_id(); let bob_id = Sr25519Keyring::Bob.to_account_id(); @@ -322,12 +323,14 @@ fn execute_orders_ed25519_signature_rejected() { }); let id = order_id(&order); - // Sign with ed25519 — valid signature, wrong scheme. - let ed_pair = sp_core::ed25519::Pair::from_legacy_string("//Alice", None); - let ed_sig = ed_pair.sign(&order.encode()); + // Sign with ecdsa — cryptographically valid signature, rejected scheme. + // The signer is still sr25519 Alice, but the rejection is driven by the + // ecdsa scheme, not by a key mismatch. + let ecdsa_pair = sp_core::ecdsa::Pair::from_legacy_string("//Alice", None); + let ecdsa_sig = ecdsa_pair.sign(&order.encode()); let signed = SignedOrder { order, - signature: MultiSignature::Ed25519(ed_sig), + signature: MultiSignature::Ecdsa(ecdsa_sig), partial_fill: None, }; @@ -450,6 +453,86 @@ fn limit_buy_order_executes_and_stakes_alpha() { }); } +/// End-to-end: a LimitBuy order whose `signer` is an ed25519 account, signed with +/// the ``-wrapped order-hash payload (the Ledger / `signRaw` +/// envelope), executes against the pool, is marked Fulfilled, and credits staked +/// alpha to the ed25519 signer. Mirrors `limit_buy_order_executes_and_stakes_alpha` +/// but exercises the ed25519 + wrapped-signature acceptance path. +#[test] +fn execute_orders_ed25519_wrapped_signature_executes() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1u16); + let bob_id = Sr25519Keyring::Bob.to_account_id(); + let charlie_id = Sr25519Keyring::Charlie.to_account_id(); + + // ed25519 signer account — the order's `signer` and the staking coldkey. + let ed_pair = sp_core::ed25519::Pair::from_legacy_string("//Alice", None); + let ed_signer: AccountId = sp_core::ed25519::Public::from(ed_pair.public()).into(); + + setup_subnet(netuid); + + // Fund the ED25519 signer (not sr25519 Alice) so buy_alpha can debit it, + // and create its hotkey association through bob. + fund_account(&ed_signer); + let _ = SubtensorModule::create_account_if_non_existent(&ed_signer, &bob_id); + + // Build the order manually: make_signed_order hardcodes an sr25519 keyring + // signer, so it cannot express an ed25519 signer. Field values match the + // limit-buy test above. + let order = VersionedOrder::V1(Order { + signer: ed_signer.clone(), + hotkey: bob_id.clone(), + netuid, + order_type: OrderType::LimitBuy, + amount: min_default_stake().into(), + limit_price: u64::MAX, + expiry: u64::MAX, + fee_rate: Perbill::zero(), + fee_recipient: charlie_id.clone(), + relayer: None, + max_slippage: None, + partial_fills_enabled: false, + // chain_id 0 matches the default pallet_evm_chain_id genesis value in tests + chain_id: 0, + }); + let id = order_id(&order); + + // Sign the ``-wrapped 32-byte order hash with ed25519. + // `id` is blake2_256(order.encode()); `id.as_bytes()` are exactly those + // 32 hash bytes, matching the runtime's wrapped-verification payload. + let payload = [b"".as_slice(), id.as_bytes(), b"".as_slice()].concat(); + let ed_sig = ed_pair.sign(&payload); + let signed = SignedOrder { + order, + signature: MultiSignature::Ed25519(ed_sig), + partial_fill: None, + }; + + let orders = make_order_batch(vec![signed]); + + assert_ok!(LimitOrders::execute_orders( + RuntimeOrigin::signed(charlie_id), + orders, + false, + )); + + // Order must be marked as executed. + assert_eq!(Orders::::get(id), Some(OrderStatus::Fulfilled)); + + // The ed25519 signer must now hold staked alpha delegated through Bob. + // AMM pool output has slight slippage even with the stable mechanism; check within 1%. + let staked = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &bob_id, &ed_signer, netuid, + ); + let expected_alpha = min_default_stake().to_u64(); + assert!( + staked >= AlphaBalance::from(expected_alpha * 99 / 100) + && staked <= AlphaBalance::from(expected_alpha), + "ed25519 signer should hold approximately min_default_stake alpha after a wrapped-signed LimitBuy executes (got {staked:?})" + ); + }); +} + /// A TakeProfit order whose price condition is satisfied executes against the pool, /// marks the order as Fulfilled, and burns the seller's staked alpha position. #[test] diff --git a/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-ed25519-wrapped.ts b/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-ed25519-wrapped.ts new file mode 100644 index 0000000000..5073ffd2e1 --- /dev/null +++ b/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-ed25519-wrapped.ts @@ -0,0 +1,116 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import type { ApiPromise } from "@polkadot/api"; +import type { KeyringPair } from "@moonwall/util"; +import { tao, generateKeyringPair } from "../../../../utils"; +import { + devForceSetBalance, + devGetAlphaStake, + devAssociateHotKey, + devEnableSubtoken, + devRegisterSubnet, + devSudoSetLockReductionInterval, + devExecuteOrders, +} from "../../../../utils/dev-helpers.js"; +import { + buildWrappedSignedOrder, + FAR_FUTURE, + fetchChainId, + filterEvents, + getOrderStatus, + orderId, + registerLimitOrderTypes, +} from "../../../../utils/limit-orders.js"; + +// One subnet per file — this test submits a real buy order signed by an +// ed25519 key over the ``-wrapped order hash (the Ledger / signRaw +// form). It exercises the runtime's alternative `is_order_valid` path: +// signature.verify(b"" ++ blake2_256(SCALE(VersionedOrder)) ++ b"", signer) +// with an Ed25519 signature. + +describeSuite({ + id: "DEV_SUB_LIMIT_ORDERS_ED25519_WRAPPED", + title: "execute_orders — ed25519 + -wrapped LimitBuy execution", + foundationMethods: "dev", + testCases: ({ it, context }) => { + let polkadotJs: ApiPromise; + let alice: KeyringPair; + let aliceHotKey: KeyringPair; + let edSigner: KeyringPair; + let edHotKey: KeyringPair; + let netuid: number; + let chainId: bigint; + + beforeAll(async () => { + polkadotJs = context.polkadotJs(); + + alice = context.keyring.alice; + aliceHotKey = generateKeyringPair("sr25519"); + + // ed25519 coldkey/signer that signs the wrapped order hash, with an + // sr25519 hotkey associated to it. + edSigner = generateKeyringPair("ed25519"); + edHotKey = generateKeyringPair("sr25519"); + + registerLimitOrderTypes(polkadotJs); + chainId = await fetchChainId(polkadotJs); + + await devForceSetBalance(polkadotJs, context, alice.address, tao(10_000)); + await devForceSetBalance(polkadotJs, context, edSigner.address, tao(10_000)); + + await devSudoSetLockReductionInterval(polkadotJs, context, alice, 1); + + netuid = await devRegisterSubnet(polkadotJs, context, alice, aliceHotKey); + + // Enable subtoken + await devEnableSubtoken(polkadotJs, context, alice, netuid); + // Associate hotkeys — the ed25519 signer associates its own hotkey. + await devAssociateHotKey(polkadotJs, context, alice, aliceHotKey.address); + await devAssociateHotKey(polkadotJs, context, edSigner, edHotKey.address); + }); + + it({ + id: "T01", + title: "LimitBuy executes with an ed25519 -wrapped signature", + test: async () => { + const stakeBefore = await devGetAlphaStake(polkadotJs, edHotKey.address, edSigner.address, netuid); + const taoBalanceBefore = ( + await polkadotJs.query.system.account(edSigner.address) + ).data.free.toBigInt(); + + const signed = buildWrappedSignedOrder(polkadotJs, { + signer: edSigner, + hotkey: edHotKey.address, + netuid, + orderType: "LimitBuy", + amount: tao(100), + limitPrice: FAR_FUTURE, + expiry: FAR_FUTURE, + feeRate: 0, + feeRecipient: edSigner.address, + chainId, + }); + + // Alice relays/submits the ed25519-signed order. + await devExecuteOrders(polkadotJs, context, alice, [signed]); + + const events = await polkadotJs.query.system.events(); + const executed = filterEvents(events, "OrderExecuted"); + expect(executed.length).toBe(1); + + // OrderId should be stored as Fulfilled + const id = orderId(polkadotJs, signed.order); + expect(await getOrderStatus(polkadotJs, id)).toBe("Fulfilled"); + + // Alpha stake for the ed25519 signer's hotkey should have increased + const stakeAfter = await devGetAlphaStake(polkadotJs, edHotKey.address, edSigner.address, netuid); + expect(stakeAfter).toBeGreaterThan(stakeBefore); + + // ed25519 signer's TAO balance should have decreased + const taoBalanceAfter = ( + await polkadotJs.query.system.account(edSigner.address) + ).data.free.toBigInt(); + expect(taoBalanceAfter).toBeLessThan(taoBalanceBefore); + }, + }); + }, +}); diff --git a/ts-tests/utils/limit-orders.ts b/ts-tests/utils/limit-orders.ts index 0ffbe177e0..e9ba6816c0 100644 --- a/ts-tests/utils/limit-orders.ts +++ b/ts-tests/utils/limit-orders.ts @@ -2,8 +2,8 @@ import type { KeyringPair } from "@moonwall/util"; import type { TypedApi } from "polkadot-api"; import type { subtensor } from "@polkadot-api/descriptors"; import { Keyring } from "@polkadot/keyring"; -import { u8aToHex } from "@polkadot/util"; -import { blake2AsHex } from "@polkadot/util-crypto"; +import { u8aToHex, u8aWrapBytes } from "@polkadot/util"; +import { blake2AsHex, blake2AsU8a } from "@polkadot/util-crypto"; import { waitForTransactionWithRetry } from "./transactions.js"; import { MultiAddress } from "@polkadot-api/descriptors"; @@ -62,11 +62,11 @@ export const EXPIRED = BigInt(1); // 1ms — always in the past // ── Order building & signing ────────────────────────────────────────────────── /** - * Build a SignedOrder ready for submission to execute_orders / - * execute_batched_orders. The Order struct is SCALE-encoded via the - * polkadot.js registry and then signed with the signer's sr25519 key. + * Build the `VersionedOrder` (V1) struct from the supplied params. Shared by + * `buildSignedOrder` (raw signing) and `buildWrappedSignedOrder` (Ledger / + * signRaw ``-wrapped signing) so the field mapping stays identical. */ -export function buildSignedOrder(api: any, params: OrderParams): SignedOrder { +function buildVersionedOrder(params: OrderParams): VersionedOrder { const inner: Order = { signer: params.signer.address, hotkey: params.hotkey, @@ -83,7 +83,16 @@ export function buildSignedOrder(api: any, params: OrderParams): SignedOrder { partial_fills_enabled: params.partialFillsEnabled ?? false, }; - const versionedOrder: VersionedOrder = { V1: inner }; + return { V1: inner }; +} + +/** + * Build a SignedOrder ready for submission to execute_orders / + * execute_batched_orders. The Order struct is SCALE-encoded via the + * polkadot.js registry and then signed with the signer's sr25519 key. + */ +export function buildSignedOrder(api: any, params: OrderParams): SignedOrder { + const versionedOrder = buildVersionedOrder(params); // SCALE-encode the VersionedOrder so the signature covers the version tag. const encoded = api.registry.createType("LimitVersionedOrder", versionedOrder); @@ -96,6 +105,46 @@ export function buildSignedOrder(api: any, params: OrderParams): SignedOrder { }; } +/** + * Build a SignedOrder whose signature is over the ``-wrapped order hash + * (the Ledger / `signRaw` form). This exercises the runtime's alternative + * verification path: + * + * signature.verify(b"" ++ blake2_256(SCALE(VersionedOrder)) ++ b"", signer) + * + * The signed payload is the raw 32-byte blake2-256 hash of the SCALE-encoded + * VersionedOrder, wrapped by `u8aWrapBytes` (which prepends `` and + * appends ``). This is byte-for-byte what the runtime reconstructs + * from `order_id.as_bytes()`, so the hash must be wrapped raw — never + * hex-encoded before wrapping. + * + * The signature scheme tag (`Sr25519` vs `Ed25519`) follows the signer's + * keypair type, so the same helper works for both schemes. + */ +export function buildWrappedSignedOrder(api: any, params: OrderParams): SignedOrder { + const versionedOrder = buildVersionedOrder(params); + + // SCALE-encode the VersionedOrder, then hash it (this is the OrderId). + const encoded = api.registry.createType("LimitVersionedOrder", versionedOrder); + const hash = blake2AsU8a(encoded.toU8a(), 256); + + // Wrap the raw 32-byte hash in the signRaw envelope: ..hash... + const wrapped = u8aWrapBytes(hash); + const sig = params.signer.sign(wrapped); + + // Tag the signature variant from the keypair type. + const signature = + params.signer.type === "ed25519" + ? { Ed25519: u8aToHex(sig) as `0x${string}` } + : { Sr25519: u8aToHex(sig) as `0x${string}` }; + + return { + order: versionedOrder, + signature, + partial_fill: null, + }; +} + /** * Compute the on-chain OrderId (blake2_256 of SCALE-encoded VersionedOrder). * Mirrors `Pallet::derive_order_id` in Rust. From c668adef3dda84344431e3fe39867c32c62922ae Mon Sep 17 00:00:00 2001 From: girazoki Date: Mon, 29 Jun 2026 13:52:03 +0200 Subject: [PATCH 03/58] rust fjmt --- pallets/limit-orders/src/benchmarking.rs | 7 +------ pallets/limit-orders/src/lib.rs | 4 +++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pallets/limit-orders/src/benchmarking.rs b/pallets/limit-orders/src/benchmarking.rs index 8a7124d419..2aa6e1ee91 100644 --- a/pallets/limit-orders/src/benchmarking.rs +++ b/pallets/limit-orders/src/benchmarking.rs @@ -24,12 +24,7 @@ fn sign_order( // Mirror the on-chain check in `is_order_valid`: the signed message is the // ``-wrapped blake2_256 hash of the SCALE-encoded order. let order_hash = sp_io::hashing::blake2_256(&order.encode()); - let payload = [ - b"".as_slice(), - &order_hash, - b"".as_slice(), - ] - .concat(); + let payload = [b"".as_slice(), &order_hash, b"".as_slice()].concat(); let sig = sp_io::crypto::sr25519_sign(sp_core::crypto::key_types::ACCOUNT, &public, &payload) .unwrap(); crate::SignedOrder { diff --git a/pallets/limit-orders/src/lib.rs b/pallets/limit-orders/src/lib.rs index 2cafdeca7c..2216794887 100644 --- a/pallets/limit-orders/src/lib.rs +++ b/pallets/limit-orders/src/lib.rs @@ -632,7 +632,9 @@ pub mod pallet { matches!( signed_order.signature, MultiSignature::Sr25519(_) | MultiSignature::Ed25519(_) - ) && signed_order.signature.verify(payload.as_slice(), &order.signer) + ) && signed_order + .signature + .verify(payload.as_slice(), &order.signer) } /// Validates all execution preconditions for a signed order. From db46d7fa6975d9b58e20f8bbc115a1baf5b1b2e6 Mon Sep 17 00:00:00 2001 From: girazoki Date: Mon, 29 Jun 2026 13:54:57 +0200 Subject: [PATCH 04/58] ts fmt --- .../limit-orders/test-execute-orders-ed25519-wrapped.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-ed25519-wrapped.ts b/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-ed25519-wrapped.ts index 5073ffd2e1..6f9893cf70 100644 --- a/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-ed25519-wrapped.ts +++ b/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-ed25519-wrapped.ts @@ -73,9 +73,7 @@ describeSuite({ title: "LimitBuy executes with an ed25519 -wrapped signature", test: async () => { const stakeBefore = await devGetAlphaStake(polkadotJs, edHotKey.address, edSigner.address, netuid); - const taoBalanceBefore = ( - await polkadotJs.query.system.account(edSigner.address) - ).data.free.toBigInt(); + const taoBalanceBefore = (await polkadotJs.query.system.account(edSigner.address)).data.free.toBigInt(); const signed = buildWrappedSignedOrder(polkadotJs, { signer: edSigner, @@ -106,9 +104,7 @@ describeSuite({ expect(stakeAfter).toBeGreaterThan(stakeBefore); // ed25519 signer's TAO balance should have decreased - const taoBalanceAfter = ( - await polkadotJs.query.system.account(edSigner.address) - ).data.free.toBigInt(); + const taoBalanceAfter = (await polkadotJs.query.system.account(edSigner.address)).data.free.toBigInt(); expect(taoBalanceAfter).toBeLessThan(taoBalanceBefore); }, }); From 0913d4d481f0d28d972b43d09949c33f3d957769 Mon Sep 17 00:00:00 2001 From: girazoki Date: Wed, 1 Jul 2026 14:30:43 +0200 Subject: [PATCH 05/58] Human friendly lerger sigs --- Cargo.lock | 1 + Cargo.toml | 1 + pallets/limit-orders/Cargo.toml | 2 + pallets/limit-orders/src/benchmarking.rs | 15 +- pallets/limit-orders/src/lib.rs | 136 +++- pallets/limit-orders/src/tests/mod.rs | 1 + pallets/limit-orders/src/tests/readable.rs | 593 ++++++++++++++++++ runtime/tests/limit_orders.rs | 125 ++++ .../test-execute-orders-readable.ts | 164 +++++ .../test-readable-message-format.ts | 193 ++++++ ts-tests/utils/limit-orders.ts | 104 ++- 11 files changed, 1325 insertions(+), 10 deletions(-) create mode 100644 pallets/limit-orders/src/tests/readable.rs create mode 100644 ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-readable.ts create mode 100644 ts-tests/suites/dev/subtensor/limit-orders/test-readable-message-format.ts diff --git a/Cargo.lock b/Cargo.lock index b49277401c..3b50d5e6a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10101,6 +10101,7 @@ dependencies = [ name = "pallet-limit-orders" version = "0.1.0" dependencies = [ + "bs58", "frame-benchmarking", "frame-support", "frame-system", diff --git a/Cargo.toml b/Cargo.toml index 6f160c29e4..949dc95106 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -301,6 +301,7 @@ pallet-shield = { path = "pallets/shield", default-features = false } ml-kem = { version = "0.2.2", default-features = false } chacha20poly1305 = { version = "0.10", default-features = false } blake2 = "0.10.6" +bs58 = { version = "0.5.1", default-features = false } # Primitives diff --git a/pallets/limit-orders/Cargo.toml b/pallets/limit-orders/Cargo.toml index 48ffc61dcb..048caa41d8 100644 --- a/pallets/limit-orders/Cargo.toml +++ b/pallets/limit-orders/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition.workspace = true [dependencies] +bs58 = { workspace = true, default-features = false, features = ["alloc"] } codec = { workspace = true, features = ["derive"] } frame-benchmarking = { workspace = true, optional = true } sp-io = { workspace = true, optional = true } @@ -31,6 +32,7 @@ workspace = true [features] default = ["std"] std = [ + "bs58/std", "codec/std", "frame-benchmarking?/std", "frame-support/std", diff --git a/pallets/limit-orders/src/benchmarking.rs b/pallets/limit-orders/src/benchmarking.rs index 2aa6e1ee91..f9a1bf1eab 100644 --- a/pallets/limit-orders/src/benchmarking.rs +++ b/pallets/limit-orders/src/benchmarking.rs @@ -11,20 +11,25 @@ use sp_core::{Get, H256}; use sp_runtime::{AccountId32, MultiSignature, Perbill, traits::AccountIdConversion}; extern crate alloc; use crate::{Call, Config, Pallet}; -use codec::Encode; /// Sign a versioned order using the runtime keystore (no `full_crypto` required). /// /// The key identified by `public` must already be registered in the keystore /// (e.g. via `sp_io::crypto::sr25519_generate`) before calling this. +/// +/// The order is signed in the **human-readable ("clear-signing") form** on +/// purpose: it is the worst case for `is_order_valid`, which tries +/// `verify_order` (raw) and `verify_wrapped` (hash) first and only succeeds on +/// the final `verify_readable`. Signing this form forces all three signature +/// verifications to run, so the measured weight reflects the true worst case. fn sign_order( public: sp_core::sr25519::Public, order: &crate::VersionedOrder, ) -> crate::SignedOrder { - // Mirror the on-chain check in `is_order_valid`: the signed message is the - // ``-wrapped blake2_256 hash of the SCALE-encoded order. - let order_hash = sp_io::hashing::blake2_256(&order.encode()); - let payload = [b"".as_slice(), &order_hash, b"".as_slice()].concat(); + // Mirror the on-chain check in `verify_readable`: the signed message is the + // ``-wrapped canonical readable rendering of the order. + let msg = crate::pallet::Pallet::::render_order(order); + let payload = [b"".as_slice(), &msg, b"".as_slice()].concat(); let sig = sp_io::crypto::sr25519_sign(sp_core::crypto::key_types::ACCOUNT, &public, &payload) .unwrap(); crate::SignedOrder { diff --git a/pallets/limit-orders/src/lib.rs b/pallets/limit-orders/src/lib.rs index 2216794887..ada685736c 100644 --- a/pallets/limit-orders/src/lib.rs +++ b/pallets/limit-orders/src/lib.rs @@ -206,10 +206,25 @@ pub mod pallet { transactional, }; use frame_system::pallet_prelude::*; + use alloc::format; + use alloc::string::String; use sp_runtime::traits::AccountIdConversion; use sp_std::collections::btree_set::BTreeSet; use sp_std::vec::Vec; + /// SS58 address format prefix used when rendering an `AccountId` into the + /// human-readable ("clear-signing") message that hardware wallets display. + /// + /// This is Bittensor's registered SS58 prefix (42). It fits in a single byte + /// because it is ≤ 63, which lets `render_account` use the simple single-byte + /// SS58 encoding path. + /// + /// INVARIANT: this MUST match the SS58 prefix constant used by the + /// frontend/wallet that produces the readable signing payload; otherwise the + /// rendered account strings — and therefore the whole signed message — will + /// differ and signature verification will fail. + const SS58_PREFIX: u8 = 42; + #[pallet::pallet] pub struct Pallet(_); @@ -637,6 +652,116 @@ pub mod pallet { .verify(payload.as_slice(), &order.signer) } + /// Render `who` into its SS58 (base58check) string using Bittensor's + /// [`SS58_PREFIX`], reproducing `Ss58Codec::to_ss58check_with_version` for a + /// single-byte prefix. + /// + /// We do the encoding manually rather than calling `to_ss58check` because that + /// method is gated behind sp-core's `serde` (`full_crypto`/`std`) feature and is + /// not reliably available in the no_std/wasm runtime build. + /// + /// `who.encode()` on `AccountId32` yields exactly 32 bytes; with the 1-byte + /// prefix and 2-byte checksum the output buffer is 35 bytes. + pub(crate) fn render_account(who: &T::AccountId) -> String { + let raw = who.encode(); // 32 bytes (AccountId32) + let mut buf = Vec::with_capacity(35); + buf.push(SS58_PREFIX); + buf.extend_from_slice(&raw); + let h = sp_core::hashing::blake2_512( + &[b"SS58PRE".as_slice(), buf.as_slice()].concat(), + ); + buf.extend_from_slice(&h[0..2]); // 2-byte checksum + bs58::encode(buf).into_string() + } + + /// Build the canonical, single-line, all-printable-ASCII "clear-signing" + /// message for a versioned order. + /// + /// This is a PURE function of the order's fields: every token is a + /// deterministic rendering of a runtime field, so a TS frontend can rebuild + /// the exact same bytes and have a hardware wallet display and sign them. + /// + /// The `none` vs `[]` distinction for the relayer field is deliberate and + /// load-bearing: it prevents a signature produced for an "any relayer" order + /// from being transplanted onto an "empty relayer list" order (or vice versa). + pub(crate) fn render_order(order: &VersionedOrder) -> Vec { + let (version, o) = match order { + VersionedOrder::V1(o) => ("v1", o), + }; + + let label = match o.order_type { + OrderType::LimitBuy => "Limit buy", + OrderType::TakeProfit => "Take-profit", + OrderType::StopLoss => "Stop-loss", + }; + let price_word = match o.order_type { + OrderType::LimitBuy => "limit price", + OrderType::TakeProfit | OrderType::StopLoss => "trigger price", + }; + + let netuid: u16 = u16::from(o.netuid); + + let max_slippage = match o.max_slippage { + None => String::from("none"), + Some(p) => format!("{}", p.deconstruct()), + }; + + let relayer = match &o.relayer { + None => String::from("none"), + Some(list) if list.is_empty() => String::from("[]"), + Some(list) => { + let mut acc = String::new(); + for (i, r) in list.iter().enumerate() { + if i > 0 { + acc.push('+'); + } + acc.push_str(&Self::render_account(r)); + } + acc + } + }; + + let msg = format!( + "TAO.com order {version}: {label} {amount} on subnet {netuid}, \ +{price_word} {limit_price}, expiry {expiry}, hotkey {hotkey}, \ +fee {fee_rate} to {fee_recipient}, relayer {relayer}, \ +max slippage {max_slippage}, chain {chain_id}, \ +partial fills {partial}, signer {signer}", + version = version, + label = label, + amount = o.amount, + netuid = netuid, + price_word = price_word, + limit_price = o.limit_price, + expiry = o.expiry, + hotkey = Self::render_account(&o.hotkey), + fee_rate = o.fee_rate.deconstruct(), + fee_recipient = Self::render_account(&o.fee_recipient), + relayer = relayer, + max_slippage = max_slippage, + chain_id = o.chain_id, + partial = o.partial_fills_enabled, + signer = Self::render_account(&o.signer), + ); + + msg.into_bytes() + } + + /// Verify the signature over the **human-readable** ("clear-signing") message — + /// the form a hardware wallet (Ledger) can display to the user field-by-field + /// and sign. The signed payload is the ``-wrapped canonical message built + /// by [`render_order`] (the `signRaw`/Ledger envelope). Accepts sr25519 and + /// ed25519; rejects ecdsa. + pub(crate) fn verify_readable(signed_order: &SignedOrder) -> bool { + let order = signed_order.order.inner(); + let msg = Self::render_order(&signed_order.order); + let payload = [b"".as_slice(), &msg, b"".as_slice()].concat(); + matches!( + signed_order.signature, + MultiSignature::Sr25519(_) | MultiSignature::Ed25519(_) + ) && signed_order.signature.verify(payload.as_slice(), &order.signer) + } + /// Validates all execution preconditions for a signed order. /// Checks that the order's netuid is not root (0), that the signature is valid, /// the order has not been processed, is not expired, and the price condition is met. @@ -660,10 +785,15 @@ pub mod pallet { // hash). Both are checked so software wallets signing raw bytes and hardware // wallets that can only sign wrapped messages are simultaneously supported. // The raw form is checked first: it short-circuits the common relayer flow, - // and an order signed in the wrapped form falls through to a second verify, - // which is the two-verification worst case the weights must account for. + // and an order signed in the wrapped form falls through to a second verify. + // The human-readable ("clear-signing") form is checked LAST: it is the least + // common and involves the SS58/format rendering work, so it should only run + // on fall-through. Exercising all three verifications is the worst case the + // weights must account for. ensure!( - Self::verify_order(signed_order) || Self::verify_wrapped(signed_order, order_id), + Self::verify_order(signed_order) + || Self::verify_wrapped(signed_order, order_id) + || Self::verify_readable(signed_order), Error::::InvalidSignature ); let order_status = Orders::::get(order_id); diff --git a/pallets/limit-orders/src/tests/mod.rs b/pallets/limit-orders/src/tests/mod.rs index 95e0875b26..b9b2037652 100644 --- a/pallets/limit-orders/src/tests/mod.rs +++ b/pallets/limit-orders/src/tests/mod.rs @@ -2,3 +2,4 @@ pub mod auxiliary; pub mod extrinsics; pub mod migration; pub mod mock; +pub mod readable; diff --git a/pallets/limit-orders/src/tests/readable.rs b/pallets/limit-orders/src/tests/readable.rs new file mode 100644 index 0000000000..9a68beccea --- /dev/null +++ b/pallets/limit-orders/src/tests/readable.rs @@ -0,0 +1,593 @@ +#![allow(clippy::expect_used, clippy::unwrap_used, clippy::indexing_slicing)] +//! Unit tests for the human-readable ("clear-signing") signature path in +//! `pallet-limit-orders`: `render_account`, `render_order`, `verify_readable`, +//! and their acceptance/rejection through `is_order_valid`. +//! +//! These exercise the third verification branch +//! (`verify_order || verify_wrapped || verify_readable`), the SS58 rendering that +//! feeds it, the injectivity of the canonical message (a change to ANY order field +//! must produce a different message and therefore break the original signature), +//! and the deliberate `none` vs `[]` relayer-rendering distinction. + +use frame_support::{BoundedVec, assert_noop, assert_ok, traits::ConstU32}; +use sp_core::{H256, Pair}; +use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; +use sp_keyring::Sr25519Keyring as AccountKeyring; +use sp_runtime::{MultiSignature, Perbill}; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::OrderSwapInterface; + +use crate::pallet::Pallet as LimitOrders; +use crate::{Error, Order, OrderType, VersionedOrder}; + +use super::mock::*; + +/// The SS58 prefix the pallet renders accounts under. Must match `SS58_PREFIX` +/// in `lib.rs`. Tests reconstruct the expected SS58 strings independently using +/// `sp-core`'s canonical codec at this same version. +const SS58_PREFIX: u16 = 42; + +/// Canonical `Ss58Codec` reconstruction of an account, used as the independent +/// oracle against the pallet's hand-rolled `render_account`. +fn canonical_ss58(acct: &AccountId) -> String { + acct.to_ss58check_with_version(Ss58AddressFormat::custom(SS58_PREFIX)) +} + +/// Build the payload the readable path signs: the `` `signRaw` +/// envelope wrapped around the canonical clear-signing message. Reconstructed +/// here from the same rendering the pallet uses so the test signs exactly what +/// `verify_readable` verifies. +fn readable_signing_payload(order: &VersionedOrder) -> Vec { + let msg = LimitOrders::::render_order(order); + [b"".as_slice(), &msg, b"".as_slice()].concat() +} + +/// A fully-specified LimitBuy order that passes every non-signature guard in +/// `is_order_valid` under the default mock setup (netuid 1, chain 945, far-future +/// expiry, no relayer restriction, price condition met at price 1.0). +fn base_buy_order() -> Order { + Order { + signer: alice(), + hotkey: bob(), + netuid: netuid(), + order_type: OrderType::LimitBuy, + amount: 1_000, + limit_price: u64::MAX, + expiry: u64::MAX, + fee_rate: Perbill::zero(), + fee_recipient: fee_recipient(), + relayer: None, + max_slippage: None, + chain_id: 945, + partial_fills_enabled: false, + } +} + +/// Sign `order` with the readable (`` ++ render_order ++ ``) form +/// using an sr25519 keyring. The `order.signer` must correspond to `keyring`. +fn make_readable_signed_order( + keyring: AccountKeyring, + order: Order, +) -> crate::SignedOrder { + let versioned = VersionedOrder::V1(order); + let sig = keyring.pair().sign(&readable_signing_payload(&versioned)); + crate::SignedOrder { + order: versioned, + signature: MultiSignature::Sr25519(sig), + partial_fill: None, + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// A. SS58 correctness cross-check +// ───────────────────────────────────────────────────────────────────────────── + +#[test] +fn render_account_matches_canonical_ss58_codec() { + new_test_ext().execute_with(|| { + let cases = vec![ + alice(), + bob(), + AccountId::new([0x00; 32]), + AccountId::new([0xff; 32]), + ]; + for acct in cases { + let rendered = LimitOrders::::render_account(&acct); + let canonical = canonical_ss58(&acct); + assert_eq!( + rendered, canonical, + "manual SS58 rendering must match sp-core Ss58Codec for {acct:?}" + ); + } + }); +} + +// ───────────────────────────────────────────────────────────────────────────── +// B. render_order golden vectors +// ───────────────────────────────────────────────────────────────────────────── + +/// Independently reconstruct the canonical message from the order's fields using +/// the SS58 oracle. Deliberately NOT a copy of production `format!`. +fn expected_message( + label: &str, + price_word: &str, + amount: u64, + netuid_val: u16, + limit_price: u64, + expiry: u64, + hotkey: &AccountId, + fee_rate_ppb: u32, + fee_recipient: &AccountId, + relayer_str: &str, + max_slippage_str: &str, + chain_id: u64, + partial: bool, + signer: &AccountId, +) -> String { + format!( + "TAO.com order v1: {label} {amount} on subnet {netuid_val}, \ +{price_word} {limit_price}, expiry {expiry}, hotkey {hotkey}, \ +fee {fee_rate_ppb} to {fee_recipient}, relayer {relayer_str}, \ +max slippage {max_slippage_str}, chain {chain_id}, \ +partial fills {partial}, signer {signer}", + hotkey = canonical_ss58(hotkey), + fee_recipient = canonical_ss58(fee_recipient), + signer = canonical_ss58(signer), + ) +} + +fn assert_all_printable_ascii(bytes: &[u8]) { + for (i, b) in bytes.iter().enumerate() { + assert!( + (0x20..=0x7e).contains(b), + "byte {i} = {b:#x} is not printable ASCII (Ledger-renderability invariant)" + ); + } +} + +#[test] +fn render_order_golden_limit_buy_relayer_none() { + new_test_ext().execute_with(|| { + let order = Order { + signer: alice(), + hotkey: bob(), + netuid: NetUid::from(7u16), + order_type: OrderType::LimitBuy, + amount: 1_234_567, + limit_price: 2_000_000_000, + expiry: 9_999_999, + fee_rate: Perbill::from_parts(5_000_000), + fee_recipient: fee_recipient(), + relayer: None, + max_slippage: None, + chain_id: 945, + partial_fills_enabled: false, + }; + let versioned = VersionedOrder::V1(order); + let rendered = LimitOrders::::render_order(&versioned); + let expected = expected_message( + "Limit buy", + "limit price", + 1_234_567, + 7, + 2_000_000_000, + 9_999_999, + &bob(), + 5_000_000, + &fee_recipient(), + "none", + "none", + 945, + false, + &alice(), + ); + assert_eq!(String::from_utf8(rendered.clone()).unwrap(), expected); + assert_all_printable_ascii(&rendered); + }); +} + +#[test] +fn render_order_golden_stop_loss_trigger_price_and_slippage() { + new_test_ext().execute_with(|| { + // StopLoss → label "Stop-loss", price word "trigger price". + // max_slippage Some(1%) → "10000000" ppb. + let order = Order { + signer: charlie(), + hotkey: dave(), + netuid: NetUid::from(2u16), + order_type: OrderType::StopLoss, + amount: 500, + limit_price: 750_000_000, + expiry: 42, + fee_rate: Perbill::zero(), + fee_recipient: alice(), + relayer: None, + max_slippage: Some(Perbill::from_percent(1)), + chain_id: 945, + partial_fills_enabled: true, + }; + let versioned = VersionedOrder::V1(order); + let rendered = LimitOrders::::render_order(&versioned); + let expected = expected_message( + "Stop-loss", + "trigger price", + 500, + 2, + 750_000_000, + 42, + &dave(), + 0, + &alice(), + "none", + &Perbill::from_percent(1).deconstruct().to_string(), + 945, + true, + &charlie(), + ); + assert_eq!(String::from_utf8(rendered.clone()).unwrap(), expected); + assert_all_printable_ascii(&rendered); + }); +} + +#[test] +fn render_order_golden_take_profit_two_relayers() { + new_test_ext().execute_with(|| { + // Take-profit → label "Take-profit", price word "trigger price". + // Two-relayer list → rendered accounts joined with '+'. + let relayers: BoundedVec> = + BoundedVec::try_from(vec![bob(), charlie()]).unwrap(); + let order = Order { + signer: alice(), + hotkey: dave(), + netuid: NetUid::from(1u16), + order_type: OrderType::TakeProfit, + amount: 88, + limit_price: 1_000_000_000, + expiry: 100_000, + fee_rate: Perbill::from_parts(1), + fee_recipient: fee_recipient(), + relayer: Some(relayers), + max_slippage: None, + chain_id: 945, + partial_fills_enabled: false, + }; + let versioned = VersionedOrder::V1(order); + let rendered = LimitOrders::::render_order(&versioned); + let relayer_str = format!("{}+{}", canonical_ss58(&bob()), canonical_ss58(&charlie())); + let expected = expected_message( + "Take-profit", + "trigger price", + 88, + 1, + 1_000_000_000, + 100_000, + &dave(), + 1, + &fee_recipient(), + &relayer_str, + "none", + 945, + false, + &alice(), + ); + assert_eq!(String::from_utf8(rendered.clone()).unwrap(), expected); + assert_all_printable_ascii(&rendered); + }); +} + +#[test] +fn render_order_golden_relayer_empty_list() { + new_test_ext().execute_with(|| { + // Some(empty) must render as "[]", distinct from None → "none". + let empty: BoundedVec> = BoundedVec::try_from(vec![]).unwrap(); + let order = Order { + relayer: Some(empty), + ..base_buy_order() + }; + let versioned = VersionedOrder::V1(order); + let rendered = LimitOrders::::render_order(&versioned); + let expected = expected_message( + "Limit buy", + "limit price", + 1_000, + u16::from(netuid()), + u64::MAX, + u64::MAX, + &bob(), + 0, + &fee_recipient(), + "[]", + "none", + 945, + false, + &alice(), + ); + assert_eq!(String::from_utf8(rendered.clone()).unwrap(), expected); + assert_all_printable_ascii(&rendered); + }); +} + +// ───────────────────────────────────────────────────────────────────────────── +// C. verify_readable / is_order_valid accepts a readable-signed order +// ───────────────────────────────────────────────────────────────────────────── + +#[test] +fn is_order_valid_accepts_readable_sr25519_signature() { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + let order = base_buy_order(); + let signed = make_readable_signed_order(AccountKeyring::Alice, order); + let id = LimitOrders::::derive_order_id(&signed.order); + + // Direct branch check. + assert!( + LimitOrders::::verify_readable(&signed), + "readable-signed order must pass verify_readable" + ); + // And through the full validation chain. + let price = MockSwap::current_alpha_price(netuid()); + assert_ok!(LimitOrders::::is_order_valid( + &signed, + id, + 1_000_000, + price, + &bob() + )); + }); +} + +#[test] +fn is_order_valid_accepts_readable_ed25519_signature() { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + // The signer field must be the ed25519 public key for verification. + let ed_pair = sp_core::ed25519::Pair::from_legacy_string("//Alice", None); + let ed_signer = AccountId::from(ed_pair.public()); + + let order = Order { + signer: ed_signer, + ..base_buy_order() + }; + let versioned = VersionedOrder::V1(order); + let ed_sig = ed_pair.sign(&readable_signing_payload(&versioned)); + let signed = crate::SignedOrder { + order: versioned, + signature: MultiSignature::Ed25519(ed_sig), + partial_fill: None, + }; + let id = LimitOrders::::derive_order_id(&signed.order); + + assert!( + LimitOrders::::verify_readable(&signed), + "ed25519 readable-signed order must pass verify_readable" + ); + let price = MockSwap::current_alpha_price(netuid()); + assert_ok!(LimitOrders::::is_order_valid( + &signed, + id, + 1_000_000, + price, + &bob() + )); + }); +} + +// ───────────────────────────────────────────────────────────────────────────── +// D. Per-field mutation sweep (injectivity of the canonical message) +// ───────────────────────────────────────────────────────────────────────────── +// +// Sign a readable order, then for EACH order field build a clone that changes +// ONLY that field while KEEPING the original signature. The mutated order renders +// to a different message, so verify_readable (and verify_order / verify_wrapped) +// all fail → is_order_valid returns InvalidSignature — except where an earlier +// guard fires first (netuid==root, chain_id!=configured), noted per case. + +/// Sign `base` readably, then swap in `mutated` (same signer) while KEEPING the +/// signature computed over `base`'s rendered message. +fn transplant_signature( + keyring: AccountKeyring, + base: Order, + mutated: Order, +) -> (crate::SignedOrder, H256) { + let signed_base = make_readable_signed_order(keyring, base); + let versioned = VersionedOrder::V1(mutated); + let id = LimitOrders::::derive_order_id(&versioned); + let signed = crate::SignedOrder { + order: versioned, + signature: signed_base.signature, + partial_fill: None, + }; + (signed, id) +} + +/// Run a mutation whose only changed field is `mutate(base)`, asserting the +/// transplanted signature is rejected as InvalidSignature. +fn assert_field_mutation_rejected(mutate: impl FnOnce(&mut Order)) { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + let base = base_buy_order(); + let mut mutated = base.clone(); + mutate(&mut mutated); + assert_ne!( + base, mutated, + "mutation must actually change the order (test bug otherwise)" + ); + + let (signed, id) = transplant_signature(AccountKeyring::Alice, base, mutated); + let price = MockSwap::current_alpha_price(netuid()); + assert_noop!( + LimitOrders::::is_order_valid(&signed, id, 1_000_000, price, &bob()), + Error::::InvalidSignature + ); + }); +} + +#[test] +fn mutation_signer_rejected() { + // New signer renders differently AND the sig is verified against the new + // signer's key → InvalidSignature. netuid non-root, chain_id 945 keep the + // signature check reachable. + assert_field_mutation_rejected(|o| o.signer = bob()); +} + +#[test] +fn mutation_hotkey_rejected() { + assert_field_mutation_rejected(|o| o.hotkey = charlie()); +} + +#[test] +fn mutation_netuid_rejected() { + // Mutate to a NON-root netuid (2) so RootNetUidNotAllowed does not pre-empt + // the signature check. + assert_field_mutation_rejected(|o| o.netuid = NetUid::from(2u16)); +} + +#[test] +fn mutation_order_type_rejected() { + // LimitBuy → StopLoss changes both label and price word in the message. + assert_field_mutation_rejected(|o| o.order_type = OrderType::StopLoss); +} + +#[test] +fn mutation_amount_rejected() { + assert_field_mutation_rejected(|o| o.amount = 2_000); +} + +#[test] +fn mutation_limit_price_rejected() { + assert_field_mutation_rejected(|o| o.limit_price = u64::MAX - 1); +} + +#[test] +fn mutation_expiry_rejected() { + assert_field_mutation_rejected(|o| o.expiry = u64::MAX - 1); +} + +#[test] +fn mutation_fee_rate_rejected() { + assert_field_mutation_rejected(|o| o.fee_rate = Perbill::from_parts(1)); +} + +#[test] +fn mutation_fee_recipient_rejected() { + assert_field_mutation_rejected(|o| o.fee_recipient = charlie()); +} + +#[test] +fn mutation_relayer_rejected() { + // None → Some([charlie]) changes the relayer rendering. + assert_field_mutation_rejected(|o| { + o.relayer = Some(BoundedVec::try_from(vec![charlie()]).unwrap()) + }); +} + +#[test] +fn mutation_max_slippage_rejected() { + // None → Some(1%) changes "none" → "10000000". + assert_field_mutation_rejected(|o| o.max_slippage = Some(Perbill::from_percent(1))); +} + +#[test] +fn mutation_partial_fills_enabled_rejected() { + assert_field_mutation_rejected(|o| o.partial_fills_enabled = true); +} + +#[test] +fn mutation_chain_id_pre_empted_by_chain_id_guard() { + // NOTE: chain_id is validated BEFORE the signature in `is_order_valid` + // (`ensure!(order.chain_id == T::ChainId::get(), ChainIdMismatch)`). + // Any change to chain_id makes it != 945, so ChainIdMismatch is reached + // first and InvalidSignature is NOT reachable for this field. We assert the + // specific reachable error instead. (The message still renders differently, + // so the signature would also fail — but the guard short-circuits.) + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + let base = base_buy_order(); + let mutated = Order { + chain_id: 946, + ..base.clone() + }; + let (signed, id) = transplant_signature(AccountKeyring::Alice, base, mutated); + let price = MockSwap::current_alpha_price(netuid()); + assert_noop!( + LimitOrders::::is_order_valid(&signed, id, 1_000_000, price, &bob()), + Error::::ChainIdMismatch + ); + }); +} + +// ───────────────────────────────────────────────────────────────────────────── +// E. Relayer None-vs-empty transplant +// ───────────────────────────────────────────────────────────────────────────── + +#[test] +fn relayer_none_to_empty_transplant_rejected() { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + // Sign with relayer: None ("none"). + let base = Order { + relayer: None, + ..base_buy_order() + }; + // Transplant onto relayer: Some(empty) ("[]"). The `none` vs `[]` rendering + // distinction must make the message — and therefore the signature — differ. + let empty: BoundedVec> = BoundedVec::try_from(vec![]).unwrap(); + let mutated = Order { + relayer: Some(empty), + ..base_buy_order() + }; + assert_ne!(base, mutated, "None and Some(empty) must differ"); + + let (signed, id) = transplant_signature(AccountKeyring::Alice, base, mutated); + let price = MockSwap::current_alpha_price(netuid()); + assert_noop!( + LimitOrders::::is_order_valid(&signed, id, 1_000_000, price, &bob()), + Error::::InvalidSignature + ); + }); +} + +// ───────────────────────────────────────────────────────────────────────────── +// F. ecdsa rejected on the readable path +// ───────────────────────────────────────────────────────────────────────────── + +#[test] +fn readable_ecdsa_signature_rejected() { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + // A well-formed ecdsa signature over the correct readable payload must + // still be rejected: only sr25519 and ed25519 are accepted. + let order = base_buy_order(); + let versioned = VersionedOrder::V1(order); + let ecdsa_pair = sp_core::ecdsa::Pair::from_legacy_string("//Alice", None); + let ecdsa_sig = ecdsa_pair.sign(&readable_signing_payload(&versioned)); + let signed = crate::SignedOrder { + order: versioned, + signature: MultiSignature::Ecdsa(ecdsa_sig), + partial_fill: None, + }; + let id = LimitOrders::::derive_order_id(&signed.order); + + assert!( + !LimitOrders::::verify_readable(&signed), + "ecdsa signature must not pass verify_readable" + ); + let price = MockSwap::current_alpha_price(netuid()); + assert_noop!( + LimitOrders::::is_order_valid(&signed, id, 1_000_000, price, &bob()), + Error::::InvalidSignature + ); + }); +} diff --git a/runtime/tests/limit_orders.rs b/runtime/tests/limit_orders.rs index 274ccd44bf..6bc977a236 100644 --- a/runtime/tests/limit_orders.rs +++ b/runtime/tests/limit_orders.rs @@ -19,6 +19,7 @@ use pallet_limit_orders::{ }; use pallet_subtensor::{SubnetAlphaIn, SubnetMechanism, SubnetTAO}; use sp_core::{Get, H256, Pair}; +use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; use sp_keyring::Sr25519Keyring; use sp_runtime::traits::AccountIdConversion; use sp_runtime::{MultiSignature, Perbill}; @@ -2748,3 +2749,127 @@ fn fee_failure_after_buy_rolls_back_swap() { ); }); } + +// ───────────────────────────────────────────────────────────────────────────── +// Human-readable ("clear-signing") signature path — runtime integration +// ───────────────────────────────────────────────────────────────────────────── + +/// Rebuild the pallet's canonical clear-signing message for an order. +/// +/// The pallet's `render_order` is `pub(crate)` and not reachable from this +/// integration crate, so we reconstruct the exact byte-for-byte message here +/// (SS58 prefix 42, single-line, `, `-separated fields). If this drifts from the +/// pallet's `render_order`, the signature over it will simply fail to verify — +/// which is exactly the invariant this test would then catch. +fn render_order_readable(order: &Order) -> Vec { + fn ss58(a: &AccountId) -> String { + a.to_ss58check_with_version(Ss58AddressFormat::custom(42)) + } + let (label, price_word) = match order.order_type { + OrderType::LimitBuy => ("Limit buy", "limit price"), + OrderType::TakeProfit => ("Take-profit", "trigger price"), + OrderType::StopLoss => ("Stop-loss", "trigger price"), + }; + let max_slippage = match order.max_slippage { + None => "none".to_string(), + Some(p) => p.deconstruct().to_string(), + }; + let relayer = match &order.relayer { + None => "none".to_string(), + Some(list) if list.is_empty() => "[]".to_string(), + Some(list) => list + .iter() + .map(ss58) + .collect::>() + .join("+"), + }; + let netuid: u16 = u16::from(order.netuid); + format!( + "TAO.com order v1: {label} {amount} on subnet {netuid}, \ +{price_word} {limit_price}, expiry {expiry}, hotkey {hotkey}, \ +fee {fee_rate} to {fee_recipient}, relayer {relayer}, \ +max slippage {max_slippage}, chain {chain_id}, \ +partial fills {partial}, signer {signer}", + amount = order.amount, + limit_price = order.limit_price, + expiry = order.expiry, + hotkey = ss58(&order.hotkey), + fee_rate = order.fee_rate.deconstruct(), + fee_recipient = ss58(&order.fee_recipient), + chain_id = order.chain_id, + partial = order.partial_fills_enabled, + signer = ss58(&order.signer), + ) + .into_bytes() +} + +/// End-to-end: a LimitBuy order signed with the human-readable ("clear-signing") +/// payload — `` ++ render_order ++ `` — executes through +/// `execute_batched_orders`, is marked Fulfilled, and credits staked alpha to the +/// signer. Exercises the `verify_readable` acceptance branch against the real +/// runtime (chain_id 0). +#[test] +fn execute_batched_orders_readable_signature_executes() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(1u16); + let alice = Sr25519Keyring::Alice; + let alice_id = alice.to_account_id(); + let bob_id = Sr25519Keyring::Bob.to_account_id(); + let charlie_id = Sr25519Keyring::Charlie.to_account_id(); + + setup_subnet(netuid); + fund_account(&alice_id); + let _ = SubtensorModule::create_account_if_non_existent(&alice_id, &bob_id); + + // Build the order manually and sign the readable clear-signing message. + let inner = Order { + signer: alice_id.clone(), + hotkey: bob_id.clone(), + netuid, + order_type: OrderType::LimitBuy, + amount: min_default_stake().into(), + limit_price: u64::MAX, + expiry: u64::MAX, + fee_rate: Perbill::zero(), + fee_recipient: charlie_id.clone(), + relayer: None, + max_slippage: None, + partial_fills_enabled: false, + // chain_id 0 matches the default pallet_evm_chain_id genesis value in tests + chain_id: 0, + }; + let order = VersionedOrder::V1(inner.clone()); + let id = order_id(&order); + + let msg = render_order_readable(&inner); + let payload = [b"".as_slice(), &msg, b"".as_slice()].concat(); + let sig = alice.pair().sign(&payload); + let signed = SignedOrder { + order, + signature: MultiSignature::Sr25519(sig), + partial_fill: None, + }; + + let orders = make_order_batch(vec![signed]); + + assert_ok!(LimitOrders::execute_batched_orders( + RuntimeOrigin::signed(charlie_id), + netuid, + orders, + )); + + // Order must be marked as executed. + assert_eq!(Orders::::get(id), Some(OrderStatus::Fulfilled)); + + // Alice must now hold staked alpha delegated through Bob (within 1% for + // AMM slippage), proving the readable-signed order was accepted and ran. + let staked = + SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(&bob_id, &alice_id, netuid); + let expected_alpha = min_default_stake().to_u64(); + assert!( + staked >= AlphaBalance::from(expected_alpha * 99 / 100) + && staked <= AlphaBalance::from(expected_alpha), + "alice should hold approximately min_default_stake alpha after a readable-signed LimitBuy executes (got {staked:?})" + ); + }); +} diff --git a/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-readable.ts b/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-readable.ts new file mode 100644 index 0000000000..7bdfa7b82b --- /dev/null +++ b/ts-tests/suites/dev/subtensor/limit-orders/test-execute-orders-readable.ts @@ -0,0 +1,164 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import type { ApiPromise } from "@polkadot/api"; +import type { KeyringPair } from "@moonwall/util"; +import { tao, generateKeyringPair } from "../../../../utils"; +import { + devForceSetBalance, + devGetAlphaStake, + devAssociateHotKey, + devEnableSubtoken, + devRegisterSubnet, + devSudoSetLockReductionInterval, +} from "../../../../utils/dev-helpers.js"; +import { + buildReadableSignedOrder, + FAR_FUTURE, + fetchChainId, + filterEvents, + getOrderStatus, + orderId, + registerLimitOrderTypes, +} from "../../../../utils/limit-orders.js"; + +// One subnet per file — this test submits real buy orders signed over the +// ``-wrapped canonical human-readable ("clear-signing") message, the +// form a hardware wallet (Ledger) displays field-by-field. It exercises the +// runtime's `verify_readable` path: +// signature.verify(b"" ++ utf8(render_order(order)) ++ b"", signer) +// for BOTH an ed25519 signer (the hardware/Ledger case) and an sr25519 signer. +// Both orders are relayed/submitted by Alice via execute_batched_orders. + +describeSuite({ + id: "DEV_SUB_LIMIT_ORDERS_READABLE", + title: "execute_batched_orders — human-readable (clear-signing) LimitBuy execution", + foundationMethods: "dev", + testCases: ({ it, context }) => { + let polkadotJs: ApiPromise; + let alice: KeyringPair; + let aliceHotKey: KeyringPair; + let edSigner: KeyringPair; + let edHotKey: KeyringPair; + let srSigner: KeyringPair; + let srHotKey: KeyringPair; + let netuid: number; + let chainId: bigint; + + beforeAll(async () => { + polkadotJs = context.polkadotJs(); + + alice = context.keyring.alice; + aliceHotKey = generateKeyringPair("sr25519"); + + // ed25519 coldkey/signer (hardware / Ledger case) with an sr25519 hotkey. + edSigner = generateKeyringPair("ed25519"); + edHotKey = generateKeyringPair("sr25519"); + + // sr25519 coldkey/signer with its own sr25519 hotkey. + srSigner = generateKeyringPair("sr25519"); + srHotKey = generateKeyringPair("sr25519"); + + registerLimitOrderTypes(polkadotJs); + chainId = await fetchChainId(polkadotJs); + + await devForceSetBalance(polkadotJs, context, alice.address, tao(10_000)); + await devForceSetBalance(polkadotJs, context, edSigner.address, tao(10_000)); + await devForceSetBalance(polkadotJs, context, srSigner.address, tao(10_000)); + + await devSudoSetLockReductionInterval(polkadotJs, context, alice, 1); + + netuid = await devRegisterSubnet(polkadotJs, context, alice, aliceHotKey); + + await devEnableSubtoken(polkadotJs, context, alice, netuid); + + // Associate hotkeys — each signer associates its own hotkey. + await devAssociateHotKey(polkadotJs, context, alice, aliceHotKey.address); + await devAssociateHotKey(polkadotJs, context, edSigner, edHotKey.address); + await devAssociateHotKey(polkadotJs, context, srSigner, srHotKey.address); + }); + + it({ + id: "T01", + title: "LimitBuy executes with an ed25519 readable (clear-signing) signature", + test: async () => { + const stakeBefore = await devGetAlphaStake(polkadotJs, edHotKey.address, edSigner.address, netuid); + const taoBalanceBefore = (await polkadotJs.query.system.account(edSigner.address)).data.free.toBigInt(); + + const signed = buildReadableSignedOrder(polkadotJs, { + signer: edSigner, + hotkey: edHotKey.address, + netuid, + orderType: "LimitBuy", + amount: tao(100), + limitPrice: FAR_FUTURE, + expiry: FAR_FUTURE, + feeRate: 0, + feeRecipient: edSigner.address, + chainId, + }); + + // Alice relays/submits the ed25519 readable-signed order. + const { + result: [attempt], + } = await context.createBlock([ + await polkadotJs.tx.limitOrders.executeBatchedOrders(netuid, [signed]).signAsync(alice), + ]); + expect(attempt.successful).toEqual(true); + + const events = await polkadotJs.query.system.events(); + expect(filterEvents(events, "OrderExecuted").length).toBe(1); + + const id = orderId(polkadotJs, signed.order); + expect(await getOrderStatus(polkadotJs, id)).toBe("Fulfilled"); + + // Alpha stake for the ed25519 signer's hotkey should have increased. + const stakeAfter = await devGetAlphaStake(polkadotJs, edHotKey.address, edSigner.address, netuid); + expect(stakeAfter).toBeGreaterThan(stakeBefore); + + // ed25519 signer's TAO balance should have decreased. + const taoBalanceAfter = (await polkadotJs.query.system.account(edSigner.address)).data.free.toBigInt(); + expect(taoBalanceAfter).toBeLessThan(taoBalanceBefore); + }, + }); + + it({ + id: "T02", + title: "LimitBuy executes with an sr25519 readable (clear-signing) signature", + test: async () => { + const stakeBefore = await devGetAlphaStake(polkadotJs, srHotKey.address, srSigner.address, netuid); + const taoBalanceBefore = (await polkadotJs.query.system.account(srSigner.address)).data.free.toBigInt(); + + const signed = buildReadableSignedOrder(polkadotJs, { + signer: srSigner, + hotkey: srHotKey.address, + netuid, + orderType: "LimitBuy", + amount: tao(100), + limitPrice: FAR_FUTURE, + expiry: FAR_FUTURE, + feeRate: 0, + feeRecipient: srSigner.address, + chainId, + }); + + const { + result: [attempt], + } = await context.createBlock([ + await polkadotJs.tx.limitOrders.executeBatchedOrders(netuid, [signed]).signAsync(alice), + ]); + expect(attempt.successful).toEqual(true); + + const events = await polkadotJs.query.system.events(); + expect(filterEvents(events, "OrderExecuted").length).toBe(1); + + const id = orderId(polkadotJs, signed.order); + expect(await getOrderStatus(polkadotJs, id)).toBe("Fulfilled"); + + const stakeAfter = await devGetAlphaStake(polkadotJs, srHotKey.address, srSigner.address, netuid); + expect(stakeAfter).toBeGreaterThan(stakeBefore); + + const taoBalanceAfter = (await polkadotJs.query.system.account(srSigner.address)).data.free.toBigInt(); + expect(taoBalanceAfter).toBeLessThan(taoBalanceBefore); + }, + }); + }, +}); diff --git a/ts-tests/suites/dev/subtensor/limit-orders/test-readable-message-format.ts b/ts-tests/suites/dev/subtensor/limit-orders/test-readable-message-format.ts new file mode 100644 index 0000000000..2abcc0a31b --- /dev/null +++ b/ts-tests/suites/dev/subtensor/limit-orders/test-readable-message-format.ts @@ -0,0 +1,193 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { Keyring } from "@polkadot/keyring"; +import { encodeAddress } from "@polkadot/util-crypto"; +import { + type Order, + type OrderType, + formatOrderMessage, + READABLE_SS58_PREFIX, +} from "../../../../utils/limit-orders.js"; + +// Byte-parity anchor for the canonical human-readable ("clear-signing") message. +// +// The runtime rebuilds this exact string in `render_order` and verifies the +// signature over `` ++ utf8(message) ++ ``. If the TS formatter +// drifts from the Rust one by a single byte, every readable-signed order breaks. +// These assertions pin the TS output against FULLY HARDCODED literals derived +// with a well-known dev key (sr25519 `//Alice` at prefix 42 is the canonical +// `5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY`), so the expected string is +// NOT derived from the same `encodeAddress` call it is testing. +// +// The field VALUES mirror the Rust golden vectors in +// `pallets/limit-orders/src/tests/readable.rs` so both suites pin identical +// output. + +// Known dev keys, sr25519, rendered at prefix 42. +const KR = new Keyring({ type: "sr25519" }); +const ALICE = KR.addFromUri("//Alice").address; // 5Grwva... +const BOB = KR.addFromUri("//Bob").address; // 5FHneW... +const CHARLIE = KR.addFromUri("//Charlie").address; // 5FLSig... +const DAVE = KR.addFromUri("//Dave").address; // 5DAAnr... + +// Hardcoded SS58 (prefix 42) of the dev keys — independent of the formatter. +const ALICE_SS58 = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"; +const BOB_SS58 = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"; +const CHARLIE_SS58 = "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"; +const DAVE_SS58 = "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy"; + +function makeOrder(overrides: Partial): Order { + return { + signer: ALICE, + hotkey: BOB, + netuid: 7, + order_type: "LimitBuy" as OrderType, + amount: 1_234_567n, + limit_price: 2_000_000_000n, + expiry: 9_999_999n, + fee_rate: 5_000_000, + fee_recipient: DAVE, + relayer: null, + max_slippage: null, + chain_id: 945n, + partial_fills_enabled: false, + ...overrides, + }; +} + +function assertAllPrintableAscii(s: string): void { + for (let i = 0; i < s.length; i++) { + const code = s.charCodeAt(i); + expect( + code >= 0x20 && code <= 0x7e, + `char ${i} = 0x${code.toString(16)} (${JSON.stringify(s[i])}) is not printable ASCII` + ).toBe(true); + } +} + +describeSuite({ + id: "DEV_SUB_LIMIT_ORDERS_READABLE_FORMAT", + title: "limit-orders — canonical human-readable message formatter parity", + foundationMethods: "dev", + testCases: ({ it }) => { + it({ + id: "T01", + title: "the well-known //Alice SS58 anchor is prefix 42", + test: () => { + // Sanity: the dev keyring already renders at prefix 42, and an + // explicit re-encode is idempotent — so both routes must equal + // the hardcoded literal. + expect(ALICE).toBe(ALICE_SS58); + expect(encodeAddress(ALICE, READABLE_SS58_PREFIX)).toBe(ALICE_SS58); + }, + }); + + it({ + id: "T02", + title: "LimitBuy with relayer none renders the exact golden string", + test: () => { + const msg = formatOrderMessage(makeOrder({})); + const expected = + "TAO.com order v1: Limit buy 1234567 on subnet 7, " + + "limit price 2000000000, expiry 9999999, " + + `hotkey ${BOB_SS58}, ` + + `fee 5000000 to ${DAVE_SS58}, ` + + "relayer none, max slippage none, chain 945, " + + `partial fills false, signer ${ALICE_SS58}`; + expect(msg).toBe(expected); + assertAllPrintableAscii(msg); + }, + }); + + it({ + id: "T03", + title: "StopLoss with max_slippage renders Stop-loss / trigger price", + test: () => { + const msg = formatOrderMessage( + makeOrder({ + signer: CHARLIE, + hotkey: DAVE, + netuid: 2, + order_type: "StopLoss", + amount: 500n, + limit_price: 750_000_000n, + expiry: 42n, + fee_rate: 0, + fee_recipient: ALICE, + relayer: null, + max_slippage: 10_000_000, // 1% in ppb + partial_fills_enabled: true, + }) + ); + const expected = + "TAO.com order v1: Stop-loss 500 on subnet 2, " + + "trigger price 750000000, expiry 42, " + + `hotkey ${DAVE_SS58}, ` + + `fee 0 to ${ALICE_SS58}, ` + + "relayer none, max slippage 10000000, chain 945, " + + `partial fills true, signer ${CHARLIE_SS58}`; + expect(msg).toBe(expected); + assertAllPrintableAscii(msg); + }, + }); + + it({ + id: "T04", + title: "TakeProfit with two relayers renders '+'-joined list", + test: () => { + const msg = formatOrderMessage( + makeOrder({ + signer: ALICE, + hotkey: DAVE, + netuid: 1, + order_type: "TakeProfit", + amount: 88n, + limit_price: 1_000_000_000n, + expiry: 100_000n, + fee_rate: 1, + fee_recipient: DAVE, + relayer: [BOB, CHARLIE], + max_slippage: null, + partial_fills_enabled: false, + }) + ); + const expected = + "TAO.com order v1: Take-profit 88 on subnet 1, " + + "trigger price 1000000000, expiry 100000, " + + `hotkey ${DAVE_SS58}, ` + + `fee 1 to ${DAVE_SS58}, ` + + `relayer ${BOB_SS58}+${CHARLIE_SS58}, ` + + "max slippage none, chain 945, " + + `partial fills false, signer ${ALICE_SS58}`; + expect(msg).toBe(expected); + assertAllPrintableAscii(msg); + }, + }); + + it({ + id: "T05", + title: "empty relayer array renders '[]' (distinct from none)", + test: () => { + const msg = formatOrderMessage( + makeOrder({ + order_type: "LimitBuy", + amount: 1_000n, + limit_price: 18_446_744_073_709_551_615n, // u64::MAX + expiry: 18_446_744_073_709_551_615n, // u64::MAX + fee_rate: 0, + relayer: [], + max_slippage: null, + }) + ); + const expected = + "TAO.com order v1: Limit buy 1000 on subnet 7, " + + "limit price 18446744073709551615, expiry 18446744073709551615, " + + `hotkey ${BOB_SS58}, ` + + `fee 0 to ${DAVE_SS58}, ` + + "relayer [], max slippage none, chain 945, " + + `partial fills false, signer ${ALICE_SS58}`; + expect(msg).toBe(expected); + assertAllPrintableAscii(msg); + }, + }); + }, +}); diff --git a/ts-tests/utils/limit-orders.ts b/ts-tests/utils/limit-orders.ts index e9ba6816c0..0ffc83a192 100644 --- a/ts-tests/utils/limit-orders.ts +++ b/ts-tests/utils/limit-orders.ts @@ -2,8 +2,8 @@ import type { KeyringPair } from "@moonwall/util"; import type { TypedApi } from "polkadot-api"; import type { subtensor } from "@polkadot-api/descriptors"; import { Keyring } from "@polkadot/keyring"; -import { u8aToHex, u8aWrapBytes } from "@polkadot/util"; -import { blake2AsHex, blake2AsU8a } from "@polkadot/util-crypto"; +import { stringToU8a, u8aToHex, u8aWrapBytes } from "@polkadot/util"; +import { blake2AsHex, blake2AsU8a, decodeAddress, encodeAddress } from "@polkadot/util-crypto"; import { waitForTransactionWithRetry } from "./transactions.js"; import { MultiAddress } from "@polkadot-api/descriptors"; @@ -145,6 +145,106 @@ export function buildWrappedSignedOrder(api: any, params: OrderParams): SignedOr }; } +// ── Human-readable ("clear-signing" / Ledger) message ────────────────────────── + +/** + * SS58 prefix under which all account fields are rendered in the canonical + * human-readable message. MUST match the pallet's `SS58_PREFIX` constant (42). + */ +export const READABLE_SS58_PREFIX = 42; + +/** + * Re-encode an account address as SS58 at prefix 42. Accepts any input the + * `@polkadot/util-crypto` `decodeAddress` understands (SS58 of any prefix, hex, + * or raw bytes) and always re-encodes so the output prefix is deterministic — + * matching the runtime's `render_account`, which always renders at prefix 42. + */ +function renderAccount(addr: string): string { + return encodeAddress(decodeAddress(addr), READABLE_SS58_PREFIX); +} + +/** + * Format the canonical human-readable ("clear-signing") message for an order. + * + * This is a PURE function of the order's V1 fields and MUST match the runtime's + * `Pallet::render_order` byte-for-byte — the runtime rebuilds this exact string + * and verifies the signature over `` ++ utf8(message) ++ ``. Any + * drift here silently breaks signature verification. + * + * Canonical form (single line, `, ` between fields): + * + * TAO.com order v1: {LABEL} {amount} on subnet {netuid}, {PRICE_WORD} {limit_price}, + * expiry {expiry}, hotkey {hotkey}, fee {fee_rate} to {fee_recipient}, + * relayer {relayer}, max slippage {max_slippage}, chain {chain_id}, + * partial fills {partial}, signer {signer} + */ +export function formatOrderMessage(order: Order): string { + const label = + order.order_type === "LimitBuy" ? "Limit buy" : order.order_type === "TakeProfit" ? "Take-profit" : "Stop-loss"; + + const priceWord = order.order_type === "LimitBuy" ? "limit price" : "trigger price"; + + const maxSlippage = order.max_slippage === null ? "none" : order.max_slippage.toString(); + + let relayer: string; + if (order.relayer === null) { + relayer = "none"; + } else if (order.relayer.length === 0) { + relayer = "[]"; + } else { + relayer = order.relayer.map(renderAccount).join("+"); + } + + return ( + `TAO.com order v1: ${label} ${order.amount.toString()} on subnet ${order.netuid.toString()}, ` + + `${priceWord} ${order.limit_price.toString()}, expiry ${order.expiry.toString()}, ` + + `hotkey ${renderAccount(order.hotkey)}, ` + + `fee ${order.fee_rate.toString()} to ${renderAccount(order.fee_recipient)}, ` + + `relayer ${relayer}, ` + + `max slippage ${maxSlippage}, chain ${order.chain_id.toString()}, ` + + `partial fills ${order.partial_fills_enabled ? "true" : "false"}, ` + + `signer ${renderAccount(order.signer)}` + ); +} + +/** + * Build a SignedOrder whose signature is over the ``-wrapped canonical + * human-readable message (the "clear-signing" / Ledger form that a hardware + * wallet can display field-by-field). This exercises the runtime's + * `verify_readable` path: + * + * signature.verify(b"" ++ utf8(render_order(order)) ++ b"", signer) + * + * IMPORTANT: the message is converted to BYTES with `stringToU8a` and then + * wrapped with `u8aWrapBytes`, so the signed payload is exactly + * `` ++ utf8(message) ++ `` — matching the runtime's + * `[b"", &render_order, b""].concat()`. Wrapping the raw string + * instead of the bytes would corrupt the payload. + * + * The signature scheme tag (`Sr25519` vs `Ed25519`) follows the signer's + * keypair type, so the same helper works for both schemes. + */ +export function buildReadableSignedOrder(api: any, params: OrderParams): SignedOrder { + const versionedOrder = buildVersionedOrder(params); + + // Render the canonical message, convert to UTF-8 bytes, then wrap. + const message = formatOrderMessage(versionedOrder.V1); + const wrapped = u8aWrapBytes(stringToU8a(message)); + const sig = params.signer.sign(wrapped); + + // Tag the signature variant from the keypair type. + const signature = + params.signer.type === "ed25519" + ? { Ed25519: u8aToHex(sig) as `0x${string}` } + : { Sr25519: u8aToHex(sig) as `0x${string}` }; + + return { + order: versionedOrder, + signature, + partial_fill: null, + }; +} + /** * Compute the on-chain OrderId (blake2_256 of SCALE-encoded VersionedOrder). * Mirrors `Pallet::derive_order_id` in Rust. From 1201a6aa74080187b38404b768662b08d1ea4fa7 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Mon, 27 Jul 2026 18:56:28 -0400 Subject: [PATCH 06/58] Expand evm precompile maintenance skill with compatibility notes, include issue 2445 notes. --- .agents/skills/emv-maintainer/SKILL.md | 99 +++++ .../references/abi-versioning.md | 249 +++++++++++ .../references/coverage-and-testing.md | 267 ++++++++++++ .../references/event-subscriptions.md | 249 +++++++++++ docs/guides/evm/index.mdx | 10 + docs/guides/evm/meta.json | 2 + docs/guides/evm/precompile-design.mdx | 407 ++++++++++++++++++ .../evm/precompiles/account-balance.mdx | 20 + .../evm/precompiles/address-mapping.mdx | 20 + docs/guides/evm/precompiles/alpha.mdx | 40 ++ .../evm/precompiles/balance-transfer.mdx | 23 + .../evm/precompiles/configuration-events.mdx | 98 +++++ docs/guides/evm/precompiles/crowdloan.mdx | 37 ++ docs/guides/evm/precompiles/drand.mdx | 35 ++ docs/guides/evm/precompiles/index.mdx | 60 +++ docs/guides/evm/precompiles/leasing.mdx | 31 ++ docs/guides/evm/precompiles/meta.json | 31 ++ docs/guides/evm/precompiles/metagraph.mdx | 38 ++ docs/guides/evm/precompiles/neuron-events.mdx | 50 +++ docs/guides/evm/precompiles/neuron.mdx | 30 ++ docs/guides/evm/precompiles/proxy.mdx | 27 ++ docs/guides/evm/precompiles/registry.mdx | 39 ++ docs/guides/evm/precompiles/scheduler.mdx | 49 +++ .../guides/evm/precompiles/staking-events.mdx | 56 +++ docs/guides/evm/precompiles/staking-v1.mdx | 29 ++ docs/guides/evm/precompiles/staking-v2.mdx | 79 ++++ docs/guides/evm/precompiles/storage-query.mdx | 65 +++ docs/guides/evm/precompiles/subnet-events.mdx | 80 ++++ docs/guides/evm/precompiles/subnet.mdx | 93 ++++ docs/guides/evm/precompiles/timestamp.mdx | 29 ++ docs/guides/evm/precompiles/uid-lookup.mdx | 20 + docs/guides/evm/precompiles/voting-power.mdx | 26 ++ .../guides/evm/precompiles/weights-events.mdx | 47 ++ .../bittensor-website/src/components/copy.tsx | 22 + .../bittensor-website/src/components/mdx.tsx | 3 +- 35 files changed, 2459 insertions(+), 1 deletion(-) create mode 100644 .agents/skills/emv-maintainer/SKILL.md create mode 100644 .agents/skills/emv-maintainer/references/abi-versioning.md create mode 100644 .agents/skills/emv-maintainer/references/coverage-and-testing.md create mode 100644 .agents/skills/emv-maintainer/references/event-subscriptions.md create mode 100644 docs/guides/evm/precompile-design.mdx create mode 100644 docs/guides/evm/precompiles/account-balance.mdx create mode 100644 docs/guides/evm/precompiles/address-mapping.mdx create mode 100644 docs/guides/evm/precompiles/alpha.mdx create mode 100644 docs/guides/evm/precompiles/balance-transfer.mdx create mode 100644 docs/guides/evm/precompiles/configuration-events.mdx create mode 100644 docs/guides/evm/precompiles/crowdloan.mdx create mode 100644 docs/guides/evm/precompiles/drand.mdx create mode 100644 docs/guides/evm/precompiles/index.mdx create mode 100644 docs/guides/evm/precompiles/leasing.mdx create mode 100644 docs/guides/evm/precompiles/meta.json create mode 100644 docs/guides/evm/precompiles/metagraph.mdx create mode 100644 docs/guides/evm/precompiles/neuron-events.mdx create mode 100644 docs/guides/evm/precompiles/neuron.mdx create mode 100644 docs/guides/evm/precompiles/proxy.mdx create mode 100644 docs/guides/evm/precompiles/registry.mdx create mode 100644 docs/guides/evm/precompiles/scheduler.mdx create mode 100644 docs/guides/evm/precompiles/staking-events.mdx create mode 100644 docs/guides/evm/precompiles/staking-v1.mdx create mode 100644 docs/guides/evm/precompiles/staking-v2.mdx create mode 100644 docs/guides/evm/precompiles/storage-query.mdx create mode 100644 docs/guides/evm/precompiles/subnet-events.mdx create mode 100644 docs/guides/evm/precompiles/subnet.mdx create mode 100644 docs/guides/evm/precompiles/timestamp.mdx create mode 100644 docs/guides/evm/precompiles/uid-lookup.mdx create mode 100644 docs/guides/evm/precompiles/voting-power.mdx create mode 100644 docs/guides/evm/precompiles/weights-events.mdx diff --git a/.agents/skills/emv-maintainer/SKILL.md b/.agents/skills/emv-maintainer/SKILL.md new file mode 100644 index 0000000000..c26d65f9b7 --- /dev/null +++ b/.agents/skills/emv-maintainer/SKILL.md @@ -0,0 +1,99 @@ +--- +name: evm-maintainer +description: Maintain the EVM precompiles in backwards compatible way with API versioning. +--- + +# EVM Precompile Maintainer + +You are the maintainer of EVM precompiles. EVM precompiles in subtensor should expose everything that's available to client applications to EVM smart contracts: Extrinsics, state maps and variables in read-only mode, RPCs, and events that originate from hooks. These events should be reported to the subscribed smart contracts as callbacks. Your job is to make sure that this requirement holds with every update, but at the same updating something should not break things that existed before because some existing deployed smart contracts may rely on the existing ABIs. Read the notes below and then execute steps. + +## Reference routing + +- Before classifying or implementing any precompile change, including an + additive function, runtime adaptation, bug fix, deprecation, or disablement, + read [ABI versioning](references/abi-versioning.md). +- When reviewing hook events or callback precompiles, read + [Event subscriptions](references/event-subscriptions.md). +- Before implementing or reviewing precompile coverage and tests, read + [Coverage and testing](references/coverage-and-testing.md). + +## Backwards compatibility + +Treat every released precompile as a permanent public API. Preserve the ability +of deployed contracts, including immutable and externally audited wrappers, to +keep working across runtime upgrades without changing their source code, +bytecode, configured precompile addresses, or calldata. + +Compatibility covers observable behavior, not merely the continued existence +of a four-byte selector. Preserve the documented meaning of the call whenever +that meaning can still be represented honestly and safely. + +For each affected released function: + +1. Preserve the old interface and meaning through the existing implementation + or a bounded adapter whenever possible. +2. Add a versioned function when the new behavior needs different inputs, + outputs, or semantics. Keep the old address and selector routed. +3. Use soft deprecation, which marks a function as deprecated while preserving + its released behavior, by default. Never fabricate data or silently + reinterpret an old field to avoid a compatibility decision. +4. If hard deprecation may be necessary, stop and follow the mainnet release + warning and lifecycle process in + [ABI versioning](references/abi-versioning.md). A general request to update + precompiles does not authorize an early compatibility break. +5. Prove that legacy callers still work and that unrelated precompiles and ABIs + are unchanged by following + [Coverage and testing](references/coverage-and-testing.md). + +## Notes on coding precompiles + +- Never allow direct writing of state maps or variables to precompile callers. +- Keep every precompile path O(1) in CPU and memory. +- Follow [ABI versioning](references/abi-versioning.md) for every released + interface. +- Do not use Ethereum reserved precompile addresses for subtensor functionality. +- Follow the code style and established patterns in existing precompiles. +- Represent Substrate account IDs in EVM space as 32-byte public keys. +- Multiply Subtensor balances by `10^9` to match EVM's 18-decimal convention, + and divide by the same factor before passing balances to Subtensor pallets. +- Follow [Event subscriptions](references/event-subscriptions.md) for callback + interfaces, charging, bounds, and delivery. + +## Step 1 - Review current precompiles vs. subtensor functionality + +- All extrinsics should be exposed to precompile callers for the following pallets: + - subtensor + - admin-util + - balances + - proxy +- All runtime API RPCs for the subtensor pallet should be exposed as a callable precompile function with similar interface +- All events emitted from hooks (such as on_initialize or on_finalize) should be exposed as callbacks. + +Use [Coverage and testing](references/coverage-and-testing.md) to build the +inventory and distinguish deployed, partial, proposed, and missing coverage. + +## Step 2 — Determine the diff + +Determine the diff between current branch and the most recent main branch (may need to pull it locally if it is outdated). See how this diff affects EVM precompiles: + +- Does it remove or change any functions that precompiles rely on? Does it change function signatures or underlying functionality? +- Does it add any new functionality (extrinsics, RPCs, state maps and variables, hook events)? + +## Step 3 - Handle changed functions + +Apply the backwards-compatibility decision rule above and the detailed +[ABI versioning](references/abi-versioning.md) process. Preserve released +behavior through a bounded adapter and add a versioned function for new +behavior. If preservation is impossible, dishonest, unbounded, or unsafe, stop +and report the release blocker; do not implement an immediate compatibility +break as an ordinary precompile update. + +## Step 4 - Handle added functions + +Determine the category under which the new functionality needs to be added and add to the corresponding existing precompile. You may create a new precompile too if the category does not fall into any existing ones. + +## Step 5 - Update precompile documentation + +Update the Solidity interface, generated ABI, NatSpec, registry metadata, SDK +copies, and public precompile documentation together. Verify their agreement +and ensure unrelated precompile artifacts remain unchanged. diff --git a/.agents/skills/emv-maintainer/references/abi-versioning.md b/.agents/skills/emv-maintainer/references/abi-versioning.md new file mode 100644 index 0000000000..54037f4b1a --- /dev/null +++ b/.agents/skills/emv-maintainer/references/abi-versioning.md @@ -0,0 +1,249 @@ +# ABI versioning and lifecycle + +## Contents + +- [Establish the released baseline](#establish-the-released-baseline) +- [Preserve the external contract](#preserve-the-external-contract) +- [Reserve addresses and selectors](#reserve-addresses-and-selectors) +- [Version functions within a domain](#version-functions-within-a-domain) +- [Preserve old behavior through adapters](#preserve-old-behavior-through-adapters) +- [Classify changes](#classify-changes) +- [Apply the lifecycle model](#apply-the-lifecycle-model) +- [Stop an undeployed compatibility break](#stop-an-undeployed-compatibility-break) +- [Report lifecycle and availability](#report-lifecycle-and-availability) +- [Handle reversible disablement](#handle-reversible-disablement) + +## Establish the released baseline + +Before changing a precompile: + +1. Determine which addresses, selectors, Solidity interfaces, and ABI files + have been deployed or published for production use. Inspect release history + and the deployed runtime, not only the working tree. +2. Inspect `precompiles/src/lib.rs`, the Rust implementation, + `precompiles/src/solidity/*.sol`, generated `*.abi` files, tests, public + documentation, SDK copies, and known integration contracts. +3. Compare the branch with the relevant base and identify every runtime change + that affects inputs, outputs, state changes, errors, authorization, units, + value handling, or gas and weight requirements. +4. Treat uncertain production status as released until evidence establishes + otherwise. +5. Distinguish released interfaces from explicit proposals. Allow an + unassigned, unpublished proposal to change during design review; freeze its + address, selectors, and observable behavior once released. + +Do not infer compatibility from Rust names. Define the external contract as the +fixed EVM address plus accepted calldata, returned bytes, state effects, +authorization, charging, and success-or-revert behavior. + +## Preserve the external contract + +Preserve all observable properties of every released call: + +- address and selector handling; +- function name, input types, input order, and ABI encoding; +- return types, tuple and struct field order, and ABI encoding; +- documented meaning, units, precision, scaling, rounding, and defaults; +- view, state-changing, payable, and static-call behavior; +- treatment of attached EVM value; +- caller-to-Substrate account mapping and dispatched origin; +- authorization and proxy behavior; +- state transitions and atomicity; +- success-versus-revert behavior and documented error payloads; +- bounded-input and complexity guarantees; +- callback selectors, event-mask assignments, filters, charging, + auto-unsubscription, sequencing, and delivery guarantees. + +Return types do not contribute to a Solidity selector, but changing them under +an existing selector still breaks old callers because they decode the returned +bytes with the old ABI. + +Allow internal Rust names, storage layouts, hashers, intermediate types, and +algorithms to change only when the implementation adapts them back to the +released behavior. + +Allow runtime weight corrections, but preserve the complexity class and input +bounds. Do not introduce an unannounced increase large enough to make a +previously practical call unusable. Never replace bounded work with an +unbounded scan. + +## Reserve addresses and selectors + +Keep every released precompile address recognized by the precompile set. +Preserve compatible handling at that address: existing calldata must still +reach behavior that honors its released contract. The internal Rust type or +dispatch structure may change; the observable routing contract may not. + +Keep every released selector reserved permanently, including after hard +deprecation. Route a hard-deprecated selector to its descriptive error. Never +allow a different function to claim it. + +Before adding a function, calculate its selector from the canonical Solidity +signature and compare it with the complete selector set at the address. Reject +collisions even when the Solidity names differ. + +Treat a new function as additive only when: + +- its selector does not collide; +- old input and output encodings remain identical; +- unknown-selector and fallback behavior remain unchanged; +- old results and side effects remain unchanged; and +- no unrelated Solidity interface or ABI changes. + +## Version functions within a domain + +Prefer one fixed address for each coherent domain. Add versions at that address: + +```text +functionName +functionNameV2 +functionNameV3 +``` + +Keep every earlier version routed. Use a new address only for a genuinely +different domain with an independent responsibility and lifecycle. + +Continue supporting legacy addresses created under earlier per-contract +versioning. Do not use them as a precedent for creating a new address whenever +one function changes. + +Do not attempt a return-type-only overload. Because return types do not +distinguish selectors, use a versioned name or a genuinely distinct input +signature. + +When an audited integration expects a missing chain value or operation, prefer +adding the typed function it expects to the appropriate existing precompile. +Do not require changes to an audited wrapper when the precompile can satisfy +the wrapper's existing interface safely. + +## Preserve old behavior through adapters + +Adapt released calls to new runtime representations whenever the old result can +still be produced honestly with bounded, proportionate work: + +- Reconstruct an old aggregate when one stored value becomes several. +- Return the original tuple when a struct gains fields; expose the extended + tuple through a new version. +- Update Rust storage access when names, keys, hashers, or map shapes change. +- Supply the exact old default when an extrinsic gains an option; expose the + option through a new version. +- Derive the documented old result when the runtime replaces its computation. +- Preserve legacy units, precision, scaling, and rounding in the old function; + expose a corrected convention through a new version. + +Do not fabricate data to retain a byte shape. Do not reinterpret an old field +as a different concept. If an adapter cannot preserve the documented meaning, +make an explicit lifecycle decision. + +## Classify changes + +| Runtime change | Required treatment | +|---|---| +| Storage rename, hasher change, or map restructuring | Update the Rust implementation; preserve ABI and meaning. | +| Equivalent internal computation refactor | Keep the function and verify equivalent observable results. | +| Additional returned information | Keep the old subset; add a version for the richer result. | +| Input or return type/order change | Add a version with a new selector. | +| One concept splits into several | Reconstruct the old aggregate when honest; expose components through a version. | +| Extrinsic gains an option | Preserve the old default; expose the option through a version. | +| Entirely new operation or view | Add a selector to the appropriate domain. | +| Concept disappears without an honest representation | Reserve the selector and evaluate hard deprecation. | +| Bug fix changes observable semantics | Preserve the released behavior and add a corrected version unless retaining it is unsafe. | +| Urgent security or operational risk | Report the risk and consider whether reversible disablement should be recommended. | + +For a security-critical behavior that cannot remain callable, stop and report +the compatibility break. Do not silently change or delete the selector. + +## Apply the lifecycle model + +Keep function lifecycle separate from precompile availability: + +| Condition | Required call behavior | +|---|---| +| Active and enabled | Execute normally. | +| Soft-deprecated and enabled | Preserve the documented behavior and encoding. | +| Hard-deprecated and enabled | Keep routing the selector and return a descriptive precompile error. | +| Disabled | Return the precompile-disabled error regardless of function lifecycle. | + +Use soft deprecation by default. Preserve the call, mark the Solidity function +with `@deprecated`, and publish replacement metadata without adding +deprecation-only work to every invocation. + +Use hard deprecation only when old behavior cannot be represented honestly or +safely, for example because: + +- the underlying concept no longer exists and has no representation; +- the semantics changed beyond what the old return type can describe; or +- preservation requires fabricated data, dead state, unbounded work, or an + unacceptable security risk. + +Do not hard-deprecate because a replacement is newer, easier to maintain, or +more complete. First document why an adapter is impossible or disproportionate, +identify affected released functions and known callers, provide a replacement +when possible, and complete the agreed migration process. + +## Stop an undeployed compatibility break + +If the runtime change that makes old behavior impossible has not reached +mainnet, treat mainnet deployment as blocked by the compatibility break. Do not +interpret a request to update precompiles as authorization to deploy the break +or hard-deprecate affected functions immediately. + +Stop and give the developer this prominent warning: + +> **Mainnet compatibility warning:** This change would force hard deprecation +> of `` and break contracts that +> still call it. Do not deploy the incompatible runtime change to mainnet until +> `` is available, the old function has been soft-deprecated for +> the agreed migration window, and the phase-out criteria have been satisfied. + +State why an adapter cannot work, which released functions and known callers +are affected, what replacement is available or required, and which phase-out +steps remain. Continue only with non-breaking preparation such as adding the +replacement, tests, documentation, and lifecycle metadata. Preserve current +mainnet behavior throughout the migration window. Hard-deprecate only in the +later release that completes the planned phase-out. + +## Report lifecycle and availability + +Use this proposed registry shape as the compatibility target: + +```solidity +struct PrecompileStatus { + bool isDeprecated; + bool isDisabled; + address newPrecompile; + bytes4 newSelector; + string message; +} +``` + +Interpret `isDeprecated` as soft or hard function deprecation. Interpret +`isDisabled` as current unavailability through a reversible operational switch. +Use `newPrecompile` and `newSelector` for the recommended replacement; zero +replacement fields mean that none is available. Use `message` for +human-readable status or migration guidance. + +Do not infer deprecation from disablement. Do not clear deprecation when a +precompile is re-enabled. Do not describe the registry as callable until its +address and implementation are released. + +Keep registry metadata, Solidity NatSpec, public documentation, and call +behavior consistent. Prefer static registry queries over emitting a log on +every deprecated call. + +## Handle reversible disablement + +Treat disablement as an external, reversible operational action, not a normal +deprecation step. An agent may identify a risk, verify the mechanism, and +recommend that responsible decision-makers consider it. An agent cannot +perform or authorize the action. + +Require re-enablement to restore each function's previous active, +soft-deprecated, or hard-deprecated behavior. Never erase lifecycle metadata +when availability changes. + +Before recommending disablement, verify that the address routes through +`PrecompileExt::try_execute` and uses the intended `PrecompileEnum` entry. +Check whether multiple addresses share that entry and report the complete +effect of a toggle. Do not claim an address is toggleable merely because the +general mechanism exists. diff --git a/.agents/skills/emv-maintainer/references/coverage-and-testing.md b/.agents/skills/emv-maintainer/references/coverage-and-testing.md new file mode 100644 index 0000000000..1f1122fc64 --- /dev/null +++ b/.agents/skills/emv-maintainer/references/coverage-and-testing.md @@ -0,0 +1,267 @@ +# Precompile coverage and testing + +## Contents + +- [Define the coverage scope](#define-the-coverage-scope) +- [Build a coverage inventory](#build-a-coverage-inventory) +- [Cover extrinsics](#cover-extrinsics) +- [Cover state with typed views](#cover-state-with-typed-views) +- [Cover runtime APIs and public RPCs](#cover-runtime-apis-and-public-rpcs) +- [Cover events](#cover-events) +- [Add regression tests first](#add-regression-tests-first) +- [Test observable behavior](#test-observable-behavior) +- [Validate ABIs and routing](#validate-abis-and-routing) +- [Validate cost and bounds](#validate-cost-and-bounds) +- [Run repository checks](#run-repository-checks) +- [Report the result](#report-the-result) + +## Define the coverage scope + +Take the authoritative pallet and API scope from `SKILL.md`. Do not silently +expand or narrow it based on an older document. + +For each in-scope pallet, inspect: + +- every dispatchable extrinsic; +- every public state map and value; +- every publicly facing runtime API and RPC; +- every emitted event, including events originating in hooks and scheduled + work; and +- changes to types, guards, authorization, units, and error behavior used by + existing precompiles. + +Coverage means that Solidity contracts receive a typed equivalent of the +authorized client-facing functionality. It does not mean exposing raw pallet +storage, SCALE bytes, or Rust types. + +Distinguish deployed coverage from proposed coverage. Do not describe a +documented proposal, unassigned address, or Rust stub as callable. + +## Build a coverage inventory + +Create or update a working matrix with one row per source item: + +| Source | Kind | Public functionality | Precompile domain | Function or callback | Status | Evidence | +|---|---|---|---|---|---|---| +| Pallet and item | Extrinsic, state, runtime API, RPC, or event | Meaning exposed to clients | Existing or proposed address/domain | Canonical signature or callback | Covered, partial, missing, or excluded | Rust, Solidity, ABI, and test paths | + +For every partial, missing, or excluded row, state the exact reason. Do not +equate a similarly named function with coverage; compare parameters, returned +information, authorization, semantics, and failure behavior. + +Use the matrix to find both directions of drift: + +- runtime functionality with no typed EVM path; and +- precompile behavior whose runtime dependency changed or disappeared. + +Group additions by meaning under as few coherent contracts as reasonably +possible. Do not mirror pallet boundaries mechanically and do not create one +precompile per storage item. + +## Cover extrinsics + +Expose each authorized extrinsic through a typed state-changing function unless +an explicit scope decision excludes it. + +Preserve: + +- dispatched origin and caller mapping; +- authorization and proxy behavior; +- payable versus nonpayable behavior; +- attached-value conversion and handling; +- input validation and bounds; +- dispatch atomicity; +- runtime errors and EVM failure behavior; and +- gas and weight charging, including post-dispatch adjustment. + +Use `PrecompileHandleExt::try_dispatch_runtime_call` and established +precompile patterns where they apply. Do not bypass guards or create a direct +state-writing path that the pallet does not authorize. + +When an extrinsic changes, compare the old and new behavior rather than only +their Rust signatures. Follow [ABI versioning](abi-versioning.md) when an +existing function is affected. + +## Cover state with typed views + +Inventory every public state map and value in scope. Expose its meaningful +contents through typed view functions; never provide direct writable access to +storage. + +Let a view read one or more storage items when that is required to return the +meaningful value. Keep the mapping from source storage to typed functions +explicit in the coverage inventory so no item disappears behind an abstract +claim of domain coverage. + +Group related reads into coherent domain precompiles. Do not expose pallet +prefixes, storage keys, hashers, or SCALE encodings as the contract interface. + +For every view, specify and test: + +- key and account conversions; +- missing-state behavior; +- result types and tuple order; +- units, precision, scaling, and rounding; +- overflow and narrowing conversions; +- maximum input and output size; and +- the exact database reads charged. + +When storage changes internally, update the Rust adapter and prove that released +calldata still returns the released meaning. + +## Cover runtime APIs and public RPCs + +Inventory the publicly facing runtime APIs and RPCs in scope, including the +Subtensor runtime API surface required by `SKILL.md`. + +Expose typed functions with equivalent inputs and meaningful outputs. A +precompile may call the same underlying helpers rather than reproduce an RPC +transport detail. Preserve pagination, bounds, defaults, and absence semantics +that affect callers. + +Do not expose node-only behavior that cannot execute deterministically in the +runtime. When a public RPC composes runtime state, implement the deterministic +runtime-side result and document any transport-only behavior that has no EVM +equivalent. + +## Cover events + +Inspect event enums and active emission sites. Cover relevant hook-origin +events with subscription callbacks so contracts are not limited to their own +transaction receipts. + +Use [Event subscriptions](event-subscriptions.md) for domain grouping, +filtering, callback ABI, charging, queue bounds, and delivery semantics. + +Do not mark an enum-only placeholder as emitted coverage. Do not expose a raw +runtime event or an unbounded vector callback. + +## Add regression tests first + +For a bug fix, add a regression unit test that fails for the reported behavior +before implementing the fix. Confirm the failure is caused by the bug, then +apply the fix and confirm the same test passes. + +For an ABI-affecting runtime change, add a compatibility test that sends the +exact legacy calldata and decodes the result using the released ABI. A test +that only calls the new Rust helper or new selector does not prove backwards +compatibility. + +Keep precompile unit tests with the implementation's existing +`#[cfg(test)] mod tests` pattern and use `precompiles/src/mock.rs`. Reuse +`selector_u32`, `encode_with_selector`, `execute_returns`, +`execute_returns_raw`, and the established mock-state helpers where suitable. + +Name tests after observable behavior and the condition being protected. Avoid +tests that merely duplicate an implementation expression. + +## Test observable behavior + +Cover every affected path: + +- legacy success and return decoding; +- new selector success independently; +- invalid and boundary inputs; +- missing state; +- authorization and proxy origin; +- payable, nonpayable, attached-value, and static-call behavior; +- expected state transitions and rollback on failure; +- runtime dispatch errors and EVM errors; +- account and address conversion; +- TAO and Alpha unit conversion; +- precision, rounding, overflow, and narrowing; +- bounded collections and duplicate inputs; +- lifecycle status, hard-deprecation error, and disable/re-enable behavior when + applicable; and +- storage adapters against legacy and new state during migrations. + +Test both a representative normal case and the boundaries where conversion or +runtime semantics change. + +## Validate ABIs and routing + +Treat `precompiles/src/solidity/*.sol` and generated `*.abi` files as external +artifacts. Compare them with the relevant released or base-branch versions. + +Verify: + +1. Every old canonical signature and selector remains present. +2. Old input and output ABI encodings are unchanged. +3. Every new selector matches its canonical Solidity signature. +4. No selector collides with another selector at the address. +5. Only the intended Solidity interface and ABI gain the intended functions. +6. Unrelated precompile Solidity and ABI files are byte-for-byte unchanged. +7. The Rust macro signature, Solidity declaration, generated ABI, NatSpec, SDK + copies, registry metadata, and public documentation agree. +8. Every released address remains in `Precompiles::used_addresses()`. +9. `Precompiles::execute()` recognizes the address and routes it through the + intended availability control and compatible implementation. +10. Unknown-address and unknown-selector behavior remains unchanged. + +Do not hand-wave generated-file churn. Inspect each changed ABI entry and +remove unrelated regeneration changes. + +## Validate cost and bounds + +Keep every precompile path bounded in CPU, memory, storage access, and output +size. Record database reads and writes and dispatch weight through the existing +helpers. + +Test: + +- gas-limit rejection before overweight dispatch; +- post-dispatch charging and refund behavior when affected; +- the maximum accepted collection size; +- rejection just beyond the bound; +- proof-size-sensitive database access where relevant; +- callback gas and per-block delivery limits for subscriptions; and +- failure paths that could otherwise perform unpaid work. + +Do not accept a bounded input if processing it can trigger an unbounded runtime +scan. Document any change large enough to make a previously practical call +unusable even if its asymptotic complexity is unchanged. + +## Run repository checks + +Run the narrowest relevant unit test while iterating, then run the complete +precompile package tests: + +```sh +cargo test -p subtensor-precompiles +``` + +Check formatting: + +```sh +cargo fmt --all --check +``` + +Run Clippy for the package when practical: + +```sh +SKIP_WASM_BUILD=1 cargo clippy \ + -p subtensor-precompiles \ + --all-targets \ + --all-features \ + -- -D warnings +``` + +Escalate to workspace checks or affected pallet tests when shared runtime +types, dispatchables, mocks, or routing changed. Report any check that could not +run and the specific reason; do not imply success from an unexecuted check. + +## Report the result + +Summarize: + +- source functionality added, changed, or still missing; +- released addresses and selectors affected; +- adapters or new versions introduced; +- lifecycle or mainnet-release warnings; +- files and ABIs changed; +- evidence that unrelated precompiles and ABIs are unchanged; +- regression tests added and their before/after behavior; and +- commands run, results, and any remaining validation gaps. + +Do not claim completion while a required coverage row is unexplained or a +legacy caller test is missing. diff --git a/.agents/skills/emv-maintainer/references/event-subscriptions.md b/.agents/skills/emv-maintainer/references/event-subscriptions.md new file mode 100644 index 0000000000..47b4bee0e0 --- /dev/null +++ b/.agents/skills/emv-maintainer/references/event-subscriptions.md @@ -0,0 +1,249 @@ +# Event subscription precompiles + +## Contents + +- [Use typed domain precompiles](#use-typed-domain-precompiles) +- [Inventory reportable events](#inventory-reportable-events) +- [Use a common subscription interface](#use-a-common-subscription-interface) +- [Fund callback delivery](#fund-callback-delivery) +- [Keep event production bounded](#keep-event-production-bounded) +- [Define stable callback ABIs](#define-stable-callback-abis) +- [Normalize variable-length events](#normalize-variable-length-events) +- [Specify delivery semantics](#specify-delivery-semantics) +- [Protect execution](#protect-execution) +- [Test subscription behavior](#test-subscription-behavior) + +## Use typed domain precompiles + +Expose events from `SubtensorModule` and `AdminUtils` as typed Solidity +callbacks. Do not expose raw `RuntimeEvent`, pallet enum discriminants, or +SCALE-encoded payloads. + +Group callbacks by meaning under a small number of independently addressed +precompiles. Use the current proposed domains as the design baseline: + +- staking and economic flows; +- neurons, identities, relationships, and key rotation; +- weights and commit-reveal; +- subnet lifecycle, epochs, emissions, leases, and voting-power tracking; +- runtime and subnet configuration. + +Consult the corresponding pages under +`docs/guides/evm/precompiles/*-events.mdx` for the current proposed inventory. +Treat names, signatures, mask bits, and addresses as provisional until +released. After release, apply the ABI rules in +[ABI versioning](abi-versioning.md). + +Create another address only when an event family has a genuinely separate +domain and lifecycle. Do not create one precompile per pallet event. + +## Inventory reportable events + +Inspect both event enum definitions and every emission site. An enum variant +without an active emission site is not a live callback. Record it as a coverage +gap or future possibility, not as currently delivered behavior. + +For each emitted event: + +1. Record the source pallet, variant, fields, and emission sites. +2. Identify whether it originates from an extrinsic, scheduled operation, or + runtime hook. +3. Assign it to a meaningful event-precompile domain. +4. Define stable EVM field types and conversions. +5. Determine whether the source payload is bounded. +6. Define a recovery view when callbacks alone are not authoritative. +7. Add an event-mask bit without changing any released assignment. + +Prioritize hook-origin events because an interested contract cannot obtain them +from its own transaction receipt. Use the same subscription model for relevant +transaction and scheduled-operation events when this provides coherent domain +coverage. + +When a new source event starts being emitted, add a new typed callback and mask +bit. Do not change an existing callback to absorb different semantics. + +## Use a common subscription interface + +Use the same control shape for every event domain unless a documented reason +requires an additive version: + +```solidity +struct EventFilter { + uint256 eventMask; + uint16 netuid; + bytes32 accountId; + bool matchAnyNetuid; + bool matchAnyAccount; +} + +struct Subscription { + bool active; + EventFilter filter; + uint64 callbackGasLimit; + uint64 nextSequence; +} + +function subscribe( + EventFilter calldata filter, + uint64 callbackGasLimit +) external; + +function unsubscribe() external; + +function getSubscription( + address subscriber +) external view returns (Subscription memory); + +function minimumCallbackBalance( + uint64 callbackGasLimit +) external view returns (uint256); +``` + +Always make the caller the subscriber. Do not allow one address to subscribe or +unsubscribe another address. + +Store at most one fixed-size subscription per contract and event domain. Use a +fixed event mask plus at most one netuid and one account filter. Do not store or +iterate an arbitrary list of filters. + +Validate the mask, callback gas limit, filter flags, and minimum balance before +creating or replacing a subscription. Make subscription replacement atomic. + +## Fund callback delivery + +Charge callback attempts to the subscribing contract's own TAO balance. Require +enough balance at subscription time to fund the documented minimum number of +attempts at the selected callback gas limit. + +Charge a reverting callback for the work it consumed. Never let callback +failure revert the runtime operation that produced the source event. + +Automatically remove a subscription when its balance cannot fund the next +attempt. Define charging, rounding, and TAO-to-EVM unit conversion precisely. +Do not provide free delivery paths that allow subscription spam. + +Keep the minimum-balance calculation available as a typed view so a contract +can determine whether a subscription is fundable before submitting it. + +## Keep event production bounded + +Do not synchronously iterate all subscribers when an event is emitted. Append a +fixed-size typed report to a bounded queue in O(1), then process a bounded +amount of delivery work in later blocks. + +Advance delivery through bounded cursors. Cap: + +- queue capacity; +- work per block; +- callback gas; +- report size; +- subscription size; and +- the number of delivery attempts performed by one bounded work item. + +Do not copy or ABI-encode an unbounded vector while producing a report. If a +source event is variable-length, normalize it incrementally as described below. + +Define what happens when the queue reaches capacity. Never permit unbounded +runtime storage or memory growth. + +## Define stable callback ABIs + +Give every event a stable, event-specific receiver selector. Include +`uint64 sequence` and `uint64 sourceBlock` in every callback before the +event-specific fields. + +Use stable EVM representations: + +- Substrate account IDs and hashes: `bytes32`; +- EVM accounts: `address`; +- netuids and UIDs: `uint16` when the runtime domain fits; +- TAO and Alpha amounts: 18-decimal `uint256` values using the documented + `10^9` conversion factor; +- fixed-point values: an explicitly documented integer representation. + +Choose bounded representations for strings, identities, and other structured +values before release. Do not expose a Rust or SCALE representation as the ABI. + +After release: + +- reserve the precompile address and control selectors; +- reserve every event-mask bit; +- preserve callback names, parameters, order, types, and meaning; +- preserve filter, charging, sequencing, and delivery guarantees; and +- add a versioned callback when richer data is required. + +Do not add speculative fields to a callback merely because a future runtime +might produce them. Add another selector when the semantics become concrete. + +## Normalize variable-length events + +Convert every variable-length source event into bounded callbacks. Emit a +summary when useful, followed by one item callback per entry. Give related +callbacks the same source sequence and include item index and item count. + +For UID-indexed emission arrays, interpret the array index as the UID and +deliver one `(uid, amount)` callback per entry. For example, `[10, 20, 30]` +represents UIDs `0`, `1`, and `2`; do not treat an entry as an arbitrary UID +value. + +Apply the same approach to children lists, weight hashes, completed-netuid +batches, and similar collections. Use a stable typed representation for +per-item failures instead of SCALE-encoded `DispatchError`. + +Produce normalized items incrementally at the source. Do not first copy the +complete vector into a queued report. + +## Specify delivery semantics + +Treat callbacks as asynchronous, best-effort notifications. Do not promise that +a callback executes in the source event's block. + +Use a monotonically increasing source sequence and source block so receivers +can order reports and detect gaps. Define whether normalized items share one +source sequence and how item indices identify completeness. + +If bounded queue overwrite or another allowed failure drops a report, make the +gap observable through sequencing. Require authoritative recovery through the +corresponding typed view where contract logic needs exact current state. + +Document ordering across event domains only if the implementation guarantees +it. Require receivers to make callbacks idempotent and tolerate retries, +reordering outside documented guarantees, and sequence gaps. + +## Protect execution + +Apply reentrancy protection around delivery. Do not allow a callback to +recursively create unbounded callback work. + +Keep the source runtime operation independent of callback execution. Bound +callback gas and isolate callback failure. Validate that subscriber-controlled +code cannot stall block processing, retain an unpaid subscription, or make +another subscriber's delivery unbounded. + +Account for database reads, writes, queue operations, EVM execution, and failed +attempts. Use saturating arithmetic where appropriate and reject values that +cannot be converted safely. + +## Test subscription behavior + +Test at least: + +- self-subscription and self-unsubscription; +- attempts to manage another address; +- invalid masks, filters, and gas limits; +- insufficient initial balance; +- successful charging and delivery; +- reverting and out-of-gas callbacks; +- automatic unsubscription when payment fails; +- event filtering by mask, netuid, and account; +- monotonic sequencing and source-block reporting; +- queue capacity and observable gaps; +- bounded per-block work with many subscribers; +- reentrancy and recursive-work resistance; +- one-item normalization and item ordering; +- unit and account conversions; +- released callback selectors and event-mask assignments; and +- additive introduction of a new callback without changing old callbacks. + +Use [Coverage and testing](coverage-and-testing.md) for the general precompile +regression and ABI-diff requirements. diff --git a/docs/guides/evm/index.mdx b/docs/guides/evm/index.mdx index b7b591cb62..8944daa5d4 100644 --- a/docs/guides/evm/index.mdx +++ b/docs/guides/evm/index.mdx @@ -39,11 +39,21 @@ deeper concepts (address mappings, decimals, precompiles). End-to-end tutorials that build on the commands below: + + + A deployed contract may be immutable. Treat every released precompile address, + function signature, and selector as a permanent public API. + + +## Design goals + +The precompile layer is designed around five goals: + +1. **Contracts at rest keep working.** Runtime upgrades must not silently break + deployed contracts. +2. **Interfaces evolve additively.** Existing selectors remain reserved, and + richer behavior is introduced through new function versions. +3. **Deprecation is normally soft.** An old function continues to preserve its + original behavior whenever that behavior can still be represented safely. +4. **Status is discoverable.** Solidity interfaces and a registry should tell + developers when a function is deprecated, replaced, or temporarily disabled. +5. **The authorized Substrate API has full parity.** Every storage item and + extrinsic in scope has a typed precompile equivalent. + +## Fixed addresses and function selectors + +A precompile has a fixed EVM address for a domain such as staking, metagraph +data, or subnet operations. Solidity dispatches a call using the first four +bytes of the Keccak-256 hash of its canonical function signature. + +For example: + +```solidity +function getStake(uint16 netuid, uint16 uid) external view returns (uint64); +``` + +The selector belongs to that signature permanently once released. It must not +later be assigned different semantics, even if the original function is +hard-deprecated. Reusing a selector could make an old contract decode a +successful but unrelated result. + +The source-of-truth Solidity interfaces and generated ABIs live in +[`precompiles/src/solidity/`](https://github.com/RaoFoundation/subtensor/tree/main/precompiles/src/solidity). + +## Compatibility rules + +### Preserve released interfaces + +Do not remove or change a released function signature. A runtime implementation +may change internally to follow a new storage layout or computation, but the +observable result must retain the function's documented meaning. + +Changing any of these creates a different EVM interface: + +- function name or version suffix; +- parameter types or order; +- return types or order; +- mutability where it affects permitted calls; +- precompile address. + +### Version functions, not whole domains + +When a breaking return-type or parameter change is necessary, add a versioned +function at the same precompile address: + +```solidity +interface IMetagraph { + // Original selector remains supported. + function getStake( + uint16 netuid, + uint16 uid + ) external view returns (uint64); + + // New selector exposes the richer representation. + function getStakeV2( + uint16 netuid, + uint16 uid + ) external view returns (StakeInfo memory); +} +``` + +Use `functionName` for the initial version, followed by `functionNameV2`, +`functionNameV3`, and so on. Both selectors route independently, so adding a +version does not alter calls made by existing contracts. + +Creating a new domain address may still be appropriate when the functionality +is genuinely a different precompile, but it should not be the default +versioning mechanism. + +### Keep old semantics when possible + +Suppose `getStake` originally returned total stake, while a later runtime stores +self-stake and delegated stake separately. The original function can continue +returning their sum, while `getStakeV2` returns the breakdown. + +This is a soft deprecation: the old selector remains correct for callers that +depend on its original meaning. + +## Replace raw storage access with typed views + +Raw storage access couples a contract to pallet names, storage item names, +hashers, key shapes, and SCALE encodings. Any internal refactor can then make +the contract read an empty value or decode the wrong bytes without a useful +error. + +A typed view instead owns the encoding and decoding: + +```solidity +uint64 weight = IMetagraph(METAGRAPH_ADDRESS).getWeight(netuid, uid); +``` + +If the underlying storage map, key format, hasher, or value encoding changes, +the precompile implementation adapts while the Solidity interface remains +stable. A resulting Rust compilation failure provides a safety net that raw +storage queries do not. + +### Phasing out raw storage reads + +`StorageQueryPrecompile` at `0x…0807` exposes raw Substrate storage and is +inherently brittle. The intended migration is: + +1. Add a typed view for every storage item in the currently authorized pallets: + SubtensorModule, Balances, Proxy, Scheduler, Drand, Crowdloan, Sudo, + Multisig, Timestamp, and Swap. +2. Soft-deprecate raw storage access after that typed coverage exists. +3. Hard-deprecate it after a documented migration window. +4. Eventually disable it through an explicit root decision. + +Whether this 1:1 coverage should extend beyond the authorized pallets remains +an open design question. + +## Subscription-based event reporting + +Some Subtensor events are produced by runtime hooks rather than by the EVM +transaction that is interested in them. A transaction receipt therefore cannot +provide complete event coverage. Proposed event precompiles let a contract +subscribe itself and receive those events later as typed EVM callbacks. + +Event reporting is divided into dedicated domain precompiles for +[staking](/docs/guides/evm/precompiles/staking-events), +[neurons and keys](/docs/guides/evm/precompiles/neuron-events), +[weights](/docs/guides/evm/precompiles/weights-events), +[subnet lifecycle](/docs/guides/evm/precompiles/subnet-events), and +[runtime configuration](/docs/guides/evm/precompiles/configuration-events). +Each domain will have its own address. These precompiles report typed events +originating from `SubtensorModule` and `AdminUtils`; they do not expose raw +`RuntimeEvent` values or SCALE-encoded payloads. + +The callback inventories cover source variants with active emission sites in +the current runtime. An enum-only placeholder is not presented as a live +callback. If such a variant starts being emitted, its typed callback must be +added without changing the existing subscription or receiver selectors. + +### Subscription control + +Each event precompile should expose the same control shape: + +```solidity +struct EventFilter { + uint256 eventMask; + uint16 netuid; + bytes32 accountId; + bool matchAnyNetuid; + bool matchAnyAccount; +} + +struct Subscription { + bool active; + EventFilter filter; + uint64 callbackGasLimit; + uint64 nextSequence; +} + +function subscribe( + EventFilter calldata filter, + uint64 callbackGasLimit +) external; + +function unsubscribe() external; + +function getSubscription( + address subscriber +) external view returns (Subscription memory); + +function minimumCallbackBalance( + uint64 callbackGasLimit +) external view returns (uint256); +``` + +The caller is always the subscriber: a contract cannot subscribe or unsubscribe +another address. One fixed-size subscription per contract and domain keeps +lookup and update costs bounded. The event mask and optional single-netuid and +single-account filters let a subscriber narrow delivery without storing or +iterating an arbitrary filter list. + +`subscribe` succeeds only when the contract's own TAO balance can fund the +documented minimum number of callback attempts at its selected gas limit. Each +attempt is charged to that same balance. If the balance can no longer pay for +an attempt, the subscription is automatically removed. A reverting callback is +charged for the work it consumed and cannot revert the runtime operation that +produced the event. + +### Typed callbacks and delivery + +Every report has a stable, event-specific callback selector. Substrate account +IDs are represented as `bytes32`, and TAO and Alpha balances are multiplied by +`10^9` for EVM's 18-decimal convention. New source events add callback +selectors; released callbacks are never changed, removed, or reused. + +Callbacks are asynchronous notifications, not part of the transaction or hook +that produced the source event. Every callback includes a monotonically +increasing sequence and source block number so receivers can order deliveries +and detect a gap. A receiver must make its callback idempotent and must not +assume delivery in the source event's block. + +The runtime must not iterate every subscriber while emitting an event. Instead, +emission appends one fixed-size typed report to a bounded queue in O(1), and a +bounded amount of later block work advances a subscriber cursor one delivery at +a time. Callback gas is capped, delivery is protected against reentrancy, and a +callback cannot recursively create more callback work. + +Variable-length pallet events are normalized into bounded item callbacks. For +example, miner emissions are reported one UID at a time and a batch of weight +hashes is reported one hash at a time, with the same source sequence plus item +index and item count. The adapter must produce those items incrementally at the +source rather than copy or ABI-encode an unbounded vector. + +The queue has a fixed capacity so event reporting cannot grow runtime memory +without bound. If delivery falls behind far enough to overwrite an undelivered +report, the next successful callback exposes the sequence gap. Event callbacks +are therefore best-effort integration signals; contracts that require +authoritative recovery must use the corresponding typed view. + +## Function lifecycle + +Deprecation and disablement are different dimensions: + +- **Deprecation** communicates API evolution. It normally points callers toward + a replacement and is expected to remain part of the function's history. +- **Disablement** is an operational switch for an entire precompile. Root can + disable and later re-enable it through + `AdminUtils.sudo_toggle_evm_precompile`. + +| Lifecycle condition | Call behavior | +|---|---| +| Active and enabled | Executes normally | +| Soft-deprecated and enabled | Preserves its documented behavior | +| Hard-deprecated and enabled | Returns a descriptive precompile error | +| Disabled | Returns a precompile-disabled error regardless of function lifecycle | + +Soft deprecation is the default. Hard deprecation is reserved for cases where +the original behavior cannot be represented honestly or safely—for example, +when the underlying concept has been removed without a replacement. + +Disablement does not erase deprecation metadata. A soft-deprecated function can +also be disabled, and re-enabling its precompile restores its soft-deprecated +behavior. + +## Discovering status + +The proposed standalone registry precompile gives tooling and contracts one +place to inspect both API lifecycle and operational availability. + +Because the result covers both lifecycle and operational availability, it is +called `PrecompileStatus`: + +```solidity +interface IPrecompileRegistry { + struct PrecompileStatus { + bool isDeprecated; + bool isDisabled; + address newPrecompile; + bytes4 newSelector; + string message; + } + + function getPrecompileStatus( + address precompile, + bytes4 selector + ) external view returns (PrecompileStatus memory); +} +``` + +The fields have the following meaning: + +| Field | Meaning | +|---|---| +| `isDeprecated` | The function is soft- or hard-deprecated. | +| `isDisabled` | The containing precompile is currently disabled by Root; Root can re-enable it. | +| `newPrecompile` | Address of the recommended replacement, often the same address. | +| `newSelector` | Selector of the recommended replacement function. | +| `message` | Human-readable status or migration guidance. | + +Zero replacement fields mean that no replacement is available. Tooling should +not infer that `isDisabled` implies deprecation, or that re-enabling a +precompile clears `isDeprecated`. + +The registry avoids adding overhead to every deprecated call. Deployment tools, +frontends, and upgradeable contracts can query it when evaluating dependencies. + +Solidity interfaces should also carry NatSpec annotations: + +```solidity +interface IMetagraph { + /// @deprecated Use getStakeV2 instead. + function getStake( + uint16 netuid, + uint16 uid + ) external view returns (uint64); + + function getStakeV2( + uint16 netuid, + uint16 uid + ) external view returns (StakeInfo memory); +} +``` + +## Handling runtime changes + +### Additive representation changes + +Keep the original function returning the original subset, add a versioned +function for the extended result, and soft-deprecate the original if callers +should migrate. + +### Semantic refinements + +Adapt the original implementation to preserve its documented meaning. Add a new +version only when callers need a representation that the original return type +cannot express. + +### Storage and computation changes + +Change the precompile implementation without changing its interface. This +includes changing: + +- storage names, key shapes, or hashers; +- the number of storage items used; +- intermediate representations; +- the computation used to produce the exposed value. + +### Complete removal + +Keep the selector reserved and make the function return a descriptive error. +Mark it hard-deprecated and explain whether an alternative exists. Do not +delete the signature and do not reuse its selector. + +### Emergency disablement + +Root may disable a precompile with: + +```text +AdminUtils.sudo_toggle_evm_precompile(precompile_id, false) +``` + +and re-enable it with: + +```text +AdminUtils.sudo_toggle_evm_precompile(precompile_id, true) +``` + +This switch is reversible and applies to the precompile as a whole. It is not a +substitute for function-level lifecycle metadata or a normal deprecation +process. + +## Maintenance and testing requirements + +Every precompile change should verify: + +- all previously released selectors remain routed; +- existing function signatures and return encodings are unchanged; +- old semantics are preserved or explicitly hard-deprecated; +- new behavior uses a new versioned selector when necessary; +- Solidity interfaces, generated ABIs, SDK copies, and runtime implementations + agree; +- lifecycle registry metadata and NatSpec annotations agree; +- disable and re-enable behavior is covered for the affected precompile; +- no selector is reused. + +Typed views provide a compile-time safety advantage: when runtime types or +storage APIs change, the Rust implementation is more likely to stop compiling, +forcing maintainers to make an explicit compatibility decision. Coverage checks +should ensure that every storage item in the authorized pallets has a +corresponding view. + +Macro or code-generation support may eventually reduce boilerplate and validate +selector coverage, ABI synchronization, and registry entries. The compatibility +rules should remain explicit even if their enforcement becomes automated. + +## Summary + +Precompiles are a long-lived contract between Subtensor and deployed EVM code. +Keep addresses and released selectors stable, version functions additively, +preserve old semantics whenever possible, and replace raw storage access with +typed views that insulate callers from storage layouts. Use deprecation to guide +migration and reversible disablement to handle operational risk; report both +through a common status model without treating them as the same condition. diff --git a/docs/guides/evm/precompiles/account-balance.mdx b/docs/guides/evm/precompiles/account-balance.mdx new file mode 100644 index 0000000000..4fb1e89612 --- /dev/null +++ b/docs/guides/evm/precompiles/account-balance.mdx @@ -0,0 +1,20 @@ +--- +title: Account balance +description: Reference for the deployed BalancePrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `BalancePrecompile` | +| Solidity interface | `IBalance` | +| Address | `0x000000000000000000000000000000000000080e` | +| Status | Deployed | + +## Functions + +| Function | Mutability | +|---|---| +| `getFreeBalance(bytes32)` | `view` | + +Source: [`balance.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balance.sol) + diff --git a/docs/guides/evm/precompiles/address-mapping.mdx b/docs/guides/evm/precompiles/address-mapping.mdx new file mode 100644 index 0000000000..1561208e92 --- /dev/null +++ b/docs/guides/evm/precompiles/address-mapping.mdx @@ -0,0 +1,20 @@ +--- +title: Address mapping +description: Reference for the deployed AddressMappingPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `AddressMappingPrecompile` | +| Solidity interface | `IAddressMapping` | +| Address | `0x000000000000000000000000000000000000080c` | +| Status | Deployed | + +## Functions + +| Function | Mutability | +|---|---| +| `addressMapping(address)` | `view` | + +Source: [`addressMapping.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/addressMapping.sol) + diff --git a/docs/guides/evm/precompiles/alpha.mdx b/docs/guides/evm/precompiles/alpha.mdx new file mode 100644 index 0000000000..c45aba78f7 --- /dev/null +++ b/docs/guides/evm/precompiles/alpha.mdx @@ -0,0 +1,40 @@ +--- +title: Alpha +description: Reference for the deployed AlphaPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `AlphaPrecompile` | +| Solidity interface | `IAlpha` | +| Address | `0x0000000000000000000000000000000000000808` | +| Status | Deployed | + +Provides typed views of subnet pools, prices, issuance, emissions, and simulated +swaps. All functions are `view`. + +## Functions + +```text +getAlphaPrice(uint16) +getMovingAlphaPrice(uint16) +getTaoInPool(uint16) +getAlphaInPool(uint16) +getAlphaOutPool(uint16) +getAlphaIssuance(uint16) +getTaoWeight() +simSwapTaoForAlpha(uint16,uint64) +simSwapAlphaForTao(uint16,uint64) +getSubnetMechanism(uint16) +getRootNetuid() +getEMAPriceHalvingBlocks(uint16) +getSubnetVolume(uint16) +getTaoInEmission(uint16) +getAlphaInEmission(uint16) +getAlphaOutEmission(uint16) +getSumAlphaPrice() +getCKBurn() +``` + +Source: [`alpha.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/alpha.sol) + diff --git a/docs/guides/evm/precompiles/balance-transfer.mdx b/docs/guides/evm/precompiles/balance-transfer.mdx new file mode 100644 index 0000000000..71b3f4c1ce --- /dev/null +++ b/docs/guides/evm/precompiles/balance-transfer.mdx @@ -0,0 +1,23 @@ +--- +title: Balance transfer +description: Reference for the deployed BalanceTransferPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `BalanceTransferPrecompile` | +| Solidity interface | `ISubtensorBalanceTransfer` | +| Address | `0x0000000000000000000000000000000000000800` | +| Status | Deployed | + +Transfers the EVM call value to the Substrate account supplied as a 32-byte +public key. + +## Functions + +| Function | Mutability | +|---|---| +| `transfer(bytes32)` | `payable` | + +Source: [`balanceTransfer.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balanceTransfer.sol) + diff --git a/docs/guides/evm/precompiles/configuration-events.mdx b/docs/guides/evm/precompiles/configuration-events.mdx new file mode 100644 index 0000000000..b3d1085b00 --- /dev/null +++ b/docs/guides/evm/precompiles/configuration-events.mdx @@ -0,0 +1,98 @@ +--- +title: Configuration events +description: Proposed subscription precompile for typed Subtensor and AdminUtils configuration callbacks. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `ConfigurationEventsPrecompile` | +| Proposed Solidity interface | `IConfigurationEvents` | +| Callback receiver interface | `IConfigurationEventsReceiver` | +| Address | Dedicated address not assigned | +| Status | Proposed | + +This precompile reports runtime and subnet configuration changes emitted by +`SubtensorModule` and `AdminUtils`. It normalizes the two pallets into +meaningful typed callbacks while retaining the source pallet in callback +metadata when both pallets can describe the same setting. + +## Proposed Subtensor callbacks + +| Receiver function | Subtensor source event | +|---|---| +| `onActivityCutoffChanged(...)` | `ActivityCutoffSet` | +| `onActivityCutoffFactorChanged(...)` | `ActivityCutoffFactorMilliSet` | +| `onAdjustmentAlphaChanged(...)` | `AdjustmentAlphaSet` | +| `onAdjustmentIntervalChanged(...)` | `AdjustmentIntervalSet` | +| `onAdminFreezeWindowChanged(...)` | `AdminFreezeWindowSet` | +| `onBondsMovingAverageChanged(...)` | `BondsMovingAverageSet` | +| `onBondsPenaltyChanged(...)` | `BondsPenaltySet` | +| `onBondsResetOnSetChanged(...)` | `BondsResetOnSet` | +| `onColdkeySwapAnnouncementDelayChanged(...)` | `ColdkeySwapAnnouncementDelaySet` | +| `onColdkeySwapReannouncementDelayChanged(...)` | `ColdkeySwapReannouncementDelaySet` | +| `onDifficultyChanged(...)` | `DifficultySet` | +| `onDissolutionScheduleDurationChanged(...)` | `DissolveNetworkScheduleDurationSet` | +| `onImmunityPeriodChanged(...)` | `ImmunityPeriodSet` | +| `onKappaChanged(...)` | `KappaSet` | +| `onMaxAllowedUidsChanged(...)` | `MaxAllowedUidsSet` | +| `onMaxAllowedValidatorsChanged(...)` | `MaxAllowedValidatorsSet` | +| `onMaxBurnChanged(...)` | `MaxBurnSet` | +| `onMaxChildKeyTakeChanged(...)` | `MaxChildKeyTakeSet` | +| `onMaxDelegateTakeChanged(...)` | `MaxDelegateTakeSet` | +| `onMaxDifficultyChanged(...)` | `MaxDifficultySet` | +| `onMaxEpochsPerBlockChanged(...)` | `MaxEpochsPerBlockSet` | +| `onMaxRegistrationsPerBlockChanged(...)` | `MaxRegistrationsPerBlockSet` | +| `onMinAllowedUidsChanged(...)` | `MinAllowedUidsSet` | +| `onMinAllowedWeightChanged(...)` | `MinAllowedWeightSet` | +| `onMinBurnChanged(...)` | `MinBurnSet` | +| `onMinChildKeyTakeChanged(...)` | `MinChildKeyTakeSet` | +| `onMinChildKeyTakeForSubnetChanged(...)` | `MinChildKeyTakePerSubnetSet` | +| `onMinDelegateTakeChanged(...)` | `MinDelegateTakeSet` | +| `onMinDifficultyChanged(...)` | `MinDifficultySet` | +| `onMinNonImmuneUidsChanged(...)` | `MinNonImmuneUidsSet` | +| `onNetworkImmunityPeriodChanged(...)` | `NetworkImmunityPeriodSet` | +| `onNetworkLockCostReductionIntervalChanged(...)` | `NetworkLockCostReductionIntervalSet` | +| `onNetworkMinimumLockCostChanged(...)` | `NetworkMinLockCostSet` | +| `onNetworkRateLimitChanged(...)` | `NetworkRateLimitSet` | +| `onOwnerHyperparameterRateLimitChanged(...)` | `OwnerHyperparamRateLimitSet` | +| `onPowRegistrationAllowedChanged(...)` | `PowRegistrationAllowed` | +| `onRaoRecycledForRegistrationChanged(...)` | `RAORecycledForRegistrationSet` | +| `onRegistrationAllowedChanged(...)` | `RegistrationAllowed` | +| `onRegistrationsPerIntervalChanged(...)` | `RegistrationPerIntervalSet` | +| `onScalingLawPowerChanged(...)` | `ScalingLawPowerSet` | +| `onServingRateLimitChanged(...)` | `ServingRateLimitSet` | +| `onStakeThresholdChanged(...)` | `StakeThresholdSet` | +| `onStartCallDelayChanged(...)` | `StartCallDelaySet` | +| `onSubnetLimitChanged(...)` | `SubnetLimitSet` | +| `onSubnetOwnerCutChanged(...)` | `SubnetOwnerCutSet` | +| `onTempoChanged(...)` | `TempoSet` | +| `onTransferEnabledChanged(...)` | `TransferToggle` | +| `onChildKeyTakeRateLimitChanged(...)` | `TxChildKeyTakeRateLimitSet` | +| `onDelegateTakeRateLimitChanged(...)` | `TxDelegateTakeRateLimitSet` | +| `onTransactionRateLimitChanged(...)` | `TxRateLimitSet` | +| `onValidatorPruneLengthChanged(...)` | `ValidatorPruneLenSet` | +| `onWeightsRateLimitChanged(...)` | `WeightsSetRateLimitSet` | +| `onWeightsVersionKeyChanged(...)` | `WeightsVersionKeySet` | + +## Proposed AdminUtils callbacks + +| Receiver function | AdminUtils source event | +|---|---| +| `onPrecompileAvailabilityChanged(...)` | `PrecompileUpdated` | +| `onYuma3EnabledChanged(...)` | `Yuma3EnableToggled` | +| `onBondsResetEnabledChanged(...)` | `BondsResetToggled` | +| `onBurnHalfLifeChanged(...)` | `BurnHalfLifeSet` | +| `onBurnIncreaseMultiplierChanged(...)` | `BurnIncreaseMultSet` | +| `onSubnetEmissionEnabledChanged(...)` | `SubnetEmissionEnabledSet` | +| `onCollateralLockShareChanged(...)` | `CollateralLockShareSet` | +| `onCollateralDrainRatioChanged(...)` | `CollateralDrainRatioSet` | + +Every callback begins with `uint64 sequence`, `uint64 sourceBlock`, and a typed +source-pallet value, followed by the setting's typed fields. Account IDs use +`bytes32`, netuids use `uint16`, and fixed-point values use a documented stable +EVM representation. + +Subscription behavior is defined in +[Subscription-based event reporting](/docs/guides/evm/precompile-design#subscription-based-event-reporting). +The names and signatures are provisional and do not reserve selectors. + diff --git a/docs/guides/evm/precompiles/crowdloan.mdx b/docs/guides/evm/precompiles/crowdloan.mdx new file mode 100644 index 0000000000..abdce95497 --- /dev/null +++ b/docs/guides/evm/precompiles/crowdloan.mdx @@ -0,0 +1,37 @@ +--- +title: Crowdloan +description: Reference for the deployed CrowdloanPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `CrowdloanPrecompile` | +| Solidity interface | `ICrowdloan` | +| Address | `0x0000000000000000000000000000000000000809` | +| Status | Deployed | + +## Views + +```text +getCrowdloan(uint32) +getContribution(uint32,bytes32) +``` + +## Operations + +All operations are `payable`: + +```text +create(uint64,uint64,uint64,uint32,address) +contribute(uint32,uint64) +withdraw(uint32) +finalize(uint32) +refund(uint32) +dissolve(uint32) +updateMinContribution(uint32,uint64) +updateEnd(uint32,uint32) +updateCap(uint32,uint64) +``` + +Source: [`crowdloan.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/crowdloan.sol) + diff --git a/docs/guides/evm/precompiles/drand.mdx b/docs/guides/evm/precompiles/drand.mdx new file mode 100644 index 0000000000..9e8bf552f3 --- /dev/null +++ b/docs/guides/evm/precompiles/drand.mdx @@ -0,0 +1,35 @@ +--- +title: Drand +description: Proposed typed EVM interface for the Drand pallet. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `DrandPrecompile` | +| Proposed Solidity interface | `IDrand` | +| Address | Not assigned | +| Status | Proposed | + +This precompile would expose typed beacon configuration and pulse data instead +of requiring callers to construct Drand storage keys and decode SCALE values. + +## Planned views + +| Function | Replaces | +|---|---| +| `getBeaconConfig()` | `Drand.BeaconConfig` | +| `getPulse(uint64 round)` | `Drand.Pulses` | +| `getStoredRoundRange()` | `Drand.OldestStoredRound` and `Drand.LastStoredRound` | +| `getNextUnsignedAt()` | `Drand.NextUnsignedAt` | +| `hasMigrationRun(bytes key)` | `Drand.HasMigrationRun` | + +## Planned operations + +```text +writePulse +setBeaconConfig +setOldestStoredRound +``` + +The runtime's existing signed, unsigned, and Root origin checks remain in force. +Names and signatures on this page are provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/index.mdx b/docs/guides/evm/precompiles/index.mdx new file mode 100644 index 0000000000..c0ed62162b --- /dev/null +++ b/docs/guides/evm/precompiles/index.mdx @@ -0,0 +1,60 @@ +--- +title: Precompiles +description: Addresses, implementations, and reference pages for Bittensor EVM precompiles. +--- + +Bittensor precompiles are fixed-address contracts implemented by the Subtensor +runtime. `Deployed` means that the address is registered in the current runtime; +it does not imply complete coverage of the underlying runtime domain. +`Proposed` precompiles have no assigned address or released selectors. + +## Ethereum and Frontier precompiles + +| Precompile | Address | Status | +|---|---|---| +| `ECRecover` | | Deployed | +| `Sha256` | | Deployed | +| `Ripemd160` | | Deployed | +| `Identity` | | Deployed | +| `Modexp` | | Deployed | +| `Dispatch` | | Deployed | +| `Bn128Mul` | | Deployed | +| `Bn128Pairing` | | Deployed | +| `Bn128Add` | | Deployed | +| `Sha3FIPS256` | | Deployed | +| `ECRecoverPublicKey` | | Deployed | +| `Ed25519Verify` | | Deployed | +| `Sr25519Verify` | | Deployed | + +## Bittensor precompiles + +| Precompile | Solidity interface | Details | +|---|---|---| +| [`BalanceTransferPrecompile`](/docs/guides/evm/precompiles/balance-transfer) | `ISubtensorBalanceTransfer` |
Deployed | +| [`StakingPrecompile`](/docs/guides/evm/precompiles/staking-v1) | `IStaking` V1 |
Deployed | +| [`MetagraphPrecompile`](/docs/guides/evm/precompiles/metagraph) | `IMetagraph` |
Deployed | +| [`SubnetPrecompile`](/docs/guides/evm/precompiles/subnet) | `ISubnet` |
Deployed | +| [`NeuronPrecompile`](/docs/guides/evm/precompiles/neuron) | `INeuron` |
Deployed | +| [`StakingPrecompileV2`](/docs/guides/evm/precompiles/staking-v2) | `IStaking` V2 |
Deployed | +| [`UidLookupPrecompile`](/docs/guides/evm/precompiles/uid-lookup) | `IUidLookup` |
Deployed | +| [`StorageQueryPrecompile`](/docs/guides/evm/precompiles/storage-query) | Selectorless |
Deployed · deprecation planned | +| [`AlphaPrecompile`](/docs/guides/evm/precompiles/alpha) | `IAlpha` |
Deployed | +| [`CrowdloanPrecompile`](/docs/guides/evm/precompiles/crowdloan) | `ICrowdloan` |
Deployed | +| [`LeasingPrecompile`](/docs/guides/evm/precompiles/leasing) | `ILeasing` |
Deployed | +| [`ProxyPrecompile`](/docs/guides/evm/precompiles/proxy) | `IProxy` |
Deployed | +| [`AddressMappingPrecompile`](/docs/guides/evm/precompiles/address-mapping) | `IAddressMapping` |
Deployed | +| [`VotingPowerPrecompile`](/docs/guides/evm/precompiles/voting-power) | `IVotingPower` |
Deployed | +| [`BalancePrecompile`](/docs/guides/evm/precompiles/account-balance) | `IBalance` |
Deployed | +| [`SchedulerPrecompile`](/docs/guides/evm/precompiles/scheduler) | `IScheduler` | Address not assigned
Proposed | +| [`DrandPrecompile`](/docs/guides/evm/precompiles/drand) | `IDrand` | Address not assigned
Proposed | +| [`TimestampPrecompile`](/docs/guides/evm/precompiles/timestamp) | `ITimestamp` | Address not assigned
Proposed | +| [`StakingEventsPrecompile`](/docs/guides/evm/precompiles/staking-events) | `IStakingEvents` | Dedicated address not assigned
Proposed | +| [`NeuronEventsPrecompile`](/docs/guides/evm/precompiles/neuron-events) | `INeuronEvents` | Dedicated address not assigned
Proposed | +| [`WeightsEventsPrecompile`](/docs/guides/evm/precompiles/weights-events) | `IWeightsEvents` | Dedicated address not assigned
Proposed | +| [`SubnetEventsPrecompile`](/docs/guides/evm/precompiles/subnet-events) | `ISubnetEvents` | Dedicated address not assigned
Proposed | +| [`ConfigurationEventsPrecompile`](/docs/guides/evm/precompiles/configuration-events) | `IConfigurationEvents` | Dedicated address not assigned
Proposed | +| [`PrecompileRegistry`](/docs/guides/evm/precompiles/registry) | `IPrecompileRegistry` | Address not assigned
Proposed | + +Released addresses and selectors remain reserved permanently. The compatibility +and lifecycle rules are documented in +[Precompile design and lifecycle](/docs/guides/evm/precompile-design). diff --git a/docs/guides/evm/precompiles/leasing.mdx b/docs/guides/evm/precompiles/leasing.mdx new file mode 100644 index 0000000000..e4a910e574 --- /dev/null +++ b/docs/guides/evm/precompiles/leasing.mdx @@ -0,0 +1,31 @@ +--- +title: Leasing +description: Reference for the deployed LeasingPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `LeasingPrecompile` | +| Solidity interface | `ILeasing` | +| Address | `0x000000000000000000000000000000000000080a` | +| Status | Deployed | + +## Views + +```text +getLease(uint32) +getContributorShare(uint32,bytes32) +getLeaseIdForSubnet(uint16) +``` + +## Operations + +```text +createLeaseCrowdloan(uint64,uint64,uint64,uint32,uint8,bool,uint32) +terminateLease(uint32,bytes32) +``` + +Both operations are `payable`. + +Source: [`leasing.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/leasing.sol) + diff --git a/docs/guides/evm/precompiles/meta.json b/docs/guides/evm/precompiles/meta.json new file mode 100644 index 0000000000..07144223c0 --- /dev/null +++ b/docs/guides/evm/precompiles/meta.json @@ -0,0 +1,31 @@ +{ + "title": "Precompiles", + "pages": [ + "index", + "balance-transfer", + "staking-v1", + "metagraph", + "subnet", + "neuron", + "staking-v2", + "uid-lookup", + "storage-query", + "alpha", + "crowdloan", + "leasing", + "proxy", + "address-mapping", + "voting-power", + "account-balance", + "---Proposed---", + "scheduler", + "drand", + "timestamp", + "staking-events", + "neuron-events", + "weights-events", + "subnet-events", + "configuration-events", + "registry" + ] +} diff --git a/docs/guides/evm/precompiles/metagraph.mdx b/docs/guides/evm/precompiles/metagraph.mdx new file mode 100644 index 0000000000..3b40492d35 --- /dev/null +++ b/docs/guides/evm/precompiles/metagraph.mdx @@ -0,0 +1,38 @@ +--- +title: Metagraph +description: Reference for the deployed MetagraphPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `MetagraphPrecompile` | +| Solidity interface | `IMetagraph` | +| Address | `0x0000000000000000000000000000000000000802` | +| Status | Deployed | + +Provides typed views of per-neuron metagraph values. + +## Functions + +All functions are `view`: + +```text +getUidCount(uint16) +getStake(uint16,uint16) +getRank(uint16,uint16) +getTrust(uint16,uint16) +getConsensus(uint16,uint16) +getIncentive(uint16,uint16) +getDividends(uint16,uint16) +getEmission(uint16,uint16) +getVtrust(uint16,uint16) +getValidatorStatus(uint16,uint16) +getLastUpdate(uint16,uint16) +getIsActive(uint16,uint16) +getAxon(uint16,uint16) +getHotkey(uint16,uint16) +getColdkey(uint16,uint16) +``` + +Source: [`metagraph.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/metagraph.sol) + diff --git a/docs/guides/evm/precompiles/neuron-events.mdx b/docs/guides/evm/precompiles/neuron-events.mdx new file mode 100644 index 0000000000..a66dc25a87 --- /dev/null +++ b/docs/guides/evm/precompiles/neuron-events.mdx @@ -0,0 +1,50 @@ +--- +title: Neuron and key events +description: Proposed subscription precompile for typed Subtensor neuron, identity, relationship, and key-rotation callbacks. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `NeuronEventsPrecompile` | +| Proposed Solidity interface | `INeuronEvents` | +| Callback receiver interface | `INeuronEventsReceiver` | +| Address | Dedicated address not assigned | +| Status | Proposed | + +This precompile reports neuron registration and serving changes, hotkey and +coldkey rotations, identities, EVM-key associations, and child relationships +emitted by `SubtensorModule`. + +## Proposed callbacks + +| Receiver function | Subtensor source event | +|---|---| +| `onNeuronRegistered(...)` | `NeuronRegistered` | +| `onAxonServed(...)` | `AxonServed` | +| `onPrometheusServed(...)` | `PrometheusServed` | +| `onHotkeySwapped(...)` | `HotkeySwapped` | +| `onHotkeySwappedOnSubnet(...)` | `HotkeySwappedOnSubnet` | +| `onColdkeySwapAnnounced(...)` | `ColdkeySwapAnnounced` | +| `onColdkeySwapReset(...)` | `ColdkeySwapReset` | +| `onColdkeySwapped(...)` | `ColdkeySwapped` | +| `onColdkeySwapDisputed(...)` | `ColdkeySwapDisputed` | +| `onColdkeySwapCleared(...)` | `ColdkeySwapCleared` | +| `onChildrenScheduled(...)` | `SetChildrenScheduled` | +| `onChildScheduled(...)` | One item from `SetChildrenScheduled` | +| `onChildrenSet(...)` | `SetChildren` | +| `onChildSet(...)` | One item from `SetChildren` | +| `onChainIdentitySet(...)` | `ChainIdentitySet` | +| `onEvmKeyAssociated(...)` | `EvmKeyAssociated` | + +The schedule and children summary callbacks carry the hotkey, netuid, and item +count. Their item callbacks carry one child and proportion at a time, using a +shared source sequence, item index, and item count; no callback contains an +unbounded array. + +All callbacks also carry the source block. Account IDs and hashes use +`bytes32`, and the associated EVM key uses `address`. + +Subscription behavior is defined in +[Subscription-based event reporting](/docs/guides/evm/precompile-design#subscription-based-event-reporting). +The names and signatures are provisional and do not reserve selectors. + diff --git a/docs/guides/evm/precompiles/neuron.mdx b/docs/guides/evm/precompiles/neuron.mdx new file mode 100644 index 0000000000..c4940dacdd --- /dev/null +++ b/docs/guides/evm/precompiles/neuron.mdx @@ -0,0 +1,30 @@ +--- +title: Neuron +description: Reference for the deployed NeuronPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `NeuronPrecompile` | +| Solidity interface | `INeuron` | +| Address | `0x0000000000000000000000000000000000000804` | +| Status | Deployed | + +Registers neurons, publishes serving endpoints, and submits weights. Every +function is `payable`. + +## Functions + +```text +burnedRegister(uint16,bytes32) +registerLimit(uint16,bytes32,uint64) +serveAxon(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8) +serveAxonTls(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8,bytes) +servePrometheus(uint16,uint32,uint128,uint16,uint8) +setWeights(uint16,uint16[],uint16[],uint64) +commitWeights(uint16,bytes32) +revealWeights(uint16,uint16[],uint16[],uint16[],uint64) +``` + +Source: [`neuron.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/neuron.sol) + diff --git a/docs/guides/evm/precompiles/proxy.mdx b/docs/guides/evm/precompiles/proxy.mdx new file mode 100644 index 0000000000..5e3fdf71f2 --- /dev/null +++ b/docs/guides/evm/precompiles/proxy.mdx @@ -0,0 +1,27 @@ +--- +title: Proxy +description: Reference for the deployed ProxyPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `ProxyPrecompile` | +| Solidity interface | `IProxy` | +| Address | `0x000000000000000000000000000000000000080b` | +| Status | Deployed | + +## Functions + +| Function | Mutability | +|---|---| +| `createPureProxy(uint8,uint32,uint16)` | nonpayable | +| `proxyCall(bytes32,uint8[],uint8[])` | nonpayable | +| `killPureProxy(bytes32,uint8,uint16,uint32,uint32)` | nonpayable | +| `addProxy(bytes32,uint8,uint32)` | nonpayable | +| `removeProxy(bytes32,uint8,uint32)` | nonpayable | +| `removeProxies()` | nonpayable | +| `pokeDeposit()` | nonpayable | +| `getProxies(bytes32)` | `view` | + +Source: [`proxy.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/proxy.sol) + diff --git a/docs/guides/evm/precompiles/registry.mdx b/docs/guides/evm/precompiles/registry.mdx new file mode 100644 index 0000000000..8c7ad14b4d --- /dev/null +++ b/docs/guides/evm/precompiles/registry.mdx @@ -0,0 +1,39 @@ +--- +title: Precompile registry +description: Proposed registry for precompile lifecycle and availability. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `PrecompileRegistry` | +| Proposed Solidity interface | `IPrecompileRegistry` | +| Address | Not assigned | +| Status | Proposed | + +The registry provides function-level lifecycle metadata and the current +operational availability of the containing precompile. + +## Proposed interface + +```solidity +interface IPrecompileRegistry { + struct PrecompileStatus { + bool isDeprecated; + bool isDisabled; + address newPrecompile; + bytes4 newSelector; + string message; + } + + function getPrecompileStatus( + address precompile, + bytes4 selector + ) external view returns (PrecompileStatus memory); +} +``` + +The lifecycle model is described in +[Precompile design and lifecycle](/docs/guides/evm/precompile-design#discovering-status). +The address and selector are not reserved until the interface is implemented +and released. + diff --git a/docs/guides/evm/precompiles/scheduler.mdx b/docs/guides/evm/precompiles/scheduler.mdx new file mode 100644 index 0000000000..64992b280c --- /dev/null +++ b/docs/guides/evm/precompiles/scheduler.mdx @@ -0,0 +1,49 @@ +--- +title: Scheduler +description: Proposed typed EVM interface for the Scheduler pallet. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `SchedulerPrecompile` | +| Proposed Solidity interface | `IScheduler` | +| Address | Not assigned | +| Status | Proposed | + +This precompile would replace raw reads of Scheduler storage and expose the +Scheduler extrinsics through a stable EVM interface. + +## Planned views + +| Function | Replaces | +|---|---| +| `getIncompleteSince()` | `Scheduler.IncompleteSince` | +| `getScheduledCall(uint64 when,uint32 index)` | One entry of `Scheduler.Agenda` | +| `getScheduledCallCount(uint64 when)` | The bounded agenda length for a block | +| `getRetry(uint64 when,uint32 index)` | `Scheduler.Retries` | +| `getTaskAddress(bytes32 taskId)` | `Scheduler.Lookup` | + +Returning one agenda entry at a time keeps execution bounded and avoids an +unbounded array result. + +## Planned operations + +```text +schedule +cancel +scheduleNamed +cancelNamed +scheduleAfter +scheduleNamedAfter +setRetry +setRetryNamed +cancelRetry +cancelRetryNamed +``` + +Scheduled payloads must use a versioned, stable EVM call description. They must +not expose SCALE-encoded `RuntimeCall`, whose encoding can change after a +runtime upgrade. + +Names and signatures on this page are provisional and do not reserve selectors. + diff --git a/docs/guides/evm/precompiles/staking-events.mdx b/docs/guides/evm/precompiles/staking-events.mdx new file mode 100644 index 0000000000..209670e080 --- /dev/null +++ b/docs/guides/evm/precompiles/staking-events.mdx @@ -0,0 +1,56 @@ +--- +title: Staking events +description: Proposed subscription precompile for typed Subtensor staking, delegation, Alpha-flow, lock, and collateral callbacks. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `StakingEventsPrecompile` | +| Proposed Solidity interface | `IStakingEvents` | +| Callback receiver interface | `IStakingEventsReceiver` | +| Address | Dedicated address not assigned | +| Status | Proposed | + +This precompile reports the economic and staking events emitted by +`SubtensorModule`. A contract subscribes itself through the common +[subscription interface](/docs/guides/evm/precompile-design#subscription-control) +and implements only the callbacks selected by its event mask. + +## Proposed callbacks + +| Receiver function | Subtensor source event | +|---|---| +| `onStakeAdded(...)` | `StakeAdded` | +| `onStakeRemoved(...)` | `StakeRemoved` | +| `onStakeMoved(...)` | `StakeMoved` | +| `onStakeTransferred(...)` | `StakeTransferred` | +| `onStakeAndHotkeyTransferred(...)` | `StakeAndHotkeyTransferred` | +| `onStakeSwapped(...)` | `StakeSwapped` | +| `onAlphaRecycled(...)` | `AlphaRecycled` | +| `onAlphaBurned(...)` | `AlphaBurned` | +| `onStakeBurned(...)` | `AddStakeBurn` | +| `onAutoStakeAdded(...)` | `AutoStakeAdded` | +| `onAutoStakeDestinationChanged(...)` | `AutoStakeDestinationSet` | +| `onStakeLocked(...)` | `StakeLocked` | +| `onLockMoved(...)` | `LockMoved` | +| `onCollateralLocked(...)` | `CollateralLocked` | +| `onMinimumCollateralChanged(...)` | `MinCollateralSet` | +| `onDelegateTakeIncreased(...)` | `TakeIncreased` | +| `onDelegateTakeDecreased(...)` | `TakeDecreased` | +| `onChildKeyTakeChanged(...)` | `ChildKeyTakeSet` | +| `onAutoParentDelegationChanged(...)` | `AutoParentDelegationEnabledSet` | +| `onRootClaimed(...)` | `RootClaimed` | +| `onRootClaimTypeChanged(...)` | `RootClaimTypeSet` | +| `onPerpetualLockChanged(...)` | `PerpetualLockUpdated` | +| `onLockedAlphaAcceptanceChanged(...)` | `RejectLockedAlphaUpdated` | +| `onFaucetFunded(...)` | `Faucet` | + +`onAutoStakeAdded` covers the current staking event emitted from a runtime hook. +The remaining callbacks also make transaction- and scheduled-operation events +available through the same receiver model. + +Each callback begins with `uint64 sequence` and `uint64 sourceBlock`, followed +by typed fields corresponding to the source event. Account IDs use `bytes32`; +TAO and Alpha amounts use 18-decimal `uint256` values. + +The names and signatures are provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/staking-v1.mdx b/docs/guides/evm/precompiles/staking-v1.mdx new file mode 100644 index 0000000000..b29cf3f203 --- /dev/null +++ b/docs/guides/evm/precompiles/staking-v1.mdx @@ -0,0 +1,29 @@ +--- +title: Staking V1 +description: Reference for the deployed legacy StakingPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `StakingPrecompile` | +| Solidity interface | `IStaking` V1 | +| Address | `0x0000000000000000000000000000000000000801` | +| Status | Deployed | + +This legacy interface remains available for deployed callers. New staking +functionality belongs on [Staking V2](./staking-v2). + +## Functions + +| Function | Mutability | +|---|---| +| `addStake(bytes32,uint256)` | `payable` | +| `removeStake(bytes32,uint256,uint256)` | nonpayable | +| `getTotalColdkeyStake(bytes32)` | `view` | +| `getTotalHotkeyStake(bytes32)` | `view` | +| `addProxy(bytes32)` | nonpayable | +| `removeProxy(bytes32)` | nonpayable | +| `getStake(bytes32,bytes32,uint256)` | `view` | + +Source: [`staking.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/staking.sol) + diff --git a/docs/guides/evm/precompiles/staking-v2.mdx b/docs/guides/evm/precompiles/staking-v2.mdx new file mode 100644 index 0000000000..1eea74daac --- /dev/null +++ b/docs/guides/evm/precompiles/staking-v2.mdx @@ -0,0 +1,79 @@ +--- +title: Staking V2 +description: Reference for the deployed StakingPrecompileV2. +--- + +| Property | Value | +|---|---| +| Rust implementation | `StakingPrecompileV2` | +| Solidity interface | `IStaking` V2 | +| Address | `0x0000000000000000000000000000000000000805` | +| Status | Deployed | + +This is the current staking interface. The V1 address remains available for +backward compatibility. + +## Stake operations + +```text +addStake(bytes32,uint256,uint256) +addStakeLimit(bytes32,uint256,uint256,bool,uint256) +removeStake(bytes32,uint256,uint256) +removeStakeLimit(bytes32,uint256,uint256,bool,uint256) +removeStakeFull(bytes32,uint256) +removeStakeFullLimit(bytes32,uint256,uint256) +moveStake(bytes32,bytes32,uint256,uint256,uint256) +transferStake(bytes32,bytes32,uint256,uint256,uint256) +burnAlpha(bytes32,uint256,uint256) +``` + +These functions are `payable`. + +## Stake views + +```text +getStake(bytes32,bytes32,uint256) +getStakeInfoForColdkeyAndNetuid(bytes32,uint256,bytes32[]) +getTotalColdkeyStake(bytes32) +getTotalColdkeyStakeOnSubnet(bytes32,uint256) +getTotalHotkeyStake(bytes32) +getAlphaStakedValidators(bytes32,uint256) +getTotalAlphaStaked(bytes32,uint256) +getNominatorMinRequiredStake() +getDefaultMinStake() +``` + +These functions are `view`. + +## Locks and account policy + +```text +lockStake(bytes32,uint256,uint256) +moveLock(bytes32,uint256) +setPerpetualLock(uint256,bool) +setRejectLockedAlpha(bool) +getColdkeyLock(bytes32,uint256) +getHotkeyLock(bytes32,uint256) +getHotkeyConvictions(uint256,bytes32[]) +getLockRates() +getRejectLockedAlpha(bytes32) +``` + +The `get` functions are `view`; the other functions are `payable`. + +## Proxies and stake allowances + +```text +addProxy(bytes32) +removeProxy(bytes32) +approve(address,uint256,uint256) +allowance(address,address,uint256) +increaseAllowance(address,uint256,uint256) +decreaseAllowance(address,uint256,uint256) +transferStakeFrom(address,address,bytes32,uint256,uint256,uint256) +``` + +`allowance` is `view`. Refer to the published ABI for the mutability and return +encoding of the allowance mutations. + +Source: [`stakingV2.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/stakingV2.sol) diff --git a/docs/guides/evm/precompiles/storage-query.mdx b/docs/guides/evm/precompiles/storage-query.mdx new file mode 100644 index 0000000000..5dc7300588 --- /dev/null +++ b/docs/guides/evm/precompiles/storage-query.mdx @@ -0,0 +1,65 @@ +--- +title: Storage query +description: Reference for the deployed selectorless StorageQueryPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `StorageQueryPrecompile` | +| Solidity interface | None | +| Address | `0x0000000000000000000000000000000000000807` | +| Status | Deployed · deprecation planned | + +This precompile has no named Solidity functions or four-byte function selector. +The complete call data is interpreted as a raw Substrate storage key. It returns +the stored SCALE-encoded bytes, or empty bytes when the key does not exist. + +Only keys whose first 16 bytes match an authorized pallet prefix are accepted: +SubtensorModule, Swap, Balances, Proxy, Scheduler, Drand, Crowdloan, Sudo, +Multisig, and Timestamp. + +Raw storage access is brittle because callers depend on runtime storage names, +hashers, key formats, and SCALE encodings. + +## Planned deprecation + + + Storage Query is still deployed and callable. Deprecation is planned, but it + does not begin until suitable typed replacement coverage is available. + + +The planned lifecycle is: + +1. Add typed views for all storage currently authorized through this + precompile. +2. Soft-deprecate Storage Query. Existing calls continue to execute identically + while the registry and documentation direct new callers to typed functions. +3. Allow a documented migration window for existing contracts and tooling. +4. Hard-deprecate Storage Query so calls return a descriptive precompile error. +5. Eventually disable the precompile through the existing Root-controlled + precompile switch. + +No migration-window length or activation block has been assigned. The general +lifecycle rules are described in +[Precompile design and lifecycle](/docs/guides/evm/precompile-design#phasing-out-raw-storage-reads). + +## Replacement destinations + +Typed coverage should be completed at existing domain addresses whenever a +compatible domain already exists. A new address is proposed only when no +existing precompile has a coherent responsibility for that state. + +| Authorized storage prefix | Typed replacement | +|---|---| +| `SubtensorModule` | Extend [Staking V2](./staking-v2), [Metagraph](./metagraph), [Subnet](./subnet), [Neuron](./neuron), [Alpha](./alpha), [Leasing](./leasing), [UID lookup](./uid-lookup), [Address mapping](./address-mapping), and [Voting power](./voting-power), according to the meaning of each value. | +| `Swap` | Extend [Alpha](./alpha) with typed liquidity, fee, balancer, reservoir, initialization, and migration-status views. | +| `Balances` | Extend [Account balance](./account-balance) with typed account, issuance, lock, reserve, hold, and freeze views. | +| `Proxy` | Extend [Proxy](./proxy) with typed announcement, last-call-result, and fee-payer views. | +| `Crowdloan` | Extend [Crowdloan](./crowdloan) with typed ID, contribution-limit, current-operation, and migration-status views. | +| `Scheduler` | Add the proposed [Scheduler](./scheduler) precompile. | +| `Drand` | Add the proposed [Drand](./drand) precompile. | +| `Sudo` | No dedicated EVM precompile is proposed; this access must be addressed explicitly before Storage Query is deprecated. | +| `Multisig` | No dedicated EVM precompile is proposed; this access must be addressed explicitly before Storage Query is deprecated. | +| `Timestamp` | Add the proposed [Timestamp](./timestamp) precompile for complete typed coverage; `getTimestamp()` is equivalent to the existing EVM `block.timestamp` value. | + +Source: [`storage_query.rs`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/storage_query.rs) diff --git a/docs/guides/evm/precompiles/subnet-events.mdx b/docs/guides/evm/precompiles/subnet-events.mdx new file mode 100644 index 0000000000..f1e8e5d8a4 --- /dev/null +++ b/docs/guides/evm/precompiles/subnet-events.mdx @@ -0,0 +1,80 @@ +--- +title: Subnet events +description: Proposed subscription precompile for typed Subtensor subnet lifecycle, lease, epoch, emission, and voting-power callbacks. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `SubnetEventsPrecompile` | +| Proposed Solidity interface | `ISubnetEvents` | +| Callback receiver interface | `ISubnetEventsReceiver` | +| Address | Dedicated address not assigned | +| Status | Proposed | + +This precompile reports subnet creation and dissolution, ownership and identity +changes, leases, epoch execution, emissions, and voting-power tracking emitted +by `SubtensorModule`. + +## Proposed callbacks + +| Receiver function | Subtensor source | +|---|---| +| `onNetworkRegistrationQueued(...)` | `NetworkRegistrationQueued` | +| `onNetworkAdded(...)` | `NetworkAdded` | +| `onNetworkDissolutionScheduled(...)` | `DissolveNetworkScheduled` | +| `onNetworkRemoved(...)` | `NetworkRemoved` | +| `onNetworkDissolutionCleanupCompleted(...)` | `NetworkDissolveCleanupCompleted` | +| `onSubnetIdentitySet(...)` | `SubnetIdentitySet` | +| `onSubnetIdentityRemoved(...)` | `SubnetIdentityRemoved` | +| `onSubnetSymbolChanged(...)` | `SymbolUpdated` | +| `onSubnetOwnerHotkeyChanged(...)` | `SubnetOwnerHotkeySet` | +| `onSubnetOwnerChanged(...)` | `SubnetOwnerChanged` | +| `onFirstEmissionBlockSet(...)` | `FirstEmissionBlockNumberSet` | +| `onSubnetLeaseCreated(...)` | `SubnetLeaseCreated` | +| `onSubnetLeaseTerminated(...)` | `SubnetLeaseTerminated` | +| `onSubnetLeaseDividendDistributed(...)` | `SubnetLeaseDividendsDistributed` | +| `onEpochTriggered(...)` | `EpochTriggered` | +| `onEpochDeferred(...)` | `EpochDeferred` | +| `onEpochSkipped(...)` | `EpochSkipped` | +| `onUidEmissionCalculated(...)` | One callback per UID emission entry from `IncentiveAlphaEmittedToMiners` | +| `onVotingPowerTrackingEnabled(...)` | `VotingPowerTrackingEnabled` | +| `onVotingPowerTrackingDisableScheduled(...)` | `VotingPowerTrackingDisableScheduled` | +| `onVotingPowerTrackingDisabled(...)` | `VotingPowerTrackingDisabled` | +| `onVotingPowerEmaAlphaChanged(...)` | `VotingPowerEmaAlphaSet` | + +The current hook-origin callbacks are `onNetworkDissolutionCleanupCompleted`, +`onSubnetLeaseDividendDistributed`, `onEpochDeferred`, `onEpochSkipped`, +`onUidEmissionCalculated`, and `onVotingPowerTrackingDisabled`. + +### Per-UID emission calculation + +`IncentiveAlphaEmittedToMiners` contains an `emissions` array whose index is the +miner UID: `emissions[0]` is the Alpha emission for UID 0, `emissions[1]` is for +UID 1, and so on. The precompile does not pass this variable-length array to a +subscriber. It delivers one bounded callback for each `(uid, alpha)` entry: + +```solidity +function onUidEmissionCalculated( + uint64 sequence, + uint64 sourceBlock, + uint16 netuid, + uint16 uid, + uint16 uidCount, + uint256 alpha +) external; +``` + +For example, a source array of `[10, 20, 30]` produces callbacks for +`(uid=0, alpha=10)`, `(uid=1, alpha=20)`, and `(uid=2, alpha=30)`. All callbacks +from that source event share the same sequence and `uidCount`, allowing the +receiver to identify the complete set without accepting an unbounded argument. + +Subnet identity and symbol values must use bounded Solidity representations +chosen before the ABI is released. + +Every callback also carries the source block. Account IDs use `bytes32`, +netuids use `uint16`, and balances use 18-decimal `uint256` values. + +Subscription behavior is defined in +[Subscription-based event reporting](/docs/guides/evm/precompile-design#subscription-based-event-reporting). +The names and signatures are provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/subnet.mdx b/docs/guides/evm/precompiles/subnet.mdx new file mode 100644 index 0000000000..7b53a362ca --- /dev/null +++ b/docs/guides/evm/precompiles/subnet.mdx @@ -0,0 +1,93 @@ +--- +title: Subnet +description: Reference for the deployed SubnetPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `SubnetPrecompile` | +| Solidity interface | `ISubnet` | +| Address | `0x0000000000000000000000000000000000000803` | +| Status | Deployed | + +Registers subnets and exposes selected subnet configuration. State-changing +functions are `payable`. + +## Registration + +`registerNetwork` has three overloads: + +```text +registerNetwork(bytes32) +registerNetwork(bytes32,string,string,string,string,string,string,string) +registerNetwork(bytes32,string,string,string,string,string,string,string,string) +``` + +## Views + +```text +getActivityCutoff(uint16) +getActivityCutoffFactor(uint16) +getAdjustmentAlpha(uint16) +getAlphaSigmoidSteepness(uint16) +getAlphaValues(uint16) +getBondsMovingAverage(uint16) +getBondsResetEnabled(uint16) +getCommitRevealWeightsEnabled(uint16) +getCommitRevealWeightsInterval(uint16) +getDifficulty(uint16) +getImmunityPeriod(uint16) +getKappa(uint16) +getLiquidAlphaEnabled(uint16) +getMaxBurn(uint16) +getMaxDifficulty(uint16) +getMaxWeightLimit(uint16) +getMinAllowedWeights(uint16) +getMinBurn(uint16) +getMinDifficulty(uint16) +getNetworkPowRegistrationAllowed(uint16) +getNetworkRegistrationAllowed(uint16) +getNetworkRegistrationBlock(uint16) +getOwnerCutAutoLockEnabled(uint16) +getRho(uint16) +getServingRateLimit(uint16) +getWeightsSetRateLimit(uint16) +getWeightsVersionKey(uint16) +getYuma3Enabled(uint16) +isSubnetDissolving(uint16) +``` + +## Configuration + +```text +setActivityCutoff(uint16,uint16) +setActivityCutoffFactor(uint16,uint32) +setAdjustmentAlpha(uint16,uint64) +setAlphaSigmoidSteepness(uint16,uint16) +setAlphaValues(uint16,uint16,uint16) +setBondsMovingAverage(uint16,uint64) +setBondsResetEnabled(uint16,bool) +setCommitRevealWeightsEnabled(uint16,bool) +setCommitRevealWeightsInterval(uint16,uint64) +setDifficulty(uint16,uint64) +setImmunityPeriod(uint16,uint16) +setKappa(uint16,uint16) +setLiquidAlphaEnabled(uint16,bool) +setMaxBurn(uint16,uint64) +setMaxDifficulty(uint16,uint64) +setMinAllowedWeights(uint16,uint16) +setMinBurn(uint16,uint64) +setMinDifficulty(uint16,uint64) +setNetworkPowRegistrationAllowed(uint16,bool) +setNetworkRegistrationAllowed(uint16,bool) +setOwnerCutAutoLockEnabled(uint16,bool) +setRho(uint16,uint16) +setServingRateLimit(uint16,uint64) +setWeightsSetRateLimit(uint16,uint64) +setWeightsVersionKey(uint16,uint64) +setYuma3Enabled(uint16,bool) +toggleTransfers(uint16,bool) +``` + +Source: [`subnet.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/subnet.sol) + diff --git a/docs/guides/evm/precompiles/timestamp.mdx b/docs/guides/evm/precompiles/timestamp.mdx new file mode 100644 index 0000000000..97f0d78510 --- /dev/null +++ b/docs/guides/evm/precompiles/timestamp.mdx @@ -0,0 +1,29 @@ +--- +title: Timestamp +description: Proposed typed EVM interface for Timestamp pallet state. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `TimestampPrecompile` | +| Proposed Solidity interface | `ITimestamp` | +| Address | Not assigned | +| Status | Proposed | + +## Planned views + +| Function | Replaces | +|---|---| +| `getTimestamp()` | `Timestamp.Now` | +| `wasUpdatedThisBlock()` | `Timestamp.DidUpdate` | + +`getTimestamp()` returns the same underlying time as the EVM +`block.timestamp` value. It exists here so every storage item authorized through +`StorageQueryPrecompile` has an explicit typed replacement. + +`Timestamp.set` is an inherent submitted by block production, not a public +user operation. The proposed precompile therefore exposes no state-changing +timestamp function. + +Names and signatures on this page are provisional and do not reserve selectors. + diff --git a/docs/guides/evm/precompiles/uid-lookup.mdx b/docs/guides/evm/precompiles/uid-lookup.mdx new file mode 100644 index 0000000000..163b6c4e83 --- /dev/null +++ b/docs/guides/evm/precompiles/uid-lookup.mdx @@ -0,0 +1,20 @@ +--- +title: UID lookup +description: Reference for the deployed UidLookupPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `UidLookupPrecompile` | +| Solidity interface | `IUidLookup` | +| Address | `0x0000000000000000000000000000000000000806` | +| Status | Deployed | + +## Functions + +| Function | Mutability | +|---|---| +| `uidLookup(uint16,address,uint16)` | `view` | + +Source: [`uidLookup.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/uidLookup.sol) + diff --git a/docs/guides/evm/precompiles/voting-power.mdx b/docs/guides/evm/precompiles/voting-power.mdx new file mode 100644 index 0000000000..ba2cdd3d8d --- /dev/null +++ b/docs/guides/evm/precompiles/voting-power.mdx @@ -0,0 +1,26 @@ +--- +title: Voting power +description: Reference for the deployed VotingPowerPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `VotingPowerPrecompile` | +| Solidity interface | `IVotingPower` | +| Address | `0x000000000000000000000000000000000000080d` | +| Status | Deployed | + +All functions are `view`. + +## Functions + +```text +getVotingPower(uint16,bytes32) +isVotingPowerTrackingEnabled(uint16) +getVotingPowerDisableAtBlock(uint16) +getVotingPowerEmaAlpha(uint16) +getTotalVotingPower(uint16) +``` + +Source: [`votingPower.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/votingPower.sol) + diff --git a/docs/guides/evm/precompiles/weights-events.mdx b/docs/guides/evm/precompiles/weights-events.mdx new file mode 100644 index 0000000000..6d1822d12c --- /dev/null +++ b/docs/guides/evm/precompiles/weights-events.mdx @@ -0,0 +1,47 @@ +--- +title: Weights events +description: Proposed subscription precompile for typed Subtensor weights, commit-reveal, and batch callbacks. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `WeightsEventsPrecompile` | +| Proposed Solidity interface | `IWeightsEvents` | +| Callback receiver interface | `IWeightsEventsReceiver` | +| Address | Dedicated address not assigned | +| Status | Proposed | + +This precompile reports weight setting and each supported commit-reveal path +emitted by `SubtensorModule`, including reveals performed later by a runtime +hook. + +## Proposed callbacks + +| Receiver function | Subtensor source event | +|---|---| +| `onWeightsSet(...)` | `WeightsSet` | +| `onWeightsCommitted(...)` | `WeightsCommitted` | +| `onWeightsRevealed(...)` | `WeightsRevealed` | +| `onWeightBatchRevealItem(...)` | One hash from `WeightsBatchRevealed` | +| `onBatchWeightCompleted(...)` | One netuid from `BatchWeightsCompleted` | +| `onWeightBatchCompletedWithErrors(...)` | `BatchCompletedWithErrors` | +| `onWeightBatchItemFailed(...)` | `BatchWeightItemFailed` | +| `onTimelockedWeightsCommitted(...)` | `TimelockedWeightsCommitted` | +| `onTimelockedWeightsRevealed(...)` | `TimelockedWeightsRevealed` | +| `onCommitRevealPeriodsChanged(...)` | `CommitRevealPeriodsSet` | +| `onCommitRevealEnabledChanged(...)` | `CommitRevealEnabled` | +| `onCommitRevealVersionChanged(...)` | `CommitRevealVersionSet` | + +`onTimelockedWeightsRevealed` covers the current weights event emitted from a +runtime hook. + +Batch callbacks carry the source sequence, item index, and item count and +report one bounded item per invocation. Dispatch failures use a stable typed +error representation rather than SCALE-encoded `DispatchError`. + +Every callback also carries the source block. Hotkeys use `bytes32`, netuids +use `uint16`, and commitment hashes use `bytes32`. + +Subscription behavior is defined in +[Subscription-based event reporting](/docs/guides/evm/precompile-design#subscription-based-event-reporting). +The names and signatures are provisional and do not reserve selectors. diff --git a/website/apps/bittensor-website/src/components/copy.tsx b/website/apps/bittensor-website/src/components/copy.tsx index 1eb4b5b831..d23fce704c 100644 --- a/website/apps/bittensor-website/src/components/copy.tsx +++ b/website/apps/bittensor-website/src/components/copy.tsx @@ -40,6 +40,28 @@ export function CopyCodeButton() { ); } +/** Compact EVM address that copies the complete 20-byte value. */ +export function EvmAddress({ address }: { address: string }) { + const { copied, flash } = useCopied(); + const shortAddress = `${address.slice(0, 3)}...${address.slice(-4)}`; + + return ( + + ); +} + /** "Copy Markdown" — fetches the page's raw markdown and copies it. */ export function CopyMarkdownButton({ markdownUrl, diff --git a/website/apps/bittensor-website/src/components/mdx.tsx b/website/apps/bittensor-website/src/components/mdx.tsx index f7fcf9b4dd..754c125924 100644 --- a/website/apps/bittensor-website/src/components/mdx.tsx +++ b/website/apps/bittensor-website/src/components/mdx.tsx @@ -1,7 +1,7 @@ import Link from 'next/link'; import type { MDXComponents } from 'mdx/types'; import type { ComponentProps, ReactNode } from 'react'; -import { CopyCodeButton } from './copy'; +import { CopyCodeButton, EvmAddress } from './copy'; import { EvmAddressDomains } from './docs/evm-address-domains'; import { EvmMoneyFlows } from './docs/evm-money-flows'; import { ConvictionLockChart } from './docs/conviction-lock-chart'; @@ -130,6 +130,7 @@ export function getMDXComponents(components?: MDXComponents) { Cards, Card, Callout, + EvmAddress, TaoHalvingChart, SubnetEmissionShareChart, YumaConsensusDemo, From a10b62e7451a346289c8fdc9ff79224c5f177823 Mon Sep 17 00:00:00 2001 From: girazoki Date: Tue, 28 Jul 2026 12:27:43 +0200 Subject: [PATCH 07/58] pass ss58 from config --- Cargo.lock | 1 - Cargo.toml | 1 - pallets/limit-orders/Cargo.toml | 7 +-- pallets/limit-orders/src/lib.rs | 54 ++++++++++------------ pallets/limit-orders/src/tests/mock.rs | 7 ++- pallets/limit-orders/src/tests/readable.rs | 34 +++++++++----- 6 files changed, 57 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e66fbf48c..2742764a10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10101,7 +10101,6 @@ dependencies = [ name = "pallet-limit-orders" version = "0.1.0" dependencies = [ - "bs58", "frame-benchmarking", "frame-support", "frame-system", diff --git a/Cargo.toml b/Cargo.toml index 460e6641f8..8b8eb786ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -301,7 +301,6 @@ pallet-shield = { path = "pallets/shield", default-features = false } ml-kem = { version = "0.2.2", default-features = false } chacha20poly1305 = { version = "0.10", default-features = false } blake2 = "0.10.6" -bs58 = { version = "0.5.1", default-features = false } # Primitives diff --git a/pallets/limit-orders/Cargo.toml b/pallets/limit-orders/Cargo.toml index 048caa41d8..3d1494ae66 100644 --- a/pallets/limit-orders/Cargo.toml +++ b/pallets/limit-orders/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition.workspace = true [dependencies] -bs58 = { workspace = true, default-features = false, features = ["alloc"] } codec = { workspace = true, features = ["derive"] } frame-benchmarking = { workspace = true, optional = true } sp-io = { workspace = true, optional = true } @@ -12,7 +11,10 @@ sp-keyring = { workspace = true, optional = true } frame-support.workspace = true frame-system.workspace = true scale-info.workspace = true -sp-core.workspace = true +# `serde` is what gates `Ss58Codec::to_ss58check_with_version`, used to render +# accounts into the human-readable order message. Despite the name it is sp-core's +# "serde support without relying on std features", so it works in the wasm build. +sp-core = { workspace = true, features = ["serde"] } sp-runtime.workspace = true sp-std.workspace = true log.workspace = true @@ -32,7 +34,6 @@ workspace = true [features] default = ["std"] std = [ - "bs58/std", "codec/std", "frame-benchmarking?/std", "frame-support/std", diff --git a/pallets/limit-orders/src/lib.rs b/pallets/limit-orders/src/lib.rs index ada685736c..80a2e969ee 100644 --- a/pallets/limit-orders/src/lib.rs +++ b/pallets/limit-orders/src/lib.rs @@ -208,23 +208,11 @@ pub mod pallet { use frame_system::pallet_prelude::*; use alloc::format; use alloc::string::String; + use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; use sp_runtime::traits::AccountIdConversion; use sp_std::collections::btree_set::BTreeSet; use sp_std::vec::Vec; - /// SS58 address format prefix used when rendering an `AccountId` into the - /// human-readable ("clear-signing") message that hardware wallets display. - /// - /// This is Bittensor's registered SS58 prefix (42). It fits in a single byte - /// because it is ≤ 63, which lets `render_account` use the simple single-byte - /// SS58 encoding path. - /// - /// INVARIANT: this MUST match the SS58 prefix constant used by the - /// frontend/wallet that produces the readable signing payload; otherwise the - /// rendered account strings — and therefore the whole signed message — will - /// differ and signature verification will fail. - const SS58_PREFIX: u8 = 42; - #[pallet::pallet] pub struct Pallet(_); @@ -652,26 +640,32 @@ pub mod pallet { .verify(payload.as_slice(), &order.signer) } - /// Render `who` into its SS58 (base58check) string using Bittensor's - /// [`SS58_PREFIX`], reproducing `Ss58Codec::to_ss58check_with_version` for a - /// single-byte prefix. + /// Render `who` into its SS58 (base58check) string, reproducing + /// `Ss58Codec::to_ss58check_with_version`. + /// + /// The address format prefix is taken from the chain's own + /// [`frame_system::Config::SS58Prefix`] rather than a constant local to this + /// pallet, so the accounts rendered into the human-readable ("clear-signing") + /// message are guaranteed to agree with the prefix the chain declares — and + /// therefore with the way wallets display those same accounts. For Bittensor + /// that value is 42. /// - /// We do the encoding manually rather than calling `to_ss58check` because that - /// method is gated behind sp-core's `serde` (`full_crypto`/`std`) feature and is - /// not reliably available in the no_std/wasm runtime build. + /// NOTE: this prefix is part of a signature preimage. Changing + /// `frame_system::Config::SS58Prefix` in a runtime upgrade changes every + /// rendered address, and therefore invalidates any readable-form order that + /// was signed before the upgrade (such orders then fail with + /// `InvalidSignature` / are skipped). The raw and wrapped signing forms are + /// unaffected, as neither renders addresses. /// - /// `who.encode()` on `AccountId32` yields exactly 32 bytes; with the 1-byte - /// prefix and 2-byte checksum the output buffer is 35 bytes. + /// The encoding itself is delegated to sp-core's canonical + /// `Ss58Codec::to_ss58check_with_version` rather than reimplemented here. That + /// method is gated behind sp-core's `serde` feature, which — despite the name — + /// is explicitly "serde support without relying on std features" and so is + /// available in the no_std/wasm runtime build; the pallet enables it via its + /// `sp-core/serde` dependency feature. pub(crate) fn render_account(who: &T::AccountId) -> String { - let raw = who.encode(); // 32 bytes (AccountId32) - let mut buf = Vec::with_capacity(35); - buf.push(SS58_PREFIX); - buf.extend_from_slice(&raw); - let h = sp_core::hashing::blake2_512( - &[b"SS58PRE".as_slice(), buf.as_slice()].concat(), - ); - buf.extend_from_slice(&h[0..2]); // 2-byte checksum - bs58::encode(buf).into_string() + let prefix = ::SS58Prefix::get(); + who.to_ss58check_with_version(Ss58AddressFormat::custom(prefix)) } /// Build the canonical, single-line, all-printable-ASCII "clear-signing" diff --git a/pallets/limit-orders/src/tests/mock.rs b/pallets/limit-orders/src/tests/mock.rs index bfc4c4714a..a5c359641b 100644 --- a/pallets/limit-orders/src/tests/mock.rs +++ b/pallets/limit-orders/src/tests/mock.rs @@ -10,7 +10,7 @@ use std::collections::HashMap; use codec::Encode; use frame_support::{ BoundedVec, PalletId, construct_runtime, derive_impl, parameter_types, - traits::{ConstU32, ConstU64, Everything}, + traits::{ConstU16, ConstU32, ConstU64, Everything}, }; use frame_system as system; use sp_core::{H256, Pair}; @@ -51,6 +51,11 @@ impl system::Config for Test { type MaxConsumers = ConstU32<16>; type Nonce = u64; type Block = Block; + /// Pinned to Bittensor's real prefix (42) because `render_account` renders + /// accounts into the readable signing message under this value. Leaving it at + /// `TestDefaultConfig`'s default (`()` → 0) would make the readable-form tests + /// exercise a prefix the chain never uses. + type SS58Prefix = ConstU16<42>; } // ── MockSwap ───────────────────────────────────────────────────────────────── diff --git a/pallets/limit-orders/src/tests/readable.rs b/pallets/limit-orders/src/tests/readable.rs index 9a68beccea..ed706d7b99 100644 --- a/pallets/limit-orders/src/tests/readable.rs +++ b/pallets/limit-orders/src/tests/readable.rs @@ -9,7 +9,10 @@ //! must produce a different message and therefore break the original signature), //! and the deliberate `none` vs `[]` relayer-rendering distinction. -use frame_support::{BoundedVec, assert_noop, assert_ok, traits::ConstU32}; +use frame_support::{ + BoundedVec, assert_noop, assert_ok, + traits::{ConstU32, Get}, +}; use sp_core::{H256, Pair}; use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; use sp_keyring::Sr25519Keyring as AccountKeyring; @@ -22,15 +25,18 @@ use crate::{Error, Order, OrderType, VersionedOrder}; use super::mock::*; -/// The SS58 prefix the pallet renders accounts under. Must match `SS58_PREFIX` -/// in `lib.rs`. Tests reconstruct the expected SS58 strings independently using -/// `sp-core`'s canonical codec at this same version. -const SS58_PREFIX: u16 = 42; +/// The SS58 prefix accounts are rendered under, read from the same place +/// `render_account` reads it — the chain's own `frame_system::Config::SS58Prefix` +/// (pinned to 42 in the mock). Deliberately not a second hardcoded literal, so the +/// test cannot silently disagree with the runtime about the prefix. +fn ss58_prefix() -> u16 { + <::SS58Prefix as Get>::get() +} -/// Canonical `Ss58Codec` reconstruction of an account, used as the independent -/// oracle against the pallet's hand-rolled `render_account`. +/// Canonical `Ss58Codec` reconstruction of an account, used to rebuild the expected +/// SS58 strings in the golden-message tests. fn canonical_ss58(acct: &AccountId) -> String { - acct.to_ss58check_with_version(Ss58AddressFormat::custom(SS58_PREFIX)) + acct.to_ss58check_with_version(Ss58AddressFormat::custom(ss58_prefix())) } /// Build the payload the readable path signs: the `` `signRaw` @@ -79,12 +85,18 @@ fn make_readable_signed_order( } // ───────────────────────────────────────────────────────────────────────────── -// A. SS58 correctness cross-check +// A. SS58 prefix wiring // ───────────────────────────────────────────────────────────────────────────── +/// `render_account` delegates encoding to sp-core's `Ss58Codec`, so the encoding +/// itself needs no cross-check. What this pins down is the *prefix wiring*: that +/// accounts are rendered under the chain's own `frame_system::Config::SS58Prefix` +/// and not some other value. If the pallet ever regressed to a local constant, or +/// read the prefix from the wrong place, this fails. #[test] -fn render_account_matches_canonical_ss58_codec() { +fn render_account_uses_chain_ss58_prefix() { new_test_ext().execute_with(|| { + assert_eq!(ss58_prefix(), 42, "mock must pin Bittensor's real prefix"); let cases = vec![ alice(), bob(), @@ -96,7 +108,7 @@ fn render_account_matches_canonical_ss58_codec() { let canonical = canonical_ss58(&acct); assert_eq!( rendered, canonical, - "manual SS58 rendering must match sp-core Ss58Codec for {acct:?}" + "render_account must encode at the chain's SS58 prefix for {acct:?}" ); } }); From 1dee117104a53e47fe344e29b2c8d9c67543ee38 Mon Sep 17 00:00:00 2001 From: girazoki Date: Tue, 28 Jul 2026 12:38:43 +0200 Subject: [PATCH 08/58] make comment shorter --- pallets/limit-orders/src/lib.rs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/pallets/limit-orders/src/lib.rs b/pallets/limit-orders/src/lib.rs index 80a2e969ee..3e4c5cff9a 100644 --- a/pallets/limit-orders/src/lib.rs +++ b/pallets/limit-orders/src/lib.rs @@ -642,27 +642,6 @@ pub mod pallet { /// Render `who` into its SS58 (base58check) string, reproducing /// `Ss58Codec::to_ss58check_with_version`. - /// - /// The address format prefix is taken from the chain's own - /// [`frame_system::Config::SS58Prefix`] rather than a constant local to this - /// pallet, so the accounts rendered into the human-readable ("clear-signing") - /// message are guaranteed to agree with the prefix the chain declares — and - /// therefore with the way wallets display those same accounts. For Bittensor - /// that value is 42. - /// - /// NOTE: this prefix is part of a signature preimage. Changing - /// `frame_system::Config::SS58Prefix` in a runtime upgrade changes every - /// rendered address, and therefore invalidates any readable-form order that - /// was signed before the upgrade (such orders then fail with - /// `InvalidSignature` / are skipped). The raw and wrapped signing forms are - /// unaffected, as neither renders addresses. - /// - /// The encoding itself is delegated to sp-core's canonical - /// `Ss58Codec::to_ss58check_with_version` rather than reimplemented here. That - /// method is gated behind sp-core's `serde` feature, which — despite the name — - /// is explicitly "serde support without relying on std features" and so is - /// available in the no_std/wasm runtime build; the pallet enables it via its - /// `sp-core/serde` dependency feature. pub(crate) fn render_account(who: &T::AccountId) -> String { let prefix = ::SS58Prefix::get(); who.to_ss58check_with_version(Ss58AddressFormat::custom(prefix)) From 5d10f594494bda96a7f75b30af0f6d5013f60c52 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Tue, 28 Jul 2026 08:55:05 -0400 Subject: [PATCH 09/58] Add precompile coverage gaps for existing domains --- .agents/skills/emv-maintainer/SKILL.md | 5 ++ .../evm/precompiles/account-balance.mdx | 17 ++++- docs/guides/evm/precompiles/alpha.mdx | 26 ++++++- .../evm/precompiles/balance-transfer.mdx | 18 ++++- docs/guides/evm/precompiles/crowdloan.mdx | 12 ++- docs/guides/evm/precompiles/drand.mdx | 19 +++-- .../evm/precompiles/extrinsic-coverage.mdx | 75 +++++++++++++++++++ docs/guides/evm/precompiles/index.mdx | 5 ++ docs/guides/evm/precompiles/leasing.mdx | 10 ++- docs/guides/evm/precompiles/meta.json | 2 + docs/guides/evm/precompiles/neuron.mdx | 44 ++++++++++- docs/guides/evm/precompiles/proxy.mdx | 17 ++++- docs/guides/evm/precompiles/registry.mdx | 10 ++- .../evm/precompiles/runtime-configuration.mdx | 30 ++++++++ docs/guides/evm/precompiles/scheduler.mdx | 25 +++---- docs/guides/evm/precompiles/staking-v2.mdx | 46 ++++++++++++ docs/guides/evm/precompiles/subnet.mdx | 67 ++++++++++++++++- docs/guides/evm/precompiles/timestamp.mdx | 4 +- docs/guides/evm/precompiles/voting-power.mdx | 11 ++- 19 files changed, 408 insertions(+), 35 deletions(-) create mode 100644 docs/guides/evm/precompiles/extrinsic-coverage.mdx create mode 100644 docs/guides/evm/precompiles/runtime-configuration.mdx diff --git a/.agents/skills/emv-maintainer/SKILL.md b/.agents/skills/emv-maintainer/SKILL.md index c26d65f9b7..f59e2a83d8 100644 --- a/.agents/skills/emv-maintainer/SKILL.md +++ b/.agents/skills/emv-maintainer/SKILL.md @@ -66,6 +66,11 @@ For each affected released function: - admin-util - balances - proxy + - scheduler + - drand + - crowdloan + - timestamp + - swap - All runtime API RPCs for the subtensor pallet should be exposed as a callable precompile function with similar interface - All events emitted from hooks (such as on_initialize or on_finalize) should be exposed as callbacks. diff --git a/docs/guides/evm/precompiles/account-balance.mdx b/docs/guides/evm/precompiles/account-balance.mdx index 4fb1e89612..63c6edbe4d 100644 --- a/docs/guides/evm/precompiles/account-balance.mdx +++ b/docs/guides/evm/precompiles/account-balance.mdx @@ -16,5 +16,20 @@ description: Reference for the deployed BalancePrecompile. |---|---| | `getFreeBalance(bytes32)` | `view` | -Source: [`balance.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balance.sol) +## Proposed operations + +| Proposed function | Source extrinsic | +|---|---| +| `burnBalance` | `Balances.burn` | +| `forceUnreserve` | `Balances.force_unreserve` | +| `upgradeAccounts` | `Balances.upgrade_accounts` | +| `forceSetBalance` | `Balances.force_set_balance` | +| `forceAdjustTotalIssuance` | `Balances.force_adjust_total_issuance` | +| `setTotalIssuance` | `AdminUtils.sudo_set_total_issuance` | +`upgradeAccounts` must have an explicit fixed input bound. The implementation +must preserve all runtime authorization and issuance invariants. + +Proposed names and signatures do not reserve selectors. + +Source: [`balance.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balance.sol) diff --git a/docs/guides/evm/precompiles/alpha.mdx b/docs/guides/evm/precompiles/alpha.mdx index c45aba78f7..4cde04cdb5 100644 --- a/docs/guides/evm/precompiles/alpha.mdx +++ b/docs/guides/evm/precompiles/alpha.mdx @@ -36,5 +36,29 @@ getSumAlphaPrice() getCKBurn() ``` -Source: [`alpha.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/alpha.sol) +## Proposed operations + +| Proposed function | Source extrinsic | +|---|---| +| `setSwapFeeRate` | `Swap.set_fee_rate` | +| `setRecycleOrBurn` | `AdminUtils.sudo_set_recycle_or_burn` | +| `setSubnetMovingAlpha` | `AdminUtils.sudo_set_subnet_moving_alpha` | +| `setEmaPriceHalvingPeriod` | `AdminUtils.sudo_set_ema_price_halving_period` | +| `setCkBurn` | `AdminUtils.sudo_set_ck_burn` | +| `setTaoFlowCutoff` | `AdminUtils.sudo_set_tao_flow_cutoff` | +| `setTaoFlowNormalizationExponent` | `AdminUtils.sudo_set_tao_flow_normalization_exponent` | +| `setTaoFlowSmoothingFactor` | `AdminUtils.sudo_set_tao_flow_smoothing_factor` | +| `setNetTaoFlowEnabled` | `AdminUtils.sudo_set_net_tao_flow_enabled` | +| `setBurnHalfLife` | `AdminUtils.sudo_set_burn_half_life` | +| `setBurnIncreaseMultiplier` | `AdminUtils.sudo_set_burn_increase_mult` | +| `setSubnetEmissionEnabled` | `AdminUtils.sudo_set_subnet_emission_enabled` | +| `setEmissionBarQuantile` | `AdminUtils.sudo_set_emission_bar_quantile` | +| `setEmissionGateExponent` | `AdminUtils.sudo_set_emission_gate_exponent` | +The five deprecated `Swap` liquidity extrinsics are intentionally not proposed; +they always return the pallet's `Deprecated` error. Runtime authorization +remains in force for every administrative operation. + +Proposed names and signatures do not reserve selectors. + +Source: [`alpha.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/alpha.sol) diff --git a/docs/guides/evm/precompiles/balance-transfer.mdx b/docs/guides/evm/precompiles/balance-transfer.mdx index 71b3f4c1ce..0631247658 100644 --- a/docs/guides/evm/precompiles/balance-transfer.mdx +++ b/docs/guides/evm/precompiles/balance-transfer.mdx @@ -19,5 +19,21 @@ public key. |---|---| | `transfer(bytes32)` | `payable` | -Source: [`balanceTransfer.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balanceTransfer.sol) +## Proposed additions + +| Proposed function | Source extrinsic | +|---|---| +| `faucet` | `SubtensorModule.faucet` | +| `transferKeepAlive` | `Balances.transfer_keep_alive` | +| `transferAll` | `Balances.transfer_all` | +| `forceTransfer` | `Balances.force_transfer` | +The existing `transfer(bytes32)` semantically covers +`Balances.transfer_allow_death` by taking the amount from attached EVM value. +The proposed functions use explicit typed arguments where attached value does +not express the complete source operation. Runtime authorization remains in +force for `forceTransfer`. + +Proposed names and signatures do not reserve selectors. + +Source: [`balanceTransfer.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balanceTransfer.sol) diff --git a/docs/guides/evm/precompiles/crowdloan.mdx b/docs/guides/evm/precompiles/crowdloan.mdx index abdce95497..d563faf76e 100644 --- a/docs/guides/evm/precompiles/crowdloan.mdx +++ b/docs/guides/evm/precompiles/crowdloan.mdx @@ -33,5 +33,15 @@ updateEnd(uint32,uint32) updateCap(uint32,uint64) ``` -Source: [`crowdloan.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/crowdloan.sol) +## Proposed addition + +| Proposed function | Source extrinsic | +|---|---| +| `setMaxContribution` | `Crowdloan.set_max_contribution` | +The typed interface must preserve the source call's optional value so the +creator can either set or clear the per-contributor maximum. + +The proposed name and signature do not reserve a selector. + +Source: [`crowdloan.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/crowdloan.sol) diff --git a/docs/guides/evm/precompiles/drand.mdx b/docs/guides/evm/precompiles/drand.mdx index 9e8bf552f3..08b5b195a5 100644 --- a/docs/guides/evm/precompiles/drand.mdx +++ b/docs/guides/evm/precompiles/drand.mdx @@ -25,11 +25,14 @@ of requiring callers to construct Drand storage keys and decode SCALE values. ## Planned operations -```text -writePulse -setBeaconConfig -setOldestStoredRound -``` - -The runtime's existing signed, unsigned, and Root origin checks remain in force. -Names and signatures on this page are provisional and do not reserve selectors. +| Proposed function | Source extrinsic | +|---|---| +| `setBeaconConfig` | `Drand.set_beacon_config` | +| `setOldestStoredRound` | `Drand.set_oldest_stored_round` | + +`Drand.write_pulse` is not exposed. It is an unsigned offchain-worker +submission that requires `None` origin, which an EVM caller cannot satisfy +without changing the security model. + +The runtime's existing authorization checks remain in force. Names and +signatures on this page are provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/extrinsic-coverage.mdx b/docs/guides/evm/precompiles/extrinsic-coverage.mdx new file mode 100644 index 0000000000..4e9b58510c --- /dev/null +++ b/docs/guides/evm/precompiles/extrinsic-coverage.mdx @@ -0,0 +1,75 @@ +--- +title: Extrinsic coverage +description: Audit of typed EVM coverage for every extrinsic in the authorized runtime pallets. +--- + +This audit covers the runtime's `SubtensorModule`, `AdminUtils`, `Balances`, +`Proxy`, `Scheduler`, `Drand`, `Crowdloan`, `Timestamp`, and `Swap` pallets. +Sudo and Multisig extrinsics are intentionally outside typed precompile +coverage. + +Generic SCALE dispatch through the Frontier `Dispatch` precompile does not +count as typed coverage. A covered operation must have a stable Solidity +interface or an explicit proposed typed replacement. + +## Coverage summary + +| Pallet | Runtime extrinsics | Typed today | Proposed additions | Not exposed | +|---|---:|---:|---:|---:| +| `SubtensorModule` | 82 | 24 | 56 | 2 | +| `AdminUtils` | 86 | 24 | 62 | 0 | +| `Balances` | 9 | 1 | 8 | 0 | +| `Proxy` | 12 | 7 | 5 | 0 | +| `Scheduler` | 10 | 0 | 10 | 0 | +| `Drand` | 3 | 0 | 2 | 1 | +| `Crowdloan` | 10 | 9 | 1 | 0 | +| `Timestamp` | 1 | 0 | 0 | 1 | +| `Swap` | 6 | 0 | 1 | 5 | +| **Total** | **219** | **65** | **145** | **9** | + +`Typed today` counts semantic coverage, not only direct dispatch to the same +Rust call. For example, `registerNetwork(bytes32)` covers basic subnet +registration by dispatching `register_network_with_identity` with empty +identity fields. + +## Classification of proposed additions + +Each missing operation is listed on the page of its target precompile: + +| Target precompile | Missing extrinsics assigned | +|---|---:| +| [Subnet](/docs/guides/evm/precompiles/subnet) | 37 | +| [Staking V2](/docs/guides/evm/precompiles/staking-v2) | 29 | +| [Neuron](/docs/guides/evm/precompiles/neuron) | 27 | +| [Alpha](/docs/guides/evm/precompiles/alpha) | 14 | +| [Scheduler](/docs/guides/evm/precompiles/scheduler) | 10 | +| [Account balance](/docs/guides/evm/precompiles/account-balance) | 6 | +| [Proxy](/docs/guides/evm/precompiles/proxy) | 5 | +| [Balance transfer](/docs/guides/evm/precompiles/balance-transfer) | 4 | +| [Runtime configuration](/docs/guides/evm/precompiles/runtime-configuration) | 4 | +| [Voting power](/docs/guides/evm/precompiles/voting-power) | 3 | +| [Drand](/docs/guides/evm/precompiles/drand) | 2 | +| [Leasing](/docs/guides/evm/precompiles/leasing) | 2 | +| [Crowdloan](/docs/guides/evm/precompiles/crowdloan) | 1 | +| [Precompile registry](/docs/guides/evm/precompiles/registry) | 1 | + +Proposed function names do not reserve selectors. Their final parameter types, +bounds, authorization model, and return values must be specified before +implementation. + +## Extrinsics not exposed as EVM calls + +| Pallet extrinsic | Reason | +|---|---| +| `SubtensorModule.set_tempo` | Retained call-index compatibility entry point that succeeds without changing state. The real setting is `AdminUtils.sudo_set_tempo`, proposed as `SubnetPrecompile.setTempo`. | +| `SubtensorModule.set_activity_cutoff_factor` | Retained call-index compatibility entry point that succeeds without changing state. The active AdminUtils operation is already covered by `SubnetPrecompile.setActivityCutoffFactor`. | +| `Drand.write_pulse` | Unsigned offchain-worker submission requiring `None` origin. An EVM caller cannot satisfy that origin without changing its security model. | +| `Timestamp.set` | Block-production inherent requiring `None` origin. Contracts already receive the same time through `block.timestamp`. | +| `Swap.add_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | +| `Swap.remove_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | +| `Swap.modify_position` | Permanently disabled pallet call that always returns `Deprecated`. | +| `Swap.toggle_user_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | +| `Swap.disable_lp` | Permanently disabled pallet call that always returns `Deprecated`. | + +These exclusions preserve the existing runtime origin and lifecycle semantics; +they are not missing callable functionality. diff --git a/docs/guides/evm/precompiles/index.mdx b/docs/guides/evm/precompiles/index.mdx index c0ed62162b..817a3c5d18 100644 --- a/docs/guides/evm/precompiles/index.mdx +++ b/docs/guides/evm/precompiles/index.mdx @@ -8,6 +8,10 @@ runtime. `Deployed` means that the address is registered in the current runtime; it does not imply complete coverage of the underlying runtime domain. `Proposed` precompiles have no assigned address or released selectors. +The [extrinsic coverage audit](/docs/guides/evm/precompiles/extrinsic-coverage) +tracks every runtime extrinsic in scope and identifies its deployed, proposed, +or intentionally non-callable EVM treatment. + ## Ethereum and Frontier precompiles | Precompile | Address | Status | @@ -48,6 +52,7 @@ it does not imply complete coverage of the underlying runtime domain. | [`SchedulerPrecompile`](/docs/guides/evm/precompiles/scheduler) | `IScheduler` | Address not assigned
Proposed | | [`DrandPrecompile`](/docs/guides/evm/precompiles/drand) | `IDrand` | Address not assigned
Proposed | | [`TimestampPrecompile`](/docs/guides/evm/precompiles/timestamp) | `ITimestamp` | Address not assigned
Proposed | +| [`RuntimeConfigurationPrecompile`](/docs/guides/evm/precompiles/runtime-configuration) | `IRuntimeConfiguration` | Address not assigned
Proposed | | [`StakingEventsPrecompile`](/docs/guides/evm/precompiles/staking-events) | `IStakingEvents` | Dedicated address not assigned
Proposed | | [`NeuronEventsPrecompile`](/docs/guides/evm/precompiles/neuron-events) | `INeuronEvents` | Dedicated address not assigned
Proposed | | [`WeightsEventsPrecompile`](/docs/guides/evm/precompiles/weights-events) | `IWeightsEvents` | Dedicated address not assigned
Proposed | diff --git a/docs/guides/evm/precompiles/leasing.mdx b/docs/guides/evm/precompiles/leasing.mdx index e4a910e574..32f20af948 100644 --- a/docs/guides/evm/precompiles/leasing.mdx +++ b/docs/guides/evm/precompiles/leasing.mdx @@ -27,5 +27,13 @@ terminateLease(uint32,bytes32) Both operations are `payable`. -Source: [`leasing.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/leasing.sol) +## Proposed additions + +| Proposed function | Source extrinsic | +|---|---| +| `startCall` | `SubtensorModule.start_call` | +| `setStartCallDelay` | `AdminUtils.sudo_set_start_call_delay` | +Proposed names and signatures do not reserve selectors. + +Source: [`leasing.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/leasing.sol) diff --git a/docs/guides/evm/precompiles/meta.json b/docs/guides/evm/precompiles/meta.json index 07144223c0..9cb554aaf6 100644 --- a/docs/guides/evm/precompiles/meta.json +++ b/docs/guides/evm/precompiles/meta.json @@ -2,6 +2,7 @@ "title": "Precompiles", "pages": [ "index", + "extrinsic-coverage", "balance-transfer", "staking-v1", "metagraph", @@ -21,6 +22,7 @@ "scheduler", "drand", "timestamp", + "runtime-configuration", "staking-events", "neuron-events", "weights-events", diff --git a/docs/guides/evm/precompiles/neuron.mdx b/docs/guides/evm/precompiles/neuron.mdx index c4940dacdd..6cbe2643e4 100644 --- a/docs/guides/evm/precompiles/neuron.mdx +++ b/docs/guides/evm/precompiles/neuron.mdx @@ -26,5 +26,47 @@ commitWeights(uint16,bytes32) revealWeights(uint16,uint16[],uint16[],uint16[],uint64) ``` -Source: [`neuron.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/neuron.sol) +## Proposed weight operations + +| Proposed function | Source extrinsic | +|---|---| +| `setMechanismWeights` | `SubtensorModule.set_mechanism_weights` | +| `batchSetWeights` | `SubtensorModule.batch_set_weights` | +| `commitMechanismWeights` | `SubtensorModule.commit_mechanism_weights` | +| `batchCommitWeights` | `SubtensorModule.batch_commit_weights` | +| `revealMechanismWeights` | `SubtensorModule.reveal_mechanism_weights` | +| `commitCrv3MechanismWeights` | `SubtensorModule.commit_crv3_mechanism_weights` | +| `batchRevealWeights` | `SubtensorModule.batch_reveal_weights` | +| `commitTimelockedWeights` | `SubtensorModule.commit_timelocked_weights` | +| `commitTimelockedMechanismWeights` | `SubtensorModule.commit_timelocked_mechanism_weights` | + +Every batch input must have an explicit fixed bound. Timelocked operations must +use typed Drand data rather than SCALE-encoded payloads. + +## Proposed registration and key operations +| Proposed function | Source extrinsic | +|---|---| +| `register` | `SubtensorModule.register` | +| `rootRegister` | `SubtensorModule.root_register` | +| `swapHotkey` | `SubtensorModule.swap_hotkey` | +| `swapHotkeyV2` | `SubtensorModule.swap_hotkey_v2` | +| `swapColdkey` | `SubtensorModule.swap_coldkey` | +| `scheduleColdkeySwap` | `SubtensorModule.schedule_swap_coldkey` | +| `setChildren` | `SubtensorModule.set_children` | +| `setIdentity` | `SubtensorModule.set_identity` | +| `tryAssociateHotkey` | `SubtensorModule.try_associate_hotkey` | +| `associateEvmKey` | `SubtensorModule.associate_evm_key` | +| `setPendingChildkeyCooldown` | `SubtensorModule.set_pending_childkey_cooldown` | +| `announceColdkeySwap` | `SubtensorModule.announce_coldkey_swap` | +| `executeAnnouncedColdkeySwap` | `SubtensorModule.swap_coldkey_announced` | +| `disputeColdkeySwap` | `SubtensorModule.dispute_coldkey_swap` | +| `resetColdkeySwap` | `SubtensorModule.reset_coldkey_swap` | +| `clearColdkeySwapAnnouncement` | `SubtensorModule.clear_coldkey_swap_announcement` | +| `setColdkeySwapAnnouncementDelay` | `AdminUtils.sudo_set_coldkey_swap_announcement_delay` | +| `setColdkeySwapReannouncementDelay` | `AdminUtils.sudo_set_coldkey_swap_reannouncement_delay` | + +Runtime authorization remains in force. Proposed names and signatures do not +reserve selectors. + +Source: [`neuron.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/neuron.sol) diff --git a/docs/guides/evm/precompiles/proxy.mdx b/docs/guides/evm/precompiles/proxy.mdx index 5e3fdf71f2..21a87446b2 100644 --- a/docs/guides/evm/precompiles/proxy.mdx +++ b/docs/guides/evm/precompiles/proxy.mdx @@ -23,5 +23,20 @@ description: Reference for the deployed ProxyPrecompile. | `pokeDeposit()` | nonpayable | | `getProxies(bytes32)` | `view` | -Source: [`proxy.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/proxy.sol) +## Proposed additions + +| Proposed function | Source extrinsic | +|---|---| +| `announce` | `Proxy.announce` | +| `removeAnnouncement` | `Proxy.remove_announcement` | +| `rejectAnnouncement` | `Proxy.reject_announcement` | +| `proxyAnnounced` | `Proxy.proxy_announced` | +| `setRealPaysFee` | `Proxy.set_real_pays_fee` | +`proxyAnnounced` must use the same versioned, stable EVM call description as +other typed proxy execution. A new interface must not introduce another +dependency on SCALE-encoded `RuntimeCall`. + +Proposed names and signatures do not reserve selectors. + +Source: [`proxy.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/proxy.sol) diff --git a/docs/guides/evm/precompiles/registry.mdx b/docs/guides/evm/precompiles/registry.mdx index 8c7ad14b4d..721c930786 100644 --- a/docs/guides/evm/precompiles/registry.mdx +++ b/docs/guides/evm/precompiles/registry.mdx @@ -32,8 +32,16 @@ interface IPrecompileRegistry { } ``` +## Proposed operation + +| Proposed function | Source extrinsic | +|---|---| +| `setPrecompileEnabled` | `AdminUtils.sudo_toggle_evm_precompile` | + +This operation changes reversible availability; it does not change or erase a +function's deprecation lifecycle. Runtime authorization remains in force. + The lifecycle model is described in [Precompile design and lifecycle](/docs/guides/evm/precompile-design#discovering-status). The address and selector are not reserved until the interface is implemented and released. - diff --git a/docs/guides/evm/precompiles/runtime-configuration.mdx b/docs/guides/evm/precompiles/runtime-configuration.mdx new file mode 100644 index 0000000000..7c8ecff2c4 --- /dev/null +++ b/docs/guides/evm/precompiles/runtime-configuration.mdx @@ -0,0 +1,30 @@ +--- +title: Runtime configuration +description: Proposed typed EVM interface for global runtime configuration operations. +--- + +| Property | Value | +|---|---| +| Proposed implementation | `RuntimeConfigurationPrecompile` | +| Proposed Solidity interface | `IRuntimeConfiguration` | +| Address | Not assigned | +| Status | Proposed | + +This precompile groups the small set of global AdminUtils operations that do +not belong to a subnet, staking, Alpha, account-balance, or precompile-lifecycle +domain. + +## Planned operations + +| Proposed function | Source extrinsic | +|---|---| +| `swapAuthorities` | `AdminUtils.swap_authorities` | +| `setTransactionRateLimit` | `AdminUtils.sudo_set_tx_rate_limit` | +| `setEvmChainId` | `AdminUtils.sudo_set_evm_chain_id` | +| `scheduleGrandpaChange` | `AdminUtils.schedule_grandpa_change` | + +The runtime's authorization checks remain in force. The implementation must +define a typed, bounded authority representation and must not expose +SCALE-encoded runtime values. + +Names and signatures on this page are provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/scheduler.mdx b/docs/guides/evm/precompiles/scheduler.mdx index 64992b280c..94f1d8545d 100644 --- a/docs/guides/evm/precompiles/scheduler.mdx +++ b/docs/guides/evm/precompiles/scheduler.mdx @@ -28,22 +28,21 @@ unbounded array result. ## Planned operations -```text -schedule -cancel -scheduleNamed -cancelNamed -scheduleAfter -scheduleNamedAfter -setRetry -setRetryNamed -cancelRetry -cancelRetryNamed -``` +| Proposed function | Source extrinsic | +|---|---| +| `schedule` | `Scheduler.schedule` | +| `cancel` | `Scheduler.cancel` | +| `scheduleNamed` | `Scheduler.schedule_named` | +| `cancelNamed` | `Scheduler.cancel_named` | +| `scheduleAfter` | `Scheduler.schedule_after` | +| `scheduleNamedAfter` | `Scheduler.schedule_named_after` | +| `setRetry` | `Scheduler.set_retry` | +| `setRetryNamed` | `Scheduler.set_retry_named` | +| `cancelRetry` | `Scheduler.cancel_retry` | +| `cancelRetryNamed` | `Scheduler.cancel_retry_named` | Scheduled payloads must use a versioned, stable EVM call description. They must not expose SCALE-encoded `RuntimeCall`, whose encoding can change after a runtime upgrade. Names and signatures on this page are provisional and do not reserve selectors. - diff --git a/docs/guides/evm/precompiles/staking-v2.mdx b/docs/guides/evm/precompiles/staking-v2.mdx index 1eea74daac..334e76640d 100644 --- a/docs/guides/evm/precompiles/staking-v2.mdx +++ b/docs/guides/evm/precompiles/staking-v2.mdx @@ -76,4 +76,50 @@ transferStakeFrom(address,address,bytes32,uint256,uint256,uint256) `allowance` is `view`. Refer to the published ABI for the mutability and return encoding of the allowance mutations. +## Proposed Subtensor operations + +| Proposed function | Source extrinsic | +|---|---| +| `decreaseTake` | `SubtensorModule.decrease_take` | +| `increaseTake` | `SubtensorModule.increase_take` | +| `setChildkeyTake` | `SubtensorModule.set_childkey_take` | +| `setTxChildkeyTakeRateLimit` | `SubtensorModule.sudo_set_tx_childkey_take_rate_limit` | +| `setMinChildkeyTake` | `SubtensorModule.sudo_set_min_childkey_take` | +| `setMaxChildkeyTake` | `SubtensorModule.sudo_set_max_childkey_take` | +| `unstakeAll` | `SubtensorModule.unstake_all` | +| `unstakeAllAlpha` | `SubtensorModule.unstake_all_alpha` | +| `swapStake` | `SubtensorModule.swap_stake` | +| `swapStakeLimit` | `SubtensorModule.swap_stake_limit` | +| `recycleAlpha` | `SubtensorModule.recycle_alpha` | +| `setColdkeyAutoStakeHotkey` | `SubtensorModule.set_coldkey_auto_stake_hotkey` | +| `claimRoot` | `SubtensorModule.claim_root` | +| `setRootClaimType` | `SubtensorModule.set_root_claim_type` | +| `setNumRootClaims` | `SubtensorModule.sudo_set_num_root_claims` | +| `setRootClaimThreshold` | `SubtensorModule.sudo_set_root_claim_threshold` | +| `addStakeBurn` | `SubtensorModule.add_stake_burn` | +| `setAutoParentDelegationEnabled` | `SubtensorModule.set_auto_parent_delegation_enabled` | +| `transferStakeAndHotkey` | `SubtensorModule.transfer_stake_and_hotkey` | +| `addCollateral` | `SubtensorModule.add_collateral` | +| `setMinCollateral` | `SubtensorModule.set_min_collateral` | + +`recycleAlpha` is distinct from deployed `burnAlpha`: recycling reduces +`SubnetAlphaOut` and Alpha issuance, while burning does not reduce +`SubnetAlphaOut`. + +## Proposed AdminUtils operations + +| Proposed function | Source extrinsic | +|---|---| +| `setDefaultTake` | `AdminUtils.sudo_set_default_take` | +| `setStakeThreshold` | `AdminUtils.sudo_set_stake_threshold` | +| `setNominatorMinRequiredStake` | `AdminUtils.sudo_set_nominator_min_required_stake` | +| `setDelegateTakeRateLimit` | `AdminUtils.sudo_set_tx_delegate_take_rate_limit` | +| `setMinDelegateTake` | `AdminUtils.sudo_set_min_delegate_take` | +| `setMinChildkeyTakePerSubnet` | `AdminUtils.sudo_set_min_childkey_take_per_subnet` | +| `setCollateralLockShare` | `AdminUtils.sudo_set_collateral_lock_share` | +| `setCollateralDrainRatio` | `AdminUtils.sudo_set_collateral_drain_ratio` | + +Runtime authorization remains in force. Proposed names and signatures do not +reserve selectors. + Source: [`stakingV2.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/stakingV2.sol) diff --git a/docs/guides/evm/precompiles/subnet.mdx b/docs/guides/evm/precompiles/subnet.mdx index 7b53a362ca..5817cc54ba 100644 --- a/docs/guides/evm/precompiles/subnet.mdx +++ b/docs/guides/evm/precompiles/subnet.mdx @@ -73,21 +73,80 @@ setDifficulty(uint16,uint64) setImmunityPeriod(uint16,uint16) setKappa(uint16,uint16) setLiquidAlphaEnabled(uint16,bool) -setMaxBurn(uint16,uint64) setMaxDifficulty(uint16,uint64) setMinAllowedWeights(uint16,uint16) -setMinBurn(uint16,uint64) setMinDifficulty(uint16,uint64) setNetworkPowRegistrationAllowed(uint16,bool) setNetworkRegistrationAllowed(uint16,bool) setOwnerCutAutoLockEnabled(uint16,bool) setRho(uint16,uint16) setServingRateLimit(uint16,uint64) -setWeightsSetRateLimit(uint16,uint64) setWeightsVersionKey(uint16,uint64) setYuma3Enabled(uint16,bool) toggleTransfers(uint16,bool) ``` -Source: [`subnet.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/subnet.sol) +## Legacy no-op functions + +These released selectors remain routed but intentionally do not change state: + +```text +setWeightsSetRateLimit(uint16,uint64) +setMinBurn(uint16,uint64) +setMaxBurn(uint16,uint64) +``` + +Changing their behavior in place would break their released semantics. The +real AdminUtils operations therefore require the proposed V2 selectors below. + +## Proposed subnet operations + +| Proposed function | Source extrinsic | +|---|---| +| `dissolveNetwork` | `SubtensorModule.dissolve_network` | +| `setSubnetIdentity` | `SubtensorModule.set_subnet_identity` | +| `updateSubnetSymbol` | `SubtensorModule.update_symbol` | +| `rootDissolveNetwork` | `SubtensorModule.root_dissolve_network` | +| `triggerEpoch` | `SubtensorModule.trigger_epoch` | +## Proposed AdminUtils operations + +| Proposed function | Source extrinsic | +|---|---| +| `setAdjustmentInterval` | `AdminUtils.sudo_set_adjustment_interval` | +| `setAdminFreezeWindow` | `AdminUtils.sudo_set_admin_freeze_window` | +| `setBondsPenalty` | `AdminUtils.sudo_set_bonds_penalty` | +| `setCommitRevealVersion` | `AdminUtils.sudo_set_commit_reveal_version` | +| `setDissolveNetworkScheduleDuration` | `AdminUtils.sudo_set_dissolve_network_schedule_duration` | +| `setNetworkLockCostReductionInterval` | `AdminUtils.sudo_set_lock_reduction_interval` | +| `setMaxAllowedUids` | `AdminUtils.sudo_set_max_allowed_uids` | +| `setMaxAllowedValidators` | `AdminUtils.sudo_set_max_allowed_validators` | +| `setMaxBurnV2` | `AdminUtils.sudo_set_max_burn` | +| `setMaxEpochsPerBlock` | `AdminUtils.sudo_set_max_epochs_per_block` | +| `setMaxMechanismCount` | `AdminUtils.sudo_set_max_mechanism_count` | +| `setMaxRegistrationsPerBlock` | `AdminUtils.sudo_set_max_registrations_per_block` | +| `setMechanismCount` | `AdminUtils.sudo_set_mechanism_count` | +| `setMechanismEmissionSplit` | `AdminUtils.sudo_set_mechanism_emission_split` | +| `setMinAllowedUids` | `AdminUtils.sudo_set_min_allowed_uids` | +| `setMinBurnV2` | `AdminUtils.sudo_set_min_burn` | +| `setMinNonImmuneUids` | `AdminUtils.sudo_set_min_non_immune_uids` | +| `setNetworkImmunityPeriod` | `AdminUtils.sudo_set_network_immunity_period` | +| `setNetworkMinLockCost` | `AdminUtils.sudo_set_network_min_lock_cost` | +| `setNetworkRateLimit` | `AdminUtils.sudo_set_network_rate_limit` | +| `setOwnerCutEnabled` | `AdminUtils.sudo_set_owner_cut_enabled` | +| `setOwnerHyperparameterRateLimit` | `AdminUtils.sudo_set_owner_hparam_rate_limit` | +| `setOwnerImmuneNeuronLimit` | `AdminUtils.sudo_set_owner_immune_neuron_limit` | +| `setRaoRecycledForRegistration` | `AdminUtils.sudo_set_rao_recycled` | +| `setSubnetOwnerHotkey` | `AdminUtils.sudo_set_sn_owner_hotkey` | +| `setSubnetLimit` | `AdminUtils.sudo_set_subnet_limit` | +| `setSubnetOwnerCut` | `AdminUtils.sudo_set_subnet_owner_cut` | +| `setSubtokenEnabled` | `AdminUtils.sudo_set_subtoken_enabled` | +| `setTargetRegistrationsPerInterval` | `AdminUtils.sudo_set_target_registrations_per_interval` | +| `setTempo` | `AdminUtils.sudo_set_tempo` | +| `setWeightsSetRateLimitV2` | `AdminUtils.sudo_set_weights_set_rate_limit` | +| `trimToMaxAllowedUids` | `AdminUtils.sudo_trim_to_max_allowed_uids` | + +Runtime authorization remains in force. Proposed names and signatures do not +reserve selectors. + +Source: [`subnet.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/subnet.sol) diff --git a/docs/guides/evm/precompiles/timestamp.mdx b/docs/guides/evm/precompiles/timestamp.mdx index 97f0d78510..8b6d6424d2 100644 --- a/docs/guides/evm/precompiles/timestamp.mdx +++ b/docs/guides/evm/precompiles/timestamp.mdx @@ -25,5 +25,7 @@ description: Proposed typed EVM interface for Timestamp pallet state. user operation. The proposed precompile therefore exposes no state-changing timestamp function. -Names and signatures on this page are provisional and do not reserve selectors. +See the complete classification in +[Extrinsic coverage](/docs/guides/evm/precompiles/extrinsic-coverage). +Names and signatures on this page are provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/voting-power.mdx b/docs/guides/evm/precompiles/voting-power.mdx index ba2cdd3d8d..a38f4d9d88 100644 --- a/docs/guides/evm/precompiles/voting-power.mdx +++ b/docs/guides/evm/precompiles/voting-power.mdx @@ -22,5 +22,14 @@ getVotingPowerEmaAlpha(uint16) getTotalVotingPower(uint16) ``` -Source: [`votingPower.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/votingPower.sol) +## Proposed operations + +| Proposed function | Source extrinsic | +|---|---| +| `enableVotingPowerTracking` | `SubtensorModule.enable_voting_power_tracking` | +| `disableVotingPowerTracking` | `SubtensorModule.disable_voting_power_tracking` | +| `setVotingPowerEmaAlpha` | `SubtensorModule.sudo_set_voting_power_ema_alpha` | +Proposed names and signatures do not reserve selectors. + +Source: [`votingPower.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/votingPower.sol) From f8571e85c9f9f78b75a9213a74f10edcc665bb4d Mon Sep 17 00:00:00 2001 From: girazoki Date: Tue, 28 Jul 2026 16:36:54 +0200 Subject: [PATCH 10/58] ledger signs hash of payload if > 256 --- pallets/limit-orders/src/benchmarking.rs | 17 ++++++++-- pallets/limit-orders/src/lib.rs | 37 +++++++++++++++++++++- pallets/limit-orders/src/tests/readable.rs | 19 +++++++++-- runtime/tests/limit_orders.rs | 22 +++++++++++-- 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/pallets/limit-orders/src/benchmarking.rs b/pallets/limit-orders/src/benchmarking.rs index fd5244a5ac..6f33c65010 100644 --- a/pallets/limit-orders/src/benchmarking.rs +++ b/pallets/limit-orders/src/benchmarking.rs @@ -27,11 +27,22 @@ fn sign_order( order: &crate::VersionedOrder, ) -> crate::SignedOrder { // Mirror the on-chain check in `verify_readable`: the signed message is the - // ``-wrapped canonical readable rendering of the order. + // ``-wrapped canonical readable rendering of the order, hashed + // when it exceeds Ledger's raw-signing limit (which it always does in practice) + // exactly as the device does before signing. let msg = crate::pallet::Pallet::::render_order(order); let payload = [b"".as_slice(), &msg, b"".as_slice()].concat(); - let sig = sp_io::crypto::sr25519_sign(sp_core::crypto::key_types::ACCOUNT, &public, &payload) - .unwrap(); + let signed_bytes = if payload.len() > crate::LEDGER_MAX_SIGN_SIZE { + sp_core::hashing::blake2_256(&payload).to_vec() + } else { + payload + }; + let sig = sp_io::crypto::sr25519_sign( + sp_core::crypto::key_types::ACCOUNT, + &public, + &signed_bytes, + ) + .unwrap(); crate::SignedOrder { order: order.clone(), signature: MultiSignature::Sr25519(sig), diff --git a/pallets/limit-orders/src/lib.rs b/pallets/limit-orders/src/lib.rs index 3e4c5cff9a..8917ff29a1 100644 --- a/pallets/limit-orders/src/lib.rs +++ b/pallets/limit-orders/src/lib.rs @@ -26,6 +26,20 @@ use subtensor_macros::freeze_struct; use subtensor_runtime_common::{AlphaBalance, NetUid, TaoBalance, Token}; use subtensor_swap_interface::OrderSwapInterface; +/// Ledger's raw-signing size limit — `MAX_SIGN_SIZE` in the Zondax Polkadot app +/// (`app/src/coin.h`), mirroring the 256-byte rule Substrate applies to extrinsic +/// signing payloads. +/// +/// A `signRaw` payload longer than this is **blake2_256-hashed on-device** before +/// the ed25519 signature is produced (`crypto_sign_ed25519` in `app/src/crypto.c`), +/// so the signature commits to the hash of the payload rather than to the payload +/// bytes. The device still displays the full message: the printable-ASCII check and +/// pagination in `tx_raw_getItem` operate on the received buffer, and the hashing +/// happens later, in the signing step only. Clear-signing therefore remains +/// what-you-see-is-what-you-sign — the on-chain verifier just has to accept the +/// hashed commitment as well (see `verify_readable`). +pub const LEDGER_MAX_SIGN_SIZE: usize = 256; + // ── Data structures ────────────────────────────────────────────────────────── /// Internal direction of a net pool trade. Used only for `GroupExecutionSummary` @@ -725,14 +739,35 @@ partial fills {partial}, signer {signer}", /// and sign. The signed payload is the ``-wrapped canonical message built /// by [`render_order`] (the `signRaw`/Ledger envelope). Accepts sr25519 and /// ed25519; rejects ecdsa. + /// + /// The bytes actually verified follow the device's own rule: a raw-signing + /// payload longer than [`LEDGER_MAX_SIGN_SIZE`] is blake2_256-hashed on-device + /// before signing, so for an oversized payload the signature commits to + /// `blake2_256(payload)` and that is what is verified; at or below the limit the + /// payload bytes are verified directly. In practice the readable message is + /// always oversized (three SS58 addresses alone are 144 characters), so the + /// hashed branch is the live one — the byte-exact branch exists to keep this + /// function correct for any future, shorter rendering. + /// + /// The sibling forms need no such rule: `verify_wrapped`'s payload is a fixed + /// 47 bytes (`` + 32-byte hash + ``), and `verify_order` is not a + /// Ledger form at all — it has no `` envelope, which the device's + /// `tx_raw_parse` requires, so a Ledger can never produce it. pub(crate) fn verify_readable(signed_order: &SignedOrder) -> bool { let order = signed_order.order.inner(); let msg = Self::render_order(&signed_order.order); let payload = [b"".as_slice(), &msg, b"".as_slice()].concat(); + let signed_bytes = if payload.len() > LEDGER_MAX_SIGN_SIZE { + sp_core::hashing::blake2_256(&payload).to_vec() + } else { + payload + }; matches!( signed_order.signature, MultiSignature::Sr25519(_) | MultiSignature::Ed25519(_) - ) && signed_order.signature.verify(payload.as_slice(), &order.signer) + ) && signed_order + .signature + .verify(signed_bytes.as_slice(), &order.signer) } /// Validates all execution preconditions for a signed order. diff --git a/pallets/limit-orders/src/tests/readable.rs b/pallets/limit-orders/src/tests/readable.rs index ed706d7b99..bd7d724351 100644 --- a/pallets/limit-orders/src/tests/readable.rs +++ b/pallets/limit-orders/src/tests/readable.rs @@ -48,6 +48,19 @@ fn readable_signing_payload(order: &VersionedOrder) -> Vec { [b"".as_slice(), &msg, b"".as_slice()].concat() } +/// The bytes a signer actually puts through ed25519/sr25519 for the readable form — +/// i.e. what a Ledger emits. The device blake2_256-hashes a raw-signing payload +/// longer than `LEDGER_MAX_SIGN_SIZE` before signing it, and `verify_readable` +/// follows the same rule, so these tests must too. +fn readable_signed_bytes(order: &VersionedOrder) -> Vec { + let payload = readable_signing_payload(order); + if payload.len() > crate::LEDGER_MAX_SIGN_SIZE { + sp_core::hashing::blake2_256(&payload).to_vec() + } else { + payload + } +} + /// A fully-specified LimitBuy order that passes every non-signature guard in /// `is_order_valid` under the default mock setup (netuid 1, chain 945, far-future /// expiry, no relayer restriction, price condition met at price 1.0). @@ -76,7 +89,7 @@ fn make_readable_signed_order( order: Order, ) -> crate::SignedOrder { let versioned = VersionedOrder::V1(order); - let sig = keyring.pair().sign(&readable_signing_payload(&versioned)); + let sig = keyring.pair().sign(&readable_signed_bytes(&versioned)); crate::SignedOrder { order: versioned, signature: MultiSignature::Sr25519(sig), @@ -365,7 +378,7 @@ fn is_order_valid_accepts_readable_ed25519_signature() { ..base_buy_order() }; let versioned = VersionedOrder::V1(order); - let ed_sig = ed_pair.sign(&readable_signing_payload(&versioned)); + let ed_sig = ed_pair.sign(&readable_signed_bytes(&versioned)); let signed = crate::SignedOrder { order: versioned, signature: MultiSignature::Ed25519(ed_sig), @@ -584,7 +597,7 @@ fn readable_ecdsa_signature_rejected() { let order = base_buy_order(); let versioned = VersionedOrder::V1(order); let ecdsa_pair = sp_core::ecdsa::Pair::from_legacy_string("//Alice", None); - let ecdsa_sig = ecdsa_pair.sign(&readable_signing_payload(&versioned)); + let ecdsa_sig = ecdsa_pair.sign(&readable_signed_bytes(&versioned)); let signed = crate::SignedOrder { order: versioned, signature: MultiSignature::Ecdsa(ecdsa_sig), diff --git a/runtime/tests/limit_orders.rs b/runtime/tests/limit_orders.rs index 79cfd4901a..1f62b4f4f9 100644 --- a/runtime/tests/limit_orders.rs +++ b/runtime/tests/limit_orders.rs @@ -2841,6 +2841,24 @@ partial fills {partial}, signer {signer}", .into_bytes() } +/// The bytes a signer actually signs for the readable form: the ``-wrapped +/// message, blake2_256-hashed when it exceeds Ledger's raw-signing limit. +/// +/// A Ledger hashes any `signRaw` payload longer than `MAX_SIGN_SIZE` (256 bytes, +/// `app/src/coin.h` in the Zondax Polkadot app) before signing it, and the runtime +/// verifies against the same rule. The readable message is always oversized (three +/// SS58 addresses alone are 144 characters), so this is the hashed shape in +/// practice — the `else` arm exists only to mirror the runtime exactly. +fn readable_signed_bytes(order: &Order) -> Vec { + let msg = render_order_readable(order); + let payload = [b"".as_slice(), &msg, b"".as_slice()].concat(); + if payload.len() > pallet_limit_orders::LEDGER_MAX_SIGN_SIZE { + sp_core::hashing::blake2_256(&payload).to_vec() + } else { + payload + } +} + /// End-to-end: a LimitBuy order signed with the human-readable ("clear-signing") /// payload — `` ++ render_order ++ `` — executes through /// `execute_batched_orders`, is marked Fulfilled, and credits staked alpha to the @@ -2879,9 +2897,7 @@ fn execute_batched_orders_readable_signature_executes() { let order = VersionedOrder::V1(inner.clone()); let id = order_id(&order); - let msg = render_order_readable(&inner); - let payload = [b"".as_slice(), &msg, b"".as_slice()].concat(); - let sig = alice.pair().sign(&payload); + let sig = alice.pair().sign(&readable_signed_bytes(&inner)); let signed = SignedOrder { order, signature: MultiSignature::Sr25519(sig), From ee6de759d67df93b2478076c2f083755fe555043 Mon Sep 17 00:00:00 2001 From: girazoki Date: Tue, 28 Jul 2026 16:39:03 +0200 Subject: [PATCH 11/58] ts tests updated --- ts-tests/utils/limit-orders.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ts-tests/utils/limit-orders.ts b/ts-tests/utils/limit-orders.ts index 0ffc83a192..b510920cc2 100644 --- a/ts-tests/utils/limit-orders.ts +++ b/ts-tests/utils/limit-orders.ts @@ -153,6 +153,18 @@ export function buildWrappedSignedOrder(api: any, params: OrderParams): SignedOr */ export const READABLE_SS58_PREFIX = 42; +/** + * Ledger's raw-signing size limit — `MAX_SIGN_SIZE` in the Zondax Polkadot app. + * MUST match the pallet's `LEDGER_MAX_SIGN_SIZE`. + * + * A `signRaw` payload longer than this is blake2_256-hashed on-device before the + * signature is produced, so for an oversized payload the signature commits to the + * hash rather than to the payload bytes, and the runtime verifies it that way. + * The device still displays the full message — the hashing happens in the signing + * step only. + */ +export const LEDGER_MAX_SIGN_SIZE = 256; + /** * Re-encode an account address as SS58 at prefix 42. Accepts any input the * `@polkadot/util-crypto` `decodeAddress` understands (SS58 of any prefix, hex, @@ -221,6 +233,13 @@ export function formatOrderMessage(order: Order): string { * `[b"", &render_order, b""].concat()`. Wrapping the raw string * instead of the bytes would corrupt the payload. * + * The bytes actually signed then follow the device's rule: a payload longer than + * `LEDGER_MAX_SIGN_SIZE` is blake2_256-hashed first, because that is what a Ledger + * signs and therefore what the runtime verifies. The readable message is always + * oversized (three SS58 addresses alone are 144 characters), so this emulates a + * hardware signer. Note that `signRaw` in a *software* wallet (polkadot.js + * extension) does NOT hash — such a signature is not valid on this path. + * * The signature scheme tag (`Sr25519` vs `Ed25519`) follows the signer's * keypair type, so the same helper works for both schemes. */ @@ -230,7 +249,8 @@ export function buildReadableSignedOrder(api: any, params: OrderParams): SignedO // Render the canonical message, convert to UTF-8 bytes, then wrap. const message = formatOrderMessage(versionedOrder.V1); const wrapped = u8aWrapBytes(stringToU8a(message)); - const sig = params.signer.sign(wrapped); + const signedBytes = wrapped.length > LEDGER_MAX_SIGN_SIZE ? blake2AsU8a(wrapped, 256) : wrapped; + const sig = params.signer.sign(signedBytes); // Tag the signature variant from the keypair type. const signature = From 75aeb3ed88b55265a478d4f29f39954478edd632 Mon Sep 17 00:00:00 2001 From: girazoki Date: Tue, 28 Jul 2026 18:07:03 +0200 Subject: [PATCH 12/58] ledger test vectors --- .../limit-orders/src/tests/ledger_vector.rs | 419 ++++++++++++++++++ pallets/limit-orders/src/tests/mod.rs | 1 + .../test-ledger-raw-sign-vector.ts | 279 ++++++++++++ 3 files changed, 699 insertions(+) create mode 100644 pallets/limit-orders/src/tests/ledger_vector.rs create mode 100644 ts-tests/suites/dev/subtensor/limit-orders/test-ledger-raw-sign-vector.ts diff --git a/pallets/limit-orders/src/tests/ledger_vector.rs b/pallets/limit-orders/src/tests/ledger_vector.rs new file mode 100644 index 0000000000..31c43e8113 --- /dev/null +++ b/pallets/limit-orders/src/tests/ledger_vector.rs @@ -0,0 +1,419 @@ +#![allow(clippy::expect_used, clippy::unwrap_used, clippy::indexing_slicing)] +//! Hardware test vector for the human-readable ("clear-signing") signing form. +//! +//! ## What this pins +//! +//! A Ledger blake2_256-hashes a raw-signing (`signRaw`) payload longer than +//! `MAX_SIGN_SIZE` = 256 bytes before signing it (`crypto_sign_ed25519` in +//! `app/src/crypto.c` of the Zondax Polkadot app; the same `app_sign_ed25519` +//! callback serves both `INS_SIGN` and `INS_SIGN_RAW`). The readable message is +//! always over that limit, so a real device signature commits to +//! `blake2_256( ++ message ++ )`, never to the payload bytes — +//! which is why `verify_readable` follows the same rule. +//! +//! That rule is NOT the symmetric one in `Encode for SignedPayload` +//! (`sp_runtime::generic::unchecked_extrinsic`): that impl is only reached when the +//! extrinsic machinery rebuilds a *transaction* signing payload, and both signer and +//! verifier go through it. Raw message signing has no such mirror — polkadot-js's +//! `pair.sign()` applies a length rule for ecdsa only — so on this path the device +//! hashes and a software signer does not. +//! +//! Two things are pinned here: +//! 1. `render_order` produces byte-for-byte the message the device displayed and +//! signed, and its wrapped payload hashes to the digest the device signed over. +//! 2. That digest, not the payload, is what the recorded device signature verifies +//! against — on real hardware. +//! +//! ## Provenance +//! +//! Captured 2026-07-28 from a Nano S+ running Polkadot Generic v100.0.25, derivation +//! path `m/44'/354'/0'/0'/0'`. The device rendered the whole order text across its +//! screens before signing, so digest signing is NOT a blind-signing fallback: +//! clear-signing works, and shrinking the message under 256 bytes would only reduce +//! the page count. A probe matrix ruled out the alternatives (unwrapped message, +//! `blake2_256` of the unwrapped message, blake2_512, ASCII hex of the digest) — +//! all of them are re-checked below. +//! +//! ## Why this is not an end-to-end order test +//! +//! The capture's device key is not the account named in the message's `signer` field +//! (the message was rendered for a different account), and `verify_readable` checks +//! the signature against `order.signer`. So the vector pins the *rule* and the +//! *rendering*, not order execution; the acceptance path itself is covered by +//! `tests/readable.rs`. An executable vector needs a fresh capture whose message +//! renders `signer` as the device's own address, with `chain_id` matching the test +//! environment and `expiry` in milliseconds (this one's `1793000000` is a +//! seconds-scale value, i.e. long expired). +//! +//! The *executable* vector at the bottom of this file closes that gap without a +//! device: the software half's seed is known, ed25519 is deterministic (RFC 8032), +//! and the device's only transformation is the conditional hash — so a signature +//! minted offline over `blake2_256(payload)` for a message naming that account as +//! `signer` is byte-identical to what a Ledger holding the seed would return, and it +//! goes through the full acceptance path. + +use frame_support::{assert_ok, traits::Get}; +use sp_core::{Pair, crypto::Ss58Codec, hexdisplay::HexDisplay}; +use sp_runtime::{MultiSignature, Perbill, traits::Verify}; +use subtensor_runtime_common::NetUid; +use subtensor_swap_interface::OrderSwapInterface; + +use crate::pallet::Pallet as LimitOrders; +use crate::{LEDGER_MAX_SIGN_SIZE, Order, OrderType, VersionedOrder}; + +use super::mock::*; + +// ── The vector ─────────────────────────────────────────────────────────────── + +/// The exact text the device displayed and signed: `render_order`'s output for +/// [`vector_order`], SS58 prefix 42. 381 bytes. +const ORDER_MESSAGE: &str = "TAO.com order v1: Limit buy 1000000000 on subnet 64, \ +limit price 500000000, expiry 1793000000, \ +hotkey 5HK5tp6t2S59DywmHRWPBVJeJ86T61KjurYqeooqj8sREpeN, \ +fee 8500000 to 5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY, \ +relayer 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty, max slippage 7500000, \ +chain 1, partial fills true, signer 5CD9UfFv3FLd9BRP8tK7BumpEYvu2y3KZMuhUnDAhuzPbdtC"; + +/// Length of `ORDER_MESSAGE` in bytes. +const ORDER_MESSAGE_LEN: usize = 381; + +/// Length of `` ++ `ORDER_MESSAGE` ++ `` — the blob that reaches the +/// device, and what it hashes because 396 > 256. +const WRAPPED_PAYLOAD_LEN: usize = 396; + +/// `blake2_256( ++ ORDER_MESSAGE ++ )`: the 32 bytes the device signs. +const WRAPPED_PAYLOAD_DIGEST: [u8; 32] = [ + 0x3c, 0x3e, 0xa8, 0x8b, 0x51, 0x45, 0x71, 0x89, 0x38, 0x89, 0x06, 0xee, 0xcb, 0x58, 0x2d, 0x5e, + 0xbf, 0x48, 0x1b, 0x1a, 0xf5, 0xb6, 0x6b, 0x6b, 0x57, 0x71, 0xe4, 0xe8, 0x4b, 0x6e, 0x5e, 0xd7, +]; + +/// ed25519 public key of the Nano S+ account that produced [`DEVICE_SIGNATURE`]. +const DEVICE_PUBLIC_KEY: [u8; 32] = [ + 0x76, 0xe2, 0x81, 0x5d, 0x89, 0xea, 0x8f, 0x87, 0xa7, 0xfc, 0x62, 0xc2, 0x1b, 0x3e, 0xe2, 0xfb, + 0x81, 0xd7, 0x8c, 0xa2, 0x8a, 0x24, 0xd3, 0x3a, 0x97, 0x4f, 0x47, 0xb2, 0x0b, 0xb7, 0x0a, 0x63, +]; + +/// The signature the device returned for the 396-byte wrapped payload. +const DEVICE_SIGNATURE: [u8; 64] = [ + 0x91, 0xa3, 0x7e, 0x50, 0xd0, 0x1e, 0xeb, 0x40, 0x7d, 0x9d, 0x19, 0x02, 0x37, 0x4f, 0xef, 0x24, + 0xdc, 0x28, 0x7c, 0x1e, 0xdb, 0x81, 0x47, 0x4d, 0xbe, 0x19, 0xe4, 0x61, 0x57, 0xbc, 0xc2, 0x3d, + 0xc5, 0xb7, 0xba, 0x72, 0x3a, 0xe7, 0xf8, 0xdd, 0x19, 0x20, 0x04, 0xc1, 0x50, 0xa8, 0xd0, 0x47, + 0x9a, 0x0c, 0xcb, 0x52, 0x2c, 0x93, 0x0d, 0xc8, 0xfc, 0xda, 0x7a, 0x15, 0xd6, 0xb4, 0x5b, 0x08, +]; + +/// Software half of the vector: reproducible without a device. Seed `0x01..0x20`, +/// with a signature over EACH form so both semantics have a fixture. +const SOFTWARE_SEED: [u8; 32] = [ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, +]; + +/// ed25519 public key derived from [`SOFTWARE_SEED`]. +const SOFTWARE_PUBLIC_KEY: [u8; 32] = [ + 0x79, 0xb5, 0x56, 0x2e, 0x8f, 0xe6, 0x54, 0xf9, 0x40, 0x78, 0xb1, 0x12, 0xe8, 0xa9, 0x8b, 0xa7, + 0x90, 0x1f, 0x85, 0x3a, 0xe6, 0x95, 0xbe, 0xd7, 0xe0, 0xe3, 0x91, 0x0b, 0xad, 0x04, 0x96, 0x64, +]; + +/// `ed25519(SOFTWARE_SEED, wrapped payload)` — the shape a software `signRaw` emits. +const SOFTWARE_SIGNATURE_OVER_PAYLOAD: [u8; 64] = [ + 0xc8, 0xd1, 0x2f, 0xfc, 0xdc, 0x50, 0x4a, 0x95, 0x6b, 0x97, 0xfd, 0x67, 0x00, 0x9d, 0xe2, 0x8c, + 0x65, 0x41, 0xbf, 0x79, 0xdc, 0x33, 0x90, 0x30, 0x92, 0xd9, 0xf1, 0xc2, 0x79, 0x71, 0x8c, 0x97, + 0x91, 0xcf, 0x5b, 0xc6, 0x9a, 0x38, 0x89, 0xc6, 0x69, 0x9a, 0x5a, 0xab, 0x18, 0x17, 0x0c, 0xdc, + 0x23, 0x66, 0xf8, 0x1d, 0xae, 0xa5, 0xec, 0xd3, 0x1c, 0x64, 0x10, 0x83, 0x85, 0xb1, 0xb6, 0x0d, +]; + +/// `ed25519(SOFTWARE_SEED, blake2_256(wrapped payload))` — the shape the device emits. +const SOFTWARE_SIGNATURE_OVER_DIGEST: [u8; 64] = [ + 0x81, 0xed, 0xd4, 0x7a, 0x3e, 0x02, 0xb7, 0xf5, 0x2c, 0xc6, 0xa7, 0xdb, 0x02, 0xe9, 0xa8, 0xc0, + 0x23, 0xc1, 0xf1, 0x01, 0x52, 0x6a, 0x7d, 0x5f, 0xe4, 0xbe, 0x11, 0x8a, 0xff, 0x36, 0x09, 0x0c, + 0xcf, 0x65, 0xf7, 0x51, 0x36, 0xb3, 0x1f, 0x6f, 0x64, 0xd8, 0xbc, 0xec, 0xc4, 0xe4, 0x41, 0xb3, + 0x23, 0x22, 0xc3, 0x7b, 0x4a, 0xf5, 0x14, 0x36, 0xa1, 0xe9, 0x90, 0x96, 0x20, 0x2b, 0x86, 0x08, +]; + +/// The order whose rendering is `ORDER_MESSAGE`. Accounts are decoded from the SS58 +/// strings in the message itself, so the rendering assertion is a round-trip through +/// `Ss58Codec` rather than a comparison of one `render_account` call against another. +fn vector_order() -> Order { + let account = |s: &str| AccountId::from_ss58check(s).expect("vector SS58 must decode"); + Order { + signer: account("5CD9UfFv3FLd9BRP8tK7BumpEYvu2y3KZMuhUnDAhuzPbdtC"), + hotkey: account("5HK5tp6t2S59DywmHRWPBVJeJ86T61KjurYqeooqj8sREpeN"), + netuid: NetUid::from(64u16), + order_type: OrderType::LimitBuy, + amount: 1_000_000_000, + limit_price: 500_000_000, + expiry: 1_793_000_000, + fee_rate: Perbill::from_parts(8_500_000), + fee_recipient: account("5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY"), + relayer: Some( + frame_support::BoundedVec::try_from(vec![account( + "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", + )]) + .unwrap(), + ), + max_slippage: Some(Perbill::from_parts(7_500_000)), + chain_id: 1, + partial_fills_enabled: true, + } +} + +/// `` ++ `ORDER_MESSAGE` ++ ``, built from the pinned text rather than +/// from `render_order`, so the two can be compared. +fn wrapped_payload() -> Vec { + [ + b"".as_slice(), + ORDER_MESSAGE.as_bytes(), + b"".as_slice(), + ] + .concat() +} + +// ── Tests ──────────────────────────────────────────────────────────────────── + +/// `render_order` must reproduce the message the device actually displayed and +/// signed. If this fails, the pallet and the hardware no longer agree on what a +/// signature means — every signature captured by a user becomes unverifiable. +#[test] +fn render_order_matches_the_device_displayed_message() { + new_test_ext().execute_with(|| { + assert_eq!( + <::SS58Prefix as Get>::get(), + 42, + "the vector was captured at SS58 prefix 42" + ); + + let rendered = LimitOrders::::render_order(&VersionedOrder::V1(vector_order())); + assert_eq!( + String::from_utf8(rendered.clone()).unwrap(), + ORDER_MESSAGE, + "render_order drifted from the message a real Ledger signed" + ); + assert_eq!(rendered.len(), ORDER_MESSAGE_LEN); + for (i, b) in rendered.iter().enumerate() { + assert!( + (0x20..=0x7e).contains(b), + "byte {i} = {b:#x} is not printable ASCII, so the device would render \ + it as hex instead of text" + ); + } + }); +} + +/// The wrapped payload is over Ledger's limit and hashes to the digest the device +/// signed. Ties our own bytes to the recorded hardware signature. +#[test] +fn wrapped_payload_is_oversized_and_hashes_to_the_signed_digest() { + new_test_ext().execute_with(|| { + let from_render = { + let msg = LimitOrders::::render_order(&VersionedOrder::V1(vector_order())); + [b"".as_slice(), &msg, b"".as_slice()].concat() + }; + assert_eq!(from_render, wrapped_payload()); + assert_eq!(from_render.len(), WRAPPED_PAYLOAD_LEN); + assert!( + from_render.len() > LEDGER_MAX_SIGN_SIZE, + "396 bytes must exceed the {LEDGER_MAX_SIGN_SIZE}-byte device limit" + ); + assert_eq!( + sp_core::hashing::blake2_256(&from_render), + WRAPPED_PAYLOAD_DIGEST + ); + }); +} + +/// The hardware fact this whole branch rests on: the Nano S+ signature verifies +/// against `blake2_256(payload)` and against nothing else. The rejected forms are +/// the alternatives the capture's probe matrix ruled out. +#[test] +fn device_signature_is_over_the_blake2_256_digest_only() { + new_test_ext().execute_with(|| { + let signer = AccountId::new(DEVICE_PUBLIC_KEY); + let signature = + MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw(DEVICE_SIGNATURE)); + let payload = wrapped_payload(); + let message = ORDER_MESSAGE.as_bytes(); + + assert!( + signature.verify(&WRAPPED_PAYLOAD_DIGEST[..], &signer), + "recorded device signature must verify over blake2_256(wrapped payload)" + ); + + for (form, bytes) in [ + ("the raw wrapped payload", payload.clone()), + ("the unwrapped message", message.to_vec()), + ( + "blake2_256 of the unwrapped message", + sp_core::hashing::blake2_256(message).to_vec(), + ), + ( + "blake2_512 of the wrapped payload", + sp_core::hashing::blake2_512(&payload).to_vec(), + ), + ( + // Lowercase hex without `0x`, i.e. what a JS `u8aToHex(d).slice(2)` + // would have put on the wire. + "the ASCII hex of the digest", + format!("{}", HexDisplay::from(&WRAPPED_PAYLOAD_DIGEST)).into_bytes(), + ), + ] { + assert!( + !signature.verify(bytes.as_slice(), &signer), + "device signature must NOT verify over {form}" + ); + } + }); +} + +/// The software half, and the reason a verifier cannot be lenient: the two forms are +/// mutually unverifiable, so signer and verifier disagreeing about which one is in +/// play is a hard rejection, never a soft fallback. +#[test] +fn software_vector_forms_are_mutually_unverifiable() { + new_test_ext().execute_with(|| { + let pair = sp_core::ed25519::Pair::from_seed(&SOFTWARE_SEED); + assert_eq!( + AccountId::from(pair.public()), + AccountId::new(SOFTWARE_PUBLIC_KEY), + "sp-core must derive the pinned public key from the pinned seed" + ); + + let signer = AccountId::new(SOFTWARE_PUBLIC_KEY); + let over_payload = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( + SOFTWARE_SIGNATURE_OVER_PAYLOAD, + )); + let over_digest = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( + SOFTWARE_SIGNATURE_OVER_DIGEST, + )); + let payload = wrapped_payload(); + + assert!(over_payload.verify(payload.as_slice(), &signer)); + assert!(!over_payload.verify(&WRAPPED_PAYLOAD_DIGEST[..], &signer)); + assert!(over_digest.verify(&WRAPPED_PAYLOAD_DIGEST[..], &signer)); + assert!(!over_digest.verify(payload.as_slice(), &signer)); + }); +} + +// ── Executable vector ──────────────────────────────────────────────────────── +// +// The hardware capture above cannot be submitted as an order: its message names +// `5CD9UfFv…` as the signer while the device that signed holds `5Ekanz…`, and +// `verify_readable` checks the signature against `order.signer`. Rejecting it is +// correct, so the acceptance path needs a vector whose message names the signing +// account. +// +// This one is minted offline from `SOFTWARE_SEED` (which we hold), over +// `blake2_256( ++ message ++ )` — the same bytes the device signs. +// ed25519 is deterministic and the transformation is fixed, so these are exactly +// the bytes a Ledger holding that seed would return for this order. What it does +// NOT do is attest to device behaviour; that is what the capture above is for. +// +// Fields are chosen to clear every non-signature guard in `is_order_valid` under +// the default mock: netuid 1 (non-root), chain 945 (the mock's `ChainId`), expiry +// `u64::MAX`, no relayer restriction, and limit price 1.0 TAO/alpha so the LimitBuy +// trigger fires at the mock price. Hotkey and fee recipient are the well-known dev +// accounts Bob (sr25519) and Charlie, decoded from SS58 so the same constants are +// reusable from TypeScript. + +/// Rendering of [`executable_vector_order`], signed by `SOFTWARE_SEED`'s account. +const EXECUTABLE_MESSAGE: &str = "TAO.com order v1: Limit buy 1000 on subnet 1, \ +limit price 1000000000, expiry 18446744073709551615, \ +hotkey 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty, \ +fee 0 to 5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y, \ +relayer none, max slippage none, chain 945, \ +partial fills false, signer 5EpHX5foDtnhZngj4GsKq5eKGpUvuMqbpUG48ZfCCCs7EzKR"; + +/// `blake2_256` of the wrapped [`EXECUTABLE_MESSAGE`] — 350 bytes wrapped, so hashed. +const EXECUTABLE_VECTOR_DIGEST: [u8; 32] = [ + 0xcd, 0x8f, 0x76, 0xe8, 0x89, 0xc5, 0x86, 0xd5, 0xef, 0xb7, 0x3d, 0xd0, 0x34, 0x33, 0xdc, 0x16, + 0x4b, 0x75, 0xfd, 0x72, 0x7c, 0x52, 0xaa, 0xa4, 0xc8, 0xd0, 0x7e, 0xb1, 0x3d, 0xc9, 0x8c, 0x12, +]; + +/// `ed25519(SOFTWARE_SEED, EXECUTABLE_VECTOR_DIGEST)`. +const EXECUTABLE_VECTOR_SIGNATURE: [u8; 64] = [ + 0xca, 0x9e, 0x4c, 0x33, 0x69, 0x50, 0x72, 0xff, 0xef, 0x1e, 0x3e, 0x1d, 0x07, 0x15, 0x97, 0x9e, + 0x3a, 0x4d, 0x8b, 0x55, 0x3e, 0xe1, 0xec, 0xc2, 0x9e, 0x5d, 0xa9, 0xea, 0xd5, 0x78, 0x89, 0x10, + 0x4d, 0x4b, 0xc7, 0x76, 0x0c, 0x4f, 0x9a, 0x86, 0x7e, 0x82, 0xb0, 0x46, 0x27, 0x1e, 0x47, 0xb5, + 0x54, 0x60, 0x94, 0x89, 0xd6, 0x66, 0x16, 0x8b, 0x54, 0x9d, 0x75, 0xb3, 0x9b, 0x55, 0x9b, 0x04, +]; + +/// The order [`EXECUTABLE_VECTOR_SIGNATURE`] authorises. Its `signer` IS the account +/// that signed, which is what makes it submittable. +fn executable_vector_order() -> Order { + let account = |s: &str| AccountId::from_ss58check(s).expect("vector SS58 must decode"); + Order { + signer: AccountId::new(SOFTWARE_PUBLIC_KEY), + hotkey: account("5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"), + netuid: NetUid::from(1u16), + order_type: OrderType::LimitBuy, + amount: 1_000, + limit_price: 1_000_000_000, + expiry: u64::MAX, + fee_rate: Perbill::zero(), + fee_recipient: account("5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"), + relayer: None, + max_slippage: None, + chain_id: 945, + partial_fills_enabled: false, + } +} + +/// The frozen signature must be the one `SOFTWARE_SEED` produces for this order's +/// rendering — pins the message, the digest, and the signature together, so any drift +/// in `render_order` fails here with the message diff rather than as an opaque +/// signature rejection. +#[test] +fn executable_vector_is_the_seeds_signature_over_the_rendered_message() { + new_test_ext().execute_with(|| { + let rendered = LimitOrders::::render_order(&VersionedOrder::V1( + executable_vector_order(), + )); + assert_eq!( + String::from_utf8(rendered.clone()).unwrap(), + EXECUTABLE_MESSAGE, + "render_order drifted from the message the frozen signature covers" + ); + + let payload = [b"".as_slice(), &rendered, b"".as_slice()].concat(); + assert!(payload.len() > LEDGER_MAX_SIGN_SIZE, "must be hashed, not signed bare"); + assert_eq!( + sp_core::hashing::blake2_256(&payload), + EXECUTABLE_VECTOR_DIGEST + ); + assert_eq!( + sp_core::ed25519::Pair::from_seed(&SOFTWARE_SEED).sign(&EXECUTABLE_VECTOR_DIGEST), + sp_core::ed25519::Signature::from_raw(EXECUTABLE_VECTOR_SIGNATURE), + "ed25519 is deterministic, so the seed must reproduce the frozen signature" + ); + }); +} + +/// The point of the whole exercise: a hardcoded, device-shaped signature is accepted +/// by `verify_readable` and clears the full validation chain. +#[test] +fn executable_vector_is_accepted_by_verify_readable_and_is_order_valid() { + new_test_ext().execute_with(|| { + MockTime::set(1_000_000); + MockSwap::set_price(1.0); + + let signed = crate::SignedOrder { + order: VersionedOrder::V1(executable_vector_order()), + signature: MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( + EXECUTABLE_VECTOR_SIGNATURE, + )), + partial_fill: None, + }; + let id = LimitOrders::::derive_order_id(&signed.order); + + assert!( + LimitOrders::::verify_readable(&signed), + "a signature in the form a Ledger emits must pass verify_readable" + ); + assert_ok!(LimitOrders::::is_order_valid( + &signed, + id, + 1_000_000, + MockSwap::current_alpha_price(netuid()), + &bob() + )); + }); +} diff --git a/pallets/limit-orders/src/tests/mod.rs b/pallets/limit-orders/src/tests/mod.rs index b9b2037652..fe941a9878 100644 --- a/pallets/limit-orders/src/tests/mod.rs +++ b/pallets/limit-orders/src/tests/mod.rs @@ -1,5 +1,6 @@ pub mod auxiliary; pub mod extrinsics; +pub mod ledger_vector; pub mod migration; pub mod mock; pub mod readable; diff --git a/ts-tests/suites/dev/subtensor/limit-orders/test-ledger-raw-sign-vector.ts b/ts-tests/suites/dev/subtensor/limit-orders/test-ledger-raw-sign-vector.ts new file mode 100644 index 0000000000..a4fee1ecb2 --- /dev/null +++ b/ts-tests/suites/dev/subtensor/limit-orders/test-ledger-raw-sign-vector.ts @@ -0,0 +1,279 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { Keyring } from "@polkadot/keyring"; +import { hexToU8a, stringToU8a, u8aToHex, u8aWrapBytes } from "@polkadot/util"; +import { blake2AsU8a, ed25519PairFromSeed, ed25519Verify } from "@polkadot/util-crypto"; +import { + type Order, + LEDGER_MAX_SIGN_SIZE, + buildReadableSignedOrder, + formatOrderMessage, +} from "../../../../utils/limit-orders.js"; + +// Hardware test vector for the human-readable ("clear-signing") signing form. +// +// A Ledger blake2_256-hashes a raw-signing (`signRaw`) payload longer than +// MAX_SIGN_SIZE = 256 bytes before signing it (`crypto_sign_ed25519` in +// `app/src/crypto.c` of the Zondax Polkadot app). The readable message is always +// over that limit, so a real device signature commits to +// `blake2_256( ++ message ++ )` — never to the payload bytes. This +// is NOT the symmetric rule in Substrate's `SignedPayload`/`GenericExtrinsicPayload` +// (that pair only governs *extrinsic* signing payloads, where signer and verifier +// both apply it). On the raw-message path only the device hashes: polkadot-js's +// `pair.sign()` applies a length rule for ecdsa only. Hence any verifier of an +// oversized Ledger-signed order must hash first, and the utils' readable signer +// mirrors that. +// +// Captured 2026-07-28 from a Nano S+ running Polkadot Generic v100.0.25, derivation +// path m/44'/354'/0'/0'/0'. The device rendered the whole order text across its +// screens and still signed the digest, so digest signing is NOT a blind-signing +// fallback — clear-signing works, and a shorter message would only cut page count. +// The probe matrix that ruled out the alternatives (unwrapped message, blake2_512, +// digest-as-hex) is re-run in T05. +// +// The vector is pinned as literal data on purpose: a vector must outlive the +// harness that produced it. The Rust half lives in +// `pallets/limit-orders/src/tests/ledger_vector.rs` and pins the same bytes against +// the pallet's own `render_order`. +// +// NOTE: the capture's device key is NOT the account named in the message's `signer` +// field, and the runtime verifies against `order.signer` — so this suite pins the +// rule and the renderer, not order execution. Order acceptance is covered by +// `test-execute-orders-readable.ts`. An executable vector needs a fresh capture +// whose message renders `signer` as the device's own address, with `chain_id` +// matching this environment and `expiry` in milliseconds (this one's 1793000000 is +// a seconds-scale value, i.e. long expired). + +/** The exact text the device displayed and signed, SS58 prefix 42. */ +const ORDER_MESSAGE = + "TAO.com order v1: Limit buy 1000000000 on subnet 64, limit price 500000000, " + + "expiry 1793000000, hotkey 5HK5tp6t2S59DywmHRWPBVJeJ86T61KjurYqeooqj8sREpeN, " + + "fee 8500000 to 5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY, " + + "relayer 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty, max slippage 7500000, " + + "chain 1, partial fills true, signer 5CD9UfFv3FLd9BRP8tK7BumpEYvu2y3KZMuhUnDAhuzPbdtC"; + +const ORDER_MESSAGE_BYTE_LENGTH = 381; + +/** ``-wrapped byte length — what actually reaches the device. */ +const WRAPPED_BYTE_LENGTH = 396; + +/** Exact bytes sent to the device's raw-sign instruction. */ +// prettier-ignore +const WRAPPED_PAYLOAD_HEX = + "0x3c42797465733e54414f2e636f6d206f726465722076313a204c696d6974206275792031303030303030303030206f6e207375626e65742036342c206c696d6974207072696365203530303030303030302c2065787069727920313739333030303030302c20686f746b65792035484b3574703674325335394479776d4852575042564a654a38365436314b6a75725971656f6f716a3873524570654e2c20666565203835303030303020746f2035474e4a715450794e71414e426b55564d4e314c50507278586e466f7557586f6532774e536d6d456f4c637478695a592c2072656c61796572203546486e655734367847586773356d5569766555347362547947427a6d73745573705a43393255686a4a4d36393474792c206d617820736c69707061676520373530303030302c20636861696e20312c207061727469616c2066696c6c7320747275652c207369676e657220354344395566467633464c643942525038744b3742756d70455976753279334b5a4d7568556e444168757a50626474433c2f42797465733e"; + +/** blake2_256 of the wrapped payload — the 32 bytes the device signs. */ +const WRAPPED_PAYLOAD_BLAKE2_256 = "0x3c3ea88b51457189388906eecb582d5ebf481b1af5b66b6b5771e4e84b6e5ed7"; + +/** + * Software half of the vector: reproducible in CI, no device needed. Holds a + * signature over EACH form so both semantics have a fixture. + */ +const SOFTWARE_VECTOR = { + seedHex: "0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + publicKeyHex: "0x79b5562e8fe654f94078b112e8a98ba7901f853ae695bed7e0e3910bad049664", + /** ed25519(wrapped payload) — the shape a software `signRaw` emits. */ + signatureOverBlobHex: + "0xc8d12ffcdc504a956b97fd67009de28c6541bf79dc33903092d9f1c279718c97" + + "91cf5bc69a3889c6699a5aab18170cdc2366f81daea5ecd31c64108385b1b60d", + /** ed25519(blake2_256(wrapped payload)) — the shape the device emits. */ + signatureOverHashHex: + "0x81edd47a3e02b7f52cc6a7db02e9a8c023c1f101526a7d5fe4be118aff36090c" + + "cf65f75136b31f6f64d8bcecc4e441b32322c37b4af51436a1e99096202b8608", +} as const; + +/** Signature captured from real hardware. */ +const DEVICE_VECTOR = { + label: "Nano S+ · Polkadot Generic v100.0.25", + derivationPath: "m/44'/354'/0'/0'/0'", + publicKeyHex: "0x76e2815d89ea8f87a7fc62c21b3ee2fb81d78ca28a24d33a974f47b20bb70a63", + signatureHex: + "0x91a37e50d01eeb407d9d1902374fef24dc287c1edb81474dbe19e46157bcc23d" + + "c5b7ba723ae7f8dd192004c150a8d0479a0ccb522c930dc8fcda7a15d6b45b08", + /** What it signed over — recorded, not assumed, so a future app version is a new entry. */ + signedOver: "blake2_256", +} as const; + +/** The order whose canonical rendering is `ORDER_MESSAGE`. */ +const VECTOR_ORDER: Order = { + signer: "5CD9UfFv3FLd9BRP8tK7BumpEYvu2y3KZMuhUnDAhuzPbdtC", + hotkey: "5HK5tp6t2S59DywmHRWPBVJeJ86T61KjurYqeooqj8sREpeN", + netuid: 64, + order_type: "LimitBuy", + amount: 1_000_000_000n, + limit_price: 500_000_000n, + expiry: 1_793_000_000n, + fee_rate: 8_500_000, + fee_recipient: "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY", + relayer: ["5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"], + max_slippage: 7_500_000, + chain_id: 1n, + partial_fills_enabled: true, +}; + +// ── Executable vector ──────────────────────────────────────────────────────── +// +// The hardware capture cannot be submitted as an order: its message names +// 5CD9UfFv… as the signer while the device holds 5Ekanz…, and the runtime verifies +// against `order.signer`. This vector closes that gap without a device — it is +// minted from SOFTWARE_VECTOR.seedHex (which we hold) over the digest, and since +// ed25519 is deterministic and the device's transformation is fixed, these are +// exactly the bytes a Ledger holding that seed would return. It does NOT attest to +// device behaviour; the capture above does that. +// +// chain 945 matches the pallet mock, because the same constants back the Rust half +// in `pallets/limit-orders/src/tests/ledger_vector.rs`. Nothing here touches chain +// state: this asserts that our production signing helper emits the device shape. + +/** SS58 of the account SOFTWARE_VECTOR.seedHex controls — the `signer` below. */ +const SOFTWARE_ADDRESS = "5EpHX5foDtnhZngj4GsKq5eKGpUvuMqbpUG48ZfCCCs7EzKR"; + +/** Well-known dev accounts, prefix 42: Bob (hotkey) and Charlie (fee recipient). */ +const BOB_SS58 = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"; +const CHARLIE_SS58 = "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"; + +const EXECUTABLE_MESSAGE = + "TAO.com order v1: Limit buy 1000 on subnet 1, limit price 1000000000, " + + `expiry 18446744073709551615, hotkey ${BOB_SS58}, fee 0 to ${CHARLIE_SS58}, ` + + `relayer none, max slippage none, chain 945, partial fills false, signer ${SOFTWARE_ADDRESS}`; + +/** blake2_256 of the wrapped EXECUTABLE_MESSAGE (350 bytes wrapped, so hashed). */ +const EXECUTABLE_DIGEST = "0xcd8f76e889c586d5efb73dd03433dc164b75fd727c52aaa4c8d07eb13dc98c12"; + +/** ed25519(seed, EXECUTABLE_DIGEST) — accepted by the runtime's `verify_readable`. */ +const EXECUTABLE_SIGNATURE = + "0xca9e4c33695072ffef1e3e1d0715979e3a4d8b553ee1ecc29e5da9ead5788910" + + "4d4bc7760c4f9a867e82b046271e47b554609489d666168b549d75b39b559b04"; + +// `new Uint8Array(...)` is load-bearing: `@polkadot/util`'s `isU8a` tests +// `constructor === Uint8Array` by identity, so an array from another realm makes +// `u8aWrapBytes` stringify its input instead of wrapping it — silently producing the +// wrong bytes. Re-wrapping puts it in this realm. +const bytes = (text: string) => new Uint8Array(stringToU8a(text)); +const wrapped = () => u8aWrapBytes(bytes(ORDER_MESSAGE)); +const digest = () => blake2AsU8a(wrapped(), 256); + +describeSuite({ + id: "DEV_SUB_LIMIT_ORDERS_LEDGER_VECTOR", + title: "limit-orders — Ledger raw-sign vector for the oversized clear-signing payload", + foundationMethods: "dev", + testCases: ({ it }) => { + it({ + id: "T01", + title: "the TS formatter reproduces the message the device displayed and signed", + test: () => { + const msg = formatOrderMessage(VECTOR_ORDER); + expect(msg).toBe(ORDER_MESSAGE); + expect(bytes(msg)).toHaveLength(ORDER_MESSAGE_BYTE_LENGTH); + for (let i = 0; i < msg.length; i++) { + const code = msg.charCodeAt(i); + expect( + code >= 0x20 && code <= 0x7e, + `char ${i} = 0x${code.toString(16)} is not printable ASCII, so the device would render hex` + ).toBe(true); + } + }, + }); + + it({ + id: "T02", + title: "the wrapped payload is over the threshold that switches the device to digest signing", + test: () => { + expect(wrapped()).toHaveLength(WRAPPED_BYTE_LENGTH); + expect(WRAPPED_BYTE_LENGTH).toBeGreaterThan(LEDGER_MAX_SIGN_SIZE); + expect(u8aToHex(wrapped())).toBe(WRAPPED_PAYLOAD_HEX); + // The utils wrap with u8aWrapBytes; the runtime concatenates literal + // tags. For printable ASCII both must produce identical bytes, or the + // device would render one thing and the chain verify another. + expect(u8aToHex(wrapped())).toBe(u8aToHex(bytes(`${ORDER_MESSAGE}`))); + }, + }); + + it({ + id: "T03", + title: "the wrapped payload hashes to the pinned digest", + test: () => { + expect(u8aToHex(digest())).toBe(WRAPPED_PAYLOAD_BLAKE2_256); + }, + }); + + it({ + id: "T04", + title: "the two signing forms are mutually unverifiable", + test: () => { + const publicKey = ed25519PairFromSeed(hexToU8a(SOFTWARE_VECTOR.seedHex)).publicKey; + expect(u8aToHex(publicKey)).toBe(SOFTWARE_VECTOR.publicKeyHex); + + const overBlob = hexToU8a(SOFTWARE_VECTOR.signatureOverBlobHex); + const overHash = hexToU8a(SOFTWARE_VECTOR.signatureOverHashHex); + + expect(ed25519Verify(wrapped(), overBlob, publicKey)).toBe(true); + expect(ed25519Verify(digest(), overHash, publicKey)).toBe(true); + // The whole hazard in two assertions: signer and verifier disagreeing + // about which form is in play is a hard rejection, never a soft fallback. + expect(ed25519Verify(digest(), overBlob, publicKey)).toBe(false); + expect(ed25519Verify(wrapped(), overHash, publicKey)).toBe(false); + }, + }); + + it({ + id: "T05", + title: `${DEVICE_VECTOR.label} signed over ${DEVICE_VECTOR.signedOver} and nothing else`, + test: () => { + const publicKey = hexToU8a(DEVICE_VECTOR.publicKeyHex); + const signature = hexToU8a(DEVICE_VECTOR.signatureHex); + + expect(ed25519Verify(digest(), signature, publicKey)).toBe(true); + + // Every alternative the capture's probe matrix ruled out. + const rejected: [string, Uint8Array][] = [ + ["the raw wrapped payload", wrapped()], + ["the unwrapped message", bytes(ORDER_MESSAGE)], + ["blake2_256 of the unwrapped message", blake2AsU8a(bytes(ORDER_MESSAGE), 256)], + ["blake2_512 of the wrapped payload", blake2AsU8a(wrapped(), 512)], + ["the ASCII hex of the digest", bytes(u8aToHex(digest()).slice(2))], + ]; + for (const [form, message] of rejected) { + expect(ed25519Verify(message, signature, publicKey), `must not verify over ${form}`).toBe( + false + ); + } + }, + }); + + it({ + id: "T06", + title: "buildReadableSignedOrder emits the device shape for the executable vector", + test: () => { + const signer = new Keyring({ type: "ed25519" }).addFromSeed( + hexToU8a(SOFTWARE_VECTOR.seedHex) + ); + expect(signer.address).toBe(SOFTWARE_ADDRESS); + + // `api` is unused by the readable builder (the payload is rendered from + // the params, not from chain metadata), so no chain state is needed. + const signed = buildReadableSignedOrder(null, { + signer, + hotkey: BOB_SS58, + netuid: 1, + orderType: "LimitBuy", + amount: 1_000n, + limitPrice: 1_000_000_000n, + expiry: 18_446_744_073_709_551_615n, + feeRate: 0, + feeRecipient: CHARLIE_SS58, + chainId: 945n, + }); + + // The message the order renders to, the digest it hashes to, and the + // signature the helper produced must all match the frozen vector — + // i.e. our signing path is byte-for-byte the one a Ledger takes. + expect(formatOrderMessage(signed.order.V1)).toBe(EXECUTABLE_MESSAGE); + const payload = u8aWrapBytes(bytes(EXECUTABLE_MESSAGE)); + expect(payload.length).toBeGreaterThan(LEDGER_MAX_SIGN_SIZE); + expect(u8aToHex(blake2AsU8a(payload, 256))).toBe(EXECUTABLE_DIGEST); + expect("Ed25519" in signed.signature).toBe(true); + expect((signed.signature as { Ed25519: string }).Ed25519).toBe(EXECUTABLE_SIGNATURE); + }, + }); + }, +}); From 48445d7ffda3136a7a8ebbbb8fcef3a6dbebf841 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Wed, 29 Jul 2026 16:57:40 -0400 Subject: [PATCH 13/58] Remove event reporting precompile suggestions --- .agents/skills/emv-maintainer/SKILL.md | 9 +- .../references/abi-versioning.md | 3 +- .../references/coverage-and-testing.md | 26 +- .../references/event-subscriptions.md | 249 ------------------ docs/guides/evm/precompile-design.mdx | 190 +++++++------ .../evm/precompiles/configuration-events.mdx | 98 ------- docs/guides/evm/precompiles/index.mdx | 9 +- docs/guides/evm/precompiles/meta.json | 5 - docs/guides/evm/precompiles/neuron-events.mdx | 50 ---- .../guides/evm/precompiles/staking-events.mdx | 56 ---- docs/guides/evm/precompiles/subnet-events.mdx | 80 ------ .../guides/evm/precompiles/weights-events.mdx | 47 ---- 12 files changed, 100 insertions(+), 722 deletions(-) delete mode 100644 .agents/skills/emv-maintainer/references/event-subscriptions.md delete mode 100644 docs/guides/evm/precompiles/configuration-events.mdx delete mode 100644 docs/guides/evm/precompiles/neuron-events.mdx delete mode 100644 docs/guides/evm/precompiles/staking-events.mdx delete mode 100644 docs/guides/evm/precompiles/subnet-events.mdx delete mode 100644 docs/guides/evm/precompiles/weights-events.mdx diff --git a/.agents/skills/emv-maintainer/SKILL.md b/.agents/skills/emv-maintainer/SKILL.md index f59e2a83d8..931b3ac8e1 100644 --- a/.agents/skills/emv-maintainer/SKILL.md +++ b/.agents/skills/emv-maintainer/SKILL.md @@ -5,15 +5,13 @@ description: Maintain the EVM precompiles in backwards compatible way with API v # EVM Precompile Maintainer -You are the maintainer of EVM precompiles. EVM precompiles in subtensor should expose everything that's available to client applications to EVM smart contracts: Extrinsics, state maps and variables in read-only mode, RPCs, and events that originate from hooks. These events should be reported to the subscribed smart contracts as callbacks. Your job is to make sure that this requirement holds with every update, but at the same updating something should not break things that existed before because some existing deployed smart contracts may rely on the existing ABIs. Read the notes below and then execute steps. +You are the maintainer of EVM precompiles. EVM precompiles in subtensor should expose the deterministic functionality available to client applications to EVM smart contracts: extrinsics, state maps and variables through typed read-only views, and runtime APIs/RPC results. Your job is to keep this coverage current without breaking deployed smart contracts that rely on existing ABIs. Read the notes below and then execute steps. ## Reference routing - Before classifying or implementing any precompile change, including an additive function, runtime adaptation, bug fix, deprecation, or disablement, read [ABI versioning](references/abi-versioning.md). -- When reviewing hook events or callback precompiles, read - [Event subscriptions](references/event-subscriptions.md). - Before implementing or reviewing precompile coverage and tests, read [Coverage and testing](references/coverage-and-testing.md). @@ -56,8 +54,6 @@ For each affected released function: - Represent Substrate account IDs in EVM space as 32-byte public keys. - Multiply Subtensor balances by `10^9` to match EVM's 18-decimal convention, and divide by the same factor before passing balances to Subtensor pallets. -- Follow [Event subscriptions](references/event-subscriptions.md) for callback - interfaces, charging, bounds, and delivery. ## Step 1 - Review current precompiles vs. subtensor functionality @@ -72,7 +68,6 @@ For each affected released function: - timestamp - swap - All runtime API RPCs for the subtensor pallet should be exposed as a callable precompile function with similar interface -- All events emitted from hooks (such as on_initialize or on_finalize) should be exposed as callbacks. Use [Coverage and testing](references/coverage-and-testing.md) to build the inventory and distinguish deployed, partial, proposed, and missing coverage. @@ -82,7 +77,7 @@ inventory and distinguish deployed, partial, proposed, and missing coverage. Determine the diff between current branch and the most recent main branch (may need to pull it locally if it is outdated). See how this diff affects EVM precompiles: - Does it remove or change any functions that precompiles rely on? Does it change function signatures or underlying functionality? -- Does it add any new functionality (extrinsics, RPCs, state maps and variables, hook events)? +- Does it add any new functionality (extrinsics, RPCs, state maps and variables)? ## Step 3 - Handle changed functions diff --git a/.agents/skills/emv-maintainer/references/abi-versioning.md b/.agents/skills/emv-maintainer/references/abi-versioning.md index 54037f4b1a..c4dafd1c0b 100644 --- a/.agents/skills/emv-maintainer/references/abi-versioning.md +++ b/.agents/skills/emv-maintainer/references/abi-versioning.md @@ -51,8 +51,7 @@ Preserve all observable properties of every released call: - state transitions and atomicity; - success-versus-revert behavior and documented error payloads; - bounded-input and complexity guarantees; -- callback selectors, event-mask assignments, filters, charging, - auto-unsubscription, sequencing, and delivery guarantees. +- lifecycle-status selectors and their documented availability guarantees. Return types do not contribute to a Solidity selector, but changing them under an existing selector still breaks old callers because they decode the returned diff --git a/.agents/skills/emv-maintainer/references/coverage-and-testing.md b/.agents/skills/emv-maintainer/references/coverage-and-testing.md index 1f1122fc64..902752a872 100644 --- a/.agents/skills/emv-maintainer/references/coverage-and-testing.md +++ b/.agents/skills/emv-maintainer/references/coverage-and-testing.md @@ -7,7 +7,6 @@ - [Cover extrinsics](#cover-extrinsics) - [Cover state with typed views](#cover-state-with-typed-views) - [Cover runtime APIs and public RPCs](#cover-runtime-apis-and-public-rpcs) -- [Cover events](#cover-events) - [Add regression tests first](#add-regression-tests-first) - [Test observable behavior](#test-observable-behavior) - [Validate ABIs and routing](#validate-abis-and-routing) @@ -25,14 +24,12 @@ For each in-scope pallet, inspect: - every dispatchable extrinsic; - every public state map and value; - every publicly facing runtime API and RPC; -- every emitted event, including events originating in hooks and scheduled - work; and - changes to types, guards, authorization, units, and error behavior used by existing precompiles. -Coverage means that Solidity contracts receive a typed equivalent of the -authorized client-facing functionality. It does not mean exposing raw pallet -storage, SCALE bytes, or Rust types. +Precompile coverage means that Solidity contracts receive a typed equivalent +of the authorized deterministic client-facing functionality. It does not mean +exposing raw pallet storage, SCALE bytes, or Rust types. Distinguish deployed coverage from proposed coverage. Do not describe a documented proposal, unassigned address, or Rust stub as callable. @@ -41,9 +38,9 @@ documented proposal, unassigned address, or Rust stub as callable. Create or update a working matrix with one row per source item: -| Source | Kind | Public functionality | Precompile domain | Function or callback | Status | Evidence | +| Source | Kind | Public functionality | Precompile domain | Function | Status | Evidence | |---|---|---|---|---|---|---| -| Pallet and item | Extrinsic, state, runtime API, RPC, or event | Meaning exposed to clients | Existing or proposed address/domain | Canonical signature or callback | Covered, partial, missing, or excluded | Rust, Solidity, ABI, and test paths | +| Pallet and item | Extrinsic, state, runtime API, or RPC | Meaning exposed to clients | Existing or proposed address/domain | Canonical signature | Covered, partial, missing, or excluded | Rust, Solidity, ABI, and test paths | For every partial, missing, or excluded row, state the exact reason. Do not equate a similarly named function with coverage; compare parameters, returned @@ -124,18 +121,6 @@ runtime. When a public RPC composes runtime state, implement the deterministic runtime-side result and document any transport-only behavior that has no EVM equivalent. -## Cover events - -Inspect event enums and active emission sites. Cover relevant hook-origin -events with subscription callbacks so contracts are not limited to their own -transaction receipts. - -Use [Event subscriptions](event-subscriptions.md) for domain grouping, -filtering, callback ABI, charging, queue bounds, and delivery semantics. - -Do not mark an enum-only placeholder as emitted coverage. Do not expose a raw -runtime event or an unbounded vector callback. - ## Add regression tests first For a bug fix, add a regression unit test that fails for the reported behavior @@ -214,7 +199,6 @@ Test: - the maximum accepted collection size; - rejection just beyond the bound; - proof-size-sensitive database access where relevant; -- callback gas and per-block delivery limits for subscriptions; and - failure paths that could otherwise perform unpaid work. Do not accept a bounded input if processing it can trigger an unbounded runtime diff --git a/.agents/skills/emv-maintainer/references/event-subscriptions.md b/.agents/skills/emv-maintainer/references/event-subscriptions.md deleted file mode 100644 index 47b4bee0e0..0000000000 --- a/.agents/skills/emv-maintainer/references/event-subscriptions.md +++ /dev/null @@ -1,249 +0,0 @@ -# Event subscription precompiles - -## Contents - -- [Use typed domain precompiles](#use-typed-domain-precompiles) -- [Inventory reportable events](#inventory-reportable-events) -- [Use a common subscription interface](#use-a-common-subscription-interface) -- [Fund callback delivery](#fund-callback-delivery) -- [Keep event production bounded](#keep-event-production-bounded) -- [Define stable callback ABIs](#define-stable-callback-abis) -- [Normalize variable-length events](#normalize-variable-length-events) -- [Specify delivery semantics](#specify-delivery-semantics) -- [Protect execution](#protect-execution) -- [Test subscription behavior](#test-subscription-behavior) - -## Use typed domain precompiles - -Expose events from `SubtensorModule` and `AdminUtils` as typed Solidity -callbacks. Do not expose raw `RuntimeEvent`, pallet enum discriminants, or -SCALE-encoded payloads. - -Group callbacks by meaning under a small number of independently addressed -precompiles. Use the current proposed domains as the design baseline: - -- staking and economic flows; -- neurons, identities, relationships, and key rotation; -- weights and commit-reveal; -- subnet lifecycle, epochs, emissions, leases, and voting-power tracking; -- runtime and subnet configuration. - -Consult the corresponding pages under -`docs/guides/evm/precompiles/*-events.mdx` for the current proposed inventory. -Treat names, signatures, mask bits, and addresses as provisional until -released. After release, apply the ABI rules in -[ABI versioning](abi-versioning.md). - -Create another address only when an event family has a genuinely separate -domain and lifecycle. Do not create one precompile per pallet event. - -## Inventory reportable events - -Inspect both event enum definitions and every emission site. An enum variant -without an active emission site is not a live callback. Record it as a coverage -gap or future possibility, not as currently delivered behavior. - -For each emitted event: - -1. Record the source pallet, variant, fields, and emission sites. -2. Identify whether it originates from an extrinsic, scheduled operation, or - runtime hook. -3. Assign it to a meaningful event-precompile domain. -4. Define stable EVM field types and conversions. -5. Determine whether the source payload is bounded. -6. Define a recovery view when callbacks alone are not authoritative. -7. Add an event-mask bit without changing any released assignment. - -Prioritize hook-origin events because an interested contract cannot obtain them -from its own transaction receipt. Use the same subscription model for relevant -transaction and scheduled-operation events when this provides coherent domain -coverage. - -When a new source event starts being emitted, add a new typed callback and mask -bit. Do not change an existing callback to absorb different semantics. - -## Use a common subscription interface - -Use the same control shape for every event domain unless a documented reason -requires an additive version: - -```solidity -struct EventFilter { - uint256 eventMask; - uint16 netuid; - bytes32 accountId; - bool matchAnyNetuid; - bool matchAnyAccount; -} - -struct Subscription { - bool active; - EventFilter filter; - uint64 callbackGasLimit; - uint64 nextSequence; -} - -function subscribe( - EventFilter calldata filter, - uint64 callbackGasLimit -) external; - -function unsubscribe() external; - -function getSubscription( - address subscriber -) external view returns (Subscription memory); - -function minimumCallbackBalance( - uint64 callbackGasLimit -) external view returns (uint256); -``` - -Always make the caller the subscriber. Do not allow one address to subscribe or -unsubscribe another address. - -Store at most one fixed-size subscription per contract and event domain. Use a -fixed event mask plus at most one netuid and one account filter. Do not store or -iterate an arbitrary list of filters. - -Validate the mask, callback gas limit, filter flags, and minimum balance before -creating or replacing a subscription. Make subscription replacement atomic. - -## Fund callback delivery - -Charge callback attempts to the subscribing contract's own TAO balance. Require -enough balance at subscription time to fund the documented minimum number of -attempts at the selected callback gas limit. - -Charge a reverting callback for the work it consumed. Never let callback -failure revert the runtime operation that produced the source event. - -Automatically remove a subscription when its balance cannot fund the next -attempt. Define charging, rounding, and TAO-to-EVM unit conversion precisely. -Do not provide free delivery paths that allow subscription spam. - -Keep the minimum-balance calculation available as a typed view so a contract -can determine whether a subscription is fundable before submitting it. - -## Keep event production bounded - -Do not synchronously iterate all subscribers when an event is emitted. Append a -fixed-size typed report to a bounded queue in O(1), then process a bounded -amount of delivery work in later blocks. - -Advance delivery through bounded cursors. Cap: - -- queue capacity; -- work per block; -- callback gas; -- report size; -- subscription size; and -- the number of delivery attempts performed by one bounded work item. - -Do not copy or ABI-encode an unbounded vector while producing a report. If a -source event is variable-length, normalize it incrementally as described below. - -Define what happens when the queue reaches capacity. Never permit unbounded -runtime storage or memory growth. - -## Define stable callback ABIs - -Give every event a stable, event-specific receiver selector. Include -`uint64 sequence` and `uint64 sourceBlock` in every callback before the -event-specific fields. - -Use stable EVM representations: - -- Substrate account IDs and hashes: `bytes32`; -- EVM accounts: `address`; -- netuids and UIDs: `uint16` when the runtime domain fits; -- TAO and Alpha amounts: 18-decimal `uint256` values using the documented - `10^9` conversion factor; -- fixed-point values: an explicitly documented integer representation. - -Choose bounded representations for strings, identities, and other structured -values before release. Do not expose a Rust or SCALE representation as the ABI. - -After release: - -- reserve the precompile address and control selectors; -- reserve every event-mask bit; -- preserve callback names, parameters, order, types, and meaning; -- preserve filter, charging, sequencing, and delivery guarantees; and -- add a versioned callback when richer data is required. - -Do not add speculative fields to a callback merely because a future runtime -might produce them. Add another selector when the semantics become concrete. - -## Normalize variable-length events - -Convert every variable-length source event into bounded callbacks. Emit a -summary when useful, followed by one item callback per entry. Give related -callbacks the same source sequence and include item index and item count. - -For UID-indexed emission arrays, interpret the array index as the UID and -deliver one `(uid, amount)` callback per entry. For example, `[10, 20, 30]` -represents UIDs `0`, `1`, and `2`; do not treat an entry as an arbitrary UID -value. - -Apply the same approach to children lists, weight hashes, completed-netuid -batches, and similar collections. Use a stable typed representation for -per-item failures instead of SCALE-encoded `DispatchError`. - -Produce normalized items incrementally at the source. Do not first copy the -complete vector into a queued report. - -## Specify delivery semantics - -Treat callbacks as asynchronous, best-effort notifications. Do not promise that -a callback executes in the source event's block. - -Use a monotonically increasing source sequence and source block so receivers -can order reports and detect gaps. Define whether normalized items share one -source sequence and how item indices identify completeness. - -If bounded queue overwrite or another allowed failure drops a report, make the -gap observable through sequencing. Require authoritative recovery through the -corresponding typed view where contract logic needs exact current state. - -Document ordering across event domains only if the implementation guarantees -it. Require receivers to make callbacks idempotent and tolerate retries, -reordering outside documented guarantees, and sequence gaps. - -## Protect execution - -Apply reentrancy protection around delivery. Do not allow a callback to -recursively create unbounded callback work. - -Keep the source runtime operation independent of callback execution. Bound -callback gas and isolate callback failure. Validate that subscriber-controlled -code cannot stall block processing, retain an unpaid subscription, or make -another subscriber's delivery unbounded. - -Account for database reads, writes, queue operations, EVM execution, and failed -attempts. Use saturating arithmetic where appropriate and reject values that -cannot be converted safely. - -## Test subscription behavior - -Test at least: - -- self-subscription and self-unsubscription; -- attempts to manage another address; -- invalid masks, filters, and gas limits; -- insufficient initial balance; -- successful charging and delivery; -- reverting and out-of-gas callbacks; -- automatic unsubscription when payment fails; -- event filtering by mask, netuid, and account; -- monotonic sequencing and source-block reporting; -- queue capacity and observable gaps; -- bounded per-block work with many subscribers; -- reentrancy and recursive-work resistance; -- one-item normalization and item ordering; -- unit and account conversions; -- released callback selectors and event-mask assignments; and -- additive introduction of a new callback without changing old callbacks. - -Use [Coverage and testing](coverage-and-testing.md) for the general precompile -regression and ABI-diff requirements. diff --git a/docs/guides/evm/precompile-design.mdx b/docs/guides/evm/precompile-design.mdx index a47c528866..66f59a8439 100644 --- a/docs/guides/evm/precompile-design.mdx +++ b/docs/guides/evm/precompile-design.mdx @@ -1,6 +1,6 @@ --- title: Precompile design and lifecycle -description: How Bittensor precompiles preserve deployed-contract compatibility, evolve function by function, and communicate deprecation or temporary disablement. +description: How Bittensor precompiles preserve compatibility and how projects relay selected Substrate events to EVM contracts. --- Bittensor precompiles are fixed-address EVM contracts implemented by the @@ -139,107 +139,93 @@ inherently brittle. The intended migration is: Whether this 1:1 coverage should extend beyond the authorized pallets remains an open design question. -## Subscription-based event reporting - -Some Subtensor events are produced by runtime hooks rather than by the EVM -transaction that is interested in them. A transaction receipt therefore cannot -provide complete event coverage. Proposed event precompiles let a contract -subscribe itself and receive those events later as typed EVM callbacks. - -Event reporting is divided into dedicated domain precompiles for -[staking](/docs/guides/evm/precompiles/staking-events), -[neurons and keys](/docs/guides/evm/precompiles/neuron-events), -[weights](/docs/guides/evm/precompiles/weights-events), -[subnet lifecycle](/docs/guides/evm/precompiles/subnet-events), and -[runtime configuration](/docs/guides/evm/precompiles/configuration-events). -Each domain will have its own address. These precompiles report typed events -originating from `SubtensorModule` and `AdminUtils`; they do not expose raw -`RuntimeEvent` values or SCALE-encoded payloads. - -The callback inventories cover source variants with active emission sites in -the current runtime. An enum-only placeholder is not presented as a live -callback. If such a variant starts being emitted, its typed callback must be -added without changing the existing subscription or receiver selectors. - -### Subscription control - -Each event precompile should expose the same control shape: - -```solidity -struct EventFilter { - uint256 eventMask; - uint16 netuid; - bytes32 accountId; - bool matchAnyNetuid; - bool matchAnyAccount; -} - -struct Subscription { - bool active; - EventFilter filter; - uint64 callbackGasLimit; - uint64 nextSequence; -} - -function subscribe( - EventFilter calldata filter, - uint64 callbackGasLimit -) external; - -function unsubscribe() external; - -function getSubscription( - address subscriber -) external view returns (Subscription memory); - -function minimumCallbackBalance( - uint64 callbackGasLimit -) external view returns (uint256); -``` - -The caller is always the subscriber: a contract cannot subscribe or unsubscribe -another address. One fixed-size subscription per contract and domain keeps -lookup and update costs bounded. The event mask and optional single-netuid and -single-account filters let a subscriber narrow delivery without storing or -iterating an arbitrary filter list. - -`subscribe` succeeds only when the contract's own TAO balance can fund the -documented minimum number of callback attempts at its selected gas limit. Each -attempt is charged to that same balance. If the balance can no longer pay for -an attempt, the subscription is automatically removed. A reverting callback is -charged for the work it consumed and cannot revert the runtime operation that -produced the event. - -### Typed callbacks and delivery - -Every report has a stable, event-specific callback selector. Substrate account -IDs are represented as `bytes32`, and TAO and Alpha balances are multiplied by -`10^9` for EVM's 18-decimal convention. New source events add callback -selectors; released callbacks are never changed, removed, or reused. - -Callbacks are asynchronous notifications, not part of the transaction or hook -that produced the source event. Every callback includes a monotonically -increasing sequence and source block number so receivers can order deliveries -and detect a gap. A receiver must make its callback idempotent and must not -assume delivery in the source event's block. - -The runtime must not iterate every subscriber while emitting an event. Instead, -emission appends one fixed-size typed report to a bounded queue in O(1), and a -bounded amount of later block work advances a subscriber cursor one delivery at -a time. Callback gas is capped, delivery is protected against reentrancy, and a -callback cannot recursively create more callback work. - -Variable-length pallet events are normalized into bounded item callbacks. For -example, miner emissions are reported one UID at a time and a batch of weight -hashes is reported one hash at a time, with the same source sequence plus item -index and item count. The adapter must produce those items incrementally at the -source rather than copy or ABI-encode an unbounded vector. - -The queue has a fixed capacity so event reporting cannot grow runtime memory -without bound. If delivery falls behind far enough to overwrite an undelivered -report, the next successful callback exposes the sequence gap. Event callbacks -are therefore best-effort integration signals; contracts that require -authoritative recovery must use the corresponding typed view. +## Project-scoped event relays + +Substrate events are already recorded in chain data. Reproducing the complete +event stream through protocol-level EVM callbacks would add another on-chain +copy together with subscription storage, delivery queues, and callback +execution. It would also force the runtime to support broad event delivery even +when an application needs only a small, highly filtered set of signals. + +Bittensor therefore does not propose event-reporting precompiles. A project +that needs proactive notifications in its EVM contracts should run an +off-chain relay tailored to that project's use cases. The relay watches +finalized Substrate events, performs application-specific filtering, +aggregation, and enrichment off chain, and submits only the reports that the +project's contracts can act on. + +Typed precompile views remain the authoritative way for contracts to read +current runtime state. Relayed reports are notifications under the trust and +availability model chosen by the project. + +### Relay flow + +A typical relay operates as follows: + +1. Relay nodes read finalized blocks and events from Substrate RPC endpoints or + an indexer. +2. Each node applies the project's filters and derives a canonical typed + report. +3. A configured signer quorum attests to the report. +4. A relayer submits the report and its authorization proof in an ordinary EVM + transaction. +5. The reporting contract verifies the report, rejects duplicates, and either + emits a typed EVM log, invokes a bounded set of subscribed receivers, or + records data for receivers to pull. + +A report should identify at least the source chain, finalized block hash and +number, source event position or another unique event identifier, schema +version, payload, and relay sequence or nonce. The signed message must be +domain-separated by chain ID, reporting-contract address, and schema version so +that it cannot be replayed on another chain, contract, or report type. + +Filtering belongs primarily in the relay. A subnet application might publish +only completed tempo summaries, material configuration changes, or aggregate +emission results instead of reproducing every underlying pallet event. + +### Subscription-capable reporting contracts + +A project can deploy a reporting contract that lets users or other contracts +register subscriptions and lets authorized relayers submit observed reports. +A subscription can select typed report kinds, project-specific filters, a +receiver, and a callback gas limit. The contract should make its payment, +retry, ordering, and removal rules explicit. + +Neither report submission nor callback delivery should iterate an unbounded +subscriber set. Limit each transaction to a fixed-size batch, let relayers +target matching subscribers explicitly, or let subscribers pull verified +reports. Catch callback failures so one receiver cannot revert delivery to +others, and require receiver callbacks to be idempotent. + +Every successful relay submission has an EVM transaction and receipt. Projects +must decide whether relayers fund these transactions, subscribers prepay for +delivery, or another project account subsidizes them. + +### Relayer trust and security + +A single relay signer is the simplest design but makes that signer a trusted +oracle. Projects that need stronger guarantees can use an independently +operated committee with an explicit `M-of-N` multisignature, a threshold +signature scheme, or another auditable quorum mechanism. The reporting +contract must define signer enrollment, quorum, key rotation, emergency +revocation, and version upgrades. + +Relay implementations should also: + +- wait for the documented source-chain finality condition; +- use deterministic report encoding and reject duplicate event identifiers; +- expose sequences or source positions so receivers can detect gaps; +- tolerate delayed, reordered, and repeated submissions; +- bound report size, callback gas, batch size, and retained on-chain history; +- separate observation from submission so any permitted party can submit a + valid quorum-authorized report; and +- provide a reconciliation path through typed precompile views when a report is + missing or disputed. + +Contracts must not treat relayed events as consensus-authenticated merely +because they describe on-chain activity. Their integrity depends on the relay +committee and verification rules, while their availability depends on relay +operators continuing to observe and submit reports. ## Function lifecycle diff --git a/docs/guides/evm/precompiles/configuration-events.mdx b/docs/guides/evm/precompiles/configuration-events.mdx deleted file mode 100644 index b3d1085b00..0000000000 --- a/docs/guides/evm/precompiles/configuration-events.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Configuration events -description: Proposed subscription precompile for typed Subtensor and AdminUtils configuration callbacks. ---- - -| Property | Value | -|---|---| -| Proposed implementation | `ConfigurationEventsPrecompile` | -| Proposed Solidity interface | `IConfigurationEvents` | -| Callback receiver interface | `IConfigurationEventsReceiver` | -| Address | Dedicated address not assigned | -| Status | Proposed | - -This precompile reports runtime and subnet configuration changes emitted by -`SubtensorModule` and `AdminUtils`. It normalizes the two pallets into -meaningful typed callbacks while retaining the source pallet in callback -metadata when both pallets can describe the same setting. - -## Proposed Subtensor callbacks - -| Receiver function | Subtensor source event | -|---|---| -| `onActivityCutoffChanged(...)` | `ActivityCutoffSet` | -| `onActivityCutoffFactorChanged(...)` | `ActivityCutoffFactorMilliSet` | -| `onAdjustmentAlphaChanged(...)` | `AdjustmentAlphaSet` | -| `onAdjustmentIntervalChanged(...)` | `AdjustmentIntervalSet` | -| `onAdminFreezeWindowChanged(...)` | `AdminFreezeWindowSet` | -| `onBondsMovingAverageChanged(...)` | `BondsMovingAverageSet` | -| `onBondsPenaltyChanged(...)` | `BondsPenaltySet` | -| `onBondsResetOnSetChanged(...)` | `BondsResetOnSet` | -| `onColdkeySwapAnnouncementDelayChanged(...)` | `ColdkeySwapAnnouncementDelaySet` | -| `onColdkeySwapReannouncementDelayChanged(...)` | `ColdkeySwapReannouncementDelaySet` | -| `onDifficultyChanged(...)` | `DifficultySet` | -| `onDissolutionScheduleDurationChanged(...)` | `DissolveNetworkScheduleDurationSet` | -| `onImmunityPeriodChanged(...)` | `ImmunityPeriodSet` | -| `onKappaChanged(...)` | `KappaSet` | -| `onMaxAllowedUidsChanged(...)` | `MaxAllowedUidsSet` | -| `onMaxAllowedValidatorsChanged(...)` | `MaxAllowedValidatorsSet` | -| `onMaxBurnChanged(...)` | `MaxBurnSet` | -| `onMaxChildKeyTakeChanged(...)` | `MaxChildKeyTakeSet` | -| `onMaxDelegateTakeChanged(...)` | `MaxDelegateTakeSet` | -| `onMaxDifficultyChanged(...)` | `MaxDifficultySet` | -| `onMaxEpochsPerBlockChanged(...)` | `MaxEpochsPerBlockSet` | -| `onMaxRegistrationsPerBlockChanged(...)` | `MaxRegistrationsPerBlockSet` | -| `onMinAllowedUidsChanged(...)` | `MinAllowedUidsSet` | -| `onMinAllowedWeightChanged(...)` | `MinAllowedWeightSet` | -| `onMinBurnChanged(...)` | `MinBurnSet` | -| `onMinChildKeyTakeChanged(...)` | `MinChildKeyTakeSet` | -| `onMinChildKeyTakeForSubnetChanged(...)` | `MinChildKeyTakePerSubnetSet` | -| `onMinDelegateTakeChanged(...)` | `MinDelegateTakeSet` | -| `onMinDifficultyChanged(...)` | `MinDifficultySet` | -| `onMinNonImmuneUidsChanged(...)` | `MinNonImmuneUidsSet` | -| `onNetworkImmunityPeriodChanged(...)` | `NetworkImmunityPeriodSet` | -| `onNetworkLockCostReductionIntervalChanged(...)` | `NetworkLockCostReductionIntervalSet` | -| `onNetworkMinimumLockCostChanged(...)` | `NetworkMinLockCostSet` | -| `onNetworkRateLimitChanged(...)` | `NetworkRateLimitSet` | -| `onOwnerHyperparameterRateLimitChanged(...)` | `OwnerHyperparamRateLimitSet` | -| `onPowRegistrationAllowedChanged(...)` | `PowRegistrationAllowed` | -| `onRaoRecycledForRegistrationChanged(...)` | `RAORecycledForRegistrationSet` | -| `onRegistrationAllowedChanged(...)` | `RegistrationAllowed` | -| `onRegistrationsPerIntervalChanged(...)` | `RegistrationPerIntervalSet` | -| `onScalingLawPowerChanged(...)` | `ScalingLawPowerSet` | -| `onServingRateLimitChanged(...)` | `ServingRateLimitSet` | -| `onStakeThresholdChanged(...)` | `StakeThresholdSet` | -| `onStartCallDelayChanged(...)` | `StartCallDelaySet` | -| `onSubnetLimitChanged(...)` | `SubnetLimitSet` | -| `onSubnetOwnerCutChanged(...)` | `SubnetOwnerCutSet` | -| `onTempoChanged(...)` | `TempoSet` | -| `onTransferEnabledChanged(...)` | `TransferToggle` | -| `onChildKeyTakeRateLimitChanged(...)` | `TxChildKeyTakeRateLimitSet` | -| `onDelegateTakeRateLimitChanged(...)` | `TxDelegateTakeRateLimitSet` | -| `onTransactionRateLimitChanged(...)` | `TxRateLimitSet` | -| `onValidatorPruneLengthChanged(...)` | `ValidatorPruneLenSet` | -| `onWeightsRateLimitChanged(...)` | `WeightsSetRateLimitSet` | -| `onWeightsVersionKeyChanged(...)` | `WeightsVersionKeySet` | - -## Proposed AdminUtils callbacks - -| Receiver function | AdminUtils source event | -|---|---| -| `onPrecompileAvailabilityChanged(...)` | `PrecompileUpdated` | -| `onYuma3EnabledChanged(...)` | `Yuma3EnableToggled` | -| `onBondsResetEnabledChanged(...)` | `BondsResetToggled` | -| `onBurnHalfLifeChanged(...)` | `BurnHalfLifeSet` | -| `onBurnIncreaseMultiplierChanged(...)` | `BurnIncreaseMultSet` | -| `onSubnetEmissionEnabledChanged(...)` | `SubnetEmissionEnabledSet` | -| `onCollateralLockShareChanged(...)` | `CollateralLockShareSet` | -| `onCollateralDrainRatioChanged(...)` | `CollateralDrainRatioSet` | - -Every callback begins with `uint64 sequence`, `uint64 sourceBlock`, and a typed -source-pallet value, followed by the setting's typed fields. Account IDs use -`bytes32`, netuids use `uint16`, and fixed-point values use a documented stable -EVM representation. - -Subscription behavior is defined in -[Subscription-based event reporting](/docs/guides/evm/precompile-design#subscription-based-event-reporting). -The names and signatures are provisional and do not reserve selectors. - diff --git a/docs/guides/evm/precompiles/index.mdx b/docs/guides/evm/precompiles/index.mdx index 817a3c5d18..84da100486 100644 --- a/docs/guides/evm/precompiles/index.mdx +++ b/docs/guides/evm/precompiles/index.mdx @@ -53,13 +53,12 @@ or intentionally non-callable EVM treatment. | [`DrandPrecompile`](/docs/guides/evm/precompiles/drand) | `IDrand` | Address not assigned
Proposed | | [`TimestampPrecompile`](/docs/guides/evm/precompiles/timestamp) | `ITimestamp` | Address not assigned
Proposed | | [`RuntimeConfigurationPrecompile`](/docs/guides/evm/precompiles/runtime-configuration) | `IRuntimeConfiguration` | Address not assigned
Proposed | -| [`StakingEventsPrecompile`](/docs/guides/evm/precompiles/staking-events) | `IStakingEvents` | Dedicated address not assigned
Proposed | -| [`NeuronEventsPrecompile`](/docs/guides/evm/precompiles/neuron-events) | `INeuronEvents` | Dedicated address not assigned
Proposed | -| [`WeightsEventsPrecompile`](/docs/guides/evm/precompiles/weights-events) | `IWeightsEvents` | Dedicated address not assigned
Proposed | -| [`SubnetEventsPrecompile`](/docs/guides/evm/precompiles/subnet-events) | `ISubnetEvents` | Dedicated address not assigned
Proposed | -| [`ConfigurationEventsPrecompile`](/docs/guides/evm/precompiles/configuration-events) | `IConfigurationEvents` | Dedicated address not assigned
Proposed | | [`PrecompileRegistry`](/docs/guides/evm/precompiles/registry) | `IPrecompileRegistry` | Address not assigned
Proposed | +Projects that need proactive event delivery should use +[project-scoped event relays](/docs/guides/evm/precompile-design#project-scoped-event-relays) +instead of protocol-level event-reporting precompiles. + Released addresses and selectors remain reserved permanently. The compatibility and lifecycle rules are documented in [Precompile design and lifecycle](/docs/guides/evm/precompile-design). diff --git a/docs/guides/evm/precompiles/meta.json b/docs/guides/evm/precompiles/meta.json index 9cb554aaf6..423e4fb969 100644 --- a/docs/guides/evm/precompiles/meta.json +++ b/docs/guides/evm/precompiles/meta.json @@ -23,11 +23,6 @@ "drand", "timestamp", "runtime-configuration", - "staking-events", - "neuron-events", - "weights-events", - "subnet-events", - "configuration-events", "registry" ] } diff --git a/docs/guides/evm/precompiles/neuron-events.mdx b/docs/guides/evm/precompiles/neuron-events.mdx deleted file mode 100644 index a66dc25a87..0000000000 --- a/docs/guides/evm/precompiles/neuron-events.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Neuron and key events -description: Proposed subscription precompile for typed Subtensor neuron, identity, relationship, and key-rotation callbacks. ---- - -| Property | Value | -|---|---| -| Proposed implementation | `NeuronEventsPrecompile` | -| Proposed Solidity interface | `INeuronEvents` | -| Callback receiver interface | `INeuronEventsReceiver` | -| Address | Dedicated address not assigned | -| Status | Proposed | - -This precompile reports neuron registration and serving changes, hotkey and -coldkey rotations, identities, EVM-key associations, and child relationships -emitted by `SubtensorModule`. - -## Proposed callbacks - -| Receiver function | Subtensor source event | -|---|---| -| `onNeuronRegistered(...)` | `NeuronRegistered` | -| `onAxonServed(...)` | `AxonServed` | -| `onPrometheusServed(...)` | `PrometheusServed` | -| `onHotkeySwapped(...)` | `HotkeySwapped` | -| `onHotkeySwappedOnSubnet(...)` | `HotkeySwappedOnSubnet` | -| `onColdkeySwapAnnounced(...)` | `ColdkeySwapAnnounced` | -| `onColdkeySwapReset(...)` | `ColdkeySwapReset` | -| `onColdkeySwapped(...)` | `ColdkeySwapped` | -| `onColdkeySwapDisputed(...)` | `ColdkeySwapDisputed` | -| `onColdkeySwapCleared(...)` | `ColdkeySwapCleared` | -| `onChildrenScheduled(...)` | `SetChildrenScheduled` | -| `onChildScheduled(...)` | One item from `SetChildrenScheduled` | -| `onChildrenSet(...)` | `SetChildren` | -| `onChildSet(...)` | One item from `SetChildren` | -| `onChainIdentitySet(...)` | `ChainIdentitySet` | -| `onEvmKeyAssociated(...)` | `EvmKeyAssociated` | - -The schedule and children summary callbacks carry the hotkey, netuid, and item -count. Their item callbacks carry one child and proportion at a time, using a -shared source sequence, item index, and item count; no callback contains an -unbounded array. - -All callbacks also carry the source block. Account IDs and hashes use -`bytes32`, and the associated EVM key uses `address`. - -Subscription behavior is defined in -[Subscription-based event reporting](/docs/guides/evm/precompile-design#subscription-based-event-reporting). -The names and signatures are provisional and do not reserve selectors. - diff --git a/docs/guides/evm/precompiles/staking-events.mdx b/docs/guides/evm/precompiles/staking-events.mdx deleted file mode 100644 index 209670e080..0000000000 --- a/docs/guides/evm/precompiles/staking-events.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Staking events -description: Proposed subscription precompile for typed Subtensor staking, delegation, Alpha-flow, lock, and collateral callbacks. ---- - -| Property | Value | -|---|---| -| Proposed implementation | `StakingEventsPrecompile` | -| Proposed Solidity interface | `IStakingEvents` | -| Callback receiver interface | `IStakingEventsReceiver` | -| Address | Dedicated address not assigned | -| Status | Proposed | - -This precompile reports the economic and staking events emitted by -`SubtensorModule`. A contract subscribes itself through the common -[subscription interface](/docs/guides/evm/precompile-design#subscription-control) -and implements only the callbacks selected by its event mask. - -## Proposed callbacks - -| Receiver function | Subtensor source event | -|---|---| -| `onStakeAdded(...)` | `StakeAdded` | -| `onStakeRemoved(...)` | `StakeRemoved` | -| `onStakeMoved(...)` | `StakeMoved` | -| `onStakeTransferred(...)` | `StakeTransferred` | -| `onStakeAndHotkeyTransferred(...)` | `StakeAndHotkeyTransferred` | -| `onStakeSwapped(...)` | `StakeSwapped` | -| `onAlphaRecycled(...)` | `AlphaRecycled` | -| `onAlphaBurned(...)` | `AlphaBurned` | -| `onStakeBurned(...)` | `AddStakeBurn` | -| `onAutoStakeAdded(...)` | `AutoStakeAdded` | -| `onAutoStakeDestinationChanged(...)` | `AutoStakeDestinationSet` | -| `onStakeLocked(...)` | `StakeLocked` | -| `onLockMoved(...)` | `LockMoved` | -| `onCollateralLocked(...)` | `CollateralLocked` | -| `onMinimumCollateralChanged(...)` | `MinCollateralSet` | -| `onDelegateTakeIncreased(...)` | `TakeIncreased` | -| `onDelegateTakeDecreased(...)` | `TakeDecreased` | -| `onChildKeyTakeChanged(...)` | `ChildKeyTakeSet` | -| `onAutoParentDelegationChanged(...)` | `AutoParentDelegationEnabledSet` | -| `onRootClaimed(...)` | `RootClaimed` | -| `onRootClaimTypeChanged(...)` | `RootClaimTypeSet` | -| `onPerpetualLockChanged(...)` | `PerpetualLockUpdated` | -| `onLockedAlphaAcceptanceChanged(...)` | `RejectLockedAlphaUpdated` | -| `onFaucetFunded(...)` | `Faucet` | - -`onAutoStakeAdded` covers the current staking event emitted from a runtime hook. -The remaining callbacks also make transaction- and scheduled-operation events -available through the same receiver model. - -Each callback begins with `uint64 sequence` and `uint64 sourceBlock`, followed -by typed fields corresponding to the source event. Account IDs use `bytes32`; -TAO and Alpha amounts use 18-decimal `uint256` values. - -The names and signatures are provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/subnet-events.mdx b/docs/guides/evm/precompiles/subnet-events.mdx deleted file mode 100644 index f1e8e5d8a4..0000000000 --- a/docs/guides/evm/precompiles/subnet-events.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Subnet events -description: Proposed subscription precompile for typed Subtensor subnet lifecycle, lease, epoch, emission, and voting-power callbacks. ---- - -| Property | Value | -|---|---| -| Proposed implementation | `SubnetEventsPrecompile` | -| Proposed Solidity interface | `ISubnetEvents` | -| Callback receiver interface | `ISubnetEventsReceiver` | -| Address | Dedicated address not assigned | -| Status | Proposed | - -This precompile reports subnet creation and dissolution, ownership and identity -changes, leases, epoch execution, emissions, and voting-power tracking emitted -by `SubtensorModule`. - -## Proposed callbacks - -| Receiver function | Subtensor source | -|---|---| -| `onNetworkRegistrationQueued(...)` | `NetworkRegistrationQueued` | -| `onNetworkAdded(...)` | `NetworkAdded` | -| `onNetworkDissolutionScheduled(...)` | `DissolveNetworkScheduled` | -| `onNetworkRemoved(...)` | `NetworkRemoved` | -| `onNetworkDissolutionCleanupCompleted(...)` | `NetworkDissolveCleanupCompleted` | -| `onSubnetIdentitySet(...)` | `SubnetIdentitySet` | -| `onSubnetIdentityRemoved(...)` | `SubnetIdentityRemoved` | -| `onSubnetSymbolChanged(...)` | `SymbolUpdated` | -| `onSubnetOwnerHotkeyChanged(...)` | `SubnetOwnerHotkeySet` | -| `onSubnetOwnerChanged(...)` | `SubnetOwnerChanged` | -| `onFirstEmissionBlockSet(...)` | `FirstEmissionBlockNumberSet` | -| `onSubnetLeaseCreated(...)` | `SubnetLeaseCreated` | -| `onSubnetLeaseTerminated(...)` | `SubnetLeaseTerminated` | -| `onSubnetLeaseDividendDistributed(...)` | `SubnetLeaseDividendsDistributed` | -| `onEpochTriggered(...)` | `EpochTriggered` | -| `onEpochDeferred(...)` | `EpochDeferred` | -| `onEpochSkipped(...)` | `EpochSkipped` | -| `onUidEmissionCalculated(...)` | One callback per UID emission entry from `IncentiveAlphaEmittedToMiners` | -| `onVotingPowerTrackingEnabled(...)` | `VotingPowerTrackingEnabled` | -| `onVotingPowerTrackingDisableScheduled(...)` | `VotingPowerTrackingDisableScheduled` | -| `onVotingPowerTrackingDisabled(...)` | `VotingPowerTrackingDisabled` | -| `onVotingPowerEmaAlphaChanged(...)` | `VotingPowerEmaAlphaSet` | - -The current hook-origin callbacks are `onNetworkDissolutionCleanupCompleted`, -`onSubnetLeaseDividendDistributed`, `onEpochDeferred`, `onEpochSkipped`, -`onUidEmissionCalculated`, and `onVotingPowerTrackingDisabled`. - -### Per-UID emission calculation - -`IncentiveAlphaEmittedToMiners` contains an `emissions` array whose index is the -miner UID: `emissions[0]` is the Alpha emission for UID 0, `emissions[1]` is for -UID 1, and so on. The precompile does not pass this variable-length array to a -subscriber. It delivers one bounded callback for each `(uid, alpha)` entry: - -```solidity -function onUidEmissionCalculated( - uint64 sequence, - uint64 sourceBlock, - uint16 netuid, - uint16 uid, - uint16 uidCount, - uint256 alpha -) external; -``` - -For example, a source array of `[10, 20, 30]` produces callbacks for -`(uid=0, alpha=10)`, `(uid=1, alpha=20)`, and `(uid=2, alpha=30)`. All callbacks -from that source event share the same sequence and `uidCount`, allowing the -receiver to identify the complete set without accepting an unbounded argument. - -Subnet identity and symbol values must use bounded Solidity representations -chosen before the ABI is released. - -Every callback also carries the source block. Account IDs use `bytes32`, -netuids use `uint16`, and balances use 18-decimal `uint256` values. - -Subscription behavior is defined in -[Subscription-based event reporting](/docs/guides/evm/precompile-design#subscription-based-event-reporting). -The names and signatures are provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/weights-events.mdx b/docs/guides/evm/precompiles/weights-events.mdx deleted file mode 100644 index 6d1822d12c..0000000000 --- a/docs/guides/evm/precompiles/weights-events.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Weights events -description: Proposed subscription precompile for typed Subtensor weights, commit-reveal, and batch callbacks. ---- - -| Property | Value | -|---|---| -| Proposed implementation | `WeightsEventsPrecompile` | -| Proposed Solidity interface | `IWeightsEvents` | -| Callback receiver interface | `IWeightsEventsReceiver` | -| Address | Dedicated address not assigned | -| Status | Proposed | - -This precompile reports weight setting and each supported commit-reveal path -emitted by `SubtensorModule`, including reveals performed later by a runtime -hook. - -## Proposed callbacks - -| Receiver function | Subtensor source event | -|---|---| -| `onWeightsSet(...)` | `WeightsSet` | -| `onWeightsCommitted(...)` | `WeightsCommitted` | -| `onWeightsRevealed(...)` | `WeightsRevealed` | -| `onWeightBatchRevealItem(...)` | One hash from `WeightsBatchRevealed` | -| `onBatchWeightCompleted(...)` | One netuid from `BatchWeightsCompleted` | -| `onWeightBatchCompletedWithErrors(...)` | `BatchCompletedWithErrors` | -| `onWeightBatchItemFailed(...)` | `BatchWeightItemFailed` | -| `onTimelockedWeightsCommitted(...)` | `TimelockedWeightsCommitted` | -| `onTimelockedWeightsRevealed(...)` | `TimelockedWeightsRevealed` | -| `onCommitRevealPeriodsChanged(...)` | `CommitRevealPeriodsSet` | -| `onCommitRevealEnabledChanged(...)` | `CommitRevealEnabled` | -| `onCommitRevealVersionChanged(...)` | `CommitRevealVersionSet` | - -`onTimelockedWeightsRevealed` covers the current weights event emitted from a -runtime hook. - -Batch callbacks carry the source sequence, item index, and item count and -report one bounded item per invocation. Dispatch failures use a stable typed -error representation rather than SCALE-encoded `DispatchError`. - -Every callback also carries the source block. Hotkeys use `bytes32`, netuids -use `uint16`, and commitment hashes use `bytes32`. - -Subscription behavior is defined in -[Subscription-based event reporting](/docs/guides/evm/precompile-design#subscription-based-event-reporting). -The names and signatures are provisional and do not reserve selectors. From 32980cdbe4ec8b3ef404c6e5032773cf6e533614 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Wed, 29 Jul 2026 17:36:10 -0400 Subject: [PATCH 14/58] Require root priviledged calls to not be implemented in precompiles in evm maintainer skill --- .agents/skills/emv-maintainer/SKILL.md | 35 ++++++++- .../references/abi-versioning.md | 16 +++++ .../references/coverage-and-testing.md | 29 ++++++-- docs/guides/evm/precompile-design.mdx | 71 ++++++++++++++++++- .../evm/precompiles/account-balance.mdx | 8 +-- docs/guides/evm/precompiles/alpha.mdx | 17 ++--- .../evm/precompiles/balance-transfer.mdx | 7 +- docs/guides/evm/precompiles/drand.mdx | 24 +++---- .../evm/precompiles/extrinsic-coverage.mdx | 62 +++++++++------- docs/guides/evm/precompiles/index.mdx | 14 ++-- docs/guides/evm/precompiles/leasing.mdx | 5 +- docs/guides/evm/precompiles/neuron.mdx | 13 ++-- docs/guides/evm/precompiles/registry.mdx | 23 +++--- .../evm/precompiles/runtime-configuration.mdx | 33 ++++----- docs/guides/evm/precompiles/scheduler.mdx | 36 ++++------ docs/guides/evm/precompiles/staking-v2.mdx | 13 +--- docs/guides/evm/precompiles/subnet.mdx | 33 ++------- docs/guides/evm/precompiles/timestamp.mdx | 9 ++- docs/guides/evm/precompiles/voting-power.mdx | 6 +- 19 files changed, 274 insertions(+), 180 deletions(-) diff --git a/.agents/skills/emv-maintainer/SKILL.md b/.agents/skills/emv-maintainer/SKILL.md index 931b3ac8e1..bbd88d169e 100644 --- a/.agents/skills/emv-maintainer/SKILL.md +++ b/.agents/skills/emv-maintainer/SKILL.md @@ -45,11 +45,33 @@ For each affected released function: ## Notes on coding precompiles -- Never allow direct writing of state maps or variables to precompile callers. - Keep every precompile path O(1) in CPU and memory. +- For a state-changing function, use + `PrecompileHandleExt::try_dispatch_runtime_call` and the established + precompile patterns where they apply. Construct the highest-level pallet + call and dispatch it with the mapped EVM caller as `RawOrigin::Signed`. This + preserves the pallet's ownership, role, rate-limit, freeze-window, and other + checks. Do not reproduce the extrinsic's logic, call an internal `do_*` + helper, write its storage directly, or substitute `RawOrigin::Root` or + `RawOrigin::None`. +- Expose a state-changing extrinsic only when that highest-level pallet call + accepts a non-Root signed origin. +- An extrinsic that accepts either a signed authority, such as a subnet owner, + or Root may expose its signed path. Do not expose an extrinsic that is + Root-only or `None`-only unless a separately approved authorization design is + added to the runtime. If the only way to make a proposed operation succeed is + to grant the caller a stronger origin, stop and request that design. +- Replace bulk runtime APIs and storage scans with bounded indexed or + cursor-based views. Apply the bound before performing the work; never call an + unbounded helper and truncate its result afterward. - Follow [ABI versioning](references/abi-versioning.md) for every released interface. - Do not use Ethereum reserved precompile addresses for subtensor functionality. +- Assign new Bittensor domain precompiles sequentially from the next unused + Bittensor address. The current proposal reserves `0x080f` through `0x0813` + for Scheduler, Drand, Timestamp, Runtime Configuration, and the Precompile + Registry, respectively. Add routing and tests that lock every implemented + address and selector before release. - Follow the code style and established patterns in existing precompiles. - Represent Substrate account IDs in EVM space as 32-byte public keys. - Multiply Subtensor balances by `10^9` to match EVM's 18-decimal convention, @@ -57,7 +79,8 @@ For each affected released function: ## Step 1 - Review current precompiles vs. subtensor functionality -- All extrinsics should be exposed to precompile callers for the following pallets: +- All extrinsics that accept a non-Root signed origin should be exposed to + precompile callers for the following pallets: - subtensor - admin-util - balances @@ -67,7 +90,13 @@ For each affected released function: - crowdloan - timestamp - swap -- All runtime API RPCs for the subtensor pallet should be exposed as a callable precompile function with similar interface +- Root-only, `None`-only, inherent, disabled, and compatibility no-op + extrinsics must be inventoried and explicitly classified as not callable + through typed EVM precompiles. +- All deterministic runtime API RPC results for the subtensor pallet should be + exposed through typed precompile views. Preserve a similar interface when it + is already bounded; redesign bulk results as bounded indexed or cursor-based + views when it is not. Use [Coverage and testing](references/coverage-and-testing.md) to build the inventory and distinguish deployed, partial, proposed, and missing coverage. diff --git a/.agents/skills/emv-maintainer/references/abi-versioning.md b/.agents/skills/emv-maintainer/references/abi-versioning.md index c4dafd1c0b..03f6493f27 100644 --- a/.agents/skills/emv-maintainer/references/abi-versioning.md +++ b/.agents/skills/emv-maintainer/references/abi-versioning.md @@ -77,6 +77,22 @@ Keep every released selector reserved permanently, including after hard deprecation. Route a hard-deprecated selector to its descriptive error. Never allow a different function to claim it. +Assign a genuinely new Bittensor domain the next unused sequential Bittensor +address. The current proposal reserves: + +| Address | Domain | +|---|---| +| `0x080f` | Scheduler | +| `0x0810` | Drand | +| `0x0811` | Timestamp | +| `0x0812` | Runtime Configuration | +| `0x0813` | Precompile Registry | + +A documented reservation prevents another domain from taking the address but +does not make the precompile callable. When implementing a reserved address, +add exact-value tests for its index and full address, routing tests through the +precompile set, and selector tests for every function at that address. + Before adding a function, calculate its selector from the canonical Solidity signature and compare it with the complete selector set at the address. Reject collisions even when the Solidity names differ. diff --git a/.agents/skills/emv-maintainer/references/coverage-and-testing.md b/.agents/skills/emv-maintainer/references/coverage-and-testing.md index 902752a872..729f4ad07e 100644 --- a/.agents/skills/emv-maintainer/references/coverage-and-testing.md +++ b/.agents/skills/emv-maintainer/references/coverage-and-testing.md @@ -57,8 +57,11 @@ precompile per storage item. ## Cover extrinsics -Expose each authorized extrinsic through a typed state-changing function unless -an explicit scope decision excludes it. +Expose each extrinsic that accepts a non-Root signed origin through a typed +state-changing function unless an explicit scope decision excludes it. Calls +that accept either Root or a signed authority may expose only the signed path. +Classify Root-only and `None`-only calls as not EVM-callable; the existence of a +runtime extrinsic does not authorize a precompile to manufacture its origin. Preserve: @@ -71,9 +74,10 @@ Preserve: - runtime errors and EVM failure behavior; and - gas and weight charging, including post-dispatch adjustment. -Use `PrecompileHandleExt::try_dispatch_runtime_call` and established -precompile patterns where they apply. Do not bypass guards or create a direct -state-writing path that the pallet does not authorize. +Do not count a selector as coverage merely because it is routed. Test that a +mapped caller with the required signed authority can succeed and that a caller +without that authority fails without changing state. A selector that always +fails `BadOrigin` is not meaningful coverage. When an extrinsic changes, compare the old and new behavior rather than only their Rust signatures. Follow [ABI versioning](abi-versioning.md) when an @@ -116,6 +120,18 @@ precompile may call the same underlying helpers rather than reproduce an RPC transport detail. Preserve pagination, bounds, defaults, and absence semantics that affect callers. +Do not copy a bulk runtime API into Solidity when its work or result can grow +with chain state. Prefer one of these bounded shapes: + +- an indexed item view plus a bounded count; +- a cursor and caller-supplied limit capped by a fixed runtime maximum; or +- a fixed-size key batch whose maximum is part of the interface contract. + +Return the next cursor or an explicit completion indicator when callers need to +walk the complete collection. Charge for the maximum work actually permitted. +Apply limits before reading or constructing the collection; calling an +unbounded runtime helper and slicing its returned vector is still unbounded. + Do not expose node-only behavior that cannot execute deterministically in the runtime. When a public RPC composes runtime state, implement the deterministic runtime-side result and document any transport-only behavior that has no EVM @@ -182,6 +198,9 @@ Verify: 9. `Precompiles::execute()` recognizes the address and routes it through the intended availability control and compatible implementation. 10. Unknown-address and unknown-selector behavior remains unchanged. +11. Every new Bittensor domain uses the next reserved sequential address, and + address constants, `used_addresses()`, routing, documentation, Solidity + interfaces, and address-locking tests agree. Do not hand-wave generated-file churn. Inspect each changed ABI entry and remove unrelated regeneration changes. diff --git a/docs/guides/evm/precompile-design.mdx b/docs/guides/evm/precompile-design.mdx index 66f59a8439..c0e2e72ff5 100644 --- a/docs/guides/evm/precompile-design.mdx +++ b/docs/guides/evm/precompile-design.mdx @@ -29,8 +29,9 @@ The precompile layer is designed around five goals: original behavior whenever that behavior can still be represented safely. 4. **Status is discoverable.** Solidity interfaces and a registry should tell developers when a function is deprecated, replaced, or temporarily disabled. -5. **The authorized Substrate API has full parity.** Every storage item and - extrinsic in scope has a typed precompile equivalent. +5. **The signed, deterministic Substrate API has typed parity.** Storage and + runtime API results have bounded typed views, and extrinsics that accept a + non-Root signed origin have typed operations. ## Fixed addresses and function selectors @@ -97,6 +98,21 @@ Creating a new domain address may still be appropriate when the functionality is genuinely a different precompile, but it should not be the default versioning mechanism. +New Bittensor domain addresses are assigned sequentially from the next unused +Bittensor address. The currently proposed domains reserve: + +| Address | Domain | +|---|---| +| `0x000000000000000000000000000000000000080f` | Scheduler | +| `0x0000000000000000000000000000000000000810` | Drand | +| `0x0000000000000000000000000000000000000811` | Timestamp | +| `0x0000000000000000000000000000000000000812` | Runtime configuration | +| `0x0000000000000000000000000000000000000813` | Precompile registry | + +An address reservation does not make a proposed precompile callable. When an +implementation is added, routing and tests must lock the address and every +implemented selector before release. + ### Keep old semantics when possible Suppose `getStake` originally returned total stake, while a later runtime stores @@ -124,12 +140,56 @@ the precompile implementation adapts while the Solidity interface remains stable. A resulting Rust compilation failure provides a safety net that raw storage queries do not. +### Bound collection views + +Runtime APIs and storage collections that grow with chain state must not be +copied into a single Solidity function returning an unbounded array. Expose an +indexed item with a bounded count, or use a cursor and a caller-supplied limit +that is capped by a fixed runtime maximum. A fixed-size batch of explicit keys +is also suitable when callers already know which records they need. + +The bound must apply before storage is scanned or results are constructed. +Calling an unbounded runtime helper and truncating its result afterward does +not make the precompile bounded. Paginated views should return a next cursor or +completion indicator and define stable ordering, missing-item behavior, and +the maximum page size. + +### Preserve runtime authorization + +A state-changing precompile dispatches the highest-level pallet extrinsic with +the mapped EVM caller as a signed origin. The pallet then enforces the same +ownership, role, rate-limit, freeze-window, and validation checks that apply to +an ordinary signed Substrate transaction. + +An extrinsic that permits either Root or a non-Root signer, such as a subnet +owner, may expose its signed path. Root-only and `None`-only extrinsics are not +exposed through typed EVM functions. A precompile must never substitute Root, +invoke an internal state-changing helper, or reproduce the extrinsic logic to +bypass the top-level checks. + +### Read-only infrastructure views + +Read-only precompiles let contracts inspect deterministic consensus state +without receiving any authority to change it: + +- Scheduler views expose bounded task metadata so contracts can verify whether + and when runtime work is scheduled. +- Drand views expose beacon configuration, stored pulses, and round ranges for + contract logic that depends on the runtime's randomness state. +- Timestamp views replace raw reads of timestamp storage; `getTimestamp` + corresponds to the same underlying time represented by `block.timestamp`. +- Lifecycle views let contracts and tooling discover whether a selector is + deprecated, replaced, or currently unavailable. + +These views replace raw storage decoding or off-chain RPC composition. They do +not execute privileged extrinsics and do not provide a path to Root. + ### Phasing out raw storage reads `StorageQueryPrecompile` at `0x…0807` exposes raw Substrate storage and is inherently brittle. The intended migration is: -1. Add a typed view for every storage item in the currently authorized pallets: +1. Add a bounded typed view for every storage item in the currently authorized pallets: SubtensorModule, Balances, Proxy, Scheduler, Drand, Crowdloan, Sudo, Multisig, Timestamp, and Swap. 2. Soft-deprecate raw storage access after that typed coverage exists. @@ -371,6 +431,11 @@ Every precompile change should verify: agree; - lifecycle registry metadata and NatSpec annotations agree; - disable and re-enable behavior is covered for the affected precompile; +- state-changing functions dispatch the highest-level extrinsic as the mapped + signed caller and do not bypass its authorization checks; +- bulk views are bounded before they read or construct results; +- new domain addresses follow the documented sequential reservation and are + locked by routing tests; - no selector is reused. Typed views provide a compile-time safety advantage: when runtime types or diff --git a/docs/guides/evm/precompiles/account-balance.mdx b/docs/guides/evm/precompiles/account-balance.mdx index 63c6edbe4d..ac400bc3c1 100644 --- a/docs/guides/evm/precompiles/account-balance.mdx +++ b/docs/guides/evm/precompiles/account-balance.mdx @@ -21,14 +21,12 @@ description: Reference for the deployed BalancePrecompile. | Proposed function | Source extrinsic | |---|---| | `burnBalance` | `Balances.burn` | -| `forceUnreserve` | `Balances.force_unreserve` | | `upgradeAccounts` | `Balances.upgrade_accounts` | -| `forceSetBalance` | `Balances.force_set_balance` | -| `forceAdjustTotalIssuance` | `Balances.force_adjust_total_issuance` | -| `setTotalIssuance` | `AdminUtils.sudo_set_total_issuance` | `upgradeAccounts` must have an explicit fixed input bound. The implementation -must preserve all runtime authorization and issuance invariants. +must dispatch the highest-level Balances call as the mapped signer and preserve +all runtime authorization and issuance invariants. Force operations require +Root and are not exposed. Proposed names and signatures do not reserve selectors. diff --git a/docs/guides/evm/precompiles/alpha.mdx b/docs/guides/evm/precompiles/alpha.mdx index 4cde04cdb5..cb69de1c74 100644 --- a/docs/guides/evm/precompiles/alpha.mdx +++ b/docs/guides/evm/precompiles/alpha.mdx @@ -40,24 +40,15 @@ getCKBurn() | Proposed function | Source extrinsic | |---|---| -| `setSwapFeeRate` | `Swap.set_fee_rate` | | `setRecycleOrBurn` | `AdminUtils.sudo_set_recycle_or_burn` | -| `setSubnetMovingAlpha` | `AdminUtils.sudo_set_subnet_moving_alpha` | -| `setEmaPriceHalvingPeriod` | `AdminUtils.sudo_set_ema_price_halving_period` | -| `setCkBurn` | `AdminUtils.sudo_set_ck_burn` | -| `setTaoFlowCutoff` | `AdminUtils.sudo_set_tao_flow_cutoff` | -| `setTaoFlowNormalizationExponent` | `AdminUtils.sudo_set_tao_flow_normalization_exponent` | -| `setTaoFlowSmoothingFactor` | `AdminUtils.sudo_set_tao_flow_smoothing_factor` | -| `setNetTaoFlowEnabled` | `AdminUtils.sudo_set_net_tao_flow_enabled` | | `setBurnHalfLife` | `AdminUtils.sudo_set_burn_half_life` | | `setBurnIncreaseMultiplier` | `AdminUtils.sudo_set_burn_increase_mult` | -| `setSubnetEmissionEnabled` | `AdminUtils.sudo_set_subnet_emission_enabled` | -| `setEmissionBarQuantile` | `AdminUtils.sudo_set_emission_bar_quantile` | -| `setEmissionGateExponent` | `AdminUtils.sudo_set_emission_gate_exponent` | The five deprecated `Swap` liquidity extrinsics are intentionally not proposed; -they always return the pallet's `Deprecated` error. Runtime authorization -remains in force for every administrative operation. +they always return the pallet's `Deprecated` error. `Swap.set_fee_rate` and the +remaining Alpha-related AdminUtils calls require Root and are not exposed. +The three listed AdminUtils calls accept a signed subnet owner; only that +signed path is exposed and runtime authorization remains in force. Proposed names and signatures do not reserve selectors. diff --git a/docs/guides/evm/precompiles/balance-transfer.mdx b/docs/guides/evm/precompiles/balance-transfer.mdx index 0631247658..46d79d9f7b 100644 --- a/docs/guides/evm/precompiles/balance-transfer.mdx +++ b/docs/guides/evm/precompiles/balance-transfer.mdx @@ -23,16 +23,15 @@ public key. | Proposed function | Source extrinsic | |---|---| -| `faucet` | `SubtensorModule.faucet` | | `transferKeepAlive` | `Balances.transfer_keep_alive` | | `transferAll` | `Balances.transfer_all` | -| `forceTransfer` | `Balances.force_transfer` | The existing `transfer(bytes32)` semantically covers `Balances.transfer_allow_death` by taking the amount from attached EVM value. The proposed functions use explicit typed arguments where attached value does -not express the complete source operation. Runtime authorization remains in -force for `forceTransfer`. +not express the complete source operation. They dispatch the highest-level +Balances call as the mapped signer. `force_transfer` requires Root and the +feature-gated development faucet is not part of the production interface. Proposed names and signatures do not reserve selectors. diff --git a/docs/guides/evm/precompiles/drand.mdx b/docs/guides/evm/precompiles/drand.mdx index 08b5b195a5..970621c48b 100644 --- a/docs/guides/evm/precompiles/drand.mdx +++ b/docs/guides/evm/precompiles/drand.mdx @@ -7,11 +7,13 @@ description: Proposed typed EVM interface for the Drand pallet. |---|---| | Proposed implementation | `DrandPrecompile` | | Proposed Solidity interface | `IDrand` | -| Address | Not assigned | -| Status | Proposed | +| Reserved address | `0x0000000000000000000000000000000000000810` | +| Status | Proposed; not yet callable | This precompile would expose typed beacon configuration and pulse data instead of requiring callers to construct Drand storage keys and decode SCALE values. +Contracts can use the runtime's stored randomness state deterministically +without receiving permission to configure the beacon or submit pulses. ## Planned views @@ -23,16 +25,12 @@ of requiring callers to construct Drand storage keys and decode SCALE values. | `getNextUnsignedAt()` | `Drand.NextUnsignedAt` | | `hasMigrationRun(bytes key)` | `Drand.HasMigrationRun` | -## Planned operations +## State-changing operations -| Proposed function | Source extrinsic | -|---|---| -| `setBeaconConfig` | `Drand.set_beacon_config` | -| `setOldestStoredRound` | `Drand.set_oldest_stored_round` | - -`Drand.write_pulse` is not exposed. It is an unsigned offchain-worker -submission that requires `None` origin, which an EVM caller cannot satisfy -without changing the security model. +`Drand.set_beacon_config` and `Drand.set_oldest_stored_round` require Root, and +`Drand.write_pulse` requires `None` origin as an unsigned offchain-worker +submission. None is exposed as a typed EVM operation because doing so would +bypass the pallet's top-level origin checks. -The runtime's existing authorization checks remain in force. Names and -signatures on this page are provisional and do not reserve selectors. +The address is reserved for this domain. Names and signatures on this page are +provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/extrinsic-coverage.mdx b/docs/guides/evm/precompiles/extrinsic-coverage.mdx index 4e9b58510c..1688bf4d57 100644 --- a/docs/guides/evm/precompiles/extrinsic-coverage.mdx +++ b/docs/guides/evm/precompiles/extrinsic-coverage.mdx @@ -14,62 +14,74 @@ interface or an explicit proposed typed replacement. ## Coverage summary -| Pallet | Runtime extrinsics | Typed today | Proposed additions | Not exposed | +| Pallet | Runtime extrinsics | Typed today | Proposed signed additions | Not exposed | |---|---:|---:|---:|---:| -| `SubtensorModule` | 82 | 24 | 56 | 2 | -| `AdminUtils` | 86 | 24 | 62 | 0 | -| `Balances` | 9 | 1 | 8 | 0 | +| `SubtensorModule` | 82 | 24 | 44 | 14 | +| `AdminUtils` | 86 | 24 | 16 | 46 | +| `Balances` | 9 | 1 | 4 | 4 | | `Proxy` | 12 | 7 | 5 | 0 | -| `Scheduler` | 10 | 0 | 10 | 0 | -| `Drand` | 3 | 0 | 2 | 1 | +| `Scheduler` | 10 | 0 | 0 | 10 | +| `Drand` | 3 | 0 | 0 | 3 | | `Crowdloan` | 10 | 9 | 1 | 0 | | `Timestamp` | 1 | 0 | 0 | 1 | -| `Swap` | 6 | 0 | 1 | 5 | -| **Total** | **219** | **65** | **145** | **9** | +| `Swap` | 6 | 0 | 0 | 6 | +| **Total** | **219** | **65** | **70** | **84** | `Typed today` counts semantic coverage, not only direct dispatch to the same Rust call. For example, `registerNetwork(bytes32)` covers basic subnet registration by dispatching `register_network_with_identity` with empty identity fields. -## Classification of proposed additions +`Proposed signed additions` includes extrinsics whose highest-level pallet call +accepts a non-Root signed origin. If a call also accepts Root, only its signed +path is exposed: the mapped EVM caller is dispatched as `Signed`, and the +pallet performs its normal authorization checks. + +## Classification of proposed signed additions Each missing operation is listed on the page of its target precompile: | Target precompile | Missing extrinsics assigned | |---|---:| -| [Subnet](/docs/guides/evm/precompiles/subnet) | 37 | -| [Staking V2](/docs/guides/evm/precompiles/staking-v2) | 29 | -| [Neuron](/docs/guides/evm/precompiles/neuron) | 27 | -| [Alpha](/docs/guides/evm/precompiles/alpha) | 14 | -| [Scheduler](/docs/guides/evm/precompiles/scheduler) | 10 | -| [Account balance](/docs/guides/evm/precompiles/account-balance) | 6 | +| [Subnet](/docs/guides/evm/precompiles/subnet) | 13 | +| [Staking V2](/docs/guides/evm/precompiles/staking-v2) | 20 | +| [Neuron](/docs/guides/evm/precompiles/neuron) | 21 | +| [Alpha](/docs/guides/evm/precompiles/alpha) | 3 | +| [Account balance](/docs/guides/evm/precompiles/account-balance) | 2 | | [Proxy](/docs/guides/evm/precompiles/proxy) | 5 | -| [Balance transfer](/docs/guides/evm/precompiles/balance-transfer) | 4 | -| [Runtime configuration](/docs/guides/evm/precompiles/runtime-configuration) | 4 | -| [Voting power](/docs/guides/evm/precompiles/voting-power) | 3 | -| [Drand](/docs/guides/evm/precompiles/drand) | 2 | -| [Leasing](/docs/guides/evm/precompiles/leasing) | 2 | +| [Balance transfer](/docs/guides/evm/precompiles/balance-transfer) | 2 | +| [Voting power](/docs/guides/evm/precompiles/voting-power) | 2 | +| [Leasing](/docs/guides/evm/precompiles/leasing) | 1 | | [Crowdloan](/docs/guides/evm/precompiles/crowdloan) | 1 | -| [Precompile registry](/docs/guides/evm/precompiles/registry) | 1 | Proposed function names do not reserve selectors. Their final parameter types, -bounds, authorization model, and return values must be specified before -implementation. +bounds, and return values must be specified before implementation. Each +implementation must dispatch the highest-level pallet extrinsic as the mapped +signed caller rather than reproducing its logic. ## Extrinsics not exposed as EVM calls | Pallet extrinsic | Reason | |---|---| +| Root-only `SubtensorModule` extrinsics | `dissolve_network`, `root_dissolve_network`, `swap_coldkey`, `sudo_set_tx_childkey_take_rate_limit`, `sudo_set_min_childkey_take`, `sudo_set_max_childkey_take`, `set_pending_childkey_cooldown`, `reset_coldkey_swap`, `sudo_set_num_root_claims`, and `sudo_set_voting_power_ema_alpha` require Root. | +| `SubtensorModule.schedule_swap_coldkey` | Deprecated compatibility call that always returns `Deprecated`. | +| `SubtensorModule.faucet` | Build-feature-only development call; it is not part of the production runtime interface. | | `SubtensorModule.set_tempo` | Retained call-index compatibility entry point that succeeds without changing state. The real setting is `AdminUtils.sudo_set_tempo`, proposed as `SubnetPrecompile.setTempo`. | | `SubtensorModule.set_activity_cutoff_factor` | Retained call-index compatibility entry point that succeeds without changing state. The active AdminUtils operation is already covered by `SubnetPrecompile.setActivityCutoffFactor`. | +| Root-only `AdminUtils` extrinsics | Root-only administration is not delegated to EVM callers. Calls that also accept a signed subnet owner remain in the proposed signed additions on the domain pages. | +| `AdminUtils.sudo_set_total_issuance` | Deprecated call that always returns `Deprecated`. | +| Root-only `Balances` extrinsics | `force_unreserve`, `force_transfer`, `force_set_balance`, and `force_adjust_total_issuance` require Root. | +| All `Scheduler` extrinsics | `Scheduler.ScheduleOrigin` is configured as Root in the runtime. | | `Drand.write_pulse` | Unsigned offchain-worker submission requiring `None` origin. An EVM caller cannot satisfy that origin without changing its security model. | +| Drand configuration extrinsics | `set_beacon_config` and `set_oldest_stored_round` require Root. | | `Timestamp.set` | Block-production inherent requiring `None` origin. Contracts already receive the same time through `block.timestamp`. | +| `Swap.set_fee_rate` | Requires Root. | | `Swap.add_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | | `Swap.remove_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | | `Swap.modify_position` | Permanently disabled pallet call that always returns `Deprecated`. | | `Swap.toggle_user_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | | `Swap.disable_lp` | Permanently disabled pallet call that always returns `Deprecated`. | -These exclusions preserve the existing runtime origin and lifecycle semantics; -they are not missing callable functionality. +These exclusions preserve the existing runtime origin and lifecycle semantics. +A typed precompile must not manufacture Root or `None`, call an internal helper, +or write storage directly to make one of these operations callable. diff --git a/docs/guides/evm/precompiles/index.mdx b/docs/guides/evm/precompiles/index.mdx index 84da100486..902b925be8 100644 --- a/docs/guides/evm/precompiles/index.mdx +++ b/docs/guides/evm/precompiles/index.mdx @@ -6,7 +6,9 @@ description: Addresses, implementations, and reference pages for Bittensor EVM p Bittensor precompiles are fixed-address contracts implemented by the Subtensor runtime. `Deployed` means that the address is registered in the current runtime; it does not imply complete coverage of the underlying runtime domain. -`Proposed` precompiles have no assigned address or released selectors. +`Proposed` precompiles are not callable. Their documented addresses are +reserved for those domains, while their function selectors remain provisional +until the interfaces are implemented and released. The [extrinsic coverage audit](/docs/guides/evm/precompiles/extrinsic-coverage) tracks every runtime extrinsic in scope and identifies its deployed, proposed, @@ -49,11 +51,11 @@ or intentionally non-callable EVM treatment. | [`AddressMappingPrecompile`](/docs/guides/evm/precompiles/address-mapping) | `IAddressMapping` |
Deployed | | [`VotingPowerPrecompile`](/docs/guides/evm/precompiles/voting-power) | `IVotingPower` |
Deployed | | [`BalancePrecompile`](/docs/guides/evm/precompiles/account-balance) | `IBalance` |
Deployed | -| [`SchedulerPrecompile`](/docs/guides/evm/precompiles/scheduler) | `IScheduler` | Address not assigned
Proposed | -| [`DrandPrecompile`](/docs/guides/evm/precompiles/drand) | `IDrand` | Address not assigned
Proposed | -| [`TimestampPrecompile`](/docs/guides/evm/precompiles/timestamp) | `ITimestamp` | Address not assigned
Proposed | -| [`RuntimeConfigurationPrecompile`](/docs/guides/evm/precompiles/runtime-configuration) | `IRuntimeConfiguration` | Address not assigned
Proposed | -| [`PrecompileRegistry`](/docs/guides/evm/precompiles/registry) | `IPrecompileRegistry` | Address not assigned
Proposed | +| [`SchedulerPrecompile`](/docs/guides/evm/precompiles/scheduler) | `IScheduler` |
Proposed · address reserved | +| [`DrandPrecompile`](/docs/guides/evm/precompiles/drand) | `IDrand` |
Proposed · address reserved | +| [`TimestampPrecompile`](/docs/guides/evm/precompiles/timestamp) | `ITimestamp` |
Proposed · address reserved | +| [`RuntimeConfigurationPrecompile`](/docs/guides/evm/precompiles/runtime-configuration) | `IRuntimeConfiguration` |
Proposed · address reserved | +| [`PrecompileRegistry`](/docs/guides/evm/precompiles/registry) | `IPrecompileRegistry` |
Proposed · address reserved | Projects that need proactive event delivery should use [project-scoped event relays](/docs/guides/evm/precompile-design#project-scoped-event-relays) diff --git a/docs/guides/evm/precompiles/leasing.mdx b/docs/guides/evm/precompiles/leasing.mdx index 32f20af948..b211bc2a47 100644 --- a/docs/guides/evm/precompiles/leasing.mdx +++ b/docs/guides/evm/precompiles/leasing.mdx @@ -32,8 +32,9 @@ Both operations are `payable`. | Proposed function | Source extrinsic | |---|---| | `startCall` | `SubtensorModule.start_call` | -| `setStartCallDelay` | `AdminUtils.sudo_set_start_call_delay` | -Proposed names and signatures do not reserve selectors. +`startCall` accepts a signed subnet owner. The Root-only start-call delay +configuration is not exposed. The proposed name and signature do not reserve a +selector. Source: [`leasing.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/leasing.sol) diff --git a/docs/guides/evm/precompiles/neuron.mdx b/docs/guides/evm/precompiles/neuron.mdx index 6cbe2643e4..47164e83aa 100644 --- a/docs/guides/evm/precompiles/neuron.mdx +++ b/docs/guides/evm/precompiles/neuron.mdx @@ -51,22 +51,19 @@ use typed Drand data rather than SCALE-encoded payloads. | `rootRegister` | `SubtensorModule.root_register` | | `swapHotkey` | `SubtensorModule.swap_hotkey` | | `swapHotkeyV2` | `SubtensorModule.swap_hotkey_v2` | -| `swapColdkey` | `SubtensorModule.swap_coldkey` | -| `scheduleColdkeySwap` | `SubtensorModule.schedule_swap_coldkey` | | `setChildren` | `SubtensorModule.set_children` | | `setIdentity` | `SubtensorModule.set_identity` | | `tryAssociateHotkey` | `SubtensorModule.try_associate_hotkey` | | `associateEvmKey` | `SubtensorModule.associate_evm_key` | -| `setPendingChildkeyCooldown` | `SubtensorModule.set_pending_childkey_cooldown` | | `announceColdkeySwap` | `SubtensorModule.announce_coldkey_swap` | | `executeAnnouncedColdkeySwap` | `SubtensorModule.swap_coldkey_announced` | | `disputeColdkeySwap` | `SubtensorModule.dispute_coldkey_swap` | -| `resetColdkeySwap` | `SubtensorModule.reset_coldkey_swap` | | `clearColdkeySwapAnnouncement` | `SubtensorModule.clear_coldkey_swap_announcement` | -| `setColdkeySwapAnnouncementDelay` | `AdminUtils.sudo_set_coldkey_swap_announcement_delay` | -| `setColdkeySwapReannouncementDelay` | `AdminUtils.sudo_set_coldkey_swap_reannouncement_delay` | -Runtime authorization remains in force. Proposed names and signatures do not -reserve selectors. +Every proposed operation accepts a non-Root signed origin. The precompile must +dispatch the highest-level extrinsic as the mapped caller so runtime +authorization remains in force. Root-only and deprecated compatibility calls +are classified in the [coverage audit](./extrinsic-coverage). Proposed names +and signatures do not reserve selectors. Source: [`neuron.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/neuron.sol) diff --git a/docs/guides/evm/precompiles/registry.mdx b/docs/guides/evm/precompiles/registry.mdx index 721c930786..df0a4782a2 100644 --- a/docs/guides/evm/precompiles/registry.mdx +++ b/docs/guides/evm/precompiles/registry.mdx @@ -7,11 +7,13 @@ description: Proposed registry for precompile lifecycle and availability. |---|---| | Proposed implementation | `PrecompileRegistry` | | Proposed Solidity interface | `IPrecompileRegistry` | -| Address | Not assigned | -| Status | Proposed | +| Reserved address | `0x0000000000000000000000000000000000000813` | +| Status | Proposed; not yet callable | The registry provides function-level lifecycle metadata and the current -operational availability of the containing precompile. +operational availability of the containing precompile. Contracts, deployment +tools, and frontends can inspect whether a selector is deprecated, has a +replacement, or is currently unavailable without attempting the affected call. ## Proposed interface @@ -32,16 +34,11 @@ interface IPrecompileRegistry { } ``` -## Proposed operation - -| Proposed function | Source extrinsic | -|---|---| -| `setPrecompileEnabled` | `AdminUtils.sudo_toggle_evm_precompile` | - -This operation changes reversible availability; it does not change or erase a -function's deprecation lifecycle. Runtime authorization remains in force. +`AdminUtils.sudo_toggle_evm_precompile` is Root-only and is not exposed by this +precompile. The registry reports availability but does not grant callers +permission to change it. The lifecycle model is described in [Precompile design and lifecycle](/docs/guides/evm/precompile-design#discovering-status). -The address and selector are not reserved until the interface is implemented -and released. +The address is reserved for this domain. The proposed selector remains +provisional until the interface is implemented and released. diff --git a/docs/guides/evm/precompiles/runtime-configuration.mdx b/docs/guides/evm/precompiles/runtime-configuration.mdx index 7c8ecff2c4..1c5f6d688e 100644 --- a/docs/guides/evm/precompiles/runtime-configuration.mdx +++ b/docs/guides/evm/precompiles/runtime-configuration.mdx @@ -7,24 +7,25 @@ description: Proposed typed EVM interface for global runtime configuration opera |---|---| | Proposed implementation | `RuntimeConfigurationPrecompile` | | Proposed Solidity interface | `IRuntimeConfiguration` | -| Address | Not assigned | -| Status | Proposed | +| Reserved address | `0x0000000000000000000000000000000000000812` | +| Status | Proposed; not yet callable | -This precompile groups the small set of global AdminUtils operations that do -not belong to a subnet, staking, Alpha, account-balance, or precompile-lifecycle -domain. +This domain is reserved for bounded typed views of global runtime +configuration that do not belong to subnet, staking, Alpha, account-balance, +or precompile-lifecycle domains. -## Planned operations +## State-changing operations -| Proposed function | Source extrinsic | -|---|---| -| `swapAuthorities` | `AdminUtils.swap_authorities` | -| `setTransactionRateLimit` | `AdminUtils.sudo_set_tx_rate_limit` | -| `setEvmChainId` | `AdminUtils.sudo_set_evm_chain_id` | -| `scheduleGrandpaChange` | `AdminUtils.schedule_grandpa_change` | +The currently identified global configuration extrinsics are Root-only: + +```text +AdminUtils.swap_authorities +AdminUtils.sudo_set_tx_rate_limit +AdminUtils.sudo_set_evm_chain_id +AdminUtils.schedule_grandpa_change +``` -The runtime's authorization checks remain in force. The implementation must -define a typed, bounded authority representation and must not expose -SCALE-encoded runtime values. +They are not proposed as typed EVM operations. A future view must return a +typed, bounded representation and must not expose SCALE-encoded runtime values. -Names and signatures on this page are provisional and do not reserve selectors. +The address is reserved for this domain. No function selector is reserved. diff --git a/docs/guides/evm/precompiles/scheduler.mdx b/docs/guides/evm/precompiles/scheduler.mdx index 94f1d8545d..3e61d9646f 100644 --- a/docs/guides/evm/precompiles/scheduler.mdx +++ b/docs/guides/evm/precompiles/scheduler.mdx @@ -7,11 +7,13 @@ description: Proposed typed EVM interface for the Scheduler pallet. |---|---| | Proposed implementation | `SchedulerPrecompile` | | Proposed Solidity interface | `IScheduler` | -| Address | Not assigned | -| Status | Proposed | +| Reserved address | `0x000000000000000000000000000000000000080f` | +| Status | Proposed; not yet callable | -This precompile would replace raw reads of Scheduler storage and expose the -Scheduler extrinsics through a stable EVM interface. +This precompile would replace raw reads of Scheduler storage with a stable EVM +interface. It lets contracts inspect whether and when runtime work is +scheduled without decoding Scheduler storage or acquiring permission to modify +the schedule. ## Planned views @@ -26,23 +28,11 @@ Scheduler extrinsics through a stable EVM interface. Returning one agenda entry at a time keeps execution bounded and avoids an unbounded array result. -## Planned operations +## State-changing operations -| Proposed function | Source extrinsic | -|---|---| -| `schedule` | `Scheduler.schedule` | -| `cancel` | `Scheduler.cancel` | -| `scheduleNamed` | `Scheduler.schedule_named` | -| `cancelNamed` | `Scheduler.cancel_named` | -| `scheduleAfter` | `Scheduler.schedule_after` | -| `scheduleNamedAfter` | `Scheduler.schedule_named_after` | -| `setRetry` | `Scheduler.set_retry` | -| `setRetryNamed` | `Scheduler.set_retry_named` | -| `cancelRetry` | `Scheduler.cancel_retry` | -| `cancelRetryNamed` | `Scheduler.cancel_retry_named` | - -Scheduled payloads must use a versioned, stable EVM call description. They must -not expose SCALE-encoded `RuntimeCall`, whose encoding can change after a -runtime upgrade. - -Names and signatures on this page are provisional and do not reserve selectors. +The runtime configures `Scheduler.ScheduleOrigin` as Root. Scheduler extrinsics +therefore have no typed EVM operation: a precompile must not manufacture Root +or bypass the top-level Scheduler authorization check. + +The address is reserved for this domain. Names and signatures on this page are +provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/staking-v2.mdx b/docs/guides/evm/precompiles/staking-v2.mdx index 334e76640d..8db426ac92 100644 --- a/docs/guides/evm/precompiles/staking-v2.mdx +++ b/docs/guides/evm/precompiles/staking-v2.mdx @@ -83,9 +83,6 @@ encoding of the allowance mutations. | `decreaseTake` | `SubtensorModule.decrease_take` | | `increaseTake` | `SubtensorModule.increase_take` | | `setChildkeyTake` | `SubtensorModule.set_childkey_take` | -| `setTxChildkeyTakeRateLimit` | `SubtensorModule.sudo_set_tx_childkey_take_rate_limit` | -| `setMinChildkeyTake` | `SubtensorModule.sudo_set_min_childkey_take` | -| `setMaxChildkeyTake` | `SubtensorModule.sudo_set_max_childkey_take` | | `unstakeAll` | `SubtensorModule.unstake_all` | | `unstakeAllAlpha` | `SubtensorModule.unstake_all_alpha` | | `swapStake` | `SubtensorModule.swap_stake` | @@ -94,7 +91,6 @@ encoding of the allowance mutations. | `setColdkeyAutoStakeHotkey` | `SubtensorModule.set_coldkey_auto_stake_hotkey` | | `claimRoot` | `SubtensorModule.claim_root` | | `setRootClaimType` | `SubtensorModule.set_root_claim_type` | -| `setNumRootClaims` | `SubtensorModule.sudo_set_num_root_claims` | | `setRootClaimThreshold` | `SubtensorModule.sudo_set_root_claim_threshold` | | `addStakeBurn` | `SubtensorModule.add_stake_burn` | | `setAutoParentDelegationEnabled` | `SubtensorModule.set_auto_parent_delegation_enabled` | @@ -110,16 +106,13 @@ encoding of the allowance mutations. | Proposed function | Source extrinsic | |---|---| -| `setDefaultTake` | `AdminUtils.sudo_set_default_take` | -| `setStakeThreshold` | `AdminUtils.sudo_set_stake_threshold` | -| `setNominatorMinRequiredStake` | `AdminUtils.sudo_set_nominator_min_required_stake` | -| `setDelegateTakeRateLimit` | `AdminUtils.sudo_set_tx_delegate_take_rate_limit` | -| `setMinDelegateTake` | `AdminUtils.sudo_set_min_delegate_take` | | `setMinChildkeyTakePerSubnet` | `AdminUtils.sudo_set_min_childkey_take_per_subnet` | | `setCollateralLockShare` | `AdminUtils.sudo_set_collateral_lock_share` | | `setCollateralDrainRatio` | `AdminUtils.sudo_set_collateral_drain_ratio` | -Runtime authorization remains in force. Proposed names and signatures do not +The listed owner-or-Root calls expose only their signed subnet-owner path. +Every operation dispatches the highest-level extrinsic as the mapped caller so +runtime authorization remains in force. Proposed names and signatures do not reserve selectors. Source: [`stakingV2.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/stakingV2.sol) diff --git a/docs/guides/evm/precompiles/subnet.mdx b/docs/guides/evm/precompiles/subnet.mdx index 5817cc54ba..95b3be9881 100644 --- a/docs/guides/evm/precompiles/subnet.mdx +++ b/docs/guides/evm/precompiles/subnet.mdx @@ -103,50 +103,31 @@ real AdminUtils operations therefore require the proposed V2 selectors below. | Proposed function | Source extrinsic | |---|---| -| `dissolveNetwork` | `SubtensorModule.dissolve_network` | | `setSubnetIdentity` | `SubtensorModule.set_subnet_identity` | | `updateSubnetSymbol` | `SubtensorModule.update_symbol` | -| `rootDissolveNetwork` | `SubtensorModule.root_dissolve_network` | | `triggerEpoch` | `SubtensorModule.trigger_epoch` | ## Proposed AdminUtils operations | Proposed function | Source extrinsic | |---|---| -| `setAdjustmentInterval` | `AdminUtils.sudo_set_adjustment_interval` | -| `setAdminFreezeWindow` | `AdminUtils.sudo_set_admin_freeze_window` | | `setBondsPenalty` | `AdminUtils.sudo_set_bonds_penalty` | -| `setCommitRevealVersion` | `AdminUtils.sudo_set_commit_reveal_version` | -| `setDissolveNetworkScheduleDuration` | `AdminUtils.sudo_set_dissolve_network_schedule_duration` | -| `setNetworkLockCostReductionInterval` | `AdminUtils.sudo_set_lock_reduction_interval` | | `setMaxAllowedUids` | `AdminUtils.sudo_set_max_allowed_uids` | -| `setMaxAllowedValidators` | `AdminUtils.sudo_set_max_allowed_validators` | | `setMaxBurnV2` | `AdminUtils.sudo_set_max_burn` | -| `setMaxEpochsPerBlock` | `AdminUtils.sudo_set_max_epochs_per_block` | -| `setMaxMechanismCount` | `AdminUtils.sudo_set_max_mechanism_count` | -| `setMaxRegistrationsPerBlock` | `AdminUtils.sudo_set_max_registrations_per_block` | | `setMechanismCount` | `AdminUtils.sudo_set_mechanism_count` | | `setMechanismEmissionSplit` | `AdminUtils.sudo_set_mechanism_emission_split` | -| `setMinAllowedUids` | `AdminUtils.sudo_set_min_allowed_uids` | | `setMinBurnV2` | `AdminUtils.sudo_set_min_burn` | -| `setMinNonImmuneUids` | `AdminUtils.sudo_set_min_non_immune_uids` | -| `setNetworkImmunityPeriod` | `AdminUtils.sudo_set_network_immunity_period` | -| `setNetworkMinLockCost` | `AdminUtils.sudo_set_network_min_lock_cost` | -| `setNetworkRateLimit` | `AdminUtils.sudo_set_network_rate_limit` | | `setOwnerCutEnabled` | `AdminUtils.sudo_set_owner_cut_enabled` | -| `setOwnerHyperparameterRateLimit` | `AdminUtils.sudo_set_owner_hparam_rate_limit` | | `setOwnerImmuneNeuronLimit` | `AdminUtils.sudo_set_owner_immune_neuron_limit` | -| `setRaoRecycledForRegistration` | `AdminUtils.sudo_set_rao_recycled` | -| `setSubnetOwnerHotkey` | `AdminUtils.sudo_set_sn_owner_hotkey` | -| `setSubnetLimit` | `AdminUtils.sudo_set_subnet_limit` | -| `setSubnetOwnerCut` | `AdminUtils.sudo_set_subnet_owner_cut` | -| `setSubtokenEnabled` | `AdminUtils.sudo_set_subtoken_enabled` | -| `setTargetRegistrationsPerInterval` | `AdminUtils.sudo_set_target_registrations_per_interval` | | `setTempo` | `AdminUtils.sudo_set_tempo` | -| `setWeightsSetRateLimitV2` | `AdminUtils.sudo_set_weights_set_rate_limit` | | `trimToMaxAllowedUids` | `AdminUtils.sudo_trim_to_max_allowed_uids` | -Runtime authorization remains in force. Proposed names and signatures do not -reserve selectors. +Each listed AdminUtils call accepts a signed subnet owner as well as Root. The +precompile exposes only the signed path and dispatches the highest-level +extrinsic so owner limits, freeze windows, and other runtime checks remain in +force. Root-only calls are classified as not EVM-callable in the +[coverage audit](./extrinsic-coverage). + +Proposed names and signatures do not reserve selectors. Source: [`subnet.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/subnet.sol) diff --git a/docs/guides/evm/precompiles/timestamp.mdx b/docs/guides/evm/precompiles/timestamp.mdx index 8b6d6424d2..52cc225207 100644 --- a/docs/guides/evm/precompiles/timestamp.mdx +++ b/docs/guides/evm/precompiles/timestamp.mdx @@ -7,8 +7,8 @@ description: Proposed typed EVM interface for Timestamp pallet state. |---|---| | Proposed implementation | `TimestampPrecompile` | | Proposed Solidity interface | `ITimestamp` | -| Address | Not assigned | -| Status | Proposed | +| Reserved address | `0x0000000000000000000000000000000000000811` | +| Status | Proposed; not yet callable | ## Planned views @@ -20,6 +20,8 @@ description: Proposed typed EVM interface for Timestamp pallet state. `getTimestamp()` returns the same underlying time as the EVM `block.timestamp` value. It exists here so every storage item authorized through `StorageQueryPrecompile` has an explicit typed replacement. +`wasUpdatedThisBlock` provides the Timestamp pallet's update state without +requiring contracts to construct a storage key or decode SCALE. `Timestamp.set` is an inherent submitted by block production, not a public user operation. The proposed precompile therefore exposes no state-changing @@ -28,4 +30,5 @@ timestamp function. See the complete classification in [Extrinsic coverage](/docs/guides/evm/precompiles/extrinsic-coverage). -Names and signatures on this page are provisional and do not reserve selectors. +The address is reserved for this domain. Names and signatures on this page are +provisional and do not reserve selectors. diff --git a/docs/guides/evm/precompiles/voting-power.mdx b/docs/guides/evm/precompiles/voting-power.mdx index a38f4d9d88..1b2747f516 100644 --- a/docs/guides/evm/precompiles/voting-power.mdx +++ b/docs/guides/evm/precompiles/voting-power.mdx @@ -28,8 +28,10 @@ getTotalVotingPower(uint16) |---|---| | `enableVotingPowerTracking` | `SubtensorModule.enable_voting_power_tracking` | | `disableVotingPowerTracking` | `SubtensorModule.disable_voting_power_tracking` | -| `setVotingPowerEmaAlpha` | `SubtensorModule.sudo_set_voting_power_ema_alpha` | -Proposed names and signatures do not reserve selectors. +Both calls accept a signed subnet owner as well as Root. The precompile exposes +only the signed path and preserves the pallet's owner checks. The Root-only EMA +configuration call is not exposed. Proposed names and signatures do not +reserve selectors. Source: [`votingPower.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/votingPower.sol) From 36dee7cb4037de517c08e7f5bd017bb969723174 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Wed, 29 Jul 2026 18:20:20 -0400 Subject: [PATCH 15/58] Spec out the deprecation with locally defined precompile lifecycle rust annotations --- .agents/skills/emv-maintainer/SKILL.md | 13 +++- .../references/abi-versioning.md | 66 +++++++++++++++++-- .../references/coverage-and-testing.md | 3 + 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/.agents/skills/emv-maintainer/SKILL.md b/.agents/skills/emv-maintainer/SKILL.md index bbd88d169e..cf70ec198e 100644 --- a/.agents/skills/emv-maintainer/SKILL.md +++ b/.agents/skills/emv-maintainer/SKILL.md @@ -33,7 +33,12 @@ For each affected released function: 2. Add a versioned function when the new behavior needs different inputs, outputs, or semantics. Keep the old address and selector routed. 3. Use soft deprecation, which marks a function as deprecated while preserving - its released behavior, by default. Never fabricate data or silently + its released behavior, by default. Declare deprecation and replacement + metadata on the Rust precompile function with the lifecycle annotation + described in [ABI versioning](references/abi-versioning.md). Treat the + annotated Rust function as the source of truth and generate Solidity + lifecycle annotations and registry metadata from it; do not maintain + separate hand-written lifecycle data. Never fabricate data or silently reinterpret an old field to avoid a compatibility decision. 4. If hard deprecation may be necessary, stop and follow the mainnet release warning and lifecycle process in @@ -66,6 +71,12 @@ For each affected released function: unbounded helper and truncate its result afterward. - Follow [ABI versioning](references/abi-versioning.md) for every released interface. +- Treat repository-owned Rust function lifecycle annotations as the source of + truth for registry deprecation metadata, replacement selectors, migration + messages, and generated Solidity interfaces and `@custom:deprecated` + NatSpec. Do not hand-edit generated Solidity lifecycle data. Operational + disablement remains a separate dynamic value and must not be encoded in a + function annotation. - Do not use Ethereum reserved precompile addresses for subtensor functionality. - Assign new Bittensor domain precompiles sequentially from the next unused Bittensor address. The current proposal reserves `0x080f` through `0x0813` diff --git a/.agents/skills/emv-maintainer/references/abi-versioning.md b/.agents/skills/emv-maintainer/references/abi-versioning.md index 03f6493f27..ea753e0216 100644 --- a/.agents/skills/emv-maintainer/references/abi-versioning.md +++ b/.agents/skills/emv-maintainer/references/abi-versioning.md @@ -179,9 +179,10 @@ Keep function lifecycle separate from precompile availability: | Hard-deprecated and enabled | Keep routing the selector and return a descriptive precompile error. | | Disabled | Return the precompile-disabled error regardless of function lifecycle. | -Use soft deprecation by default. Preserve the call, mark the Solidity function -with `@deprecated`, and publish replacement metadata without adding -deprecation-only work to every invocation. +Use soft deprecation by default. Preserve the call, annotate the Rust +precompile function with its lifecycle metadata, generate the Solidity +`@custom:deprecated` NatSpec from that annotation, and publish replacement +metadata without adding deprecation-only work to every invocation. Use hard deprecation only when old behavior cannot be represented honestly or safely, for example because: @@ -232,19 +233,70 @@ struct PrecompileStatus { } ``` +### Function lifecycle annotations + +Declare deprecation metadata on the affected Rust precompile function with a +repository-owned annotation. The target syntax is: + +```rust +#[precompile_lifecycle::deprecated( + replace_with = "getStakeV2(uint16,uint16)", + message = "Use getStakeV2 for the current stake representation." +)] +#[precompile::public("getStake(uint16,uint16)")] +``` + +Do not use `#[precompile::deprecated]` unless the Frontier precompile macro +explicitly supports it: that namespace belongs to the Frontier macro. Do not +encode structured replacement metadata in Rust's built-in `#[deprecated]` +attribute, which does not provide `replace_with` and `message` fields. The +repository-owned annotation and its generator can be implemented in subtensor +without changing Frontier. + +The annotated Rust precompile function is the authoritative source for: + +- whether the function is deprecated; +- the canonical replacement signature used to derive `newSelector`; +- migration guidance returned in `message`; and +- the generated Solidity interface and its lifecycle NatSpec. + +The replacement precompile defaults to the containing precompile address. +Allow an explicit replacement address when migration genuinely crosses +domains. If no replacement exists, omit `replace_with`; the registry returns +zero replacement fields. A deprecated function without a useful human message +is incomplete metadata. + +Repository tooling should collect these Rust annotations and generate the +static registry metadata and Solidity interface lifecycle data. Generate +standards-compliant `@custom:deprecated` and, when applicable, +`@custom:replace-with` NatSpec; an additional `@notice` may make the warning +visible to clients that ignore custom tags. Do not duplicate the same +lifecycle data in a manually maintained Rust match, static table, Solidity +comment, or registry file, and do not hand-edit generated Solidity lifecycle +annotations. Build validation must fail when annotated Rust metadata, the +canonical replacement selector, generated Solidity and NatSpec, and public +documentation disagree. + +The annotation describes function lifecycle only. It does not perform +deprecation work on each invocation and does not control availability. +`isDisabled` remains a dynamic lookup of the containing precompile's +operational enablement state. + Interpret `isDeprecated` as soft or hard function deprecation. Interpret `isDisabled` as current unavailability through a reversible operational switch. Use `newPrecompile` and `newSelector` for the recommended replacement; zero replacement fields mean that none is available. Use `message` for human-readable status or migration guidance. -Do not infer deprecation from disablement. Do not clear deprecation when a +An active function has no deprecation annotation and therefore returns +`isDeprecated = false` with zero replacement fields and an empty message. Do +not infer deprecation from disablement. Do not clear deprecation when a precompile is re-enabled. Do not describe the registry as callable until its address and implementation are released. -Keep registry metadata, Solidity NatSpec, public documentation, and call -behavior consistent. Prefer static registry queries over emitting a log on -every deprecated call. +Keep generated registry metadata, Solidity NatSpec, public documentation, and +call behavior consistent. Prefer static registry queries over emitting a log +on every deprecated call. ## Handle reversible disablement diff --git a/.agents/skills/emv-maintainer/references/coverage-and-testing.md b/.agents/skills/emv-maintainer/references/coverage-and-testing.md index 729f4ad07e..f4b711c33b 100644 --- a/.agents/skills/emv-maintainer/references/coverage-and-testing.md +++ b/.agents/skills/emv-maintainer/references/coverage-and-testing.md @@ -194,6 +194,9 @@ Verify: 6. Unrelated precompile Solidity and ABI files are byte-for-byte unchanged. 7. The Rust macro signature, Solidity declaration, generated ABI, NatSpec, SDK copies, registry metadata, and public documentation agree. + For deprecated functions, verify that registry metadata and Solidity + `@custom:deprecated` NatSpec are generated from the Rust function lifecycle + annotation rather than duplicated manually. 8. Every released address remains in `Precompiles::used_addresses()`. 9. `Precompiles::execute()` recognizes the address and routes it through the intended availability control and compatible implementation. From 374619fef60655e1a2e60e7736d1dd0667e3a995 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Thu, 30 Jul 2026 09:49:38 -0400 Subject: [PATCH 16/58] 99% complete implementation of precompiles --- docs/guides/evm/precompile-design.mdx | 458 +++++++++++++++ .../evm/precompiles/account-balance.mdx | 32 ++ docs/guides/evm/precompiles/alpha.mdx | 54 ++ .../evm/precompiles/balance-transfer.mdx | 37 ++ docs/guides/evm/precompiles/crowdloan.mdx | 46 ++ docs/guides/evm/precompiles/drand.mdx | 38 ++ .../evm/precompiles/extrinsic-coverage.mdx | 86 +++ docs/guides/evm/precompiles/index.mdx | 66 +++ docs/guides/evm/precompiles/leasing.mdx | 39 ++ docs/guides/evm/precompiles/metagraph.mdx | 45 ++ docs/guides/evm/precompiles/neuron.mdx | 78 +++ docs/guides/evm/precompiles/proxy.mdx | 47 ++ docs/guides/evm/precompiles/registry.mdx | 44 ++ .../evm/precompiles/runtime-configuration.mdx | 38 ++ docs/guides/evm/precompiles/scheduler.mdx | 40 ++ docs/guides/evm/precompiles/staking-v2.mdx | 124 ++++ docs/guides/evm/precompiles/storage-query.mdx | 65 +++ docs/guides/evm/precompiles/subnet.mdx | 134 +++++ docs/guides/evm/precompiles/timestamp.mdx | 33 ++ docs/guides/evm/precompiles/voting-power.mdx | 36 ++ pallets/admin-utils/src/lib.rs | 10 + pallets/drand/src/lib.rs | 7 + precompiles/Cargo.toml | 8 +- precompiles/src/alpha.rs | 100 +++- precompiles/src/balance.rs | 86 ++- precompiles/src/balance_transfer.rs | 76 ++- precompiles/src/crowdloan.rs | 15 + precompiles/src/drand.rs | 185 ++++++ precompiles/src/leasing.rs | 9 + precompiles/src/lib.rs | 294 +++++++++- precompiles/src/neuron.rs | 474 +++++++++++++++- precompiles/src/proxy.rs | 82 +++ precompiles/src/registry.rs | 191 +++++++ precompiles/src/runtime_configuration.rs | 87 +++ precompiles/src/scheduler.rs | 256 +++++++++ precompiles/src/solidity/alpha.abi | 54 ++ precompiles/src/solidity/alpha.sol | 9 + precompiles/src/solidity/balance.abi | 33 +- precompiles/src/solidity/balance.sol | 4 +- precompiles/src/solidity/balanceTransfer.abi | 38 +- precompiles/src/solidity/balanceTransfer.sol | 4 +- precompiles/src/solidity/crowdloan.abi | 25 +- precompiles/src/solidity/crowdloan.sol | 7 +- precompiles/src/solidity/drand.abi | 129 +++++ precompiles/src/solidity/drand.sol | 25 + precompiles/src/solidity/leasing.abi | 15 +- precompiles/src/solidity/leasing.sol | 1 + precompiles/src/solidity/neuron.abi | 530 +++++++++++++++++- precompiles/src/solidity/neuron.sol | 105 ++++ precompiles/src/solidity/proxy.abi | 74 ++- precompiles/src/solidity/proxy.sol | 5 + precompiles/src/solidity/registry.abi | 53 ++ precompiles/src/solidity/registry.sol | 19 + .../src/solidity/runtimeConfiguration.abi | 28 + .../src/solidity/runtimeConfiguration.sol | 9 + precompiles/src/solidity/scheduler.abi | 183 ++++++ precompiles/src/solidity/scheduler.sol | 33 ++ precompiles/src/solidity/stakingV2.abi | 437 ++++++++++++++- precompiles/src/solidity/stakingV2.sol | 66 +++ precompiles/src/solidity/subnet.abi | 273 ++++++++- precompiles/src/solidity/subnet.sol | 31 + precompiles/src/solidity/timestamp.abi | 28 + precompiles/src/solidity/timestamp.sol | 9 + precompiles/src/solidity/votingPower.abi | 28 +- precompiles/src/solidity/votingPower.sol | 3 + precompiles/src/staking.rs | 396 ++++++++++++- precompiles/src/subnet.rs | 279 ++++++++- precompiles/src/timestamp.rs | 107 ++++ precompiles/src/voting_power.rs | 71 ++- sdk/python/bittensor/evm/abi/alpha.json | 54 ++ sdk/python/bittensor/evm/abi/balance.json | 33 +- .../bittensor/evm/abi/balanceTransfer.json | 38 +- sdk/python/bittensor/evm/abi/crowdloan.json | 25 +- sdk/python/bittensor/evm/abi/drand.json | 129 +++++ sdk/python/bittensor/evm/abi/leasing.json | 15 +- sdk/python/bittensor/evm/abi/neuron.json | 530 +++++++++++++++++- sdk/python/bittensor/evm/abi/proxy.json | 74 ++- sdk/python/bittensor/evm/abi/registry.json | 53 ++ .../evm/abi/runtimeConfiguration.json | 28 + sdk/python/bittensor/evm/abi/scheduler.json | 183 ++++++ sdk/python/bittensor/evm/abi/stakingV2.json | 437 ++++++++++++++- sdk/python/bittensor/evm/abi/subnet.json | 273 ++++++++- sdk/python/bittensor/evm/abi/timestamp.json | 28 + sdk/python/bittensor/evm/abi/votingPower.json | 28 +- sdk/python/bittensor/evm/precompiles.py | 52 +- sdk/python/tests/unit/test_evm.py | 10 + 86 files changed, 8459 insertions(+), 62 deletions(-) create mode 100644 docs/guides/evm/precompile-design.mdx create mode 100644 docs/guides/evm/precompiles/account-balance.mdx create mode 100644 docs/guides/evm/precompiles/alpha.mdx create mode 100644 docs/guides/evm/precompiles/balance-transfer.mdx create mode 100644 docs/guides/evm/precompiles/crowdloan.mdx create mode 100644 docs/guides/evm/precompiles/drand.mdx create mode 100644 docs/guides/evm/precompiles/extrinsic-coverage.mdx create mode 100644 docs/guides/evm/precompiles/index.mdx create mode 100644 docs/guides/evm/precompiles/leasing.mdx create mode 100644 docs/guides/evm/precompiles/metagraph.mdx create mode 100644 docs/guides/evm/precompiles/neuron.mdx create mode 100644 docs/guides/evm/precompiles/proxy.mdx create mode 100644 docs/guides/evm/precompiles/registry.mdx create mode 100644 docs/guides/evm/precompiles/runtime-configuration.mdx create mode 100644 docs/guides/evm/precompiles/scheduler.mdx create mode 100644 docs/guides/evm/precompiles/staking-v2.mdx create mode 100644 docs/guides/evm/precompiles/storage-query.mdx create mode 100644 docs/guides/evm/precompiles/subnet.mdx create mode 100644 docs/guides/evm/precompiles/timestamp.mdx create mode 100644 docs/guides/evm/precompiles/voting-power.mdx create mode 100644 precompiles/src/drand.rs create mode 100644 precompiles/src/registry.rs create mode 100644 precompiles/src/runtime_configuration.rs create mode 100644 precompiles/src/scheduler.rs create mode 100644 precompiles/src/solidity/drand.abi create mode 100644 precompiles/src/solidity/drand.sol create mode 100644 precompiles/src/solidity/registry.abi create mode 100644 precompiles/src/solidity/registry.sol create mode 100644 precompiles/src/solidity/runtimeConfiguration.abi create mode 100644 precompiles/src/solidity/runtimeConfiguration.sol create mode 100644 precompiles/src/solidity/scheduler.abi create mode 100644 precompiles/src/solidity/scheduler.sol create mode 100644 precompiles/src/solidity/timestamp.abi create mode 100644 precompiles/src/solidity/timestamp.sol create mode 100644 precompiles/src/timestamp.rs create mode 100644 sdk/python/bittensor/evm/abi/drand.json create mode 100644 sdk/python/bittensor/evm/abi/registry.json create mode 100644 sdk/python/bittensor/evm/abi/runtimeConfiguration.json create mode 100644 sdk/python/bittensor/evm/abi/scheduler.json create mode 100644 sdk/python/bittensor/evm/abi/timestamp.json diff --git a/docs/guides/evm/precompile-design.mdx b/docs/guides/evm/precompile-design.mdx new file mode 100644 index 0000000000..a2a233c57f --- /dev/null +++ b/docs/guides/evm/precompile-design.mdx @@ -0,0 +1,458 @@ +--- +title: Precompile design and lifecycle +description: How Bittensor precompiles preserve compatibility and how projects relay selected Substrate events to EVM contracts. +--- + +Bittensor precompiles are fixed-address EVM contracts implemented by the +Subtensor runtime. They give Solidity callers typed access to chain operations +and durable chain values without requiring contracts to understand Substrate +storage. + +This page defines the compatibility model that new and existing precompiles +should follow. It also describes the target lifecycle registry. The registry +interface shown below is a design contract; it is not yet available on chain. + + + A deployed contract may be immutable. Treat every released precompile address, + function signature, and selector as a permanent public API. + + +## Design goals + +The precompile layer is designed around five goals: + +1. **Contracts at rest keep working.** Runtime upgrades must not silently break + deployed contracts. +2. **Interfaces evolve additively.** Existing selectors remain reserved, and + richer behavior is introduced through new function versions. +3. **Deprecation is normally soft.** An old function continues to preserve its + original behavior whenever that behavior can still be represented safely. +4. **Status is discoverable.** Solidity interfaces and a registry should tell + developers when a function is deprecated, replaced, or temporarily disabled. +5. **The signed, deterministic Substrate API has typed parity.** Storage and + runtime API results have bounded typed views, and extrinsics that accept a + non-Root signed origin have typed operations. + +## Fixed addresses and function selectors + +A precompile has a fixed EVM address for a domain such as staking, metagraph +data, or subnet operations. Solidity dispatches a call using the first four +bytes of the Keccak-256 hash of its canonical function signature. + +For example: + +```solidity +function getStake(uint16 netuid, uint16 uid) external view returns (uint64); +``` + +The selector belongs to that signature permanently once released. It must not +later be assigned different semantics, even if the original function is +hard-deprecated. Reusing a selector could make an old contract decode a +successful but unrelated result. + +The source-of-truth Solidity interfaces and generated ABIs live in +[`precompiles/src/solidity/`](https://github.com/RaoFoundation/subtensor/tree/main/precompiles/src/solidity). + +## Compatibility rules + +### Preserve released interfaces + +Do not remove or change a released function signature. A runtime implementation +may change internally to follow a new storage layout or computation, but the +observable result must retain the function's documented meaning. + +Changing any of these creates a different EVM interface: + +- function name or version suffix; +- parameter types or order; +- return types or order; +- mutability where it affects permitted calls; +- precompile address. + +### Version functions, not whole domains + +When a breaking return-type or parameter change is necessary, add a versioned +function at the same precompile address: + +```solidity +interface IMetagraph { + // Original selector remains supported. + function getStake( + uint16 netuid, + uint16 uid + ) external view returns (uint64); + + // New selector exposes the richer representation. + function getStakeV2( + uint16 netuid, + uint16 uid + ) external view returns (StakeInfo memory); +} +``` + +Use `functionName` for the initial version, followed by `functionNameV2`, +`functionNameV3`, and so on. Both selectors route independently, so adding a +version does not alter calls made by existing contracts. + +Creating a new domain address may still be appropriate when the functionality +is genuinely a different precompile, but it should not be the default +versioning mechanism. + +New Bittensor domain addresses are assigned sequentially from the next unused +Bittensor address. The latest deployed domains are: + +| Address | Domain | +|---|---| +| `0x000000000000000000000000000000000000080f` | Scheduler | +| `0x0000000000000000000000000000000000000810` | Drand | +| `0x0000000000000000000000000000000000000811` | Timestamp | +| `0x0000000000000000000000000000000000000812` | Runtime configuration | +| `0x0000000000000000000000000000000000000813` | Precompile registry | + +Documenting an address reservation does not make a proposed precompile +callable. When an implementation is added, routing and tests must lock the +address and every implemented selector before release. + +### Keep old semantics when possible + +Suppose `getStake` originally returned total stake, while a later runtime stores +self-stake and delegated stake separately. The original function can continue +returning their sum, while `getStakeV2` returns the breakdown. + +This is a soft deprecation: the old selector remains correct for callers that +depend on its original meaning. + +## Replace raw storage access with typed views + +Raw storage access couples a contract to pallet names, storage item names, +hashers, key shapes, and SCALE encodings. Any internal refactor can then make +the contract read an empty value or decode the wrong bytes without a useful +error. + +A typed view instead owns the encoding and decoding: + +```solidity +uint64 weight = IMetagraph(METAGRAPH_ADDRESS).getWeight(netuid, uid); +``` + +If the underlying storage map, key format, hasher, or value encoding changes, +the precompile implementation adapts while the Solidity interface remains +stable. A resulting Rust compilation failure provides a safety net that raw +storage queries do not. + +### Bound collection views + +Runtime APIs and storage collections that grow with chain state must not be +copied into a single Solidity function returning an unbounded array. Expose an +indexed item with a bounded count, or use a cursor and a caller-supplied limit +that is capped by a fixed runtime maximum. A fixed-size batch of explicit keys +is also suitable when callers already know which records they need. + +The bound must apply before storage is scanned or results are constructed. +Calling an unbounded runtime helper and truncating its result afterward does +not make the precompile bounded. Paginated views should return a next cursor or +completion indicator and define stable ordering, missing-item behavior, and +the maximum page size. + +### Preserve runtime authorization + +A state-changing precompile dispatches the highest-level pallet extrinsic with +the mapped EVM caller as a signed origin. The pallet then enforces the same +ownership, role, rate-limit, freeze-window, and validation checks that apply to +an ordinary signed Substrate transaction. + +An extrinsic that permits either Root or a non-Root signer, such as a subnet +owner, may expose its signed path. Root-only and `None`-only extrinsics are not +exposed through typed EVM functions. A precompile must never substitute Root, +invoke an internal state-changing helper, or reproduce the extrinsic logic to +bypass the top-level checks. + +### Read-only infrastructure views + +Read-only precompiles let contracts inspect deterministic consensus state +without receiving any authority to change it: + +- Scheduler views expose bounded task metadata so contracts can verify whether + and when runtime work is scheduled. +- Drand views expose beacon configuration, stored pulses, and round ranges for + contract logic that depends on the runtime's randomness state. +- Timestamp views replace raw reads of timestamp storage; `getTimestamp` + corresponds to the same underlying time represented by `block.timestamp`. +- Lifecycle views let contracts and tooling discover whether a selector is + deprecated, replaced, or currently unavailable. + +These views replace raw storage decoding or off-chain RPC composition. They do +not execute privileged extrinsics and do not provide a path to Root. + +### Phasing out raw storage reads + +`StorageQueryPrecompile` at `0x…0807` exposes raw Substrate storage and is +inherently brittle. The intended migration is: + +1. Add a bounded typed view for every storage item in the currently authorized pallets: + SubtensorModule, Balances, Proxy, Scheduler, Drand, Crowdloan, Sudo, + Multisig, Timestamp, and Swap. +2. Soft-deprecate raw storage access after that typed coverage exists. +3. Hard-deprecate it after a documented migration window. +4. Eventually disable it through an explicit root decision. + +Whether this 1:1 coverage should extend beyond the authorized pallets remains +an open design question. + +## Project-scoped event relays + +Substrate events are already recorded in chain data. Reproducing the complete +event stream through protocol-level EVM callbacks would add another on-chain +copy together with subscription storage, delivery queues, and callback +execution. It would also force the runtime to support broad event delivery even +when an application needs only a small, highly filtered set of signals. + +Bittensor therefore does not propose event-reporting precompiles. A project +that needs proactive notifications in its EVM contracts should run an +off-chain relay tailored to that project's use cases. The relay watches +finalized Substrate events, performs application-specific filtering, +aggregation, and enrichment off chain, and submits only the reports that the +project's contracts can act on. + +Typed precompile views remain the authoritative way for contracts to read +current runtime state. Relayed reports are notifications under the trust and +availability model chosen by the project. + +### Relay flow + +A typical relay operates as follows: + +1. Relay nodes read finalized blocks and events from Substrate RPC endpoints or + an indexer. +2. Each node applies the project's filters and derives a canonical typed + report. +3. A configured signer quorum attests to the report. +4. A relayer submits the report and its authorization proof in an ordinary EVM + transaction. +5. The reporting contract verifies the report, rejects duplicates, and either + emits a typed EVM log, invokes a bounded set of subscribed receivers, or + records data for receivers to pull. + +A report should identify at least the source chain, finalized block hash and +number, source event position or another unique event identifier, schema +version, payload, and relay sequence or nonce. The signed message must be +domain-separated by chain ID, reporting-contract address, and schema version so +that it cannot be replayed on another chain, contract, or report type. + +Filtering belongs primarily in the relay. A subnet application might publish +only completed tempo summaries, material configuration changes, or aggregate +emission results instead of reproducing every underlying pallet event. + +### Subscription-capable reporting contracts + +A project can deploy a reporting contract that lets users or other contracts +register subscriptions and lets authorized relayers submit observed reports. +A subscription can select typed report kinds, project-specific filters, a +receiver, and a callback gas limit. The contract should make its payment, +retry, ordering, and removal rules explicit. + +Neither report submission nor callback delivery should iterate an unbounded +subscriber set. Limit each transaction to a fixed-size batch, let relayers +target matching subscribers explicitly, or let subscribers pull verified +reports. Catch callback failures so one receiver cannot revert delivery to +others, and require receiver callbacks to be idempotent. + +Every successful relay submission has an EVM transaction and receipt. Projects +must decide whether relayers fund these transactions, subscribers prepay for +delivery, or another project account subsidizes them. + +### Relayer trust and security + +A single relay signer is the simplest design but makes that signer a trusted +oracle. Projects that need stronger guarantees can use an independently +operated committee with an explicit `M-of-N` multisignature, a threshold +signature scheme, or another auditable quorum mechanism. The reporting +contract must define signer enrollment, quorum, key rotation, emergency +revocation, and version upgrades. + +Relay implementations should also: + +- wait for the documented source-chain finality condition; +- use deterministic report encoding and reject duplicate event identifiers; +- expose sequences or source positions so receivers can detect gaps; +- tolerate delayed, reordered, and repeated submissions; +- bound report size, callback gas, batch size, and retained on-chain history; +- separate observation from submission so any permitted party can submit a + valid quorum-authorized report; and +- provide a reconciliation path through typed precompile views when a report is + missing or disputed. + +Contracts must not treat relayed events as consensus-authenticated merely +because they describe on-chain activity. Their integrity depends on the relay +committee and verification rules, while their availability depends on relay +operators continuing to observe and submit reports. + +## Function lifecycle + +Deprecation and disablement are different dimensions: + +- **Deprecation** communicates API evolution. It normally points callers toward + a replacement and is expected to remain part of the function's history. +- **Disablement** is an operational switch for an entire precompile. Root can + disable and later re-enable it through + `AdminUtils.sudo_toggle_evm_precompile`. + +| Lifecycle condition | Call behavior | +|---|---| +| Active and enabled | Executes normally | +| Soft-deprecated and enabled | Preserves its documented behavior | +| Hard-deprecated and enabled | Returns a descriptive precompile error | +| Disabled | Returns a precompile-disabled error regardless of function lifecycle | + +Soft deprecation is the default. Hard deprecation is reserved for cases where +the original behavior cannot be represented honestly or safely—for example, +when the underlying concept has been removed without a replacement. + +Disablement does not erase deprecation metadata. A soft-deprecated function can +also be disabled, and re-enabling its precompile restores its soft-deprecated +behavior. + +## Discovering status + +The standalone registry precompile gives tooling and contracts one +place to inspect both API lifecycle and operational availability. + +Because the result covers both lifecycle and operational availability, it is +called `PrecompileStatus`: + +```solidity +interface IPrecompileRegistry { + struct PrecompileStatus { + bool isDeprecated; + bool isDisabled; + address newPrecompile; + bytes4 newSelector; + string message; + } + + function getPrecompileStatus( + address precompile, + bytes4 selector + ) external view returns (PrecompileStatus memory); +} +``` + +The fields have the following meaning: + +| Field | Meaning | +|---|---| +| `isDeprecated` | The function is soft- or hard-deprecated. | +| `isDisabled` | The containing precompile is currently disabled by Root; Root can re-enable it. | +| `newPrecompile` | Address of the recommended replacement, often the same address. | +| `newSelector` | Selector of the recommended replacement function. | +| `message` | Human-readable status or migration guidance. | + +Zero replacement fields mean that no replacement is available. Tooling should +not infer that `isDisabled` implies deprecation, or that re-enabling a +precompile clears `isDeprecated`. + +The registry avoids adding overhead to every deprecated call. Deployment tools, +frontends, and upgradeable contracts can query it when evaluating dependencies. + +Solidity interfaces should also carry NatSpec annotations: + +```solidity +interface IMetagraph { + /// @deprecated Use getStakeV2 instead. + function getStake( + uint16 netuid, + uint16 uid + ) external view returns (uint64); + + function getStakeV2( + uint16 netuid, + uint16 uid + ) external view returns (StakeInfo memory); +} +``` + +## Handling runtime changes + +### Additive representation changes + +Keep the original function returning the original subset, add a versioned +function for the extended result, and soft-deprecate the original if callers +should migrate. + +### Semantic refinements + +Adapt the original implementation to preserve its documented meaning. Add a new +version only when callers need a representation that the original return type +cannot express. + +### Storage and computation changes + +Change the precompile implementation without changing its interface. This +includes changing: + +- storage names, key shapes, or hashers; +- the number of storage items used; +- intermediate representations; +- the computation used to produce the exposed value. + +### Complete removal + +Keep the selector reserved and make the function return a descriptive error. +Mark it hard-deprecated and explain whether an alternative exists. Do not +delete the signature and do not reuse its selector. + +### Emergency disablement + +Root may disable a precompile with: + +```text +AdminUtils.sudo_toggle_evm_precompile(precompile_id, false) +``` + +and re-enable it with: + +```text +AdminUtils.sudo_toggle_evm_precompile(precompile_id, true) +``` + +This switch is reversible and applies to the precompile as a whole. It is not a +substitute for function-level lifecycle metadata or a normal deprecation +process. + +## Maintenance and testing requirements + +Every precompile change should verify: + +- all previously released selectors remain routed; +- existing function signatures and return encodings are unchanged; +- old semantics are preserved or explicitly hard-deprecated; +- new behavior uses a new versioned selector when necessary; +- Solidity interfaces, generated ABIs, SDK copies, and runtime implementations + agree; +- lifecycle registry metadata and NatSpec annotations agree; +- disable and re-enable behavior is covered for the affected precompile; +- state-changing functions dispatch the highest-level extrinsic as the mapped + signed caller and do not bypass its authorization checks; +- bulk views are bounded before they read or construct results; +- new domain addresses follow the documented sequential reservation and are + locked by routing tests; +- no selector is reused. + +Typed views provide a compile-time safety advantage: when runtime types or +storage APIs change, the Rust implementation is more likely to stop compiling, +forcing maintainers to make an explicit compatibility decision. Coverage checks +should ensure that every storage item in the authorized pallets has a +corresponding view. + +Macro or code-generation support may eventually reduce boilerplate and validate +selector coverage, ABI synchronization, and registry entries. The compatibility +rules should remain explicit even if their enforcement becomes automated. + +## Summary + +Precompiles are a long-lived contract between Subtensor and deployed EVM code. +Keep addresses and released selectors stable, version functions additively, +preserve old semantics whenever possible, and replace raw storage access with +typed views that insulate callers from storage layouts. Use deprecation to guide +migration and reversible disablement to handle operational risk; report both +through a common status model without treating them as the same condition. diff --git a/docs/guides/evm/precompiles/account-balance.mdx b/docs/guides/evm/precompiles/account-balance.mdx new file mode 100644 index 0000000000..a665cd574a --- /dev/null +++ b/docs/guides/evm/precompiles/account-balance.mdx @@ -0,0 +1,32 @@ +--- +title: Account balance +description: Reference for the deployed BalancePrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `BalancePrecompile` | +| Solidity interface | `IBalance` | +| Address | `0x000000000000000000000000000000000000080e` | +| Status | Deployed | + +## Functions + +| Function | Mutability | +|---|---| +| `getFreeBalance(bytes32)` | `view` | + +## Added operations + +| Function | Source extrinsic | +|---|---| +| `burnBalance` | `Balances.burn` | +| `upgradeAccounts` | `Balances.upgrade_accounts` | + +`upgradeAccounts` has an explicit input bound of 64 accounts. Both operations +dispatch the highest-level Balances call as the mapped signer and preserve all +runtime authorization and issuance invariants. Force operations require Root +and are not exposed. + + +Source: [`balance.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balance.sol) diff --git a/docs/guides/evm/precompiles/alpha.mdx b/docs/guides/evm/precompiles/alpha.mdx new file mode 100644 index 0000000000..05b4fb2b2e --- /dev/null +++ b/docs/guides/evm/precompiles/alpha.mdx @@ -0,0 +1,54 @@ +--- +title: Alpha +description: Reference for the deployed AlphaPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `AlphaPrecompile` | +| Solidity interface | `IAlpha` | +| Address | `0x0000000000000000000000000000000000000808` | +| Status | Deployed | + +Provides typed views of subnet pools, prices, issuance, emissions, and simulated +swaps. All functions are `view`. + +## Functions + +```text +getAlphaPrice(uint16) +getMovingAlphaPrice(uint16) +getTaoInPool(uint16) +getAlphaInPool(uint16) +getAlphaOutPool(uint16) +getAlphaIssuance(uint16) +getTaoWeight() +simSwapTaoForAlpha(uint16,uint64) +simSwapAlphaForTao(uint16,uint64) +getSubnetMechanism(uint16) +getRootNetuid() +getEMAPriceHalvingBlocks(uint16) +getSubnetVolume(uint16) +getTaoInEmission(uint16) +getAlphaInEmission(uint16) +getAlphaOutEmission(uint16) +getSumAlphaPrice() +getCKBurn() +``` + +## Added operations + +| Function | Source extrinsic | +|---|---| +| `setRecycleOrBurn` | `AdminUtils.sudo_set_recycle_or_burn` | +| `setBurnHalfLife` | `AdminUtils.sudo_set_burn_half_life` | +| `setBurnIncreaseMultiplier` | `AdminUtils.sudo_set_burn_increase_mult` | + +The five deprecated `Swap` liquidity extrinsics are intentionally not proposed; +they always return the pallet's `Deprecated` error. `Swap.set_fee_rate` and the +remaining Alpha-related AdminUtils calls require Root and are not exposed. +The three listed AdminUtils calls accept a signed subnet owner; only that +signed path is exposed and runtime authorization remains in force. + + +Source: [`alpha.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/alpha.sol) diff --git a/docs/guides/evm/precompiles/balance-transfer.mdx b/docs/guides/evm/precompiles/balance-transfer.mdx new file mode 100644 index 0000000000..b94532ccf9 --- /dev/null +++ b/docs/guides/evm/precompiles/balance-transfer.mdx @@ -0,0 +1,37 @@ +--- +title: Balance transfer +description: Reference for the deployed BalanceTransferPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `BalanceTransferPrecompile` | +| Solidity interface | `ISubtensorBalanceTransfer` | +| Address | `0x0000000000000000000000000000000000000800` | +| Status | Deployed | + +Transfers the EVM call value to the Substrate account supplied as a 32-byte +public key. + +## Functions + +| Function | Mutability | +|---|---| +| `transfer(bytes32)` | `payable` | + +## Added operations + +| Function | Source extrinsic | +|---|---| +| `transferKeepAlive` | `Balances.transfer_keep_alive` | +| `transferAll` | `Balances.transfer_all` | + +The existing `transfer(bytes32)` semantically covers +`Balances.transfer_allow_death` by taking the amount from attached EVM value. +The added functions use explicit typed arguments where attached value does +not express the complete source operation. They dispatch the highest-level +Balances call as the mapped signer. `force_transfer` requires Root and the +feature-gated development faucet is not part of the production interface. + + +Source: [`balanceTransfer.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balanceTransfer.sol) diff --git a/docs/guides/evm/precompiles/crowdloan.mdx b/docs/guides/evm/precompiles/crowdloan.mdx new file mode 100644 index 0000000000..5684ff5a3f --- /dev/null +++ b/docs/guides/evm/precompiles/crowdloan.mdx @@ -0,0 +1,46 @@ +--- +title: Crowdloan +description: Reference for the deployed CrowdloanPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `CrowdloanPrecompile` | +| Solidity interface | `ICrowdloan` | +| Address | `0x0000000000000000000000000000000000000809` | +| Status | Deployed | + +## Views + +```text +getCrowdloan(uint32) +getContribution(uint32,bytes32) +``` + +## Operations + +All operations are `payable`: + +```text +create(uint64,uint64,uint64,uint32,address) +contribute(uint32,uint64) +withdraw(uint32) +finalize(uint32) +refund(uint32) +dissolve(uint32) +updateMinContribution(uint32,uint64) +updateEnd(uint32,uint32) +updateCap(uint32,uint64) +``` + +## Added operation + +| Function | Source extrinsic | +|---|---| +| `setMaxContribution` | `Crowdloan.set_max_contribution` | + +The typed interface preserves the source call's optional value so the creator +can either set or clear the per-contributor maximum. + + +Source: [`crowdloan.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/crowdloan.sol) diff --git a/docs/guides/evm/precompiles/drand.mdx b/docs/guides/evm/precompiles/drand.mdx new file mode 100644 index 0000000000..ebfbf778af --- /dev/null +++ b/docs/guides/evm/precompiles/drand.mdx @@ -0,0 +1,38 @@ +--- +title: Drand +description: Typed EVM interface for stored Drand randomness. +--- + +| Property | Value | +|---|---| +| Implementation | `DrandPrecompile` | +| Solidity interface | `IDrand` | +| Address | `0x0000000000000000000000000000000000000810` | +| Status | Deployed | + +This precompile exposes typed beacon configuration and pulse data instead +of requiring callers to construct Drand storage keys and decode SCALE values. +Contracts can use the runtime's stored randomness state deterministically +without receiving permission to configure the beacon or submit pulses. + +## Views + +| Function | Replaces | +|---|---| +| `getBeaconConfig()` | `Drand.BeaconConfig` | +| `getPulse(uint64 round)` | `Drand.Pulses` | +| `getStoredRoundRange()` | `Drand.OldestStoredRound` and `Drand.LastStoredRound` | +| `getNextUnsignedAt()` | `Drand.NextUnsignedAt` | +| `hasMigrationRun(bytes key)` | `Drand.HasMigrationRun` | + +## State-changing operations + +`Drand.set_beacon_config` and `Drand.set_oldest_stored_round` require Root, and +`Drand.write_pulse` requires `None` origin as an unsigned offchain-worker +submission. None is exposed as a typed EVM operation because doing so would +bypass the pallet's top-level origin checks. + +`hasMigrationRun(bytes)` bounds the supplied key to 128 bytes before reading +storage. + +Source: [`drand.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/drand.sol) diff --git a/docs/guides/evm/precompiles/extrinsic-coverage.mdx b/docs/guides/evm/precompiles/extrinsic-coverage.mdx new file mode 100644 index 0000000000..ce41488e86 --- /dev/null +++ b/docs/guides/evm/precompiles/extrinsic-coverage.mdx @@ -0,0 +1,86 @@ +--- +title: Extrinsic coverage +description: Audit of typed EVM coverage for every extrinsic in the authorized runtime pallets. +--- + +This audit covers the runtime's `SubtensorModule`, `AdminUtils`, `Balances`, +`Proxy`, `Scheduler`, `Drand`, `Crowdloan`, `Timestamp`, and `Swap` pallets. +Sudo and Multisig extrinsics are intentionally outside typed precompile +coverage. + +Generic SCALE dispatch through the Frontier `Dispatch` precompile does not +count as typed coverage. A covered operation must have a stable Solidity +interface or an explicit proposed typed replacement. + +## Coverage summary + +| Pallet | Runtime extrinsics | Typed today | Proposed signed additions | Not exposed | +|---|---:|---:|---:|---:| +| `SubtensorModule` | 82 | 68 | 0 | 14 | +| `AdminUtils` | 86 | 40 | 0 | 46 | +| `Balances` | 9 | 5 | 0 | 4 | +| `Proxy` | 12 | 11 | 1 | 0 | +| `Scheduler` | 10 | 0 | 0 | 10 | +| `Drand` | 3 | 0 | 0 | 3 | +| `Crowdloan` | 10 | 10 | 0 | 0 | +| `Timestamp` | 1 | 0 | 0 | 1 | +| `Swap` | 6 | 0 | 0 | 6 | +| **Total** | **219** | **134** | **1** | **84** | + +`Typed today` counts semantic coverage, not only direct dispatch to the same +Rust call. For example, `registerNetwork(bytes32)` covers basic subnet +registration by dispatching `register_network_with_identity` with empty +identity fields. + +`Proposed signed additions` includes extrinsics whose highest-level pallet call +accepts a non-Root signed origin. If a call also accepts Root, only its signed +path is exposed: the mapped EVM caller is dispatched as `Signed`, and the +pallet performs its normal authorization checks. + +## Signed additions + +Each implemented operation is listed on the page of its target precompile: + +| Target precompile | Missing extrinsics assigned | +|---|---:| +| [Subnet](/docs/guides/evm/precompiles/subnet) | 13 | +| [Staking V2](/docs/guides/evm/precompiles/staking-v2) | 20 | +| [Neuron](/docs/guides/evm/precompiles/neuron) | 21 | +| [Alpha](/docs/guides/evm/precompiles/alpha) | 3 | +| [Account balance](/docs/guides/evm/precompiles/account-balance) | 2 | +| [Proxy](/docs/guides/evm/precompiles/proxy) | 4 | +| [Balance transfer](/docs/guides/evm/precompiles/balance-transfer) | 2 | +| [Voting power](/docs/guides/evm/precompiles/voting-power) | 2 | +| [Leasing](/docs/guides/evm/precompiles/leasing) | 1 | +| [Crowdloan](/docs/guides/evm/precompiles/crowdloan) | 1 | + +The only remaining proposed signed operation is `Proxy.proxy_announced`. It +requires a stable, versioned EVM description of the proxied runtime call and +must not add another SCALE-encoded `RuntimeCall` interface. + +## Extrinsics not exposed as EVM calls + +| Pallet extrinsic | Reason | +|---|---| +| Root-only `SubtensorModule` extrinsics | `dissolve_network`, `root_dissolve_network`, `swap_coldkey`, `sudo_set_tx_childkey_take_rate_limit`, `sudo_set_min_childkey_take`, `sudo_set_max_childkey_take`, `set_pending_childkey_cooldown`, `reset_coldkey_swap`, `sudo_set_num_root_claims`, and `sudo_set_voting_power_ema_alpha` require Root. | +| `SubtensorModule.schedule_swap_coldkey` | Deprecated compatibility call that always returns `Deprecated`. | +| `SubtensorModule.faucet` | Build-feature-only development call; it is not part of the production runtime interface. | +| `SubtensorModule.set_tempo` | Retained call-index compatibility entry point that succeeds without changing state. The real setting is exposed as `SubnetPrecompile.setTempo` through `AdminUtils.sudo_set_tempo`. | +| `SubtensorModule.set_activity_cutoff_factor` | Retained call-index compatibility entry point that succeeds without changing state. The active AdminUtils operation is already covered by `SubnetPrecompile.setActivityCutoffFactor`. | +| Root-only `AdminUtils` extrinsics | Root-only administration is not delegated to EVM callers. For calls that also accept a signed subnet owner, the domain precompile dispatches the highest-level call as the mapped EVM signer and preserves its authorization checks. | +| `AdminUtils.sudo_set_total_issuance` | Deprecated call that always returns `Deprecated`. | +| Root-only `Balances` extrinsics | `force_unreserve`, `force_transfer`, `force_set_balance`, and `force_adjust_total_issuance` require Root. | +| All `Scheduler` extrinsics | `Scheduler.ScheduleOrigin` is configured as Root in the runtime. | +| `Drand.write_pulse` | Unsigned offchain-worker submission requiring `None` origin. An EVM caller cannot satisfy that origin without changing its security model. | +| Drand configuration extrinsics | `set_beacon_config` and `set_oldest_stored_round` require Root. | +| `Timestamp.set` | Block-production inherent requiring `None` origin. Contracts already receive the same time through `block.timestamp`. | +| `Swap.set_fee_rate` | Requires Root. | +| `Swap.add_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | +| `Swap.remove_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | +| `Swap.modify_position` | Permanently disabled pallet call that always returns `Deprecated`. | +| `Swap.toggle_user_liquidity` | Permanently disabled pallet call that always returns `Deprecated`. | +| `Swap.disable_lp` | Permanently disabled pallet call that always returns `Deprecated`. | + +These exclusions preserve the existing runtime origin and lifecycle semantics. +A typed precompile must not manufacture Root or `None`, call an internal helper, +or write storage directly to make one of these operations callable. diff --git a/docs/guides/evm/precompiles/index.mdx b/docs/guides/evm/precompiles/index.mdx new file mode 100644 index 0000000000..6a264d9b98 --- /dev/null +++ b/docs/guides/evm/precompiles/index.mdx @@ -0,0 +1,66 @@ +--- +title: Precompiles +description: Addresses, implementations, and reference pages for Bittensor EVM precompiles. +--- + +Bittensor precompiles are fixed-address contracts implemented by the Subtensor +runtime. `Deployed` means that the address is registered in the current runtime; +it does not imply complete coverage of the underlying runtime domain. +`Proposed` precompiles are not callable. Their documented addresses are +reserved for those domains, while their function selectors remain provisional +until the interfaces are implemented and released. + +The [extrinsic coverage audit](/docs/guides/evm/precompiles/extrinsic-coverage) +tracks every runtime extrinsic in scope and identifies its deployed, proposed, +or intentionally non-callable EVM treatment. + +## Ethereum and Frontier precompiles + +| Precompile | Address | Status | +|---|---|---| +| `ECRecover` | | Deployed | +| `Sha256` | | Deployed | +| `Ripemd160` | | Deployed | +| `Identity` | | Deployed | +| `Modexp` | | Deployed | +| `Dispatch` | | Deployed | +| `Bn128Mul` | | Deployed | +| `Bn128Pairing` | | Deployed | +| `Bn128Add` | | Deployed | +| `Sha3FIPS256` | | Deployed | +| `ECRecoverPublicKey` | | Deployed | +| `Ed25519Verify` | | Deployed | +| `Sr25519Verify` | | Deployed | + +## Bittensor precompiles + +| Precompile | Solidity interface | Details | +|---|---|---| +| [`BalanceTransferPrecompile`](/docs/guides/evm/precompiles/balance-transfer) | `ISubtensorBalanceTransfer` |
Deployed | +| [`StakingPrecompile`](/docs/guides/evm/precompiles/staking-v1) | `IStaking` V1 |
Deployed | +| [`MetagraphPrecompile`](/docs/guides/evm/precompiles/metagraph) | `IMetagraph` |
Deployed | +| [`SubnetPrecompile`](/docs/guides/evm/precompiles/subnet) | `ISubnet` |
Deployed | +| [`NeuronPrecompile`](/docs/guides/evm/precompiles/neuron) | `INeuron` |
Deployed | +| [`StakingPrecompileV2`](/docs/guides/evm/precompiles/staking-v2) | `IStaking` V2 |
Deployed | +| [`UidLookupPrecompile`](/docs/guides/evm/precompiles/uid-lookup) | `IUidLookup` |
Deployed | +| [`StorageQueryPrecompile`](/docs/guides/evm/precompiles/storage-query) | Selectorless |
Deployed · deprecation planned | +| [`AlphaPrecompile`](/docs/guides/evm/precompiles/alpha) | `IAlpha` |
Deployed | +| [`CrowdloanPrecompile`](/docs/guides/evm/precompiles/crowdloan) | `ICrowdloan` |
Deployed | +| [`LeasingPrecompile`](/docs/guides/evm/precompiles/leasing) | `ILeasing` |
Deployed | +| [`ProxyPrecompile`](/docs/guides/evm/precompiles/proxy) | `IProxy` |
Deployed | +| [`AddressMappingPrecompile`](/docs/guides/evm/precompiles/address-mapping) | `IAddressMapping` |
Deployed | +| [`VotingPowerPrecompile`](/docs/guides/evm/precompiles/voting-power) | `IVotingPower` |
Deployed | +| [`BalancePrecompile`](/docs/guides/evm/precompiles/account-balance) | `IBalance` |
Deployed | +| [`SchedulerPrecompile`](/docs/guides/evm/precompiles/scheduler) | `IScheduler` |
Deployed | +| [`DrandPrecompile`](/docs/guides/evm/precompiles/drand) | `IDrand` |
Deployed | +| [`TimestampPrecompile`](/docs/guides/evm/precompiles/timestamp) | `ITimestamp` |
Deployed | +| [`RuntimeConfigurationPrecompile`](/docs/guides/evm/precompiles/runtime-configuration) | `IRuntimeConfiguration` |
Deployed | +| [`PrecompileRegistry`](/docs/guides/evm/precompiles/registry) | `IPrecompileRegistry` |
Deployed | + +Projects that need proactive event delivery should use +[project-scoped event relays](/docs/guides/evm/precompile-design#project-scoped-event-relays) +instead of protocol-level event-reporting precompiles. + +Released addresses and selectors remain reserved permanently. The compatibility +and lifecycle rules are documented in +[Precompile design and lifecycle](/docs/guides/evm/precompile-design). diff --git a/docs/guides/evm/precompiles/leasing.mdx b/docs/guides/evm/precompiles/leasing.mdx new file mode 100644 index 0000000000..2550312355 --- /dev/null +++ b/docs/guides/evm/precompiles/leasing.mdx @@ -0,0 +1,39 @@ +--- +title: Leasing +description: Reference for the deployed LeasingPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `LeasingPrecompile` | +| Solidity interface | `ILeasing` | +| Address | `0x000000000000000000000000000000000000080a` | +| Status | Deployed | + +## Views + +```text +getLease(uint32) +getContributorShare(uint32,bytes32) +getLeaseIdForSubnet(uint16) +``` + +## Operations + +```text +createLeaseCrowdloan(uint64,uint64,uint64,uint32,uint8,bool,uint32) +terminateLease(uint32,bytes32) +``` + +Both operations are `payable`. + +## Added operation + +| Function | Source extrinsic | +|---|---| +| `startCall` | `SubtensorModule.start_call` | + +`startCall` accepts a signed subnet owner. The Root-only start-call delay +configuration is not exposed. + +Source: [`leasing.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/leasing.sol) diff --git a/docs/guides/evm/precompiles/metagraph.mdx b/docs/guides/evm/precompiles/metagraph.mdx new file mode 100644 index 0000000000..f463c35454 --- /dev/null +++ b/docs/guides/evm/precompiles/metagraph.mdx @@ -0,0 +1,45 @@ +--- +title: Metagraph +description: Reference for the deployed MetagraphPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `MetagraphPrecompile` | +| Solidity interface | `IMetagraph` | +| Address | `0x0000000000000000000000000000000000000802` | +| Status | Deployed | + +Provides typed views of per-neuron metagraph values. + +## Functions + +All functions are `view`: + +```text +getUidCount(uint16) +getStake(uint16,uint16) +getRank(uint16,uint16) +getTrust(uint16,uint16) +getConsensus(uint16,uint16) +getIncentive(uint16,uint16) +getDividends(uint16,uint16) +getEmission(uint16,uint16) +getVtrust(uint16,uint16) +getValidatorStatus(uint16,uint16) +getLastUpdate(uint16,uint16) +getIsActive(uint16,uint16) +getAxon(uint16,uint16) +getHotkey(uint16,uint16) +getColdkey(uint16,uint16) +``` + +## Proposed bulk runtime API + +`SubnetInfoRuntimeApi.get_all_metagraphs` remains proposed. Its current result +can grow with the number and size of subnets, so no Solidity selector is +assigned in this change. Before implementation, it needs a bounded +cursor-based or indexed interface with stable typed metadata. The deployed +per-subnet and per-UID views above are unchanged. + +Source: [`metagraph.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/metagraph.sol) diff --git a/docs/guides/evm/precompiles/neuron.mdx b/docs/guides/evm/precompiles/neuron.mdx new file mode 100644 index 0000000000..d0c6ff1d12 --- /dev/null +++ b/docs/guides/evm/precompiles/neuron.mdx @@ -0,0 +1,78 @@ +--- +title: Neuron +description: Reference for the deployed NeuronPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `NeuronPrecompile` | +| Solidity interface | `INeuron` | +| Address | `0x0000000000000000000000000000000000000804` | +| Status | Deployed | + +Registers neurons, publishes serving endpoints, and submits weights. Every +function is `payable`. + +## Functions + +```text +burnedRegister(uint16,bytes32) +registerLimit(uint16,bytes32,uint64) +serveAxon(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8) +serveAxonTls(uint16,uint32,uint128,uint16,uint8,uint8,uint8,uint8,bytes) +servePrometheus(uint16,uint32,uint128,uint16,uint8) +setWeights(uint16,uint16[],uint16[],uint64) +commitWeights(uint16,bytes32) +revealWeights(uint16,uint16[],uint16[],uint16[],uint64) +``` + +## Added weight operations + +| Function | Source extrinsic | +|---|---| +| `setMechanismWeights` | `SubtensorModule.set_mechanism_weights` | +| `batchSetWeights` | `SubtensorModule.batch_set_weights` | +| `commitMechanismWeights` | `SubtensorModule.commit_mechanism_weights` | +| `batchCommitWeights` | `SubtensorModule.batch_commit_weights` | +| `revealMechanismWeights` | `SubtensorModule.reveal_mechanism_weights` | +| `commitCrv3MechanismWeights` | `SubtensorModule.commit_crv3_mechanism_weights` | +| `batchRevealWeights` | `SubtensorModule.batch_reveal_weights` | +| `commitTimelockedWeights` | `SubtensorModule.commit_timelocked_weights` | +| `commitTimelockedMechanismWeights` | `SubtensorModule.commit_timelocked_mechanism_weights` | + +Batch calls accept at most 16 outer items and at most 4,096 weight entries per +inner array. Timelocked commits and registration work are bounded to 5,000 and +64 bytes respectively; none of these functions accepts SCALE-encoded runtime +calls. + +## Added registration and key operations + +| Function | Source extrinsic | +|---|---| +| `register` | `SubtensorModule.register` | +| `rootRegister` | `SubtensorModule.root_register` | +| `swapHotkey` | `SubtensorModule.swap_hotkey` | +| `swapHotkeyV2` | `SubtensorModule.swap_hotkey_v2` | +| `setChildren` | `SubtensorModule.set_children` | +| `setIdentity` | `SubtensorModule.set_identity` | +| `tryAssociateHotkey` | `SubtensorModule.try_associate_hotkey` | +| `associateEvmKey` | `SubtensorModule.associate_evm_key` | +| `announceColdkeySwap` | `SubtensorModule.announce_coldkey_swap` | +| `executeAnnouncedColdkeySwap` | `SubtensorModule.swap_coldkey_announced` | +| `disputeColdkeySwap` | `SubtensorModule.dispute_coldkey_swap` | +| `clearColdkeySwapAnnouncement` | `SubtensorModule.clear_coldkey_swap_announcement` | + +Every added operation accepts a non-Root signed origin. The precompile +dispatches the highest-level extrinsic as the mapped caller so runtime +authorization remains in force. Root-only and deprecated compatibility calls +are classified in the [coverage audit](./extrinsic-coverage). + +## Proposed bulk runtime API + +`NeuronInfoRuntimeApi.get_neurons` remains proposed. Its current result can +grow with subnet size, so no Solidity selector is assigned in this change. +Before implementation, it needs a bounded cursor-based or indexed interface +with a stable typed result. Existing single-neuron and per-field views remain +available through the deployed Neuron and Metagraph precompiles. + +Source: [`neuron.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/neuron.sol) diff --git a/docs/guides/evm/precompiles/proxy.mdx b/docs/guides/evm/precompiles/proxy.mdx new file mode 100644 index 0000000000..c8791f4732 --- /dev/null +++ b/docs/guides/evm/precompiles/proxy.mdx @@ -0,0 +1,47 @@ +--- +title: Proxy +description: Reference for the deployed ProxyPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `ProxyPrecompile` | +| Solidity interface | `IProxy` | +| Address | `0x000000000000000000000000000000000000080b` | +| Status | Deployed | + +## Functions + +| Function | Mutability | +|---|---| +| `createPureProxy(uint8,uint32,uint16)` | nonpayable | +| `proxyCall(bytes32,uint8[],uint8[])` | nonpayable | +| `killPureProxy(bytes32,uint8,uint16,uint32,uint32)` | nonpayable | +| `addProxy(bytes32,uint8,uint32)` | nonpayable | +| `removeProxy(bytes32,uint8,uint32)` | nonpayable | +| `removeProxies()` | nonpayable | +| `pokeDeposit()` | nonpayable | +| `getProxies(bytes32)` | `view` | + +## Added operations + +| Function | Source extrinsic | +|---|---| +| `announce` | `Proxy.announce` | +| `removeAnnouncement` | `Proxy.remove_announcement` | +| `rejectAnnouncement` | `Proxy.reject_announcement` | +| `setRealPaysFee` | `Proxy.set_real_pays_fee` | + +## Proposed operation + +| Function | Source extrinsic | +|---|---| +| `proxyAnnounced` | `Proxy.proxy_announced` | + +`proxyAnnounced` must use the same versioned, stable EVM call description as +other typed proxy execution. A new interface must not introduce another +dependency on SCALE-encoded `RuntimeCall`. + +No selector is reserved for `proxyAnnounced`. + +Source: [`proxy.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/proxy.sol) diff --git a/docs/guides/evm/precompiles/registry.mdx b/docs/guides/evm/precompiles/registry.mdx new file mode 100644 index 0000000000..5a0ca38ef0 --- /dev/null +++ b/docs/guides/evm/precompiles/registry.mdx @@ -0,0 +1,44 @@ +--- +title: Precompile registry +description: Registry for precompile lifecycle and availability. +--- + +| Property | Value | +|---|---| +| Implementation | `PrecompileRegistry` | +| Solidity interface | `IPrecompileRegistry` | +| Address | `0x0000000000000000000000000000000000000813` | +| Status | Deployed | + +The registry provides function-level lifecycle metadata and the current +operational availability of the containing precompile. Contracts, deployment +tools, and frontends can inspect whether a selector is deprecated, has a +replacement, or is currently unavailable without attempting the affected call. + +## Interface + +```solidity +interface IPrecompileRegistry { + struct PrecompileStatus { + bool isDeprecated; + bool isDisabled; + address newPrecompile; + bytes4 newSelector; + string message; + } + + function getPrecompileStatus( + address precompile, + bytes4 selector + ) external view returns (PrecompileStatus memory); +} +``` + +`AdminUtils.sudo_toggle_evm_precompile` is Root-only and is not exposed by this +precompile. The registry reports availability but does not grant callers +permission to change it. + +The lifecycle model is described in +[Precompile design and lifecycle](/docs/guides/evm/precompile-design#discovering-status). + +Source: [`registry.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/registry.sol) diff --git a/docs/guides/evm/precompiles/runtime-configuration.mdx b/docs/guides/evm/precompiles/runtime-configuration.mdx new file mode 100644 index 0000000000..1bf2650600 --- /dev/null +++ b/docs/guides/evm/precompiles/runtime-configuration.mdx @@ -0,0 +1,38 @@ +--- +title: Runtime configuration +description: Typed EVM views for global runtime configuration. +--- + +| Property | Value | +|---|---| +| Implementation | `RuntimeConfigurationPrecompile` | +| Solidity interface | `IRuntimeConfiguration` | +| Address | `0x0000000000000000000000000000000000000812` | +| Status | Deployed | + +This domain contains bounded typed views of global runtime +configuration that do not belong to subnet, staking, Alpha, account-balance, +or precompile-lifecycle domains. + +## Views + +| Function | Meaning | +|---|---| +| `getEvmChainId()` | Current EVM chain identifier | +| `getTransactionRateLimit()` | Global Subtensor transaction rate limit | + +## State-changing operations + +The currently identified global configuration extrinsics are Root-only: + +```text +AdminUtils.swap_authorities +AdminUtils.sudo_set_tx_rate_limit +AdminUtils.sudo_set_evm_chain_id +AdminUtils.schedule_grandpa_change +``` + +They are not exposed as typed EVM operations. A future view must return a +typed, bounded representation and must not expose SCALE-encoded runtime values. + +Source: [`runtimeConfiguration.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/runtimeConfiguration.sol) diff --git a/docs/guides/evm/precompiles/scheduler.mdx b/docs/guides/evm/precompiles/scheduler.mdx new file mode 100644 index 0000000000..662c8c6b95 --- /dev/null +++ b/docs/guides/evm/precompiles/scheduler.mdx @@ -0,0 +1,40 @@ +--- +title: Scheduler +description: Typed EVM interface for Scheduler metadata. +--- + +| Property | Value | +|---|---| +| Implementation | `SchedulerPrecompile` | +| Solidity interface | `IScheduler` | +| Address | `0x000000000000000000000000000000000000080f` | +| Status | Deployed | + +This precompile replaces raw reads of Scheduler storage with a stable EVM +interface. It lets contracts inspect whether and when runtime work is +scheduled without decoding Scheduler storage or acquiring permission to modify +the schedule. + +## Views + +| Function | Replaces | +|---|---| +| `getIncompleteSince()` | `Scheduler.IncompleteSince` | +| `getScheduledCall(uint64 when,uint32 index)` | One entry of `Scheduler.Agenda` | +| `getScheduledCallCount(uint64 when)` | The bounded agenda length for a block | +| `getRetry(uint64 when,uint32 index)` | `Scheduler.Retries` | +| `getTaskAddress(bytes32 taskId)` | `Scheduler.Lookup` | + +Returning one agenda entry at a time keeps execution bounded and avoids an +unbounded array result. + +## State-changing operations + +The runtime configures `Scheduler.ScheduleOrigin` as Root. Scheduler extrinsics +therefore have no typed EVM operation: a precompile must not manufacture Root +or bypass the top-level Scheduler authorization check. + +The returned agenda entry contains stable metadata rather than a SCALE-encoded +runtime call or origin. + +Source: [`scheduler.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/scheduler.sol) diff --git a/docs/guides/evm/precompiles/staking-v2.mdx b/docs/guides/evm/precompiles/staking-v2.mdx new file mode 100644 index 0000000000..82a324be34 --- /dev/null +++ b/docs/guides/evm/precompiles/staking-v2.mdx @@ -0,0 +1,124 @@ +--- +title: Staking V2 +description: Reference for the deployed StakingPrecompileV2. +--- + +| Property | Value | +|---|---| +| Rust implementation | `StakingPrecompileV2` | +| Solidity interface | `IStaking` V2 | +| Address | `0x0000000000000000000000000000000000000805` | +| Status | Deployed | + +This is the current staking interface. The V1 address remains available for +backward compatibility. + +## Stake operations + +```text +addStake(bytes32,uint256,uint256) +addStakeLimit(bytes32,uint256,uint256,bool,uint256) +removeStake(bytes32,uint256,uint256) +removeStakeLimit(bytes32,uint256,uint256,bool,uint256) +removeStakeFull(bytes32,uint256) +removeStakeFullLimit(bytes32,uint256,uint256) +moveStake(bytes32,bytes32,uint256,uint256,uint256) +transferStake(bytes32,bytes32,uint256,uint256,uint256) +burnAlpha(bytes32,uint256,uint256) +``` + +These functions are `payable`. + +## Stake views + +```text +getStake(bytes32,bytes32,uint256) +getStakeInfoForColdkeyAndNetuid(bytes32,uint256,bytes32[]) +getTotalColdkeyStake(bytes32) +getTotalColdkeyStakeOnSubnet(bytes32,uint256) +getTotalHotkeyStake(bytes32) +getAlphaStakedValidators(bytes32,uint256) +getTotalAlphaStaked(bytes32,uint256) +getNominatorMinRequiredStake() +getDefaultMinStake() +``` + +These functions are `view`. + +## Locks and account policy + +```text +lockStake(bytes32,uint256,uint256) +moveLock(bytes32,uint256) +setPerpetualLock(uint256,bool) +setRejectLockedAlpha(bool) +getColdkeyLock(bytes32,uint256) +getHotkeyLock(bytes32,uint256) +getHotkeyConvictions(uint256,bytes32[]) +getLockRates() +getRejectLockedAlpha(bytes32) +``` + +The `get` functions are `view`; the other functions are `payable`. + +## Proxies and stake allowances + +```text +addProxy(bytes32) +removeProxy(bytes32) +approve(address,uint256,uint256) +allowance(address,address,uint256) +increaseAllowance(address,uint256,uint256) +decreaseAllowance(address,uint256,uint256) +transferStakeFrom(address,address,bytes32,uint256,uint256,uint256) +``` + +`allowance` is `view`. Refer to the published ABI for the mutability and return +encoding of the allowance mutations. + +## Added Subtensor operations + +| Function | Source extrinsic | +|---|---| +| `decreaseTake` | `SubtensorModule.decrease_take` | +| `increaseTake` | `SubtensorModule.increase_take` | +| `setChildkeyTake` | `SubtensorModule.set_childkey_take` | +| `unstakeAll` | `SubtensorModule.unstake_all` | +| `unstakeAllAlpha` | `SubtensorModule.unstake_all_alpha` | +| `swapStake` | `SubtensorModule.swap_stake` | +| `swapStakeLimit` | `SubtensorModule.swap_stake_limit` | +| `recycleAlpha` | `SubtensorModule.recycle_alpha` | +| `setColdkeyAutoStakeHotkey` | `SubtensorModule.set_coldkey_auto_stake_hotkey` | +| `claimRoot` | `SubtensorModule.claim_root` | +| `setRootClaimType` | `SubtensorModule.set_root_claim_type` | +| `setRootClaimThreshold` | `SubtensorModule.sudo_set_root_claim_threshold` | +| `addStakeBurn` | `SubtensorModule.add_stake_burn` | +| `setAutoParentDelegationEnabled` | `SubtensorModule.set_auto_parent_delegation_enabled` | +| `transferStakeAndHotkey` | `SubtensorModule.transfer_stake_and_hotkey` | +| `addCollateral` | `SubtensorModule.add_collateral` | +| `setMinCollateral` | `SubtensorModule.set_min_collateral` | + +`recycleAlpha` is distinct from deployed `burnAlpha`: recycling reduces +`SubnetAlphaOut` and Alpha issuance, while burning does not reduce +`SubnetAlphaOut`. + +## Added AdminUtils operations + +| Function | Source extrinsic | +|---|---| +| `setMinChildkeyTakePerSubnet` | `AdminUtils.sudo_set_min_childkey_take_per_subnet` | +| `setCollateralLockShare` | `AdminUtils.sudo_set_collateral_lock_share` | +| `setCollateralDrainRatio` | `AdminUtils.sudo_set_collateral_drain_ratio` | + +The listed owner-or-Root calls expose only their signed subnet-owner path. +Every operation dispatches the highest-level extrinsic as the mapped caller so +runtime authorization remains in force. + +## Proposed bulk runtime API + +`DelegateInfoRuntimeApi.get_delegates` remains proposed. Its current result can +grow with chain state, so no Solidity selector is assigned in this change. +Before implementation, it needs a bounded cursor-based or indexed interface +whose stable return type is independent of the runtime's SCALE representation. + +Source: [`stakingV2.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/stakingV2.sol) diff --git a/docs/guides/evm/precompiles/storage-query.mdx b/docs/guides/evm/precompiles/storage-query.mdx new file mode 100644 index 0000000000..dd3636ed4d --- /dev/null +++ b/docs/guides/evm/precompiles/storage-query.mdx @@ -0,0 +1,65 @@ +--- +title: Storage query +description: Reference for the deployed selectorless StorageQueryPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `StorageQueryPrecompile` | +| Solidity interface | None | +| Address | `0x0000000000000000000000000000000000000807` | +| Status | Deployed · deprecation planned | + +This precompile has no named Solidity functions or four-byte function selector. +The complete call data is interpreted as a raw Substrate storage key. It returns +the stored SCALE-encoded bytes, or empty bytes when the key does not exist. + +Only keys whose first 16 bytes match an authorized pallet prefix are accepted: +SubtensorModule, Swap, Balances, Proxy, Scheduler, Drand, Crowdloan, Sudo, +Multisig, and Timestamp. + +Raw storage access is brittle because callers depend on runtime storage names, +hashers, key formats, and SCALE encodings. + +## Planned deprecation + + + Storage Query is still deployed and callable. Deprecation is planned, but it + does not begin until suitable typed replacement coverage is available. + + +The planned lifecycle is: + +1. Add typed views for all storage currently authorized through this + precompile. +2. Soft-deprecate Storage Query. Existing calls continue to execute identically + while the registry and documentation direct new callers to typed functions. +3. Allow a documented migration window for existing contracts and tooling. +4. Hard-deprecate Storage Query so calls return a descriptive precompile error. +5. Eventually disable the precompile through the existing Root-controlled + precompile switch. + +No migration-window length or activation block has been assigned. The general +lifecycle rules are described in +[Precompile design and lifecycle](/docs/guides/evm/precompile-design#phasing-out-raw-storage-reads). + +## Replacement destinations + +Typed coverage should be completed at existing domain addresses whenever a +compatible domain already exists. A new address is proposed only when no +existing precompile has a coherent responsibility for that state. + +| Authorized storage prefix | Typed replacement | +|---|---| +| `SubtensorModule` | Extend [Staking V2](./staking-v2), [Metagraph](./metagraph), [Subnet](./subnet), [Neuron](./neuron), [Alpha](./alpha), [Leasing](./leasing), [UID lookup](./uid-lookup), [Address mapping](./address-mapping), and [Voting power](./voting-power), according to the meaning of each value. | +| `Swap` | Extend [Alpha](./alpha) with typed liquidity, fee, balancer, reservoir, initialization, and migration-status views. | +| `Balances` | Extend [Account balance](./account-balance) with typed account, issuance, lock, reserve, hold, and freeze views. | +| `Proxy` | Extend [Proxy](./proxy) with typed announcement, last-call-result, and fee-payer views. | +| `Crowdloan` | Extend [Crowdloan](./crowdloan) with typed ID, contribution-limit, current-operation, and migration-status views. | +| `Scheduler` | Use the typed [Scheduler](./scheduler) precompile. | +| `Drand` | Use the typed [Drand](./drand) precompile. | +| `Sudo` | No dedicated EVM precompile is proposed; this access must be addressed explicitly before Storage Query is deprecated. | +| `Multisig` | No dedicated EVM precompile is proposed; this access must be addressed explicitly before Storage Query is deprecated. | +| `Timestamp` | Use the typed [Timestamp](./timestamp) precompile; `getTimestamp()` is equivalent to the existing EVM `block.timestamp` value. | + +Source: [`storage_query.rs`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/storage_query.rs) diff --git a/docs/guides/evm/precompiles/subnet.mdx b/docs/guides/evm/precompiles/subnet.mdx new file mode 100644 index 0000000000..acf9f492bb --- /dev/null +++ b/docs/guides/evm/precompiles/subnet.mdx @@ -0,0 +1,134 @@ +--- +title: Subnet +description: Reference for the deployed SubnetPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `SubnetPrecompile` | +| Solidity interface | `ISubnet` | +| Address | `0x0000000000000000000000000000000000000803` | +| Status | Deployed | + +Registers subnets and exposes selected subnet configuration. State-changing +functions are `payable`. + +## Registration + +`registerNetwork` has three overloads: + +```text +registerNetwork(bytes32) +registerNetwork(bytes32,string,string,string,string,string,string,string) +registerNetwork(bytes32,string,string,string,string,string,string,string,string) +``` + +## Views + +```text +getActivityCutoff(uint16) +getActivityCutoffFactor(uint16) +getAdjustmentAlpha(uint16) +getAlphaSigmoidSteepness(uint16) +getAlphaValues(uint16) +getBondsMovingAverage(uint16) +getBondsResetEnabled(uint16) +getCommitRevealWeightsEnabled(uint16) +getCommitRevealWeightsInterval(uint16) +getDifficulty(uint16) +getImmunityPeriod(uint16) +getKappa(uint16) +getLiquidAlphaEnabled(uint16) +getMaxBurn(uint16) +getMaxDifficulty(uint16) +getMaxWeightLimit(uint16) +getMinAllowedWeights(uint16) +getMinBurn(uint16) +getMinDifficulty(uint16) +getNetworkPowRegistrationAllowed(uint16) +getNetworkRegistrationAllowed(uint16) +getNetworkRegistrationBlock(uint16) +getOwnerCutAutoLockEnabled(uint16) +getRho(uint16) +getServingRateLimit(uint16) +getWeightsSetRateLimit(uint16) +getWeightsVersionKey(uint16) +getYuma3Enabled(uint16) +isSubnetDissolving(uint16) +``` + +## Configuration + +```text +setActivityCutoff(uint16,uint16) +setActivityCutoffFactor(uint16,uint32) +setAdjustmentAlpha(uint16,uint64) +setAlphaSigmoidSteepness(uint16,uint16) +setAlphaValues(uint16,uint16,uint16) +setBondsMovingAverage(uint16,uint64) +setBondsResetEnabled(uint16,bool) +setCommitRevealWeightsEnabled(uint16,bool) +setCommitRevealWeightsInterval(uint16,uint64) +setDifficulty(uint16,uint64) +setImmunityPeriod(uint16,uint16) +setKappa(uint16,uint16) +setLiquidAlphaEnabled(uint16,bool) +setMaxDifficulty(uint16,uint64) +setMinAllowedWeights(uint16,uint16) +setMinDifficulty(uint16,uint64) +setNetworkPowRegistrationAllowed(uint16,bool) +setNetworkRegistrationAllowed(uint16,bool) +setOwnerCutAutoLockEnabled(uint16,bool) +setRho(uint16,uint16) +setServingRateLimit(uint16,uint64) +setWeightsVersionKey(uint16,uint64) +setYuma3Enabled(uint16,bool) +toggleTransfers(uint16,bool) +``` + +## Legacy no-op functions + +These released selectors remain routed but intentionally do not change state: + +```text +setWeightsSetRateLimit(uint16,uint64) +setMinBurn(uint16,uint64) +setMaxBurn(uint16,uint64) +``` + +Changing their behavior in place would break their released semantics. The +real AdminUtils operations therefore use the V2 selectors below. + +## Added subnet operations + +| Function | Source extrinsic | +|---|---| +| `setSubnetIdentity` | `SubtensorModule.set_subnet_identity` | +| `updateSubnetSymbol` | `SubtensorModule.update_symbol` | +| `triggerEpoch` | `SubtensorModule.trigger_epoch` | + +## Added AdminUtils operations + +| Function | Source extrinsic | +|---|---| +| `setBondsPenalty` | `AdminUtils.sudo_set_bonds_penalty` | +| `setMaxAllowedUids` | `AdminUtils.sudo_set_max_allowed_uids` | +| `setMaxBurnV2` | `AdminUtils.sudo_set_max_burn` | +| `setMechanismCount` | `AdminUtils.sudo_set_mechanism_count` | +| `setMechanismEmissionSplit` | `AdminUtils.sudo_set_mechanism_emission_split` | +| `setMinBurnV2` | `AdminUtils.sudo_set_min_burn` | +| `setOwnerCutEnabled` | `AdminUtils.sudo_set_owner_cut_enabled` | +| `setOwnerImmuneNeuronLimit` | `AdminUtils.sudo_set_owner_immune_neuron_limit` | +| `setTempo` | `AdminUtils.sudo_set_tempo` | +| `trimToMaxAllowedUids` | `AdminUtils.sudo_trim_to_max_allowed_uids` | + +Each listed AdminUtils call accepts a signed subnet owner as well as Root. The +precompile exposes only the signed path and dispatches the highest-level +extrinsic so owner limits, freeze windows, and other runtime checks remain in +force. Root-only calls are classified as not EVM-callable in the +[coverage audit](./extrinsic-coverage). + +These functions dispatch the listed highest-level extrinsics as the mapped +signed caller. + +Source: [`subnet.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/subnet.sol) diff --git a/docs/guides/evm/precompiles/timestamp.mdx b/docs/guides/evm/precompiles/timestamp.mdx new file mode 100644 index 0000000000..5c78dfffee --- /dev/null +++ b/docs/guides/evm/precompiles/timestamp.mdx @@ -0,0 +1,33 @@ +--- +title: Timestamp +description: Typed EVM interface for Timestamp pallet state. +--- + +| Property | Value | +|---|---| +| Implementation | `TimestampPrecompile` | +| Solidity interface | `ITimestamp` | +| Address | `0x0000000000000000000000000000000000000811` | +| Status | Deployed | + +## Views + +| Function | Replaces | +|---|---| +| `getTimestamp()` | `Timestamp.Now` | +| `wasUpdatedThisBlock()` | `Timestamp.DidUpdate` | + +`getTimestamp()` returns the same underlying time as the EVM +`block.timestamp` value. It exists here so every storage item authorized through +`StorageQueryPrecompile` has an explicit typed replacement. +`wasUpdatedThisBlock` provides the Timestamp pallet's update state without +requiring contracts to construct a storage key or decode SCALE. + +`Timestamp.set` is an inherent submitted by block production, not a public +user operation. The precompile therefore exposes no state-changing +timestamp function. + +See the complete classification in +[Extrinsic coverage](/docs/guides/evm/precompiles/extrinsic-coverage). + +Source: [`timestamp.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/timestamp.sol) diff --git a/docs/guides/evm/precompiles/voting-power.mdx b/docs/guides/evm/precompiles/voting-power.mdx new file mode 100644 index 0000000000..5e8742908e --- /dev/null +++ b/docs/guides/evm/precompiles/voting-power.mdx @@ -0,0 +1,36 @@ +--- +title: Voting power +description: Reference for the deployed VotingPowerPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `VotingPowerPrecompile` | +| Solidity interface | `IVotingPower` | +| Address | `0x000000000000000000000000000000000000080d` | +| Status | Deployed | + +All functions are `view`. + +## Functions + +```text +getVotingPower(uint16,bytes32) +isVotingPowerTrackingEnabled(uint16) +getVotingPowerDisableAtBlock(uint16) +getVotingPowerEmaAlpha(uint16) +getTotalVotingPower(uint16) +``` + +## Added operations + +| Function | Source extrinsic | +|---|---| +| `enableVotingPowerTracking` | `SubtensorModule.enable_voting_power_tracking` | +| `disableVotingPowerTracking` | `SubtensorModule.disable_voting_power_tracking` | + +Both calls accept a signed subnet owner as well as Root. The precompile exposes +only the signed path and preserves the pallet's owner checks. The Root-only EMA +configuration call is not exposed. + +Source: [`votingPower.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/votingPower.sol) diff --git a/pallets/admin-utils/src/lib.rs b/pallets/admin-utils/src/lib.rs index 25877b7820..7aa15c2a75 100644 --- a/pallets/admin-utils/src/lib.rs +++ b/pallets/admin-utils/src/lib.rs @@ -203,6 +203,16 @@ pub mod pallet { VotingPower, /// Account balance precompile AccountBalance, + /// Scheduler metadata precompile + Scheduler, + /// Drand metadata precompile + Drand, + /// Timestamp metadata precompile + Timestamp, + /// Global runtime configuration metadata precompile + RuntimeConfiguration, + /// Precompile lifecycle and availability registry + PrecompileRegistry, } #[pallet::type_value] diff --git a/pallets/drand/src/lib.rs b/pallets/drand/src/lib.rs index f92cc09236..90d50c5938 100644 --- a/pallets/drand/src/lib.rs +++ b/pallets/drand/src/lib.rs @@ -451,6 +451,13 @@ pub mod pallet { } } +impl Pallet { + /// Return the block at which the next unsigned pulse submission is accepted. + pub fn next_unsigned_at() -> BlockNumberFor { + NextUnsignedAt::::get() + } +} + impl Pallet { /// fetch the latest public pulse from the configured drand beacon /// then send a signed transaction to include it on-chain diff --git a/precompiles/Cargo.toml b/precompiles/Cargo.toml index 4c1b924ed9..8f2cd1f55f 100644 --- a/precompiles/Cargo.toml +++ b/precompiles/Cargo.toml @@ -39,7 +39,11 @@ pallet-subtensor-swap.workspace = true pallet-admin-utils.workspace = true subtensor-swap-interface.workspace = true pallet-crowdloan.workspace = true +pallet-drand.workspace = true +pallet-evm-chain-id.workspace = true pallet-shield.workspace = true +pallet-scheduler.workspace = true +pallet-timestamp.workspace = true [lints] workspace = true @@ -103,9 +107,5 @@ runtime-benchmarks = [ ] [dev-dependencies] -pallet-drand = { workspace = true, features = ["std"] } -pallet-evm-chain-id = { workspace = true, features = ["std"] } pallet-preimage = { workspace = true, features = ["std"] } -pallet-scheduler = { workspace = true, features = ["std"] } -pallet-timestamp = { workspace = true, features = ["std"] } precompile-utils = { workspace = true, features = ["std", "testing"] } diff --git a/precompiles/src/alpha.rs b/precompiles/src/alpha.rs index 9840c42575..38a5d401aa 100644 --- a/precompiles/src/alpha.rs +++ b/precompiles/src/alpha.rs @@ -2,9 +2,17 @@ use core::marker::PhantomData; use crate::PrecompileExt; use fp_evm::{ExitError, PrecompileFailure}; -use pallet_evm::{BalanceConverter, PrecompileHandle, SubstrateBalance}; +use frame_support::{ + dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}, + traits::IsSubType, +}; +use frame_system::RawOrigin; +use pallet_evm::{AddressMapping, BalanceConverter, PrecompileHandle, SubstrateBalance}; use precompile_utils::EvmResult; -use sp_runtime::{SaturatedConversion, Vec}; +use sp_runtime::{ + SaturatedConversion, Vec, + traits::{AsSystemOriginSigner, Dispatchable}, +}; use crate::PrecompileHandleExt; use sp_core::U256; @@ -18,8 +26,24 @@ where R: frame_system::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config - + pallet_evm::Config, + + pallet_evm::Config + + pallet_admin_utils::Config + + pallet_balances::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, R::AccountId: From<[u8; 32]>, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::AddressMapping: AddressMapping, { const INDEX: u64 = 2056; } @@ -30,7 +54,24 @@ where R: frame_system::Config + pallet_subtensor::Config + pallet_subtensor_swap::Config - + pallet_evm::Config, + + pallet_evm::Config + + pallet_admin_utils::Config + + pallet_balances::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, + R::AccountId: From<[u8; 32]>, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::AddressMapping: AddressMapping, { #[precompile::public("getAlphaPrice(uint16)")] #[precompile::view] @@ -251,6 +292,57 @@ where Ok(price_eth) } + + #[precompile::public("setRecycleOrBurn(uint16,uint8)")] + fn set_recycle_or_burn( + handle: &mut impl PrecompileHandle, + netuid: u16, + mode: u8, + ) -> EvmResult<()> { + let recycle_or_burn = match mode { + 0 => pallet_subtensor::RecycleOrBurnEnum::Burn, + 1 => pallet_subtensor::RecycleOrBurnEnum::Recycle, + _ => { + return Err(PrecompileFailure::Error { + exit_status: ExitError::Other("invalid recycle-or-burn mode".into()), + }); + } + }; + let caller = handle.caller_account_id::(); + let call = pallet_admin_utils::Call::::sudo_set_recycle_or_burn { + netuid: NetUid::from(netuid), + recycle_or_burn, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } + + #[precompile::public("setBurnHalfLife(uint16,uint16)")] + fn set_burn_half_life( + handle: &mut impl PrecompileHandle, + netuid: u16, + burn_half_life: u16, + ) -> EvmResult<()> { + let caller = handle.caller_account_id::(); + let call = pallet_admin_utils::Call::::sudo_set_burn_half_life { + netuid: NetUid::from(netuid), + burn_half_life, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } + + #[precompile::public("setBurnIncreaseMultiplier(uint16,uint128)")] + fn set_burn_increase_multiplier( + handle: &mut impl PrecompileHandle, + netuid: u16, + raw_multiplier: u128, + ) -> EvmResult<()> { + let caller = handle.caller_account_id::(); + let call = pallet_admin_utils::Call::::sudo_set_burn_increase_mult { + netuid: NetUid::from(netuid), + burn_increase_mult: U64F64::from_bits(raw_multiplier), + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } } #[cfg(test)] diff --git a/precompiles/src/balance.rs b/precompiles/src/balance.rs index 36b80489e3..217e36aa26 100644 --- a/precompiles/src/balance.rs +++ b/precompiles/src/balance.rs @@ -1,8 +1,14 @@ use core::marker::PhantomData; -use pallet_evm::PrecompileHandle; -use precompile_utils::EvmResult; +use frame_support::{ + dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}, + traits::{ConstU32, IsSubType}, +}; +use frame_system::RawOrigin; +use pallet_evm::{AddressMapping, PrecompileHandle}; +use precompile_utils::{EvmResult, prelude::BoundedVec}; use sp_core::{H256, U256}; +use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable}; use crate::PrecompileExt; use crate::PrecompileHandleExt; @@ -11,9 +17,26 @@ pub struct BalancePrecompile(PhantomData); impl PrecompileExt for BalancePrecompile where - R: frame_system::Config + pallet_balances::Config + pallet_evm::Config, + R: frame_system::Config + + pallet_balances::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, R::AccountId: From<[u8; 32]>, - ::Balance: Into, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::Balance: Into + TryFrom, + ::AddressMapping: AddressMapping, { const INDEX: u64 = 2062; } @@ -21,9 +44,26 @@ where #[precompile_utils::precompile] impl BalancePrecompile where - R: frame_system::Config + pallet_balances::Config + pallet_evm::Config, + R: frame_system::Config + + pallet_balances::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, R::AccountId: From<[u8; 32]>, - ::Balance: Into, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::Balance: Into + TryFrom, + ::AddressMapping: AddressMapping, { #[precompile::public("getFreeBalance(bytes32)")] #[precompile::view] @@ -32,6 +72,40 @@ where let coldkey = R::AccountId::from(coldkey.0); Ok(pallet_balances::Pallet::::free_balance(&coldkey).into()) } + + #[precompile::public("burnBalance(uint256,bool)")] + fn burn_balance( + handle: &mut impl PrecompileHandle, + amount: U256, + keep_alive: bool, + ) -> EvmResult<()> { + let caller = handle.caller_account_id::(); + let call = pallet_balances::Call::::burn { + value: amount + .try_into() + .map_err(|_| fp_evm::PrecompileFailure::Error { + exit_status: fp_evm::ExitError::Other( + "balance amount does not fit runtime".into(), + ), + })?, + keep_alive, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } + + #[precompile::public("upgradeAccounts(bytes32[])")] + fn upgrade_accounts( + handle: &mut impl PrecompileHandle, + accounts: BoundedVec>, + ) -> EvmResult<()> { + let caller = handle.caller_account_id::(); + let who = Vec::::from(accounts) + .into_iter() + .map(|account| R::AccountId::from(account.0)) + .collect(); + let call = pallet_balances::Call::::upgrade_accounts { who }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } } #[cfg(test)] diff --git a/precompiles/src/balance_transfer.rs b/precompiles/src/balance_transfer.rs index d8d10970a3..5bf66af47c 100644 --- a/precompiles/src/balance_transfer.rs +++ b/precompiles/src/balance_transfer.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use frame_support::dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}; use frame_support::traits::IsSubType; use frame_system::RawOrigin; -use pallet_evm::PrecompileHandle; +use pallet_evm::{AddressMapping, PrecompileHandle}; use precompile_utils::EvmResult; use sp_core::{H256, U256}; use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable, StaticLookup, UniqueSaturatedInto}; @@ -36,6 +36,7 @@ where + Dispatchable, <::Lookup as StaticLookup>::Source: From, ::Balance: TryFrom, + ::AddressMapping: AddressMapping, { const INDEX: u64 = 2048; } @@ -65,6 +66,7 @@ where + Dispatchable, <::Lookup as StaticLookup>::Source: From, ::Balance: TryFrom, + ::AddressMapping: AddressMapping, { #[precompile::public("transfer(bytes32)")] #[precompile::payable] @@ -84,4 +86,76 @@ where handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(Self::account_id())) } + + #[precompile::public("transferKeepAlive(bytes32,uint256)")] + fn transfer_keep_alive( + handle: &mut impl PrecompileHandle, + address: H256, + amount: U256, + ) -> EvmResult<()> { + let caller = handle.caller_account_id::(); + let call = pallet_balances::Call::::transfer_keep_alive { + dest: R::AccountId::from(address.0).into(), + value: amount + .try_into() + .map_err(|_| fp_evm::PrecompileFailure::Error { + exit_status: fp_evm::ExitError::Other( + "balance amount does not fit runtime".into(), + ), + })?, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } + + #[precompile::public("transferAll(bytes32,bool)")] + fn transfer_all( + handle: &mut impl PrecompileHandle, + address: H256, + keep_alive: bool, + ) -> EvmResult<()> { + let caller = handle.caller_account_id::(); + let call = pallet_balances::Call::::transfer_all { + dest: R::AccountId::from(address.0).into(), + keep_alive, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{ + AccountId, Runtime, addr_from_index, fund_account, mapped_account, new_test_ext, + precompiles, selector_u32, + }; + use precompile_utils::{solidity::encode_with_selector, testing::PrecompileTesterExt}; + + #[test] + fn transfer_keep_alive_dispatches_as_mapped_caller() { + new_test_ext().execute_with(|| { + let caller = addr_from_index(0x8100); + let caller_account = mapped_account(caller); + let destination = RUNTIME_DESTINATION; + fund_account(&caller_account, 1_000); + + precompiles::>() + .prepare_test( + caller, + addr_from_index(BalanceTransferPrecompile::::INDEX), + encode_with_selector( + selector_u32("transferKeepAlive(bytes32,uint256)"), + (destination, U256::from(100u64)), + ), + ) + .execute_returns(()); + + assert_eq!( + pallet_balances::Pallet::::free_balance(AccountId::from(destination.0)), + 100u64.into() + ); + }); + } + + const RUNTIME_DESTINATION: H256 = H256([0x44; 32]); } diff --git a/precompiles/src/crowdloan.rs b/precompiles/src/crowdloan.rs index 1c66d941ca..a5152d14c6 100644 --- a/precompiles/src/crowdloan.rs +++ b/precompiles/src/crowdloan.rs @@ -244,6 +244,21 @@ where handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) } + + #[precompile::public("setMaxContribution(uint32,bool,uint64)")] + fn set_max_contribution( + handle: &mut impl PrecompileHandle, + crowdloan_id: u32, + has_max_contribution: bool, + max_contribution: u64, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_crowdloan::Call::::set_max_contribution { + crowdloan_id, + new_max_contribution: has_max_contribution.then_some(max_contribution.into()), + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } } #[derive(Codec)] diff --git a/precompiles/src/drand.rs b/precompiles/src/drand.rs new file mode 100644 index 0000000000..ee98d5e821 --- /dev/null +++ b/precompiles/src/drand.rs @@ -0,0 +1,185 @@ +use core::marker::PhantomData; + +use alloc::vec::Vec; +use fp_evm::{ExitError, PrecompileFailure}; +use frame_support::BoundedVec; +use pallet_evm::PrecompileHandle; +use precompile_utils::{ + EvmResult, + prelude::{BoundedBytes, UnboundedBytes}, +}; +use sp_core::ConstU32; + +use crate::{PrecompileExt, PrecompileHandleExt}; + +type BeaconConfiguration = ( + UnboundedBytes, + u32, + u32, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, +); + +pub struct DrandPrecompile(PhantomData); + +impl PrecompileExt for DrandPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_drand::Config, + R::AccountId: From<[u8; 32]>, + frame_system::pallet_prelude::BlockNumberFor: TryInto, +{ + const INDEX: u64 = 2064; +} + +#[precompile_utils::precompile] +impl DrandPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_drand::Config, + R::AccountId: From<[u8; 32]>, + frame_system::pallet_prelude::BlockNumberFor: TryInto, +{ + #[precompile::public("getBeaconConfig()")] + #[precompile::view] + fn get_beacon_config(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + let config = pallet_drand::BeaconConfig::::get(); + Ok(( + config.public_key.into_inner().into(), + config.period, + config.genesis_time, + config.hash.into_inner().into(), + config.group_hash.into_inner().into(), + config.scheme_id.into_inner().into(), + config.metadata.beacon_id.into_inner().into(), + )) + } + + #[precompile::public("getPulse(uint64)")] + #[precompile::view] + fn get_pulse( + handle: &mut impl PrecompileHandle, + round: u64, + ) -> EvmResult<(bool, u64, UnboundedBytes, UnboundedBytes)> { + handle.record_db_reads::(1)?; + match pallet_drand::Pulses::::get(round) { + Some(pulse) => Ok(( + true, + pulse.round, + pulse.randomness.into_inner().into(), + pulse.signature.into_inner().into(), + )), + None => Ok(( + false, + round, + UnboundedBytes::default(), + UnboundedBytes::default(), + )), + } + } + + #[precompile::public("getStoredRoundRange()")] + #[precompile::view] + fn get_stored_round_range(handle: &mut impl PrecompileHandle) -> EvmResult<(u64, u64)> { + handle.record_db_reads::(2)?; + Ok(( + pallet_drand::OldestStoredRound::::get(), + pallet_drand::LastStoredRound::::get(), + )) + } + + #[precompile::public("getNextUnsignedAt()")] + #[precompile::view] + fn get_next_unsigned_at(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + pallet_drand::Pallet::::next_unsigned_at() + .try_into() + .map_err(|_| conversion_error("drand next unsigned block")) + } + + #[precompile::public("hasMigrationRun(bytes)")] + #[precompile::view] + fn has_migration_run( + handle: &mut impl PrecompileHandle, + key: BoundedBytes>, + ) -> EvmResult { + handle.record_db_reads::(1)?; + let key = BoundedVec::>::try_from(Vec::::from(key)) + .map_err(|_| conversion_error("drand migration key"))?; + Ok(pallet_drand::HasMigrationRun::::get(key)) + } +} + +fn conversion_error(field: &'static str) -> PrecompileFailure { + PrecompileFailure::Error { + exit_status: ExitError::Other(field.into()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{Runtime, addr_from_index, new_test_ext, precompiles, selector_u32}; + use precompile_utils::{ + prelude::RuntimeHelper, + solidity::{encode_return_value, encode_with_selector}, + testing::PrecompileTesterExt, + }; + + #[test] + fn address_selectors_and_empty_state_are_stable() { + new_test_ext().execute_with(|| { + assert_eq!(DrandPrecompile::::INDEX, 2064); + let precompiles = precompiles::>(); + let caller = addr_from_index(1); + let address = addr_from_index(2064); + let read_cost = RuntimeHelper::::db_read_gas_cost(); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getPulse(uint64)"), (42u64,)), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(( + false, + 42u64, + UnboundedBytes::default(), + UnboundedBytes::default(), + ))); + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getStoredRoundRange()"), ()), + ) + .with_static_call(true) + .expect_cost(read_cost.saturating_mul(2)) + .execute_returns_raw(encode_return_value((0u64, 0u64))); + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getNextUnsignedAt()"), ()), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(0u64)); + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("hasMigrationRun(bytes)"), + (BoundedBytes::>::from(Vec::::new()),), + ), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(false)); + }); + } +} diff --git a/precompiles/src/leasing.rs b/precompiles/src/leasing.rs index 5ebf03cb3c..a89d40a4b3 100644 --- a/precompiles/src/leasing.rs +++ b/precompiles/src/leasing.rs @@ -177,6 +177,15 @@ where handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(who)) } + + #[precompile::public("startCall(uint16)")] + fn start_call(handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult<()> { + let who = handle.caller_account_id::(); + let call = pallet_subtensor::Call::::start_call { + netuid: NetUid::from(netuid), + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(who)) + } } #[derive(Codec)] diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index d70c3b5eea..02dec9f5c0 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -10,6 +10,7 @@ pub use alpha::AlphaPrecompile; pub use balance::BalancePrecompile; pub use balance_transfer::BalanceTransferPrecompile; pub use crowdloan::CrowdloanPrecompile; +pub use drand::DrandPrecompile; pub use ed25519::Ed25519Verify; pub use extensions::PrecompileExt; use fp_evm::{ExitError, PrecompileFailure}; @@ -33,6 +34,9 @@ use pallet_evm_precompile_sha3fips::Sha3FIPS256; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; use pallet_subtensor_proxy as pallet_proxy; pub use proxy::ProxyPrecompile; +pub use registry::PrecompileRegistry; +pub use runtime_configuration::RuntimeConfigurationPrecompile; +pub use scheduler::SchedulerPrecompile; use sp_core::{H160, U256, crypto::ByteArray}; use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable, StaticLookup}; pub use sr25519::Sr25519Verify; @@ -40,6 +44,7 @@ pub use staking::{StakingPrecompile, StakingPrecompileV2}; pub use storage_query::StorageQueryPrecompile; pub use subnet::SubnetPrecompile; use subtensor_runtime_common::ProxyType; +pub use timestamp::TimestampPrecompile; pub use uid_lookup::UidLookupPrecompile; pub use voting_power::VotingPowerPrecompile; @@ -48,16 +53,21 @@ mod alpha; mod balance; mod balance_transfer; mod crowdloan; +mod drand; mod ed25519; mod extensions; mod leasing; mod metagraph; mod neuron; mod proxy; +mod registry; +mod runtime_configuration; +mod scheduler; mod sr25519; mod staking; mod storage_query; mod subnet; +mod timestamp; mod uid_lookup; mod voting_power; @@ -76,12 +86,19 @@ where + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + + pallet_drand::Config + + pallet_evm_chain_id::Config + + pallet_scheduler::Config + pallet_shield::Config + pallet_subtensor_proxy::Config + + pallet_timestamp::Config + Send + Sync + scale_info::TypeInfo, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, + R::Hash: AsRef<[u8]>, + ::Moment: TryInto, + pallet_scheduler::BlockNumberFor: TryFrom + TryInto, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + From> @@ -113,12 +130,19 @@ where + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + + pallet_drand::Config + + pallet_evm_chain_id::Config + + pallet_scheduler::Config + pallet_shield::Config + pallet_subtensor_proxy::Config + + pallet_timestamp::Config + Send + Sync + scale_info::TypeInfo, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, + R::Hash: AsRef<[u8]>, + ::Moment: TryInto, + pallet_scheduler::BlockNumberFor: TryFrom + TryInto, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + From> @@ -139,7 +163,7 @@ where Self(Default::default()) } - pub fn used_addresses() -> [H160; 28] { + pub fn used_addresses() -> [H160; 33] { [ hash(1), hash(2), @@ -169,6 +193,11 @@ where hash(ProxyPrecompile::::INDEX), hash(AddressMappingPrecompile::::INDEX), hash(BalancePrecompile::::INDEX), + hash(SchedulerPrecompile::::INDEX), + hash(DrandPrecompile::::INDEX), + hash(TimestampPrecompile::::INDEX), + hash(RuntimeConfigurationPrecompile::::INDEX), + hash(PrecompileRegistry::::INDEX), ] } } @@ -182,12 +211,19 @@ where + pallet_subtensor_swap::Config + pallet_proxy::Config + pallet_crowdloan::Config + + pallet_drand::Config + + pallet_evm_chain_id::Config + + pallet_scheduler::Config + pallet_shield::Config + pallet_subtensor_proxy::Config + + pallet_timestamp::Config + Send + Sync + scale_info::TypeInfo, R::AccountId: From<[u8; 32]> + ByteArray + Into<[u8; 32]>, + R::Hash: AsRef<[u8]>, + ::Moment: TryInto, + pallet_scheduler::BlockNumberFor: TryFrom + TryInto, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + From> @@ -280,6 +316,27 @@ where a if a == hash(BalancePrecompile::::INDEX) => { BalancePrecompile::::try_execute::(handle, PrecompileEnum::AccountBalance) } + a if a == hash(SchedulerPrecompile::::INDEX) => { + SchedulerPrecompile::::try_execute::(handle, PrecompileEnum::Scheduler) + } + a if a == hash(DrandPrecompile::::INDEX) => { + DrandPrecompile::::try_execute::(handle, PrecompileEnum::Drand) + } + a if a == hash(TimestampPrecompile::::INDEX) => { + TimestampPrecompile::::try_execute::(handle, PrecompileEnum::Timestamp) + } + a if a == hash(RuntimeConfigurationPrecompile::::INDEX) => { + RuntimeConfigurationPrecompile::::try_execute::( + handle, + PrecompileEnum::RuntimeConfiguration, + ) + } + a if a == hash(PrecompileRegistry::::INDEX) => { + PrecompileRegistry::::try_execute::( + handle, + PrecompileEnum::PrecompileRegistry, + ) + } _ => None, } } @@ -317,3 +374,238 @@ fn parse_slice(data: &[u8], from: usize, to: usize) -> Result<&[u8], PrecompileF }) } } + +#[cfg(test)] +mod address_and_selector_tests { + use super::*; + use crate::mock::{Runtime, selector_u32}; + use alloc::collections::BTreeSet; + use codec::Encode; + + #[test] + fn precompile_addresses_are_unique_and_new_addresses_are_locked() { + let addresses = Precompiles::::used_addresses(); + assert_eq!(addresses.len(), BTreeSet::from_iter(addresses).len()); + assert_eq!(SchedulerPrecompile::::INDEX, 2063); + assert_eq!(DrandPrecompile::::INDEX, 2064); + assert_eq!(TimestampPrecompile::::INDEX, 2065); + assert_eq!(RuntimeConfigurationPrecompile::::INDEX, 2066); + assert_eq!(PrecompileRegistry::::INDEX, 2067); + } + + #[test] + fn precompile_enable_keys_preserve_existing_scale_indices() { + let variants = [ + (PrecompileEnum::BalanceTransfer, 0), + (PrecompileEnum::Staking, 1), + (PrecompileEnum::Subnet, 2), + (PrecompileEnum::Metagraph, 3), + (PrecompileEnum::Neuron, 4), + (PrecompileEnum::UidLookup, 5), + (PrecompileEnum::Alpha, 6), + (PrecompileEnum::Crowdloan, 7), + (PrecompileEnum::Proxy, 8), + (PrecompileEnum::Leasing, 9), + (PrecompileEnum::AddressMapping, 10), + (PrecompileEnum::VotingPower, 11), + (PrecompileEnum::AccountBalance, 12), + (PrecompileEnum::Scheduler, 13), + (PrecompileEnum::Drand, 14), + (PrecompileEnum::Timestamp, 15), + (PrecompileEnum::RuntimeConfiguration, 16), + (PrecompileEnum::PrecompileRegistry, 17), + ]; + + for (variant, expected_index) in variants { + assert_eq!(variant.encode(), [expected_index]); + } + } + + #[test] + fn new_precompile_selectors_are_locked() { + for signature in [ + "getIncompleteSince()", + "getScheduledCallCount(uint64)", + "getScheduledCall(uint64,uint32)", + "getRetry(uint64,uint32)", + "getTaskAddress(bytes32)", + ] { + assert!( + scheduler::SchedulerPrecompileCall::::supports_selector(selector_u32( + signature + )), + "missing Scheduler selector {signature}" + ); + } + for signature in [ + "getBeaconConfig()", + "getPulse(uint64)", + "getStoredRoundRange()", + "getNextUnsignedAt()", + "hasMigrationRun(bytes)", + ] { + assert!( + drand::DrandPrecompileCall::::supports_selector(selector_u32(signature)), + "missing Drand selector {signature}" + ); + } + for signature in ["getTimestamp()", "wasUpdatedThisBlock()"] { + assert!( + timestamp::TimestampPrecompileCall::::supports_selector(selector_u32( + signature + )), + "missing Timestamp selector {signature}" + ); + } + for signature in ["getEvmChainId()", "getTransactionRateLimit()"] { + assert!( + runtime_configuration::RuntimeConfigurationPrecompileCall::::supports_selector( + selector_u32(signature) + ), + "missing runtime-configuration selector {signature}" + ); + } + assert!( + registry::PrecompileRegistryCall::::supports_selector(selector_u32( + "getPrecompileStatus(address,bytes4)" + )) + ); + } + + #[test] + fn added_domain_selectors_are_locked() { + for signature in [ + "transferKeepAlive(bytes32,uint256)", + "transferAll(bytes32,bool)", + ] { + assert!( + balance_transfer::BalanceTransferPrecompileCall::::supports_selector( + selector_u32(signature) + ) + ); + } + for signature in ["burnBalance(uint256,bool)", "upgradeAccounts(bytes32[])"] { + assert!( + balance::BalancePrecompileCall::::supports_selector(selector_u32( + signature + )) + ); + } + for signature in [ + "enableVotingPowerTracking(uint16)", + "disableVotingPowerTracking(uint16)", + ] { + assert!( + voting_power::VotingPowerPrecompileCall::::supports_selector( + selector_u32(signature) + ) + ); + } + assert!( + leasing::LeasingPrecompileCall::::supports_selector(selector_u32( + "startCall(uint16)" + )) + ); + assert!( + crowdloan::CrowdloanPrecompileCall::::supports_selector(selector_u32( + "setMaxContribution(uint32,bool,uint64)" + )) + ); + for signature in [ + "setRecycleOrBurn(uint16,uint8)", + "setBurnHalfLife(uint16,uint16)", + "setBurnIncreaseMultiplier(uint16,uint128)", + ] { + assert!(alpha::AlphaPrecompileCall::::supports_selector( + selector_u32(signature) + )); + } + for signature in [ + "announce(bytes32,bytes32)", + "removeAnnouncement(bytes32,bytes32)", + "rejectAnnouncement(bytes32,bytes32)", + "setRealPaysFee(bytes32,bool)", + ] { + assert!(proxy::ProxyPrecompileCall::::supports_selector( + selector_u32(signature) + )); + } + for signature in [ + "setSubnetIdentity(uint16,string,string,string,string,string,string,string,string)", + "updateSubnetSymbol(uint16,string)", + "triggerEpoch(uint16)", + "setBondsPenalty(uint16,uint16)", + "setMaxAllowedUids(uint16,uint16)", + "setMaxBurnV2(uint16,uint64)", + "setMechanismCount(uint16,uint8)", + "setMechanismEmissionSplit(uint16,bool,uint16[])", + "setMinBurnV2(uint16,uint64)", + "setOwnerCutEnabled(uint16,bool)", + "setOwnerImmuneNeuronLimit(uint16,uint16)", + "setTempo(uint16,uint16)", + "trimToMaxAllowedUids(uint16,uint16)", + ] { + assert!( + subnet::SubnetPrecompileCall::::supports_selector(selector_u32(signature)), + "missing Subnet selector {signature}" + ); + } + for signature in [ + "decreaseTake(bytes32,uint16)", + "increaseTake(bytes32,uint16)", + "setChildkeyTake(bytes32,uint16,uint16)", + "unstakeAll(bytes32)", + "unstakeAllAlpha(bytes32)", + "swapStake(bytes32,uint16,uint16,uint64)", + "swapStakeLimit(bytes32,uint16,uint16,uint64,uint64,bool)", + "recycleAlpha(bytes32,uint64,uint16)", + "setColdkeyAutoStakeHotkey(uint16,bytes32)", + "claimRoot(uint16[])", + "setRootClaimType(uint8,uint16[])", + "setRootClaimThreshold(uint16,uint64)", + "addStakeBurn(bytes32,uint16,uint64,bool,uint64)", + "setAutoParentDelegationEnabled(bytes32,bool)", + "transferStakeAndHotkey(bytes32,bytes32,bytes32,uint16,uint16,uint64)", + "addCollateral(uint16,bytes32,uint64,uint64)", + "setMinCollateral(uint16,bytes32,uint64)", + "setMinChildkeyTakePerSubnet(uint16,uint16)", + "setCollateralLockShare(uint16,uint16)", + "setCollateralDrainRatio(uint16,uint128)", + ] { + assert!( + staking::StakingPrecompileV2Call::::supports_selector(selector_u32( + signature + )), + "missing Staking V2 selector {signature}" + ); + } + for signature in [ + "setMechanismWeights(uint16,uint8,uint16[],uint16[],uint64)", + "batchSetWeights(uint16[],uint16[][],uint16[][],uint64[])", + "commitMechanismWeights(uint16,uint8,bytes32)", + "batchCommitWeights(uint16[],bytes32[])", + "revealMechanismWeights(uint16,uint8,uint16[],uint16[],uint16[],uint64)", + "commitCrv3MechanismWeights(uint16,uint8,bytes,uint64)", + "batchRevealWeights(uint16,uint16[][],uint16[][],uint16[][],uint64[])", + "commitTimelockedWeights(uint16,bytes,uint64,uint16)", + "commitTimelockedMechanismWeights(uint16,uint8,bytes,uint64,uint16)", + "register(uint16,uint64,uint64,bytes,bytes32,bytes32)", + "rootRegister(bytes32)", + "swapHotkey(bytes32,bytes32,bool,uint16)", + "swapHotkeyV2(bytes32,bytes32,bool,uint16,bool)", + "setChildren(bytes32,uint16,uint64[],bytes32[])", + "setIdentity(string,string,string,string,string,string,string)", + "tryAssociateHotkey(bytes32)", + "associateEvmKey(uint16,address,uint64,bytes)", + "announceColdkeySwap(bytes32)", + "executeAnnouncedColdkeySwap(bytes32)", + "disputeColdkeySwap()", + "clearColdkeySwapAnnouncement()", + ] { + assert!( + neuron::NeuronPrecompileCall::::supports_selector(selector_u32(signature)), + "missing Neuron selector {signature}" + ); + } + } +} diff --git a/precompiles/src/neuron.rs b/precompiles/src/neuron.rs index 8a7eac497f..82c078b5b1 100644 --- a/precompiles/src/neuron.rs +++ b/precompiles/src/neuron.rs @@ -1,13 +1,20 @@ use core::marker::PhantomData; use frame_support::dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}; -use frame_support::traits::IsSubType; +use frame_support::traits::{ConstU32, IsSubType}; use frame_system::RawOrigin; use pallet_evm::{AddressMapping, PrecompileHandle}; -use precompile_utils::{EvmResult, prelude::UnboundedBytes}; -use sp_core::H256; +use precompile_utils::{ + EvmResult, + prelude::{ + Address, BoundedBytes, BoundedString, BoundedVec as SolidityBoundedVec, UnboundedBytes, + revert, + }, +}; +use sp_core::{H256, ecdsa::Signature}; use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable}; use sp_std::vec::Vec; +use subtensor_runtime_common::{MechId, NetUid}; use crate::{PrecompileExt, PrecompileHandleExt}; @@ -386,6 +393,467 @@ where RawOrigin::Signed(handle.caller_account_id::()), ) } + + #[precompile::public("setMechanismWeights(uint16,uint8,uint16[],uint16[],uint64)")] + fn set_mechanism_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + mecid: u8, + dests: SolidityBoundedVec>, + weights: SolidityBoundedVec>, + version_key: u64, + ) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::set_mechanism_weights { + netuid: netuid.into(), + mecid: MechId::from(mecid), + dests: dests.into(), + weights: weights.into(), + version_key, + }, + ) + } + + #[precompile::public("commitMechanismWeights(uint16,uint8,bytes32)")] + fn commit_mechanism_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + mecid: u8, + commit_hash: H256, + ) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::commit_mechanism_weights { + netuid: netuid.into(), + mecid: mecid.into(), + commit_hash, + }, + ) + } + + #[precompile::public("revealMechanismWeights(uint16,uint8,uint16[],uint16[],uint16[],uint64)")] + fn reveal_mechanism_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + mecid: u8, + uids: SolidityBoundedVec>, + values: SolidityBoundedVec>, + salt: SolidityBoundedVec>, + version_key: u64, + ) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::reveal_mechanism_weights { + netuid: netuid.into(), + mecid: mecid.into(), + uids: uids.into(), + values: values.into(), + salt: salt.into(), + version_key, + }, + ) + } + + #[precompile::public("commitCrv3MechanismWeights(uint16,uint8,bytes,uint64)")] + fn commit_crv3_mechanism_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + mecid: u8, + commit: BoundedBytes>, + reveal_round: u64, + ) -> EvmResult<()> { + let commit = + frame_support::BoundedVec::>::try_from(Vec::::from(commit)) + .map_err(|_| revert("commit exceeds runtime bound"))?; + dispatch_neuron( + handle, + pallet_subtensor::Call::::commit_crv3_mechanism_weights { + netuid: netuid.into(), + mecid: mecid.into(), + commit, + reveal_round, + }, + ) + } + + #[precompile::public("commitTimelockedWeights(uint16,bytes,uint64,uint16)")] + fn commit_timelocked_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + commit: BoundedBytes>, + reveal_round: u64, + commit_reveal_version: u16, + ) -> EvmResult<()> { + let commit = + frame_support::BoundedVec::>::try_from(Vec::::from(commit)) + .map_err(|_| revert("commit exceeds runtime bound"))?; + dispatch_neuron( + handle, + pallet_subtensor::Call::::commit_timelocked_weights { + netuid: netuid.into(), + commit, + reveal_round, + commit_reveal_version, + }, + ) + } + + #[precompile::public("commitTimelockedMechanismWeights(uint16,uint8,bytes,uint64,uint16)")] + fn commit_timelocked_mechanism_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + mecid: u8, + commit: BoundedBytes>, + reveal_round: u64, + commit_reveal_version: u16, + ) -> EvmResult<()> { + let commit = + frame_support::BoundedVec::>::try_from(Vec::::from(commit)) + .map_err(|_| revert("commit exceeds runtime bound"))?; + dispatch_neuron( + handle, + pallet_subtensor::Call::::commit_timelocked_mechanism_weights { + netuid: netuid.into(), + mecid: mecid.into(), + commit, + reveal_round, + commit_reveal_version, + }, + ) + } + + #[precompile::public("batchSetWeights(uint16[],uint16[][],uint16[][],uint64[])")] + fn batch_set_weights( + handle: &mut impl PrecompileHandle, + netuids: SolidityBoundedVec>, + dests: SolidityBoundedVec>, ConstU32<16>>, + values: SolidityBoundedVec>, ConstU32<16>>, + version_keys: SolidityBoundedVec>, + ) -> EvmResult<()> { + let netuids = Vec::::from(netuids); + let dests = Vec::>>::from(dests); + let values = Vec::>>::from(values); + let version_keys = Vec::::from(version_keys); + if netuids.len() != dests.len() + || netuids.len() != values.len() + || netuids.len() != version_keys.len() + { + return Err(revert("batch weight arrays must have equal outer lengths")); + } + let mut weights = Vec::with_capacity(netuids.len()); + for (batch_dests, batch_values) in dests.into_iter().zip(values) { + let batch_dests = Vec::::from(batch_dests); + let batch_values = Vec::::from(batch_values); + if batch_dests.len() != batch_values.len() { + return Err(revert( + "batch destination and value arrays must have equal lengths", + )); + } + weights.push( + batch_dests + .into_iter() + .zip(batch_values) + .map(|(uid, value)| (codec::Compact(uid), codec::Compact(value))) + .collect(), + ); + } + dispatch_neuron( + handle, + pallet_subtensor::Call::::batch_set_weights { + netuids: netuids + .into_iter() + .map(|netuid| codec::Compact(NetUid::from(netuid))) + .collect(), + weights, + version_keys: version_keys.into_iter().map(codec::Compact).collect(), + }, + ) + } + + #[precompile::public("batchCommitWeights(uint16[],bytes32[])")] + fn batch_commit_weights( + handle: &mut impl PrecompileHandle, + netuids: SolidityBoundedVec>, + commit_hashes: SolidityBoundedVec>, + ) -> EvmResult<()> { + let netuids = Vec::::from(netuids); + let commit_hashes = Vec::::from(commit_hashes); + if netuids.len() != commit_hashes.len() { + return Err(revert( + "batch netuid and commitment arrays must have equal lengths", + )); + } + dispatch_neuron( + handle, + pallet_subtensor::Call::::batch_commit_weights { + netuids: netuids + .into_iter() + .map(|netuid| codec::Compact(NetUid::from(netuid))) + .collect(), + commit_hashes, + }, + ) + } + + #[precompile::public("batchRevealWeights(uint16,uint16[][],uint16[][],uint16[][],uint64[])")] + fn batch_reveal_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + uids_list: SolidityBoundedVec>, ConstU32<16>>, + values_list: SolidityBoundedVec>, ConstU32<16>>, + salts_list: SolidityBoundedVec>, ConstU32<16>>, + version_keys: SolidityBoundedVec>, + ) -> EvmResult<()> { + let uids_list = Vec::>>::from(uids_list); + let values_list = Vec::>>::from(values_list); + let salts_list = Vec::>>::from(salts_list); + let version_keys = Vec::::from(version_keys); + if uids_list.len() != values_list.len() + || uids_list.len() != salts_list.len() + || uids_list.len() != version_keys.len() + { + return Err(revert("batch reveal arrays must have equal outer lengths")); + } + dispatch_neuron( + handle, + pallet_subtensor::Call::::batch_reveal_weights { + netuid: netuid.into(), + uids_list: uids_list.into_iter().map(Into::into).collect(), + values_list: values_list.into_iter().map(Into::into).collect(), + salts_list: salts_list.into_iter().map(Into::into).collect(), + version_keys, + }, + ) + } + + #[precompile::public("register(uint16,uint64,uint64,bytes,bytes32,bytes32)")] + fn register( + handle: &mut impl PrecompileHandle, + netuid: u16, + block_number: u64, + nonce: u64, + work: BoundedBytes>, + hotkey: H256, + coldkey: H256, + ) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::register { + netuid: netuid.into(), + block_number, + nonce, + work: work.into(), + hotkey: hotkey.0.into(), + coldkey: coldkey.0.into(), + }, + ) + } + + #[precompile::public("rootRegister(bytes32)")] + fn root_register(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::root_register { + hotkey: hotkey.0.into(), + }, + ) + } + + #[precompile::public("swapHotkey(bytes32,bytes32,bool,uint16)")] + fn swap_hotkey( + handle: &mut impl PrecompileHandle, + hotkey: H256, + new_hotkey: H256, + has_netuid: bool, + netuid: u16, + ) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::swap_hotkey { + hotkey: hotkey.0.into(), + new_hotkey: new_hotkey.0.into(), + netuid: has_netuid.then_some(NetUid::from(netuid)), + }, + ) + } + + #[precompile::public("swapHotkeyV2(bytes32,bytes32,bool,uint16,bool)")] + fn swap_hotkey_v2( + handle: &mut impl PrecompileHandle, + hotkey: H256, + new_hotkey: H256, + has_netuid: bool, + netuid: u16, + keep_stake: bool, + ) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::swap_hotkey_v2 { + hotkey: hotkey.0.into(), + new_hotkey: new_hotkey.0.into(), + netuid: has_netuid.then_some(NetUid::from(netuid)), + keep_stake, + }, + ) + } + + #[precompile::public("setChildren(bytes32,uint16,uint64[],bytes32[])")] + fn set_children( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + proportions: SolidityBoundedVec>, + children: SolidityBoundedVec>, + ) -> EvmResult<()> { + let proportions = Vec::::from(proportions); + let children = Vec::::from(children); + if proportions.len() != children.len() { + return Err(revert( + "child proportions and hotkeys must have equal length", + )); + } + let children = proportions + .into_iter() + .zip(children) + .map(|(proportion, child)| (proportion, child.0.into())) + .collect(); + dispatch_neuron( + handle, + pallet_subtensor::Call::::set_children { + hotkey: hotkey.0.into(), + netuid: netuid.into(), + children, + }, + ) + } + + #[precompile::public("setIdentity(string,string,string,string,string,string,string)")] + #[allow(clippy::too_many_arguments)] + fn set_identity( + handle: &mut impl PrecompileHandle, + name: BoundedString>, + url: BoundedString>, + github_repo: BoundedString>, + image: BoundedString>, + discord: BoundedString>, + description: BoundedString>, + additional: BoundedString>, + ) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::set_identity { + name: name.into(), + url: url.into(), + github_repo: github_repo.into(), + image: image.into(), + discord: discord.into(), + description: description.into(), + additional: additional.into(), + }, + ) + } + + #[precompile::public("tryAssociateHotkey(bytes32)")] + fn try_associate_hotkey(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::try_associate_hotkey { + hotkey: hotkey.0.into(), + }, + ) + } + + #[precompile::public("associateEvmKey(uint16,address,uint64,bytes)")] + fn associate_evm_key( + handle: &mut impl PrecompileHandle, + netuid: u16, + evm_key: Address, + block_number: u64, + signature: BoundedBytes>, + ) -> EvmResult<()> { + let bytes = Vec::::from(signature); + let signature: [u8; 65] = bytes + .try_into() + .map_err(|_| revert("ECDSA signature must be exactly 65 bytes"))?; + dispatch_neuron( + handle, + pallet_subtensor::Call::::associate_evm_key { + netuid: netuid.into(), + evm_key: evm_key.0, + block_number, + signature: Signature::from_raw(signature), + }, + ) + } + + #[precompile::public("announceColdkeySwap(bytes32)")] + fn announce_coldkey_swap( + handle: &mut impl PrecompileHandle, + new_coldkey_hash: H256, + ) -> EvmResult<()> { + let new_coldkey_hash = codec::Decode::decode(&mut new_coldkey_hash.as_bytes()) + .map_err(|_| revert("runtime hash is not compatible with bytes32"))?; + dispatch_neuron( + handle, + pallet_subtensor::Call::::announce_coldkey_swap { new_coldkey_hash }, + ) + } + + #[precompile::public("executeAnnouncedColdkeySwap(bytes32)")] + fn execute_announced_coldkey_swap( + handle: &mut impl PrecompileHandle, + new_coldkey: H256, + ) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::swap_coldkey_announced { + new_coldkey: new_coldkey.0.into(), + }, + ) + } + + #[precompile::public("disputeColdkeySwap()")] + fn dispute_coldkey_swap(handle: &mut impl PrecompileHandle) -> EvmResult<()> { + dispatch_neuron(handle, pallet_subtensor::Call::::dispute_coldkey_swap {}) + } + + #[precompile::public("clearColdkeySwapAnnouncement()")] + fn clear_coldkey_swap_announcement(handle: &mut impl PrecompileHandle) -> EvmResult<()> { + dispatch_neuron( + handle, + pallet_subtensor::Call::::clear_coldkey_swap_announcement {}, + ) + } +} + +fn dispatch_neuron( + handle: &mut impl PrecompileHandle, + call: pallet_subtensor::Call, +) -> EvmResult<()> +where + R: frame_system::Config + + pallet_balances::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, + R::AccountId: From<[u8; 32]>, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::AddressMapping: AddressMapping, +{ + let caller = handle.caller_account_id::(); + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) } #[cfg(test)] diff --git a/precompiles/src/proxy.rs b/precompiles/src/proxy.rs index 78d59f5ce2..06a26b6476 100644 --- a/precompiles/src/proxy.rs +++ b/precompiles/src/proxy.rs @@ -291,4 +291,86 @@ where Ok(result) } + + #[precompile::public("announce(bytes32,bytes32)")] + pub fn announce( + handle: &mut impl PrecompileHandle, + real: H256, + call_hash: H256, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call_hash = DecodeLimit::decode_all_with_depth_limit(1, &mut &call_hash.as_bytes()[..]) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other( + "runtime call hash is not compatible with bytes32".into(), + ), + })?; + let call = pallet_proxy::Call::::announce { + real: <::Lookup as StaticLookup>::Source::from( + real.0.into(), + ), + call_hash, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("removeAnnouncement(bytes32,bytes32)")] + pub fn remove_announcement( + handle: &mut impl PrecompileHandle, + real: H256, + call_hash: H256, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call_hash = DecodeLimit::decode_all_with_depth_limit(1, &mut &call_hash.as_bytes()[..]) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other( + "runtime call hash is not compatible with bytes32".into(), + ), + })?; + let call = pallet_proxy::Call::::remove_announcement { + real: <::Lookup as StaticLookup>::Source::from( + real.0.into(), + ), + call_hash, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("rejectAnnouncement(bytes32,bytes32)")] + pub fn reject_announcement( + handle: &mut impl PrecompileHandle, + delegate: H256, + call_hash: H256, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call_hash = DecodeLimit::decode_all_with_depth_limit(1, &mut &call_hash.as_bytes()[..]) + .map_err(|_| PrecompileFailure::Error { + exit_status: ExitError::Other( + "runtime call hash is not compatible with bytes32".into(), + ), + })?; + let call = pallet_proxy::Call::::reject_announcement { + delegate: <::Lookup as StaticLookup>::Source::from( + delegate.0.into(), + ), + call_hash, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } + + #[precompile::public("setRealPaysFee(bytes32,bool)")] + pub fn set_real_pays_fee( + handle: &mut impl PrecompileHandle, + delegate: H256, + pays_fee: bool, + ) -> EvmResult<()> { + let account_id = handle.caller_account_id::(); + let call = pallet_proxy::Call::::set_real_pays_fee { + delegate: <::Lookup as StaticLookup>::Source::from( + delegate.0.into(), + ), + pays_fee, + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) + } } diff --git a/precompiles/src/registry.rs b/precompiles/src/registry.rs new file mode 100644 index 0000000000..8efd170e30 --- /dev/null +++ b/precompiles/src/registry.rs @@ -0,0 +1,191 @@ +use core::marker::PhantomData; + +use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; +use pallet_evm::PrecompileHandle; +use precompile_utils::{ + EvmResult, + prelude::{Address, UnboundedString}, + solidity::{ + Codec, + codec::{Reader, Writer}, + }, +}; +use sp_core::{H160, H256}; + +use crate::{PrecompileExt, PrecompileHandleExt}; + +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct Bytes4([u8; 4]); + +impl Codec for Bytes4 { + fn read(reader: &mut Reader) -> precompile_utils::solidity::revert::MayRevert { + let word = reader.read::()?; + let [a, b, c, d, ..] = word.to_fixed_bytes(); + Ok(Self([a, b, c, d])) + } + + fn write(writer: &mut Writer, value: Self) { + let mut word = [0u8; 32]; + word[..4].copy_from_slice(&value.0); + H256::write(writer, H256::from(word)); + } + + fn has_static_size() -> bool { + true + } + + fn signature() -> alloc::string::String { + "bytes4".into() + } +} + +#[derive(Codec)] +struct PrecompileStatus { + is_deprecated: bool, + is_disabled: bool, + new_precompile: Address, + new_selector: Bytes4, + message: UnboundedString, +} + +pub struct PrecompileRegistry(PhantomData); + +impl PrecompileExt for PrecompileRegistry +where + R: frame_system::Config + + pallet_admin_utils::Config + + pallet_evm::Config + + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, +{ + const INDEX: u64 = 2067; +} + +#[precompile_utils::precompile] +impl PrecompileRegistry +where + R: frame_system::Config + + pallet_admin_utils::Config + + pallet_evm::Config + + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, +{ + #[precompile::public("getPrecompileStatus(address,bytes4)")] + #[precompile::view] + fn get_precompile_status( + handle: &mut impl PrecompileHandle, + precompile: Address, + _selector: Bytes4, + ) -> EvmResult { + let is_disabled = match precompile_enum::(precompile.0) { + Some(precompile_id) => { + handle.record_db_reads::(1)?; + !PrecompileEnable::::get(precompile_id) + } + None => false, + }; + + Ok(PrecompileStatus { + is_deprecated: false, + is_disabled, + new_precompile: Address(H160::zero()), + new_selector: Bytes4::default(), + message: UnboundedString::default(), + }) + } +} + +fn precompile_enum(address: H160) -> Option +where + R: frame_system::Config + + pallet_admin_utils::Config + + pallet_evm::Config + + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, +{ + let _runtime = PhantomData::; + let at = |index| address == H160::from_low_u64_be(index); + if at(2048) { + Some(PrecompileEnum::BalanceTransfer) + } else if at(2049) || at(2053) { + Some(PrecompileEnum::Staking) + } else if at(2051) { + Some(PrecompileEnum::Subnet) + } else if at(2050) { + Some(PrecompileEnum::Metagraph) + } else if at(2052) { + Some(PrecompileEnum::Neuron) + } else if at(2054) { + Some(PrecompileEnum::UidLookup) + } else if at(2056) { + Some(PrecompileEnum::Alpha) + } else if at(2057) { + Some(PrecompileEnum::Crowdloan) + } else if at(2059) { + Some(PrecompileEnum::Proxy) + } else if at(2058) { + Some(PrecompileEnum::Leasing) + } else if at(2060) { + Some(PrecompileEnum::AddressMapping) + } else if at(2061) { + Some(PrecompileEnum::VotingPower) + } else if at(2062) { + Some(PrecompileEnum::AccountBalance) + } else if at(2063) { + Some(PrecompileEnum::Scheduler) + } else if at(2064) { + Some(PrecompileEnum::Drand) + } else if at(2065) { + Some(PrecompileEnum::Timestamp) + } else if at(2066) { + Some(PrecompileEnum::RuntimeConfiguration) + } else if at(2067) { + Some(PrecompileEnum::PrecompileRegistry) + } else { + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{Runtime, addr_from_index, new_test_ext, precompiles, selector_u32}; + use precompile_utils::{ + prelude::RuntimeHelper, + solidity::{encode_return_value, encode_with_selector}, + testing::PrecompileTesterExt, + }; + + #[test] + fn reports_reversible_disablement_at_reserved_address() { + new_test_ext().execute_with(|| { + assert_eq!(PrecompileRegistry::::INDEX, 2067); + PrecompileEnable::::insert(PrecompileEnum::Scheduler, false); + + let precompiles = precompiles::>(); + let caller = addr_from_index(1); + let registry = addr_from_index(2067); + let scheduler = Address(addr_from_index(2063)); + let selector = Bytes4(selector_u32("getIncompleteSince()").to_be_bytes()); + + precompiles + .prepare_test( + caller, + registry, + encode_with_selector( + selector_u32("getPrecompileStatus(address,bytes4)"), + (scheduler, selector), + ), + ) + .with_static_call(true) + .expect_cost(RuntimeHelper::::db_read_gas_cost()) + .execute_returns_raw(encode_return_value(PrecompileStatus { + is_deprecated: false, + is_disabled: true, + new_precompile: Address(H160::zero()), + new_selector: Bytes4::default(), + message: UnboundedString::default(), + })); + }); + } +} diff --git a/precompiles/src/runtime_configuration.rs b/precompiles/src/runtime_configuration.rs new file mode 100644 index 0000000000..72cb9fa9d8 --- /dev/null +++ b/precompiles/src/runtime_configuration.rs @@ -0,0 +1,87 @@ +use core::marker::PhantomData; + +use pallet_evm::PrecompileHandle; +use precompile_utils::EvmResult; + +use crate::{PrecompileExt, PrecompileHandleExt}; + +pub struct RuntimeConfigurationPrecompile(PhantomData); + +impl PrecompileExt for RuntimeConfigurationPrecompile +where + R: frame_system::Config + + pallet_evm::Config + + pallet_evm_chain_id::Config + + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, +{ + const INDEX: u64 = 2066; +} + +#[precompile_utils::precompile] +impl RuntimeConfigurationPrecompile +where + R: frame_system::Config + + pallet_evm::Config + + pallet_evm_chain_id::Config + + pallet_subtensor::Config, + R::AccountId: From<[u8; 32]>, +{ + #[precompile::public("getEvmChainId()")] + #[precompile::view] + fn get_evm_chain_id(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_evm_chain_id::ChainId::::get()) + } + + #[precompile::public("getTransactionRateLimit()")] + #[precompile::view] + fn get_transaction_rate_limit(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::Pallet::::get_tx_rate_limit()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{Runtime, addr_from_index, new_test_ext, precompiles, selector_u32}; + use precompile_utils::{ + prelude::RuntimeHelper, + solidity::{encode_return_value, encode_with_selector}, + testing::PrecompileTesterExt, + }; + + #[test] + fn address_selectors_and_values_are_stable() { + new_test_ext().execute_with(|| { + assert_eq!(RuntimeConfigurationPrecompile::::INDEX, 2066); + pallet_evm_chain_id::ChainId::::put(9_999u64); + pallet_subtensor::TxRateLimit::::put(77u64); + + let precompiles = precompiles::>(); + let caller = addr_from_index(1); + let address = addr_from_index(2066); + let read_cost = RuntimeHelper::::db_read_gas_cost(); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getEvmChainId()"), ()), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(9_999u64)); + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getTransactionRateLimit()"), ()), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(77u64)); + }); + } +} diff --git a/precompiles/src/scheduler.rs b/precompiles/src/scheduler.rs new file mode 100644 index 0000000000..0182240478 --- /dev/null +++ b/precompiles/src/scheduler.rs @@ -0,0 +1,256 @@ +use core::marker::PhantomData; + +use codec::{Decode, Encode}; +use fp_evm::{ExitError, PrecompileFailure}; +use pallet_evm::PrecompileHandle; +use precompile_utils::EvmResult; +use sp_core::H256; + +use crate::{PrecompileExt, PrecompileHandleExt}; + +type ScheduledCallMetadata = (bool, bool, H256, u8, H256, bool, u32, bool, u64, u32); + +pub struct SchedulerPrecompile(PhantomData); + +impl PrecompileExt for SchedulerPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_scheduler::Config, + R::AccountId: From<[u8; 32]>, + R::Hash: AsRef<[u8]>, + pallet_scheduler::BlockNumberFor: TryFrom + TryInto, +{ + const INDEX: u64 = 2063; +} + +#[precompile_utils::precompile] +impl SchedulerPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_scheduler::Config, + R::AccountId: From<[u8; 32]>, + R::Hash: AsRef<[u8]>, + pallet_scheduler::BlockNumberFor: TryFrom + TryInto, +{ + #[precompile::public("getIncompleteSince()")] + #[precompile::view] + fn get_incomplete_since(handle: &mut impl PrecompileHandle) -> EvmResult<(bool, u64)> { + handle.record_db_reads::(1)?; + match pallet_scheduler::IncompleteSince::::get() { + Some(block) => Ok((true, block_number_to_u64::(block)?)), + None => Ok((false, 0)), + } + } + + #[precompile::public("getScheduledCallCount(uint64)")] + #[precompile::view] + fn get_scheduled_call_count(handle: &mut impl PrecompileHandle, when: u64) -> EvmResult { + handle.record_db_reads::(1)?; + let agenda = pallet_scheduler::Agenda::::get(block_number_from_u64::(when)?); + u32::try_from(agenda.len()).map_err(|_| conversion_error("scheduler agenda length")) + } + + #[precompile::public("getScheduledCall(uint64,uint32)")] + #[precompile::view] + fn get_scheduled_call( + handle: &mut impl PrecompileHandle, + when: u64, + index: u32, + ) -> EvmResult { + handle.record_db_reads::(1)?; + let agenda = pallet_scheduler::Agenda::::get(block_number_from_u64::(when)?); + let Some(Some(scheduled)) = agenda + .get(usize::try_from(index).map_err(|_| conversion_error("scheduler agenda index"))?) + else { + return Ok(( + false, + false, + H256::zero(), + 0, + H256::zero(), + false, + 0, + false, + 0, + 0, + )); + }; + + let (has_task_id, task_id) = scheduled + .maybe_id + .map(|id| (true, H256::from(id))) + .unwrap_or((false, H256::zero())); + let call_hash = <[u8; 32]>::try_from(scheduled.call.hash().as_ref()) + .map(H256::from) + .map_err(|_| conversion_error("scheduler call hash"))?; + let (has_call_length, call_length) = scheduled + .call + .len() + .map(|length| (true, length)) + .unwrap_or((false, 0)); + let (is_periodic, period, remaining) = match scheduled.maybe_periodic { + Some((period, remaining)) => (true, block_number_to_u64::(period)?, remaining), + None => (false, 0, 0), + }; + + Ok(( + true, + has_task_id, + task_id, + scheduled.priority, + call_hash, + has_call_length, + call_length, + is_periodic, + period, + remaining, + )) + } + + #[precompile::public("getRetry(uint64,uint32)")] + #[precompile::view] + fn get_retry( + handle: &mut impl PrecompileHandle, + when: u64, + index: u32, + ) -> EvmResult<(bool, u8, u8, u64)> { + handle.record_db_reads::(1)?; + let address = (block_number_from_u64::(when)?, index); + match pallet_scheduler::Retries::::get(address) { + Some(retry) => { + let encoded = retry.encode(); + let (total_retries, remaining, period) = + <(u8, u8, pallet_scheduler::BlockNumberFor)>::decode( + &mut encoded.as_slice(), + ) + .map_err(|_| conversion_error("scheduler retry metadata"))?; + Ok(( + true, + total_retries, + remaining, + block_number_to_u64::(period)?, + )) + } + None => Ok((false, 0, 0, 0)), + } + } + + #[precompile::public("getTaskAddress(bytes32)")] + #[precompile::view] + fn get_task_address( + handle: &mut impl PrecompileHandle, + task_id: H256, + ) -> EvmResult<(bool, u64, u32)> { + handle.record_db_reads::(1)?; + match pallet_scheduler::Lookup::::get(task_id.0) { + Some((when, index)) => Ok((true, block_number_to_u64::(when)?, index)), + None => Ok((false, 0, 0)), + } + } +} + +fn block_number_from_u64(block: u64) -> EvmResult> +where + R: pallet_scheduler::Config, + pallet_scheduler::BlockNumberFor: TryFrom, +{ + block + .try_into() + .map_err(|_| conversion_error("scheduler block number")) +} + +fn block_number_to_u64(block: pallet_scheduler::BlockNumberFor) -> EvmResult +where + R: pallet_scheduler::Config, + pallet_scheduler::BlockNumberFor: TryInto, +{ + block + .try_into() + .map_err(|_| conversion_error("scheduler block number")) +} + +fn conversion_error(field: &'static str) -> PrecompileFailure { + PrecompileFailure::Error { + exit_status: ExitError::Other(field.into()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{Runtime, addr_from_index, new_test_ext, precompiles, selector_u32}; + use precompile_utils::{ + prelude::RuntimeHelper, + solidity::{encode_return_value, encode_with_selector}, + testing::PrecompileTesterExt, + }; + + #[test] + fn address_selectors_and_empty_metadata_are_stable() { + new_test_ext().execute_with(|| { + assert_eq!(SchedulerPrecompile::::INDEX, 2063); + let precompiles = precompiles::>(); + let caller = addr_from_index(1); + let address = addr_from_index(2063); + let read_cost = RuntimeHelper::::db_read_gas_cost(); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getIncompleteSince()"), ()), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value((false, 0u64))); + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getScheduledCallCount(uint64)"), (10u64,)), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(0u32)); + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getScheduledCall(uint64,uint32)"), + (10u64, 0u32), + ), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(( + false, + false, + H256::zero(), + 0u8, + H256::zero(), + false, + 0u32, + false, + 0u64, + 0u32, + ))); + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getRetry(uint64,uint32)"), (10u64, 0u32)), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value((false, 0u8, 0u8, 0u64))); + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getTaskAddress(bytes32)"), (H256::zero(),)), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value((false, 0u64, 0u32))); + }); + } +} diff --git a/precompiles/src/solidity/alpha.abi b/precompiles/src/solidity/alpha.abi index 14d6eb66dc..b3ce52f2dc 100644 --- a/precompiles/src/solidity/alpha.abi +++ b/precompiles/src/solidity/alpha.abi @@ -326,5 +326,59 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "burnHalfLife", + "type": "uint16" + } + ], + "name": "setBurnHalfLife", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint128", + "name": "rawMultiplier", + "type": "uint128" + } + ], + "name": "setBurnIncreaseMultiplier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + } + ], + "name": "setRecycleOrBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/precompiles/src/solidity/alpha.sol b/precompiles/src/solidity/alpha.sol index c99252ff48..598efbe910 100644 --- a/precompiles/src/solidity/alpha.sol +++ b/precompiles/src/solidity/alpha.sol @@ -98,4 +98,13 @@ interface IAlpha { /// @dev Returns the CK burn rate. /// @return The CK burn rate. function getCKBurn() external view returns (uint256); + + /// mode: 0 = burn, 1 = recycle. + function setRecycleOrBurn(uint16 netuid, uint8 mode) external; + function setBurnHalfLife(uint16 netuid, uint16 burnHalfLife) external; + /// Raw U64F64 bits. + function setBurnIncreaseMultiplier( + uint16 netuid, + uint128 rawMultiplier + ) external; } diff --git a/precompiles/src/solidity/balance.abi b/precompiles/src/solidity/balance.abi index 6f6e51c1af..9a625eafb7 100644 --- a/precompiles/src/solidity/balance.abi +++ b/precompiles/src/solidity/balance.abi @@ -17,5 +17,36 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "keepAlive", + "type": "bool" + } + ], + "name": "burnBalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "accounts", + "type": "bytes32[]" + } + ], + "name": "upgradeAccounts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } -] +] \ No newline at end of file diff --git a/precompiles/src/solidity/balance.sol b/precompiles/src/solidity/balance.sol index 004cf8762b..92bd0b04b2 100644 --- a/precompiles/src/solidity/balance.sol +++ b/precompiles/src/solidity/balance.sol @@ -1,11 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -address constant IBALANCE_ADDRESS = 0x000000000000000000000000000000000000080E; +address constant IBALANCE_ADDRESS = 0x000000000000000000000000000000000000080e; interface IBalance { /// @dev Returns the native free TAO balance for an ss58 account public key. /// @param coldkey The coldkey public key (32 bytes). /// @return The free balance in rao (1 TAO = 1e9 rao). function getFreeBalance(bytes32 coldkey) external view returns (uint256); + function burnBalance(uint256 amount, bool keepAlive) external; + function upgradeAccounts(bytes32[] calldata accounts) external; } diff --git a/precompiles/src/solidity/balanceTransfer.abi b/precompiles/src/solidity/balanceTransfer.abi index 99913b9005..b7b5041ab8 100644 --- a/precompiles/src/solidity/balanceTransfer.abi +++ b/precompiles/src/solidity/balanceTransfer.abi @@ -11,5 +11,41 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "destination", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "keepAlive", + "type": "bool" + } + ], + "name": "transferAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "destination", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferKeepAlive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/precompiles/src/solidity/balanceTransfer.sol b/precompiles/src/solidity/balanceTransfer.sol index 42790b9005..773252f962 100644 --- a/precompiles/src/solidity/balanceTransfer.sol +++ b/precompiles/src/solidity/balanceTransfer.sol @@ -4,4 +4,6 @@ address constant ISUBTENSOR_BALANCE_TRANSFER_ADDRESS = 0x00000000000000000000000 interface ISubtensorBalanceTransfer { function transfer(bytes32 data) external payable; -} \ No newline at end of file + function transferKeepAlive(bytes32 destination, uint256 amount) external; + function transferAll(bytes32 destination, bool keepAlive) external; +} diff --git a/precompiles/src/solidity/crowdloan.abi b/precompiles/src/solidity/crowdloan.abi index c507afcca2..3601e1fb1e 100644 --- a/precompiles/src/solidity/crowdloan.abi +++ b/precompiles/src/solidity/crowdloan.abi @@ -255,5 +255,28 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "hasMaxContribution", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxContribution", + "type": "uint64" + } + ], + "name": "setMaxContribution", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/precompiles/src/solidity/crowdloan.sol b/precompiles/src/solidity/crowdloan.sol index e8bf30c5d0..283517b9fc 100644 --- a/precompiles/src/solidity/crowdloan.sol +++ b/precompiles/src/solidity/crowdloan.sol @@ -94,6 +94,11 @@ interface ICrowdloan { * @param newCap The new cap. */ function updateCap(uint32 crowdloanId, uint64 newCap) external payable; + function setMaxContribution( + uint32 crowdloanId, + bool hasMaxContribution, + uint64 maxContribution + ) external; } struct CrowdloanInfo { @@ -108,4 +113,4 @@ struct CrowdloanInfo { bytes32 target_address; bool finalized; uint32 contributors_count; -} \ No newline at end of file +} diff --git a/precompiles/src/solidity/drand.abi b/precompiles/src/solidity/drand.abi new file mode 100644 index 0000000000..691f53f05b --- /dev/null +++ b/precompiles/src/solidity/drand.abi @@ -0,0 +1,129 @@ +[ + { + "inputs": [], + "name": "getBeaconConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "period", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "genesisTime", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "chainHash", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "groupHash", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "schemeId", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "beaconId", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextUnsignedAt", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "round", + "type": "uint64" + } + ], + "name": "getPulse", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "storedRound", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "randomness", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStoredRoundRange", + "outputs": [ + { + "internalType": "uint64", + "name": "oldest", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latest", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "hasMigrationRun", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/precompiles/src/solidity/drand.sol b/precompiles/src/solidity/drand.sol new file mode 100644 index 0000000000..7827c325c6 --- /dev/null +++ b/precompiles/src/solidity/drand.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +address constant IDRAND_ADDRESS = 0x0000000000000000000000000000000000000810; + +interface IDrand { + function getBeaconConfig() + external + view + returns ( + bytes memory publicKey, + uint32 period, + uint32 genesisTime, + bytes memory chainHash, + bytes memory groupHash, + bytes memory schemeId, + bytes memory beaconId + ); + function getPulse( + uint64 round + ) external view returns (bool exists, uint64 storedRound, bytes memory randomness, bytes memory signature); + function getStoredRoundRange() external view returns (uint64 oldest, uint64 latest); + function getNextUnsignedAt() external view returns (uint64); + function hasMigrationRun(bytes calldata key) external view returns (bool); +} diff --git a/precompiles/src/solidity/leasing.abi b/precompiles/src/solidity/leasing.abi index 88115ee29c..c4bdca22e0 100644 --- a/precompiles/src/solidity/leasing.abi +++ b/precompiles/src/solidity/leasing.abi @@ -168,5 +168,18 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "startCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/precompiles/src/solidity/leasing.sol b/precompiles/src/solidity/leasing.sol index 1b9a406fac..d2988f1676 100644 --- a/precompiles/src/solidity/leasing.sol +++ b/precompiles/src/solidity/leasing.sol @@ -56,6 +56,7 @@ interface ILeasing { * @param hotkey The hotkey of beneficiary, it must be owned by the beneficiary coldkey. */ function terminateLease(uint32 leaseId, bytes32 hotkey) external payable; + function startCall(uint16 netuid) external; } struct LeaseInfo { diff --git a/precompiles/src/solidity/neuron.abi b/precompiles/src/solidity/neuron.abi index 44d47449eb..88d3a530b2 100644 --- a/precompiles/src/solidity/neuron.abi +++ b/precompiles/src/solidity/neuron.abi @@ -252,5 +252,531 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } -] + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newColdkeyHash", + "type": "bytes32" + } + ], + "name": "announceColdkeySwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "address", + "name": "evmKey", + "type": "address" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "associateEvmKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16[]", + "name": "netuids", + "type": "uint16[]" + }, + { + "internalType": "bytes32[]", + "name": "commitHashes", + "type": "bytes32[]" + } + ], + "name": "batchCommitWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16[][]", + "name": "uids", + "type": "uint16[][]" + }, + { + "internalType": "uint16[][]", + "name": "values", + "type": "uint16[][]" + }, + { + "internalType": "uint16[][]", + "name": "salts", + "type": "uint16[][]" + }, + { + "internalType": "uint64[]", + "name": "versionKeys", + "type": "uint64[]" + } + ], + "name": "batchRevealWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16[]", + "name": "netuids", + "type": "uint16[]" + }, + { + "internalType": "uint16[][]", + "name": "dests", + "type": "uint16[][]" + }, + { + "internalType": "uint16[][]", + "name": "values", + "type": "uint16[][]" + }, + { + "internalType": "uint64[]", + "name": "versionKeys", + "type": "uint64[]" + } + ], + "name": "batchSetWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearColdkeySwapAnnouncement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "commit", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + } + ], + "name": "commitCrv3MechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "commitHash", + "type": "bytes32" + } + ], + "name": "commitMechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "commit", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "commitRevealVersion", + "type": "uint16" + } + ], + "name": "commitTimelockedMechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes", + "name": "commit", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "commitRevealVersion", + "type": "uint16" + } + ], + "name": "commitTimelockedWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disputeColdkeySwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newColdkey", + "type": "bytes32" + } + ], + "name": "executeAnnouncedColdkeySwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "work", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "register", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "uint16[]", + "name": "uids", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "values", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "salt", + "type": "uint16[]" + }, + { + "internalType": "uint64", + "name": "versionKey", + "type": "uint64" + } + ], + "name": "revealMechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "rootRegister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64[]", + "name": "proportions", + "type": "uint64[]" + }, + { + "internalType": "bytes32[]", + "name": "children", + "type": "bytes32[]" + } + ], + "name": "setChildren", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "githubRepo", + "type": "string" + }, + { + "internalType": "string", + "name": "image", + "type": "string" + }, + { + "internalType": "string", + "name": "discord", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "additional", + "type": "string" + } + ], + "name": "setIdentity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "uint16[]", + "name": "dests", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "weights", + "type": "uint16[]" + }, + { + "internalType": "uint64", + "name": "versionKey", + "type": "uint64" + } + ], + "name": "setMechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newHotkey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "hasNetuid", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "swapHotkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newHotkey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "hasNetuid", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "keepStake", + "type": "bool" + } + ], + "name": "swapHotkeyV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "tryAssociateHotkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/neuron.sol b/precompiles/src/solidity/neuron.sol index e06da79f2f..1340b88d49 100644 --- a/precompiles/src/solidity/neuron.sol +++ b/precompiles/src/solidity/neuron.sol @@ -133,4 +133,109 @@ interface INeuron { uint16[] memory salt, uint64 versionKey ) external payable; + + function setMechanismWeights( + uint16 netuid, + uint8 mecid, + uint16[] calldata dests, + uint16[] calldata weights, + uint64 versionKey + ) external; + function batchSetWeights( + uint16[] calldata netuids, + uint16[][] calldata dests, + uint16[][] calldata values, + uint64[] calldata versionKeys + ) external; + function commitMechanismWeights( + uint16 netuid, + uint8 mecid, + bytes32 commitHash + ) external; + function batchCommitWeights( + uint16[] calldata netuids, + bytes32[] calldata commitHashes + ) external; + function revealMechanismWeights( + uint16 netuid, + uint8 mecid, + uint16[] calldata uids, + uint16[] calldata values, + uint16[] calldata salt, + uint64 versionKey + ) external; + function commitCrv3MechanismWeights( + uint16 netuid, + uint8 mecid, + bytes calldata commit, + uint64 revealRound + ) external; + function batchRevealWeights( + uint16 netuid, + uint16[][] calldata uids, + uint16[][] calldata values, + uint16[][] calldata salts, + uint64[] calldata versionKeys + ) external; + function commitTimelockedWeights( + uint16 netuid, + bytes calldata commit, + uint64 revealRound, + uint16 commitRevealVersion + ) external; + function commitTimelockedMechanismWeights( + uint16 netuid, + uint8 mecid, + bytes calldata commit, + uint64 revealRound, + uint16 commitRevealVersion + ) external; + function register( + uint16 netuid, + uint64 blockNumber, + uint64 nonce, + bytes calldata work, + bytes32 hotkey, + bytes32 coldkey + ) external; + function rootRegister(bytes32 hotkey) external; + function swapHotkey( + bytes32 hotkey, + bytes32 newHotkey, + bool hasNetuid, + uint16 netuid + ) external; + function swapHotkeyV2( + bytes32 hotkey, + bytes32 newHotkey, + bool hasNetuid, + uint16 netuid, + bool keepStake + ) external; + function setChildren( + bytes32 hotkey, + uint16 netuid, + uint64[] calldata proportions, + bytes32[] calldata children + ) external; + function setIdentity( + string calldata name, + string calldata url, + string calldata githubRepo, + string calldata image, + string calldata discord, + string calldata description, + string calldata additional + ) external; + function tryAssociateHotkey(bytes32 hotkey) external; + function associateEvmKey( + uint16 netuid, + address evmKey, + uint64 blockNumber, + bytes calldata signature + ) external; + function announceColdkeySwap(bytes32 newColdkeyHash) external; + function executeAnnouncedColdkeySwap(bytes32 newColdkey) external; + function disputeColdkeySwap() external; + function clearColdkeySwapAnnouncement() external; } diff --git a/precompiles/src/solidity/proxy.abi b/precompiles/src/solidity/proxy.abi index 2f751002b7..ed10b00c9b 100644 --- a/precompiles/src/solidity/proxy.abi +++ b/precompiles/src/solidity/proxy.abi @@ -173,5 +173,77 @@ } ], "stateMutability": "view" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + } + ], + "name": "announce", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + } + ], + "name": "rejectAnnouncement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + } + ], + "name": "removeAnnouncement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "paysFee", + "type": "bool" + } + ], + "name": "setRealPaysFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } -] +] \ No newline at end of file diff --git a/precompiles/src/solidity/proxy.sol b/precompiles/src/solidity/proxy.sol index 1e79eebc94..c51cf9aafb 100644 --- a/precompiles/src/solidity/proxy.sol +++ b/precompiles/src/solidity/proxy.sol @@ -49,4 +49,9 @@ interface IProxy { function getProxies( bytes32 account ) external view returns (ProxyInfo[] memory); + + function announce(bytes32 real, bytes32 callHash) external; + function removeAnnouncement(bytes32 real, bytes32 callHash) external; + function rejectAnnouncement(bytes32 delegate, bytes32 callHash) external; + function setRealPaysFee(bytes32 delegate, bool paysFee) external; } diff --git a/precompiles/src/solidity/registry.abi b/precompiles/src/solidity/registry.abi new file mode 100644 index 0000000000..b15d2cabd9 --- /dev/null +++ b/precompiles/src/solidity/registry.abi @@ -0,0 +1,53 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "precompile", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getPrecompileStatus", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "isDeprecated", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isDisabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "newPrecompile", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "newSelector", + "type": "bytes4" + }, + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "internalType": "struct IPrecompileRegistry.PrecompileStatus", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/precompiles/src/solidity/registry.sol b/precompiles/src/solidity/registry.sol new file mode 100644 index 0000000000..ba67235154 --- /dev/null +++ b/precompiles/src/solidity/registry.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +address constant IPRECOMPILE_REGISTRY_ADDRESS = 0x0000000000000000000000000000000000000813; + +interface IPrecompileRegistry { + struct PrecompileStatus { + bool isDeprecated; + bool isDisabled; + address newPrecompile; + bytes4 newSelector; + string message; + } + + function getPrecompileStatus( + address precompile, + bytes4 selector + ) external view returns (PrecompileStatus memory); +} diff --git a/precompiles/src/solidity/runtimeConfiguration.abi b/precompiles/src/solidity/runtimeConfiguration.abi new file mode 100644 index 0000000000..44d814754a --- /dev/null +++ b/precompiles/src/solidity/runtimeConfiguration.abi @@ -0,0 +1,28 @@ +[ + { + "inputs": [], + "name": "getEvmChainId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransactionRateLimit", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/precompiles/src/solidity/runtimeConfiguration.sol b/precompiles/src/solidity/runtimeConfiguration.sol new file mode 100644 index 0000000000..ad733b106c --- /dev/null +++ b/precompiles/src/solidity/runtimeConfiguration.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +address constant IRUNTIME_CONFIGURATION_ADDRESS = 0x0000000000000000000000000000000000000812; + +interface IRuntimeConfiguration { + function getEvmChainId() external view returns (uint64); + function getTransactionRateLimit() external view returns (uint64); +} diff --git a/precompiles/src/solidity/scheduler.abi b/precompiles/src/solidity/scheduler.abi new file mode 100644 index 0000000000..8bf7ecbe5c --- /dev/null +++ b/precompiles/src/solidity/scheduler.abi @@ -0,0 +1,183 @@ +[ + { + "inputs": [], + "name": "getIncompleteSince", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "when", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getRetry", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "totalRetries", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "remaining", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "period", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "when", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getScheduledCall", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bool", + "name": "hasTaskId", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "taskId", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "priority", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "hasCallLength", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "callLength", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "isPeriodic", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "period", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "remaining", + "type": "uint32" + } + ], + "internalType": "struct IScheduler.ScheduledCall", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "when", + "type": "uint64" + } + ], + "name": "getScheduledCallCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "taskId", + "type": "bytes32" + } + ], + "name": "getTaskAddress", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "when", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/precompiles/src/solidity/scheduler.sol b/precompiles/src/solidity/scheduler.sol new file mode 100644 index 0000000000..5e2bcb3b93 --- /dev/null +++ b/precompiles/src/solidity/scheduler.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +address constant ISCHEDULER_ADDRESS = 0x000000000000000000000000000000000000080F; + +interface IScheduler { + struct ScheduledCall { + bool exists; + bool hasTaskId; + bytes32 taskId; + uint8 priority; + bytes32 callHash; + bool hasCallLength; + uint32 callLength; + bool isPeriodic; + uint64 period; + uint32 remaining; + } + + function getIncompleteSince() external view returns (bool exists, uint64 blockNumber); + function getScheduledCallCount(uint64 when) external view returns (uint32); + function getScheduledCall( + uint64 when, + uint32 index + ) external view returns (ScheduledCall memory); + function getRetry( + uint64 when, + uint32 index + ) external view returns (bool exists, uint8 totalRetries, uint8 remaining, uint64 period); + function getTaskAddress( + bytes32 taskId + ) external view returns (bool exists, uint64 when, uint32 index); +} diff --git a/precompiles/src/solidity/stakingV2.abi b/precompiles/src/solidity/stakingV2.abi index 64edc7ae3d..f0b7177168 100644 --- a/precompiles/src/solidity/stakingV2.abi +++ b/precompiles/src/solidity/stakingV2.abi @@ -809,5 +809,440 @@ "outputs": [], "stateMutability": "payable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "alpha", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limitPrice", + "type": "uint64" + } + ], + "name": "addCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "hasLimit", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + } + ], + "name": "addStakeBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16[]", + "name": "subnets", + "type": "uint16[]" + } + ], + "name": "claimRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "name": "decreaseTake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "name": "increaseTake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "recycleAlpha", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setAutoParentDelegationEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "name": "setChildkeyTake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "setColdkeyAutoStakeHotkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint128", + "name": "rawRatio", + "type": "uint128" + } + ], + "name": "setCollateralDrainRatio", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "lockShare", + "type": "uint16" + } + ], + "name": "setCollateralLockShare", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "name": "setMinChildkeyTakePerSubnet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "minLocked", + "type": "uint64" + } + ], + "name": "setMinCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "threshold", + "type": "uint64" + } + ], + "name": "setRootClaimThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "claimType", + "type": "uint8" + }, + { + "internalType": "uint16[]", + "name": "subnets", + "type": "uint16[]" + } + ], + "name": "setRootClaimType", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "originNetuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "destinationNetuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alphaAmount", + "type": "uint64" + } + ], + "name": "swapStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "originNetuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "destinationNetuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alphaAmount", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limitPrice", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "allowPartial", + "type": "bool" + } + ], + "name": "swapStakeLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "destinationColdkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "originHotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "destinationHotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "originNetuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "destinationNetuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alphaAmount", + "type": "uint64" + } + ], + "name": "transferStakeAndHotkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "unstakeAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "unstakeAllAlpha", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } -] +] \ No newline at end of file diff --git a/precompiles/src/solidity/stakingV2.sol b/precompiles/src/solidity/stakingV2.sol index 9170abc829..6647ce55e3 100644 --- a/precompiles/src/solidity/stakingV2.sol +++ b/precompiles/src/solidity/stakingV2.sol @@ -559,4 +559,70 @@ interface IStaking { uint256 destinationNetuid, uint256 amount ) external; + + function decreaseTake(bytes32 hotkey, uint16 take) external; + function increaseTake(bytes32 hotkey, uint16 take) external; + function setChildkeyTake(bytes32 hotkey, uint16 netuid, uint16 take) external; + function unstakeAll(bytes32 hotkey) external; + function unstakeAllAlpha(bytes32 hotkey) external; + function swapStake( + bytes32 hotkey, + uint16 originNetuid, + uint16 destinationNetuid, + uint64 alphaAmount + ) external; + function swapStakeLimit( + bytes32 hotkey, + uint16 originNetuid, + uint16 destinationNetuid, + uint64 alphaAmount, + uint64 limitPrice, + bool allowPartial + ) external; + function recycleAlpha(bytes32 hotkey, uint64 amount, uint16 netuid) external; + function setColdkeyAutoStakeHotkey(uint16 netuid, bytes32 hotkey) external; + function claimRoot(uint16[] calldata subnets) external; + /// claimType: 0 = swap, 1 = keep, 2 = keep only listed subnets. + function setRootClaimType( + uint8 claimType, + uint16[] calldata subnets + ) external; + function setRootClaimThreshold(uint16 netuid, uint64 threshold) external; + function addStakeBurn( + bytes32 hotkey, + uint16 netuid, + uint64 amount, + bool hasLimit, + uint64 limit + ) external; + function setAutoParentDelegationEnabled( + bytes32 hotkey, + bool enabled + ) external; + function transferStakeAndHotkey( + bytes32 destinationColdkey, + bytes32 originHotkey, + bytes32 destinationHotkey, + uint16 originNetuid, + uint16 destinationNetuid, + uint64 alphaAmount + ) external; + function addCollateral( + uint16 netuid, + bytes32 hotkey, + uint64 alpha, + uint64 limitPrice + ) external; + function setMinCollateral( + uint16 netuid, + bytes32 hotkey, + uint64 minLocked + ) external; + function setMinChildkeyTakePerSubnet(uint16 netuid, uint16 take) external; + function setCollateralLockShare(uint16 netuid, uint16 lockShare) external; + /// Raw U64F64 bits. + function setCollateralDrainRatio( + uint16 netuid, + uint128 rawRatio + ) external; } diff --git a/precompiles/src/solidity/subnet.abi b/precompiles/src/solidity/subnet.abi index e765c37c4a..7e5046d854 100644 --- a/precompiles/src/solidity/subnet.abi +++ b/precompiles/src/solidity/subnet.abi @@ -1159,5 +1159,274 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } -] + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "string", + "name": "subnetName", + "type": "string" + }, + { + "internalType": "string", + "name": "githubRepo", + "type": "string" + }, + { + "internalType": "string", + "name": "subnetContact", + "type": "string" + }, + { + "internalType": "string", + "name": "subnetUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "discord", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "logoUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "additional", + "type": "string" + } + ], + "name": "setSubnetIdentity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "name": "updateSubnetSymbol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "triggerEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "bondsPenalty", + "type": "uint16" + } + ], + "name": "setBondsPenalty", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxAllowedUids", + "type": "uint16" + } + ], + "name": "setMaxAllowedUids", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "maxBurn", + "type": "uint64" + } + ], + "name": "setMaxBurnV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mechanismCount", + "type": "uint8" + } + ], + "name": "setMechanismCount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "hasSplit", + "type": "bool" + }, + { + "internalType": "uint16[]", + "name": "split", + "type": "uint16[]" + } + ], + "name": "setMechanismEmissionSplit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "minBurn", + "type": "uint64" + } + ], + "name": "setMinBurnV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setOwnerCutEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "immuneNeurons", + "type": "uint16" + } + ], + "name": "setOwnerImmuneNeuronLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "tempo", + "type": "uint16" + } + ], + "name": "setTempo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxUids", + "type": "uint16" + } + ], + "name": "trimToMaxAllowedUids", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/precompiles/src/solidity/subnet.sol b/precompiles/src/solidity/subnet.sol index 174814cc28..fd12fbcf66 100644 --- a/precompiles/src/solidity/subnet.sol +++ b/precompiles/src/solidity/subnet.sol @@ -232,4 +232,35 @@ interface ISubnet { uint16 netuid, uint64 commitRevealWeightsInterval ) external payable; + + function setSubnetIdentity( + uint16 netuid, + string calldata subnetName, + string calldata githubRepo, + string calldata subnetContact, + string calldata subnetUrl, + string calldata discord, + string calldata description, + string calldata logoUrl, + string calldata additional + ) external; + function updateSubnetSymbol(uint16 netuid, string calldata symbol) external; + function triggerEpoch(uint16 netuid) external; + function setBondsPenalty(uint16 netuid, uint16 bondsPenalty) external; + function setMaxAllowedUids(uint16 netuid, uint16 maxAllowedUids) external; + function setMaxBurnV2(uint16 netuid, uint64 maxBurn) external; + function setMechanismCount(uint16 netuid, uint8 mechanismCount) external; + function setMechanismEmissionSplit( + uint16 netuid, + bool hasSplit, + uint16[] calldata split + ) external; + function setMinBurnV2(uint16 netuid, uint64 minBurn) external; + function setOwnerCutEnabled(uint16 netuid, bool enabled) external; + function setOwnerImmuneNeuronLimit( + uint16 netuid, + uint16 immuneNeurons + ) external; + function setTempo(uint16 netuid, uint16 tempo) external; + function trimToMaxAllowedUids(uint16 netuid, uint16 maxUids) external; } diff --git a/precompiles/src/solidity/timestamp.abi b/precompiles/src/solidity/timestamp.abi new file mode 100644 index 0000000000..78d2ee9784 --- /dev/null +++ b/precompiles/src/solidity/timestamp.abi @@ -0,0 +1,28 @@ +[ + { + "inputs": [], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wasUpdatedThisBlock", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/precompiles/src/solidity/timestamp.sol b/precompiles/src/solidity/timestamp.sol new file mode 100644 index 0000000000..5923e23fc9 --- /dev/null +++ b/precompiles/src/solidity/timestamp.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +address constant ITIMESTAMP_ADDRESS = 0x0000000000000000000000000000000000000811; + +interface ITimestamp { + function getTimestamp() external view returns (uint64); + function wasUpdatedThisBlock() external view returns (bool); +} diff --git a/precompiles/src/solidity/votingPower.abi b/precompiles/src/solidity/votingPower.abi index a2694e9a99..d825bcdfde 100644 --- a/precompiles/src/solidity/votingPower.abi +++ b/precompiles/src/solidity/votingPower.abi @@ -98,5 +98,31 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "disableVotingPowerTracking", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "enableVotingPowerTracking", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } -] +] \ No newline at end of file diff --git a/precompiles/src/solidity/votingPower.sol b/precompiles/src/solidity/votingPower.sol index 043772a66d..7f8725544c 100644 --- a/precompiles/src/solidity/votingPower.sol +++ b/precompiles/src/solidity/votingPower.sol @@ -40,4 +40,7 @@ interface IVotingPower { /// useful for computing voting thresholds (e.g. a 51% quorum). /// @param netuid The subnet identifier. function getTotalVotingPower(uint16 netuid) external view returns (uint256); + + function enableVotingPowerTracking(uint16 netuid) external; + function disableVotingPowerTracking(uint16 netuid) external; } diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs index 7f47bf8ab3..0c636afc3a 100644 --- a/precompiles/src/staking.rs +++ b/precompiles/src/staking.rs @@ -46,10 +46,13 @@ use pallet_subtensor_proxy as pallet_proxy; use precompile_utils::EvmResult; use precompile_utils::prelude::{Address, BoundedVec, revert}; use sp_core::{H160, H256, U256}; -use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable, StaticLookup, UniqueSaturatedInto}; +use sp_runtime::{ + PerU16, + traits::{AsSystemOriginSigner, Dispatchable, StaticLookup, UniqueSaturatedInto}, +}; use sp_std::vec; use substrate_fixed::types::U64F64; -use subtensor_runtime_common::{AlphaBalance, NetUid, ProxyType, Token}; +use subtensor_runtime_common::{AlphaBalance, NetUid, ProxyType, TaoBalance, Token}; use crate::{PrecompileExt, PrecompileHandleExt}; @@ -103,6 +106,7 @@ where + pallet_balances::Config + pallet_evm::Config + pallet_subtensor::Config + + pallet_admin_utils::Config + pallet_proxy::Config + pallet_shield::Config + pallet_subtensor_proxy::Config @@ -112,6 +116,7 @@ where R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + + From> + From> + GetDispatchInfo + Dispatchable @@ -132,6 +137,7 @@ where + pallet_balances::Config + pallet_evm::Config + pallet_subtensor::Config + + pallet_admin_utils::Config + pallet_proxy::Config + pallet_shield::Config + pallet_subtensor_proxy::Config @@ -141,6 +147,7 @@ where R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + + From> + From> + GetDispatchInfo + Dispatchable @@ -977,6 +984,391 @@ where handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(source_id)) } + + #[precompile::public("decreaseTake(bytes32,uint16)")] + fn decrease_take(handle: &mut impl PrecompileHandle, hotkey: H256, take: u16) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::decrease_take { + hotkey: hotkey.0.into(), + take: PerU16::from_parts(take), + }, + ) + } + + #[precompile::public("increaseTake(bytes32,uint16)")] + fn increase_take(handle: &mut impl PrecompileHandle, hotkey: H256, take: u16) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::increase_take { + hotkey: hotkey.0.into(), + take: PerU16::from_parts(take), + }, + ) + } + + #[precompile::public("setChildkeyTake(bytes32,uint16,uint16)")] + fn set_childkey_take( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + take: u16, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::set_childkey_take { + hotkey: hotkey.0.into(), + netuid: netuid.into(), + take: PerU16::from_parts(take), + }, + ) + } + + #[precompile::public("unstakeAll(bytes32)")] + fn unstake_all(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::unstake_all { + hotkey: hotkey.0.into(), + }, + ) + } + + #[precompile::public("unstakeAllAlpha(bytes32)")] + fn unstake_all_alpha(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::unstake_all_alpha { + hotkey: hotkey.0.into(), + }, + ) + } + + #[precompile::public("swapStake(bytes32,uint16,uint16,uint64)")] + fn swap_stake( + handle: &mut impl PrecompileHandle, + hotkey: H256, + origin_netuid: u16, + destination_netuid: u16, + alpha_amount: u64, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::swap_stake { + hotkey: hotkey.0.into(), + origin_netuid: origin_netuid.into(), + destination_netuid: destination_netuid.into(), + alpha_amount: AlphaBalance::from(alpha_amount), + }, + ) + } + + #[precompile::public("swapStakeLimit(bytes32,uint16,uint16,uint64,uint64,bool)")] + fn swap_stake_limit( + handle: &mut impl PrecompileHandle, + hotkey: H256, + origin_netuid: u16, + destination_netuid: u16, + alpha_amount: u64, + limit_price: u64, + allow_partial: bool, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::swap_stake_limit { + hotkey: hotkey.0.into(), + origin_netuid: origin_netuid.into(), + destination_netuid: destination_netuid.into(), + alpha_amount: AlphaBalance::from(alpha_amount), + limit_price: TaoBalance::from(limit_price), + allow_partial, + }, + ) + } + + #[precompile::public("recycleAlpha(bytes32,uint64,uint16)")] + fn recycle_alpha( + handle: &mut impl PrecompileHandle, + hotkey: H256, + amount: u64, + netuid: u16, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::recycle_alpha { + hotkey: hotkey.0.into(), + amount: AlphaBalance::from(amount), + netuid: netuid.into(), + }, + ) + } + + #[precompile::public("setColdkeyAutoStakeHotkey(uint16,bytes32)")] + fn set_coldkey_auto_stake_hotkey( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::set_coldkey_auto_stake_hotkey { + netuid: netuid.into(), + hotkey: hotkey.0.into(), + }, + ) + } + + #[precompile::public("claimRoot(uint16[])")] + fn claim_root( + handle: &mut impl PrecompileHandle, + subnets: BoundedVec>, + ) -> EvmResult<()> { + let subnets = Vec::::from(subnets) + .into_iter() + .map(NetUid::from) + .collect::>(); + dispatch_subtensor(handle, pallet_subtensor::Call::::claim_root { subnets }) + } + + #[precompile::public("setRootClaimType(uint8,uint16[])")] + fn set_root_claim_type( + handle: &mut impl PrecompileHandle, + claim_type: u8, + subnets: BoundedVec>, + ) -> EvmResult<()> { + let subnets = Vec::::from(subnets) + .into_iter() + .map(NetUid::from) + .collect::>(); + let new_root_claim_type = match claim_type { + 0 => pallet_subtensor::RootClaimTypeEnum::Swap, + 1 => pallet_subtensor::RootClaimTypeEnum::Keep, + 2 => pallet_subtensor::RootClaimTypeEnum::KeepSubnets { subnets }, + _ => return Err(revert("invalid root claim type")), + }; + dispatch_subtensor( + handle, + pallet_subtensor::Call::::set_root_claim_type { + new_root_claim_type, + }, + ) + } + + #[precompile::public("setRootClaimThreshold(uint16,uint64)")] + fn set_root_claim_threshold( + handle: &mut impl PrecompileHandle, + netuid: u16, + new_value: u64, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::sudo_set_root_claim_threshold { + netuid: netuid.into(), + new_value, + }, + ) + } + + #[precompile::public("addStakeBurn(bytes32,uint16,uint64,bool,uint64)")] + fn add_stake_burn( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + amount: u64, + has_limit: bool, + limit: u64, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::add_stake_burn { + hotkey: hotkey.0.into(), + netuid: netuid.into(), + amount: TaoBalance::from(amount), + limit: has_limit.then_some(TaoBalance::from(limit)), + }, + ) + } + + #[precompile::public("setAutoParentDelegationEnabled(bytes32,bool)")] + fn set_auto_parent_delegation_enabled( + handle: &mut impl PrecompileHandle, + hotkey: H256, + enabled: bool, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::set_auto_parent_delegation_enabled { + hotkey: hotkey.0.into(), + enabled, + }, + ) + } + + #[precompile::public("transferStakeAndHotkey(bytes32,bytes32,bytes32,uint16,uint16,uint64)")] + fn transfer_stake_and_hotkey( + handle: &mut impl PrecompileHandle, + destination_coldkey: H256, + origin_hotkey: H256, + destination_hotkey: H256, + origin_netuid: u16, + destination_netuid: u16, + alpha_amount: u64, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::transfer_stake_and_hotkey { + destination_coldkey: destination_coldkey.0.into(), + origin_hotkey: origin_hotkey.0.into(), + destination_hotkey: destination_hotkey.0.into(), + origin_netuid: origin_netuid.into(), + destination_netuid: destination_netuid.into(), + alpha_amount: AlphaBalance::from(alpha_amount), + }, + ) + } + + #[precompile::public("addCollateral(uint16,bytes32,uint64,uint64)")] + fn add_collateral( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + alpha: u64, + limit_price: u64, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::add_collateral { + netuid: netuid.into(), + hotkey: hotkey.0.into(), + alpha: AlphaBalance::from(alpha), + limit_price: TaoBalance::from(limit_price), + }, + ) + } + + #[precompile::public("setMinCollateral(uint16,bytes32,uint64)")] + fn set_min_collateral( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + min_locked: u64, + ) -> EvmResult<()> { + dispatch_subtensor( + handle, + pallet_subtensor::Call::::set_min_collateral { + netuid: netuid.into(), + hotkey: hotkey.0.into(), + min_locked: AlphaBalance::from(min_locked), + }, + ) + } + + #[precompile::public("setMinChildkeyTakePerSubnet(uint16,uint16)")] + fn set_min_childkey_take_per_subnet( + handle: &mut impl PrecompileHandle, + netuid: u16, + take: u16, + ) -> EvmResult<()> { + dispatch_staking_admin( + handle, + pallet_admin_utils::Call::::sudo_set_min_childkey_take_per_subnet { + netuid: netuid.into(), + take: PerU16::from_parts(take), + }, + ) + } + + #[precompile::public("setCollateralLockShare(uint16,uint16)")] + fn set_collateral_lock_share( + handle: &mut impl PrecompileHandle, + netuid: u16, + lock_share: u16, + ) -> EvmResult<()> { + dispatch_staking_admin( + handle, + pallet_admin_utils::Call::::sudo_set_collateral_lock_share { + netuid: netuid.into(), + lock_share, + }, + ) + } + + #[precompile::public("setCollateralDrainRatio(uint16,uint128)")] + fn set_collateral_drain_ratio( + handle: &mut impl PrecompileHandle, + netuid: u16, + raw_ratio: u128, + ) -> EvmResult<()> { + dispatch_staking_admin( + handle, + pallet_admin_utils::Call::::sudo_set_collateral_drain_ratio { + netuid: netuid.into(), + drain_ratio: U64F64::from_bits(raw_ratio), + }, + ) + } +} + +fn dispatch_subtensor( + handle: &mut impl PrecompileHandle, + call: pallet_subtensor::Call, +) -> EvmResult<()> +where + R: frame_system::Config + + pallet_balances::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_admin_utils::Config + + pallet_proxy::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::AddressMapping: AddressMapping, +{ + let caller = handle.caller_account_id::(); + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) +} + +fn dispatch_staking_admin( + handle: &mut impl PrecompileHandle, + call: pallet_admin_utils::Call, +) -> EvmResult<()> +where + R: frame_system::Config + + pallet_balances::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_admin_utils::Config + + pallet_proxy::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::AddressMapping: AddressMapping, +{ + let caller = handle.caller_account_id::(); + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) } // Deprecated, exists for backward compatibility. diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs index a591a7f0d8..c9687fe1fb 100644 --- a/precompiles/src/subnet.rs +++ b/precompiles/src/subnet.rs @@ -5,11 +5,14 @@ use frame_support::traits::ConstU32; use frame_support::traits::IsSubType; use frame_system::RawOrigin; use pallet_evm::{AddressMapping, PrecompileHandle}; -use precompile_utils::{EvmResult, prelude::BoundedString}; +use precompile_utils::{ + EvmResult, + prelude::{BoundedString, BoundedVec}, +}; use sp_core::H256; use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable}; -use sp_std::vec; -use subtensor_runtime_common::{NetUid, Token}; +use sp_std::{vec, vec::Vec}; +use subtensor_runtime_common::{NetUid, TaoBalance, Token}; use crate::{PrecompileExt, PrecompileHandleExt}; @@ -891,6 +894,243 @@ where handle.record_db_reads::(1)?; Ok(pallet_subtensor::DissolveCleanupQueue::::get().contains(&NetUid::from(netuid))) } + + #[precompile::public( + "setSubnetIdentity(uint16,string,string,string,string,string,string,string,string)" + )] + #[allow(clippy::too_many_arguments)] + fn set_subnet_identity( + handle: &mut impl PrecompileHandle, + netuid: u16, + subnet_name: BoundedString>, + github_repo: BoundedString>, + subnet_contact: BoundedString>, + subnet_url: BoundedString>, + discord: BoundedString>, + description: BoundedString>, + logo_url: BoundedString>, + additional: BoundedString>, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::set_subnet_identity { + netuid: NetUid::from(netuid), + subnet_name: subnet_name.into(), + github_repo: github_repo.into(), + subnet_contact: subnet_contact.into(), + subnet_url: subnet_url.into(), + discord: discord.into(), + description: description.into(), + logo_url: logo_url.into(), + additional: additional.into(), + }; + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("updateSubnetSymbol(uint16,string)")] + fn update_subnet_symbol( + handle: &mut impl PrecompileHandle, + netuid: u16, + symbol: BoundedString>, + ) -> EvmResult<()> { + let call = pallet_subtensor::Call::::update_symbol { + netuid: NetUid::from(netuid), + symbol: symbol.into(), + }; + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("triggerEpoch(uint16)")] + fn trigger_epoch(handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult<()> { + let call = pallet_subtensor::Call::::trigger_epoch { + netuid: NetUid::from(netuid), + }; + handle.try_dispatch_runtime_call::( + call, + RawOrigin::Signed(handle.caller_account_id::()), + ) + } + + #[precompile::public("setBondsPenalty(uint16,uint16)")] + fn set_bonds_penalty( + handle: &mut impl PrecompileHandle, + netuid: u16, + bonds_penalty: u16, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_bonds_penalty { + netuid: netuid.into(), + bonds_penalty, + }, + ) + } + + #[precompile::public("setMaxAllowedUids(uint16,uint16)")] + fn set_max_allowed_uids( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_allowed_uids: u16, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_max_allowed_uids { + netuid: netuid.into(), + max_allowed_uids, + }, + ) + } + + #[precompile::public("setMaxBurnV2(uint16,uint64)")] + fn set_max_burn_v2( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_burn: u64, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_max_burn { + netuid: netuid.into(), + max_burn: TaoBalance::from(max_burn), + }, + ) + } + + #[precompile::public("setMechanismCount(uint16,uint8)")] + fn set_mechanism_count( + handle: &mut impl PrecompileHandle, + netuid: u16, + mechanism_count: u8, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_mechanism_count { + netuid: netuid.into(), + mechanism_count: mechanism_count.into(), + }, + ) + } + + #[precompile::public("setMechanismEmissionSplit(uint16,bool,uint16[])")] + fn set_mechanism_emission_split( + handle: &mut impl PrecompileHandle, + netuid: u16, + has_split: bool, + split: BoundedVec>, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_mechanism_emission_split { + netuid: netuid.into(), + maybe_split: has_split.then(|| Vec::::from(split)), + }, + ) + } + + #[precompile::public("setMinBurnV2(uint16,uint64)")] + fn set_min_burn_v2( + handle: &mut impl PrecompileHandle, + netuid: u16, + min_burn: u64, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_min_burn { + netuid: netuid.into(), + min_burn: TaoBalance::from(min_burn), + }, + ) + } + + #[precompile::public("setOwnerCutEnabled(uint16,bool)")] + fn set_owner_cut_enabled( + handle: &mut impl PrecompileHandle, + netuid: u16, + enabled: bool, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_owner_cut_enabled { + netuid: netuid.into(), + enabled, + }, + ) + } + + #[precompile::public("setOwnerImmuneNeuronLimit(uint16,uint16)")] + fn set_owner_immune_neuron_limit( + handle: &mut impl PrecompileHandle, + netuid: u16, + immune_neurons: u16, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_owner_immune_neuron_limit { + netuid: netuid.into(), + immune_neurons, + }, + ) + } + + #[precompile::public("setTempo(uint16,uint16)")] + fn set_tempo(handle: &mut impl PrecompileHandle, netuid: u16, tempo: u16) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_set_tempo { + netuid: netuid.into(), + tempo, + }, + ) + } + + #[precompile::public("trimToMaxAllowedUids(uint16,uint16)")] + fn trim_to_max_allowed_uids( + handle: &mut impl PrecompileHandle, + netuid: u16, + max_n: u16, + ) -> EvmResult<()> { + dispatch_admin( + handle, + pallet_admin_utils::Call::::sudo_trim_to_max_allowed_uids { + netuid: netuid.into(), + max_n, + }, + ) + } +} + +fn dispatch_admin( + handle: &mut impl PrecompileHandle, + call: pallet_admin_utils::Call, +) -> EvmResult<()> +where + R: frame_system::Config + + pallet_balances::Config + + pallet_evm::Config + + pallet_subtensor::Config + + pallet_admin_utils::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, + R::AccountId: From<[u8; 32]>, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::AddressMapping: AddressMapping, +{ + let caller = handle.caller_account_id::(); + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) } #[cfg(test)] @@ -904,8 +1144,8 @@ mod tests { use super::*; use crate::PrecompileExt; use crate::mock::{ - AccountId, Runtime, addr_from_index, assert_static_call, mapped_account, new_test_ext, - precompiles, selector_u32, + AccountId, Runtime, addr_from_index, assert_static_call, execute_precompile, + mapped_account, new_test_ext, precompiles, selector_u32, }; use precompile_utils::solidity::encode_with_selector; use precompile_utils::testing::PrecompileTesterExt; @@ -1484,4 +1724,33 @@ mod tests { ); }); } + + #[test] + fn added_admin_call_preserves_subnet_owner_authorization() { + new_test_ext().execute_with(|| { + let owner = addr_from_index(0x5010); + let non_owner = addr_from_index(0x5011); + let netuid = setup_owner_subnet(owner); + let address = addr_from_index(SubnetPrecompile::::INDEX); + let input = encode_with_selector( + selector_u32("setBondsPenalty(uint16,uint16)"), + (TEST_NETUID_U16, 123u16), + ); + + precompiles::>() + .prepare_test(owner, address, input.clone()) + .execute_returns(()); + assert_eq!(pallet_subtensor::BondsPenalty::::get(netuid), 123); + + let rejected = execute_precompile( + &precompiles::>(), + address, + non_owner, + input, + U256::zero(), + ); + assert!(matches!(rejected, Some(Err(_)))); + assert_eq!(pallet_subtensor::BondsPenalty::::get(netuid), 123); + }); + } } diff --git a/precompiles/src/timestamp.rs b/precompiles/src/timestamp.rs new file mode 100644 index 0000000000..7878200ddc --- /dev/null +++ b/precompiles/src/timestamp.rs @@ -0,0 +1,107 @@ +use core::marker::PhantomData; + +use fp_evm::{ExitError, PrecompileFailure}; +use frame_support::pallet_prelude::{StorageValue, ValueQuery}; +use frame_support::traits::StorageInstance; +use pallet_evm::PrecompileHandle; +use precompile_utils::EvmResult; + +use crate::{PrecompileExt, PrecompileHandleExt}; + +struct DidUpdateStorage; + +impl StorageInstance for DidUpdateStorage { + const STORAGE_PREFIX: &'static str = "DidUpdate"; + + fn pallet_prefix() -> &'static str { + "Timestamp" + } +} + +type DidUpdate = StorageValue; + +pub struct TimestampPrecompile(PhantomData); + +impl PrecompileExt for TimestampPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_timestamp::Config, + R::AccountId: From<[u8; 32]>, + R::Moment: TryInto, +{ + const INDEX: u64 = 2065; +} + +#[precompile_utils::precompile] +impl TimestampPrecompile +where + R: frame_system::Config + pallet_evm::Config + pallet_timestamp::Config, + R::AccountId: From<[u8; 32]>, + R::Moment: TryInto, +{ + #[precompile::public("getTimestamp()")] + #[precompile::view] + fn get_timestamp(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + pallet_timestamp::Pallet::::get() + .try_into() + .map_err(|_| conversion_error("timestamp moment")) + } + + #[precompile::public("wasUpdatedThisBlock()")] + #[precompile::view] + fn was_updated_this_block(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(DidUpdate::get()) + } +} + +fn conversion_error(field: &'static str) -> PrecompileFailure { + PrecompileFailure::Error { + exit_status: ExitError::Other(field.into()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{ + Runtime, Timestamp, addr_from_index, new_test_ext, precompiles, selector_u32, + }; + use precompile_utils::{ + prelude::RuntimeHelper, + solidity::{encode_return_value, encode_with_selector}, + testing::PrecompileTesterExt, + }; + + #[test] + fn address_selectors_and_values_are_stable() { + new_test_ext().execute_with(|| { + assert_eq!(TimestampPrecompile::::INDEX, 2065); + Timestamp::set_timestamp(1_234); + + let precompiles = precompiles::>(); + let caller = addr_from_index(1); + let address = addr_from_index(2065); + let read_cost = RuntimeHelper::::db_read_gas_cost(); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getTimestamp()"), ()), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(1_234u64)); + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("wasUpdatedThisBlock()"), ()), + ) + .with_static_call(true) + .expect_cost(read_cost) + .execute_returns_raw(encode_return_value(true)); + }); + } +} diff --git a/precompiles/src/voting_power.rs b/precompiles/src/voting_power.rs index 4cad7fcb89..f44f626b2d 100644 --- a/precompiles/src/voting_power.rs +++ b/precompiles/src/voting_power.rs @@ -1,8 +1,15 @@ use core::marker::PhantomData; use fp_evm::PrecompileHandle; +use frame_support::{ + dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}, + traits::IsSubType, +}; +use frame_system::RawOrigin; +use pallet_evm::AddressMapping; use precompile_utils::EvmResult; use sp_core::{ByteArray, H256, U256}; +use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable}; use subtensor_runtime_common::NetUid; use crate::PrecompileExt; @@ -16,8 +23,25 @@ pub struct VotingPowerPrecompile(PhantomData); impl PrecompileExt for VotingPowerPrecompile where - R: frame_system::Config + pallet_subtensor::Config + pallet_evm::Config, + R: frame_system::Config + + pallet_balances::Config + + pallet_subtensor::Config + + pallet_evm::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, R::AccountId: From<[u8; 32]> + ByteArray, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::AddressMapping: AddressMapping, { const INDEX: u64 = 2061; } @@ -25,8 +49,25 @@ where #[precompile_utils::precompile] impl VotingPowerPrecompile where - R: frame_system::Config + pallet_subtensor::Config + pallet_evm::Config, - R::AccountId: From<[u8; 32]>, + R: frame_system::Config + + pallet_balances::Config + + pallet_subtensor::Config + + pallet_evm::Config + + pallet_shield::Config + + pallet_subtensor_proxy::Config + + Send + + Sync + + scale_info::TypeInfo, + R::AccountId: From<[u8; 32]> + ByteArray, + ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: From> + + GetDispatchInfo + + Dispatchable + + IsSubType> + + IsSubType> + + IsSubType> + + IsSubType>, + ::AddressMapping: AddressMapping, { /// Get voting power for a hotkey on a subnet. /// @@ -140,6 +181,30 @@ where } Ok(U256::from(total)) } + + #[precompile::public("enableVotingPowerTracking(uint16)")] + fn enable_voting_power_tracking( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<()> { + let caller = handle.caller_account_id::(); + let call = pallet_subtensor::Call::::enable_voting_power_tracking { + netuid: NetUid::from(netuid), + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } + + #[precompile::public("disableVotingPowerTracking(uint16)")] + fn disable_voting_power_tracking( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<()> { + let caller = handle.caller_account_id::(); + let call = pallet_subtensor::Call::::disable_voting_power_tracking { + netuid: NetUid::from(netuid), + }; + handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) + } } #[cfg(test)] diff --git a/sdk/python/bittensor/evm/abi/alpha.json b/sdk/python/bittensor/evm/abi/alpha.json index 14d6eb66dc..b3ce52f2dc 100644 --- a/sdk/python/bittensor/evm/abi/alpha.json +++ b/sdk/python/bittensor/evm/abi/alpha.json @@ -326,5 +326,59 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "burnHalfLife", + "type": "uint16" + } + ], + "name": "setBurnHalfLife", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint128", + "name": "rawMultiplier", + "type": "uint128" + } + ], + "name": "setBurnIncreaseMultiplier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + } + ], + "name": "setRecycleOrBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/balance.json b/sdk/python/bittensor/evm/abi/balance.json index 6f6e51c1af..9a625eafb7 100644 --- a/sdk/python/bittensor/evm/abi/balance.json +++ b/sdk/python/bittensor/evm/abi/balance.json @@ -17,5 +17,36 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "keepAlive", + "type": "bool" + } + ], + "name": "burnBalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "accounts", + "type": "bytes32[]" + } + ], + "name": "upgradeAccounts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } -] +] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/balanceTransfer.json b/sdk/python/bittensor/evm/abi/balanceTransfer.json index 99913b9005..b7b5041ab8 100644 --- a/sdk/python/bittensor/evm/abi/balanceTransfer.json +++ b/sdk/python/bittensor/evm/abi/balanceTransfer.json @@ -11,5 +11,41 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "destination", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "keepAlive", + "type": "bool" + } + ], + "name": "transferAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "destination", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferKeepAlive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/crowdloan.json b/sdk/python/bittensor/evm/abi/crowdloan.json index c507afcca2..3601e1fb1e 100644 --- a/sdk/python/bittensor/evm/abi/crowdloan.json +++ b/sdk/python/bittensor/evm/abi/crowdloan.json @@ -255,5 +255,28 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "crowdloanId", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "hasMaxContribution", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxContribution", + "type": "uint64" + } + ], + "name": "setMaxContribution", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/drand.json b/sdk/python/bittensor/evm/abi/drand.json new file mode 100644 index 0000000000..691f53f05b --- /dev/null +++ b/sdk/python/bittensor/evm/abi/drand.json @@ -0,0 +1,129 @@ +[ + { + "inputs": [], + "name": "getBeaconConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "period", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "genesisTime", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "chainHash", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "groupHash", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "schemeId", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "beaconId", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextUnsignedAt", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "round", + "type": "uint64" + } + ], + "name": "getPulse", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "storedRound", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "randomness", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStoredRoundRange", + "outputs": [ + { + "internalType": "uint64", + "name": "oldest", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latest", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "hasMigrationRun", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/sdk/python/bittensor/evm/abi/leasing.json b/sdk/python/bittensor/evm/abi/leasing.json index 88115ee29c..c4bdca22e0 100644 --- a/sdk/python/bittensor/evm/abi/leasing.json +++ b/sdk/python/bittensor/evm/abi/leasing.json @@ -168,5 +168,18 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "startCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/neuron.json b/sdk/python/bittensor/evm/abi/neuron.json index 44d47449eb..88d3a530b2 100644 --- a/sdk/python/bittensor/evm/abi/neuron.json +++ b/sdk/python/bittensor/evm/abi/neuron.json @@ -252,5 +252,531 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } -] + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newColdkeyHash", + "type": "bytes32" + } + ], + "name": "announceColdkeySwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "address", + "name": "evmKey", + "type": "address" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "associateEvmKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16[]", + "name": "netuids", + "type": "uint16[]" + }, + { + "internalType": "bytes32[]", + "name": "commitHashes", + "type": "bytes32[]" + } + ], + "name": "batchCommitWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16[][]", + "name": "uids", + "type": "uint16[][]" + }, + { + "internalType": "uint16[][]", + "name": "values", + "type": "uint16[][]" + }, + { + "internalType": "uint16[][]", + "name": "salts", + "type": "uint16[][]" + }, + { + "internalType": "uint64[]", + "name": "versionKeys", + "type": "uint64[]" + } + ], + "name": "batchRevealWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16[]", + "name": "netuids", + "type": "uint16[]" + }, + { + "internalType": "uint16[][]", + "name": "dests", + "type": "uint16[][]" + }, + { + "internalType": "uint16[][]", + "name": "values", + "type": "uint16[][]" + }, + { + "internalType": "uint64[]", + "name": "versionKeys", + "type": "uint64[]" + } + ], + "name": "batchSetWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearColdkeySwapAnnouncement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "commit", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + } + ], + "name": "commitCrv3MechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "commitHash", + "type": "bytes32" + } + ], + "name": "commitMechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "commit", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "commitRevealVersion", + "type": "uint16" + } + ], + "name": "commitTimelockedMechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes", + "name": "commit", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "commitRevealVersion", + "type": "uint16" + } + ], + "name": "commitTimelockedWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disputeColdkeySwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newColdkey", + "type": "bytes32" + } + ], + "name": "executeAnnouncedColdkeySwap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "work", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "register", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "uint16[]", + "name": "uids", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "values", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "salt", + "type": "uint16[]" + }, + { + "internalType": "uint64", + "name": "versionKey", + "type": "uint64" + } + ], + "name": "revealMechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "rootRegister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64[]", + "name": "proportions", + "type": "uint64[]" + }, + { + "internalType": "bytes32[]", + "name": "children", + "type": "bytes32[]" + } + ], + "name": "setChildren", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "string", + "name": "githubRepo", + "type": "string" + }, + { + "internalType": "string", + "name": "image", + "type": "string" + }, + { + "internalType": "string", + "name": "discord", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "additional", + "type": "string" + } + ], + "name": "setIdentity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mecid", + "type": "uint8" + }, + { + "internalType": "uint16[]", + "name": "dests", + "type": "uint16[]" + }, + { + "internalType": "uint16[]", + "name": "weights", + "type": "uint16[]" + }, + { + "internalType": "uint64", + "name": "versionKey", + "type": "uint64" + } + ], + "name": "setMechanismWeights", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newHotkey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "hasNetuid", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "swapHotkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newHotkey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "hasNetuid", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "keepStake", + "type": "bool" + } + ], + "name": "swapHotkeyV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "tryAssociateHotkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/proxy.json b/sdk/python/bittensor/evm/abi/proxy.json index 2f751002b7..ed10b00c9b 100644 --- a/sdk/python/bittensor/evm/abi/proxy.json +++ b/sdk/python/bittensor/evm/abi/proxy.json @@ -173,5 +173,77 @@ } ], "stateMutability": "view" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + } + ], + "name": "announce", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + } + ], + "name": "rejectAnnouncement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + } + ], + "name": "removeAnnouncement", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "paysFee", + "type": "bool" + } + ], + "name": "setRealPaysFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } -] +] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/registry.json b/sdk/python/bittensor/evm/abi/registry.json new file mode 100644 index 0000000000..b15d2cabd9 --- /dev/null +++ b/sdk/python/bittensor/evm/abi/registry.json @@ -0,0 +1,53 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "precompile", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "getPrecompileStatus", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "isDeprecated", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isDisabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "newPrecompile", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "newSelector", + "type": "bytes4" + }, + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "internalType": "struct IPrecompileRegistry.PrecompileStatus", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/sdk/python/bittensor/evm/abi/runtimeConfiguration.json b/sdk/python/bittensor/evm/abi/runtimeConfiguration.json new file mode 100644 index 0000000000..44d814754a --- /dev/null +++ b/sdk/python/bittensor/evm/abi/runtimeConfiguration.json @@ -0,0 +1,28 @@ +[ + { + "inputs": [], + "name": "getEvmChainId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransactionRateLimit", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/sdk/python/bittensor/evm/abi/scheduler.json b/sdk/python/bittensor/evm/abi/scheduler.json new file mode 100644 index 0000000000..8bf7ecbe5c --- /dev/null +++ b/sdk/python/bittensor/evm/abi/scheduler.json @@ -0,0 +1,183 @@ +[ + { + "inputs": [], + "name": "getIncompleteSince", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "when", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getRetry", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "totalRetries", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "remaining", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "period", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "when", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getScheduledCall", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bool", + "name": "hasTaskId", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "taskId", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "priority", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "hasCallLength", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "callLength", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "isPeriodic", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "period", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "remaining", + "type": "uint32" + } + ], + "internalType": "struct IScheduler.ScheduledCall", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "when", + "type": "uint64" + } + ], + "name": "getScheduledCallCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "taskId", + "type": "bytes32" + } + ], + "name": "getTaskAddress", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "when", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/sdk/python/bittensor/evm/abi/stakingV2.json b/sdk/python/bittensor/evm/abi/stakingV2.json index 64edc7ae3d..f0b7177168 100644 --- a/sdk/python/bittensor/evm/abi/stakingV2.json +++ b/sdk/python/bittensor/evm/abi/stakingV2.json @@ -809,5 +809,440 @@ "outputs": [], "stateMutability": "payable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "alpha", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limitPrice", + "type": "uint64" + } + ], + "name": "addCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "hasLimit", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "limit", + "type": "uint64" + } + ], + "name": "addStakeBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16[]", + "name": "subnets", + "type": "uint16[]" + } + ], + "name": "claimRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "name": "decreaseTake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "name": "increaseTake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "recycleAlpha", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setAutoParentDelegationEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "name": "setChildkeyTake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "setColdkeyAutoStakeHotkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint128", + "name": "rawRatio", + "type": "uint128" + } + ], + "name": "setCollateralDrainRatio", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "lockShare", + "type": "uint16" + } + ], + "name": "setCollateralLockShare", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "name": "setMinChildkeyTakePerSubnet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "minLocked", + "type": "uint64" + } + ], + "name": "setMinCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "threshold", + "type": "uint64" + } + ], + "name": "setRootClaimThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "claimType", + "type": "uint8" + }, + { + "internalType": "uint16[]", + "name": "subnets", + "type": "uint16[]" + } + ], + "name": "setRootClaimType", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "originNetuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "destinationNetuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alphaAmount", + "type": "uint64" + } + ], + "name": "swapStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "originNetuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "destinationNetuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alphaAmount", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "limitPrice", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "allowPartial", + "type": "bool" + } + ], + "name": "swapStakeLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "destinationColdkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "originHotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "destinationHotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "originNetuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "destinationNetuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "alphaAmount", + "type": "uint64" + } + ], + "name": "transferStakeAndHotkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "unstakeAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "unstakeAllAlpha", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } -] +] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/subnet.json b/sdk/python/bittensor/evm/abi/subnet.json index e765c37c4a..7e5046d854 100644 --- a/sdk/python/bittensor/evm/abi/subnet.json +++ b/sdk/python/bittensor/evm/abi/subnet.json @@ -1159,5 +1159,274 @@ "outputs": [], "stateMutability": "payable", "type": "function" - } -] + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "string", + "name": "subnetName", + "type": "string" + }, + { + "internalType": "string", + "name": "githubRepo", + "type": "string" + }, + { + "internalType": "string", + "name": "subnetContact", + "type": "string" + }, + { + "internalType": "string", + "name": "subnetUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "discord", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + }, + { + "internalType": "string", + "name": "logoUrl", + "type": "string" + }, + { + "internalType": "string", + "name": "additional", + "type": "string" + } + ], + "name": "setSubnetIdentity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "name": "updateSubnetSymbol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "triggerEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "bondsPenalty", + "type": "uint16" + } + ], + "name": "setBondsPenalty", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxAllowedUids", + "type": "uint16" + } + ], + "name": "setMaxAllowedUids", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "maxBurn", + "type": "uint64" + } + ], + "name": "setMaxBurnV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mechanismCount", + "type": "uint8" + } + ], + "name": "setMechanismCount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "hasSplit", + "type": "bool" + }, + { + "internalType": "uint16[]", + "name": "split", + "type": "uint16[]" + } + ], + "name": "setMechanismEmissionSplit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "minBurn", + "type": "uint64" + } + ], + "name": "setMinBurnV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setOwnerCutEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "immuneNeurons", + "type": "uint16" + } + ], + "name": "setOwnerImmuneNeuronLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "tempo", + "type": "uint16" + } + ], + "name": "setTempo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxUids", + "type": "uint16" + } + ], + "name": "trimToMaxAllowedUids", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/timestamp.json b/sdk/python/bittensor/evm/abi/timestamp.json new file mode 100644 index 0000000000..78d2ee9784 --- /dev/null +++ b/sdk/python/bittensor/evm/abi/timestamp.json @@ -0,0 +1,28 @@ +[ + { + "inputs": [], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wasUpdatedThisBlock", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/sdk/python/bittensor/evm/abi/votingPower.json b/sdk/python/bittensor/evm/abi/votingPower.json index a2694e9a99..d825bcdfde 100644 --- a/sdk/python/bittensor/evm/abi/votingPower.json +++ b/sdk/python/bittensor/evm/abi/votingPower.json @@ -98,5 +98,31 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "disableVotingPowerTracking", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "enableVotingPowerTracking", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } -] +] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/precompiles.py b/sdk/python/bittensor/evm/precompiles.py index 5d627cfd79..d1061f63ad 100644 --- a/sdk/python/bittensor/evm/precompiles.py +++ b/sdk/python/bittensor/evm/precompiles.py @@ -66,7 +66,7 @@ def _load_abi(filename: str) -> list[dict]: "balance-transfer", 2048, "balanceTransfer.json", - "Send TAO from an EVM account to any ss58 address (payable transfer(bytes32 pubkey)).", + "Transfer TAO from an EVM account to an ss58 account.", ), Precompile( "staking", @@ -109,7 +109,7 @@ def _load_abi(filename: str) -> list[dict]: "alpha", 2056, "alpha.json", - "Subnet alpha token info: prices, pool reserves, and alpha amounts.", + "Subnet Alpha pools, prices, issuance, emissions, and owner configuration.", ), Precompile( "crowdloan", @@ -127,7 +127,7 @@ def _load_abi(filename: str) -> list[dict]: "proxy", 2059, "proxy.json", - "Add/remove proxy delegations from EVM.", + "Manage proxy delegations and delayed proxy announcements from EVM.", ), Precompile( "address-mapping", @@ -145,7 +145,37 @@ def _load_abi(filename: str) -> list[dict]: "balance", 2062, "balance.json", - "Read native free TAO balance for any ss58 coldkey (getFreeBalance(bytes32) -> rao).", + "Read free TAO balances and dispatch signed Balances operations.", + ), + Precompile( + "scheduler", + 2063, + "scheduler.json", + "Read stable metadata for scheduled runtime calls.", + ), + Precompile( + "drand", + 2064, + "drand.json", + "Read stored Drand beacon configuration and pulse data.", + ), + Precompile( + "timestamp", + 2065, + "timestamp.json", + "Read the runtime timestamp and its per-block update state.", + ), + Precompile( + "runtime-configuration", + 2066, + "runtimeConfiguration.json", + "Read stable global runtime configuration.", + ), + Precompile( + "precompile-registry", + 2067, + "registry.json", + "Inspect precompile lifecycle and operational availability.", ), Precompile( "ed25519-verify", @@ -297,6 +327,16 @@ def coerce_argument(abi_type: str, raw: Any) -> Any: nobody should have to run the conversion by hand. """ text = str(raw).strip() + if abi_type.endswith("[]"): + inner = abi_type[:-2] + parts = ( + raw + if isinstance(raw, list) + else json.loads(text) + if text.startswith("[") + else text.split(",") + ) + return [coerce_argument(inner, part) for part in parts] if abi_type.startswith(("uint", "int")): return int(text, 16 if text.startswith("0x") else 10) if abi_type == "bool": @@ -308,10 +348,6 @@ def coerce_argument(abi_type: str, raw: Any) -> Any: # ss58 -> 32-byte public key, the shape hotkey/coldkey params take return bytes.fromhex(ss58_to_pubkey(text)[2:]) return bytes.fromhex(text.removeprefix("0x")) - if abi_type.endswith("[]"): - inner = abi_type[:-2] - parts = json.loads(text) if text.startswith("[") else text.split(",") - return [coerce_argument(inner, part) for part in parts] return text diff --git a/sdk/python/tests/unit/test_evm.py b/sdk/python/tests/unit/test_evm.py index 931404dd5d..b3a85d0145 100644 --- a/sdk/python/tests/unit/test_evm.py +++ b/sdk/python/tests/unit/test_evm.py @@ -86,6 +86,16 @@ def test_balance_transfer_encode(self): data = precompiles.encode_call(fn_abi, [addresses.ss58_to_pubkey(ALICE)]) assert data.startswith("0x") + def test_new_bounded_array_calls_encode(self): + claim_root = precompiles.get_precompile("staking-v2").function("claimRoot") + assert precompiles.encode_call(claim_root, ["[1, 2]"]).startswith("0x") + + batch_commit = precompiles.get_precompile("neuron").function("batchCommitWeights") + assert precompiles.encode_call( + batch_commit, + ["[1, 2]", ["0x" + "11" * 32, "0x" + "22" * 32]], + ).startswith("0x") + # The vendored ABIs in bittensor/evm/abi must stay in sync with the canonical # .abi artifacts in precompiles/src/solidity (see the bittensor.evm.precompiles From 26d9925cd439acbc621580febbb9f2f89262c8d6 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Thu, 30 Jul 2026 17:09:01 -0400 Subject: [PATCH 17/58] Add rules for read exposure of state variables and maps --- .agents/skills/emv-maintainer/SKILL.md | 19 +++++- .../references/coverage-and-testing.md | 12 +++- .../emv-maintainer/references/exceptions.md | 43 +++++++++++++ .../references/state-exposure.md | 61 +++++++++++++++++++ 4 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 .agents/skills/emv-maintainer/references/exceptions.md create mode 100644 .agents/skills/emv-maintainer/references/state-exposure.md diff --git a/.agents/skills/emv-maintainer/SKILL.md b/.agents/skills/emv-maintainer/SKILL.md index cf70ec198e..f309a52c6d 100644 --- a/.agents/skills/emv-maintainer/SKILL.md +++ b/.agents/skills/emv-maintainer/SKILL.md @@ -14,6 +14,14 @@ You are the maintainer of EVM precompiles. EVM precompiles in subtensor should e read [ABI versioning](references/abi-versioning.md). - Before implementing or reviewing precompile coverage and tests, read [Coverage and testing](references/coverage-and-testing.md). +- Before classifying pallet state or adding, reviewing, or omitting a typed + state view, read [State exposure](references/state-exposure.md) and use its + direct, wrapped, and do-not-expose classifications. Do not override a + classification without an explicit human decision. +- Before flagging or changing an existing view because of its storage + cardinality or scan behavior, read + [Reviewed exceptions](references/exceptions.md). Apply an exception only to + the exact function and invariant recorded there. ## Backwards compatibility @@ -50,7 +58,9 @@ For each affected released function: ## Notes on coding precompiles -- Keep every precompile path O(1) in CPU and memory. +- Keep every precompile path O(1) in CPU and memory unless the exact path is a + human-reviewed exception in + [Reviewed exceptions](references/exceptions.md). - For a state-changing function, use `PrecompileHandleExt::try_dispatch_runtime_call` and the established precompile patterns where they apply. Construct the highest-level pallet @@ -68,7 +78,9 @@ For each affected released function: to grant the caller a stronger origin, stop and request that design. - Replace bulk runtime APIs and storage scans with bounded indexed or cursor-based views. Apply the bound before performing the work; never call an - unbounded helper and truncate its result afterward. + unbounded helper and truncate its result afterward. Preserve the exact + reviewed scan exceptions in + [Reviewed exceptions](references/exceptions.md). - Follow [ABI versioning](references/abi-versioning.md) for every released interface. - Treat repository-owned Rust function lifecycle annotations as the source of @@ -111,6 +123,9 @@ For each affected released function: Use [Coverage and testing](references/coverage-and-testing.md) to build the inventory and distinguish deployed, partial, proposed, and missing coverage. +Use [State exposure](references/state-exposure.md) to classify every state item +and [Reviewed exceptions](references/exceptions.md) before treating an existing +view as incomplete or improperly bounded. ## Step 2 — Determine the diff diff --git a/.agents/skills/emv-maintainer/references/coverage-and-testing.md b/.agents/skills/emv-maintainer/references/coverage-and-testing.md index f4b711c33b..b60feadb2d 100644 --- a/.agents/skills/emv-maintainer/references/coverage-and-testing.md +++ b/.agents/skills/emv-maintainer/references/coverage-and-testing.md @@ -89,6 +89,11 @@ Inventory every public state map and value in scope. Expose its meaningful contents through typed view functions; never provide direct writable access to storage. +Apply the classifications in [State exposure](state-exposure.md). Before +changing an existing view because its shape appears incomplete or unbounded, +check [Reviewed exceptions](exceptions.md). Treat exceptions as exact, +human-reviewed cases rather than patterns to extend by analogy. + Let a view read one or more storage items when that is required to return the meaningful value. Keep the mapping from source storage to typed functions explicit in the coverage inventory so no item disappears behind an abstract @@ -211,8 +216,11 @@ remove unrelated regeneration changes. ## Validate cost and bounds Keep every precompile path bounded in CPU, memory, storage access, and output -size. Record database reads and writes and dispatch weight through the existing -helpers. +size, except for the exact human-reviewed cases in +[Reviewed exceptions](exceptions.md). Record database reads and writes and +dispatch weight through the existing helpers. For an accepted scan exception, +test the protocol limit that makes the scan acceptable and charge for the +complete permitted scan. Test: diff --git a/.agents/skills/emv-maintainer/references/exceptions.md b/.agents/skills/emv-maintainer/references/exceptions.md new file mode 100644 index 0000000000..5da61b2489 --- /dev/null +++ b/.agents/skills/emv-maintainer/references/exceptions.md @@ -0,0 +1,43 @@ +# Reviewed precompile exceptions + +This file records narrow, human-reviewed exceptions to the general state +coverage and bounded-work rules. Apply an exception only to the exact function +and invariant described here. Do not infer that a similar storage shape or +collection is also exempt. + +When reviewing one of these functions, verify that its supporting invariant +still holds. If the runtime changes that invariant, stop treating the function +as an exception and reassess its interface, compatibility, cost, and tests. + +## `getColdkeyLock(bytes32,uint256)` + +`getColdkeyLock` returns the one individual lock for a `(coldkey, netuid)`. +Although `Lock` includes the target hotkey in its storage key and the +implementation locates the row with `iter_prefix(...).next()`, multiple lock +rows are not valid state for that pair: + +- `do_lock_stake` creates the lock when none exists and rejects a different + target hotkey with `LockHotkeyMismatch` when one already exists; +- `move_lock` moves the existing lock to a new target instead of creating a + second lock; and +- the lock is subnet-wide for the coldkey, while the hotkey identifies its + current target. + +The precompile therefore reflects the runtime design accurately and does not +need a paginated or hotkey-keyed replacement. Keep tests proving that a second +target is rejected and that moving a lock leaves exactly one row. + +This exception becomes invalid if any lock creation, transfer, migration, or +repair path permits multiple `Lock` rows for the same `(coldkey, netuid)`. + +## `getSumAlphaPrice()` + +`getSumAlphaPrice` may scan every subnet. Subnets are a protocol-limited, +scarce resource, and the function's meaningful result is the aggregate over +the complete set. A cursor would change that meaning and move composition to +the caller. + +Keep the complete scan, charge for all permitted subnet reads, and test it at +the configured subnet limit. This exception does not apply to collections +whose size grows with accounts, neurons, stakes, commitments, or other +user-created records. diff --git a/.agents/skills/emv-maintainer/references/state-exposure.md b/.agents/skills/emv-maintainer/references/state-exposure.md new file mode 100644 index 0000000000..f64e63ec46 --- /dev/null +++ b/.agents/skills/emv-maintainer/references/state-exposure.md @@ -0,0 +1,61 @@ +# Rules of exposing the state variables and maps + +This file lists concrete state variables and maps and classifies them as one of three classes: + +1. Safe to expose directly, as is, or +2. Need some type-safe wrapping, or +3. Internal, do not need to be exposed, or already known to be deprecated soon + +The class 1 state variables and maps are not anticipated to change anytime soon or change significantly. Also, even if they do, it is expected that their exposed values can be easily simulated or recalculated with no greater than O(1) complexity. + +The class 2 state variables and maps are not expected to stay for a long time, are temporary, or express complex formulas and need to be safely wrapped. + +## Safe to expose directly + +### Pallet subtensor + +- Delegation and childkeys: Delegates, ChildkeyTake, PendingChildKeys, ChildKeys, ParentKeys, PendingChildKeyCooldown, minimum/maximum delegate and childkey takes, and MinChildkeyTakePerSubnet. + +- Ownership and account relationships: OwnedHotkeys, AutoStakeDestination, AutoStakeDestinationColdkeys, HotkeySuccessor, HotkeyRoot, ColdkeySuccessor, ColdkeyRoot, coldkey-swap announcements/disputes/delays, and LastHotkeySwapOnNetuid. Owner is only indirectly available when the caller already knows a subnet UID, so arbitrary hotkey ownership is only partially covered. + +- Subnet identity and configuration: TokenSymbol, SubnetOwner, SubnetOwnerHotkey, Tempo, RecycleOrBurn, BondsPenalty, MaxAllowedUids, MaxAllowedValidators, AdjustmentInterval, TargetRegistrationsPerInterval, OwnerCutEnabled, ImmuneOwnerUidsLimit, MechanismCountCurrent, MechanismEmissionSplit, BurnHalfLife, BurnIncreaseMult, TransferToggle, MinAllowedUids, MinNonImmuneUids, and numerous global network limits. + +- Emission and economic accounting: BlockEmission, Subtensor TotalIssuance, TotalStake, AlphaDividendsPerSubnet, RootAlphaDividendsPerSubnet, LastHotkeyEmissionOnNetuid, SubnetMovingAlpha, RootProp, SubnetEmissionEnabled, SubnetExcessTao, SubnetRootSellTao, SubnetProtocolAlpha, flow/EMA maps, emission gate configuration, pending emission/cut maps, MinerBurned, and RAORecycledForRegistration. + +- Neuron state: Uids, IsNetworkMember, Weights, Bonds, BlockAtRegistration, NeuronCertificates, Prometheus, IdentitiesV2, SubnetIdentitiesV3, LoadedEmission, transaction-rate timestamps, and all weight-commit maps and versions. + +- Collateral and leasing: MinerCollateral, ColdkeyMinerCollateral, ColdkeyCollateralHotkeys, CollateralLockShare, CollateralDrainRatio, NextSubnetLeaseId, and AccumulatedLeaseDividends. + +- EVM associations: Forward view for AssociatedEvmAddress(netuid, uid). + +### Pallet balances + +TotalIssuance + +### Pallet Proxy + +proxy deposit, Announcements, LastCallResult, RealPaysFee + +### Pallet Swap + +FeeRate, SwapBalancer, BalancerTaoReservoir, BalancerAlphaReservoir, HasMigrationRun + +## Need some type-safe wrapping + +### Pallet Swap + +PalSwapInitialized and its successors should be exposed as just generic "IsSwapInitialized", non-specific to palswap / balancer. + +## Do not expose + +### Pallet subtensor + +- Root claims: RootClaimableThreshold, RootClaimable, RootClaimed, RootClaimType. + +### Pallet balances + +InactiveIssuance, the reserved, frozen, and flags portions of Account: Locks, Reserves, Holds, Freezes + +### Pallet swap + +ScrapReservoirAlpha \ No newline at end of file From 3fe23771a124f37e07cd63c34fb74fb6103f49a9 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Fri, 31 Jul 2026 11:05:19 -0400 Subject: [PATCH 18/58] Precompiles: Add missing readers --- .../evm/precompiles/account-balance.mdx | 1 + docs/guides/evm/precompiles/alpha.mdx | 11 + docs/guides/evm/precompiles/leasing.mdx | 2 + docs/guides/evm/precompiles/neuron.mdx | 27 + docs/guides/evm/precompiles/proxy.mdx | 12 + docs/guides/evm/precompiles/staking-v2.mdx | 38 + docs/guides/evm/precompiles/subnet.mdx | 54 ++ docs/guides/evm/precompiles/uid-lookup.mdx | 24 + docs/guides/evm/precompiles/voting-power.mdx | 5 + pallets/proxy/src/lib.rs | 14 + pallets/subtensor/src/lib.rs | 6 + pallets/subtensor/src/macros/hooks.rs | 4 +- .../migrations/migrate_total_voting_power.rs | 68 ++ pallets/subtensor/src/migrations/mod.rs | 1 + pallets/subtensor/src/tests/voting_power.rs | 36 + pallets/subtensor/src/utils/voting_power.rs | 41 +- precompiles/src/alpha.rs | 262 ++++++- precompiles/src/balance.rs | 18 + precompiles/src/leasing.rs | 43 ++ precompiles/src/lib.rs | 164 ++++ precompiles/src/neuron.rs | 552 +++++++++++++- precompiles/src/proxy.rs | 178 ++++- precompiles/src/solidity/alpha.abi | 268 +++++++ precompiles/src/solidity/alpha.sol | 73 ++ precompiles/src/solidity/balance.abi | 13 + precompiles/src/solidity/balance.sol | 1 + precompiles/src/solidity/leasing.abi | 32 + precompiles/src/solidity/leasing.sol | 4 + precompiles/src/solidity/neuron.abi | 678 +++++++++++++++++ precompiles/src/solidity/neuron.sol | 149 ++++ precompiles/src/solidity/proxy.abi | 123 +++ precompiles/src/solidity/proxy.sol | 25 + precompiles/src/solidity/stakingV2.abi | 624 +++++++++++++++ precompiles/src/solidity/stakingV2.sol | 100 +++ precompiles/src/solidity/subnet.abi | 345 ++++++++- precompiles/src/solidity/subnet.sol | 116 ++- precompiles/src/solidity/uidLookup.abi | 36 +- precompiles/src/solidity/uidLookup.sol | 4 + precompiles/src/staking.rs | 716 +++++++++++++++++- precompiles/src/subnet.rs | 445 ++++++++++- precompiles/src/uid_lookup.rs | 43 ++ precompiles/src/voting_power.rs | 13 +- sdk/python/bittensor/evm/abi/alpha.json | 268 +++++++ sdk/python/bittensor/evm/abi/balance.json | 13 + sdk/python/bittensor/evm/abi/leasing.json | 32 + sdk/python/bittensor/evm/abi/neuron.json | 678 +++++++++++++++++ sdk/python/bittensor/evm/abi/proxy.json | 123 +++ sdk/python/bittensor/evm/abi/stakingV2.json | 624 +++++++++++++++ sdk/python/bittensor/evm/abi/subnet.json | 345 ++++++++- sdk/python/bittensor/evm/abi/uidLookup.json | 36 +- 50 files changed, 7446 insertions(+), 42 deletions(-) create mode 100644 docs/guides/evm/precompiles/uid-lookup.mdx create mode 100644 pallets/subtensor/src/migrations/migrate_total_voting_power.rs diff --git a/docs/guides/evm/precompiles/account-balance.mdx b/docs/guides/evm/precompiles/account-balance.mdx index a665cd574a..478cbcf9f9 100644 --- a/docs/guides/evm/precompiles/account-balance.mdx +++ b/docs/guides/evm/precompiles/account-balance.mdx @@ -15,6 +15,7 @@ description: Reference for the deployed BalancePrecompile. | Function | Mutability | |---|---| | `getFreeBalance(bytes32)` | `view` | +| `getTotalIssuance()` | `view` | ## Added operations diff --git a/docs/guides/evm/precompiles/alpha.mdx b/docs/guides/evm/precompiles/alpha.mdx index 05b4fb2b2e..ae4cf01904 100644 --- a/docs/guides/evm/precompiles/alpha.mdx +++ b/docs/guides/evm/precompiles/alpha.mdx @@ -34,8 +34,19 @@ getAlphaInEmission(uint16) getAlphaOutEmission(uint16) getSumAlphaPrice() getCKBurn() +getEmissionAccounting(uint16,bytes32) +getSubnetEconomicState(uint16) +getSubnetFlowState(uint16) +getEmissionGateConfig() +getSwapState(uint16) +hasSwapMigrationRun(bytes) ``` +Flow values use signed Solidity integers. Fixed-point economic values are +returned as their raw runtime bits. `getSwapState` includes the fee, +initialization status, balancer quote weight, and both protocol reservoirs; +the initialization flag is the generic swap-initialization view. + ## Added operations | Function | Source extrinsic | diff --git a/docs/guides/evm/precompiles/leasing.mdx b/docs/guides/evm/precompiles/leasing.mdx index 2550312355..52694ee71f 100644 --- a/docs/guides/evm/precompiles/leasing.mdx +++ b/docs/guides/evm/precompiles/leasing.mdx @@ -16,6 +16,8 @@ description: Reference for the deployed LeasingPrecompile. getLease(uint32) getContributorShare(uint32,bytes32) getLeaseIdForSubnet(uint16) +getNextLeaseId() +getAccumulatedLeaseDividends(uint32) ``` ## Operations diff --git a/docs/guides/evm/precompiles/neuron.mdx b/docs/guides/evm/precompiles/neuron.mdx index d0c6ff1d12..3a7cd165d0 100644 --- a/docs/guides/evm/precompiles/neuron.mdx +++ b/docs/guides/evm/precompiles/neuron.mdx @@ -67,6 +67,33 @@ dispatches the highest-level extrinsic as the mapped caller so runtime authorization remains in force. Root-only and deprecated compatibility calls are classified in the [coverage audit](./extrinsic-coverage). +## Typed state views + +```text +getUid(uint16,bytes32) +isNetworkMember(bytes32,uint16) +getWeights(uint16,uint16) +getBonds(uint16,uint16) +getBlockAtRegistration(uint16,uint16) +getNeuronCertificate(uint16,bytes32) +getPrometheus(uint16,bytes32) +getChainIdentity(bytes32) +getSubnetIdentity(uint16) +getLoadedEmission(uint16) +getTransactionKeyLastBlock(bytes32,uint16,uint16) +getLegacyTransactionRateBlocks(bytes32) +getWeightCommitCount(uint16,bytes32) +getWeightCommit(uint16,bytes32,uint32) +getTimelockedWeightCommitCount(uint16,uint64) +getTimelockedWeightCommit(uint16,uint64,uint32) +getLegacyTimelockedWeightCommitCount(uint8,uint16,uint64) +getLegacyTimelockedWeightCommit(uint8,uint16,uint64,uint32) +``` + +The indexed commit readers expose stable metadata. Timelocked ciphertext is +represented by its Keccak-256 hash and byte length instead of returning the +runtime's encrypted payload type. + ## Proposed bulk runtime API `NeuronInfoRuntimeApi.get_neurons` remains proposed. Its current result can diff --git a/docs/guides/evm/precompiles/proxy.mdx b/docs/guides/evm/precompiles/proxy.mdx index c8791f4732..0880a66b39 100644 --- a/docs/guides/evm/precompiles/proxy.mdx +++ b/docs/guides/evm/precompiles/proxy.mdx @@ -22,6 +22,18 @@ description: Reference for the deployed ProxyPrecompile. | `removeProxies()` | nonpayable | | `pokeDeposit()` | nonpayable | | `getProxies(bytes32)` | `view` | +| `getProxyDeposit(bytes32)` | `view` | +| `getAnnouncements(bytes32)` | `view` | +| `getLastCallResult(bytes32)` | `view` | +| `isRealPaysFee(bytes32,bytes32)` | `view` | + +`getLastCallResult` returns stable success/error metadata. Module errors expose +the pallet index and four error bytes. Error kinds are `1` Other, `2` +CannotLookup, `3` BadOrigin, `4` Module, `5` ConsumerRemaining, `6` +NoProviders, `7` TooManyConsumers, `8` Token, `9` Arithmetic, `10` +Transactional, `11` Exhausted, `12` Corruption, `13` Unavailable, `14` +RootNotAllowed, and `15` Trie. This avoids returning SCALE-encoded runtime +data. ## Added operations diff --git a/docs/guides/evm/precompiles/staking-v2.mdx b/docs/guides/evm/precompiles/staking-v2.mdx index 82a324be34..e57ed90de4 100644 --- a/docs/guides/evm/precompiles/staking-v2.mdx +++ b/docs/guides/evm/precompiles/staking-v2.mdx @@ -45,6 +45,44 @@ getDefaultMinStake() These functions are `view`. +## Relationship and ownership views + +```text +getDelegate(bytes32) +getChildkeyTake(bytes32,uint16) +getPendingChildKeys(bytes32,uint16) +getChildKeys(bytes32,uint16) +getParentKeys(bytes32,uint16) +getPendingChildKeyCooldown() +getTakeLimits() +getMinChildkeyTakePerSubnet(uint16) +getHotkeyOwner(bytes32) +getOwnedHotkeys(bytes32) +getAutoStakeDestination(bytes32,uint16) +getAutoStakeDestinationColdkeys(bytes32,uint16) +getHotkeySuccessor(bytes32,uint16) +getHotkeyRoot(bytes32,uint16) +getColdkeySuccessor(bytes32) +getColdkeyRoot(bytes32) +getColdkeySwapStatus(bytes32) +getColdkeySwapDelays() +getLastHotkeySwapOnSubnet(bytes32,uint16) +``` + +Optional relationships return an explicit `exists` flag. Child and parent +links return typed `(proportion, account)` entries. + +## Accounting and collateral views + +```text +getStakeAccounting() +getMinerCollateral(uint16,bytes32,bytes32) +getColdkeyCollateral(uint16,bytes32) +getCollateralConfig(uint16) +``` + +Fixed-point collateral ratios are returned as their raw `U64F64` bits. + ## Locks and account policy ```text diff --git a/docs/guides/evm/precompiles/subnet.mdx b/docs/guides/evm/precompiles/subnet.mdx index acf9f492bb..0caa4dd9f6 100644 --- a/docs/guides/evm/precompiles/subnet.mdx +++ b/docs/guides/evm/precompiles/subnet.mdx @@ -48,6 +48,7 @@ getMinDifficulty(uint16) getNetworkPowRegistrationAllowed(uint16) getNetworkRegistrationAllowed(uint16) getNetworkRegistrationBlock(uint16) +getRegisteredSubnetCounter(uint16) getOwnerCutAutoLockEnabled(uint16) getRho(uint16) getServingRateLimit(uint16) @@ -55,8 +56,61 @@ getWeightsSetRateLimit(uint16) getWeightsVersionKey(uint16) getYuma3Enabled(uint16) isSubnetDissolving(uint16) +getSubnetDissolutionStatus(uint16) +getSubnetMetadata(uint16) +getSubnetCapacityConfig(uint16) +getMechanismEmissionSplit(uint16) +getBurnConfig(uint16) +getGlobalNetworkLimits() +getGlobalRateLimits() +getGlobalProtocolConfig() ``` +The grouped configuration views return stable typed fields rather than raw +storage encodings. Fixed-point burn multipliers are returned as raw `U64F64` +bits. + +`getRegisteredSubnetCounter` returns a monotonic generation number for a +netuid. It increments on every successful registration, allowing a contract to +distinguish a reused netuid even when it did not retain the previous +registration block. + +`getSubnetDissolutionStatus` returns `(isDissolving, cleanupInProgress, +cleanupPhase)`. Phase `0` means that detailed cleanup has not started. Active +cleanup uses stable, append-only phase codes: + +| Code | Cleanup work | +|---:|---| +| 1 | Root claimable dividends | +| 2 | Root claimed dividends | +| 3 | Calculate stake value | +| 4 | Settle stakes | +| 5 | Clear alpha | +| 6 | Clear hotkey totals | +| 7 | Clear stake locks | +| 8 | Clear decaying stake locks | +| 9 | Finish stake cleanup | +| 10 | Clear protocol liquidity | +| 11 | Purge subnet commitments | +| 12 | Clear network membership | +| 13 | Clear network parameters | +| 14 | Clear network maps | +| 15 | Update root weights | +| 16 | Clear childkey takes | +| 17 | Clear childkeys | +| 18 | Clear parentkeys | +| 19 | Clear last hotkey emissions | +| 20 | Clear last-epoch hotkey alpha | +| 21 | Clear transaction rate-limit records | +| 22 | Clear network locks | +| 23 | Clear decaying network locks | + +The runtime does not currently store a per-subnet future dissolution block. +The authorized dissolution calls execute dissolution immediately, while the +generic scheduler stores calls by agenda position rather than maintaining a +typed netuid-to-dissolution lookup. Consequently, there is no truthful, +bounded per-subnet scheduled-block view to expose. + ## Configuration ```text diff --git a/docs/guides/evm/precompiles/uid-lookup.mdx b/docs/guides/evm/precompiles/uid-lookup.mdx new file mode 100644 index 0000000000..a34bf4a19f --- /dev/null +++ b/docs/guides/evm/precompiles/uid-lookup.mdx @@ -0,0 +1,24 @@ +--- +title: UID lookup +description: Reference for the deployed UidLookupPrecompile. +--- + +| Property | Value | +|---|---| +| Rust implementation | `UidLookupPrecompile` | +| Solidity interface | `IUidLookup` | +| Address | `0x0000000000000000000000000000000000000806` | +| Status | Deployed | + +## Views + +```text +uidLookup(uint16,address,uint16) +getAssociatedEvmAddress(uint16,uint16) +``` + +`uidLookup` returns the bounded reverse association list for an EVM address. +`getAssociatedEvmAddress` returns the forward address and the block at which +ownership was last proved, with an explicit `exists` flag. + +Source: [`uidLookup.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/uidLookup.sol) diff --git a/docs/guides/evm/precompiles/voting-power.mdx b/docs/guides/evm/precompiles/voting-power.mdx index 5e8742908e..6fda95fe61 100644 --- a/docs/guides/evm/precompiles/voting-power.mdx +++ b/docs/guides/evm/precompiles/voting-power.mdx @@ -22,6 +22,11 @@ getVotingPowerEmaAlpha(uint16) getTotalVotingPower(uint16) ``` +`getTotalVotingPower` reads a maintained per-subnet aggregate. A one-time +runtime migration initializes the aggregate from existing validator entries; +normal epoch updates, removals, swaps, and tracking disablement keep it in +sync without a precompile-side map scan. + ## Added operations | Function | Source extrinsic | diff --git a/pallets/proxy/src/lib.rs b/pallets/proxy/src/lib.rs index 1fca855327..4e5b781555 100644 --- a/pallets/proxy/src/lib.rs +++ b/pallets/proxy/src/lib.rs @@ -93,6 +93,20 @@ pub struct Announcement { height: BlockNumber, } +impl Announcement { + pub fn real(&self) -> &AccountId { + &self.real + } + + pub fn call_hash(&self) -> &Hash { + &self.call_hash + } + + pub fn height(&self) -> &BlockNumber { + &self.height + } +} + /// The type of deposit #[derive( Encode, diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 3cf4318e9d..957df5ea93 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -2410,6 +2410,12 @@ pub mod pallet { pub type VotingPower = StorageDoubleMap<_, Identity, NetUid, Blake2_128Concat, T::AccountId, u64, ValueQuery>; + #[pallet::storage] + /// MAP ( netuid ) --> total_voting_power | Sum of all validator voting-power + /// entries on the subnet. Kept in sync with `VotingPower` so consumers can + /// read the aggregate without iterating the complete validator map. + pub type TotalVotingPower = StorageMap<_, Identity, NetUid, u64, ValueQuery>; + #[pallet::storage] /// MAP ( netuid ) --> bool | Whether voting power tracking is enabled for this subnet. /// When enabled, VotingPower EMA is updated every epoch. Default is false. diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index 6d3692d9a2..97eb5125b8 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -183,7 +183,9 @@ mod hooks { // Remove orphan SubnetIdentitiesV3 entries left for recycled netuids. .saturating_add(migrations::migrate_clear_orphan_subnet_identities_v3::migrate_clear_orphan_subnet_identities_v3::()) // Backfill ColdkeyCollateralHotkeys from standing MinerCollateral rows. - .saturating_add(migrations::migrate_coldkey_collateral_hotkeys::migrate_coldkey_collateral_hotkeys::()); + .saturating_add(migrations::migrate_coldkey_collateral_hotkeys::migrate_coldkey_collateral_hotkeys::()) + // Backfill the O(1) aggregate used by the voting-power precompile. + .saturating_add(migrations::migrate_total_voting_power::migrate_total_voting_power::()); weight } diff --git a/pallets/subtensor/src/migrations/migrate_total_voting_power.rs b/pallets/subtensor/src/migrations/migrate_total_voting_power.rs new file mode 100644 index 0000000000..2fa5343846 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_total_voting_power.rs @@ -0,0 +1,68 @@ +use crate::{Config, HasMigrationRun, TotalVotingPower, VotingPower}; +use alloc::collections::BTreeMap; +use frame_support::{traits::Get, weights::Weight}; +use subtensor_runtime_common::NetUid; + +const MIGRATION_NAME: &[u8] = b"migrate_total_voting_power"; + +/// Backfill the per-subnet voting-power aggregate from the existing +/// `VotingPower` entries. The full scan happens once during the runtime +/// upgrade; subsequent reads use `TotalVotingPower` in O(1). +pub fn migrate_total_voting_power() -> Weight { + let migration_name = MIGRATION_NAME.to_vec(); + let mut reads = 1u64; + + if HasMigrationRun::::get(&migration_name) { + return T::DbWeight::get().reads(reads); + } + + let mut totals = BTreeMap::::new(); + for (netuid, _, voting_power) in VotingPower::::iter() { + reads = reads.saturating_add(1); + totals + .entry(netuid) + .and_modify(|total| *total = total.saturating_add(voting_power)) + .or_insert(voting_power); + } + + let mut writes = 1u64; + for (netuid, total) in totals { + TotalVotingPower::::insert(netuid, total); + writes = writes.saturating_add(1); + } + + HasMigrationRun::::insert(&migration_name, true); + T::DbWeight::get().reads_writes(reads, writes) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{tests::mock::*, *}; + use sp_core::U256; + + #[test] + fn migration_backfills_total_voting_power_once() { + new_test_ext(1).execute_with(|| { + let first_netuid = NetUid::from(1); + let second_netuid = NetUid::from(2); + VotingPower::::insert(first_netuid, U256::from(1), 10); + VotingPower::::insert(first_netuid, U256::from(2), 20); + VotingPower::::insert(second_netuid, U256::from(3), 7); + + let weight = migrate_total_voting_power::(); + + assert_eq!(TotalVotingPower::::get(first_netuid), 30); + assert_eq!(TotalVotingPower::::get(second_netuid), 7); + assert!(HasMigrationRun::::get(MIGRATION_NAME.to_vec())); + assert_eq!( + weight, + ::DbWeight::get().reads_writes(4, 3) + ); + + VotingPower::::insert(first_netuid, U256::from(4), 100); + migrate_total_voting_power::(); + assert_eq!(TotalVotingPower::::get(first_netuid), 30); + }); + } +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index 63a7ec4439..2cf4955e10 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -73,6 +73,7 @@ pub mod migrate_subnet_volume; pub mod migrate_tao_in_refund_deployment_block; pub mod migrate_to_v1_separate_emission; pub mod migrate_to_v2_fixed_total_stake; +pub mod migrate_total_voting_power; pub mod migrate_transfer_ownership_to_foundation; pub mod migrate_upgrade_revealed_commitments; diff --git a/pallets/subtensor/src/tests/voting_power.rs b/pallets/subtensor/src/tests/voting_power.rs index 9af3639b99..8a8f8c0664 100644 --- a/pallets/subtensor/src/tests/voting_power.rs +++ b/pallets/subtensor/src/tests/voting_power.rs @@ -354,6 +354,42 @@ fn test_voting_power_ema_calculation() { }); } +#[test] +fn test_total_voting_power_tracks_updates_removals_and_swaps() { + new_test_ext(1).execute_with(|| { + let f = VotingPowerTestFixture::new(); + f.setup_full(); + f.run_epochs(1); + + let voting_power = f.get_voting_power(); + assert!(voting_power > 0); + assert_eq!(TotalVotingPower::::get(f.netuid), voting_power); + + let replacement = U256::from(99); + SubtensorModule::swap_voting_power_for_hotkey(&f.hotkey, &replacement, f.netuid); + assert_eq!( + VotingPower::::get(f.netuid, replacement), + voting_power + ); + assert_eq!(TotalVotingPower::::get(f.netuid), voting_power); + + ValidatorPermit::::insert(f.netuid, vec![false]); + let mut output = BTreeMap::new(); + output.insert( + replacement, + EpochTerms { + uid: 0, + new_validator_permit: false, + ..Default::default() + }, + ); + SubtensorModule::update_voting_power_for_subnet(f.netuid, &output); + + assert_eq!(VotingPower::::get(f.netuid, replacement), 0); + assert_eq!(TotalVotingPower::::get(f.netuid), 0); + }); +} + // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::voting_power::test_voting_power_cleared_when_deregistered --exact --nocapture #[test] fn test_voting_power_cleared_when_deregistered() { diff --git a/pallets/subtensor/src/utils/voting_power.rs b/pallets/subtensor/src/utils/voting_power.rs index 11d8880b97..6af558c071 100644 --- a/pallets/subtensor/src/utils/voting_power.rs +++ b/pallets/subtensor/src/utils/voting_power.rs @@ -37,6 +37,11 @@ impl Pallet { VotingPowerEmaAlpha::::get(netuid) } + /// Get the maintained sum of voting power for all validators on a subnet. + pub fn get_total_voting_power(netuid: NetUid) -> u64 { + TotalVotingPower::::get(netuid) + } + // ======================== // === Extrinsic Handlers === // ======================== @@ -148,7 +153,7 @@ impl Pallet { Self::update_voting_power_for_hotkey(netuid, hotkey, terms.stake, alpha, min_stake); } else { // Miner without vpermit - remove any existing voting power - VotingPower::::remove(netuid, hotkey); + Self::remove_voting_power(netuid, hotkey); } } @@ -174,7 +179,7 @@ impl Pallet { // Remove voting power for deregistered hotkeys for hotkey in hotkeys_to_remove { - VotingPower::::remove(netuid, &hotkey); + Self::remove_voting_power(netuid, &hotkey); log::trace!( "VotingPower removed for deregistered hotkey {hotkey:?} on netuid {netuid:?}" ); @@ -201,13 +206,13 @@ impl Pallet { // This allows new validators to build up voting power from 0 without being removed. if new_ema < min_stake && previous_ema >= min_stake { // Was above threshold, now decayed below - remove - VotingPower::::remove(netuid, hotkey); + Self::remove_voting_power(netuid, hotkey); log::trace!( "VotingPower removed for hotkey {hotkey:?} on netuid {netuid:?} (decayed below removal threshold: {new_ema:?} < {min_stake:?})" ); } else if new_ema > 0 { // Update voting power (building up or maintaining) - VotingPower::::insert(netuid, hotkey, new_ema); + Self::set_voting_power(netuid, hotkey, previous_ema, new_ema); log::trace!( "VotingPower updated for hotkey {hotkey:?} on netuid {netuid:?}: {previous_ema:?} -> {new_ema:?}" ); @@ -238,11 +243,39 @@ impl Pallet { result.min(u64::MAX as u128) as u64 } + /// Store one validator's voting power and update the subnet aggregate by + /// the same delta. + fn set_voting_power( + netuid: NetUid, + hotkey: &T::AccountId, + previous_voting_power: u64, + new_voting_power: u64, + ) { + VotingPower::::insert(netuid, hotkey, new_voting_power); + TotalVotingPower::::mutate(netuid, |total| { + *total = total + .saturating_sub(previous_voting_power) + .saturating_add(new_voting_power); + }); + } + + /// Remove one validator's voting power and subtract it from the subnet + /// aggregate. + fn remove_voting_power(netuid: NetUid, hotkey: &T::AccountId) { + let removed = VotingPower::::take(netuid, hotkey); + if removed > 0 { + TotalVotingPower::::mutate(netuid, |total| { + *total = total.saturating_sub(removed); + }); + } + } + /// Finalize the disabling of voting power tracking. /// Clears all VotingPower entries for the subnet. fn finalize_voting_power_disable(netuid: NetUid) { // Clear all VotingPower entries for this subnet let _ = VotingPower::::clear_prefix(netuid, u32::MAX, None); + TotalVotingPower::::remove(netuid); // Disable tracking VotingPowerTrackingEnabled::::insert(netuid, false); diff --git a/precompiles/src/alpha.rs b/precompiles/src/alpha.rs index 38a5d401aa..62b70272d4 100644 --- a/precompiles/src/alpha.rs +++ b/precompiles/src/alpha.rs @@ -3,12 +3,13 @@ use core::marker::PhantomData; use crate::PrecompileExt; use fp_evm::{ExitError, PrecompileFailure}; use frame_support::{ + BoundedVec, dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}, - traits::IsSubType, + traits::{ConstU32, IsSubType}, }; use frame_system::RawOrigin; use pallet_evm::{AddressMapping, BalanceConverter, PrecompileHandle, SubstrateBalance}; -use precompile_utils::EvmResult; +use precompile_utils::{EvmResult, prelude::BoundedBytes}; use sp_runtime::{ SaturatedConversion, Vec, traits::{AsSystemOriginSigner, Dispatchable}, @@ -343,6 +344,132 @@ where }; handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) } + + #[precompile::public("getEmissionAccounting(uint16,bytes32)")] + #[precompile::view] + fn get_emission_accounting( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: sp_core::H256, + ) -> EvmResult<(u64, u64, u64, u64, u64, u64, u64, u128, u64)> { + handle.record_db_reads::(9)?; + let netuid = NetUid::from(netuid); + let hotkey = R::AccountId::from(hotkey.0); + Ok(( + pallet_subtensor::AlphaDividendsPerSubnet::::get(netuid, &hotkey).to_u64(), + pallet_subtensor::RootAlphaDividendsPerSubnet::::get(netuid, &hotkey).to_u64(), + pallet_subtensor::LastHotkeyEmissionOnNetuid::::get(&hotkey, netuid).to_u64(), + pallet_subtensor::PendingServerEmission::::get(netuid).to_u64(), + pallet_subtensor::PendingValidatorEmission::::get(netuid).to_u64(), + pallet_subtensor::PendingRootAlphaDivs::::get(netuid).to_u64(), + pallet_subtensor::PendingOwnerCut::::get(netuid).to_u64(), + pallet_subtensor::MinerBurned::::get(netuid).to_bits(), + pallet_subtensor::RAORecycledForRegistration::::get(netuid).to_u64(), + )) + } + + #[precompile::public("getSubnetEconomicState(uint16)")] + #[precompile::view] + fn get_subnet_economic_state( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(bool, u128, u64, u64, u64)> { + handle.record_db_reads::(5)?; + let netuid = NetUid::from(netuid); + Ok(( + pallet_subtensor::SubnetEmissionEnabled::::get(netuid), + pallet_subtensor::RootProp::::get(netuid).to_bits(), + pallet_subtensor::SubnetExcessTao::::get(netuid).to_u64(), + pallet_subtensor::SubnetRootSellTao::::get(netuid).to_u64(), + pallet_subtensor::SubnetProtocolAlpha::::get(netuid).to_u64(), + )) + } + + #[precompile::public("getSubnetFlowState(uint16)")] + #[precompile::view] + fn get_subnet_flow_state( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(U256, bool, u64, U256, U256, bool, u64, U256)> { + handle.record_db_reads::(4)?; + let netuid = NetUid::from(netuid); + let tao_ema = pallet_subtensor::SubnetEmaTaoFlow::::get(netuid); + let protocol_ema = pallet_subtensor::SubnetEmaProtocolFlow::::get(netuid); + Ok(( + signed_i64_word(pallet_subtensor::SubnetTaoFlow::::get(netuid)), + tao_ema.is_some(), + tao_ema.map(|(block, _)| block).unwrap_or(0), + signed_i128_word(tao_ema.map(|(_, value)| value.to_bits()).unwrap_or(0)), + signed_i64_word(pallet_subtensor::SubnetProtocolFlow::::get(netuid)), + protocol_ema.is_some(), + protocol_ema.map(|(block, _)| block).unwrap_or(0), + signed_i128_word(protocol_ema.map(|(_, value)| value.to_bits()).unwrap_or(0)), + )) + } + + #[precompile::public("getEmissionGateConfig()")] + #[precompile::view] + fn get_emission_gate_config( + handle: &mut impl PrecompileHandle, + ) -> EvmResult<(u64, U256, bool, U256, u128, u128, u128, u128, u64)> { + handle.record_db_reads::(9)?; + Ok(( + #[allow(deprecated)] + pallet_subtensor::BlockEmission::::get(), + signed_i128_word(pallet_subtensor::SubnetMovingAlpha::::get().to_bits()), + pallet_subtensor::NetTaoFlowEnabled::::get(), + signed_i128_word(pallet_subtensor::TaoFlowCutoff::::get().to_bits()), + pallet_subtensor::FlowNormExponent::::get().to_bits(), + pallet_subtensor::EmissionBarQuantile::::get().to_bits(), + pallet_subtensor::EmissionGateExponent::::get().to_bits(), + pallet_subtensor::EmissionGateBar::::get().to_bits(), + pallet_subtensor::FlowEmaSmoothingFactor::::get(), + )) + } + + #[precompile::public("getSwapState(uint16)")] + #[precompile::view] + fn get_swap_state( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(u16, bool, u64, u64, u64)> { + handle.record_db_reads::(5)?; + let netuid = NetUid::from(netuid); + Ok(( + pallet_subtensor_swap::FeeRate::::get(netuid), + pallet_subtensor_swap::PalSwapInitialized::::get(netuid), + pallet_subtensor_swap::SwapBalancer::::get(netuid) + .get_quote_weight() + .deconstruct(), + pallet_subtensor_swap::BalancerTaoReservoir::::get(netuid).to_u64(), + pallet_subtensor_swap::BalancerAlphaReservoir::::get(netuid).to_u64(), + )) + } + + #[precompile::public("hasSwapMigrationRun(bytes)")] + #[precompile::view] + fn has_swap_migration_run( + handle: &mut impl PrecompileHandle, + migration_name: BoundedBytes>, + ) -> EvmResult { + handle.record_db_reads::(1)?; + let migration_name = BoundedVec::>::truncate_from(migration_name.into()); + Ok(pallet_subtensor_swap::HasMigrationRun::::get( + migration_name, + )) + } +} + +fn signed_i64_word(value: i64) -> U256 { + let mut encoded = [if value.is_negative() { 0xff } else { 0 }; 32]; + encoded[24..].copy_from_slice(&value.to_be_bytes()); + U256::from_big_endian(&encoded) +} + +fn signed_i128_word(value: i128) -> U256 { + let mut encoded = [if value.is_negative() { 0xff } else { 0 }; 32]; + encoded[16..].copy_from_slice(&value.to_be_bytes()); + U256::from_big_endian(&encoded) } #[cfg(test)] @@ -705,4 +832,135 @@ mod tests { ); }); } + + #[test] + fn alpha_state_views_return_typed_runtime_state() { + new_test_ext().execute_with(|| { + let precompiles = precompiles::>(); + let caller = addr_from_index(1); + let address = addr_from_index(AlphaPrecompile::::INDEX); + let netuid = NetUid::from(DYNAMIC_NETUID_U16); + let hotkey = sp_core::H256::repeat_byte(0x41); + + assert_view( + &precompiles, + caller, + address, + "getEmissionAccounting(uint16,bytes32)", + (DYNAMIC_NETUID_U16, hotkey), + ( + 0_u64, 0_u64, 0_u64, 0_u64, 0_u64, 0_u64, 0_u64, 0_u128, 0_u64, + ), + ); + + assert_view( + &precompiles, + caller, + address, + "getSubnetEconomicState(uint16)", + (DYNAMIC_NETUID_U16,), + ( + pallet_subtensor::SubnetEmissionEnabled::::get(netuid), + pallet_subtensor::RootProp::::get(netuid).to_bits(), + pallet_subtensor::SubnetExcessTao::::get(netuid).to_u64(), + pallet_subtensor::SubnetRootSellTao::::get(netuid).to_u64(), + pallet_subtensor::SubnetProtocolAlpha::::get(netuid).to_u64(), + ), + ); + + let tao_ema = pallet_subtensor::SubnetEmaTaoFlow::::get(netuid); + let protocol_ema = pallet_subtensor::SubnetEmaProtocolFlow::::get(netuid); + assert_view( + &precompiles, + caller, + address, + "getSubnetFlowState(uint16)", + (DYNAMIC_NETUID_U16,), + ( + signed_i64_word(pallet_subtensor::SubnetTaoFlow::::get(netuid)), + tao_ema.is_some(), + tao_ema.map(|(block, _)| block).unwrap_or(0), + signed_i128_word(tao_ema.map(|(_, value)| value.to_bits()).unwrap_or(0)), + signed_i64_word(pallet_subtensor::SubnetProtocolFlow::::get(netuid)), + protocol_ema.is_some(), + protocol_ema.map(|(block, _)| block).unwrap_or(0), + signed_i128_word(protocol_ema.map(|(_, value)| value.to_bits()).unwrap_or(0)), + ), + ); + + #[allow(deprecated)] + let emission_gate = ( + pallet_subtensor::BlockEmission::::get(), + signed_i128_word(pallet_subtensor::SubnetMovingAlpha::::get().to_bits()), + pallet_subtensor::NetTaoFlowEnabled::::get(), + signed_i128_word(pallet_subtensor::TaoFlowCutoff::::get().to_bits()), + pallet_subtensor::FlowNormExponent::::get().to_bits(), + pallet_subtensor::EmissionBarQuantile::::get().to_bits(), + pallet_subtensor::EmissionGateExponent::::get().to_bits(), + pallet_subtensor::EmissionGateBar::::get().to_bits(), + pallet_subtensor::FlowEmaSmoothingFactor::::get(), + ); + assert_view( + &precompiles, + caller, + address, + "getEmissionGateConfig()", + (), + emission_gate, + ); + + let balancer = pallet_subtensor_swap::SwapBalancer::::get(netuid); + assert_view( + &precompiles, + caller, + address, + "getSwapState(uint16)", + (DYNAMIC_NETUID_U16,), + ( + pallet_subtensor_swap::FeeRate::::get(netuid), + pallet_subtensor_swap::PalSwapInitialized::::get(netuid), + balancer.get_quote_weight().deconstruct(), + pallet_subtensor_swap::BalancerTaoReservoir::::get(netuid).to_u64(), + pallet_subtensor_swap::BalancerAlphaReservoir::::get(netuid).to_u64(), + ), + ); + + let migration_name = b"reader-test".to_vec(); + pallet_subtensor_swap::HasMigrationRun::::insert( + BoundedVec::truncate_from(migration_name.clone()), + true, + ); + assert_view( + &precompiles, + caller, + address, + "hasSwapMigrationRun(bytes)", + (BoundedBytes::>::from(migration_name),), + true, + ); + }); + } + + fn assert_view( + precompiles: &impl pallet_evm::PrecompileSet, + caller: sp_core::H160, + address: sp_core::H160, + signature: &str, + args: Args, + expected: Output, + ) where + Args: precompile_utils::solidity::Codec, + Output: precompile_utils::solidity::Codec, + { + use precompile_utils::testing::PrecompileTesterExt; + + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32(signature), args), + ) + .with_static_call(true) + .execute_returns(expected); + } } diff --git a/precompiles/src/balance.rs b/precompiles/src/balance.rs index 217e36aa26..af990b40ad 100644 --- a/precompiles/src/balance.rs +++ b/precompiles/src/balance.rs @@ -73,6 +73,13 @@ where Ok(pallet_balances::Pallet::::free_balance(&coldkey).into()) } + #[precompile::public("getTotalIssuance()")] + #[precompile::view] + fn get_total_issuance(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_balances::Pallet::::total_issuance().into()) + } + #[precompile::public("burnBalance(uint256,bool)")] fn burn_balance( handle: &mut impl PrecompileHandle, @@ -161,6 +168,17 @@ mod tests { .with_static_call(true) .expect_cost(RuntimeHelper::::db_read_gas_cost()) .execute_returns_raw(abi_word(U256::from(amount))); + + let total_issuance: U256 = pallet_balances::Pallet::::total_issuance().into(); + precompiles::>() + .prepare_test( + caller, + addr_from_index(BalancePrecompile::::INDEX), + selector_u32("getTotalIssuance()").to_be_bytes().to_vec(), + ) + .with_static_call(true) + .expect_cost(RuntimeHelper::::db_read_gas_cost()) + .execute_returns(total_issuance); }); } diff --git a/precompiles/src/leasing.rs b/precompiles/src/leasing.rs index a89d40a4b3..4dcb371ca2 100644 --- a/precompiles/src/leasing.rs +++ b/precompiles/src/leasing.rs @@ -122,6 +122,23 @@ where Ok(lease_id.into()) } + #[precompile::public("getNextLeaseId()")] + #[precompile::view] + fn get_next_lease_id(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::NextSubnetLeaseId::::get()) + } + + #[precompile::public("getAccumulatedLeaseDividends(uint32)")] + #[precompile::view] + fn get_accumulated_lease_dividends( + handle: &mut impl PrecompileHandle, + lease_id: u32, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::AccumulatedLeaseDividends::::get(lease_id).into()) + } + #[precompile::public("createLeaseCrowdloan(uint64,uint64,uint64,uint32,uint8,bool,uint32)")] #[precompile::payable] #[allow(clippy::too_many_arguments)] @@ -334,6 +351,32 @@ mod tests { get_lease(caller, lease_id, expected_lease_info(lease_id)); let precompile_addr = addr_from_index(LeasingPrecompile::::INDEX); + precompiles::>() + .prepare_test( + caller, + precompile_addr, + selector_u32("getNextLeaseId()").to_be_bytes().to_vec(), + ) + .with_static_call(true) + .execute_returns(pallet_subtensor::NextSubnetLeaseId::::get()); + + let accumulated_dividends = 321_u64; + pallet_subtensor::AccumulatedLeaseDividends::::insert( + lease_id, + subtensor_runtime_common::AlphaBalance::from(accumulated_dividends), + ); + precompiles::>() + .prepare_test( + caller, + precompile_addr, + encode_with_selector( + selector_u32("getAccumulatedLeaseDividends(uint32)"), + (lease_id,), + ), + ) + .with_static_call(true) + .execute_returns(accumulated_dividends); + precompiles::>() .prepare_test( caller, diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index 02dec9f5c0..ae31b1809d 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -608,4 +608,168 @@ mod address_and_selector_tests { ); } } + + #[test] + fn state_reader_selectors_are_locked() { + for signature in [ + "getDelegate(bytes32)", + "getChildkeyTake(bytes32,uint16)", + "getPendingChildKeys(bytes32,uint16)", + "getChildKeys(bytes32,uint16)", + "getParentKeys(bytes32,uint16)", + "getPendingChildKeyCooldown()", + "getTakeLimits()", + "getMinChildkeyTakePerSubnet(uint16)", + "getHotkeyOwner(bytes32)", + "getOwnedHotkeys(bytes32)", + "getAutoStakeDestination(bytes32,uint16)", + "getAutoStakeDestinationColdkeys(bytes32,uint16)", + "getHotkeySuccessor(bytes32,uint16)", + "getHotkeyRoot(bytes32,uint16)", + "getColdkeySuccessor(bytes32)", + "getColdkeyRoot(bytes32)", + "getColdkeySwapStatus(bytes32)", + "getColdkeySwapDelays()", + "getLastHotkeySwapOnSubnet(bytes32,uint16)", + "getStakeAccounting()", + "getMinerCollateral(uint16,bytes32,bytes32)", + "getColdkeyCollateral(uint16,bytes32)", + "getCollateralConfig(uint16)", + ] { + assert!( + staking::StakingPrecompileV2Call::::supports_selector(selector_u32( + signature + )), + "missing Staking V2 reader selector {signature}" + ); + } + + for signature in [ + "getRegisteredSubnetCounter(uint16)", + "getSubnetDissolutionStatus(uint16)", + "getSubnetMetadata(uint16)", + "getSubnetCapacityConfig(uint16)", + "getMechanismEmissionSplit(uint16)", + "getBurnConfig(uint16)", + "getGlobalNetworkLimits()", + "getGlobalRateLimits()", + "getGlobalProtocolConfig()", + ] { + assert!( + subnet::SubnetPrecompileCall::::supports_selector(selector_u32(signature)), + "missing Subnet reader selector {signature}" + ); + } + + for signature in [ + "getEmissionAccounting(uint16,bytes32)", + "getSubnetEconomicState(uint16)", + "getSubnetFlowState(uint16)", + "getEmissionGateConfig()", + "getSwapState(uint16)", + "hasSwapMigrationRun(bytes)", + ] { + assert!( + alpha::AlphaPrecompileCall::::supports_selector(selector_u32(signature)), + "missing Alpha reader selector {signature}" + ); + } + + for signature in [ + "getUid(uint16,bytes32)", + "isNetworkMember(bytes32,uint16)", + "getWeights(uint16,uint16)", + "getBonds(uint16,uint16)", + "getBlockAtRegistration(uint16,uint16)", + "getNeuronCertificate(uint16,bytes32)", + "getPrometheus(uint16,bytes32)", + "getChainIdentity(bytes32)", + "getSubnetIdentity(uint16)", + "getLoadedEmission(uint16)", + "getTransactionKeyLastBlock(bytes32,uint16,uint16)", + "getLegacyTransactionRateBlocks(bytes32)", + "getWeightCommit(uint16,bytes32,uint32)", + "getWeightCommitCount(uint16,bytes32)", + "getTimelockedWeightCommit(uint16,uint64,uint32)", + "getTimelockedWeightCommitCount(uint16,uint64)", + "getLegacyTimelockedWeightCommit(uint8,uint16,uint64,uint32)", + "getLegacyTimelockedWeightCommitCount(uint8,uint16,uint64)", + ] { + assert!( + neuron::NeuronPrecompileCall::::supports_selector(selector_u32(signature)), + "missing Neuron reader selector {signature}" + ); + } + + for signature in [ + "getProxyDeposit(bytes32)", + "getAnnouncements(bytes32)", + "getLastCallResult(bytes32)", + "isRealPaysFee(bytes32,bytes32)", + ] { + assert!( + proxy::ProxyPrecompileCall::::supports_selector(selector_u32(signature)), + "missing Proxy reader selector {signature}" + ); + } + + for signature in ["getNextLeaseId()", "getAccumulatedLeaseDividends(uint32)"] { + assert!( + leasing::LeasingPrecompileCall::::supports_selector(selector_u32( + signature + )), + "missing Leasing reader selector {signature}" + ); + } + + assert!( + balance::BalancePrecompileCall::::supports_selector(selector_u32( + "getTotalIssuance()" + )) + ); + assert!( + uid_lookup::UidLookupPrecompileCall::::supports_selector(selector_u32( + "getAssociatedEvmAddress(uint16,uint16)" + )) + ); + + for (domain, selectors) in [ + ( + "Staking V2", + staking::StakingPrecompileV2Call::::selectors(), + ), + ( + "Subnet", + subnet::SubnetPrecompileCall::::selectors(), + ), + ("Alpha", alpha::AlphaPrecompileCall::::selectors()), + ( + "Neuron", + neuron::NeuronPrecompileCall::::selectors(), + ), + ("Proxy", proxy::ProxyPrecompileCall::::selectors()), + ( + "Leasing", + leasing::LeasingPrecompileCall::::selectors(), + ), + ( + "Balance", + balance::BalancePrecompileCall::::selectors(), + ), + ( + "UID lookup", + uid_lookup::UidLookupPrecompileCall::::selectors(), + ), + ] { + let unique = selectors + .iter() + .copied() + .collect::>(); + assert_eq!( + unique.len(), + selectors.len(), + "{domain} contains a selector collision" + ); + } + } } diff --git a/precompiles/src/neuron.rs b/precompiles/src/neuron.rs index 82c078b5b1..21bf15edc0 100644 --- a/precompiles/src/neuron.rs +++ b/precompiles/src/neuron.rs @@ -14,7 +14,7 @@ use precompile_utils::{ use sp_core::{H256, ecdsa::Signature}; use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable}; use sp_std::vec::Vec; -use subtensor_runtime_common::{MechId, NetUid}; +use subtensor_runtime_common::{MechId, NetUid, NetUidStorageIndex}; use crate::{PrecompileExt, PrecompileHandleExt}; @@ -39,7 +39,7 @@ where + Send + Sync + scale_info::TypeInfo, - R::AccountId: From<[u8; 32]>, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + GetDispatchInfo @@ -65,7 +65,7 @@ where + Send + Sync + scale_info::TypeInfo, - R::AccountId: From<[u8; 32]>, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + GetDispatchInfo @@ -825,6 +825,411 @@ where pallet_subtensor::Call::::clear_coldkey_swap_announcement {}, ) } + + #[precompile::public("getUid(uint16,bytes32)")] + #[precompile::view] + fn get_uid( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + ) -> EvmResult<(bool, u16)> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::Uids::::get( + NetUid::from(netuid), + R::AccountId::from(hotkey.0), + ) { + Some(uid) => (true, uid), + None => (false, 0), + }, + ) + } + + #[precompile::public("isNetworkMember(bytes32,uint16)")] + #[precompile::view] + fn is_network_member( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::IsNetworkMember::::get( + R::AccountId::from(hotkey.0), + NetUid::from(netuid), + )) + } + + #[precompile::public("getWeights(uint16,uint16)")] + #[precompile::view] + fn get_weights( + handle: &mut impl PrecompileHandle, + netuid: u16, + uid: u16, + ) -> EvmResult> { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::Weights::::get( + NetUidStorageIndex::from(NetUid::from(netuid)), + uid, + )) + } + + #[precompile::public("getBonds(uint16,uint16)")] + #[precompile::view] + fn get_bonds( + handle: &mut impl PrecompileHandle, + netuid: u16, + uid: u16, + ) -> EvmResult> { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::Bonds::::get( + NetUidStorageIndex::from(NetUid::from(netuid)), + uid, + )) + } + + #[precompile::public("getBlockAtRegistration(uint16,uint16)")] + #[precompile::view] + fn get_block_at_registration( + handle: &mut impl PrecompileHandle, + netuid: u16, + uid: u16, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::BlockAtRegistration::::get( + NetUid::from(netuid), + uid, + )) + } + + #[precompile::public("getNeuronCertificate(uint16,bytes32)")] + #[precompile::view] + fn get_neuron_certificate( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + ) -> EvmResult<(bool, u8, UnboundedBytes)> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::NeuronCertificates::::get( + NetUid::from(netuid), + R::AccountId::from(hotkey.0), + ) { + Some(certificate) => ( + true, + certificate.algorithm, + UnboundedBytes::from(certificate.public_key.into_inner()), + ), + None => (false, 0, UnboundedBytes::default()), + }, + ) + } + + #[precompile::public("getPrometheus(uint16,bytes32)")] + #[precompile::view] + fn get_prometheus( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + ) -> EvmResult<(bool, u64, u32, u128, u16, u8)> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::Prometheus::::get( + NetUid::from(netuid), + R::AccountId::from(hotkey.0), + ) { + Some(info) => ( + true, + info.block, + info.version, + info.ip, + info.port, + info.ip_type, + ), + None => (false, 0, 0, 0, 0, 0), + }, + ) + } + + #[precompile::public("getChainIdentity(bytes32)")] + #[precompile::view] + fn get_chain_identity( + handle: &mut impl PrecompileHandle, + coldkey: H256, + ) -> EvmResult<( + bool, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + )> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::IdentitiesV2::::get(R::AccountId::from(coldkey.0)) { + Some(identity) => ( + true, + identity.name.into(), + identity.url.into(), + identity.github_repo.into(), + identity.image.into(), + identity.discord.into(), + identity.description.into(), + identity.additional.into(), + ), + None => ( + false, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ), + }, + ) + } + + #[precompile::public("getSubnetIdentity(uint16)")] + #[precompile::view] + fn get_subnet_identity( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<( + bool, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + UnboundedBytes, + )> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::SubnetIdentitiesV3::::get(NetUid::from(netuid)) { + Some(identity) => ( + true, + identity.subnet_name.into(), + identity.github_repo.into(), + identity.subnet_contact.into(), + identity.subnet_url.into(), + identity.discord.into(), + identity.description.into(), + identity.logo_url.into(), + identity.additional.into(), + ), + None => ( + false, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ), + }, + ) + } + + #[precompile::public("getLoadedEmission(uint16)")] + #[precompile::view] + fn get_loaded_emission( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(bool, Vec<(H256, u64, u64)>)> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::LoadedEmission::::get(NetUid::from(netuid)) { + Some(emission) => ( + true, + emission + .into_iter() + .map(|(hotkey, server, validator)| { + (H256::from(hotkey.into()), server, validator) + }) + .collect(), + ), + None => (false, Vec::new()), + }, + ) + } + + #[precompile::public("getTransactionKeyLastBlock(bytes32,uint16,uint16)")] + #[precompile::view] + fn get_transaction_key_last_block( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + transaction_key: u16, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::TransactionKeyLastBlock::::get(( + R::AccountId::from(hotkey.0), + NetUid::from(netuid), + transaction_key, + ))) + } + + #[allow(deprecated)] + #[precompile::public("getLegacyTransactionRateBlocks(bytes32)")] + #[precompile::view] + fn get_legacy_transaction_rate_blocks( + handle: &mut impl PrecompileHandle, + hotkey: H256, + ) -> EvmResult<(u64, u64, u64)> { + handle.record_db_reads::(3)?; + let hotkey = R::AccountId::from(hotkey.0); + Ok(( + pallet_subtensor::LastTxBlock::::get(&hotkey), + pallet_subtensor::LastTxBlockChildKeyTake::::get(&hotkey), + pallet_subtensor::LastTxBlockDelegateTake::::get(hotkey), + )) + } + + #[precompile::public("getWeightCommit(uint16,bytes32,uint32)")] + #[precompile::view] + fn get_weight_commit( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + index: u32, + ) -> EvmResult<(bool, H256, u64, u64)> { + handle.record_db_reads::(1)?; + let commits = pallet_subtensor::WeightCommits::::get( + NetUidStorageIndex::from(NetUid::from(netuid)), + R::AccountId::from(hotkey.0), + ); + Ok(commits + .and_then(|commits| commits.get(index as usize).copied()) + .map(|(hash, epoch, block, _)| (true, hash, epoch, block)) + .unwrap_or((false, H256::zero(), 0, 0))) + } + + #[precompile::public("getWeightCommitCount(uint16,bytes32)")] + #[precompile::view] + fn get_weight_commit_count( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::WeightCommits::::get( + NetUidStorageIndex::from(NetUid::from(netuid)), + R::AccountId::from(hotkey.0), + ) + .map(|commits| commits.len() as u32) + .unwrap_or(0)) + } + + #[precompile::public("getTimelockedWeightCommit(uint16,uint64,uint32)")] + #[precompile::view] + fn get_timelocked_weight_commit( + handle: &mut impl PrecompileHandle, + netuid: u16, + epoch: u64, + index: u32, + ) -> EvmResult<(bool, H256, u64, H256, u32, u64)> { + handle.record_db_reads::(1)?; + let commits = pallet_subtensor::TimelockedWeightCommits::::get( + NetUidStorageIndex::from(NetUid::from(netuid)), + epoch, + ); + Ok(commits + .get(index as usize) + .map(|(who, block, ciphertext, round)| { + ( + true, + H256::from(who.clone().into()), + *block, + H256::from(sp_io::hashing::keccak_256(ciphertext.as_slice())), + ciphertext.len() as u32, + *round, + ) + }) + .unwrap_or((false, H256::zero(), 0, H256::zero(), 0, 0))) + } + + #[precompile::public("getTimelockedWeightCommitCount(uint16,uint64)")] + #[precompile::view] + fn get_timelocked_weight_commit_count( + handle: &mut impl PrecompileHandle, + netuid: u16, + epoch: u64, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::TimelockedWeightCommits::::get( + NetUidStorageIndex::from(NetUid::from(netuid)), + epoch, + ) + .len() as u32) + } + + #[precompile::public("getLegacyTimelockedWeightCommit(uint8,uint16,uint64,uint32)")] + #[precompile::view] + fn get_legacy_timelocked_weight_commit( + handle: &mut impl PrecompileHandle, + version: u8, + netuid: u16, + epoch: u64, + index: u32, + ) -> EvmResult<(bool, H256, u64, H256, u32, u64)> { + handle.record_db_reads::(1)?; + let netuid = NetUidStorageIndex::from(NetUid::from(netuid)); + match version { + 1 => Ok(pallet_subtensor::CRV3WeightCommits::::get(netuid, epoch) + .get(index as usize) + .map(|(who, ciphertext, round)| { + ( + true, + H256::from(who.clone().into()), + 0, + H256::from(sp_io::hashing::keccak_256(ciphertext.as_slice())), + ciphertext.len() as u32, + *round, + ) + }) + .unwrap_or((false, H256::zero(), 0, H256::zero(), 0, 0))), + 2 => Ok( + pallet_subtensor::CRV3WeightCommitsV2::::get(netuid, epoch) + .get(index as usize) + .map(|(who, block, ciphertext, round)| { + ( + true, + H256::from(who.clone().into()), + *block, + H256::from(sp_io::hashing::keccak_256(ciphertext.as_slice())), + ciphertext.len() as u32, + *round, + ) + }) + .unwrap_or((false, H256::zero(), 0, H256::zero(), 0, 0)), + ), + _ => Err(revert("unsupported legacy weight-commit version")), + } + } + + #[precompile::public("getLegacyTimelockedWeightCommitCount(uint8,uint16,uint64)")] + #[precompile::view] + fn get_legacy_timelocked_weight_commit_count( + handle: &mut impl PrecompileHandle, + version: u8, + netuid: u16, + epoch: u64, + ) -> EvmResult { + handle.record_db_reads::(1)?; + let netuid = NetUidStorageIndex::from(NetUid::from(netuid)); + match version { + 1 => Ok(pallet_subtensor::CRV3WeightCommits::::get(netuid, epoch).len() as u32), + 2 => Ok(pallet_subtensor::CRV3WeightCommitsV2::::get(netuid, epoch).len() as u32), + _ => Err(revert("unsupported legacy weight-commit version")), + } + } } fn dispatch_neuron( @@ -841,7 +1246,7 @@ where + Send + Sync + scale_info::TypeInfo, - R::AccountId: From<[u8; 32]>, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + GetDispatchInfo @@ -1343,4 +1748,143 @@ mod tests { assert_eq!(prometheus.ip_type, SERVE_IP_TYPE); }); } + + #[test] + fn neuron_state_views_return_typed_values_and_missing_state() { + new_test_ext().execute_with(|| { + let caller = addr_from_index(0x8234); + let address = addr_from_index(NeuronPrecompile::::INDEX); + let precompiles = precompiles::>(); + let netuid = NetUid::from(TEST_NETUID_U16); + let netuid_index = NetUidStorageIndex::from(netuid); + let hotkey = AccountId::from([0x81; 32]); + let hotkey_word = H256::from_slice(hotkey.as_ref()); + let uid = 7_u16; + let weights = vec![(1_u16, 2_u16), (3_u16, 4_u16)]; + let bonds = vec![(5_u16, 6_u16)]; + + pallet_subtensor::Uids::::insert(netuid, &hotkey, uid); + pallet_subtensor::IsNetworkMember::::insert(&hotkey, netuid, true); + pallet_subtensor::Weights::::insert(netuid_index, uid, weights.clone()); + pallet_subtensor::Bonds::::insert(netuid_index, uid, bonds.clone()); + pallet_subtensor::BlockAtRegistration::::insert(netuid, uid, 91_u64); + + macro_rules! assert_view { + ($signature:literal, $arguments:expr, $expected:expr) => { + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32($signature), $arguments), + ) + .with_static_call(true) + .execute_returns($expected); + }; + } + + assert_view!( + "getUid(uint16,bytes32)", + (TEST_NETUID_U16, hotkey_word), + (true, uid) + ); + assert_view!( + "isNetworkMember(bytes32,uint16)", + (hotkey_word, TEST_NETUID_U16), + true + ); + assert_view!("getWeights(uint16,uint16)", (TEST_NETUID_U16, uid), weights); + assert_view!("getBonds(uint16,uint16)", (TEST_NETUID_U16, uid), bonds); + assert_view!( + "getBlockAtRegistration(uint16,uint16)", + (TEST_NETUID_U16, uid), + 91_u64 + ); + assert_view!( + "getNeuronCertificate(uint16,bytes32)", + (TEST_NETUID_U16, hotkey_word), + (false, 0_u8, UnboundedBytes::default()) + ); + assert_view!( + "getPrometheus(uint16,bytes32)", + (TEST_NETUID_U16, hotkey_word), + (false, 0_u64, 0_u32, 0_u128, 0_u16, 0_u8) + ); + assert_view!( + "getChainIdentity(bytes32)", + (hotkey_word,), + ( + false, + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + ) + ); + assert_view!( + "getSubnetIdentity(uint16)", + (TEST_NETUID_U16,), + ( + false, + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + UnboundedBytes::default(), + ) + ); + assert_view!( + "getLoadedEmission(uint16)", + (TEST_NETUID_U16,), + (false, Vec::<(H256, u64, u64)>::new()) + ); + assert_view!( + "getTransactionKeyLastBlock(bytes32,uint16,uint16)", + (hotkey_word, TEST_NETUID_U16, 4_u16), + 0_u64 + ); + assert_view!( + "getLegacyTransactionRateBlocks(bytes32)", + (hotkey_word,), + (0_u64, 0_u64, 0_u64) + ); + assert_view!( + "getWeightCommit(uint16,bytes32,uint32)", + (TEST_NETUID_U16, hotkey_word, 0_u32), + (false, H256::zero(), 0_u64, 0_u64) + ); + assert_view!( + "getWeightCommitCount(uint16,bytes32)", + (TEST_NETUID_U16, hotkey_word), + 0_u32 + ); + assert_view!( + "getTimelockedWeightCommit(uint16,uint64,uint32)", + (TEST_NETUID_U16, 2_u64, 0_u32), + (false, H256::zero(), 0_u64, H256::zero(), 0_u32, 0_u64) + ); + assert_view!( + "getTimelockedWeightCommitCount(uint16,uint64)", + (TEST_NETUID_U16, 2_u64), + 0_u32 + ); + for version in [1_u8, 2_u8] { + assert_view!( + "getLegacyTimelockedWeightCommit(uint8,uint16,uint64,uint32)", + (version, TEST_NETUID_U16, 2_u64, 0_u32), + (false, H256::zero(), 0_u64, H256::zero(), 0_u32, 0_u64) + ); + assert_view!( + "getLegacyTimelockedWeightCommitCount(uint8,uint16,uint64)", + (version, TEST_NETUID_U16, 2_u64), + 0_u32 + ); + } + }); + } } diff --git a/precompiles/src/proxy.rs b/precompiles/src/proxy.rs index 06a26b6476..5a2df9ab57 100644 --- a/precompiles/src/proxy.rs +++ b/precompiles/src/proxy.rs @@ -12,8 +12,11 @@ use pallet_subtensor_proxy as pallet_proxy; use precompile_utils::EvmResult; use sp_core::{H256, U256}; use sp_runtime::{ + DispatchError, codec::DecodeLimit, - traits::{AsSystemOriginSigner, Dispatchable, StaticLookup}, + traits::{ + AsSystemOriginSigner, Dispatchable, SaturatedConversion, StaticLookup, UniqueSaturatedInto, + }, }; use sp_std::boxed::Box; use sp_std::convert::{TryFrom, TryInto}; @@ -292,6 +295,75 @@ where Ok(result) } + #[precompile::public("getProxyDeposit(bytes32)")] + #[precompile::view] + pub fn get_proxy_deposit( + handle: &mut impl PrecompileHandle, + account_id: H256, + ) -> EvmResult { + handle.record_db_reads::(1)?; + let (_, deposit) = pallet_proxy::Proxies::::get(R::AccountId::from(account_id.0)); + Ok(U256::from(deposit.saturated_into::())) + } + + #[precompile::public("getAnnouncements(bytes32)")] + #[precompile::view] + pub fn get_announcements( + handle: &mut impl PrecompileHandle, + account_id: H256, + ) -> EvmResult<(Vec<(H256, H256, u64)>, U256)> { + handle.record_db_reads::(1)?; + let (announcements, deposit) = + pallet_proxy::Announcements::::get(R::AccountId::from(account_id.0)); + let announcements = announcements + .into_iter() + .map(|announcement| { + ( + H256::from(>::into( + announcement.real().clone(), + )), + H256::from_slice(announcement.call_hash().as_ref()), + (*announcement.height()).unique_saturated_into(), + ) + }) + .collect(); + Ok((announcements, U256::from(deposit.saturated_into::()))) + } + + #[precompile::public("getLastCallResult(bytes32)")] + #[precompile::view] + pub fn get_last_call_result( + handle: &mut impl PrecompileHandle, + account_id: H256, + ) -> EvmResult<(bool, bool, u8, u8, H256)> { + handle.record_db_reads::(1)?; + let Some(result) = pallet_proxy::LastCallResult::::get(R::AccountId::from(account_id.0)) + else { + return Ok((false, false, 0, 0, H256::zero())); + }; + match result { + Ok(()) => Ok((true, true, 0, 0, H256::zero())), + Err(error) => { + let (kind, pallet_index, error_data) = dispatch_error_metadata(error); + Ok((true, false, kind, pallet_index, error_data)) + } + } + } + + #[precompile::public("isRealPaysFee(bytes32,bytes32)")] + #[precompile::view] + pub fn is_real_pays_fee( + handle: &mut impl PrecompileHandle, + real: H256, + delegate: H256, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_proxy::RealPaysFee::::contains_key( + R::AccountId::from(real.0), + R::AccountId::from(delegate.0), + )) + } + #[precompile::public("announce(bytes32,bytes32)")] pub fn announce( handle: &mut impl PrecompileHandle, @@ -374,3 +446,107 @@ where handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(account_id)) } } + +fn dispatch_error_metadata(error: DispatchError) -> (u8, u8, H256) { + let mut data = [0u8; 32]; + match error { + DispatchError::Other(_) => (1, 0, H256::zero()), + DispatchError::CannotLookup => (2, 0, H256::zero()), + DispatchError::BadOrigin => (3, 0, H256::zero()), + DispatchError::Module(module) => { + data[..4].copy_from_slice(&module.error); + (4, module.index, H256::from(data)) + } + DispatchError::ConsumerRemaining => (5, 0, H256::zero()), + DispatchError::NoProviders => (6, 0, H256::zero()), + DispatchError::TooManyConsumers => (7, 0, H256::zero()), + DispatchError::Token(_) => (8, 0, H256::zero()), + DispatchError::Arithmetic(_) => (9, 0, H256::zero()), + DispatchError::Transactional(_) => (10, 0, H256::zero()), + DispatchError::Exhausted => (11, 0, H256::zero()), + DispatchError::Corruption => (12, 0, H256::zero()), + DispatchError::Unavailable => (13, 0, H256::zero()), + DispatchError::RootNotAllowed => (14, 0, H256::zero()), + DispatchError::Trie(_) => (15, 0, H256::zero()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::PrecompileExt; + use crate::mock::{ + AccountId, Runtime, addr_from_index, new_test_ext, precompiles, selector_u32, + }; + use precompile_utils::solidity::encode_with_selector; + use precompile_utils::testing::PrecompileTesterExt; + + #[test] + fn proxy_state_views_return_typed_values_and_missing_state() { + new_test_ext().execute_with(|| { + let caller = addr_from_index(0x80b1); + let address = addr_from_index(ProxyPrecompile::::INDEX); + let real = AccountId::from([0x31; 32]); + let delegate = AccountId::from([0x32; 32]); + let real_word = H256::from_slice(real.as_ref()); + let delegate_word = H256::from_slice(delegate.as_ref()); + let precompiles = precompiles::>(); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getProxyDeposit(bytes32)"), (real_word,)), + ) + .with_static_call(true) + .execute_returns(U256::zero()); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getAnnouncements(bytes32)"), + (delegate_word,), + ), + ) + .with_static_call(true) + .execute_returns((Vec::<(H256, H256, u64)>::new(), U256::zero())); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getLastCallResult(bytes32)"), (real_word,)), + ) + .with_static_call(true) + .execute_returns((false, false, 0_u8, 0_u8, H256::zero())); + + pallet_proxy::LastCallResult::::insert( + &real, + Err::<(), _>(DispatchError::BadOrigin), + ); + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getLastCallResult(bytes32)"), (real_word,)), + ) + .with_static_call(true) + .execute_returns((true, false, 3_u8, 0_u8, H256::zero())); + + pallet_proxy::RealPaysFee::::insert(&real, &delegate, ()); + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("isRealPaysFee(bytes32,bytes32)"), + (real_word, delegate_word), + ), + ) + .with_static_call(true) + .execute_returns(true); + }); + } +} diff --git a/precompiles/src/solidity/alpha.abi b/precompiles/src/solidity/alpha.abi index b3ce52f2dc..aa37571e54 100644 --- a/precompiles/src/solidity/alpha.abi +++ b/precompiles/src/solidity/alpha.abi @@ -380,5 +380,273 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getEmissionAccounting", + "outputs": [ + { + "internalType": "uint64", + "name": "alphaDividends", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rootAlphaDividends", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastHotkeyEmission", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "pendingServerEmission", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "pendingValidatorEmission", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "pendingRootAlphaDividends", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "pendingOwnerCut", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "minerBurned", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "raoRecycledForRegistration", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getEmissionGateConfig", + "outputs": [ + { + "internalType": "uint64", + "name": "blockEmission", + "type": "uint64" + }, + { + "internalType": "int128", + "name": "movingAlpha", + "type": "int128" + }, + { + "internalType": "bool", + "name": "netTaoFlowEnabled", + "type": "bool" + }, + { + "internalType": "int128", + "name": "taoFlowCutoff", + "type": "int128" + }, + { + "internalType": "uint128", + "name": "flowNormExponent", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "emissionBarQuantile", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "emissionGateExponent", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "emissionGateBar", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "flowEmaSmoothingFactor", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetEconomicState", + "outputs": [ + { + "internalType": "bool", + "name": "emissionEnabled", + "type": "bool" + }, + { + "internalType": "uint128", + "name": "rootProportion", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "excessTao", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rootSellTao", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "protocolAlpha", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetFlowState", + "outputs": [ + { + "internalType": "int64", + "name": "taoFlow", + "type": "int64" + }, + { + "internalType": "bool", + "name": "hasTaoFlowEma", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "taoFlowEmaBlock", + "type": "uint64" + }, + { + "internalType": "int128", + "name": "taoFlowEma", + "type": "int128" + }, + { + "internalType": "int64", + "name": "protocolFlow", + "type": "int64" + }, + { + "internalType": "bool", + "name": "hasProtocolFlowEma", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "protocolFlowEmaBlock", + "type": "uint64" + }, + { + "internalType": "int128", + "name": "protocolFlowEma", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSwapState", + "outputs": [ + { + "internalType": "uint16", + "name": "feeRate", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "quoteWeight", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "taoReservoir", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "alphaReservoir", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "migrationName", + "type": "bytes" + } + ], + "name": "hasSwapMigrationRun", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/precompiles/src/solidity/alpha.sol b/precompiles/src/solidity/alpha.sol index 598efbe910..3bbcf9ad55 100644 --- a/precompiles/src/solidity/alpha.sol +++ b/precompiles/src/solidity/alpha.sol @@ -107,4 +107,77 @@ interface IAlpha { uint16 netuid, uint128 rawMultiplier ) external; + function getEmissionAccounting( + uint16 netuid, + bytes32 hotkey + ) + external + view + returns ( + uint64 alphaDividends, + uint64 rootAlphaDividends, + uint64 lastHotkeyEmission, + uint64 pendingServerEmission, + uint64 pendingValidatorEmission, + uint64 pendingRootAlphaDividends, + uint64 pendingOwnerCut, + uint128 minerBurned, + uint64 raoRecycledForRegistration + ); + function getSubnetEconomicState( + uint16 netuid + ) + external + view + returns ( + bool emissionEnabled, + uint128 rootProportion, + uint64 excessTao, + uint64 rootSellTao, + uint64 protocolAlpha + ); + function getSubnetFlowState( + uint16 netuid + ) + external + view + returns ( + int64 taoFlow, + bool hasTaoFlowEma, + uint64 taoFlowEmaBlock, + int128 taoFlowEma, + int64 protocolFlow, + bool hasProtocolFlowEma, + uint64 protocolFlowEmaBlock, + int128 protocolFlowEma + ); + function getEmissionGateConfig() + external + view + returns ( + uint64 blockEmission, + int128 movingAlpha, + bool netTaoFlowEnabled, + int128 taoFlowCutoff, + uint128 flowNormExponent, + uint128 emissionBarQuantile, + uint128 emissionGateExponent, + uint128 emissionGateBar, + uint64 flowEmaSmoothingFactor + ); + function getSwapState( + uint16 netuid + ) + external + view + returns ( + uint16 feeRate, + bool initialized, + uint64 quoteWeight, + uint64 taoReservoir, + uint64 alphaReservoir + ); + function hasSwapMigrationRun( + bytes calldata migrationName + ) external view returns (bool); } diff --git a/precompiles/src/solidity/balance.abi b/precompiles/src/solidity/balance.abi index 9a625eafb7..52c19b6eb6 100644 --- a/precompiles/src/solidity/balance.abi +++ b/precompiles/src/solidity/balance.abi @@ -48,5 +48,18 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [], + "name": "getTotalIssuance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/precompiles/src/solidity/balance.sol b/precompiles/src/solidity/balance.sol index 92bd0b04b2..a20075c5ea 100644 --- a/precompiles/src/solidity/balance.sol +++ b/precompiles/src/solidity/balance.sol @@ -8,6 +8,7 @@ interface IBalance { /// @param coldkey The coldkey public key (32 bytes). /// @return The free balance in rao (1 TAO = 1e9 rao). function getFreeBalance(bytes32 coldkey) external view returns (uint256); + function getTotalIssuance() external view returns (uint256); function burnBalance(uint256 amount, bool keepAlive) external; function upgradeAccounts(bytes32[] calldata accounts) external; } diff --git a/precompiles/src/solidity/leasing.abi b/precompiles/src/solidity/leasing.abi index c4bdca22e0..541ad0cedf 100644 --- a/precompiles/src/solidity/leasing.abi +++ b/precompiles/src/solidity/leasing.abi @@ -181,5 +181,37 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "uint32", + "name": "leaseId", + "type": "uint32" + } + ], + "name": "getAccumulatedLeaseDividends", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextLeaseId", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/precompiles/src/solidity/leasing.sol b/precompiles/src/solidity/leasing.sol index d2988f1676..95ff1927b4 100644 --- a/precompiles/src/solidity/leasing.sol +++ b/precompiles/src/solidity/leasing.sol @@ -29,6 +29,10 @@ interface ILeasing { * @return The lease id. */ function getLeaseIdForSubnet(uint16 netuid) external view returns (uint32); + function getNextLeaseId() external view returns (uint32); + function getAccumulatedLeaseDividends( + uint32 leaseId + ) external view returns (uint64); /** * @dev Create a lease crowdloan. diff --git a/precompiles/src/solidity/neuron.abi b/precompiles/src/solidity/neuron.abi index 88d3a530b2..a8639ab2ce 100644 --- a/precompiles/src/solidity/neuron.abi +++ b/precompiles/src/solidity/neuron.abi @@ -778,5 +778,683 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getBlockAtRegistration", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getBonds", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "value", + "type": "uint16" + } + ], + "internalType": "struct INeuron.WeightPair[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getChainIdentity", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "url", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "githubRepo", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "image", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "discord", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "description", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "additional", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getLegacyTimelockedWeightCommit", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "ciphertextHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "ciphertextLength", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "getLegacyTimelockedWeightCommitCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getLegacyTransactionRateBlocks", + "outputs": [ + { + "internalType": "uint64", + "name": "lastTransactionBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastChildkeyTakeBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastDelegateTakeBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getLoadedEmission", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "serverEmission", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "validatorEmission", + "type": "uint64" + } + ], + "internalType": "struct INeuron.LoadedEmission[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getNeuronCertificate", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "algorithm", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getPrometheus", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "ip", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "port", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "ipType", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetIdentity", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "subnetName", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "githubRepo", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "subnetContact", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "subnetUrl", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "discord", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "description", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "logoUrl", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "additional", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getTimelockedWeightCommit", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "ciphertextHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "ciphertextLength", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "getTimelockedWeightCommitCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transactionKey", + "type": "uint16" + } + ], + "name": "getTransactionKeyLastBlock", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getUid", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getWeightCommit", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getWeightCommitCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getWeights", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "value", + "type": "uint16" + } + ], + "internalType": "struct INeuron.WeightPair[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "isNetworkMember", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/precompiles/src/solidity/neuron.sol b/precompiles/src/solidity/neuron.sol index 1340b88d49..3d8649a7e5 100644 --- a/precompiles/src/solidity/neuron.sol +++ b/precompiles/src/solidity/neuron.sol @@ -3,6 +3,11 @@ pragma solidity ^0.8.0; address constant INeuron_ADDRESS = 0x0000000000000000000000000000000000000804; interface INeuron { + struct WeightPair { + uint16 uid; + uint16 value; + } + /** * @dev Registers a neuron by calling `do_burned_registration` internally with the origin set to the ss58 mirror of the H160 address. * This allows the H160 to further call neuron-related methods and receive emissions. @@ -238,4 +243,148 @@ interface INeuron { function executeAnnouncedColdkeySwap(bytes32 newColdkey) external; function disputeColdkeySwap() external; function clearColdkeySwapAnnouncement() external; + function getUid( + uint16 netuid, + bytes32 hotkey + ) external view returns (bool exists, uint16 uid); + function isNetworkMember( + bytes32 hotkey, + uint16 netuid + ) external view returns (bool); + function getWeights( + uint16 netuid, + uint16 uid + ) external view returns (WeightPair[] memory); + function getBonds( + uint16 netuid, + uint16 uid + ) external view returns (WeightPair[] memory); + function getBlockAtRegistration( + uint16 netuid, + uint16 uid + ) external view returns (uint64); + function getNeuronCertificate( + uint16 netuid, + bytes32 hotkey + ) external view returns (bool exists, uint8 algorithm, bytes memory publicKey); + function getPrometheus( + uint16 netuid, + bytes32 hotkey + ) + external + view + returns ( + bool exists, + uint64 blockNumber, + uint32 version, + uint128 ip, + uint16 port, + uint8 ipType + ); + function getChainIdentity( + bytes32 coldkey + ) + external + view + returns ( + bool exists, + bytes memory name, + bytes memory url, + bytes memory githubRepo, + bytes memory image, + bytes memory discord, + bytes memory description, + bytes memory additional + ); + function getSubnetIdentity( + uint16 netuid + ) + external + view + returns ( + bool exists, + bytes memory subnetName, + bytes memory githubRepo, + bytes memory subnetContact, + bytes memory subnetUrl, + bytes memory discord, + bytes memory description, + bytes memory logoUrl, + bytes memory additional + ); + struct LoadedEmission { + bytes32 hotkey; + uint64 serverEmission; + uint64 validatorEmission; + } + function getLoadedEmission( + uint16 netuid + ) external view returns (bool exists, LoadedEmission[] memory); + function getTransactionKeyLastBlock( + bytes32 hotkey, + uint16 netuid, + uint16 transactionKey + ) external view returns (uint64); + function getLegacyTransactionRateBlocks( + bytes32 hotkey + ) + external + view + returns ( + uint64 lastTransactionBlock, + uint64 lastChildkeyTakeBlock, + uint64 lastDelegateTakeBlock + ); + function getWeightCommit( + uint16 netuid, + bytes32 hotkey, + uint32 index + ) + external + view + returns (bool exists, bytes32 hash, uint64 epoch, uint64 blockNumber); + function getWeightCommitCount( + uint16 netuid, + bytes32 hotkey + ) external view returns (uint32); + function getTimelockedWeightCommit( + uint16 netuid, + uint64 epoch, + uint32 index + ) + external + view + returns ( + bool exists, + bytes32 hotkey, + uint64 blockNumber, + bytes32 ciphertextHash, + uint32 ciphertextLength, + uint64 revealRound + ); + function getTimelockedWeightCommitCount( + uint16 netuid, + uint64 epoch + ) external view returns (uint32); + function getLegacyTimelockedWeightCommit( + uint8 version, + uint16 netuid, + uint64 epoch, + uint32 index + ) + external + view + returns ( + bool exists, + bytes32 hotkey, + uint64 blockNumber, + bytes32 ciphertextHash, + uint32 ciphertextLength, + uint64 revealRound + ); + function getLegacyTimelockedWeightCommitCount( + uint8 version, + uint16 netuid, + uint64 epoch + ) external view returns (uint32); } diff --git a/precompiles/src/solidity/proxy.abi b/precompiles/src/solidity/proxy.abi index ed10b00c9b..cb7644a637 100644 --- a/precompiles/src/solidity/proxy.abi +++ b/precompiles/src/solidity/proxy.abi @@ -245,5 +245,128 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "name": "getAnnouncements", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "internalType": "struct IProxy.AnnouncementInfo[]", + "name": "", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "deposit", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "name": "getLastCallResult", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bool", + "name": "succeeded", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "errorKind", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "palletIndex", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "errorData", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "name": "getProxyDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + } + ], + "name": "isRealPaysFee", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/precompiles/src/solidity/proxy.sol b/precompiles/src/solidity/proxy.sol index c51cf9aafb..d60910285f 100644 --- a/precompiles/src/solidity/proxy.sol +++ b/precompiles/src/solidity/proxy.sol @@ -54,4 +54,29 @@ interface IProxy { function removeAnnouncement(bytes32 real, bytes32 callHash) external; function rejectAnnouncement(bytes32 delegate, bytes32 callHash) external; function setRealPaysFee(bytes32 delegate, bool paysFee) external; + function getProxyDeposit(bytes32 account) external view returns (uint256); + struct AnnouncementInfo { + bytes32 real; + bytes32 callHash; + uint64 height; + } + function getAnnouncements( + bytes32 account + ) external view returns (AnnouncementInfo[] memory, uint256 deposit); + function getLastCallResult( + bytes32 account + ) + external + view + returns ( + bool exists, + bool succeeded, + uint8 errorKind, + uint8 palletIndex, + bytes32 errorData + ); + function isRealPaysFee( + bytes32 real, + bytes32 delegate + ) external view returns (bool); } diff --git a/precompiles/src/solidity/stakingV2.abi b/precompiles/src/solidity/stakingV2.abi index f0b7177168..61a7310a82 100644 --- a/precompiles/src/solidity/stakingV2.abi +++ b/precompiles/src/solidity/stakingV2.abi @@ -1244,5 +1244,629 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAutoStakeDestination", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAutoStakeDestinationColdkeys", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "parent", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getChildKeys", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proportion", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "internalType": "struct IStaking.KeyLink[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getChildkeyTake", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getColdkeyCollateral", + "outputs": [ + { + "internalType": "uint64", + "name": "locked", + "type": "uint64" + }, + { + "internalType": "bytes32[]", + "name": "hotkeys", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getColdkeyRoot", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getColdkeySuccessor", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "successor", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getColdkeySwapDelays", + "outputs": [ + { + "internalType": "uint64", + "name": "announcementDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "reannouncementDelay", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getColdkeySwapStatus", + "outputs": [ + { + "internalType": "bool", + "name": "hasAnnouncement", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "announcementBlock", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "hasDispute", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "disputeBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getCollateralConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "lockShare", + "type": "uint16" + }, + { + "internalType": "uint128", + "name": "drainRatio", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getDelegate", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getHotkeyOwner", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "owner", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getHotkeyRoot", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getHotkeySuccessor", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "successor", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getLastHotkeySwapOnSubnet", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMinChildkeyTakePerSubnet", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getMinerCollateral", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "locked", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "drainRatio", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "minLocked", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "earned", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getOwnedHotkeys", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "child", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getParentKeys", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proportion", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "internalType": "struct IStaking.KeyLink[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPendingChildKeyCooldown", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "parent", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getPendingChildKeys", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proportion", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "internalType": "struct IStaking.KeyLink[]", + "name": "children", + "type": "tuple[]" + }, + { + "internalType": "uint64", + "name": "cooldownBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStakeAccounting", + "outputs": [ + { + "internalType": "uint64", + "name": "totalIssuance", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "totalStake", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTakeLimits", + "outputs": [ + { + "internalType": "uint16", + "name": "minDelegateTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxDelegateTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "minChildkeyTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxChildkeyTake", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/precompiles/src/solidity/stakingV2.sol b/precompiles/src/solidity/stakingV2.sol index 6647ce55e3..b85296132e 100644 --- a/precompiles/src/solidity/stakingV2.sol +++ b/precompiles/src/solidity/stakingV2.sol @@ -625,4 +625,104 @@ interface IStaking { uint16 netuid, uint128 rawRatio ) external; + + struct KeyLink { + uint64 proportion; + bytes32 account; + } + + function getDelegate(bytes32 hotkey) external view returns (bool exists, uint16 take); + function getChildkeyTake(bytes32 hotkey, uint16 netuid) external view returns (uint16); + function getPendingChildKeys( + bytes32 parent, + uint16 netuid + ) external view returns (KeyLink[] memory children, uint64 cooldownBlock); + function getChildKeys( + bytes32 parent, + uint16 netuid + ) external view returns (KeyLink[] memory); + function getParentKeys( + bytes32 child, + uint16 netuid + ) external view returns (KeyLink[] memory); + function getPendingChildKeyCooldown() external view returns (uint64); + function getTakeLimits() + external + view + returns ( + uint16 minDelegateTake, + uint16 maxDelegateTake, + uint16 minChildkeyTake, + uint16 maxChildkeyTake + ); + function getMinChildkeyTakePerSubnet(uint16 netuid) external view returns (uint16); + function getHotkeyOwner(bytes32 hotkey) external view returns (bool exists, bytes32 owner); + function getOwnedHotkeys(bytes32 coldkey) external view returns (bytes32[] memory); + function getAutoStakeDestination( + bytes32 coldkey, + uint16 netuid + ) external view returns (bool exists, bytes32 hotkey); + function getAutoStakeDestinationColdkeys( + bytes32 hotkey, + uint16 netuid + ) external view returns (bytes32[] memory); + function getHotkeySuccessor( + bytes32 hotkey, + uint16 netuid + ) external view returns (bool exists, bytes32 successor); + function getHotkeyRoot( + bytes32 hotkey, + uint16 netuid + ) external view returns (bool exists, bytes32 root); + function getColdkeySuccessor( + bytes32 coldkey + ) external view returns (bool exists, bytes32 successor); + function getColdkeyRoot( + bytes32 coldkey + ) external view returns (bool exists, bytes32 root); + function getColdkeySwapStatus( + bytes32 coldkey + ) + external + view + returns ( + bool hasAnnouncement, + uint64 announcementBlock, + bytes32 callHash, + bool hasDispute, + uint64 disputeBlock + ); + function getColdkeySwapDelays() + external + view + returns (uint64 announcementDelay, uint64 reannouncementDelay); + function getLastHotkeySwapOnSubnet( + bytes32 coldkey, + uint16 netuid + ) external view returns (uint64); + function getStakeAccounting() + external + view + returns (uint64 totalIssuance, uint64 totalStake); + function getMinerCollateral( + uint16 netuid, + bytes32 hotkey, + bytes32 coldkey + ) + external + view + returns ( + bool exists, + uint64 locked, + uint128 drainRatio, + uint64 minLocked, + uint64 earned + ); + function getColdkeyCollateral( + uint16 netuid, + bytes32 coldkey + ) external view returns (uint64 locked, bytes32[] memory hotkeys); + function getCollateralConfig( + uint16 netuid + ) external view returns (uint16 lockShare, uint128 drainRatio); } diff --git a/precompiles/src/solidity/subnet.abi b/precompiles/src/solidity/subnet.abi index 7e5046d854..a21dbd1c2e 100644 --- a/precompiles/src/solidity/subnet.abi +++ b/precompiles/src/solidity/subnet.abi @@ -1428,5 +1428,348 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getBurnConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "halfLife", + "type": "uint16" + }, + { + "internalType": "uint128", + "name": "increaseMultiplier", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalNetworkLimits", + "outputs": [ + { + "internalType": "uint16", + "name": "minActivityCutoff", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "adminFreezeWindow", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "ownerHyperparamRateLimit", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "dissolveScheduleDuration", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "subnetLimit", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "totalNetworks", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "networkImmunityPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "startCallDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minNetworkLockCost", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastNetworkLockCost", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "networkLockReductionInterval", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "subnetOwnerCut", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalProtocolConfig", + "outputs": [ + { + "internalType": "uint8", + "name": "maxMechanismCount", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "commitRevealWeightsVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "networkRegistrationStartBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "taoInRefundDeploymentBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalRateLimits", + "outputs": [ + { + "internalType": "uint64", + "name": "networkRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "weightsVersionKeyRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "transactionRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "delegateTakeRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "childkeyTakeRateLimit", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "maxEpochsPerBlock", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMechanismEmissionSplit", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint16[]", + "name": "split", + "type": "uint16[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetCapacityConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "minAllowedUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxAllowedUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxAllowedValidators", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "adjustmentInterval", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "targetRegistrationsPerInterval", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "minNonImmuneUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "immuneOwnerUidsLimit", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "bondsPenalty", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "ownerCutEnabled", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transfersEnabled", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "maxRegistrationsPerBlock", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mechanismCount", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetMetadata", + "outputs": [ + { + "internalType": "bytes", + "name": "tokenSymbol", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "owner", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "ownerHotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "tempo", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "recycleOrBurn", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getRegisteredSubnetCounter", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetDissolutionStatus", + "outputs": [ + { + "internalType": "bool", + "name": "isDissolving", + "type": "bool" + }, + { + "internalType": "bool", + "name": "cleanupInProgress", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "cleanupPhase", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" } -] \ No newline at end of file +] diff --git a/precompiles/src/solidity/subnet.sol b/precompiles/src/solidity/subnet.sol index fd12fbcf66..23582d2f0f 100644 --- a/precompiles/src/solidity/subnet.sol +++ b/precompiles/src/solidity/subnet.sol @@ -35,6 +35,14 @@ interface ISubnet { uint16 netuid ) external view returns (uint64); + /** + * @dev Returns the monotonic registration generation for a netuid. + * The value increments whenever the netuid is successfully registered. + */ + function getRegisteredSubnetCounter( + uint16 netuid + ) external view returns (uint64); + function setServingRateLimit( uint16 netuid, uint64 servingRateLimit @@ -83,7 +91,7 @@ interface ISubnet { function setImmunityPeriod( uint16 netuid, - uint64 immunityPeriod + uint16 immunityPeriod ) external payable; function getMinAllowedWeights(uint16 netuid) external view returns (uint16); @@ -107,7 +115,7 @@ interface ISubnet { function setAlphaSigmoidSteepness( uint16 netuid, - int16 steepness + uint16 steepness ) external payable; function getActivityCutoff(uint16 netuid) external view returns (uint16); @@ -194,6 +202,34 @@ interface ISubnet { function isSubnetDissolving(uint16 netuid) external view returns (bool); + /** + * @dev Returns stable dissolution and cleanup state for a subnet. + * + * cleanupPhase is zero while cleanup has not started. Once cleanup is in + * progress, the append-only phase codes are: + * 1 root claimable dividends; 2 root claimed dividends; + * 3 calculate stake value; 4 settle stakes; 5 clear alpha; + * 6 clear hotkey totals; 7 clear stake locks; 8 clear decaying stake locks; + * 9 finish stake cleanup; 10 clear protocol liquidity; + * 11 purge subnet commitments; 12 clear network membership; + * 13 clear network parameters; 14 clear network maps; + * 15 update root weights; 16 clear childkey takes; + * 17 clear childkeys; 18 clear parentkeys; + * 19 clear last hotkey emissions; 20 clear last-epoch hotkey alpha; + * 21 clear transaction rate-limit records; 22 clear network locks; + * 23 clear decaying network locks. + */ + function getSubnetDissolutionStatus( + uint16 netuid + ) + external + view + returns ( + bool isDissolving, + bool cleanupInProgress, + uint8 cleanupPhase + ); + function setLiquidAlphaEnabled( uint16 netuid, bool liquidAlphaEnabled @@ -233,6 +269,8 @@ interface ISubnet { uint64 commitRevealWeightsInterval ) external payable; + function toggleTransfers(uint16 netuid, bool toggle) external payable; + function setSubnetIdentity( uint16 netuid, string calldata subnetName, @@ -263,4 +301,78 @@ interface ISubnet { ) external; function setTempo(uint16 netuid, uint16 tempo) external; function trimToMaxAllowedUids(uint16 netuid, uint16 maxUids) external; + function getSubnetMetadata( + uint16 netuid + ) + external + view + returns ( + bytes memory tokenSymbol, + bytes32 owner, + bytes32 ownerHotkey, + uint16 tempo, + uint8 recycleOrBurn + ); + function getSubnetCapacityConfig( + uint16 netuid + ) + external + view + returns ( + uint16 minAllowedUids, + uint16 maxAllowedUids, + uint16 maxAllowedValidators, + uint16 adjustmentInterval, + uint16 targetRegistrationsPerInterval, + uint16 minNonImmuneUids, + uint16 immuneOwnerUidsLimit, + uint16 bondsPenalty, + bool ownerCutEnabled, + bool transfersEnabled, + uint16 maxRegistrationsPerBlock, + uint8 mechanismCount + ); + function getMechanismEmissionSplit( + uint16 netuid + ) external view returns (bool exists, uint16[] memory split); + function getBurnConfig( + uint16 netuid + ) external view returns (uint16 halfLife, uint128 increaseMultiplier); + function getGlobalNetworkLimits() + external + view + returns ( + uint16 minActivityCutoff, + uint16 adminFreezeWindow, + uint16 ownerHyperparamRateLimit, + uint64 dissolveScheduleDuration, + uint16 subnetLimit, + uint16 totalNetworks, + uint64 networkImmunityPeriod, + uint64 startCallDelay, + uint64 minNetworkLockCost, + uint64 lastNetworkLockCost, + uint64 networkLockReductionInterval, + uint16 subnetOwnerCut + ); + function getGlobalRateLimits() + external + view + returns ( + uint64 networkRateLimit, + uint64 weightsVersionKeyRateLimit, + uint64 transactionRateLimit, + uint64 delegateTakeRateLimit, + uint64 childkeyTakeRateLimit, + uint8 maxEpochsPerBlock + ); + function getGlobalProtocolConfig() + external + view + returns ( + uint8 maxMechanismCount, + uint16 commitRevealWeightsVersion, + uint64 networkRegistrationStartBlock, + uint64 taoInRefundDeploymentBlock + ); } diff --git a/precompiles/src/solidity/uidLookup.abi b/precompiles/src/solidity/uidLookup.abi index 558358dcaa..dfe4f8ebfc 100644 --- a/precompiles/src/solidity/uidLookup.abi +++ b/precompiles/src/solidity/uidLookup.abi @@ -39,5 +39,39 @@ ], "stateMutability": "view", "type": "function" - } + }, +{ + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getAssociatedEvmAddress", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "address", + "name": "evmAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "blockAssociated", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } ] \ No newline at end of file diff --git a/precompiles/src/solidity/uidLookup.sol b/precompiles/src/solidity/uidLookup.sol index 4eae98899c..42a604ed15 100644 --- a/precompiles/src/solidity/uidLookup.sol +++ b/precompiles/src/solidity/uidLookup.sol @@ -13,4 +13,8 @@ interface IUidLookup { address evm_address, uint16 limit ) external view returns (LookupItem[] memory); + function getAssociatedEvmAddress( + uint16 netuid, + uint16 uid + ) external view returns (bool exists, address evmAddress, uint64 blockAssociated); } diff --git a/precompiles/src/staking.rs b/precompiles/src/staking.rs index 0c636afc3a..5b8be6801a 100644 --- a/precompiles/src/staking.rs +++ b/precompiles/src/staking.rs @@ -68,6 +68,16 @@ const MAX_CONVICTION_HOTKEYS: usize = 64; const COLDKEY_LOCK_READS: u64 = 6; // Aggregate state reads the owner hotkey, global rates, current block, and up to four buckets. const HOTKEY_LOCK_READS: u64 = 8; +// Each hotkey-wide total visits every possible subnet. Besides the +// `NetworksAdded` entry, one active subnet can read TotalHotkeyAlpha plus the +// four values used by `current_alpha_price`. +const TOTAL_HOTKEY_STAKE_READS_PER_SUBNET: u64 = 5; +// For each raw Alpha/AlphaV2 position, the coldkey totals read the position +// once while accounting and once in the released helper. A matching position +// can then perform the conservative V2 stake lookup, swap simulation, and +// current-price reads. +const TOTAL_COLDKEY_POSITION_BASE_READS: u64 = 2; +const TOTAL_COLDKEY_MATCHED_POSITION_READS: u64 = STAKE_INFO_READS_PER_HOTKEY + 9 + 4; /// Prefix for the Allowances map in Substrate storage. pub struct AllowancesPrefix; @@ -321,9 +331,8 @@ where handle: &mut impl PrecompileHandle, coldkey: H256, ) -> EvmResult { - // StakingHotkeys + per-hotkey stake reads - handle.record_db_reads::(2)?; let coldkey = R::AccountId::from(coldkey.0); + record_total_coldkey_stake_reads::(handle, &coldkey, None)?; let stake = pallet_subtensor::Pallet::::get_total_stake_for_coldkey(&coldkey); Ok(stake.to_u64().into()) @@ -332,8 +341,7 @@ where #[precompile::public("getTotalHotkeyStake(bytes32)")] #[precompile::view] fn get_total_hotkey_stake(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult { - // Per-subnet stake + alpha price reads - handle.record_db_reads::(2)?; + record_total_hotkey_stake_reads::(handle)?; let hotkey = R::AccountId::from(hotkey.0); let stake = pallet_subtensor::Pallet::::get_total_stake_for_hotkey(&hotkey); @@ -791,10 +799,9 @@ where coldkey: H256, netuid: U256, ) -> EvmResult { - // StakingHotkeys + per-hotkey stake reads - handle.record_db_reads::(2)?; let coldkey = R::AccountId::from(coldkey.0); let netuid = try_u16_from_u256(netuid)?; + record_total_coldkey_stake_reads::(handle, &coldkey, Some(netuid.into()))?; let stake = pallet_subtensor::Pallet::::get_total_stake_for_coldkey_on_subnet( &coldkey, netuid.into(), @@ -1307,6 +1314,370 @@ where }, ) } + + #[precompile::public("getDelegate(bytes32)")] + #[precompile::view] + fn get_delegate(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult<(bool, u16)> { + handle.record_db_reads::(1)?; + let hotkey = R::AccountId::from(hotkey.0); + Ok(match pallet_subtensor::Delegates::::try_get(hotkey) { + Ok(take) => (true, take.deconstruct()), + Err(()) => (false, 0), + }) + } + + #[precompile::public("getChildkeyTake(bytes32,uint16)")] + #[precompile::view] + fn get_childkey_take( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::ChildkeyTake::::get( + R::AccountId::from(hotkey.0), + NetUid::from(netuid), + ) + .deconstruct()) + } + + #[precompile::public("getPendingChildKeys(bytes32,uint16)")] + #[precompile::view] + fn get_pending_child_keys( + handle: &mut impl PrecompileHandle, + parent: H256, + netuid: u16, + ) -> EvmResult<(Vec<(u64, H256)>, u64)> { + handle.record_db_reads::(1)?; + let (children, cooldown_block) = pallet_subtensor::PendingChildKeys::::get( + NetUid::from(netuid), + R::AccountId::from(parent.0), + ); + Ok(( + children + .into_iter() + .map(|(proportion, child)| (proportion, account_to_h256(child))) + .collect(), + cooldown_block, + )) + } + + #[precompile::public("getChildKeys(bytes32,uint16)")] + #[precompile::view] + fn get_child_keys( + handle: &mut impl PrecompileHandle, + parent: H256, + netuid: u16, + ) -> EvmResult> { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::ChildKeys::::get( + R::AccountId::from(parent.0), + NetUid::from(netuid), + ) + .into_iter() + .map(|(proportion, child)| (proportion, account_to_h256(child))) + .collect()) + } + + #[precompile::public("getParentKeys(bytes32,uint16)")] + #[precompile::view] + fn get_parent_keys( + handle: &mut impl PrecompileHandle, + child: H256, + netuid: u16, + ) -> EvmResult> { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::ParentKeys::::get( + R::AccountId::from(child.0), + NetUid::from(netuid), + ) + .into_iter() + .map(|(proportion, parent)| (proportion, account_to_h256(parent))) + .collect()) + } + + #[precompile::public("getPendingChildKeyCooldown()")] + #[precompile::view] + fn get_pending_childkey_cooldown(handle: &mut impl PrecompileHandle) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::PendingChildKeyCooldown::::get()) + } + + #[precompile::public("getTakeLimits()")] + #[precompile::view] + fn get_take_limits(handle: &mut impl PrecompileHandle) -> EvmResult<(u16, u16, u16, u16)> { + handle.record_db_reads::(4)?; + Ok(( + pallet_subtensor::MinDelegateTake::::get().deconstruct(), + pallet_subtensor::MaxDelegateTake::::get().deconstruct(), + pallet_subtensor::MinChildkeyTake::::get().deconstruct(), + pallet_subtensor::MaxChildkeyTake::::get().deconstruct(), + )) + } + + #[precompile::public("getMinChildkeyTakePerSubnet(uint16)")] + #[precompile::view] + fn get_min_childkey_take_per_subnet( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok( + pallet_subtensor::MinChildkeyTakePerSubnet::::get(NetUid::from(netuid)) + .deconstruct(), + ) + } + + #[precompile::public("getHotkeyOwner(bytes32)")] + #[precompile::view] + fn get_hotkey_owner( + handle: &mut impl PrecompileHandle, + hotkey: H256, + ) -> EvmResult<(bool, H256)> { + handle.record_db_reads::(1)?; + let hotkey = R::AccountId::from(hotkey.0); + Ok(match pallet_subtensor::Owner::::try_get(hotkey) { + Ok(owner) => (true, account_to_h256(owner)), + Err(()) => (false, H256::zero()), + }) + } + + #[precompile::public("getOwnedHotkeys(bytes32)")] + #[precompile::view] + fn get_owned_hotkeys( + handle: &mut impl PrecompileHandle, + coldkey: H256, + ) -> EvmResult> { + handle.record_db_reads::(1)?; + Ok( + pallet_subtensor::OwnedHotkeys::::get(R::AccountId::from(coldkey.0)) + .into_iter() + .map(account_to_h256) + .collect(), + ) + } + + #[precompile::public("getAutoStakeDestination(bytes32,uint16)")] + #[precompile::view] + fn get_auto_stake_destination( + handle: &mut impl PrecompileHandle, + coldkey: H256, + netuid: u16, + ) -> EvmResult<(bool, H256)> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::AutoStakeDestination::::get( + R::AccountId::from(coldkey.0), + NetUid::from(netuid), + ) { + Some(hotkey) => (true, account_to_h256(hotkey)), + None => (false, H256::zero()), + }, + ) + } + + #[precompile::public("getAutoStakeDestinationColdkeys(bytes32,uint16)")] + #[precompile::view] + fn get_auto_stake_destination_coldkeys( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + ) -> EvmResult> { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::AutoStakeDestinationColdkeys::::get( + R::AccountId::from(hotkey.0), + NetUid::from(netuid), + ) + .into_iter() + .map(account_to_h256) + .collect()) + } + + #[precompile::public("getHotkeySuccessor(bytes32,uint16)")] + #[precompile::view] + fn get_hotkey_successor( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + ) -> EvmResult<(bool, H256)> { + handle.record_db_reads::(1)?; + Ok(optional_account( + pallet_subtensor::HotkeySuccessor::::get( + NetUid::from(netuid), + R::AccountId::from(hotkey.0), + ), + )) + } + + #[precompile::public("getHotkeyRoot(bytes32,uint16)")] + #[precompile::view] + fn get_hotkey_root( + handle: &mut impl PrecompileHandle, + hotkey: H256, + netuid: u16, + ) -> EvmResult<(bool, H256)> { + handle.record_db_reads::(1)?; + Ok(optional_account(pallet_subtensor::HotkeyRoot::::get( + NetUid::from(netuid), + R::AccountId::from(hotkey.0), + ))) + } + + #[precompile::public("getColdkeySuccessor(bytes32)")] + #[precompile::view] + fn get_coldkey_successor( + handle: &mut impl PrecompileHandle, + coldkey: H256, + ) -> EvmResult<(bool, H256)> { + handle.record_db_reads::(1)?; + Ok(optional_account( + pallet_subtensor::ColdkeySuccessor::::get(R::AccountId::from(coldkey.0)), + )) + } + + #[precompile::public("getColdkeyRoot(bytes32)")] + #[precompile::view] + fn get_coldkey_root( + handle: &mut impl PrecompileHandle, + coldkey: H256, + ) -> EvmResult<(bool, H256)> { + handle.record_db_reads::(1)?; + Ok(optional_account(pallet_subtensor::ColdkeyRoot::::get( + R::AccountId::from(coldkey.0), + ))) + } + + #[precompile::public("getColdkeySwapStatus(bytes32)")] + #[precompile::view] + fn get_coldkey_swap_status( + handle: &mut impl PrecompileHandle, + coldkey: H256, + ) -> EvmResult<(bool, u64, H256, bool, u64)> { + handle.record_db_reads::(2)?; + let coldkey = R::AccountId::from(coldkey.0); + let announcement = pallet_subtensor::ColdkeySwapAnnouncements::::get(&coldkey); + let dispute = pallet_subtensor::ColdkeySwapDisputes::::get(&coldkey); + let (has_announcement, announcement_block, call_hash) = match announcement { + Some((block, hash)) => ( + true, + block.unique_saturated_into(), + H256::from_slice(hash.as_ref()), + ), + None => (false, 0, H256::zero()), + }; + Ok(( + has_announcement, + announcement_block, + call_hash, + dispute.is_some(), + dispute + .map(UniqueSaturatedInto::unique_saturated_into) + .unwrap_or(0), + )) + } + + #[precompile::public("getColdkeySwapDelays()")] + #[precompile::view] + fn get_coldkey_swap_delays(handle: &mut impl PrecompileHandle) -> EvmResult<(u64, u64)> { + handle.record_db_reads::(2)?; + Ok(( + pallet_subtensor::ColdkeySwapAnnouncementDelay::::get().unique_saturated_into(), + pallet_subtensor::ColdkeySwapReannouncementDelay::::get().unique_saturated_into(), + )) + } + + #[precompile::public("getLastHotkeySwapOnSubnet(bytes32,uint16)")] + #[precompile::view] + fn get_last_hotkey_swap_on_subnet( + handle: &mut impl PrecompileHandle, + coldkey: H256, + netuid: u16, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::LastHotkeySwapOnNetuid::::get( + NetUid::from(netuid), + R::AccountId::from(coldkey.0), + )) + } + + #[precompile::public("getStakeAccounting()")] + #[precompile::view] + fn get_stake_accounting(handle: &mut impl PrecompileHandle) -> EvmResult<(u64, u64)> { + handle.record_db_reads::(2)?; + Ok(( + pallet_subtensor::TotalIssuance::::get().to_u64(), + pallet_subtensor::TotalStake::::get().to_u64(), + )) + } + + #[precompile::public("getMinerCollateral(uint16,bytes32,bytes32)")] + #[precompile::view] + fn get_miner_collateral( + handle: &mut impl PrecompileHandle, + netuid: u16, + hotkey: H256, + coldkey: H256, + ) -> EvmResult<(bool, u64, u128, u64, u64)> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::MinerCollateral::::get(( + NetUid::from(netuid), + R::AccountId::from(hotkey.0), + R::AccountId::from(coldkey.0), + )) { + Some(state) => ( + true, + state.locked.to_u64(), + state.drain_ratio.to_bits(), + state.min_locked.to_u64(), + state.earned.to_u64(), + ), + None => (false, 0, 0, 0, 0), + }, + ) + } + + #[precompile::public("getColdkeyCollateral(uint16,bytes32)")] + #[precompile::view] + fn get_coldkey_collateral( + handle: &mut impl PrecompileHandle, + netuid: u16, + coldkey: H256, + ) -> EvmResult<(u64, Vec)> { + handle.record_db_reads::(2)?; + let coldkey = R::AccountId::from(coldkey.0); + Ok(( + pallet_subtensor::ColdkeyMinerCollateral::::get(NetUid::from(netuid), &coldkey) + .to_u64(), + pallet_subtensor::ColdkeyCollateralHotkeys::::get(NetUid::from(netuid), coldkey) + .into_iter() + .map(account_to_h256) + .collect(), + )) + } + + #[precompile::public("getCollateralConfig(uint16)")] + #[precompile::view] + fn get_collateral_config( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(u16, u128)> { + handle.record_db_reads::(2)?; + Ok(( + pallet_subtensor::CollateralLockShare::::get(NetUid::from(netuid)), + pallet_subtensor::CollateralDrainRatio::::get(NetUid::from(netuid)).to_bits(), + )) + } +} + +fn account_to_h256>(account: AccountId) -> H256 { + H256::from(account.into()) +} + +fn optional_account>(account: Option) -> (bool, H256) { + account + .map(|account| (true, account_to_h256(account))) + .unwrap_or((false, H256::zero())) } fn dispatch_subtensor( @@ -1371,6 +1742,55 @@ where handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) } +fn record_total_hotkey_stake_reads(handle: &mut impl PrecompileHandle) -> EvmResult<()> +where + R: frame_system::Config + pallet_subtensor::Config + pallet_evm::Config, +{ + // Charge the SubnetLimit read plus the maximum permitted work before the + // released helper scans NetworksAdded. + handle.record_db_reads::(1)?; + let subnet_limit: u64 = pallet_subtensor::SubnetLimit::::get().unique_saturated_into(); + handle.record_db_reads::(subnet_limit.saturating_mul(TOTAL_HOTKEY_STAKE_READS_PER_SUBNET)) +} + +fn record_total_coldkey_stake_reads( + handle: &mut impl PrecompileHandle, + coldkey: &R::AccountId, + selected_netuid: Option, +) -> EvmResult<()> +where + R: frame_system::Config + pallet_subtensor::Config + pallet_evm::Config, + R::AccountId: Clone, +{ + // Read the bounded-by-state list once here and once in the released + // aggregate helper. + handle.record_db_reads::(2)?; + let hotkeys = pallet_subtensor::StakingHotkeys::::get(coldkey); + + let mut raw_positions = 0u64; + let mut matched_positions = 0u64; + for hotkey in hotkeys { + for (netuid, _) in pallet_subtensor::Alpha::::iter_prefix((&hotkey, coldkey)) { + raw_positions = raw_positions.saturating_add(1); + if selected_netuid.is_none_or(|selected| selected == netuid) { + matched_positions = matched_positions.saturating_add(1); + } + } + for (netuid, _) in pallet_subtensor::AlphaV2::::iter_prefix((&hotkey, coldkey)) { + raw_positions = raw_positions.saturating_add(1); + if selected_netuid.is_none_or(|selected| selected == netuid) { + matched_positions = matched_positions.saturating_add(1); + } + } + } + + handle.record_db_reads::( + raw_positions + .saturating_mul(TOTAL_COLDKEY_POSITION_BASE_READS) + .saturating_add(matched_positions.saturating_mul(TOTAL_COLDKEY_MATCHED_POSITION_READS)), + ) +} + // Deprecated, exists for backward compatibility. pub struct StakingPrecompile(PhantomData); @@ -1486,9 +1906,8 @@ where handle: &mut impl PrecompileHandle, coldkey: H256, ) -> EvmResult { - // StakingHotkeys + per-hotkey stake reads - handle.record_db_reads::(2)?; let coldkey = R::AccountId::from(coldkey.0); + record_total_coldkey_stake_reads::(handle, &coldkey, None)?; // get total stake of coldkey let total_stake = @@ -1505,8 +1924,7 @@ where #[precompile::public("getTotalHotkeyStake(bytes32)")] #[precompile::view] fn get_total_hotkey_stake(handle: &mut impl PrecompileHandle, hotkey: H256) -> EvmResult { - // Per-subnet stake + alpha price reads - handle.record_db_reads::(2)?; + record_total_hotkey_stake_reads::(handle)?; let hotkey = R::AccountId::from(hotkey.0); // get total stake of hotkey @@ -1634,12 +2052,12 @@ mod tests { )] use super::*; - use crate::PrecompileExt; use crate::mock::{ AccountId, Proxy, Runtime, RuntimeCall, RuntimeOrigin, addr_from_index, assert_static_call, execute_precompile, fund_account, mapped_account, new_test_ext, precompiles, selector_u32, substrate_to_evm, }; + use crate::{PrecompileExt, Precompiles}; use precompile_utils::prelude::RuntimeHelper; use precompile_utils::solidity::{encode_return_value, encode_with_selector}; use precompile_utils::testing::PrecompileTesterExt; @@ -3491,4 +3909,280 @@ mod tests { assert_eq!(stake_after, stake_before); }); } + + #[test] + fn aggregate_stake_views_charge_their_scans() { + new_test_ext().execute_with(|| { + setup_staking_subnet(); + let caller = addr_from_index(0x3005); + let empty_account = AccountId::from([0x91; 32]); + let account_arg = H256::from_slice(empty_account.as_ref()); + let db_read = RuntimeHelper::::db_read_gas_cost(); + let hotkey_reads = 1u64.saturating_add( + u64::from(pallet_subtensor::SubnetLimit::::get()) + .saturating_mul(TOTAL_HOTKEY_STAKE_READS_PER_SUBNET), + ); + + for (address, is_v2) in [ + (addr_from_index(StakingPrecompileV2::::INDEX), true), + (addr_from_index(StakingPrecompile::::INDEX), false), + ] { + let precompiles = Precompiles::::new(); + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getTotalHotkeyStake(bytes32)"), + (account_arg,), + ), + ) + .with_static_call(true) + .expect_cost(db_read.saturating_mul(hotkey_reads)) + .execute_returns(U256::zero()); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getTotalColdkeyStake(bytes32)"), + (account_arg,), + ), + ) + .with_static_call(true) + .expect_cost(db_read.saturating_mul(2)) + .execute_returns(U256::zero()); + + if is_v2 { + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getTotalColdkeyStakeOnSubnet(bytes32,uint256)"), + (account_arg, U256::from(TEST_NETUID_U16)), + ), + ) + .with_static_call(true) + .expect_cost(db_read.saturating_mul(2)) + .execute_returns(U256::zero()); + } + } + }); + } + + #[test] + fn coldkey_aggregate_views_charge_each_stake_position() { + new_test_ext().execute_with(|| { + let netuid = setup_staking_subnet(); + let caller = addr_from_index(0x3007); + let coldkey = AccountId::from([0x92; 32]); + let hotkey = AccountId::from([0x93; 32]); + let coldkey_word = H256::from_slice(coldkey.as_ref()); + pallet_subtensor::Pallet::::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &coldkey, + netuid, + AlphaBalance::from(1_000_u64), + ); + + let total = + pallet_subtensor::Pallet::::get_total_stake_for_coldkey(&coldkey).to_u64(); + let subnet_total = + pallet_subtensor::Pallet::::get_total_stake_for_coldkey_on_subnet( + &coldkey, netuid, + ) + .to_u64(); + let reads = 2_u64 + .saturating_add(TOTAL_COLDKEY_POSITION_BASE_READS) + .saturating_add(TOTAL_COLDKEY_MATCHED_POSITION_READS); + let cost = RuntimeHelper::::db_read_gas_cost().saturating_mul(reads); + let address = addr_from_index(StakingPrecompileV2::::INDEX); + let precompiles = Precompiles::::new(); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getTotalColdkeyStake(bytes32)"), + (coldkey_word,), + ), + ) + .with_static_call(true) + .expect_cost(cost) + .execute_returns(U256::from(total)); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getTotalColdkeyStakeOnSubnet(bytes32,uint256)"), + (coldkey_word, U256::from(TEST_NETUID_U16)), + ), + ) + .with_static_call(true) + .expect_cost(cost) + .execute_returns(U256::from(subnet_total)); + }); + } + + #[test] + fn staking_state_views_return_typed_values_and_missing_state() { + new_test_ext().execute_with(|| { + let netuid = NetUid::from(TEST_NETUID_U16); + let caller = addr_from_index(0x3006); + let address = addr_from_index(StakingPrecompileV2::::INDEX); + let hotkey = AccountId::from([0x71; 32]); + let coldkey = AccountId::from([0x72; 32]); + let hotkey_word = H256::from_slice(hotkey.as_ref()); + let coldkey_word = H256::from_slice(coldkey.as_ref()); + let precompiles = precompiles::>(); + + macro_rules! assert_view { + ($signature:literal, $arguments:expr, $expected:expr) => { + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32($signature), $arguments), + ) + .with_static_call(true) + .execute_returns($expected); + }; + } + + pallet_subtensor::Delegates::::insert(&hotkey, PerU16::from_parts(123)); + pallet_subtensor::Owner::::insert(&hotkey, &coldkey); + pallet_subtensor::OwnedHotkeys::::insert(&coldkey, vec![hotkey.clone()]); + + assert_view!("getDelegate(bytes32)", (hotkey_word,), (true, 123_u16)); + assert_view!( + "getChildkeyTake(bytes32,uint16)", + (hotkey_word, TEST_NETUID_U16), + pallet_subtensor::ChildkeyTake::::get(&hotkey, netuid).deconstruct() + ); + assert_view!( + "getPendingChildKeys(bytes32,uint16)", + (hotkey_word, TEST_NETUID_U16), + (Vec::<(u64, H256)>::new(), 0_u64) + ); + assert_view!( + "getChildKeys(bytes32,uint16)", + (hotkey_word, TEST_NETUID_U16), + Vec::<(u64, H256)>::new() + ); + assert_view!( + "getParentKeys(bytes32,uint16)", + (hotkey_word, TEST_NETUID_U16), + Vec::<(u64, H256)>::new() + ); + assert_view!( + "getPendingChildKeyCooldown()", + (), + pallet_subtensor::PendingChildKeyCooldown::::get() + ); + assert_view!( + "getTakeLimits()", + (), + ( + pallet_subtensor::MinDelegateTake::::get().deconstruct(), + pallet_subtensor::MaxDelegateTake::::get().deconstruct(), + pallet_subtensor::MinChildkeyTake::::get().deconstruct(), + pallet_subtensor::MaxChildkeyTake::::get().deconstruct(), + ) + ); + assert_view!( + "getMinChildkeyTakePerSubnet(uint16)", + (TEST_NETUID_U16,), + pallet_subtensor::MinChildkeyTakePerSubnet::::get(netuid).deconstruct() + ); + assert_view!( + "getHotkeyOwner(bytes32)", + (hotkey_word,), + (true, coldkey_word) + ); + assert_view!( + "getOwnedHotkeys(bytes32)", + (coldkey_word,), + vec![hotkey_word] + ); + assert_view!( + "getAutoStakeDestination(bytes32,uint16)", + (coldkey_word, TEST_NETUID_U16), + (false, H256::zero()) + ); + assert_view!( + "getAutoStakeDestinationColdkeys(bytes32,uint16)", + (hotkey_word, TEST_NETUID_U16), + Vec::::new() + ); + assert_view!( + "getHotkeySuccessor(bytes32,uint16)", + (hotkey_word, TEST_NETUID_U16), + (false, H256::zero()) + ); + assert_view!( + "getHotkeyRoot(bytes32,uint16)", + (hotkey_word, TEST_NETUID_U16), + (false, H256::zero()) + ); + assert_view!( + "getColdkeySuccessor(bytes32)", + (coldkey_word,), + (false, H256::zero()) + ); + assert_view!( + "getColdkeyRoot(bytes32)", + (coldkey_word,), + (false, H256::zero()) + ); + assert_view!( + "getColdkeySwapStatus(bytes32)", + (coldkey_word,), + (false, 0_u64, H256::zero(), false, 0_u64) + ); + assert_view!( + "getColdkeySwapDelays()", + (), + ( + pallet_subtensor::ColdkeySwapAnnouncementDelay::::get(), + pallet_subtensor::ColdkeySwapReannouncementDelay::::get(), + ) + ); + assert_view!( + "getLastHotkeySwapOnSubnet(bytes32,uint16)", + (coldkey_word, TEST_NETUID_U16), + 0_u64 + ); + assert_view!( + "getStakeAccounting()", + (), + ( + pallet_subtensor::TotalIssuance::::get().to_u64(), + pallet_subtensor::TotalStake::::get().to_u64(), + ) + ); + assert_view!( + "getMinerCollateral(uint16,bytes32,bytes32)", + (TEST_NETUID_U16, hotkey_word, coldkey_word), + (false, 0_u64, 0_u128, 0_u64, 0_u64) + ); + assert_view!( + "getColdkeyCollateral(uint16,bytes32)", + (TEST_NETUID_U16, coldkey_word), + (0_u64, Vec::::new()) + ); + assert_view!( + "getCollateralConfig(uint16)", + (TEST_NETUID_U16,), + ( + pallet_subtensor::CollateralLockShare::::get(netuid), + pallet_subtensor::CollateralDrainRatio::::get(netuid).to_bits(), + ) + ); + }); + } } diff --git a/precompiles/src/subnet.rs b/precompiles/src/subnet.rs index c9687fe1fb..6551c7ee0f 100644 --- a/precompiles/src/subnet.rs +++ b/precompiles/src/subnet.rs @@ -7,14 +7,15 @@ use frame_system::RawOrigin; use pallet_evm::{AddressMapping, PrecompileHandle}; use precompile_utils::{ EvmResult, - prelude::{BoundedString, BoundedVec}, + prelude::{BoundedString, BoundedVec, UnboundedBytes}, }; use sp_core::H256; -use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable}; +use sp_runtime::traits::{AsSystemOriginSigner, Dispatchable, UniqueSaturatedInto}; use sp_std::{vec, vec::Vec}; use subtensor_runtime_common::{NetUid, TaoBalance, Token}; use crate::{PrecompileExt, PrecompileHandleExt}; +use pallet_subtensor::subnets::dissolution::DissolveCleanupPhase; pub struct SubnetPrecompile(PhantomData); @@ -30,7 +31,7 @@ where + Send + Sync + scale_info::TypeInfo, - R::AccountId: From<[u8; 32]>, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + From> @@ -58,7 +59,7 @@ where + Send + Sync + scale_info::TypeInfo, - R::AccountId: From<[u8; 32]>, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + From> @@ -176,6 +177,18 @@ where )) } + #[precompile::public("getRegisteredSubnetCounter(uint16)")] + #[precompile::view] + fn get_registered_subnet_counter( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult { + handle.record_db_reads::(1)?; + Ok(pallet_subtensor::RegisteredSubnetCounter::::get( + NetUid::from(netuid), + )) + } + #[precompile::public("getServingRateLimit(uint16)")] #[precompile::view] fn get_serving_rate_limit(handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { @@ -895,6 +908,24 @@ where Ok(pallet_subtensor::DissolveCleanupQueue::::get().contains(&NetUid::from(netuid))) } + #[precompile::public("getSubnetDissolutionStatus(uint16)")] + #[precompile::view] + fn get_subnet_dissolution_status( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(bool, bool, u8)> { + handle.record_db_reads::(2)?; + let netuid = NetUid::from(netuid); + let is_queued = pallet_subtensor::DissolveCleanupQueue::::get().contains(&netuid); + + match pallet_subtensor::CurrentDissolveCleanupStatus::::get() { + Some(status) if status.netuid == netuid => { + Ok((true, true, dissolution_cleanup_phase_code(&status.phase))) + } + _ => Ok((is_queued, false, 0)), + } + } + #[precompile::public( "setSubnetIdentity(uint16,string,string,string,string,string,string,string,string)" )] @@ -1101,6 +1132,133 @@ where }, ) } + + #[precompile::public("getSubnetMetadata(uint16)")] + #[precompile::view] + fn get_subnet_metadata( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(UnboundedBytes, H256, H256, u16, u8)> { + handle.record_db_reads::(5)?; + let netuid = NetUid::from(netuid); + let recycle_or_burn = match pallet_subtensor::RecycleOrBurn::::get(netuid) { + pallet_subtensor::RecycleOrBurnEnum::Burn => 0, + pallet_subtensor::RecycleOrBurnEnum::Recycle => 1, + }; + Ok(( + UnboundedBytes::from(pallet_subtensor::TokenSymbol::::get(netuid)), + account_to_h256(pallet_subtensor::SubnetOwner::::get(netuid)), + account_to_h256(pallet_subtensor::SubnetOwnerHotkey::::get(netuid)), + pallet_subtensor::Tempo::::get(netuid), + recycle_or_burn, + )) + } + + #[precompile::public("getSubnetCapacityConfig(uint16)")] + #[precompile::view] + fn get_subnet_capacity_config( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(u16, u16, u16, u16, u16, u16, u16, u16, bool, bool, u16, u8)> { + handle.record_db_reads::(12)?; + let netuid = NetUid::from(netuid); + Ok(( + pallet_subtensor::MinAllowedUids::::get(netuid), + pallet_subtensor::MaxAllowedUids::::get(netuid), + pallet_subtensor::MaxAllowedValidators::::get(netuid), + pallet_subtensor::AdjustmentInterval::::get(netuid), + pallet_subtensor::TargetRegistrationsPerInterval::::get(netuid), + pallet_subtensor::MinNonImmuneUids::::get(netuid), + pallet_subtensor::ImmuneOwnerUidsLimit::::get(netuid), + pallet_subtensor::BondsPenalty::::get(netuid), + pallet_subtensor::OwnerCutEnabled::::get(netuid), + pallet_subtensor::TransferToggle::::get(netuid), + pallet_subtensor::MaxRegistrationsPerBlock::::get(netuid), + pallet_subtensor::MechanismCountCurrent::::get(netuid).into(), + )) + } + + #[precompile::public("getMechanismEmissionSplit(uint16)")] + #[precompile::view] + fn get_mechanism_emission_split( + handle: &mut impl PrecompileHandle, + netuid: u16, + ) -> EvmResult<(bool, Vec)> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::MechanismEmissionSplit::::get(NetUid::from(netuid)) { + Some(split) => (true, split), + None => (false, Vec::new()), + }, + ) + } + + #[precompile::public("getBurnConfig(uint16)")] + #[precompile::view] + fn get_burn_config(handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult<(u16, u128)> { + handle.record_db_reads::(2)?; + let netuid = NetUid::from(netuid); + Ok(( + pallet_subtensor::BurnHalfLife::::get(netuid), + pallet_subtensor::BurnIncreaseMult::::get(netuid).to_bits(), + )) + } + + #[precompile::public("getGlobalNetworkLimits()")] + #[precompile::view] + fn get_global_network_limits( + handle: &mut impl PrecompileHandle, + ) -> EvmResult<(u16, u16, u16, u64, u16, u16, u64, u64, u64, u64, u64, u16)> { + handle.record_db_reads::(12)?; + Ok(( + pallet_subtensor::MinActivityCutoff::::get(), + pallet_subtensor::AdminFreezeWindow::::get(), + pallet_subtensor::OwnerHyperparamRateLimit::::get(), + pallet_subtensor::DissolveNetworkScheduleDuration::::get().unique_saturated_into(), + pallet_subtensor::SubnetLimit::::get(), + pallet_subtensor::TotalNetworks::::get(), + pallet_subtensor::NetworkImmunityPeriod::::get(), + pallet_subtensor::StartCallDelay::::get(), + pallet_subtensor::NetworkMinLockCost::::get().to_u64(), + pallet_subtensor::NetworkLastLockCost::::get().to_u64(), + pallet_subtensor::NetworkLockReductionInterval::::get(), + pallet_subtensor::SubnetOwnerCut::::get(), + )) + } + + #[precompile::public("getGlobalRateLimits()")] + #[precompile::view] + fn get_global_rate_limits( + handle: &mut impl PrecompileHandle, + ) -> EvmResult<(u64, u64, u64, u64, u64, u8)> { + handle.record_db_reads::(6)?; + Ok(( + pallet_subtensor::NetworkRateLimit::::get(), + pallet_subtensor::WeightsVersionKeyRateLimit::::get(), + pallet_subtensor::TxRateLimit::::get(), + pallet_subtensor::TxDelegateTakeRateLimit::::get(), + pallet_subtensor::TxChildkeyTakeRateLimit::::get(), + pallet_subtensor::MaxEpochsPerBlock::::get(), + )) + } + + #[precompile::public("getGlobalProtocolConfig()")] + #[precompile::view] + fn get_global_protocol_config( + handle: &mut impl PrecompileHandle, + ) -> EvmResult<(u8, u16, u64, u64)> { + handle.record_db_reads::(4)?; + Ok(( + pallet_subtensor::MaxMechanismCount::::get().into(), + pallet_subtensor::CommitRevealWeightsVersion::::get(), + pallet_subtensor::NetworkRegistrationStartBlock::::get(), + pallet_subtensor::TaoInRefundDeploymentBlock::::get(), + )) + } +} + +fn account_to_h256>(account: AccountId) -> H256 { + H256::from(account.into()) } fn dispatch_admin( @@ -1118,7 +1276,7 @@ where + Send + Sync + scale_info::TypeInfo, - R::AccountId: From<[u8; 32]>, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, ::RuntimeOrigin: AsSystemOriginSigner + Clone, ::RuntimeCall: From> + GetDispatchInfo @@ -1133,6 +1291,38 @@ where handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) } +/// Stable, append-only EVM codes for the runtime's detailed cleanup phases. +/// +/// These values intentionally do not use the Rust enum discriminant. Runtime +/// phases may be reordered internally without changing the Solidity contract. +fn dissolution_cleanup_phase_code(phase: &DissolveCleanupPhase) -> u8 { + match phase { + DissolveCleanupPhase::SubnetRootDividendsRootClaimable => 1, + DissolveCleanupPhase::SubnetRootDividendsRootClaimed => 2, + DissolveCleanupPhase::AlphaInOutStakesGetTotalAlphaValue => 3, + DissolveCleanupPhase::AlphaInOutStakesSettleStakes => 4, + DissolveCleanupPhase::AlphaInOutStakesAlpha => 5, + DissolveCleanupPhase::AlphaInOutStakesHotkeyTotals => 6, + DissolveCleanupPhase::AlphaInOutStakesLocks => 7, + DissolveCleanupPhase::AlphaInOutStakesDecayingLocks => 8, + DissolveCleanupPhase::AlphaInOutStakes => 9, + DissolveCleanupPhase::ProtocolLiquidity => 10, + DissolveCleanupPhase::PurgeNetuid => 11, + DissolveCleanupPhase::NetworkIsNetworkMember => 12, + DissolveCleanupPhase::NetworkParameters => 13, + DissolveCleanupPhase::NetworkMapParameters => 14, + DissolveCleanupPhase::NetworkUpdateWeightsOnRoot => 15, + DissolveCleanupPhase::NetworkChildkeyTake => 16, + DissolveCleanupPhase::NetworkChildkeys => 17, + DissolveCleanupPhase::NetworkParentkeys => 18, + DissolveCleanupPhase::NetworkLastHotkeyEmissionOnNetuid => 19, + DissolveCleanupPhase::NetworkTotalHotkeyAlphaLastEpoch => 20, + DissolveCleanupPhase::NetworkTransactionKeyLastBlock => 21, + DissolveCleanupPhase::NetworkLock => 22, + DissolveCleanupPhase::NetworkDecayingLock => 23, + } +} + #[cfg(test)] mod tests { #![allow( @@ -1691,6 +1881,42 @@ mod tests { }); } + #[test] + fn subnet_precompile_gets_registered_subnet_counter() { + new_test_ext().execute_with(|| { + let caller = addr_from_index(0x5003); + let netuid = setup_owner_subnet(caller); + let precompiles = precompiles::>(); + let precompile_addr = addr_from_index(SubnetPrecompile::::INDEX); + + pallet_subtensor::RegisteredSubnetCounter::::insert(netuid, 7); + + assert_static_call( + &precompiles, + caller, + precompile_addr, + encode_with_selector( + selector_u32("getRegisteredSubnetCounter(uint16)"), + (TEST_NETUID_U16,), + ), + U256::from(7_u64), + ); + + pallet_subtensor::RegisteredSubnetCounter::::remove(netuid); + + assert_static_call( + &precompiles, + caller, + precompile_addr, + encode_with_selector( + selector_u32("getRegisteredSubnetCounter(uint16)"), + (TEST_NETUID_U16,), + ), + U256::zero(), + ); + }); + } + #[test] fn subnet_precompile_is_subnet_dissolving() { new_test_ext().execute_with(|| { @@ -1725,6 +1951,215 @@ mod tests { }); } + #[test] + fn subnet_precompile_reports_stable_dissolution_cleanup_status() { + new_test_ext().execute_with(|| { + let caller = addr_from_index(0x5003); + let netuid = setup_owner_subnet(caller); + let precompiles = precompiles::>(); + let precompile_addr = addr_from_index(SubnetPrecompile::::INDEX); + let input = || { + encode_with_selector( + selector_u32("getSubnetDissolutionStatus(uint16)"), + (TEST_NETUID_U16,), + ) + }; + + precompiles + .prepare_test(caller, precompile_addr, input()) + .with_static_call(true) + .execute_returns((false, false, 0_u8)); + + pallet_subtensor::DissolveCleanupQueue::::set(vec![netuid]); + + precompiles + .prepare_test(caller, precompile_addr, input()) + .with_static_call(true) + .execute_returns((true, false, 0_u8)); + + let mut status = + pallet_subtensor::subnets::dissolution::DissolveCleanupStatus::new(netuid); + status.set_phase(DissolveCleanupPhase::AlphaInOutStakesSettleStakes); + pallet_subtensor::CurrentDissolveCleanupStatus::::set(Some(status)); + + precompiles + .prepare_test(caller, precompile_addr, input()) + .with_static_call(true) + .execute_returns((true, true, 4_u8)); + }); + } + + #[test] + fn dissolution_cleanup_phase_codes_are_stable() { + let phases = [ + (DissolveCleanupPhase::SubnetRootDividendsRootClaimable, 1), + (DissolveCleanupPhase::SubnetRootDividendsRootClaimed, 2), + (DissolveCleanupPhase::AlphaInOutStakesGetTotalAlphaValue, 3), + (DissolveCleanupPhase::AlphaInOutStakesSettleStakes, 4), + (DissolveCleanupPhase::AlphaInOutStakesAlpha, 5), + (DissolveCleanupPhase::AlphaInOutStakesHotkeyTotals, 6), + (DissolveCleanupPhase::AlphaInOutStakesLocks, 7), + (DissolveCleanupPhase::AlphaInOutStakesDecayingLocks, 8), + (DissolveCleanupPhase::AlphaInOutStakes, 9), + (DissolveCleanupPhase::ProtocolLiquidity, 10), + (DissolveCleanupPhase::PurgeNetuid, 11), + (DissolveCleanupPhase::NetworkIsNetworkMember, 12), + (DissolveCleanupPhase::NetworkParameters, 13), + (DissolveCleanupPhase::NetworkMapParameters, 14), + (DissolveCleanupPhase::NetworkUpdateWeightsOnRoot, 15), + (DissolveCleanupPhase::NetworkChildkeyTake, 16), + (DissolveCleanupPhase::NetworkChildkeys, 17), + (DissolveCleanupPhase::NetworkParentkeys, 18), + (DissolveCleanupPhase::NetworkLastHotkeyEmissionOnNetuid, 19), + (DissolveCleanupPhase::NetworkTotalHotkeyAlphaLastEpoch, 20), + (DissolveCleanupPhase::NetworkTransactionKeyLastBlock, 21), + (DissolveCleanupPhase::NetworkLock, 22), + (DissolveCleanupPhase::NetworkDecayingLock, 23), + ]; + + for (phase, expected) in phases { + assert_eq!(dissolution_cleanup_phase_code(&phase), expected); + } + } + + #[test] + fn subnet_state_views_return_grouped_runtime_configuration() { + new_test_ext().execute_with(|| { + let caller = addr_from_index(0x5020); + let netuid = setup_owner_subnet(caller); + let address = addr_from_index(SubnetPrecompile::::INDEX); + let precompiles = precompiles::>(); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getSubnetMetadata(uint16)"), + (TEST_NETUID_U16,), + ), + ) + .with_static_call(true) + .execute_returns(( + UnboundedBytes::from(pallet_subtensor::TokenSymbol::::get(netuid)), + account_to_h256(pallet_subtensor::SubnetOwner::::get(netuid)), + account_to_h256(pallet_subtensor::SubnetOwnerHotkey::::get(netuid)), + pallet_subtensor::Tempo::::get(netuid), + 0_u8, + )); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getSubnetCapacityConfig(uint16)"), + (TEST_NETUID_U16,), + ), + ) + .with_static_call(true) + .execute_returns(( + pallet_subtensor::MinAllowedUids::::get(netuid), + pallet_subtensor::MaxAllowedUids::::get(netuid), + pallet_subtensor::MaxAllowedValidators::::get(netuid), + pallet_subtensor::AdjustmentInterval::::get(netuid), + pallet_subtensor::TargetRegistrationsPerInterval::::get(netuid), + pallet_subtensor::MinNonImmuneUids::::get(netuid), + pallet_subtensor::ImmuneOwnerUidsLimit::::get(netuid), + pallet_subtensor::BondsPenalty::::get(netuid), + pallet_subtensor::OwnerCutEnabled::::get(netuid), + pallet_subtensor::TransferToggle::::get(netuid), + pallet_subtensor::MaxRegistrationsPerBlock::::get(netuid), + u8::from(pallet_subtensor::MechanismCountCurrent::::get( + netuid, + )), + )); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector( + selector_u32("getMechanismEmissionSplit(uint16)"), + (TEST_NETUID_U16,), + ), + ) + .with_static_call(true) + .execute_returns((false, Vec::::new())); + + precompiles + .prepare_test( + caller, + address, + encode_with_selector(selector_u32("getBurnConfig(uint16)"), (TEST_NETUID_U16,)), + ) + .with_static_call(true) + .execute_returns(( + pallet_subtensor::BurnHalfLife::::get(netuid), + pallet_subtensor::BurnIncreaseMult::::get(netuid).to_bits(), + )); + + let dissolve_schedule_duration: u64 = + pallet_subtensor::DissolveNetworkScheduleDuration::::get() + .unique_saturated_into(); + precompiles + .prepare_test( + caller, + address, + selector_u32("getGlobalNetworkLimits()") + .to_be_bytes() + .to_vec(), + ) + .with_static_call(true) + .execute_returns(( + pallet_subtensor::MinActivityCutoff::::get(), + pallet_subtensor::AdminFreezeWindow::::get(), + pallet_subtensor::OwnerHyperparamRateLimit::::get(), + dissolve_schedule_duration, + pallet_subtensor::SubnetLimit::::get(), + pallet_subtensor::TotalNetworks::::get(), + pallet_subtensor::NetworkImmunityPeriod::::get(), + pallet_subtensor::StartCallDelay::::get(), + pallet_subtensor::NetworkMinLockCost::::get().to_u64(), + pallet_subtensor::NetworkLastLockCost::::get().to_u64(), + pallet_subtensor::NetworkLockReductionInterval::::get(), + pallet_subtensor::SubnetOwnerCut::::get(), + )); + + precompiles + .prepare_test( + caller, + address, + selector_u32("getGlobalRateLimits()").to_be_bytes().to_vec(), + ) + .with_static_call(true) + .execute_returns(( + pallet_subtensor::NetworkRateLimit::::get(), + pallet_subtensor::WeightsVersionKeyRateLimit::::get(), + pallet_subtensor::TxRateLimit::::get(), + pallet_subtensor::TxDelegateTakeRateLimit::::get(), + pallet_subtensor::TxChildkeyTakeRateLimit::::get(), + pallet_subtensor::MaxEpochsPerBlock::::get(), + )); + + precompiles + .prepare_test( + caller, + address, + selector_u32("getGlobalProtocolConfig()") + .to_be_bytes() + .to_vec(), + ) + .with_static_call(true) + .execute_returns(( + u8::from(pallet_subtensor::MaxMechanismCount::::get()), + pallet_subtensor::CommitRevealWeightsVersion::::get(), + pallet_subtensor::NetworkRegistrationStartBlock::::get(), + pallet_subtensor::TaoInRefundDeploymentBlock::::get(), + )); + }); + } + #[test] fn added_admin_call_preserves_subnet_owner_authorization() { new_test_ext().execute_with(|| { diff --git a/precompiles/src/uid_lookup.rs b/precompiles/src/uid_lookup.rs index 9846eb0463..4291a8189c 100644 --- a/precompiles/src/uid_lookup.rs +++ b/precompiles/src/uid_lookup.rs @@ -5,6 +5,7 @@ use pallet_evm::PrecompileHandle; use precompile_utils::{EvmResult, prelude::Address}; use sp_runtime::traits::{Dispatchable, StaticLookup}; use sp_std::vec::Vec; +use subtensor_runtime_common::NetUid; use crate::{PrecompileExt, PrecompileHandleExt}; @@ -51,6 +52,22 @@ where limit, )) } + + #[precompile::public("getAssociatedEvmAddress(uint16,uint16)")] + #[precompile::view] + fn get_associated_evm_address( + handle: &mut impl PrecompileHandle, + netuid: u16, + uid: u16, + ) -> EvmResult<(bool, Address, u64)> { + handle.record_db_reads::(1)?; + Ok( + match pallet_subtensor::AssociatedEvmAddress::::get(NetUid::from(netuid), uid) { + Some((address, block)) => (true, Address(address), block), + None => (false, Address::default(), 0), + }, + ) + } } #[cfg(test)] @@ -102,6 +119,32 @@ mod tests { .with_static_call(true) .expect_cost(RuntimeHelper::::db_read_gas_cost()) .execute_returns_raw(encode_return_value(expected)); + + precompiles + .prepare_test( + caller, + precompile_addr, + encode_with_selector( + selector_u32("getAssociatedEvmAddress(uint16,uint16)"), + (TEST_NETUID_U16, uid), + ), + ) + .with_static_call(true) + .expect_cost(RuntimeHelper::::db_read_gas_cost()) + .execute_returns((true, Address(evm_address), block_associated)); + + precompiles + .prepare_test( + caller, + precompile_addr, + encode_with_selector( + selector_u32("getAssociatedEvmAddress(uint16,uint16)"), + (TEST_NETUID_U16, uid + 1), + ), + ) + .with_static_call(true) + .expect_cost(RuntimeHelper::::db_read_gas_cost()) + .execute_returns((false, Address::default(), 0_u64)); }); } } diff --git a/precompiles/src/voting_power.rs b/precompiles/src/voting_power.rs index f44f626b2d..4c08c3f7a3 100644 --- a/precompiles/src/voting_power.rs +++ b/precompiles/src/voting_power.rs @@ -172,14 +172,10 @@ where #[precompile::public("getTotalVotingPower(uint16)")] #[precompile::view] fn get_total_voting_power(handle: &mut impl PrecompileHandle, netuid: u16) -> EvmResult { - let mut total: u64 = 0; - for (_, voting_power) in - pallet_subtensor::VotingPower::::iter_prefix(NetUid::from(netuid)) - { - handle.record_db_reads::(1)?; - total = total.saturating_add(voting_power); - } - Ok(U256::from(total)) + handle.record_db_reads::(1)?; + Ok(U256::from(pallet_subtensor::TotalVotingPower::::get( + NetUid::from(netuid), + ))) } #[precompile::public("enableVotingPowerTracking(uint16)")] @@ -311,6 +307,7 @@ mod tests { pallet_subtensor::VotingPowerTrackingEnabled::::insert(netuid, true); pallet_subtensor::VotingPower::::insert(netuid, &first_hotkey, 123_u64); pallet_subtensor::VotingPower::::insert(netuid, &second_hotkey, 456_u64); + pallet_subtensor::TotalVotingPower::::insert(netuid, 579_u64); assert_voting_power_call( caller, diff --git a/sdk/python/bittensor/evm/abi/alpha.json b/sdk/python/bittensor/evm/abi/alpha.json index b3ce52f2dc..aa37571e54 100644 --- a/sdk/python/bittensor/evm/abi/alpha.json +++ b/sdk/python/bittensor/evm/abi/alpha.json @@ -380,5 +380,273 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getEmissionAccounting", + "outputs": [ + { + "internalType": "uint64", + "name": "alphaDividends", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rootAlphaDividends", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastHotkeyEmission", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "pendingServerEmission", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "pendingValidatorEmission", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "pendingRootAlphaDividends", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "pendingOwnerCut", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "minerBurned", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "raoRecycledForRegistration", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getEmissionGateConfig", + "outputs": [ + { + "internalType": "uint64", + "name": "blockEmission", + "type": "uint64" + }, + { + "internalType": "int128", + "name": "movingAlpha", + "type": "int128" + }, + { + "internalType": "bool", + "name": "netTaoFlowEnabled", + "type": "bool" + }, + { + "internalType": "int128", + "name": "taoFlowCutoff", + "type": "int128" + }, + { + "internalType": "uint128", + "name": "flowNormExponent", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "emissionBarQuantile", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "emissionGateExponent", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "emissionGateBar", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "flowEmaSmoothingFactor", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetEconomicState", + "outputs": [ + { + "internalType": "bool", + "name": "emissionEnabled", + "type": "bool" + }, + { + "internalType": "uint128", + "name": "rootProportion", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "excessTao", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rootSellTao", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "protocolAlpha", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetFlowState", + "outputs": [ + { + "internalType": "int64", + "name": "taoFlow", + "type": "int64" + }, + { + "internalType": "bool", + "name": "hasTaoFlowEma", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "taoFlowEmaBlock", + "type": "uint64" + }, + { + "internalType": "int128", + "name": "taoFlowEma", + "type": "int128" + }, + { + "internalType": "int64", + "name": "protocolFlow", + "type": "int64" + }, + { + "internalType": "bool", + "name": "hasProtocolFlowEma", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "protocolFlowEmaBlock", + "type": "uint64" + }, + { + "internalType": "int128", + "name": "protocolFlowEma", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSwapState", + "outputs": [ + { + "internalType": "uint16", + "name": "feeRate", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "quoteWeight", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "taoReservoir", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "alphaReservoir", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "migrationName", + "type": "bytes" + } + ], + "name": "hasSwapMigrationRun", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/balance.json b/sdk/python/bittensor/evm/abi/balance.json index 9a625eafb7..52c19b6eb6 100644 --- a/sdk/python/bittensor/evm/abi/balance.json +++ b/sdk/python/bittensor/evm/abi/balance.json @@ -48,5 +48,18 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [], + "name": "getTotalIssuance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/leasing.json b/sdk/python/bittensor/evm/abi/leasing.json index c4bdca22e0..541ad0cedf 100644 --- a/sdk/python/bittensor/evm/abi/leasing.json +++ b/sdk/python/bittensor/evm/abi/leasing.json @@ -181,5 +181,37 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "uint32", + "name": "leaseId", + "type": "uint32" + } + ], + "name": "getAccumulatedLeaseDividends", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextLeaseId", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/neuron.json b/sdk/python/bittensor/evm/abi/neuron.json index 88d3a530b2..a8639ab2ce 100644 --- a/sdk/python/bittensor/evm/abi/neuron.json +++ b/sdk/python/bittensor/evm/abi/neuron.json @@ -778,5 +778,683 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getBlockAtRegistration", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getBonds", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "value", + "type": "uint16" + } + ], + "internalType": "struct INeuron.WeightPair[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getChainIdentity", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "url", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "githubRepo", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "image", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "discord", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "description", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "additional", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getLegacyTimelockedWeightCommit", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "ciphertextHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "ciphertextLength", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "getLegacyTimelockedWeightCommitCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getLegacyTransactionRateBlocks", + "outputs": [ + { + "internalType": "uint64", + "name": "lastTransactionBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastChildkeyTakeBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastDelegateTakeBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getLoadedEmission", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "serverEmission", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "validatorEmission", + "type": "uint64" + } + ], + "internalType": "struct INeuron.LoadedEmission[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getNeuronCertificate", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "algorithm", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getPrometheus", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "ip", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "port", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "ipType", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetIdentity", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "subnetName", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "githubRepo", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "subnetContact", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "subnetUrl", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "discord", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "description", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "logoUrl", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "additional", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getTimelockedWeightCommit", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "ciphertextHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "ciphertextLength", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "revealRound", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + } + ], + "name": "getTimelockedWeightCommitCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transactionKey", + "type": "uint16" + } + ], + "name": "getTransactionKeyLastBlock", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getUid", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "getWeightCommit", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "epoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getWeightCommitCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getWeights", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "value", + "type": "uint16" + } + ], + "internalType": "struct INeuron.WeightPair[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "isNetworkMember", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/proxy.json b/sdk/python/bittensor/evm/abi/proxy.json index ed10b00c9b..cb7644a637 100644 --- a/sdk/python/bittensor/evm/abi/proxy.json +++ b/sdk/python/bittensor/evm/abi/proxy.json @@ -245,5 +245,128 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "name": "getAnnouncements", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "internalType": "struct IProxy.AnnouncementInfo[]", + "name": "", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "deposit", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "name": "getLastCallResult", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bool", + "name": "succeeded", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "errorKind", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "palletIndex", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "errorData", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "name": "getProxyDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "real", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "delegate", + "type": "bytes32" + } + ], + "name": "isRealPaysFee", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/stakingV2.json b/sdk/python/bittensor/evm/abi/stakingV2.json index f0b7177168..61a7310a82 100644 --- a/sdk/python/bittensor/evm/abi/stakingV2.json +++ b/sdk/python/bittensor/evm/abi/stakingV2.json @@ -1244,5 +1244,629 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAutoStakeDestination", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getAutoStakeDestinationColdkeys", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "parent", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getChildKeys", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proportion", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "internalType": "struct IStaking.KeyLink[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getChildkeyTake", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getColdkeyCollateral", + "outputs": [ + { + "internalType": "uint64", + "name": "locked", + "type": "uint64" + }, + { + "internalType": "bytes32[]", + "name": "hotkeys", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getColdkeyRoot", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getColdkeySuccessor", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "successor", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getColdkeySwapDelays", + "outputs": [ + { + "internalType": "uint64", + "name": "announcementDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "reannouncementDelay", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getColdkeySwapStatus", + "outputs": [ + { + "internalType": "bool", + "name": "hasAnnouncement", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "announcementBlock", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "callHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "hasDispute", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "disputeBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getCollateralConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "lockShare", + "type": "uint16" + }, + { + "internalType": "uint128", + "name": "drainRatio", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getDelegate", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "take", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + } + ], + "name": "getHotkeyOwner", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "owner", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getHotkeyRoot", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getHotkeySuccessor", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "successor", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getLastHotkeySwapOnSubnet", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMinChildkeyTakePerSubnet", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "hotkey", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getMinerCollateral", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "locked", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "drainRatio", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "minLocked", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "earned", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + } + ], + "name": "getOwnedHotkeys", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "child", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getParentKeys", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proportion", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "internalType": "struct IStaking.KeyLink[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPendingChildKeyCooldown", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "parent", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getPendingChildKeys", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "proportion", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "account", + "type": "bytes32" + } + ], + "internalType": "struct IStaking.KeyLink[]", + "name": "children", + "type": "tuple[]" + }, + { + "internalType": "uint64", + "name": "cooldownBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStakeAccounting", + "outputs": [ + { + "internalType": "uint64", + "name": "totalIssuance", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "totalStake", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTakeLimits", + "outputs": [ + { + "internalType": "uint16", + "name": "minDelegateTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxDelegateTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "minChildkeyTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxChildkeyTake", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/sdk/python/bittensor/evm/abi/subnet.json b/sdk/python/bittensor/evm/abi/subnet.json index 7e5046d854..a21dbd1c2e 100644 --- a/sdk/python/bittensor/evm/abi/subnet.json +++ b/sdk/python/bittensor/evm/abi/subnet.json @@ -1428,5 +1428,348 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, +{ + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getBurnConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "halfLife", + "type": "uint16" + }, + { + "internalType": "uint128", + "name": "increaseMultiplier", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalNetworkLimits", + "outputs": [ + { + "internalType": "uint16", + "name": "minActivityCutoff", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "adminFreezeWindow", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "ownerHyperparamRateLimit", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "dissolveScheduleDuration", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "subnetLimit", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "totalNetworks", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "networkImmunityPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "startCallDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minNetworkLockCost", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastNetworkLockCost", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "networkLockReductionInterval", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "subnetOwnerCut", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalProtocolConfig", + "outputs": [ + { + "internalType": "uint8", + "name": "maxMechanismCount", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "commitRevealWeightsVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "networkRegistrationStartBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "taoInRefundDeploymentBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalRateLimits", + "outputs": [ + { + "internalType": "uint64", + "name": "networkRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "weightsVersionKeyRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "transactionRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "delegateTakeRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "childkeyTakeRateLimit", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "maxEpochsPerBlock", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getMechanismEmissionSplit", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint16[]", + "name": "split", + "type": "uint16[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetCapacityConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "minAllowedUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxAllowedUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxAllowedValidators", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "adjustmentInterval", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "targetRegistrationsPerInterval", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "minNonImmuneUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "immuneOwnerUidsLimit", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "bondsPenalty", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "ownerCutEnabled", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transfersEnabled", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "maxRegistrationsPerBlock", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "mechanismCount", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetMetadata", + "outputs": [ + { + "internalType": "bytes", + "name": "tokenSymbol", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "owner", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "ownerHotkey", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "tempo", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "recycleOrBurn", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getRegisteredSubnetCounter", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + } + ], + "name": "getSubnetDissolutionStatus", + "outputs": [ + { + "internalType": "bool", + "name": "isDissolving", + "type": "bool" + }, + { + "internalType": "bool", + "name": "cleanupInProgress", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "cleanupPhase", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" } -] \ No newline at end of file +] diff --git a/sdk/python/bittensor/evm/abi/uidLookup.json b/sdk/python/bittensor/evm/abi/uidLookup.json index 558358dcaa..dfe4f8ebfc 100644 --- a/sdk/python/bittensor/evm/abi/uidLookup.json +++ b/sdk/python/bittensor/evm/abi/uidLookup.json @@ -39,5 +39,39 @@ ], "stateMutability": "view", "type": "function" - } + }, +{ + "inputs": [ + { + "internalType": "uint16", + "name": "netuid", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "uid", + "type": "uint16" + } + ], + "name": "getAssociatedEvmAddress", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "address", + "name": "evmAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "blockAssociated", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } ] \ No newline at end of file From 7f9ae800f9cfdcbcb16e4fc63eb67cbd1452a2fa Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Fri, 31 Jul 2026 11:06:19 -0400 Subject: [PATCH 19/58] Fix typo in path --- .agents/skills/{emv-maintainer => evm-maintainer}/SKILL.md | 0 .../references/abi-versioning.md | 0 .../references/coverage-and-testing.md | 0 .../{emv-maintainer => evm-maintainer}/references/exceptions.md | 0 .../references/state-exposure.md | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename .agents/skills/{emv-maintainer => evm-maintainer}/SKILL.md (100%) rename .agents/skills/{emv-maintainer => evm-maintainer}/references/abi-versioning.md (100%) rename .agents/skills/{emv-maintainer => evm-maintainer}/references/coverage-and-testing.md (100%) rename .agents/skills/{emv-maintainer => evm-maintainer}/references/exceptions.md (100%) rename .agents/skills/{emv-maintainer => evm-maintainer}/references/state-exposure.md (100%) diff --git a/.agents/skills/emv-maintainer/SKILL.md b/.agents/skills/evm-maintainer/SKILL.md similarity index 100% rename from .agents/skills/emv-maintainer/SKILL.md rename to .agents/skills/evm-maintainer/SKILL.md diff --git a/.agents/skills/emv-maintainer/references/abi-versioning.md b/.agents/skills/evm-maintainer/references/abi-versioning.md similarity index 100% rename from .agents/skills/emv-maintainer/references/abi-versioning.md rename to .agents/skills/evm-maintainer/references/abi-versioning.md diff --git a/.agents/skills/emv-maintainer/references/coverage-and-testing.md b/.agents/skills/evm-maintainer/references/coverage-and-testing.md similarity index 100% rename from .agents/skills/emv-maintainer/references/coverage-and-testing.md rename to .agents/skills/evm-maintainer/references/coverage-and-testing.md diff --git a/.agents/skills/emv-maintainer/references/exceptions.md b/.agents/skills/evm-maintainer/references/exceptions.md similarity index 100% rename from .agents/skills/emv-maintainer/references/exceptions.md rename to .agents/skills/evm-maintainer/references/exceptions.md diff --git a/.agents/skills/emv-maintainer/references/state-exposure.md b/.agents/skills/evm-maintainer/references/state-exposure.md similarity index 100% rename from .agents/skills/emv-maintainer/references/state-exposure.md rename to .agents/skills/evm-maintainer/references/state-exposure.md From 539f5d00b528ff652a43fa3bdf886cf6c5b240cc Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Fri, 31 Jul 2026 13:52:37 -0400 Subject: [PATCH 20/58] Add runtime constants to the precompile requirements --- .agents/skills/evm-maintainer/SKILL.md | 72 +++++++++++++------ .../references/abi-versioning.md | 9 ++- .../references/coverage-and-testing.md | 23 +++++- .../references/state-exposure.md | 30 ++++++-- 4 files changed, 105 insertions(+), 29 deletions(-) diff --git a/.agents/skills/evm-maintainer/SKILL.md b/.agents/skills/evm-maintainer/SKILL.md index f309a52c6d..555222f960 100644 --- a/.agents/skills/evm-maintainer/SKILL.md +++ b/.agents/skills/evm-maintainer/SKILL.md @@ -1,11 +1,16 @@ --- name: evm-maintainer -description: Maintain the EVM precompiles in backwards compatible way with API versioning. +description: Maintain backwards-compatible, versioned EVM precompiles that expose runtime extrinsics, state, constants, and APIs to Solidity. --- # EVM Precompile Maintainer -You are the maintainer of EVM precompiles. EVM precompiles in subtensor should expose the deterministic functionality available to client applications to EVM smart contracts: extrinsics, state maps and variables through typed read-only views, and runtime APIs/RPC results. Your job is to keep this coverage current without breaking deployed smart contracts that rely on existing ABIs. Read the notes below and then execute steps. +You are the maintainer of EVM precompiles. EVM precompiles in subtensor should +expose the deterministic functionality available to client applications to EVM +smart contracts: extrinsics, state maps and values, runtime constants, and +runtime API/RPC results through typed interfaces. Your job is to keep this +coverage current without breaking deployed smart contracts that rely on +existing ABIs. Read the notes below and then execute the workflow. ## Reference routing @@ -14,10 +19,11 @@ You are the maintainer of EVM precompiles. EVM precompiles in subtensor should e read [ABI versioning](references/abi-versioning.md). - Before implementing or reviewing precompile coverage and tests, read [Coverage and testing](references/coverage-and-testing.md). -- Before classifying pallet state or adding, reviewing, or omitting a typed - state view, read [State exposure](references/state-exposure.md) and use its - direct, wrapped, and do-not-expose classifications. Do not override a - classification without an explicit human decision. +- Before classifying pallet state or runtime constants, or adding, reviewing, + or omitting a typed view, read + [State exposure](references/state-exposure.md) and use its direct, wrapped, + and do-not-expose classifications. Do not override a classification without + an explicit human decision. - Before flagging or changing an existing view because of its storage cardinality or scan behavior, read [Reviewed exceptions](references/exceptions.md). Apply an exception only to @@ -34,7 +40,7 @@ Compatibility covers observable behavior, not merely the continued existence of a four-byte selector. Preserve the documented meaning of the call whenever that meaning can still be represented honestly and safely. -For each affected released function: +For each affected released function or view: 1. Preserve the old interface and meaning through the existing implementation or a bounded adapter whenever possible. @@ -56,6 +62,13 @@ For each affected released function: are unchanged by following [Coverage and testing](references/coverage-and-testing.md). +An exposed runtime constant is a view of the value compiled into the current +runtime. Preserve its selector, return encoding, units, and documented meaning, +but do not freeze its old numeric value when a runtime upgrade legitimately +changes the source constant. Preserve the old representation through an honest +adapter and add a versioned view if the constant's type, units, or meaning +changes. + ## Notes on coding precompiles - Keep every precompile path O(1) in CPU and memory unless the exact path is a @@ -81,6 +94,10 @@ For each affected released function: unbounded helper and truncate its result afterward. Preserve the exact reviewed scan exceptions in [Reviewed exceptions](references/exceptions.md). +- Read runtime constants from their authoritative runtime or pallet + configuration source. Never duplicate the literal value in precompile code. + Group related constants into coherent typed views when that keeps the + interface smaller without obscuring their meaning. - Follow [ABI versioning](references/abi-versioning.md) for every released interface. - Treat repository-owned Rust function lifecycle annotations as the source of @@ -100,10 +117,26 @@ For each affected released function: - Multiply Subtensor balances by `10^9` to match EVM's 18-decimal convention, and divide by the same factor before passing balances to Subtensor pallets. -## Step 1 - Review current precompiles vs. subtensor functionality +## Maintenance workflow + +Perform this workflow on: + +- Every change to subtensor Rust codebase +- When explicitly prompted + +## Step 1 — Determine the diff + +Determine the diff between current branch and the most recent main branch (may need to pull it locally if it is outdated). See how this diff affects EVM precompiles: + +- Does it remove or change any functions that precompiles rely on? Does it change function signatures or underlying functionality? +- Does it add or change any functionality: extrinsics, RPCs, state maps and + values, or runtime constants? + +## Step 2 - Review the diff in the context of current precompiles vs. subtensor functionality -- All extrinsics that accept a non-Root signed origin should be exposed to - precompile callers for the following pallets: +- All extrinsics that accept a non-Root signed origin, as well as all state + variables, maps, and constants should be exposed directly or through + type-safe readers to precompile callers for the following pallets: - subtensor - admin-util - balances @@ -124,17 +157,10 @@ For each affected released function: Use [Coverage and testing](references/coverage-and-testing.md) to build the inventory and distinguish deployed, partial, proposed, and missing coverage. Use [State exposure](references/state-exposure.md) to classify every state item -and [Reviewed exceptions](references/exceptions.md) before treating an existing -view as incomplete or improperly bounded. - -## Step 2 — Determine the diff - -Determine the diff between current branch and the most recent main branch (may need to pull it locally if it is outdated). See how this diff affects EVM precompiles: - -- Does it remove or change any functions that precompiles rely on? Does it change function signatures or underlying functionality? -- Does it add any new functionality (extrinsics, RPCs, state maps and variables)? +and runtime constant, and [Reviewed exceptions](references/exceptions.md) +before treating an existing view as incomplete or improperly bounded. -## Step 3 - Handle changed functions +## Step 3 - Handle changed functions, state variables and maps, and constants Apply the backwards-compatibility decision rule above and the detailed [ABI versioning](references/abi-versioning.md) process. Preserve released @@ -143,7 +169,7 @@ behavior. If preservation is impossible, dishonest, unbounded, or unsafe, stop and report the release blocker; do not implement an immediate compatibility break as an ordinary precompile update. -## Step 4 - Handle added functions +## Step 4 - Handle added functions, state variables and maps, and constants Determine the category under which the new functionality needs to be added and add to the corresponding existing precompile. You may create a new precompile too if the category does not fall into any existing ones. @@ -151,4 +177,6 @@ Determine the category under which the new functionality needs to be added and a Update the Solidity interface, generated ABI, NatSpec, registry metadata, SDK copies, and public precompile documentation together. Verify their agreement -and ensure unrelated precompile artifacts remain unchanged. +and ensure unrelated precompile artifacts remain unchanged. Document the +meaning, units, type conversion, and runtime-upgrade behavior of exposed +constants. diff --git a/.agents/skills/evm-maintainer/references/abi-versioning.md b/.agents/skills/evm-maintainer/references/abi-versioning.md index ea753e0216..98a5febd89 100644 --- a/.agents/skills/evm-maintainer/references/abi-versioning.md +++ b/.agents/skills/evm-maintainer/references/abi-versioning.md @@ -25,7 +25,7 @@ Before changing a precompile: documentation, SDK copies, and known integration contracts. 3. Compare the branch with the relevant base and identify every runtime change that affects inputs, outputs, state changes, errors, authorization, units, - value handling, or gas and weight requirements. + value handling, runtime constants, or gas and weight requirements. 4. Treat uncertain production status as released until evidence establishes otherwise. 5. Distinguish released interfaces from explicit proposals. Allow an @@ -44,6 +44,8 @@ Preserve all observable properties of every released call: - function name, input types, input order, and ABI encoding; - return types, tuple and struct field order, and ABI encoding; - documented meaning, units, precision, scaling, rounding, and defaults; +- whether a returned constant means the value compiled into the current + runtime or a value fixed by the released interface; - view, state-changing, payable, and static-call behavior; - treatment of attached EVM value; - caller-to-Substrate account mapping and dispatched origin; @@ -142,6 +144,8 @@ still be produced honestly with bounded, proportionate work: - Update Rust storage access when names, keys, hashers, or map shapes change. - Supply the exact old default when an extrinsic gains an option; expose the option through a new version. +- Follow a renamed or relocated runtime constant to its authoritative source + while preserving the released view's meaning, type, and units. - Derive the documented old result when the runtime replaces its computation. - Preserve legacy units, precision, scaling, and rounding in the old function; expose a corrected convention through a new version. @@ -160,6 +164,9 @@ make an explicit lifecycle decision. | Input or return type/order change | Add a version with a new selector. | | One concept splits into several | Reconstruct the old aggregate when honest; expose components through a version. | | Extrinsic gains an option | Preserve the old default; expose the option through a version. | +| Runtime constant is added | Add a typed view in the appropriate domain. | +| Current-runtime constant value changes | Keep the existing selector returning the new authoritative value when that is its documented meaning. | +| Runtime constant type, units, or meaning changes | Preserve the old representation through an honest adapter or add a versioned view. | | Entirely new operation or view | Add a selector to the appropriate domain. | | Concept disappears without an honest representation | Reserve the selector and evaluate hard deprecation. | | Bug fix changes observable semantics | Preserve the released behavior and add a corrected version unless retaining it is unsafe. | diff --git a/.agents/skills/evm-maintainer/references/coverage-and-testing.md b/.agents/skills/evm-maintainer/references/coverage-and-testing.md index b60feadb2d..83cab27509 100644 --- a/.agents/skills/evm-maintainer/references/coverage-and-testing.md +++ b/.agents/skills/evm-maintainer/references/coverage-and-testing.md @@ -6,6 +6,7 @@ - [Build a coverage inventory](#build-a-coverage-inventory) - [Cover extrinsics](#cover-extrinsics) - [Cover state with typed views](#cover-state-with-typed-views) +- [Cover runtime constants](#cover-runtime-constants) - [Cover runtime APIs and public RPCs](#cover-runtime-apis-and-public-rpcs) - [Add regression tests first](#add-regression-tests-first) - [Test observable behavior](#test-observable-behavior) @@ -23,6 +24,7 @@ For each in-scope pallet, inspect: - every dispatchable extrinsic; - every public state map and value; +- every public runtime constant; - every publicly facing runtime API and RPC; - changes to types, guards, authorization, units, and error behavior used by existing precompiles. @@ -40,7 +42,7 @@ Create or update a working matrix with one row per source item: | Source | Kind | Public functionality | Precompile domain | Function | Status | Evidence | |---|---|---|---|---|---|---| -| Pallet and item | Extrinsic, state, runtime API, or RPC | Meaning exposed to clients | Existing or proposed address/domain | Canonical signature | Covered, partial, missing, or excluded | Rust, Solidity, ABI, and test paths | +| Pallet and item | Extrinsic, state, constant, runtime API, or RPC | Meaning exposed to clients | Existing or proposed address/domain | Canonical signature | Covered, partial, missing, or excluded | Rust, Solidity, ABI, and test paths | For every partial, missing, or excluded row, state the exact reason. Do not equate a similarly named function with coverage; compare parameters, returned @@ -115,6 +117,23 @@ For every view, specify and test: When storage changes internally, update the Rust adapter and prove that released calldata still returns the released meaning. +## Cover runtime constants + +Inventory every public runtime constant in the in-scope pallet configuration +and expose its meaningful value through a typed view. Read the authoritative +`Get::get()`, associated constant, or equivalent runtime source; never repeat +its literal value in precompile code. + +Group related constants by contract use case when appropriate. Preserve each +constant's meaning, units, signedness, width, and overflow behavior. A constant +may change when a new runtime is compiled: when a released view promises the +current runtime value, test and document that behavior instead of treating the +old numeric value as ABI state. + +Do not expose generated weights, compiler/build constants, or private +implementation limits unless they are part of the pallet's deterministic +client-facing contract. + ## Cover runtime APIs and public RPCs Inventory the publicly facing runtime APIs and RPCs in scope, including the @@ -176,6 +195,7 @@ Cover every affected path: - account and address conversion; - TAO and Alpha unit conversion; - precision, rounding, overflow, and narrowing; +- runtime-constant source values, units, and conversion boundaries; - bounded collections and duplicate inputs; - lifecycle status, hard-deprecation error, and disable/re-enable behavior when applicable; and @@ -269,6 +289,7 @@ run and the specific reason; do not imply success from an unexecuted check. Summarize: - source functionality added, changed, or still missing; +- runtime constants added, changed, or still missing; - released addresses and selectors affected; - adapters or new versions introduced; - lifecycle or mainnet-release warnings; diff --git a/.agents/skills/evm-maintainer/references/state-exposure.md b/.agents/skills/evm-maintainer/references/state-exposure.md index f64e63ec46..a6146e2efc 100644 --- a/.agents/skills/evm-maintainer/references/state-exposure.md +++ b/.agents/skills/evm-maintainer/references/state-exposure.md @@ -1,14 +1,34 @@ -# Rules of exposing the state variables and maps +# Rules for exposing state and runtime constants -This file lists concrete state variables and maps and classifies them as one of three classes: +This file lists concrete state variables, maps, and runtime constants and +classifies them as one of three classes: 1. Safe to expose directly, as is, or 2. Need some type-safe wrapping, or 3. Internal, do not need to be exposed, or already known to be deprecated soon -The class 1 state variables and maps are not anticipated to change anytime soon or change significantly. Also, even if they do, it is expected that their exposed values can be easily simulated or recalculated with no greater than O(1) complexity. +The class 1 items are not anticipated to change significantly. Even if they do, +their exposed values should remain honestly reproducible with no greater than +O(1) complexity. -The class 2 state variables and maps are not expected to stay for a long time, are temporary, or express complex formulas and need to be safely wrapped. +The class 2 items are temporary, use unstable internal representations, or +express complex formulas and need to be safely wrapped. + +## Runtime constants + +Inventory every public runtime constant declared by or supplied to the +configuration of an in-scope pallet. Expose it directly or through a coherent +typed grouped view, reading the authoritative runtime source rather than +copying its literal value into the precompile. + +Preserve semantic types and units when converting Rust values to Solidity. +Treat fixed-point values, balances, block numbers, bounded sizes, and other +representation-specific constants as type-safe wrapping cases when their Rust +representation is not a suitable permanent ABI. + +This requirement covers deterministic client-facing runtime configuration. It +does not cover generated weights, compiler/build constants, or private +implementation details that are not part of the pallet's public behavior. ## Safe to expose directly @@ -58,4 +78,4 @@ InactiveIssuance, the reserved, frozen, and flags portions of Account: Locks, Re ### Pallet swap -ScrapReservoirAlpha \ No newline at end of file +ScrapReservoirAlpha From 8041d88615005eb9fb664a87aea4131af6543fb8 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Fri, 31 Jul 2026 16:04:53 -0400 Subject: [PATCH 21/58] Add runtime constants --- .../evm/precompiles/runtime-configuration.mdx | 34 +- precompiles/src/lib.rs | 34 +- precompiles/src/runtime_configuration.rs | 715 ++++++++++++++- .../src/solidity/runtimeConfiguration.abi | 811 +++++++++++++++++- .../src/solidity/runtimeConfiguration.sol | 162 ++++ .../evm/abi/runtimeConfiguration.json | 811 +++++++++++++++++- 6 files changed, 2503 insertions(+), 64 deletions(-) diff --git a/docs/guides/evm/precompiles/runtime-configuration.mdx b/docs/guides/evm/precompiles/runtime-configuration.mdx index 1bf2650600..5817de694e 100644 --- a/docs/guides/evm/precompiles/runtime-configuration.mdx +++ b/docs/guides/evm/precompiles/runtime-configuration.mdx @@ -10,9 +10,9 @@ description: Typed EVM views for global runtime configuration. | Address | `0x0000000000000000000000000000000000000812` | | Status | Deployed | -This domain contains bounded typed views of global runtime -configuration that do not belong to subnet, staking, Alpha, account-balance, -or precompile-lifecycle domains. +This domain contains bounded typed views of runtime configuration. The grouped +constant views read their values from the runtime and therefore reflect the +runtime version executing the call. ## Views @@ -20,6 +20,34 @@ or precompile-lifecycle domains. |---|---| | `getEvmChainId()` | Current EVM chain identifier | | `getTransactionRateLimit()` | Global Subtensor transaction rate limit | +| `getSubtensorEconomicConstants()` | Initial issuance, burn, stake, transfer, registration-lock, and key-swap balance constants | +| `getSubtensorSubnetConstants()` | Subnet size, tempo, immunity, activity, owner-cut, and epoch limits | +| `getSubtensorConsensusConstants()` | Initial weight, emission, Yuma, bonds, pruning, and TAO-weight configuration | +| `getSubtensorRegistrationConstants()` | Registration difficulty, adjustment, rate-limit, immunity, lock-reduction, and price-EMA configuration | +| `getSubtensorDelegationConstants()` | Initial delegate and childkey takes plus Liquid Alpha and Yuma feature defaults | +| `getSubtensorRateLimitConstants()` | Transaction, serving, EVM-association, swap, dissolution, start-call, and lease timing constants | +| `getSubtensorProtocolConstants()` | Fixed public protocol bounds, flags, voting-power timing, lock timing, and maximum TAO issuance | +| `getSubtensorSystemAccounts()` | Derived Subtensor pallet and burn accounts as `bytes32` | +| `getBalancesConstants()` | Existential deposit and lock, reserve, and freeze limits | +| `getProxyConstants()` | Proxy and announcement deposits and count limits | +| `getSchedulerConstants()` | Maximum scheduler weight and calls per block | +| `getDrandConstants()` | Quicknet chain hash, unsigned transaction configuration, and pulse-retention limits | +| `getCrowdloanConstants()` | Deposit, contribution, duration, contributor, refund, and pallet-account configuration | +| `getSwapConstants()` | Maximum fee rate, minimum liquidity and reserve, and derived protocol account | +| `getTimestampConstants()` | Minimum timestamp period | +| `getAdminConstants()` | Maximum authority count | + +## Constant representation + +All balance-valued constants are returned as `uint256` values using EVM's +18-decimal convention. Block numbers, durations, percentages, fixed-point +parts, and count limits retain the units stated by their Solidity output +names. `PalletId` configuration is wrapped as the derived 32-byte account that +contracts can use. + +A runtime upgrade may change a constant's returned value. The function +selector, output type and order, units, and documented meaning remain the +compatibility contract. ## State-changing operations diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index ae31b1809d..c67ef77b1a 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -113,6 +113,7 @@ where + IsSubType>, ::AddressMapping: AddressMapping, ::Balance: Into + TryFrom, + runtime_configuration::ProxyBalanceOf: Into, <::Lookup as StaticLookup>::Source: From, { fn default() -> Self { @@ -157,6 +158,7 @@ where + IsSubType>, ::AddressMapping: AddressMapping, ::Balance: Into + TryFrom, + runtime_configuration::ProxyBalanceOf: Into, <::Lookup as StaticLookup>::Source: From, { pub fn new() -> Self { @@ -241,6 +243,7 @@ where From>>, ::AddressMapping: AddressMapping, ::Balance: Into + TryFrom, + runtime_configuration::ProxyBalanceOf: Into, <::Lookup as StaticLookup>::Source: From, { fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { @@ -457,7 +460,36 @@ mod address_and_selector_tests { "missing Timestamp selector {signature}" ); } - for signature in ["getEvmChainId()", "getTransactionRateLimit()"] { + let runtime_configuration_signatures = [ + "getEvmChainId()", + "getTransactionRateLimit()", + "getSubtensorEconomicConstants()", + "getSubtensorSubnetConstants()", + "getSubtensorConsensusConstants()", + "getSubtensorRegistrationConstants()", + "getSubtensorDelegationConstants()", + "getSubtensorRateLimitConstants()", + "getSubtensorProtocolConstants()", + "getSubtensorSystemAccounts()", + "getBalancesConstants()", + "getProxyConstants()", + "getSchedulerConstants()", + "getDrandConstants()", + "getCrowdloanConstants()", + "getSwapConstants()", + "getTimestampConstants()", + "getAdminConstants()", + ]; + assert_eq!( + runtime_configuration_signatures.len(), + runtime_configuration_signatures + .iter() + .map(|signature| selector_u32(signature)) + .collect::>() + .len(), + "runtime-configuration selectors collide" + ); + for signature in runtime_configuration_signatures { assert!( runtime_configuration::RuntimeConfigurationPrecompileCall::::supports_selector( selector_u32(signature) diff --git a/precompiles/src/runtime_configuration.rs b/precompiles/src/runtime_configuration.rs index 72cb9fa9d8..e654266f4e 100644 --- a/precompiles/src/runtime_configuration.rs +++ b/precompiles/src/runtime_configuration.rs @@ -1,19 +1,111 @@ use core::marker::PhantomData; -use pallet_evm::PrecompileHandle; -use precompile_utils::EvmResult; +use fp_evm::ExitError; +use frame_support::traits::{Currency, Get}; +use pallet_evm::{BalanceConverter, PrecompileHandle, SubstrateBalance}; +use precompile_utils::{EvmResult, prelude::UnboundedString}; +use sp_core::{H256, U256}; +use sp_runtime::traits::AccountIdConversion; +use subtensor_runtime_common::{TaoBalance, Token}; use crate::{PrecompileExt, PrecompileHandleExt}; +type SubtensorEconomicConstants = ( + U256, + U256, + U256, + U256, + U256, + U256, + U256, + U256, + U256, + U256, + U256, + U256, + U256, +); +type SubtensorSubnetConstants = ( + u16, + u16, + u16, + u16, + u16, + u16, + u16, + u16, + u32, + u32, + u8, + u16, + u8, +); +type SubtensorConsensusConstants = ( + u16, + u16, + u16, + U256, + u16, + u64, + u16, + bool, + u64, + u16, + u16, + u64, + u64, +); +type SubtensorRegistrationConstants = (u64, u64, u64, u16, u64, u16, u16, u64, u64, u64, u64); +type SubtensorDelegationConstants = (u16, u16, u16, u16, u16, u16, u16, bool, bool); +type SubtensorRateLimitConstants = (u64, u64, u64, u64, u64, u64, u64, u64, u64, u64, u64); +type SubtensorProtocolConstants = ( + u32, + u32, + u32, + u128, + u64, + u64, + u16, + u8, + u64, + u64, + u64, + u64, + U256, + u32, + U256, +); +type BalancesConstants = (U256, u32, u32, u32); +type ProxyConstants = (U256, U256, u32, u32, U256, U256); +type SchedulerConstants = (u64, u64, u32); +type DrandConstants = (UnboundedString, u64, u64, u64, u64, u64); +type CrowdloanConstants = (U256, U256, u64, u64, u32, u32, H256); +type SwapConstants = (u16, U256, U256, H256); +pub(crate) type ProxyBalanceOf = <::Currency as Currency< + ::AccountId, +>>::Balance; + pub struct RuntimeConfigurationPrecompile(PhantomData); impl PrecompileExt for RuntimeConfigurationPrecompile where R: frame_system::Config + + pallet_admin_utils::Config + + pallet_balances::Config + + pallet_crowdloan::Config + + pallet_drand::Config + pallet_evm::Config + pallet_evm_chain_id::Config - + pallet_subtensor::Config, - R::AccountId: From<[u8; 32]>, + + pallet_scheduler::Config + + pallet_subtensor::Config + + pallet_subtensor_proxy::Config + + pallet_subtensor_swap::Config + + pallet_timestamp::Config, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, + frame_system::pallet_prelude::BlockNumberFor: TryInto, + ::Moment: TryInto, + ::Balance: Into, + ProxyBalanceOf: Into, { const INDEX: u64 = 2066; } @@ -22,10 +114,22 @@ where impl RuntimeConfigurationPrecompile where R: frame_system::Config + + pallet_admin_utils::Config + + pallet_balances::Config + + pallet_crowdloan::Config + + pallet_drand::Config + pallet_evm::Config + pallet_evm_chain_id::Config - + pallet_subtensor::Config, - R::AccountId: From<[u8; 32]>, + + pallet_scheduler::Config + + pallet_subtensor::Config + + pallet_subtensor_proxy::Config + + pallet_subtensor_swap::Config + + pallet_timestamp::Config, + R::AccountId: From<[u8; 32]> + Into<[u8; 32]>, + frame_system::pallet_prelude::BlockNumberFor: TryInto, + ::Moment: TryInto, + ::Balance: Into, + ProxyBalanceOf: Into, { #[precompile::public("getEvmChainId()")] #[precompile::view] @@ -40,20 +144,347 @@ where handle.record_db_reads::(1)?; Ok(pallet_subtensor::Pallet::::get_tx_rate_limit()) } + + #[precompile::public("getSubtensorEconomicConstants()")] + #[precompile::view] + fn get_subtensor_economic_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + Ok(( + tao_to_evm::(::InitialIssuance::get())?, + tao_to_evm::( + ::InitialRAORecycledForRegistration::get(), + )?, + tao_to_evm::(::InitialBurn::get())?, + tao_to_evm::(::InitialMinBurn::get())?, + tao_to_evm::(::InitialMaxBurn::get())?, + tao_to_evm::(::InitialMinStake::get())?, + tao_to_evm::(::InitialMinTransfer::get())?, + tao_to_evm::(::MinBurnUpperBound::get())?, + tao_to_evm::(::MaxBurnLowerBound::get())?, + tao_to_evm::(::InitialNetworkMinLockCost::get())?, + tao_to_evm::(::KeySwapCost::get())?, + tao_to_evm::(::KeySwapOnSubnetCost::get())?, + tao_to_evm::(pallet_subtensor::pallet::MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP)?, + )) + } + + #[precompile::public("getSubtensorSubnetConstants()")] + #[precompile::view] + fn get_subtensor_subnet_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + Ok(( + ::InitialTempo::get(), + ::MinTempo::get(), + ::MaxTempo::get(), + ::InitialMinAllowedUids::get(), + ::InitialMaxAllowedUids::get(), + ::InitialMaxAllowedValidators::get(), + ::InitialImmunityPeriod::get(), + ::InitialActivityCutoff::get(), + ::MinActivityCutoffFactorMilli::get(), + ::MaxActivityCutoffFactorMilli::get(), + ::MaxImmuneUidsPercentage::get().deconstruct(), + ::InitialSubnetOwnerCut::get(), + ::InitialMaxEpochsPerBlock::get(), + )) + } + + #[precompile::public("getSubtensorConsensusConstants()")] + #[precompile::view] + fn get_subtensor_consensus_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + Ok(( + ::InitialMinAllowedWeights::get(), + ::InitialEmissionValue::get(), + ::InitialRho::get(), + signed_i16_word(::InitialAlphaSigmoidSteepness::get()), + ::InitialKappa::get(), + ::InitialBondsMovingAverage::get(), + ::InitialBondsPenalty::get(), + ::InitialBondsResetOn::get(), + ::InitialValidatorPruneLen::get(), + ::InitialScalingLawPower::get(), + ::InitialPruningScore::get(), + ::InitialWeightsVersionKey::get(), + ::InitialTaoWeight::get(), + )) + } + + #[precompile::public("getSubtensorRegistrationConstants()")] + #[precompile::view] + fn get_subtensor_registration_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + Ok(( + ::InitialDifficulty::get(), + ::InitialMinDifficulty::get(), + ::InitialMaxDifficulty::get(), + ::InitialAdjustmentInterval::get(), + ::InitialAdjustmentAlpha::get(), + ::InitialMaxRegistrationsPerBlock::get(), + ::InitialTargetRegistrationsPerInterval::get(), + ::InitialNetworkRateLimit::get(), + ::InitialNetworkImmunityPeriod::get(), + ::InitialNetworkLockReductionInterval::get(), + ::InitialEmaPriceHalvingPeriod::get(), + )) + } + + #[precompile::public("getSubtensorDelegationConstants()")] + #[precompile::view] + fn get_subtensor_delegation_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + Ok(( + ::InitialDefaultDelegateTake::get(), + ::InitialMinDelegateTake::get(), + ::InitialDefaultChildKeyTake::get(), + ::InitialMinChildKeyTake::get(), + ::InitialMaxChildKeyTake::get(), + ::AlphaHigh::get(), + ::AlphaLow::get(), + ::LiquidAlphaOn::get(), + ::Yuma3On::get(), + )) + } + + #[precompile::public("getSubtensorRateLimitConstants()")] + #[precompile::view] + fn get_subtensor_rate_limit_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + Ok(( + ::InitialServingRateLimit::get(), + ::InitialTxRateLimit::get(), + ::InitialTxDelegateTakeRateLimit::get(), + ::InitialTxChildKeyTakeRateLimit::get(), + ::EvmKeyAssociateRateLimit::get(), + block_to_u64( + ::InitialColdkeySwapAnnouncementDelay::get(), + )?, + block_to_u64( + ::InitialColdkeySwapReannouncementDelay::get(), + )?, + block_to_u64( + ::InitialDissolveNetworkScheduleDuration::get(), + )?, + ::InitialStartCallDelay::get(), + ::HotkeySwapOnSubnetInterval::get(), + block_to_u64( + ::LeaseDividendsDistributionInterval::get(), + )?, + )) + } + + #[precompile::public("getSubtensorProtocolConstants()")] + #[precompile::view] + fn get_subtensor_protocol_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + Ok(( + pallet_subtensor::MAX_CRV3_COMMIT_SIZE_BYTES, + pallet_subtensor::MAX_ASSOCIATED_UIDS_PER_EVM_ADDRESS, + pallet_subtensor::MAX_COLDKEY_COLLATERAL_HOTKEYS, + pallet_subtensor::ACCOUNT_FLAGS_ACCEPT_LOCKED_ALPHA, + pallet_subtensor::pallet::MIN_COMMIT_REVEAL_PEROIDS, + pallet_subtensor::pallet::MAX_COMMIT_REVEAL_PEROIDS, + pallet_subtensor::subnets::mechanism::GLOBAL_MAX_SUBNET_COUNT, + pallet_subtensor::subnets::mechanism::MAX_MECHANISM_COUNT_PER_SUBNET, + pallet_subtensor::utils::voting_power::VOTING_POWER_DISABLE_GRACE_PERIOD_BLOCKS, + pallet_subtensor::utils::voting_power::MAX_VOTING_POWER_EMA_ALPHA, + pallet_subtensor::Pallet::::EMISSION_BAR_UPDATE_INTERVAL, + pallet_subtensor::staking::lock::ONE_YEAR, + tao_u64_to_evm::(pallet_subtensor::staking::lock::LOCK_STATE_ZERO_THRESHOLD)?, + pallet_subtensor::pallet::INITIAL_ACTIVITY_CUTOFF_FACTOR_MILLI, + tao_u64_to_evm::(pallet_subtensor::coinbase::tao::MAX_TAO_ISSUANCE)?, + )) + } + + #[precompile::public("getSubtensorSystemAccounts()")] + #[precompile::view] + fn get_subtensor_system_accounts( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult<(H256, H256)> { + Ok(( + pallet_account::(::SubtensorPalletId::get()), + pallet_account::(::BurnAccountId::get()), + )) + } + + #[precompile::public("getBalancesConstants()")] + #[precompile::view] + fn get_balances_constants(_handle: &mut impl PrecompileHandle) -> EvmResult { + Ok(( + balance_to_evm::(::ExistentialDeposit::get())?, + ::MaxLocks::get(), + ::MaxReserves::get(), + ::MaxFreezes::get(), + )) + } + + #[precompile::public("getProxyConstants()")] + #[precompile::view] + fn get_proxy_constants(_handle: &mut impl PrecompileHandle) -> EvmResult { + Ok(( + balance_to_evm::(::ProxyDepositBase::get())?, + balance_to_evm::( + ::ProxyDepositFactor::get(), + )?, + ::MaxProxies::get(), + ::MaxPending::get(), + balance_to_evm::( + ::AnnouncementDepositBase::get(), + )?, + balance_to_evm::( + ::AnnouncementDepositFactor::get(), + )?, + )) + } + + #[precompile::public("getSchedulerConstants()")] + #[precompile::view] + fn get_scheduler_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + let maximum_weight = ::MaximumWeight::get(); + Ok(( + maximum_weight.ref_time(), + maximum_weight.proof_size(), + ::MaxScheduledPerBlock::get(), + )) + } + + #[precompile::public("getDrandConstants()")] + #[precompile::view] + fn get_drand_constants(_handle: &mut impl PrecompileHandle) -> EvmResult { + Ok(( + UnboundedString::from(pallet_drand::QUICKNET_CHAIN_HASH), + ::UnsignedPriority::get(), + ::HttpFetchTimeout::get(), + pallet_drand::MAX_PULSES_TO_FETCH, + pallet_drand::MAX_KEPT_PULSES, + pallet_drand::MAX_REMOVED_PULSES, + )) + } + + #[precompile::public("getCrowdloanConstants()")] + #[precompile::view] + fn get_crowdloan_constants( + _handle: &mut impl PrecompileHandle, + ) -> EvmResult { + Ok(( + tao_to_evm::(::MinimumDeposit::get())?, + tao_to_evm::(::AbsoluteMinimumContribution::get())?, + block_to_u64(::MinimumBlockDuration::get())?, + block_to_u64(::MaximumBlockDuration::get())?, + ::RefundContributorsLimit::get(), + ::MaxContributors::get(), + pallet_account::(::PalletId::get()), + )) + } + + #[precompile::public("getSwapConstants()")] + #[precompile::view] + fn get_swap_constants(_handle: &mut impl PrecompileHandle) -> EvmResult { + Ok(( + ::MaxFeeRate::get(), + tao_u64_to_evm::(::MinimumLiquidity::get())?, + tao_u64_to_evm::(::MinimumReserve::get().get())?, + pallet_account::(::ProtocolId::get()), + )) + } + + #[precompile::public("getTimestampConstants()")] + #[precompile::view] + fn get_timestamp_constants(_handle: &mut impl PrecompileHandle) -> EvmResult { + ::MinimumPeriod::get() + .try_into() + .map_err(|_| ExitError::InvalidRange.into()) + } + + #[precompile::public("getAdminConstants()")] + #[precompile::view] + fn get_admin_constants(_handle: &mut impl PrecompileHandle) -> EvmResult { + Ok(::MaxAuthorities::get()) + } +} + +fn tao_to_evm(value: TaoBalance) -> EvmResult +where + R: pallet_evm::Config, +{ + tao_u64_to_evm::(value.to_u64()) +} + +fn tao_u64_to_evm(value: u64) -> EvmResult +where + R: pallet_evm::Config, +{ + let value: SubstrateBalance = value.into(); + R::BalanceConverter::into_evm_balance(value) + .map(|amount| amount.into_u256()) + .ok_or_else(|| ExitError::InvalidRange.into()) +} + +fn balance_to_evm(value: Balance) -> EvmResult +where + R: pallet_evm::Config, + Balance: Into, +{ + let value = SubstrateBalance::new(value.into()); + R::BalanceConverter::into_evm_balance(value) + .map(|amount| amount.into_u256()) + .ok_or_else(|| ExitError::InvalidRange.into()) +} + +fn block_to_u64>(block: Block) -> EvmResult { + block.try_into().map_err(|_| ExitError::InvalidRange.into()) +} + +fn pallet_account(pallet_id: frame_support::PalletId) -> H256 +where + R: frame_system::Config, + R::AccountId: Into<[u8; 32]>, +{ + let account: R::AccountId = pallet_id.into_account_truncating(); + H256::from(>::into(account)) +} + +fn signed_i16_word(value: i16) -> U256 { + let mut encoded = [if value.is_negative() { 0xff } else { 0 }; 32]; + encoded[30..].copy_from_slice(&value.to_be_bytes()); + U256::from_big_endian(&encoded) } #[cfg(test)] mod tests { + #![allow(clippy::unwrap_used)] + use super::*; use crate::mock::{Runtime, addr_from_index, new_test_ext, precompiles, selector_u32}; use precompile_utils::{ prelude::RuntimeHelper, - solidity::{encode_return_value, encode_with_selector}, + solidity::{Codec, encode_return_value, encode_with_selector}, testing::PrecompileTesterExt, }; + fn assert_view(signature: &str, expected: Output) { + let precompiles = precompiles::>(); + precompiles + .prepare_test( + addr_from_index(1), + addr_from_index(RuntimeConfigurationPrecompile::::INDEX), + encode_with_selector(selector_u32(signature), ()), + ) + .with_static_call(true) + .execute_returns_raw(encode_return_value(expected)); + } + #[test] - fn address_selectors_and_values_are_stable() { + fn address_storage_selectors_and_values_are_stable() { new_test_ext().execute_with(|| { assert_eq!(RuntimeConfigurationPrecompile::::INDEX, 2066); pallet_evm_chain_id::ChainId::::put(9_999u64); @@ -84,4 +515,272 @@ mod tests { .execute_returns_raw(encode_return_value(77u64)); }); } + + #[test] + fn subtensor_constant_views_return_authoritative_runtime_values() { + new_test_ext().execute_with(|| { + assert_view( + "getSubtensorEconomicConstants()", + ( + tao_to_evm::(::InitialIssuance::get()).unwrap(), + tao_to_evm::(::InitialRAORecycledForRegistration::get()) + .unwrap(), + tao_to_evm::(::InitialBurn::get()).unwrap(), + tao_to_evm::(::InitialMinBurn::get()).unwrap(), + tao_to_evm::(::InitialMaxBurn::get()).unwrap(), + tao_to_evm::(::InitialMinStake::get()).unwrap(), + tao_to_evm::(::InitialMinTransfer::get()).unwrap(), + tao_to_evm::(::MinBurnUpperBound::get()).unwrap(), + tao_to_evm::(::MaxBurnLowerBound::get()).unwrap(), + tao_to_evm::(::InitialNetworkMinLockCost::get()).unwrap(), + tao_to_evm::(::KeySwapCost::get()).unwrap(), + tao_to_evm::(::KeySwapOnSubnetCost::get()).unwrap(), + tao_to_evm::( + pallet_subtensor::pallet::MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP, + ) + .unwrap(), + ), + ); + assert_view( + "getSubtensorSubnetConstants()", + ( + ::InitialTempo::get(), + ::MinTempo::get(), + ::MaxTempo::get(), + ::InitialMinAllowedUids::get(), + ::InitialMaxAllowedUids::get(), + ::InitialMaxAllowedValidators::get(), + ::InitialImmunityPeriod::get(), + ::InitialActivityCutoff::get(), + ::MinActivityCutoffFactorMilli::get(), + ::MaxActivityCutoffFactorMilli::get(), + ::MaxImmuneUidsPercentage::get().deconstruct(), + ::InitialSubnetOwnerCut::get(), + ::InitialMaxEpochsPerBlock::get(), + ), + ); + assert_view( + "getSubtensorConsensusConstants()", + ( + ::InitialMinAllowedWeights::get(), + ::InitialEmissionValue::get(), + ::InitialRho::get(), + signed_i16_word(::InitialAlphaSigmoidSteepness::get()), + ::InitialKappa::get(), + ::InitialBondsMovingAverage::get(), + ::InitialBondsPenalty::get(), + ::InitialBondsResetOn::get(), + ::InitialValidatorPruneLen::get(), + ::InitialScalingLawPower::get(), + ::InitialPruningScore::get(), + ::InitialWeightsVersionKey::get(), + ::InitialTaoWeight::get(), + ), + ); + assert_view( + "getSubtensorRegistrationConstants()", + ( + ::InitialDifficulty::get(), + ::InitialMinDifficulty::get(), + ::InitialMaxDifficulty::get(), + ::InitialAdjustmentInterval::get(), + ::InitialAdjustmentAlpha::get(), + ::InitialMaxRegistrationsPerBlock::get(), + ::InitialTargetRegistrationsPerInterval::get(), + ::InitialNetworkRateLimit::get(), + ::InitialNetworkImmunityPeriod::get(), + ::InitialNetworkLockReductionInterval::get(), + ::InitialEmaPriceHalvingPeriod::get(), + ), + ); + assert_view( + "getSubtensorDelegationConstants()", + ( + ::InitialDefaultDelegateTake::get(), + ::InitialMinDelegateTake::get(), + ::InitialDefaultChildKeyTake::get(), + ::InitialMinChildKeyTake::get(), + ::InitialMaxChildKeyTake::get(), + ::AlphaHigh::get(), + ::AlphaLow::get(), + ::LiquidAlphaOn::get(), + ::Yuma3On::get(), + ), + ); + assert_view( + "getSubtensorRateLimitConstants()", + ( + ::InitialServingRateLimit::get(), + ::InitialTxRateLimit::get(), + ::InitialTxDelegateTakeRateLimit::get(), + ::InitialTxChildKeyTakeRateLimit::get(), + ::EvmKeyAssociateRateLimit::get(), + block_to_u64(::InitialColdkeySwapAnnouncementDelay::get()).unwrap(), + block_to_u64(::InitialColdkeySwapReannouncementDelay::get()).unwrap(), + block_to_u64(::InitialDissolveNetworkScheduleDuration::get()).unwrap(), + ::InitialStartCallDelay::get(), + ::HotkeySwapOnSubnetInterval::get(), + block_to_u64(::LeaseDividendsDistributionInterval::get()).unwrap(), + ), + ); + assert_view( + "getSubtensorProtocolConstants()", + ( + pallet_subtensor::MAX_CRV3_COMMIT_SIZE_BYTES, + pallet_subtensor::MAX_ASSOCIATED_UIDS_PER_EVM_ADDRESS, + pallet_subtensor::MAX_COLDKEY_COLLATERAL_HOTKEYS, + pallet_subtensor::ACCOUNT_FLAGS_ACCEPT_LOCKED_ALPHA, + pallet_subtensor::pallet::MIN_COMMIT_REVEAL_PEROIDS, + pallet_subtensor::pallet::MAX_COMMIT_REVEAL_PEROIDS, + pallet_subtensor::subnets::mechanism::GLOBAL_MAX_SUBNET_COUNT, + pallet_subtensor::subnets::mechanism::MAX_MECHANISM_COUNT_PER_SUBNET, + pallet_subtensor::utils::voting_power::VOTING_POWER_DISABLE_GRACE_PERIOD_BLOCKS, + pallet_subtensor::utils::voting_power::MAX_VOTING_POWER_EMA_ALPHA, + pallet_subtensor::Pallet::::EMISSION_BAR_UPDATE_INTERVAL, + pallet_subtensor::staking::lock::ONE_YEAR, + tao_u64_to_evm::( + pallet_subtensor::staking::lock::LOCK_STATE_ZERO_THRESHOLD, + ) + .unwrap(), + pallet_subtensor::pallet::INITIAL_ACTIVITY_CUTOFF_FACTOR_MILLI, + tao_u64_to_evm::(pallet_subtensor::coinbase::tao::MAX_TAO_ISSUANCE) + .unwrap(), + ), + ); + assert_view( + "getSubtensorSystemAccounts()", + ( + pallet_account::(::SubtensorPalletId::get()), + pallet_account::(::BurnAccountId::get()), + ), + ); + }); + } + + #[test] + fn other_pallet_constant_views_return_authoritative_runtime_values() { + new_test_ext().execute_with(|| { + assert_view( + "getBalancesConstants()", + ( + balance_to_evm::( + ::ExistentialDeposit::get(), + ) + .unwrap(), + <::MaxLocks as Get>::get(), + <::MaxReserves as Get>::get(), + ::MaxFreezes::get(), + ), + ); + assert_view( + "getProxyConstants()", + ( + balance_to_evm::( + ::ProxyDepositBase::get(), + ) + .unwrap(), + balance_to_evm::( + ::ProxyDepositFactor::get(), + ) + .unwrap(), + ::MaxProxies::get(), + ::MaxPending::get(), + balance_to_evm::( + ::AnnouncementDepositBase::get(), + ) + .unwrap(), + balance_to_evm::( + ::AnnouncementDepositFactor::get( + ), + ) + .unwrap(), + ), + ); + let maximum_weight = ::MaximumWeight::get(); + assert_view( + "getSchedulerConstants()", + ( + maximum_weight.ref_time(), + maximum_weight.proof_size(), + ::MaxScheduledPerBlock::get(), + ), + ); + assert_view( + "getDrandConstants()", + ( + UnboundedString::from(pallet_drand::QUICKNET_CHAIN_HASH), + <::UnsignedPriority as Get>::get(), + <::HttpFetchTimeout as Get>::get(), + pallet_drand::MAX_PULSES_TO_FETCH, + pallet_drand::MAX_KEPT_PULSES, + pallet_drand::MAX_REMOVED_PULSES, + ), + ); + assert_view( + "getCrowdloanConstants()", + ( + tao_to_evm::( + ::MinimumDeposit::get(), + ) + .unwrap(), + tao_to_evm::( + ::AbsoluteMinimumContribution::get(), + ) + .unwrap(), + block_to_u64( + ::MinimumBlockDuration::get(), + ) + .unwrap(), + block_to_u64( + ::MaximumBlockDuration::get(), + ) + .unwrap(), + ::RefundContributorsLimit::get(), + ::MaxContributors::get(), + pallet_account::( + ::PalletId::get(), + ), + ), + ); + assert_view( + "getSwapConstants()", + ( + ::MaxFeeRate::get(), + tao_u64_to_evm::( + ::MinimumLiquidity::get(), + ) + .unwrap(), + tao_u64_to_evm::( + ::MinimumReserve::get().get(), + ) + .unwrap(), + pallet_account::( + ::ProtocolId::get(), + ), + ), + ); + assert_view( + "getTimestampConstants()", + ::MinimumPeriod::get(), + ); + assert_view( + "getAdminConstants()", + ::MaxAuthorities::get(), + ); + }); + } + + #[test] + fn signed_i16_constants_use_solidity_sign_extension() { + assert_eq!(signed_i16_word(1), U256::one()); + assert_eq!(signed_i16_word(-1), U256::from_big_endian(&[0xff; 32])); + assert_eq!( + signed_i16_word(i16::MIN), + U256::from_big_endian(&{ + let mut word = [0xff; 32]; + word[30..].copy_from_slice(&i16::MIN.to_be_bytes()); + word + }) + ); + } } diff --git a/precompiles/src/solidity/runtimeConfiguration.abi b/precompiles/src/solidity/runtimeConfiguration.abi index 44d814754a..257bd47289 100644 --- a/precompiles/src/solidity/runtimeConfiguration.abi +++ b/precompiles/src/solidity/runtimeConfiguration.abi @@ -1,28 +1,787 @@ [ - { - "inputs": [], - "name": "getEvmChainId", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransactionRateLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - } + { + "inputs": [ + + ], + "name": "getEvmChainId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getTransactionRateLimit", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorEconomicConstants", + "outputs": [ + { + "internalType": "uint256", + "name": "initialIssuance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialRaoRecycledForRegistration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMinBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMaxBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMinStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMinTransfer", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBurnUpperBound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxBurnLowerBound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialNetworkMinLockCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "keySwapCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "keySwapOnSubnetCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBalanceToPerformColdkeySwap", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorSubnetConstants", + "outputs": [ + { + "internalType": "uint16", + "name": "initialTempo", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "minTempo", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxTempo", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMinAllowedUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMaxAllowedUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMaxAllowedValidators", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialImmunityPeriod", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialActivityCutoff", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "minActivityCutoffFactorMilli", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxActivityCutoffFactorMilli", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "maxImmuneUidsPercentage", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "initialSubnetOwnerCut", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "initialMaxEpochsPerBlock", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorConsensusConstants", + "outputs": [ + { + "internalType": "uint16", + "name": "initialMinAllowedWeights", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialEmissionValue", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialRho", + "type": "uint16" + }, + { + "internalType": "int16", + "name": "initialAlphaSigmoidSteepness", + "type": "int16" + }, + { + "internalType": "uint16", + "name": "initialKappa", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "initialBondsMovingAverage", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "initialBondsPenalty", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "initialBondsResetOn", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "initialValidatorPruneLen", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "initialScalingLawPower", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialPruningScore", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "initialWeightsVersionKey", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialTaoWeight", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorRegistrationConstants", + "outputs": [ + { + "internalType": "uint64", + "name": "initialDifficulty", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialMinDifficulty", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialMaxDifficulty", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "initialAdjustmentInterval", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "initialAdjustmentAlpha", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "initialMaxRegistrationsPerBlock", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialTargetRegistrationsPerInterval", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "initialNetworkRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialNetworkImmunityPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialNetworkLockReductionInterval", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialEmaPriceHalvingPeriod", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorDelegationConstants", + "outputs": [ + { + "internalType": "uint16", + "name": "initialDefaultDelegateTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMinDelegateTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialDefaultChildKeyTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMinChildKeyTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMaxChildKeyTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "alphaHigh", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "alphaLow", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "liquidAlphaOn", + "type": "bool" + }, + { + "internalType": "bool", + "name": "yuma3On", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorRateLimitConstants", + "outputs": [ + { + "internalType": "uint64", + "name": "initialServingRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialTxRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialTxDelegateTakeRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialTxChildKeyTakeRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "evmKeyAssociateRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialColdkeySwapAnnouncementDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialColdkeySwapReannouncementDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialDissolveNetworkScheduleDuration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialStartCallDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "hotkeySwapOnSubnetInterval", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "leaseDividendsDistributionInterval", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorProtocolConstants", + "outputs": [ + { + "internalType": "uint32", + "name": "maxCrv3CommitSizeBytes", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxAssociatedUidsPerEvmAddress", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxColdkeyCollateralHotkeys", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "accountFlagsAcceptLockedAlpha", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "minCommitRevealPeriods", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxCommitRevealPeriods", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "globalMaxSubnetCount", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "maxMechanismCountPerSubnet", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "votingPowerDisableGracePeriodBlocks", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxVotingPowerEmaAlpha", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "emissionBarUpdateInterval", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "stakingLockDuration", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "lockStateZeroThreshold", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "initialActivityCutoffFactorMilli", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "maxTaoIssuance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorSystemAccounts", + "outputs": [ + { + "internalType": "bytes32", + "name": "subtensorPalletAccount", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "burnAccount", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getBalancesConstants", + "outputs": [ + { + "internalType": "uint256", + "name": "existentialDeposit", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxLocks", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxReserves", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxFreezes", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getProxyConstants", + "outputs": [ + { + "internalType": "uint256", + "name": "proxyDepositBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proxyDepositFactor", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxProxies", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPending", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "announcementDepositBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "announcementDepositFactor", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSchedulerConstants", + "outputs": [ + { + "internalType": "uint64", + "name": "maximumWeightRefTime", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maximumWeightProofSize", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "maxScheduledPerBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getDrandConstants", + "outputs": [ + { + "internalType": "string", + "name": "quicknetChainHash", + "type": "string" + }, + { + "internalType": "uint64", + "name": "unsignedPriority", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "httpFetchTimeout", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxPulsesToFetch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxKeptPulses", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxRemovedPulses", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getCrowdloanConstants", + "outputs": [ + { + "internalType": "uint256", + "name": "minimumDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "absoluteMinimumContribution", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "minimumBlockDuration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maximumBlockDuration", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "refundContributorsLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxContributors", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "palletAccount", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSwapConstants", + "outputs": [ + { + "internalType": "uint16", + "name": "maxFeeRate", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "minimumLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumReserve", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "protocolAccount", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getTimestampConstants", + "outputs": [ + { + "internalType": "uint64", + "name": "minimumPeriod", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getAdminConstants", + "outputs": [ + { + "internalType": "uint32", + "name": "maxAuthorities", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } ] diff --git a/precompiles/src/solidity/runtimeConfiguration.sol b/precompiles/src/solidity/runtimeConfiguration.sol index ad733b106c..1c32ae66c2 100644 --- a/precompiles/src/solidity/runtimeConfiguration.sol +++ b/precompiles/src/solidity/runtimeConfiguration.sol @@ -6,4 +6,166 @@ address constant IRUNTIME_CONFIGURATION_ADDRESS = 0x0000000000000000000000000000 interface IRuntimeConfiguration { function getEvmChainId() external view returns (uint64); function getTransactionRateLimit() external view returns (uint64); + + function getSubtensorEconomicConstants() external view returns ( + uint256 initialIssuance, + uint256 initialRaoRecycledForRegistration, + uint256 initialBurn, + uint256 initialMinBurn, + uint256 initialMaxBurn, + uint256 initialMinStake, + uint256 initialMinTransfer, + uint256 minBurnUpperBound, + uint256 maxBurnLowerBound, + uint256 initialNetworkMinLockCost, + uint256 keySwapCost, + uint256 keySwapOnSubnetCost, + uint256 minBalanceToPerformColdkeySwap + ); + + function getSubtensorSubnetConstants() external view returns ( + uint16 initialTempo, + uint16 minTempo, + uint16 maxTempo, + uint16 initialMinAllowedUids, + uint16 initialMaxAllowedUids, + uint16 initialMaxAllowedValidators, + uint16 initialImmunityPeriod, + uint16 initialActivityCutoff, + uint32 minActivityCutoffFactorMilli, + uint32 maxActivityCutoffFactorMilli, + uint8 maxImmuneUidsPercentage, + uint16 initialSubnetOwnerCut, + uint8 initialMaxEpochsPerBlock + ); + + function getSubtensorConsensusConstants() external view returns ( + uint16 initialMinAllowedWeights, + uint16 initialEmissionValue, + uint16 initialRho, + int16 initialAlphaSigmoidSteepness, + uint16 initialKappa, + uint64 initialBondsMovingAverage, + uint16 initialBondsPenalty, + bool initialBondsResetOn, + uint64 initialValidatorPruneLen, + uint16 initialScalingLawPower, + uint16 initialPruningScore, + uint64 initialWeightsVersionKey, + uint64 initialTaoWeight + ); + + function getSubtensorRegistrationConstants() external view returns ( + uint64 initialDifficulty, + uint64 initialMinDifficulty, + uint64 initialMaxDifficulty, + uint16 initialAdjustmentInterval, + uint64 initialAdjustmentAlpha, + uint16 initialMaxRegistrationsPerBlock, + uint16 initialTargetRegistrationsPerInterval, + uint64 initialNetworkRateLimit, + uint64 initialNetworkImmunityPeriod, + uint64 initialNetworkLockReductionInterval, + uint64 initialEmaPriceHalvingPeriod + ); + + function getSubtensorDelegationConstants() external view returns ( + uint16 initialDefaultDelegateTake, + uint16 initialMinDelegateTake, + uint16 initialDefaultChildKeyTake, + uint16 initialMinChildKeyTake, + uint16 initialMaxChildKeyTake, + uint16 alphaHigh, + uint16 alphaLow, + bool liquidAlphaOn, + bool yuma3On + ); + + function getSubtensorRateLimitConstants() external view returns ( + uint64 initialServingRateLimit, + uint64 initialTxRateLimit, + uint64 initialTxDelegateTakeRateLimit, + uint64 initialTxChildKeyTakeRateLimit, + uint64 evmKeyAssociateRateLimit, + uint64 initialColdkeySwapAnnouncementDelay, + uint64 initialColdkeySwapReannouncementDelay, + uint64 initialDissolveNetworkScheduleDuration, + uint64 initialStartCallDelay, + uint64 hotkeySwapOnSubnetInterval, + uint64 leaseDividendsDistributionInterval + ); + + function getSubtensorProtocolConstants() external view returns ( + uint32 maxCrv3CommitSizeBytes, + uint32 maxAssociatedUidsPerEvmAddress, + uint32 maxColdkeyCollateralHotkeys, + uint128 accountFlagsAcceptLockedAlpha, + uint64 minCommitRevealPeriods, + uint64 maxCommitRevealPeriods, + uint16 globalMaxSubnetCount, + uint8 maxMechanismCountPerSubnet, + uint64 votingPowerDisableGracePeriodBlocks, + uint64 maxVotingPowerEmaAlpha, + uint64 emissionBarUpdateInterval, + uint64 stakingLockDuration, + uint256 lockStateZeroThreshold, + uint32 initialActivityCutoffFactorMilli, + uint256 maxTaoIssuance + ); + + function getSubtensorSystemAccounts() external view returns ( + bytes32 subtensorPalletAccount, + bytes32 burnAccount + ); + + function getBalancesConstants() external view returns ( + uint256 existentialDeposit, + uint32 maxLocks, + uint32 maxReserves, + uint32 maxFreezes + ); + + function getProxyConstants() external view returns ( + uint256 proxyDepositBase, + uint256 proxyDepositFactor, + uint32 maxProxies, + uint32 maxPending, + uint256 announcementDepositBase, + uint256 announcementDepositFactor + ); + + function getSchedulerConstants() external view returns ( + uint64 maximumWeightRefTime, + uint64 maximumWeightProofSize, + uint32 maxScheduledPerBlock + ); + + function getDrandConstants() external view returns ( + string memory quicknetChainHash, + uint64 unsignedPriority, + uint64 httpFetchTimeout, + uint64 maxPulsesToFetch, + uint64 maxKeptPulses, + uint64 maxRemovedPulses + ); + + function getCrowdloanConstants() external view returns ( + uint256 minimumDeposit, + uint256 absoluteMinimumContribution, + uint64 minimumBlockDuration, + uint64 maximumBlockDuration, + uint32 refundContributorsLimit, + uint32 maxContributors, + bytes32 palletAccount + ); + + function getSwapConstants() external view returns ( + uint16 maxFeeRate, + uint256 minimumLiquidity, + uint256 minimumReserve, + bytes32 protocolAccount + ); + + function getTimestampConstants() external view returns (uint64 minimumPeriod); + function getAdminConstants() external view returns (uint32 maxAuthorities); } diff --git a/sdk/python/bittensor/evm/abi/runtimeConfiguration.json b/sdk/python/bittensor/evm/abi/runtimeConfiguration.json index 44d814754a..257bd47289 100644 --- a/sdk/python/bittensor/evm/abi/runtimeConfiguration.json +++ b/sdk/python/bittensor/evm/abi/runtimeConfiguration.json @@ -1,28 +1,787 @@ [ - { - "inputs": [], - "name": "getEvmChainId", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransactionRateLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - } + { + "inputs": [ + + ], + "name": "getEvmChainId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getTransactionRateLimit", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorEconomicConstants", + "outputs": [ + { + "internalType": "uint256", + "name": "initialIssuance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialRaoRecycledForRegistration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMinBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMaxBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMinStake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialMinTransfer", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBurnUpperBound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxBurnLowerBound", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialNetworkMinLockCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "keySwapCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "keySwapOnSubnetCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minBalanceToPerformColdkeySwap", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorSubnetConstants", + "outputs": [ + { + "internalType": "uint16", + "name": "initialTempo", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "minTempo", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxTempo", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMinAllowedUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMaxAllowedUids", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMaxAllowedValidators", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialImmunityPeriod", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialActivityCutoff", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "minActivityCutoffFactorMilli", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxActivityCutoffFactorMilli", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "maxImmuneUidsPercentage", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "initialSubnetOwnerCut", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "initialMaxEpochsPerBlock", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorConsensusConstants", + "outputs": [ + { + "internalType": "uint16", + "name": "initialMinAllowedWeights", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialEmissionValue", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialRho", + "type": "uint16" + }, + { + "internalType": "int16", + "name": "initialAlphaSigmoidSteepness", + "type": "int16" + }, + { + "internalType": "uint16", + "name": "initialKappa", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "initialBondsMovingAverage", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "initialBondsPenalty", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "initialBondsResetOn", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "initialValidatorPruneLen", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "initialScalingLawPower", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialPruningScore", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "initialWeightsVersionKey", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialTaoWeight", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorRegistrationConstants", + "outputs": [ + { + "internalType": "uint64", + "name": "initialDifficulty", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialMinDifficulty", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialMaxDifficulty", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "initialAdjustmentInterval", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "initialAdjustmentAlpha", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "initialMaxRegistrationsPerBlock", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialTargetRegistrationsPerInterval", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "initialNetworkRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialNetworkImmunityPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialNetworkLockReductionInterval", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialEmaPriceHalvingPeriod", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorDelegationConstants", + "outputs": [ + { + "internalType": "uint16", + "name": "initialDefaultDelegateTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMinDelegateTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialDefaultChildKeyTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMinChildKeyTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "initialMaxChildKeyTake", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "alphaHigh", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "alphaLow", + "type": "uint16" + }, + { + "internalType": "bool", + "name": "liquidAlphaOn", + "type": "bool" + }, + { + "internalType": "bool", + "name": "yuma3On", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorRateLimitConstants", + "outputs": [ + { + "internalType": "uint64", + "name": "initialServingRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialTxRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialTxDelegateTakeRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialTxChildKeyTakeRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "evmKeyAssociateRateLimit", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialColdkeySwapAnnouncementDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialColdkeySwapReannouncementDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialDissolveNetworkScheduleDuration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initialStartCallDelay", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "hotkeySwapOnSubnetInterval", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "leaseDividendsDistributionInterval", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorProtocolConstants", + "outputs": [ + { + "internalType": "uint32", + "name": "maxCrv3CommitSizeBytes", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxAssociatedUidsPerEvmAddress", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxColdkeyCollateralHotkeys", + "type": "uint32" + }, + { + "internalType": "uint128", + "name": "accountFlagsAcceptLockedAlpha", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "minCommitRevealPeriods", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxCommitRevealPeriods", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "globalMaxSubnetCount", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "maxMechanismCountPerSubnet", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "votingPowerDisableGracePeriodBlocks", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxVotingPowerEmaAlpha", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "emissionBarUpdateInterval", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "stakingLockDuration", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "lockStateZeroThreshold", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "initialActivityCutoffFactorMilli", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "maxTaoIssuance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSubtensorSystemAccounts", + "outputs": [ + { + "internalType": "bytes32", + "name": "subtensorPalletAccount", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "burnAccount", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getBalancesConstants", + "outputs": [ + { + "internalType": "uint256", + "name": "existentialDeposit", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxLocks", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxReserves", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxFreezes", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getProxyConstants", + "outputs": [ + { + "internalType": "uint256", + "name": "proxyDepositBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proxyDepositFactor", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "maxProxies", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPending", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "announcementDepositBase", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "announcementDepositFactor", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSchedulerConstants", + "outputs": [ + { + "internalType": "uint64", + "name": "maximumWeightRefTime", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maximumWeightProofSize", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "maxScheduledPerBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getDrandConstants", + "outputs": [ + { + "internalType": "string", + "name": "quicknetChainHash", + "type": "string" + }, + { + "internalType": "uint64", + "name": "unsignedPriority", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "httpFetchTimeout", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxPulsesToFetch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxKeptPulses", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxRemovedPulses", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getCrowdloanConstants", + "outputs": [ + { + "internalType": "uint256", + "name": "minimumDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "absoluteMinimumContribution", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "minimumBlockDuration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maximumBlockDuration", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "refundContributorsLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxContributors", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "palletAccount", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getSwapConstants", + "outputs": [ + { + "internalType": "uint16", + "name": "maxFeeRate", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "minimumLiquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumReserve", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "protocolAccount", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getTimestampConstants", + "outputs": [ + { + "internalType": "uint64", + "name": "minimumPeriod", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + + ], + "name": "getAdminConstants", + "outputs": [ + { + "internalType": "uint32", + "name": "maxAuthorities", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } ] From fa7c922f3d3777f68f2ff7dd19f8f757fbaf05a6 Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Tue, 4 Aug 2026 09:03:08 -0700 Subject: [PATCH 22/58] reject invalid during transaction validation --- pallets/subtensor/src/extensions/subtensor.rs | 138 +++++++++++++++++- .../subtensor/src/guards/check_rate_limits.rs | 58 +++++++- 2 files changed, 189 insertions(+), 7 deletions(-) diff --git a/pallets/subtensor/src/extensions/subtensor.rs b/pallets/subtensor/src/extensions/subtensor.rs index 7899ed855e..2b1844fe8c 100644 --- a/pallets/subtensor/src/extensions/subtensor.rs +++ b/pallets/subtensor/src/extensions/subtensor.rs @@ -1,11 +1,11 @@ use crate::{ Call, CheckColdkeySwap, CheckDelegateTake, CheckEvmKeyAssociation, CheckRateLimits, - CheckServingEndpoints, CheckWeights, Config, Error, guards::applicable_call, + CheckServingEndpoints, CheckWeights, Config, Error, Pallet, guards::applicable_call, }; use codec::{Decode, DecodeWithMemTracking, Encode}; use frame_support::{ dispatch::{DispatchExtension, DispatchInfo, PostDispatchInfo}, - traits::{IsSubType, OriginTrait}, + traits::{Get, IsSubType, OriginTrait}, weights::Weight, }; use scale_info::TypeInfo; @@ -14,7 +14,7 @@ use sp_runtime::traits::{ }; use sp_runtime::{ impl_tx_ext_default, - transaction_validity::{TransactionSource, TransactionValidityError}, + transaction_validity::{TransactionSource, TransactionValidityError, ValidTransaction}, }; use sp_std::marker::PhantomData; use subtensor_macros::freeze_struct; @@ -77,9 +77,10 @@ impl SubtensorTransactionExtension { fn check(origin: &OriginOf, call: &CallOf) -> Result<(), Error> where - T: pallet_shield::Config, + T: pallet_commitments::Config + pallet_shield::Config, CallOf: Dispatchable> + IsSubType> + + IsSubType> + IsSubType>, OriginOf: OriginTrait, { @@ -89,6 +90,16 @@ impl SubtensorTransactionExtension { CheckColdkeySwap::::check(who, call)?; + let commitment_call: Option<&pallet_commitments::Call> = call.is_sub_type(); + if let Some(pallet_commitments::Call::set_commitment { netuid, .. }) = commitment_call { + if !Pallet::::if_subnet_exist(*netuid) { + return Err(Error::::SubnetNotExists); + } + if !Pallet::::is_hotkey_registered_on_network(*netuid, who) { + return Err(Error::::HotKeyNotRegisteredInSubNet); + } + } + if let Some(call) = applicable_call(call, CheckWeights::::applies_to) { CheckWeights::::check(who, call)?; } @@ -107,13 +118,30 @@ impl SubtensorTransactionExtension { Ok(()) } + + fn commitment_weight(call: &CallOf) -> Weight + where + T: pallet_commitments::Config, + CallOf: IsSubType>, + { + let commitment_call: Option<&pallet_commitments::Call> = call.is_sub_type(); + if matches!( + commitment_call, + Some(pallet_commitments::Call::set_commitment { .. }) + ) { + T::DbWeight::get().reads(2) + } else { + Weight::zero() + } + } } impl TransactionExtension> for SubtensorTransactionExtension where - T: Config + pallet_shield::Config + Send + Sync + TypeInfo, + T: Config + pallet_commitments::Config + pallet_shield::Config + Send + Sync + TypeInfo, CallOf: Dispatchable, Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType> + + IsSubType> + IsSubType>, OriginOf: Clone + OriginTrait, { @@ -131,6 +159,7 @@ where .saturating_add( as DE>>::weight(call)) .saturating_add( as DE>>::weight(call)) .saturating_add( as DE>>::weight(call)) + .saturating_add(Self::commitment_weight(call)) } fn validate( @@ -144,7 +173,17 @@ where _source: TransactionSource, ) -> ValidateResult> { Self::check(&origin, call) - .map(|()| (Default::default(), (), origin)) + .map(|()| { + let mut validity = ValidTransaction::default(); + if let Some(who) = origin.as_signer() + && let Some(call) = applicable_call(call, CheckRateLimits::::applies_to) + { + validity + .provides + .extend(CheckRateLimits::::provides_tags(who, call)); + } + (validity, (), origin) + }) .map_err(|error| TransactionValidityError::from(CustomTransactionError::from(error))) } @@ -206,6 +245,9 @@ mod tests { .saturating_add( as DE>::weight( call, )) + .saturating_add(SubtensorTransactionExtension::::commitment_weight( + call, + )) } #[test] @@ -278,6 +320,84 @@ mod tests { }); } + #[test] + fn validate_rejects_ineligible_metadata_commitment() { + new_test_ext(0).execute_with(|| { + let netuid = NetUid::from(1); + let hotkey = U256::from(1); + let coldkey = U256::from(2); + let commitment_call = || { + RuntimeCall::Commitments(pallet_commitments::Call::set_commitment { + netuid, + info: Box::new(pallet_commitments::CommitmentInfo { + fields: frame_support::BoundedVec::default(), + }), + }) + }; + + assert_eq!( + validate_signed(hotkey, &commitment_call()).unwrap_err(), + CustomTransactionError::SubnetNotExists.into() + ); + + add_network(netuid, 1, 0); + assert_eq!( + validate_signed(hotkey, &commitment_call()).unwrap_err(), + CustomTransactionError::UidNotFound.into() + ); + + setup_reserves( + netuid, + 1_000_000_000_000_u64.into(), + 1_000_000_000_000_u64.into(), + ); + register_ok_neuron(netuid, hotkey, coldkey, 0); + assert_ok!(validate_signed(hotkey, &commitment_call())); + }); + } + + #[test] + fn timelocked_commits_reject_at_validity_and_conflict_in_pool() { + new_test_ext(0).execute_with(|| { + let netuid = NetUid::from(1); + let hotkey = U256::from(1); + let coldkey = U256::from(2); + + add_network(netuid, 1, 0); + setup_reserves( + netuid, + 1_000_000_000_000_u64.into(), + 1_000_000_000_000_u64.into(), + ); + register_ok_neuron(netuid, hotkey, coldkey, 0); + SubtensorModule::set_stake_threshold(0); + SubtensorModule::set_weights_set_rate_limit(netuid, 100); + System::set_block_number(10_u64); + let uid = SubtensorModule::get_uid_for_net_and_hotkey(netuid, &hotkey).unwrap(); + let netuid_index = SubtensorModule::get_mechanism_storage_index(netuid, MechId::MAIN); + SubtensorModule::set_last_update_for_uid(netuid_index, uid, 10); + + let call = + RuntimeCall::SubtensorModule(SubtensorCall::commit_timelocked_mechanism_weights { + netuid, + mecid: MechId::MAIN, + commit: Default::default(), + reveal_round: 1, + commit_reveal_version: 4, + }); + assert_eq!( + validate_signed(hotkey, &call).unwrap_err(), + CustomTransactionError::RateLimitExceeded.into() + ); + + System::set_block_number(200_u64); + let first = validate_signed(hotkey, &call).unwrap(); + let second = validate_signed(hotkey, &call).unwrap(); + assert_eq!(first.provides.len(), 1); + assert_eq!(first.provides, second.provides); + }); + } + #[test] fn weight_matches_top_level_dispatch_extension_checks() { new_test_ext(1).execute_with(|| { @@ -293,6 +413,12 @@ mod tests { RuntimeCall::SubtensorModule(SubtensorCall::register_network { hotkey: U256::from(9), }), + RuntimeCall::Commitments(pallet_commitments::Call::set_commitment { + netuid: NetUid::from(1), + info: Box::new(pallet_commitments::CommitmentInfo { + fields: frame_support::BoundedVec::default(), + }), + }), ]; for call in calls { diff --git a/pallets/subtensor/src/guards/check_rate_limits.rs b/pallets/subtensor/src/guards/check_rate_limits.rs index e12c9d064b..7e958a1661 100644 --- a/pallets/subtensor/src/guards/check_rate_limits.rs +++ b/pallets/subtensor/src/guards/check_rate_limits.rs @@ -1,13 +1,14 @@ use super::{CallOf, DispatchableOriginOf, applicable_call}; use crate::weights::WeightInfo; use crate::{Call, Config, Error, Pallet, TransactionType}; +use codec::Encode; use frame_support::{ dispatch::{DispatchErrorWithPostInfo, DispatchExtension, DispatchInfo, PostDispatchInfo}, pallet_prelude::*, traits::{IsSubType, OriginTrait}, }; use sp_runtime::traits::Dispatchable; -use sp_std::marker::PhantomData; +use sp_std::{marker::PhantomData, vec, vec::Vec}; use subtensor_runtime_common::{NetUid, NetUidStorageIndex}; /// Dispatch extension for rate-limit checks that are safe to reject before dispatch. @@ -22,6 +23,9 @@ impl CheckRateLimits { call, Call::commit_weights { .. } | Call::commit_mechanism_weights { .. } + | Call::commit_timelocked_weights { .. } + | Call::commit_timelocked_mechanism_weights { .. } + | Call::commit_crv3_mechanism_weights { .. } | Call::set_weights { .. } | Call::set_mechanism_weights { .. } | Call::register_network { .. } @@ -60,6 +64,21 @@ impl CheckRateLimits { Pallet::::get_mechanism_storage_index(*netuid, *mecid), Error::::CommittingWeightsTooFast, ), + Call::commit_timelocked_weights { netuid, .. } => Self::check_weights_rate_limit( + who, + *netuid, + NetUidStorageIndex::from(*netuid), + Error::::CommittingWeightsTooFast, + ), + Call::commit_timelocked_mechanism_weights { netuid, mecid, .. } + | Call::commit_crv3_mechanism_weights { netuid, mecid, .. } => { + Self::check_weights_rate_limit( + who, + *netuid, + Pallet::::get_mechanism_storage_index(*netuid, *mecid), + Error::::CommittingWeightsTooFast, + ) + } Call::set_weights { netuid, .. } if !Pallet::::get_commit_reveal_weights_enabled(*netuid) => { @@ -88,6 +107,24 @@ impl CheckRateLimits { _ => Ok(()), } } + + /// One pending commit per hotkey and mechanism. Calls sharing this tag also share the same + /// on-chain rate limit, so the pool keeps only one candidate instead of landing the rest as + /// deterministic `CommittingWeightsTooFast` failures. + pub(crate) fn provides_tags(who: &T::AccountId, call: &Call) -> Vec> { + let netuid_index = match call { + Call::commit_weights { netuid, .. } + | Call::commit_timelocked_weights { netuid, .. } => NetUidStorageIndex::from(*netuid), + Call::commit_mechanism_weights { netuid, mecid, .. } + | Call::commit_timelocked_mechanism_weights { netuid, mecid, .. } + | Call::commit_crv3_mechanism_weights { netuid, mecid, .. } => { + Pallet::::get_mechanism_storage_index(*netuid, *mecid) + } + _ => return Vec::new(), + }; + + vec![(b"weight-commit", who, netuid_index).encode()] + } } impl DispatchExtension> for CheckRateLimits @@ -191,6 +228,25 @@ mod tests { mecid: MechId::MAIN, commit_hash: sp_core::H256::zero(), }), + RuntimeCall::SubtensorModule(SubtensorCall::commit_timelocked_weights { + netuid, + commit: Default::default(), + reveal_round: 1, + commit_reveal_version: 4, + }), + RuntimeCall::SubtensorModule(SubtensorCall::commit_timelocked_mechanism_weights { + netuid, + mecid: MechId::MAIN, + commit: Default::default(), + reveal_round: 1, + commit_reveal_version: 4, + }), + RuntimeCall::SubtensorModule(SubtensorCall::commit_crv3_mechanism_weights { + netuid, + mecid: MechId::MAIN, + commit: Default::default(), + reveal_round: 1, + }), set_weights_call(netuid, 0), RuntimeCall::SubtensorModule(SubtensorCall::set_mechanism_weights { netuid, From 2769b73a8a94b369c8c712553a0a28b17125f54f Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Tue, 4 Aug 2026 10:16:18 -0700 Subject: [PATCH 23/58] fix provides tag --- pallets/subtensor/src/extensions/subtensor.rs | 33 +++++++++++++++++++ .../subtensor/src/guards/check_rate_limits.rs | 23 ++++++++----- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/pallets/subtensor/src/extensions/subtensor.rs b/pallets/subtensor/src/extensions/subtensor.rs index 2b1844fe8c..3842332cf1 100644 --- a/pallets/subtensor/src/extensions/subtensor.rs +++ b/pallets/subtensor/src/extensions/subtensor.rs @@ -398,6 +398,39 @@ mod tests { }); } + #[test] + fn timelocked_commits_with_zero_rate_limit_do_not_conflict_in_pool() { + new_test_ext(0).execute_with(|| { + let netuid = NetUid::from(1); + let hotkey = U256::from(1); + let coldkey = U256::from(2); + + add_network(netuid, 1, 0); + setup_reserves( + netuid, + 1_000_000_000_000_u64.into(), + 1_000_000_000_000_u64.into(), + ); + register_ok_neuron(netuid, hotkey, coldkey, 0); + SubtensorModule::set_stake_threshold(0); + SubtensorModule::set_weights_set_rate_limit(netuid, 0); + + let call = + RuntimeCall::SubtensorModule(SubtensorCall::commit_timelocked_mechanism_weights { + netuid, + mecid: MechId::MAIN, + commit: Default::default(), + reveal_round: 1, + commit_reveal_version: 4, + }); + + let first = validate_signed(hotkey, &call).unwrap(); + let second = validate_signed(hotkey, &call).unwrap(); + assert!(first.provides.is_empty()); + assert!(second.provides.is_empty()); + }); + } + #[test] fn weight_matches_top_level_dispatch_extension_checks() { new_test_ext(1).execute_with(|| { diff --git a/pallets/subtensor/src/guards/check_rate_limits.rs b/pallets/subtensor/src/guards/check_rate_limits.rs index 7e958a1661..b241903ce5 100644 --- a/pallets/subtensor/src/guards/check_rate_limits.rs +++ b/pallets/subtensor/src/guards/check_rate_limits.rs @@ -108,21 +108,28 @@ impl CheckRateLimits { } } - /// One pending commit per hotkey and mechanism. Calls sharing this tag also share the same - /// on-chain rate limit, so the pool keeps only one candidate instead of landing the rest as - /// deterministic `CommittingWeightsTooFast` failures. + /// One pending commit per hotkey and mechanism when commits are rate limited. Calls sharing + /// this tag also share the same on-chain rate limit, so the pool keeps only one candidate + /// instead of landing the rest as deterministic `CommittingWeightsTooFast` failures. pub(crate) fn provides_tags(who: &T::AccountId, call: &Call) -> Vec> { - let netuid_index = match call { + let (netuid, netuid_index) = match call { Call::commit_weights { netuid, .. } - | Call::commit_timelocked_weights { netuid, .. } => NetUidStorageIndex::from(*netuid), + | Call::commit_timelocked_weights { netuid, .. } => { + (*netuid, NetUidStorageIndex::from(*netuid)) + } Call::commit_mechanism_weights { netuid, mecid, .. } | Call::commit_timelocked_mechanism_weights { netuid, mecid, .. } - | Call::commit_crv3_mechanism_weights { netuid, mecid, .. } => { - Pallet::::get_mechanism_storage_index(*netuid, *mecid) - } + | Call::commit_crv3_mechanism_weights { netuid, mecid, .. } => ( + *netuid, + Pallet::::get_mechanism_storage_index(*netuid, *mecid), + ), _ => return Vec::new(), }; + if Pallet::::get_weights_set_rate_limit(netuid) == 0 { + return Vec::new(); + } + vec![(b"weight-commit", who, netuid_index).encode()] } } From ef6a09b8da910f598b9f1f58cbd955f4799a3fee Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Tue, 4 Aug 2026 10:47:05 -0700 Subject: [PATCH 24/58] use existing helper --- pallets/commitments/src/lib.rs | 24 ++++++++++----- pallets/commitments/src/mock.rs | 10 +++++-- pallets/subtensor/src/extensions/subtensor.rs | 17 +++++------ pallets/subtensor/src/tests/mock.rs | 16 ++++++++-- runtime/src/lib.rs | 29 +++++++++++++++---- 5 files changed, 70 insertions(+), 26 deletions(-) diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index 5ed05744ed..d1f085747d 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -211,7 +211,8 @@ pub mod pallet { /// Set the commitment for a given netuid #[pallet::call_index(0)] #[pallet::weight(( - ::WeightInfo::set_commitment(), + ::WeightInfo::set_commitment() + .saturating_add(T::CanCommit::validation_weight()), DispatchClass::Normal, Pays::No ))] @@ -221,10 +222,8 @@ pub mod pallet { info: Box>, ) -> DispatchResult { let who = ensure_signed(origin.clone())?; - ensure!( - T::CanCommit::can_commit(netuid, &who), - Error::::AccountNotAllowedCommit - ); + T::CanCommit::validate(netuid, &who) + .map_err(|_| Error::::AccountNotAllowedCommit)?; let extra_fields = info.fields.len() as u32; ensure!( @@ -356,12 +355,21 @@ pub mod pallet { // Interfaces to interact with other pallets pub trait CanCommit { - fn can_commit(netuid: NetUid, who: &AccountId) -> bool; + type Error; + + fn validate(netuid: NetUid, who: &AccountId) -> Result<(), Self::Error>; + fn validation_weight() -> frame_support::weights::Weight; } impl CanCommit for () { - fn can_commit(_: NetUid, _: &A) -> bool { - false + type Error = (); + + fn validate(_: NetUid, _: &A) -> Result<(), Self::Error> { + Err(()) + } + + fn validation_weight() -> frame_support::weights::Weight { + frame_support::weights::Weight::zero() } } diff --git a/pallets/commitments/src/mock.rs b/pallets/commitments/src/mock.rs index 58ed8cd863..c626a6f784 100644 --- a/pallets/commitments/src/mock.rs +++ b/pallets/commitments/src/mock.rs @@ -90,8 +90,14 @@ impl TypeInfo for TestMaxFields { pub struct TestCanCommit; impl pallet_commitments::CanCommit for TestCanCommit { - fn can_commit(_netuid: NetUid, _who: &u64) -> bool { - true + type Error = (); + + fn validate(_netuid: NetUid, _who: &u64) -> Result<(), Self::Error> { + Ok(()) + } + + fn validation_weight() -> Weight { + Weight::zero() } } diff --git a/pallets/subtensor/src/extensions/subtensor.rs b/pallets/subtensor/src/extensions/subtensor.rs index 3842332cf1..983a1ce97d 100644 --- a/pallets/subtensor/src/extensions/subtensor.rs +++ b/pallets/subtensor/src/extensions/subtensor.rs @@ -1,13 +1,14 @@ use crate::{ Call, CheckColdkeySwap, CheckDelegateTake, CheckEvmKeyAssociation, CheckRateLimits, - CheckServingEndpoints, CheckWeights, Config, Error, Pallet, guards::applicable_call, + CheckServingEndpoints, CheckWeights, Config, Error, guards::applicable_call, }; use codec::{Decode, DecodeWithMemTracking, Encode}; use frame_support::{ dispatch::{DispatchExtension, DispatchInfo, PostDispatchInfo}, - traits::{Get, IsSubType, OriginTrait}, + traits::{IsSubType, OriginTrait}, weights::Weight, }; +use pallet_commitments::CanCommit; use scale_info::TypeInfo; use sp_runtime::traits::{ DispatchInfoOf, Dispatchable, Implication, TransactionExtension, ValidateResult, @@ -22,6 +23,7 @@ use subtensor_runtime_common::CustomTransactionError; type CallOf = ::RuntimeCall; type OriginOf = ::RuntimeOrigin; +type CommitmentPolicy = ::CanCommit; #[allow(deprecated)] impl From> for CustomTransactionError { @@ -83,6 +85,7 @@ impl SubtensorTransactionExtension { + IsSubType> + IsSubType>, OriginOf: OriginTrait, + CommitmentPolicy: CanCommit>, { let Some(who) = origin.as_signer() else { return Ok(()); @@ -92,12 +95,7 @@ impl SubtensorTransactionExtension { let commitment_call: Option<&pallet_commitments::Call> = call.is_sub_type(); if let Some(pallet_commitments::Call::set_commitment { netuid, .. }) = commitment_call { - if !Pallet::::if_subnet_exist(*netuid) { - return Err(Error::::SubnetNotExists); - } - if !Pallet::::is_hotkey_registered_on_network(*netuid, who) { - return Err(Error::::HotKeyNotRegisteredInSubNet); - } + CommitmentPolicy::::validate(*netuid, who)?; } if let Some(call) = applicable_call(call, CheckWeights::::applies_to) { @@ -129,7 +127,7 @@ impl SubtensorTransactionExtension { commitment_call, Some(pallet_commitments::Call::set_commitment { .. }) ) { - T::DbWeight::get().reads(2) + CommitmentPolicy::::validation_weight() } else { Weight::zero() } @@ -144,6 +142,7 @@ where + IsSubType> + IsSubType>, OriginOf: Clone + OriginTrait, + CommitmentPolicy: CanCommit>, { const IDENTIFIER: &'static str = "SubtensorTransactionExtension"; diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index 0452471018..9fcc28f866 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -52,8 +52,20 @@ impl Get for TestMaxFields { pub struct TestCanCommit; impl pallet_commitments::CanCommit for TestCanCommit { - fn can_commit(_netuid: NetUid, _who: &U256) -> bool { - true + type Error = crate::Error; + + fn validate(netuid: NetUid, who: &U256) -> Result<(), Self::Error> { + if !SubtensorModule::if_subnet_exist(netuid) { + return Err(crate::Error::::SubnetNotExists); + } + if !SubtensorModule::is_hotkey_registered_on_network(netuid, who) { + return Err(crate::Error::::HotKeyNotRegisteredInSubNet); + } + Ok(()) + } + + fn validation_weight() -> Weight { + ::DbWeight::get().reads(2) } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index f4ad13bf81..56fbc7a287 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -712,15 +712,34 @@ impl Get for MaxCommitFields { #[subtensor_macros::freeze_struct("c39297f5eb97ee82")] pub struct AllowCommitments; impl CanCommit for AllowCommitments { + type Error = pallet_subtensor::Error; + #[cfg(not(feature = "runtime-benchmarks"))] - fn can_commit(netuid: NetUid, address: &AccountId) -> bool { - SubtensorModule::if_subnet_exist(netuid) - && SubtensorModule::is_hotkey_registered_on_network(netuid, address) + fn validate(netuid: NetUid, address: &AccountId) -> Result<(), Self::Error> { + if !SubtensorModule::if_subnet_exist(netuid) { + return Err(pallet_subtensor::Error::::SubnetNotExists); + } + if !SubtensorModule::is_hotkey_registered_on_network(netuid, address) { + return Err(pallet_subtensor::Error::::HotKeyNotRegisteredInSubNet); + } + Ok(()) } #[cfg(feature = "runtime-benchmarks")] - fn can_commit(_: NetUid, _: &AccountId) -> bool { - true + fn validate(_: NetUid, _: &AccountId) -> Result<(), Self::Error> { + Ok(()) + } + + fn validation_weight() -> frame_support::weights::Weight { + #[cfg(not(feature = "runtime-benchmarks"))] + { + ::DbWeight::get().reads(2) + } + + #[cfg(feature = "runtime-benchmarks")] + { + frame_support::weights::Weight::zero() + } } } From 040e9e090503408daba375a07d139ae9cb418995 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Wed, 5 Aug 2026 13:54:24 +0200 Subject: [PATCH 25/58] fix: burn transaction fees instead of rewarding authors --- pallets/transaction-fee/src/lib.rs | 84 +++++------ pallets/transaction-fee/src/tests/burning.rs | 142 +++++++++++++++++++ pallets/transaction-fee/src/tests/mock.rs | 86 +++++------ pallets/transaction-fee/src/tests/mod.rs | 137 +++++++----------- runtime/tests/evm_transaction_fee.rs | 27 +++- 5 files changed, 285 insertions(+), 191 deletions(-) create mode 100644 pallets/transaction-fee/src/tests/burning.rs diff --git a/pallets/transaction-fee/src/lib.rs b/pallets/transaction-fee/src/lib.rs index c8415e4c5f..d6798035d8 100644 --- a/pallets/transaction-fee/src/lib.rs +++ b/pallets/transaction-fee/src/lib.rs @@ -21,7 +21,7 @@ use pallet_evm::{ // Runtime use sp_runtime::{ DispatchError, Perbill, Saturating, - traits::{DispatchInfoOf, PostDispatchInfoOf}, + traits::{AccountIdConversion, DispatchInfoOf, PostDispatchInfoOf}, transaction_validity::{InvalidTransaction, TransactionValidityError}, }; @@ -37,7 +37,7 @@ use smallvec::smallvec; use sp_core::H160; use sp_runtime::traits::SaturatedConversion; use sp_std::vec::Vec; -use subtensor_runtime_common::{AlphaBalance, AuthorshipInfo, NetUid, TaoBalance}; +use subtensor_runtime_common::{AlphaBalance, NetUid, TaoBalance}; // Tests #[cfg(test)] @@ -97,27 +97,21 @@ type BalancesImbalanceOf = FungibleImbalance< impl OnUnbalanced> for TransactionFeeHandler where - T: frame_system::Config - + pallet_balances::Config - + pallet_subtensor::Config - + AuthorshipInfo>, + T: frame_system::Config + pallet_balances::Config + pallet_subtensor::Config, ::Balance: Into + Copy, { fn on_nonzero_unbalanced(imbalance: BalancesImbalanceOf) { - if let Some(author) = T::author() { - // Pay block author - let _ = as Balanced<_>>::resolve(&author, imbalance); - } else { - // Fallback: if no author, burn (or just drop). - drop(imbalance); - } + let amount = imbalance.peek().into(); + pallet_subtensor::TotalIssuance::::mutate(|total| { + *total = total.saturating_sub(amount); + }); + drop(imbalance); } } /// Handle Alpha fees impl AlphaFeeHandler for TransactionFeeHandler where - T: AuthorshipInfo>, T: frame_system::Config, T: pallet_subtensor::Config, T: pallet_subtensor_swap::Config, @@ -184,34 +178,30 @@ where return Err(InvalidTransaction::Payment.into()); } - // Sell alpha_fee and burn received tao (ignore unstake_from_subnet return). - if let Some(author) = T::author() { - with_transaction( - || -> TransactionOutcome> { - match pallet_subtensor::Pallet::::unstake_from_subnet( - hotkey, - coldkey, - &author, - *netuid, - alpha_fee, - 0.into(), - true, - false, - ) { - Ok(tao_amount) => TransactionOutcome::Commit(Ok(tao_amount)), - Err(err) => TransactionOutcome::Rollback(Err(err)), - } - }, - ) - .map(|tao_amount| (alpha_fee, tao_amount, *netuid)) - .map_err(|err| { - log::warn!("Error withdrawing transaction fee in alpha: {err:?}"); - InvalidTransaction::Payment.into() - }) - } else { - // Fallback: no author => no fees (do nothing) - Ok((0.into(), 0.into(), NetUid::ROOT)) - } + // Sell the Alpha fee and send the resulting TAO to the burn account. + let burn_account: AccountIdOf = T::BurnAccountId::get().into_account_truncating(); + with_transaction( + || -> TransactionOutcome> { + match pallet_subtensor::Pallet::::unstake_from_subnet( + hotkey, + coldkey, + &burn_account, + *netuid, + alpha_fee, + 0.into(), + true, + false, + ) { + Ok(tao_amount) => TransactionOutcome::Commit(Ok(tao_amount)), + Err(err) => TransactionOutcome::Rollback(Err(err)), + } + }, + ) + .map(|tao_amount| (alpha_fee, tao_amount, *netuid)) + .map_err(|err| { + log::warn!("Error withdrawing transaction fee in alpha: {err:?}"); + InvalidTransaction::Payment.into() + }) } else { Ok((0.into(), 0.into(), NetUid::ROOT)) } @@ -257,7 +247,7 @@ impl SubtensorTxFeeHandler { /// distributed evenly between subnets in case of multiple subnets. pub fn fees_in_alpha(who: &AccountIdOf, call: &CallOf) -> Vec<(AccountIdOf, NetUid)> where - T: frame_system::Config + pallet_subtensor::Config + AuthorshipInfo>, + T: frame_system::Config + pallet_subtensor::Config, CallOf: IsSubType>, OU: AlphaFeeHandler, { @@ -362,7 +352,7 @@ impl SubtensorTxFeeHandler { impl OnChargeTransaction for SubtensorTxFeeHandler where - T: PTPConfig + pallet_subtensor::Config + AuthorshipInfo>, + T: PTPConfig + pallet_subtensor::Config, CallOf: IsSubType>, F: Balanced, OU: OnUnbalanced> + AlphaFeeHandler, @@ -465,7 +455,6 @@ where OU::on_unbalanceds(Some(fee).into_iter().chain(Some(tip))); } WithdrawnFee::Alpha((alpha_fee, tao_amount, netuid)) => { - // Block author already received the fee in withdraw_in_alpha, nothing to do here. frame_system::Pallet::::deposit_event( pallet_subtensor::Event::::TransactionFeePaidWithAlpha { who: who.clone(), @@ -560,10 +549,7 @@ where fn pay_priority_fee(tip: Self::LiquidityInfo) { if let Some(tip) = tip { - let author = >::into_account_id( - pallet_evm::Pallet::::find_author(), - ); - let _ = F::resolve(&author, tip); + OU::on_unbalanced(tip); } } } diff --git a/pallets/transaction-fee/src/tests/burning.rs b/pallets/transaction-fee/src/tests/burning.rs new file mode 100644 index 0000000000..e54811221d --- /dev/null +++ b/pallets/transaction-fee/src/tests/burning.rs @@ -0,0 +1,142 @@ +use super::mock::*; + +use frame_support::{assert_ok, dispatch::GetDispatchInfo, pallet_prelude::Zero}; +use sp_runtime::traits::{AccountIdConversion, DispatchTransaction}; +use subtensor_runtime_common::AlphaBalance; + +#[test] +fn tao_transaction_fees_are_burned() { + new_test_ext().execute_with(|| { + let payer = U256::from(42u64); + let block_builder = U256::from(MOCK_BLOCK_BUILDER); + add_balance_to_coldkey_account(&payer, TaoBalance::from(TAO)); + + let payer_balance_before = Balances::free_balance(payer); + let block_builder_balance_before = Balances::free_balance(block_builder); + let balances_issuance_before = Balances::total_issuance(); + let subtensor_issuance_before = SubtensorModule::get_total_issuance(); + assert_eq!(balances_issuance_before, subtensor_issuance_before); + + let call = RuntimeCall::System(frame_system::Call::remark { + remark: vec![0; 32], + }); + let info = call.get_dispatch_info(); + let ext = pallet_transaction_payment::ChargeTransactionPayment::::from( + TaoBalance::from(1_000u64), + ); + assert_ok!(ext.dispatch_transaction( + RuntimeOrigin::signed(payer).into(), + call, + &info, + 0, + 0, + )); + + let charged = payer_balance_before.saturating_sub(Balances::free_balance(payer)); + assert!(!charged.is_zero()); + assert_eq!( + Balances::free_balance(block_builder), + block_builder_balance_before + ); + assert_eq!( + balances_issuance_before.saturating_sub(Balances::total_issuance()), + charged + ); + assert_eq!( + subtensor_issuance_before.saturating_sub(SubtensorModule::get_total_issuance()), + charged + ); + }); +} + +#[test] +fn alpha_transaction_fees_are_burned_without_a_block_author() { + new_test_ext().execute_with(|| { + let stake_amount = TAO; + let unstake_amount = AlphaBalance::from(TAO / 50); + let setup = setup_subnets(1, 1); + let netuid = setup.subnets[0].netuid; + let hotkey = setup.hotkeys[0]; + setup_stake(netuid, &setup.coldkey, &hotkey, stake_amount); + + let current_balance = Balances::free_balance(setup.coldkey); + remove_balance_from_coldkey_account( + &setup.coldkey, + current_balance - ExistentialDeposit::get(), + ); + + let block_builder = U256::from(MOCK_BLOCK_BUILDER); + let block_builder_balance_before = Balances::free_balance(block_builder); + let burn_account: U256 = BurnAccountId::get().into_account_truncating(); + let burn_balance_before = Balances::free_balance(burn_account); + let balances_issuance_before = Balances::total_issuance(); + let subtensor_issuance_before = SubtensorModule::get_total_issuance(); + assert_eq!(balances_issuance_before, subtensor_issuance_before); + let alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &setup.coldkey, + netuid, + ); + + set_mock_block_author(None); + let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::remove_stake { + hotkey, + netuid, + amount_unstaked: unstake_amount, + }); + let info = call.get_dispatch_info(); + let ext = pallet_transaction_payment::ChargeTransactionPayment::::from(0.into()); + assert_ok!(ext.dispatch_transaction( + RuntimeOrigin::signed(setup.coldkey).into(), + call, + &info, + 0, + 0, + )); + + let alpha_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey, + &setup.coldkey, + netuid, + ); + let alpha_fee = alpha_before - alpha_after - unstake_amount; + assert!(!alpha_fee.is_zero()); + + let burned_tao = System::events() + .iter() + .find_map(|event_record| match &event_record.event { + RuntimeEvent::SubtensorModule(SubtensorEvent::TransactionFeePaidWithAlpha { + who, + netuid: event_netuid, + alpha_fee: event_alpha_fee, + tao_amount, + }) if who == &setup.coldkey + && *event_netuid == netuid + && *event_alpha_fee == alpha_fee => + { + Some(*tao_amount) + } + _ => None, + }) + .expect("expected TransactionFeePaidWithAlpha event"); + + assert!(!burned_tao.is_zero()); + assert_eq!( + Balances::free_balance(burn_account) - burn_balance_before, + burned_tao + ); + assert_eq!( + Balances::free_balance(block_builder), + block_builder_balance_before + ); + assert_eq!(Balances::total_issuance(), balances_issuance_before); + assert_eq!( + SubtensorModule::get_total_issuance(), + subtensor_issuance_before + ); + assert_eq!( + Balances::total_issuance(), + SubtensorModule::get_total_issuance() + ); + }); +} diff --git a/pallets/transaction-fee/src/tests/mock.rs b/pallets/transaction-fee/src/tests/mock.rs index a539e389fe..38373b7c0e 100644 --- a/pallets/transaction-fee/src/tests/mock.rs +++ b/pallets/transaction-fee/src/tests/mock.rs @@ -1,6 +1,7 @@ #![allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] use core::num::NonZeroU64; +use std::cell::RefCell; use crate::TransactionFeeHandler; use frame_support::pallet_prelude::Zero; @@ -142,15 +143,28 @@ pub struct MockAuthorshipProvider; pub const MOCK_BLOCK_BUILDER: u64 = 12345u64; +thread_local! { + static MOCK_BLOCK_AUTHOR: RefCell> = + RefCell::new(Some(U256::from(MOCK_BLOCK_BUILDER))); +} + +pub fn set_mock_block_author(author: Option) { + MOCK_BLOCK_AUTHOR.with(|mock_author| *mock_author.borrow_mut() = author); +} + +fn mock_block_author() -> Option { + MOCK_BLOCK_AUTHOR.with(|mock_author| *mock_author.borrow()) +} + impl AuthorshipInfo for MockAuthorshipProvider { fn author() -> Option { - Some(U256::from(MOCK_BLOCK_BUILDER)) + mock_block_author() } } impl AuthorshipInfo for Test { fn author() -> Option { - Some(U256::from(MOCK_BLOCK_BUILDER)) + mock_block_author() } } @@ -548,6 +562,7 @@ where // Build genesis storage according to the mock runtime. pub fn new_test_ext() -> sp_io::TestExternalities { sp_tracing::try_init_simple(); + set_mock_block_author(Some(U256::from(MOCK_BLOCK_BUILDER))); let t = frame_system::GenesisConfig::::default() .build_storage() .unwrap(); @@ -702,38 +717,6 @@ pub(crate) fn swap_alpha_to_tao(netuid: NetUid, alpha: AlphaBalance) -> (u64, u6 swap_alpha_to_tao_ext(netuid, alpha, false) } -pub(crate) fn swap_tao_to_alpha_ext( - netuid: NetUid, - tao: TaoBalance, - drop_fees: bool, -) -> (u64, u64) { - if netuid.is_root() { - return (tao.into(), 0); - } - - let order = GetAlphaForTao::::with_amount(tao); - let result = ::SwapInterface::swap( - netuid.into(), - order, - ::SwapInterface::max_price(), - drop_fees, - true, - ); - - assert_ok!(&result); - - let result = result.unwrap(); - - // we don't want to have silent 0 comparisons in tests - assert!(!result.amount_paid_out.is_zero()); - - (result.amount_paid_out.to_u64(), result.fee_paid.to_u64()) -} - -pub(crate) fn swap_tao_to_alpha(netuid: NetUid, tao: TaoBalance) -> (u64, u64) { - swap_tao_to_alpha_ext(netuid, tao, false) -} - #[allow(dead_code)] pub fn add_network(netuid: NetUid, tempo: u16) { SubtensorModule::init_new_network(netuid, tempo); @@ -833,9 +816,9 @@ pub(crate) fn quote_remove_stake_after_alpha_fee( hotkey: &U256, netuid: NetUid, alpha: AlphaBalance, -) -> (u64, u64) { +) -> u64 { if netuid.is_root() { - return (alpha.into(), 0); + return alpha.into(); } let call: RuntimeCall = RuntimeCall::SubtensorModule(pallet_subtensor::Call::remove_stake { @@ -847,17 +830,15 @@ pub(crate) fn quote_remove_stake_after_alpha_fee( let tao_fee = pallet_transaction_payment::Pallet::::compute_fee(0, &info, 0.into()); frame_support::storage::with_transaction( - || -> frame_support::storage::TransactionOutcome< - Result<(u64, u64), sp_runtime::DispatchError>, - > { - let alpha_balance = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid); - - let mut alpha_fee = - pallet_subtensor_swap::Pallet::::get_alpha_amount_for_tao( - netuid, - tao_fee.into(), - ); + || -> frame_support::storage::TransactionOutcome> { + let alpha_balance = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, coldkey, netuid, + ); + + let mut alpha_fee = pallet_subtensor_swap::Pallet::::get_alpha_amount_for_tao( + netuid, + tao_fee.into(), + ); if alpha_fee.is_zero() { alpha_fee = alpha_balance; @@ -878,14 +859,13 @@ pub(crate) fn quote_remove_stake_after_alpha_fee( )); } - let alpha_after_fee = - SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( - hotkey, coldkey, netuid, - ); + let alpha_after_fee = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + hotkey, coldkey, netuid, + ); let quoted_alpha = alpha.min(alpha_after_fee); - let quote = swap_alpha_to_tao(netuid, quoted_alpha); - frame_support::storage::TransactionOutcome::Rollback(Ok(quote)) + let (tao_amount, _) = swap_alpha_to_tao(netuid, quoted_alpha); + frame_support::storage::TransactionOutcome::Rollback(Ok(tao_amount)) }, ) .expect("transactional quote should not fail") diff --git a/pallets/transaction-fee/src/tests/mod.rs b/pallets/transaction-fee/src/tests/mod.rs index 92032aa73d..f77467c707 100644 --- a/pallets/transaction-fee/src/tests/mod.rs +++ b/pallets/transaction-fee/src/tests/mod.rs @@ -3,10 +3,9 @@ use crate::{AlphaFeeHandler, SubtensorTxFeeHandler, TransactionFeeHandler, Trans use approx::assert_abs_diff_eq; use frame_support::dispatch::GetDispatchInfo; use frame_support::pallet_prelude::Zero; -use frame_support::traits::Currency; use frame_support::{assert_err, assert_ok}; use sp_runtime::{ - traits::{DispatchTransaction, TransactionExtension, TxBaseImplication}, + traits::{AccountIdConversion, DispatchTransaction, TransactionExtension, TxBaseImplication}, transaction_validity::{InvalidTransaction, TransactionValidityError}, }; use substrate_fixed::types::U64F64; @@ -14,6 +13,7 @@ use subtensor_runtime_common::AlphaBalance; use subtensor_swap_interface::SwapHandler; use mock::*; +mod burning; mod mock; fn mark_collateral(netuid: NetUid, hotkey: &U256, coldkey: &U256, locked: AlphaBalance) { @@ -306,7 +306,7 @@ fn test_remove_stake_fees_alpha() { // Simulate stake removal to get how much TAO should we get for unstaked Alpha // after the alpha-fee pre-withdrawal has already moved the pool. - let (expected_unstaked_tao, swap_fee) = mock::quote_remove_stake_after_alpha_fee( + let expected_unstaked_tao = mock::quote_remove_stake_after_alpha_fee( &sn.coldkey, &sn.hotkeys[0], sn.subnets[0].netuid, @@ -320,9 +320,8 @@ fn test_remove_stake_fees_alpha() { current_balance - ExistentialDeposit::get(), ); - // Get the block builder balance - let block_builder = U256::from(MOCK_BLOCK_BUILDER); - let block_builder_balance_before = Balances::free_balance(block_builder); + let burn_account: U256 = BurnAccountId::get().into_account_truncating(); + let burn_balance_before = Balances::free_balance(burn_account); // Remove stake let balance_before = Balances::free_balance(sn.coldkey); @@ -365,33 +364,30 @@ fn test_remove_stake_fees_alpha() { assert_abs_diff_eq!(actual_tao_fee, 0.into(), epsilon = 10.into()); assert!(actual_alpha_fee > 0.into()); - // Assert that swapped TAO from alpha fee goes to block author - let block_builder_fee_portion = 1.; - let expected_block_builder_swap_reward = swap_fee as f64 * block_builder_fee_portion; - let expected_tx_fee = 14000.; // Use very low value (0.000014) for less test flakiness, value before we 10x tx fees - let block_builder_balance_after = Balances::free_balance(block_builder); - let actual_block_builder_reward = - block_builder_balance_after - block_builder_balance_before; - assert!( - u64::from(actual_block_builder_reward) as f64 - >= expected_block_builder_swap_reward + expected_tx_fee - ); - let events = System::events(); - let alpha_event = events + let (alpha_event, burned_tao) = events .iter() - .position(|event_record| { - matches!( - &event_record.event, - RuntimeEvent::SubtensorModule(SubtensorEvent::TransactionFeePaidWithAlpha { - who, - netuid, - alpha_fee, - tao_amount: _, - }) if who == &sn.coldkey && *alpha_fee == actual_alpha_fee && *netuid == sn.subnets[0].netuid - ) + .enumerate() + .find_map(|(index, event_record)| match &event_record.event { + RuntimeEvent::SubtensorModule(SubtensorEvent::TransactionFeePaidWithAlpha { + who, + netuid, + alpha_fee, + tao_amount, + }) if who == &sn.coldkey + && *alpha_fee == actual_alpha_fee + && *netuid == sn.subnets[0].netuid => + { + Some((index, *tao_amount)) + } + _ => None, }) .expect("expected TransactionFeePaidWithAlpha event"); + assert!(!burned_tao.is_zero()); + assert_eq!( + Balances::free_balance(burn_account) - burn_balance_before, + burned_tao + ); let tao_event = events .iter() .position(|event_record| { @@ -431,10 +427,16 @@ fn test_alpha_fee_withdraw_failure_aborts_and_rolls_back() { // Force the alpha-fee unstake to fail after AMM bookkeeping by draining // the subnet account used by transfer_tao_from_subnet. let subnet_account = SubtensorModule::get_subnet_account_id(netuid).unwrap(); - Balances::make_free_balance_be(&subnet_account, 0.into()); + let subnet_balance = Balances::free_balance(subnet_account); + assert_ok!(SubtensorModule::burn_tao(&subnet_account, subnet_balance)); let block_builder = U256::from(MOCK_BLOCK_BUILDER); + let burn_account: U256 = BurnAccountId::get().into_account_truncating(); let block_builder_balance_before = Balances::free_balance(block_builder); + let burn_balance_before = Balances::free_balance(burn_account); + let balances_issuance_before = Balances::total_issuance(); + let subtensor_issuance_before = SubtensorModule::get_total_issuance(); + assert_eq!(balances_issuance_before, subtensor_issuance_before); let signer_balance_before = Balances::free_balance(sn.coldkey); let alpha_before = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, @@ -480,6 +482,16 @@ fn test_alpha_fee_withdraw_failure_aborts_and_rolls_back() { Balances::free_balance(block_builder), block_builder_balance_before ); + assert_eq!(Balances::free_balance(burn_account), burn_balance_before); + assert_eq!(Balances::total_issuance(), balances_issuance_before); + assert_eq!( + SubtensorModule::get_total_issuance(), + subtensor_issuance_before + ); + assert_eq!( + Balances::total_issuance(), + SubtensorModule::get_total_issuance() + ); assert!(!System::events().iter().any(|event_record| { matches!( @@ -1737,59 +1749,6 @@ fn test_recycle_alpha_fees_alpha() { }); } -// cargo test --package subtensor-transaction-fee --lib -- tests::test_add_stake_fees_go_to_block_builder --exact --show-output -#[test] -fn test_add_stake_fees_go_to_block_builder() { - new_test_ext().execute_with(|| { - // Portion of swap fees that should go to the block builder - let block_builder_fee_portion = 1.; - - // Get the block builder balance - let block_builder = U256::from(MOCK_BLOCK_BUILDER); - let block_builder_balance_before = Balances::free_balance(block_builder); - - let stake_amount = TAO; - let sn = setup_subnets(1, 1); - - // Simulate add stake to get the expected TAO fee - let (_, swap_fee) = mock::swap_tao_to_alpha(sn.subnets[0].netuid, stake_amount.into()); - - add_balance_to_coldkey_account(&sn.coldkey, (stake_amount * 10).into()); - - // Stake - let balance_before = Balances::free_balance(sn.coldkey); - let call = RuntimeCall::SubtensorModule(pallet_subtensor::Call::add_stake { - hotkey: sn.hotkeys[0], - netuid: sn.subnets[0].netuid, - amount_staked: stake_amount.into(), - }); - - // Dispatch the extrinsic with ChargeTransactionPayment extension - let info = call.get_dispatch_info(); - let ext = pallet_transaction_payment::ChargeTransactionPayment::::from(0.into()); - assert_ok!(ext.dispatch_transaction( - RuntimeOrigin::signed(sn.coldkey).into(), - call, - &info, - 0, - 0, - )); - - let final_balance = Balances::free_balance(sn.coldkey); - let actual_tao_fee = balance_before - stake_amount.into() - final_balance; - assert!(!actual_tao_fee.is_zero()); - - // Expect that block builder balance has increased by both the swap fee and the transaction fee - let expected_block_builder_swap_reward = swap_fee as f64 * block_builder_fee_portion; - let expected_tx_fee = 14000.; // Use very low value (0.000014) for less test flakiness, value before we 10x tx fees - let block_builder_balance_after = Balances::free_balance(block_builder); - let actual_reward = block_builder_balance_after - block_builder_balance_before; - assert!( - u64::from(actual_reward) as f64 >= expected_block_builder_swap_reward + expected_tx_fee - ); - }); -} - // Fully collateral-bonded stake must not pay alpha fees. Regression for the // phantom-bond bug where fee unstake stripped stake while MinerCollateral.locked // stayed unchanged. @@ -1941,10 +1900,14 @@ fn test_alpha_fee_only_from_free_stake_above_collateral() { ) ); + let block_builder = U256::from(MOCK_BLOCK_BUILDER); + let burn_account: U256 = BurnAccountId::get().into_account_truncating(); + let block_builder_balance_before = Balances::free_balance(block_builder); + let burn_balance_before = Balances::free_balance(burn_account); let collateral_before = MinerCollateral::::get((netuid, hotkey, sn.coldkey)) .expect("collateral entry") .locked; - let (taken, _tao_out, fee_netuid) = + let (taken, tao_out, fee_netuid) = as AlphaFeeHandler>::withdraw_in_alpha( &sn.coldkey, &alpha_vec, @@ -1953,6 +1916,12 @@ fn test_alpha_fee_only_from_free_stake_above_collateral() { .expect("free-slice fee should withdraw"); assert_eq!(fee_netuid, netuid); assert_eq!(taken, alpha_for_small); + assert!(!tao_out.is_zero()); + assert_eq!(Balances::free_balance(block_builder), block_builder_balance_before); + assert_eq!( + Balances::free_balance(burn_account).saturating_sub(burn_balance_before), + tao_out + ); let alpha_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, diff --git a/runtime/tests/evm_transaction_fee.rs b/runtime/tests/evm_transaction_fee.rs index 19cab4c77d..7a935b09f8 100644 --- a/runtime/tests/evm_transaction_fee.rs +++ b/runtime/tests/evm_transaction_fee.rs @@ -38,7 +38,7 @@ fn initialize_block_with_aura_authority(authority: AuraId, slot: u64) { } #[test] -fn evm_fee_refund_does_not_change_total_issuance() { +fn evm_fees_are_burned_without_total_issuance_drift() { new_test_ext().execute_with(|| { initialize_block_with_aura_authority(AuraId::from(sr25519::Public::from_raw([1u8; 32])), 0); @@ -59,6 +59,8 @@ fn evm_fee_refund_does_not_change_total_issuance() { let balances_issuance_before = Balances::total_issuance(); let subtensor_issuance_before = pallet_subtensor::Pallet::::get_total_issuance(); let balance_before = Balances::total_balance(&account_id); + let substrate_author_balance_before = Balances::total_balance(&substrate_author); + let evm_author_balance_before = Balances::total_balance(&evm_author); assert_eq!(balances_issuance_before, subtensor_issuance_before); @@ -82,13 +84,28 @@ fn evm_fee_refund_does_not_change_total_issuance() { Runtime, >>::pay_priority_fee(tip); - assert_eq!( - Balances::total_issuance(), - pallet_subtensor::Pallet::::get_total_issuance() - ); + let balances_issuance_after = Balances::total_issuance(); + let subtensor_issuance_after = pallet_subtensor::Pallet::::get_total_issuance(); + assert_eq!(balances_issuance_after, subtensor_issuance_after); assert_eq!( Balances::total_balance(&account_id), balance_before - TaoBalance::from(5) ); + assert_eq!( + balances_issuance_before - balances_issuance_after, + TaoBalance::from(5) + ); + assert_eq!( + subtensor_issuance_before - subtensor_issuance_after, + TaoBalance::from(5) + ); + assert_eq!( + Balances::total_balance(&substrate_author), + substrate_author_balance_before + ); + assert_eq!( + Balances::total_balance(&evm_author), + evm_author_balance_before + ); }); } From 40dd1f10823c7dcd0e6bee018c40eaabc686c80b Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Wed, 5 Aug 2026 18:35:01 +0200 Subject: [PATCH 26/58] chore: apply workspace rustfmt --- pallets/subtensor/src/tests/stake_into_basket.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pallets/subtensor/src/tests/stake_into_basket.rs b/pallets/subtensor/src/tests/stake_into_basket.rs index a265d1d1e7..c937059598 100644 --- a/pallets/subtensor/src/tests/stake_into_basket.rs +++ b/pallets/subtensor/src/tests/stake_into_basket.rs @@ -577,11 +577,7 @@ fn test_root_slot_yield_accrues_to_share_holders() { // Bob buys in directly: all-root basket at N/P = 1, so his TAO mints 1:1 exactly. let b = 10_000_000u64; add_balance_to_coldkey_account(&bob, TaoBalance::from(2 * b)); - assert_ok!(SubtensorModule::do_stake_into_basket( - bob, - hotkey, - b.into(), - )); + assert_ok!(SubtensorModule::do_stake_into_basket(bob, hotkey, b.into(),)); assert_eq!(SubtensorModule::get_basket_owed_shares(&hotkey, &bob), b); let bob_payout_before = SubtensorModule::get_basket_payout_tao(&hotkey, &bob); assert_eq!(bob_payout_before, b, "N/P = 1: payout == shares == TAO in"); From e6c7ca56a9054ba4cccf9730fdea498ba570dac1 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Wed, 5 Aug 2026 18:44:14 +0200 Subject: [PATCH 27/58] fix: recycle alpha-paid transaction fees --- pallets/transaction-fee/src/lib.rs | 27 +++++++++++--- pallets/transaction-fee/src/tests/mod.rs | 36 +++++++++++++++---- .../src/tests/{burning.rs => recycling.rs} | 28 +++++++-------- runtime/tests/evm_transaction_fee.rs | 2 +- 4 files changed, 66 insertions(+), 27 deletions(-) rename pallets/transaction-fee/src/tests/{burning.rs => recycling.rs} (88%) diff --git a/pallets/transaction-fee/src/lib.rs b/pallets/transaction-fee/src/lib.rs index d6798035d8..26b061ea82 100644 --- a/pallets/transaction-fee/src/lib.rs +++ b/pallets/transaction-fee/src/lib.rs @@ -21,7 +21,7 @@ use pallet_evm::{ // Runtime use sp_runtime::{ DispatchError, Perbill, Saturating, - traits::{AccountIdConversion, DispatchInfoOf, PostDispatchInfoOf}, + traits::{DispatchInfoOf, PostDispatchInfoOf}, transaction_validity::{InvalidTransaction, TransactionValidityError}, }; @@ -178,21 +178,38 @@ where return Err(InvalidTransaction::Payment.into()); } - // Sell the Alpha fee and send the resulting TAO to the burn account. - let burn_account: AccountIdOf = T::BurnAccountId::get().into_account_truncating(); + // Sell the Alpha fee and recycle the resulting TAO directly from the subnet + // account. This avoids relying on the payer having enough TAO to keep an account + // alive. Keeping both operations in one storage transaction ensures that a failure + // to recycle the TAO also rolls back the Alpha withdrawal and AMM updates. with_transaction( || -> TransactionOutcome> { + let Some(subnet_account) = + pallet_subtensor::Pallet::::get_subnet_account_id(*netuid) + else { + return TransactionOutcome::Rollback(Err( + pallet_subtensor::Error::::SubnetNotExists.into(), + )); + }; match pallet_subtensor::Pallet::::unstake_from_subnet( hotkey, coldkey, - &burn_account, + &subnet_account, *netuid, alpha_fee, 0.into(), true, false, ) { - Ok(tao_amount) => TransactionOutcome::Commit(Ok(tao_amount)), + Ok(tao_amount) => { + match pallet_subtensor::Pallet::::recycle_tao( + &subnet_account, + tao_amount, + ) { + Ok(()) => TransactionOutcome::Commit(Ok(tao_amount)), + Err(err) => TransactionOutcome::Rollback(Err(err)), + } + } Err(err) => TransactionOutcome::Rollback(Err(err)), } }, diff --git a/pallets/transaction-fee/src/tests/mod.rs b/pallets/transaction-fee/src/tests/mod.rs index f77467c707..b8156cd6c8 100644 --- a/pallets/transaction-fee/src/tests/mod.rs +++ b/pallets/transaction-fee/src/tests/mod.rs @@ -13,8 +13,8 @@ use subtensor_runtime_common::AlphaBalance; use subtensor_swap_interface::SwapHandler; use mock::*; -mod burning; mod mock; +mod recycling; fn mark_collateral(netuid: NetUid, hotkey: &U256, coldkey: &U256, locked: AlphaBalance) { MinerCollateral::::insert( @@ -322,6 +322,9 @@ fn test_remove_stake_fees_alpha() { let burn_account: U256 = BurnAccountId::get().into_account_truncating(); let burn_balance_before = Balances::free_balance(burn_account); + let balances_issuance_before = Balances::total_issuance(); + let subtensor_issuance_before = SubtensorModule::get_total_issuance(); + assert_eq!(balances_issuance_before, subtensor_issuance_before); // Remove stake let balance_before = Balances::free_balance(sn.coldkey); @@ -365,7 +368,7 @@ fn test_remove_stake_fees_alpha() { assert!(actual_alpha_fee > 0.into()); let events = System::events(); - let (alpha_event, burned_tao) = events + let (alpha_event, recycled_tao) = events .iter() .enumerate() .find_map(|(index, event_record)| match &event_record.event { @@ -383,10 +386,19 @@ fn test_remove_stake_fees_alpha() { _ => None, }) .expect("expected TransactionFeePaidWithAlpha event"); - assert!(!burned_tao.is_zero()); + assert!(!recycled_tao.is_zero()); + assert_eq!(Balances::free_balance(burn_account), burn_balance_before); + assert_eq!( + balances_issuance_before - Balances::total_issuance(), + recycled_tao + ); assert_eq!( - Balances::free_balance(burn_account) - burn_balance_before, - burned_tao + subtensor_issuance_before - SubtensorModule::get_total_issuance(), + recycled_tao + ); + assert_eq!( + Balances::total_issuance(), + SubtensorModule::get_total_issuance() ); let tao_event = events .iter() @@ -1904,6 +1916,9 @@ fn test_alpha_fee_only_from_free_stake_above_collateral() { let burn_account: U256 = BurnAccountId::get().into_account_truncating(); let block_builder_balance_before = Balances::free_balance(block_builder); let burn_balance_before = Balances::free_balance(burn_account); + let balances_issuance_before = Balances::total_issuance(); + let subtensor_issuance_before = SubtensorModule::get_total_issuance(); + assert_eq!(balances_issuance_before, subtensor_issuance_before); let collateral_before = MinerCollateral::::get((netuid, hotkey, sn.coldkey)) .expect("collateral entry") .locked; @@ -1918,10 +1933,19 @@ fn test_alpha_fee_only_from_free_stake_above_collateral() { assert_eq!(taken, alpha_for_small); assert!(!tao_out.is_zero()); assert_eq!(Balances::free_balance(block_builder), block_builder_balance_before); + assert_eq!(Balances::free_balance(burn_account), burn_balance_before); + assert_eq!( + balances_issuance_before - Balances::total_issuance(), + tao_out + ); assert_eq!( - Balances::free_balance(burn_account).saturating_sub(burn_balance_before), + subtensor_issuance_before - SubtensorModule::get_total_issuance(), tao_out ); + assert_eq!( + Balances::total_issuance(), + SubtensorModule::get_total_issuance() + ); let alpha_after = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( &hotkey, diff --git a/pallets/transaction-fee/src/tests/burning.rs b/pallets/transaction-fee/src/tests/recycling.rs similarity index 88% rename from pallets/transaction-fee/src/tests/burning.rs rename to pallets/transaction-fee/src/tests/recycling.rs index e54811221d..d196f84ceb 100644 --- a/pallets/transaction-fee/src/tests/burning.rs +++ b/pallets/transaction-fee/src/tests/recycling.rs @@ -5,7 +5,7 @@ use sp_runtime::traits::{AccountIdConversion, DispatchTransaction}; use subtensor_runtime_common::AlphaBalance; #[test] -fn tao_transaction_fees_are_burned() { +fn tao_transaction_fees_are_recycled() { new_test_ext().execute_with(|| { let payer = U256::from(42u64); let block_builder = U256::from(MOCK_BLOCK_BUILDER); @@ -50,7 +50,7 @@ fn tao_transaction_fees_are_burned() { } #[test] -fn alpha_transaction_fees_are_burned_without_a_block_author() { +fn alpha_transaction_fees_are_recycled_without_a_block_author() { new_test_ext().execute_with(|| { let stake_amount = TAO; let unstake_amount = AlphaBalance::from(TAO / 50); @@ -60,10 +60,8 @@ fn alpha_transaction_fees_are_burned_without_a_block_author() { setup_stake(netuid, &setup.coldkey, &hotkey, stake_amount); let current_balance = Balances::free_balance(setup.coldkey); - remove_balance_from_coldkey_account( - &setup.coldkey, - current_balance - ExistentialDeposit::get(), - ); + remove_balance_from_coldkey_account(&setup.coldkey, current_balance); + assert_eq!(Balances::free_balance(setup.coldkey), TaoBalance::ZERO); let block_builder = U256::from(MOCK_BLOCK_BUILDER); let block_builder_balance_before = Balances::free_balance(block_builder); @@ -102,7 +100,7 @@ fn alpha_transaction_fees_are_burned_without_a_block_author() { let alpha_fee = alpha_before - alpha_after - unstake_amount; assert!(!alpha_fee.is_zero()); - let burned_tao = System::events() + let recycled_tao = System::events() .iter() .find_map(|event_record| match &event_record.event { RuntimeEvent::SubtensorModule(SubtensorEvent::TransactionFeePaidWithAlpha { @@ -120,19 +118,19 @@ fn alpha_transaction_fees_are_burned_without_a_block_author() { }) .expect("expected TransactionFeePaidWithAlpha event"); - assert!(!burned_tao.is_zero()); - assert_eq!( - Balances::free_balance(burn_account) - burn_balance_before, - burned_tao - ); + assert!(!recycled_tao.is_zero()); + assert_eq!(Balances::free_balance(burn_account), burn_balance_before); assert_eq!( Balances::free_balance(block_builder), block_builder_balance_before ); - assert_eq!(Balances::total_issuance(), balances_issuance_before); assert_eq!( - SubtensorModule::get_total_issuance(), - subtensor_issuance_before + balances_issuance_before - Balances::total_issuance(), + recycled_tao + ); + assert_eq!( + subtensor_issuance_before - SubtensorModule::get_total_issuance(), + recycled_tao ); assert_eq!( Balances::total_issuance(), diff --git a/runtime/tests/evm_transaction_fee.rs b/runtime/tests/evm_transaction_fee.rs index 7a935b09f8..9f10e1e538 100644 --- a/runtime/tests/evm_transaction_fee.rs +++ b/runtime/tests/evm_transaction_fee.rs @@ -38,7 +38,7 @@ fn initialize_block_with_aura_authority(authority: AuraId, slot: u64) { } #[test] -fn evm_fees_are_burned_without_total_issuance_drift() { +fn evm_fees_are_recycled_without_total_issuance_drift() { new_test_ext().execute_with(|| { initialize_block_with_aura_authority(AuraId::from(sr25519::Public::from_raw([1u8; 32])), 0); From 61df032cce37b77b8336a7c8c7b56585cfa9b7d7 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Wed, 5 Aug 2026 19:48:16 +0200 Subject: [PATCH 28/58] chore: bump runtime spec version to 444 --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 27fe5f0c2c..36bb308c5e 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -235,7 +235,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 443, + spec_version: 444, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From a15d632e52929af1f3d1d9fcb88f5d71463307f5 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Wed, 5 Aug 2026 21:57:28 +0200 Subject: [PATCH 29/58] chore: refresh SDK metadata for spec 444 --- sdk/python/bittensor/_generated/calls.py | 2 +- sdk/python/bittensor/_generated/constants.py | 2 +- sdk/python/bittensor/_generated/errors.py | 2 +- sdk/python/bittensor/_generated/runtime_apis.py | 2 +- sdk/python/bittensor/_generated/storage.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/python/bittensor/_generated/calls.py b/sdk/python/bittensor/_generated/calls.py index 0bd9eb25c7..0ac4793935 100644 --- a/sdk/python/bittensor/_generated/calls.py +++ b/sdk/python/bittensor/_generated/calls.py @@ -1,7 +1,7 @@ """Generated from runtime metadata by codegen. DO NOT EDIT BY HAND. Regenerate with: python -m codegen -Spec version: 442 +Spec version: 444 """ from typing import Any, NamedTuple diff --git a/sdk/python/bittensor/_generated/constants.py b/sdk/python/bittensor/_generated/constants.py index 58f5e0356f..27276d9970 100644 --- a/sdk/python/bittensor/_generated/constants.py +++ b/sdk/python/bittensor/_generated/constants.py @@ -1,7 +1,7 @@ """Generated from runtime metadata by codegen. DO NOT EDIT BY HAND. Regenerate with: python -m codegen -Spec version: 442 +Spec version: 444 Pallet constant descriptors: unpack into substrate.constant. """ diff --git a/sdk/python/bittensor/_generated/errors.py b/sdk/python/bittensor/_generated/errors.py index 059cfb7e0d..4417a3fe36 100644 --- a/sdk/python/bittensor/_generated/errors.py +++ b/sdk/python/bittensor/_generated/errors.py @@ -1,7 +1,7 @@ """Generated from runtime metadata by codegen. DO NOT EDIT BY HAND. Regenerate with: python -m codegen -Spec version: 442 +Spec version: 444 """ from dataclasses import dataclass diff --git a/sdk/python/bittensor/_generated/runtime_apis.py b/sdk/python/bittensor/_generated/runtime_apis.py index 0260b37d05..0408cfabc3 100644 --- a/sdk/python/bittensor/_generated/runtime_apis.py +++ b/sdk/python/bittensor/_generated/runtime_apis.py @@ -1,7 +1,7 @@ """Generated from runtime metadata by codegen. DO NOT EDIT BY HAND. Regenerate with: python -m codegen -Spec version: 442 +Spec version: 444 Runtime API method descriptors: unpack into substrate.runtime_call. """ diff --git a/sdk/python/bittensor/_generated/storage.py b/sdk/python/bittensor/_generated/storage.py index dd1d3e9baf..06be5cec81 100644 --- a/sdk/python/bittensor/_generated/storage.py +++ b/sdk/python/bittensor/_generated/storage.py @@ -1,7 +1,7 @@ """Generated from runtime metadata by codegen. DO NOT EDIT BY HAND. Regenerate with: python -m codegen -Spec version: 442 +Spec version: 444 Storage item descriptors: unpack into substrate.query/query_map. Each carries its VALUE's type identity (value_type_ident) so normalization can key on the runtime's own type names without a node round-trip. """ From 6c49a11870ba44c09126f5cb0e2fcd23d25b87e0 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Thu, 6 Aug 2026 00:49:05 +0200 Subject: [PATCH 30/58] docs: refresh generated transaction links --- docs/tx/add-collateral.mdx | 4 +- docs/tx/announce-coldkey-swap.mdx | 4 +- docs/tx/clear-coldkey-swap-announcement.mdx | 4 +- docs/tx/dispute-coldkey-swap.mdx | 4 +- docs/tx/lock-stake.mdx | 4 +- docs/tx/move-lock.mdx | 4 +- docs/tx/set-min-collateral.mdx | 4 +- docs/tx/set-perpetual-lock.mdx | 4 +- docs/tx/set-root-claim-threshold.mdx | 4 +- docs/tx/stake-burn.mdx | 4 +- docs/tx/swap-coldkey-announced.mdx | 4 +- docs/tx/transfer-stake.mdx | 4 +- .../public/catalog/intents.json | 72 +++++++++---------- 13 files changed, 60 insertions(+), 60 deletions(-) diff --git a/docs/tx/add-collateral.mdx b/docs/tx/add-collateral.mdx index 4b0df0a517..60bcc2c489 100644 --- a/docs/tx/add-collateral.mdx +++ b/docs/tx/add-collateral.mdx @@ -23,7 +23,7 @@ to clear unshielded at an unbounded AMM price. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.add_collateral`](/code/pallets/subtensor/src/macros/dispatches.rs#L2524-L2534) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.add_collateral`](/code/pallets/subtensor/src/macros/dispatches.rs#L2529-L2539) | ## Parameters @@ -77,7 +77,7 @@ result = sub.execute_tool("add_collateral", {...}, wallet) ## On-chain implementation -`SubtensorModule.add_collateral` — [`pallets/subtensor/src/macros/dispatches.rs#L2526`](/code/pallets/subtensor/src/macros/dispatches.rs#L2524-L2534): +`SubtensorModule.add_collateral` — [`pallets/subtensor/src/macros/dispatches.rs#L2531`](/code/pallets/subtensor/src/macros/dispatches.rs#L2529-L2539): ```rust #[pallet::call_index(144)] diff --git a/docs/tx/announce-coldkey-swap.mdx b/docs/tx/announce-coldkey-swap.mdx index d269770ffd..e17b2bfe51 100644 --- a/docs/tx/announce-coldkey-swap.mdx +++ b/docs/tx/announce-coldkey-swap.mdx @@ -23,7 +23,7 @@ an unauthorized one with `dispute_coldkey_swap`. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.announce_coldkey_swap`](/code/pallets/subtensor/src/macros/dispatches.rs#L2060-L2088) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.announce_coldkey_swap`](/code/pallets/subtensor/src/macros/dispatches.rs#L2065-L2093) | ## Parameters @@ -72,7 +72,7 @@ result = sub.execute_tool("announce_coldkey_swap", {...}, wallet) ## On-chain implementation -`SubtensorModule.announce_coldkey_swap` — [`pallets/subtensor/src/macros/dispatches.rs#L2062`](/code/pallets/subtensor/src/macros/dispatches.rs#L2060-L2088): +`SubtensorModule.announce_coldkey_swap` — [`pallets/subtensor/src/macros/dispatches.rs#L2067`](/code/pallets/subtensor/src/macros/dispatches.rs#L2065-L2093): ```rust #[pallet::call_index(125)] diff --git a/docs/tx/clear-coldkey-swap-announcement.mdx b/docs/tx/clear-coldkey-swap-announcement.mdx index 70f1bbac90..44dfdb44fd 100644 --- a/docs/tx/clear-coldkey-swap-announcement.mdx +++ b/docs/tx/clear-coldkey-swap-announcement.mdx @@ -17,7 +17,7 @@ right call instead. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.clear_coldkey_swap_announcement`](/code/pallets/subtensor/src/macros/dispatches.rs#L2259-L2276) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.clear_coldkey_swap_announcement`](/code/pallets/subtensor/src/macros/dispatches.rs#L2264-L2281) | ## Parameters @@ -62,7 +62,7 @@ result = sub.execute_tool("clear_coldkey_swap_announcement", {...}, wallet) ## On-chain implementation -`SubtensorModule.clear_coldkey_swap_announcement` — [`pallets/subtensor/src/macros/dispatches.rs#L2261`](/code/pallets/subtensor/src/macros/dispatches.rs#L2259-L2276): +`SubtensorModule.clear_coldkey_swap_announcement` — [`pallets/subtensor/src/macros/dispatches.rs#L2266`](/code/pallets/subtensor/src/macros/dispatches.rs#L2264-L2281): ```rust #[pallet::call_index(133)] diff --git a/docs/tx/dispute-coldkey-swap.mdx b/docs/tx/dispute-coldkey-swap.mdx index 27d224886d..9fb6580740 100644 --- a/docs/tx/dispute-coldkey-swap.mdx +++ b/docs/tx/dispute-coldkey-swap.mdx @@ -18,7 +18,7 @@ you made yourself. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.dispute_coldkey_swap`](/code/pallets/subtensor/src/macros/dispatches.rs#L2129-L2148) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.dispute_coldkey_swap`](/code/pallets/subtensor/src/macros/dispatches.rs#L2134-L2153) | ## Parameters @@ -63,7 +63,7 @@ result = sub.execute_tool("dispute_coldkey_swap", {...}, wallet) ## On-chain implementation -`SubtensorModule.dispute_coldkey_swap` — [`pallets/subtensor/src/macros/dispatches.rs#L2131`](/code/pallets/subtensor/src/macros/dispatches.rs#L2129-L2148): +`SubtensorModule.dispute_coldkey_swap` — [`pallets/subtensor/src/macros/dispatches.rs#L2136`](/code/pallets/subtensor/src/macros/dispatches.rs#L2134-L2153): ```rust #[pallet::call_index(127)] diff --git a/docs/tx/lock-stake.mdx b/docs/tx/lock-stake.mdx index 1faf267199..116ebc9436 100644 --- a/docs/tx/lock-stake.mdx +++ b/docs/tx/lock-stake.mdx @@ -21,7 +21,7 @@ persists is controlled per coldkey per subnet with | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.lock_stake`](/code/pallets/subtensor/src/macros/dispatches.rs#L2331-L2341) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.lock_stake`](/code/pallets/subtensor/src/macros/dispatches.rs#L2336-L2346) | ## Parameters @@ -74,7 +74,7 @@ result = sub.execute_tool("lock_stake", {...}, wallet) ## On-chain implementation -`SubtensorModule.lock_stake` — [`pallets/subtensor/src/macros/dispatches.rs#L2333`](/code/pallets/subtensor/src/macros/dispatches.rs#L2331-L2341): +`SubtensorModule.lock_stake` — [`pallets/subtensor/src/macros/dispatches.rs#L2338`](/code/pallets/subtensor/src/macros/dispatches.rs#L2336-L2346): ```rust #[pallet::call_index(136)] diff --git a/docs/tx/move-lock.mdx b/docs/tx/move-lock.mdx index 5b481063cb..9b4d629454 100644 --- a/docs/tx/move-lock.mdx +++ b/docs/tx/move-lock.mdx @@ -16,7 +16,7 @@ existing lock on the subnet to move. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.move_lock`](/code/pallets/subtensor/src/macros/dispatches.rs#L2355-L2364) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.move_lock`](/code/pallets/subtensor/src/macros/dispatches.rs#L2360-L2369) | ## Parameters @@ -68,7 +68,7 @@ result = sub.execute_tool("move_lock", {...}, wallet) ## On-chain implementation -`SubtensorModule.move_lock` — [`pallets/subtensor/src/macros/dispatches.rs#L2357`](/code/pallets/subtensor/src/macros/dispatches.rs#L2355-L2364): +`SubtensorModule.move_lock` — [`pallets/subtensor/src/macros/dispatches.rs#L2362`](/code/pallets/subtensor/src/macros/dispatches.rs#L2360-L2369): ```rust #[pallet::call_index(137)] diff --git a/docs/tx/set-min-collateral.mdx b/docs/tx/set-min-collateral.mdx index 7b5661ff15..da556306ad 100644 --- a/docs/tx/set-min-collateral.mdx +++ b/docs/tx/set-min-collateral.mdx @@ -15,7 +15,7 @@ immediately). Zero clears the floor and restores pure drain behavior. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.set_min_collateral`](/code/pallets/subtensor/src/macros/dispatches.rs#L2559-L2568) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.set_min_collateral`](/code/pallets/subtensor/src/macros/dispatches.rs#L2564-L2573) | ## Parameters @@ -68,7 +68,7 @@ result = sub.execute_tool("set_min_collateral", {...}, wallet) ## On-chain implementation -`SubtensorModule.set_min_collateral` — [`pallets/subtensor/src/macros/dispatches.rs#L2561`](/code/pallets/subtensor/src/macros/dispatches.rs#L2559-L2568): +`SubtensorModule.set_min_collateral` — [`pallets/subtensor/src/macros/dispatches.rs#L2566`](/code/pallets/subtensor/src/macros/dispatches.rs#L2564-L2573): ```rust #[pallet::call_index(145)] diff --git a/docs/tx/set-perpetual-lock.mdx b/docs/tx/set-perpetual-lock.mdx index f2d824afe3..a82dccdf2d 100644 --- a/docs/tx/set-perpetual-lock.mdx +++ b/docs/tx/set-perpetual-lock.mdx @@ -15,7 +15,7 @@ illiquid until you switch back to decaying and the lock runs off. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.set_perpetual_lock`](/code/pallets/subtensor/src/macros/dispatches.rs#L2371-L2380) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.set_perpetual_lock`](/code/pallets/subtensor/src/macros/dispatches.rs#L2376-L2385) | ## Parameters @@ -67,7 +67,7 @@ result = sub.execute_tool("set_perpetual_lock", {...}, wallet) ## On-chain implementation -`SubtensorModule.set_perpetual_lock` — [`pallets/subtensor/src/macros/dispatches.rs#L2373`](/code/pallets/subtensor/src/macros/dispatches.rs#L2371-L2380): +`SubtensorModule.set_perpetual_lock` — [`pallets/subtensor/src/macros/dispatches.rs#L2378`](/code/pallets/subtensor/src/macros/dispatches.rs#L2376-L2385): ```rust #[pallet::call_index(138)] diff --git a/docs/tx/set-root-claim-threshold.mdx b/docs/tx/set-root-claim-threshold.mdx index 933695c737..277ac3b93f 100644 --- a/docs/tx/set-root-claim-threshold.mdx +++ b/docs/tx/set-root-claim-threshold.mdx @@ -19,7 +19,7 @@ effect afterwards with the `root_claim_threshold` read. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | root (chain sudo) | SubtensorModule | [`SubtensorModule.sudo_set_root_claim_threshold`](/code/pallets/subtensor/src/macros/dispatches.rs#L2023-L2044), `Sudo.sudo` | +| `coldkey` | root (chain sudo) | SubtensorModule | [`SubtensorModule.sudo_set_root_claim_threshold`](/code/pallets/subtensor/src/macros/dispatches.rs#L2028-L2049), `Sudo.sudo` | ## Verify @@ -77,7 +77,7 @@ result = sub.execute_tool("set_root_claim_threshold", {...}, wallet) ## On-chain implementation -`SubtensorModule.sudo_set_root_claim_threshold` — [`pallets/subtensor/src/macros/dispatches.rs#L2025`](/code/pallets/subtensor/src/macros/dispatches.rs#L2023-L2044): +`SubtensorModule.sudo_set_root_claim_threshold` — [`pallets/subtensor/src/macros/dispatches.rs#L2030`](/code/pallets/subtensor/src/macros/dispatches.rs#L2028-L2049): ```rust #[pallet::call_index(124)] diff --git a/docs/tx/stake-burn.mdx b/docs/tx/stake-burn.mdx index 5e7a69b5f6..aafd47b7ac 100644 --- a/docs/tx/stake-burn.mdx +++ b/docs/tx/stake-burn.mdx @@ -18,7 +18,7 @@ cap. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.add_stake_burn`](/code/pallets/subtensor/src/macros/dispatches.rs#L2243-L2253) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.add_stake_burn`](/code/pallets/subtensor/src/macros/dispatches.rs#L2248-L2258) | ## Parameters @@ -74,7 +74,7 @@ result = sub.execute_tool("stake_burn", {...}, wallet) ## On-chain implementation -`SubtensorModule.add_stake_burn` — [`pallets/subtensor/src/macros/dispatches.rs#L2245`](/code/pallets/subtensor/src/macros/dispatches.rs#L2243-L2253): +`SubtensorModule.add_stake_burn` — [`pallets/subtensor/src/macros/dispatches.rs#L2250`](/code/pallets/subtensor/src/macros/dispatches.rs#L2248-L2258): ```rust #[pallet::call_index(132)] diff --git a/docs/tx/swap-coldkey-announced.mdx b/docs/tx/swap-coldkey-announced.mdx index 69f77cae63..1156d23022 100644 --- a/docs/tx/swap-coldkey-announced.mdx +++ b/docs/tx/swap-coldkey-announced.mdx @@ -15,7 +15,7 @@ future operations sign with the new coldkey. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.swap_coldkey_announced`](/code/pallets/subtensor/src/macros/dispatches.rs#L2098-L2120) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.swap_coldkey_announced`](/code/pallets/subtensor/src/macros/dispatches.rs#L2103-L2125) | ## Parameters @@ -64,7 +64,7 @@ result = sub.execute_tool("swap_coldkey_announced", {...}, wallet) ## On-chain implementation -`SubtensorModule.swap_coldkey_announced` — [`pallets/subtensor/src/macros/dispatches.rs#L2100`](/code/pallets/subtensor/src/macros/dispatches.rs#L2098-L2120): +`SubtensorModule.swap_coldkey_announced` — [`pallets/subtensor/src/macros/dispatches.rs#L2105`](/code/pallets/subtensor/src/macros/dispatches.rs#L2103-L2125): ```rust #[pallet::call_index(126)] diff --git a/docs/tx/transfer-stake.mdx b/docs/tx/transfer-stake.mdx index 371d666e4a..73253c797f 100644 --- a/docs/tx/transfer-stake.mdx +++ b/docs/tx/transfer-stake.mdx @@ -32,7 +32,7 @@ owners. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.transfer_stake`](/code/pallets/subtensor/src/macros/dispatches.rs#L1324-L1342), [`SubtensorModule.transfer_stake_and_hotkey`](/code/pallets/subtensor/src/macros/dispatches.rs#L2466-L2486) | +| `coldkey` | signed account (pallet role may apply) | SubtensorModule | [`SubtensorModule.transfer_stake`](/code/pallets/subtensor/src/macros/dispatches.rs#L1324-L1342), [`SubtensorModule.transfer_stake_and_hotkey`](/code/pallets/subtensor/src/macros/dispatches.rs#L2471-L2491) | ## Parameters @@ -120,7 +120,7 @@ pub fn transfer_stake( Delegates to [`do_transfer_stake`](/code/pallets/subtensor/src/staking/move_stake.rs#L120). -`SubtensorModule.transfer_stake_and_hotkey` — [`pallets/subtensor/src/macros/dispatches.rs#L2468`](/code/pallets/subtensor/src/macros/dispatches.rs#L2466-L2486): +`SubtensorModule.transfer_stake_and_hotkey` — [`pallets/subtensor/src/macros/dispatches.rs#L2473`](/code/pallets/subtensor/src/macros/dispatches.rs#L2471-L2491): ```rust #[pallet::call_index(143)] diff --git a/website/apps/bittensor-website/public/catalog/intents.json b/website/apps/bittensor-website/public/catalog/intents.json index 754b2c7671..f74ba7d09e 100644 --- a/website/apps/bittensor-website/public/catalog/intents.json +++ b/website/apps/bittensor-website/public/catalog/intents.json @@ -56,9 +56,9 @@ "pallet": "SubtensorModule", "call": "add_collateral", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2526, - "end_line": 2534, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2524-L2534", + "line": 2531, + "end_line": 2539, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2529-L2539", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -300,9 +300,9 @@ "pallet": "SubtensorModule", "call": "announce_coldkey_swap", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2062, - "end_line": 2088, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2060-L2088", + "line": 2067, + "end_line": 2093, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2065-L2093", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -605,9 +605,9 @@ "pallet": "SubtensorModule", "call": "clear_coldkey_swap_announcement", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2261, - "end_line": 2276, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2259-L2276", + "line": 2266, + "end_line": 2281, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2264-L2281", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -954,9 +954,9 @@ "pallet": "SubtensorModule", "call": "dispute_coldkey_swap", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2131, - "end_line": 2148, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2129-L2148", + "line": 2136, + "end_line": 2153, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2134-L2153", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -1358,9 +1358,9 @@ "pallet": "SubtensorModule", "call": "lock_stake", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2333, - "end_line": 2341, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2331-L2341", + "line": 2338, + "end_line": 2346, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2336-L2346", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -1405,9 +1405,9 @@ "pallet": "SubtensorModule", "call": "move_lock", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2357, - "end_line": 2364, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2355-L2364", + "line": 2362, + "end_line": 2369, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2360-L2369", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -3188,9 +3188,9 @@ "pallet": "SubtensorModule", "call": "set_min_collateral", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2561, - "end_line": 2568, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2559-L2568", + "line": 2566, + "end_line": 2573, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2564-L2573", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -3235,9 +3235,9 @@ "pallet": "SubtensorModule", "call": "set_perpetual_lock", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2373, - "end_line": 2380, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2371-L2380", + "line": 2378, + "end_line": 2385, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2376-L2385", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -3290,9 +3290,9 @@ "pallet": "SubtensorModule", "call": "sudo_set_root_claim_threshold", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2025, - "end_line": 2044, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2023-L2044", + "line": 2030, + "end_line": 2049, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2028-L2049", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -3674,9 +3674,9 @@ "pallet": "SubtensorModule", "call": "add_stake_burn", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2245, - "end_line": 2253, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2243-L2253", + "line": 2250, + "end_line": 2258, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2248-L2258", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -3758,9 +3758,9 @@ "pallet": "SubtensorModule", "call": "swap_coldkey_announced", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2100, - "end_line": 2120, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2098-L2120", + "line": 2105, + "end_line": 2125, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2103-L2125", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] @@ -4127,9 +4127,9 @@ "pallet": "SubtensorModule", "call": "transfer_stake_and_hotkey", "path": "pallets/subtensor/src/macros/dispatches.rs", - "line": 2468, - "end_line": 2486, - "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2466-L2486", + "line": 2473, + "end_line": 2491, + "url": "/code/pallets/subtensor/src/macros/dispatches.rs#L2471-L2491", "raw_url": "/code/raw/pallets/subtensor/src/macros/dispatches.rs" } ] From a85d83db44579e47e89b8ea7b3b3d7c20a4fc810 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Thu, 6 Aug 2026 01:55:16 +0200 Subject: [PATCH 31/58] fix(testnet): restore GRANDPA finality after warp sync --- Cargo.lock | 764 +++++++++++++------------- Cargo.toml | 418 +++++++------- eco-tests/Cargo.toml | 22 +- node/src/service/grandpa_warp_sync.rs | 8 +- 4 files changed, 605 insertions(+), 607 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8e1e1e611a..5cd24d9b79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1114,7 +1114,7 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "assets-common" version = "0.22.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "ethereum-standards", @@ -1499,7 +1499,7 @@ checksum = "5a45f9771ced8a774de5e5ebffbe520f52e3943bf5a9a6baa3a5d14a5de1afe6" [[package]] name = "binary-merkle-tree" version = "16.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "hash-db", "log", @@ -1870,7 +1870,7 @@ dependencies = [ [[package]] name = "bp-header-chain" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-runtime", "finality-grandpa", @@ -1887,7 +1887,7 @@ dependencies = [ [[package]] name = "bp-messages" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-runtime", @@ -1903,7 +1903,7 @@ dependencies = [ [[package]] name = "bp-parachains" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-polkadot-core", @@ -1920,7 +1920,7 @@ dependencies = [ [[package]] name = "bp-polkadot-core" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-messages", "bp-runtime", @@ -1936,7 +1936,7 @@ dependencies = [ [[package]] name = "bp-relayers" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-messages", @@ -1954,7 +1954,7 @@ dependencies = [ [[package]] name = "bp-runtime" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -1977,7 +1977,7 @@ dependencies = [ [[package]] name = "bp-test-utils" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-parachains", @@ -1997,7 +1997,7 @@ dependencies = [ [[package]] name = "bp-xcm-bridge-hub" version = "0.7.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-messages", "bp-runtime", @@ -2014,7 +2014,7 @@ dependencies = [ [[package]] name = "bp-xcm-bridge-hub-router" version = "0.18.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -2026,7 +2026,7 @@ dependencies = [ [[package]] name = "bridge-hub-common" version = "0.14.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2045,7 +2045,7 @@ dependencies = [ [[package]] name = "bridge-runtime-common" version = "0.22.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-messages", @@ -2958,7 +2958,7 @@ dependencies = [ [[package]] name = "cumulus-client-bootnodes" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -2984,7 +2984,7 @@ dependencies = [ [[package]] name = "cumulus-client-cli" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "clap", "parity-scale-codec", @@ -3001,7 +3001,7 @@ dependencies = [ [[package]] name = "cumulus-client-collator" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", @@ -3024,7 +3024,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-client-collator", @@ -3071,7 +3071,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-client-pov-recovery", @@ -3103,7 +3103,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-proposer" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "anyhow", "async-trait", @@ -3118,7 +3118,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-relay-chain" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -3141,7 +3141,7 @@ dependencies = [ [[package]] name = "cumulus-client-network" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-relay-chain-interface", @@ -3168,7 +3168,7 @@ dependencies = [ [[package]] name = "cumulus-client-parachain-inherent" version = "0.18.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3178,7 +3178,7 @@ dependencies = [ "parity-scale-codec", "sc-client-api", "sc-consensus-babe", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-inherents", "sp-runtime", "sp-state-machine", @@ -3189,7 +3189,7 @@ dependencies = [ [[package]] name = "cumulus-client-pov-recovery" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3217,7 +3217,7 @@ dependencies = [ [[package]] name = "cumulus-client-service" version = "0.25.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-channel 1.9.0", "cumulus-client-cli", @@ -3257,7 +3257,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-aura-ext" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-pallet-parachain-system", "frame-support", @@ -3274,7 +3274,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-dmp-queue" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "frame-benchmarking", @@ -3291,7 +3291,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bytes", "cumulus-pallet-parachain-system-proc-macro", @@ -3328,7 +3328,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.6.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -3339,7 +3339,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-session-benchmarking" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -3352,7 +3352,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-solo-to-para" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-pallet-parachain-system", "frame-support", @@ -3367,7 +3367,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-weight-reclaim" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-storage-weight-reclaim", "derive-where", @@ -3386,7 +3386,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -3401,7 +3401,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "approx", "bounded-collections 0.2.4", @@ -3426,7 +3426,7 @@ dependencies = [ [[package]] name = "cumulus-ping" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-pallet-xcm", "cumulus-primitives-core", @@ -3441,7 +3441,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-aura" version = "0.18.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "sp-api", "sp-consensus-aura", @@ -3450,7 +3450,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", @@ -3467,7 +3467,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3481,7 +3481,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-proof-size-hostfunction" version = "0.13.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "sp-externalities", "sp-runtime-interface", @@ -3491,7 +3491,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-storage-weight-reclaim" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "cumulus-primitives-proof-size-hostfunction", @@ -3508,7 +3508,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -3525,7 +3525,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-inprocess-interface" version = "0.25.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-channel 1.9.0", "async-trait", @@ -3553,7 +3553,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-interface" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3573,7 +3573,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-minimal-node" version = "0.25.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -3609,7 +3609,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-rpc-interface" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3650,7 +3650,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-streams" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-relay-chain-interface", "futures", @@ -3664,7 +3664,7 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -4471,7 +4471,7 @@ dependencies = [ [[package]] name = "ethereum-standards" version = "0.1.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "alloy-core", ] @@ -4853,7 +4853,7 @@ dependencies = [ "rustc-hex", "serde", "serde_json", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", ] [[package]] @@ -5036,7 +5036,7 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fork-tree" version = "13.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", ] @@ -5156,7 +5156,7 @@ checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" [[package]] name = "frame-benchmarking" version = "41.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-support-procedural", @@ -5180,7 +5180,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "49.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "Inflector", "array-bytes 6.2.3", @@ -5245,7 +5245,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-pallet-pov" version = "31.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -5273,7 +5273,7 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" version = "16.1.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -5284,7 +5284,7 @@ dependencies = [ [[package]] name = "frame-election-provider-support" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -5301,7 +5301,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "41.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "aquamarine", "frame-support", @@ -5354,7 +5354,7 @@ dependencies = [ [[package]] name = "frame-metadata-hash-extension" version = "0.9.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "const-hex", @@ -5370,7 +5370,7 @@ dependencies = [ [[package]] name = "frame-storage-access-test-runtime" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-pallet-parachain-system", "parity-scale-codec", @@ -5384,7 +5384,7 @@ dependencies = [ [[package]] name = "frame-support" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "aquamarine", "array-bytes 6.2.3", @@ -5425,7 +5425,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "34.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "Inflector", "cfg-expr", @@ -5439,14 +5439,14 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "syn 2.0.106", ] [[package]] name = "frame-support-procedural-core" version = "34.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cfg-expr", "frame-support-procedural-tools 13.0.1", @@ -5471,7 +5471,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "13.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support-procedural-tools-derive 12.0.0", "proc-macro-crate 3.4.0", @@ -5494,7 +5494,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro2", "quote", @@ -5504,7 +5504,7 @@ dependencies = [ [[package]] name = "frame-system" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cfg-if", "docify", @@ -5523,7 +5523,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -5537,7 +5537,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "parity-scale-codec", @@ -5547,7 +5547,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.47.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "parity-scale-codec", @@ -8287,7 +8287,7 @@ dependencies = [ [[package]] name = "mmr-gadget" version = "46.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "log", @@ -8306,7 +8306,7 @@ dependencies = [ [[package]] name = "mmr-rpc" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -9284,7 +9284,7 @@ dependencies = [ [[package]] name = "pallet-alliance" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "frame-benchmarking", @@ -9296,7 +9296,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-io", "sp-runtime", ] @@ -9320,7 +9320,7 @@ dependencies = [ [[package]] name = "pallet-asset-conversion" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9338,7 +9338,7 @@ dependencies = [ [[package]] name = "pallet-asset-conversion-ops" version = "0.9.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9356,7 +9356,7 @@ dependencies = [ [[package]] name = "pallet-asset-conversion-tx-payment" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9371,7 +9371,7 @@ dependencies = [ [[package]] name = "pallet-asset-rate" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9385,7 +9385,7 @@ dependencies = [ [[package]] name = "pallet-asset-rewards" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9403,7 +9403,7 @@ dependencies = [ [[package]] name = "pallet-asset-tx-payment" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9419,7 +9419,7 @@ dependencies = [ [[package]] name = "pallet-assets" version = "43.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "ethereum-standards", "frame-benchmarking", @@ -9437,7 +9437,7 @@ dependencies = [ [[package]] name = "pallet-assets-freezer" version = "0.8.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "pallet-assets", @@ -9449,7 +9449,7 @@ dependencies = [ [[package]] name = "pallet-assets-holder" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9464,7 +9464,7 @@ dependencies = [ [[package]] name = "pallet-atomic-swap" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -9474,7 +9474,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -9490,7 +9490,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -9505,7 +9505,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -9518,7 +9518,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9541,7 +9541,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "aquamarine", "docify", @@ -9562,7 +9562,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -9591,7 +9591,7 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -9610,7 +9610,7 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "binary-merkle-tree", @@ -9635,7 +9635,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9652,7 +9652,7 @@ dependencies = [ [[package]] name = "pallet-bridge-grandpa" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-runtime", @@ -9671,7 +9671,7 @@ dependencies = [ [[package]] name = "pallet-bridge-messages" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-messages", @@ -9690,7 +9690,7 @@ dependencies = [ [[package]] name = "pallet-bridge-parachains" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-parachains", @@ -9710,7 +9710,7 @@ dependencies = [ [[package]] name = "pallet-bridge-relayers" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-header-chain", "bp-messages", @@ -9733,7 +9733,7 @@ dependencies = [ [[package]] name = "pallet-broker" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "frame-benchmarking", @@ -9751,7 +9751,7 @@ dependencies = [ [[package]] name = "pallet-child-bounties" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9769,7 +9769,7 @@ dependencies = [ [[package]] name = "pallet-collator-selection" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9788,7 +9788,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -9805,7 +9805,7 @@ dependencies = [ [[package]] name = "pallet-collective-content" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9846,7 +9846,7 @@ dependencies = [ [[package]] name = "pallet-contracts" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "environmental", "frame-benchmarking", @@ -9877,7 +9877,7 @@ dependencies = [ [[package]] name = "pallet-contracts-mock-network" version = "18.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -9908,7 +9908,7 @@ dependencies = [ [[package]] name = "pallet-contracts-proc-macro" version = "23.0.3" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro2", "quote", @@ -9918,7 +9918,7 @@ dependencies = [ [[package]] name = "pallet-contracts-uapi" version = "14.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitflags 1.3.2", "parity-scale-codec", @@ -9929,7 +9929,7 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "assert_matches", "frame-benchmarking", @@ -9945,7 +9945,7 @@ dependencies = [ [[package]] name = "pallet-core-fellowship" version = "25.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -9983,7 +9983,7 @@ dependencies = [ [[package]] name = "pallet-delegated-staking" version = "8.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -9998,7 +9998,7 @@ dependencies = [ [[package]] name = "pallet-democracy" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10015,7 +10015,7 @@ dependencies = [ [[package]] name = "pallet-dev-mode" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -10064,7 +10064,7 @@ dependencies = [ [[package]] name = "pallet-dummy-dim" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10082,7 +10082,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-block" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10103,7 +10103,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10124,7 +10124,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-support-benchmarking" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10137,7 +10137,7 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10256,7 +10256,7 @@ dependencies = [ [[package]] name = "pallet-fast-unstake" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -10274,7 +10274,7 @@ dependencies = [ [[package]] name = "pallet-glutton" version = "27.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "blake2 0.10.6", "frame-benchmarking", @@ -10292,7 +10292,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10328,7 +10328,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "enumflags2", "frame-benchmarking", @@ -10344,7 +10344,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10363,7 +10363,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10378,7 +10378,7 @@ dependencies = [ [[package]] name = "pallet-insecure-randomness-collective-flip" version = "29.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -10411,7 +10411,7 @@ dependencies = [ [[package]] name = "pallet-lottery" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10424,7 +10424,7 @@ dependencies = [ [[package]] name = "pallet-membership" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10440,7 +10440,7 @@ dependencies = [ [[package]] name = "pallet-message-queue" version = "44.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "environmental", "frame-benchmarking", @@ -10459,7 +10459,7 @@ dependencies = [ [[package]] name = "pallet-meta-tx" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -10477,7 +10477,7 @@ dependencies = [ [[package]] name = "pallet-migrations" version = "11.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -10496,7 +10496,7 @@ dependencies = [ [[package]] name = "pallet-mixnet" version = "0.17.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "parity-scale-codec", @@ -10510,7 +10510,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "parity-scale-codec", @@ -10522,7 +10522,7 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "parity-scale-codec", @@ -10533,7 +10533,7 @@ dependencies = [ [[package]] name = "pallet-nft-fractionalization" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "pallet-assets", @@ -10546,7 +10546,7 @@ dependencies = [ [[package]] name = "pallet-nfts" version = "35.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "enumflags2", "frame-benchmarking", @@ -10563,7 +10563,7 @@ dependencies = [ [[package]] name = "pallet-nis" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -10573,7 +10573,7 @@ dependencies = [ [[package]] name = "pallet-node-authorization" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "parity-scale-codec", @@ -10584,7 +10584,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" version = "39.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -10602,7 +10602,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" version = "39.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10622,7 +10622,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -10632,7 +10632,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -10647,7 +10647,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10670,7 +10670,7 @@ dependencies = [ [[package]] name = "pallet-origin-restriction" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10688,7 +10688,7 @@ dependencies = [ [[package]] name = "pallet-paged-list" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "parity-scale-codec", @@ -10699,7 +10699,7 @@ dependencies = [ [[package]] name = "pallet-parameters" version = "0.12.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -10716,7 +10716,7 @@ dependencies = [ [[package]] name = "pallet-people" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10734,7 +10734,7 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10750,7 +10750,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -10762,7 +10762,7 @@ dependencies = [ [[package]] name = "pallet-ranked-collective" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10780,7 +10780,7 @@ dependencies = [ [[package]] name = "pallet-recovery" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -10790,7 +10790,7 @@ dependencies = [ [[package]] name = "pallet-referenda" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "assert_matches", "frame-benchmarking", @@ -10808,7 +10808,7 @@ dependencies = [ [[package]] name = "pallet-remark" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -10823,7 +10823,7 @@ dependencies = [ [[package]] name = "pallet-revive" version = "0.7.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "alloy-core", "derive_more 0.99.20", @@ -10869,7 +10869,7 @@ dependencies = [ [[package]] name = "pallet-revive-fixtures" version = "0.4.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "anyhow", "cargo_metadata", @@ -10883,7 +10883,7 @@ dependencies = [ [[package]] name = "pallet-revive-proc-macro" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro2", "quote", @@ -10893,7 +10893,7 @@ dependencies = [ [[package]] name = "pallet-revive-uapi" version = "0.5.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitflags 1.3.2", "pallet-revive-proc-macro", @@ -10905,7 +10905,7 @@ dependencies = [ [[package]] name = "pallet-root-offences" version = "38.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -10921,7 +10921,7 @@ dependencies = [ [[package]] name = "pallet-root-testing" version = "17.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -10934,7 +10934,7 @@ dependencies = [ [[package]] name = "pallet-safe-mode" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "pallet-balances", @@ -10948,7 +10948,7 @@ dependencies = [ [[package]] name = "pallet-salary" version = "26.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "pallet-ranked-collective", @@ -10960,7 +10960,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -10977,7 +10977,7 @@ dependencies = [ [[package]] name = "pallet-scored-pool" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -10990,7 +10990,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -11011,7 +11011,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11057,7 +11057,7 @@ dependencies = [ [[package]] name = "pallet-skip-feeless-payment" version = "16.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -11069,7 +11069,7 @@ dependencies = [ [[package]] name = "pallet-society" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11086,7 +11086,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -11108,7 +11108,7 @@ dependencies = [ [[package]] name = "pallet-staking-async" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -11131,7 +11131,7 @@ dependencies = [ [[package]] name = "pallet-staking-async-ah-client" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -11150,7 +11150,7 @@ dependencies = [ [[package]] name = "pallet-staking-async-rc-client" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -11167,7 +11167,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -11178,7 +11178,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-fn" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "sp-arithmetic", @@ -11187,7 +11187,7 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" version = "27.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "sp-api", @@ -11197,7 +11197,7 @@ dependencies = [ [[package]] name = "pallet-state-trie-migration" version = "46.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11213,7 +11213,7 @@ dependencies = [ [[package]] name = "pallet-statement" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", @@ -11377,7 +11377,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -11392,7 +11392,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -11410,7 +11410,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11428,7 +11428,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11443,7 +11443,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "44.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -11459,7 +11459,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -11471,7 +11471,7 @@ dependencies = [ [[package]] name = "pallet-transaction-storage" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "frame-benchmarking", @@ -11490,7 +11490,7 @@ dependencies = [ [[package]] name = "pallet-treasury" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -11509,7 +11509,7 @@ dependencies = [ [[package]] name = "pallet-tx-pause" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "parity-scale-codec", @@ -11520,7 +11520,7 @@ dependencies = [ [[package]] name = "pallet-uniques" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11534,7 +11534,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11549,7 +11549,7 @@ dependencies = [ [[package]] name = "pallet-verify-signature" version = "0.4.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11564,7 +11564,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11578,7 +11578,7 @@ dependencies = [ [[package]] name = "pallet-whitelist" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -11588,7 +11588,7 @@ dependencies = [ [[package]] name = "pallet-xcm" version = "20.1.3" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bounded-collections 0.2.4", "frame-benchmarking", @@ -11614,7 +11614,7 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-benchmarking", "frame-support", @@ -11631,7 +11631,7 @@ dependencies = [ [[package]] name = "pallet-xcm-bridge-hub" version = "0.17.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-messages", "bp-runtime", @@ -11653,7 +11653,7 @@ dependencies = [ [[package]] name = "pallet-xcm-bridge-hub-router" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-xcm-bridge-hub-router", "frame-benchmarking", @@ -11673,7 +11673,7 @@ dependencies = [ [[package]] name = "parachains-common" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "cumulus-primitives-utility", @@ -12035,7 +12035,7 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "polkadot-approval-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "futures-timer", @@ -12053,7 +12053,7 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "futures-timer", @@ -12068,7 +12068,7 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "fatality", "futures", @@ -12091,7 +12091,7 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "fatality", @@ -12124,7 +12124,7 @@ dependencies = [ [[package]] name = "polkadot-cli" version = "25.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "clap", "frame-benchmarking-cli", @@ -12148,7 +12148,7 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "fatality", @@ -12171,7 +12171,7 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" version = "18.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -12182,7 +12182,7 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "fatality", "futures", @@ -12204,7 +12204,7 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -12218,7 +12218,7 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" version = "24.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "futures-timer", @@ -12231,7 +12231,7 @@ dependencies = [ "sc-network", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-keystore", "tracing-gum", ] @@ -12239,7 +12239,7 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "always-assert", "async-trait", @@ -12262,7 +12262,7 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "parity-scale-codec", @@ -12280,7 +12280,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "bitvec", @@ -12312,7 +12312,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting-parallel" version = "0.7.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -12336,7 +12336,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "futures", @@ -12355,7 +12355,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "fatality", @@ -12376,7 +12376,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "polkadot-node-subsystem", @@ -12391,7 +12391,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -12413,7 +12413,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "polkadot-node-metrics", @@ -12427,7 +12427,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "futures-timer", @@ -12443,7 +12443,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "fatality", "futures", @@ -12461,7 +12461,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -12478,7 +12478,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-prospective-parachains" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "fatality", "futures", @@ -12492,7 +12492,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "fatality", @@ -12509,7 +12509,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "always-assert", "array-bytes 6.2.3", @@ -12537,7 +12537,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-checker" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "polkadot-node-subsystem", @@ -12550,7 +12550,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-common" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cpu-time", "futures", @@ -12565,7 +12565,7 @@ dependencies = [ "sc-executor-wasmtime", "seccompiler", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-externalities", "sp-io", "sp-tracing", @@ -12576,7 +12576,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-runtime-api" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "polkadot-node-metrics", @@ -12591,7 +12591,7 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bs58", "futures", @@ -12608,7 +12608,7 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-channel 1.9.0", "async-trait", @@ -12633,7 +12633,7 @@ dependencies = [ [[package]] name = "polkadot-node-primitives" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "bounded-vec", @@ -12657,7 +12657,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "polkadot-node-subsystem-types", "polkadot-overseer", @@ -12666,7 +12666,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "derive_more 0.99.20", @@ -12694,7 +12694,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" version = "24.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "fatality", "futures", @@ -12725,7 +12725,7 @@ dependencies = [ [[package]] name = "polkadot-omni-node-lib" version = "0.7.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "clap", @@ -12813,7 +12813,7 @@ dependencies = [ [[package]] name = "polkadot-overseer" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -12833,7 +12833,7 @@ dependencies = [ [[package]] name = "polkadot-parachain-primitives" version = "17.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bounded-collections 0.2.4", "derive_more 0.99.20", @@ -12849,7 +12849,7 @@ dependencies = [ [[package]] name = "polkadot-primitives" version = "19.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "bounded-collections 0.2.4", @@ -12878,7 +12878,7 @@ dependencies = [ [[package]] name = "polkadot-rpc" version = "25.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "jsonrpsee", "mmr-rpc", @@ -12911,7 +12911,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "frame-benchmarking", @@ -12961,7 +12961,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-metrics" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bs58", "frame-benchmarking", @@ -12973,7 +12973,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" version = "20.0.2" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitflags 1.3.2", "bitvec", @@ -13021,7 +13021,7 @@ dependencies = [ [[package]] name = "polkadot-sdk" version = "2506.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "assets-common", "bridge-hub-common", @@ -13179,7 +13179,7 @@ dependencies = [ [[package]] name = "polkadot-sdk-frame" version = "0.10.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-benchmarking", @@ -13214,7 +13214,7 @@ dependencies = [ [[package]] name = "polkadot-service" version = "25.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "frame-benchmarking", @@ -13324,7 +13324,7 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitvec", "fatality", @@ -13344,7 +13344,7 @@ dependencies = [ [[package]] name = "polkadot-statement-table" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -13651,7 +13651,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "syn 2.0.106", ] @@ -13833,7 +13833,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "syn 2.0.106", ] @@ -14673,7 +14673,7 @@ dependencies = [ [[package]] name = "rococo-runtime" version = "24.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "binary-merkle-tree", "bitvec", @@ -14771,7 +14771,7 @@ dependencies = [ [[package]] name = "rococo-runtime-constants" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "polkadot-primitives", @@ -15201,7 +15201,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "32.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "sp-core", @@ -15212,7 +15212,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -15243,7 +15243,7 @@ dependencies = [ [[package]] name = "sc-basic-authorship" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "log", @@ -15265,7 +15265,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.45.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "sp-api", @@ -15280,7 +15280,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "44.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "clap", @@ -15296,7 +15296,7 @@ dependencies = [ "serde_json", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-genesis-builder", "sp-io", "sp-runtime", @@ -15307,7 +15307,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -15318,7 +15318,7 @@ dependencies = [ [[package]] name = "sc-cli" version = "0.53.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "chrono", @@ -15360,7 +15360,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "fnv", "futures", @@ -15386,7 +15386,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.47.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "hash-db", "kvdb", @@ -15414,7 +15414,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -15437,7 +15437,7 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -15466,7 +15466,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "fork-tree", @@ -15491,7 +15491,7 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-slots", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-inherents", "sp-keystore", "sp-runtime", @@ -15502,7 +15502,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "jsonrpsee", @@ -15524,7 +15524,7 @@ dependencies = [ [[package]] name = "sc-consensus-beefy" version = "30.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15558,7 +15558,7 @@ dependencies = [ [[package]] name = "sc-consensus-beefy-rpc" version = "30.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "jsonrpsee", @@ -15578,7 +15578,7 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "fork-tree", "parity-scale-codec", @@ -15591,7 +15591,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" version = "0.36.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "ahash 0.8.12", "array-bytes 6.2.3", @@ -15625,7 +15625,7 @@ dependencies = [ "sp-consensus", "sp-consensus-grandpa", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", @@ -15635,7 +15635,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa-rpc" version = "0.36.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "finality-grandpa", "futures", @@ -15655,7 +15655,7 @@ dependencies = [ [[package]] name = "sc-consensus-manual-seal" version = "0.52.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "assert_matches", "async-trait", @@ -15690,7 +15690,7 @@ dependencies = [ [[package]] name = "sc-consensus-slots" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -15713,7 +15713,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "parking_lot 0.12.5", @@ -15736,7 +15736,7 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.39.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "polkavm 0.24.0", "sc-allocator", @@ -15749,7 +15749,7 @@ dependencies = [ [[package]] name = "sc-executor-polkavm" version = "0.36.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "polkavm 0.24.0", @@ -15760,7 +15760,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.39.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "anyhow", "log", @@ -15776,7 +15776,7 @@ dependencies = [ [[package]] name = "sc-informant" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "console", "futures", @@ -15792,7 +15792,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "36.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "parking_lot 0.12.5", @@ -15806,7 +15806,7 @@ dependencies = [ [[package]] name = "sc-mixnet" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "arrayvec 0.7.6", @@ -15834,7 +15834,7 @@ dependencies = [ [[package]] name = "sc-network" version = "0.51.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15884,7 +15884,7 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.49.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bitflags 1.3.2", "parity-scale-codec", @@ -15894,7 +15894,7 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "ahash 0.8.12", "futures", @@ -15913,7 +15913,7 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15934,7 +15934,7 @@ dependencies = [ [[package]] name = "sc-network-statement" version = "0.33.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15954,7 +15954,7 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15989,7 +15989,7 @@ dependencies = [ [[package]] name = "sc-network-transactions" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "futures", @@ -16008,7 +16008,7 @@ dependencies = [ [[package]] name = "sc-network-types" version = "0.17.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bs58", "bytes", @@ -16029,7 +16029,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "46.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bytes", "fnv", @@ -16063,7 +16063,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -16072,7 +16072,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "46.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "jsonrpsee", @@ -16104,7 +16104,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -16124,7 +16124,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "dyn-clone", "forwarded-header-value", @@ -16148,7 +16148,7 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "futures", @@ -16181,13 +16181,13 @@ dependencies = [ [[package]] name = "sc-runtime-utilities" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "sc-executor", "sc-executor-common", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-state-machine", "sp-wasm-interface", "thiserror 1.0.69", @@ -16196,7 +16196,7 @@ dependencies = [ [[package]] name = "sc-service" version = "0.52.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "directories", @@ -16260,7 +16260,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.39.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "parity-scale-codec", @@ -16271,7 +16271,7 @@ dependencies = [ [[package]] name = "sc-statement-store" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "parity-db", @@ -16290,7 +16290,7 @@ dependencies = [ [[package]] name = "sc-storage-monitor" version = "0.25.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "clap", "fs4", @@ -16303,7 +16303,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -16322,7 +16322,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "43.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "derive_more 0.99.20", "futures", @@ -16335,14 +16335,14 @@ dependencies = [ "serde", "serde_json", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-io", ] [[package]] name = "sc-telemetry" version = "29.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "chrono", "futures", @@ -16361,7 +16361,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "chrono", "console", @@ -16389,7 +16389,7 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "11.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -16400,7 +16400,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool" version = "40.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -16417,7 +16417,7 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-runtime", "sp-tracing", "sp-transaction-pool", @@ -16431,7 +16431,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -16448,7 +16448,7 @@ dependencies = [ [[package]] name = "sc-utils" version = "19.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-channel 1.9.0", "futures", @@ -17204,7 +17204,7 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "slot-range-helper" version = "18.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "enumn", "parity-scale-codec", @@ -17488,7 +17488,7 @@ dependencies = [ [[package]] name = "snowbridge-core" version = "0.14.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bp-relayers", "frame-support", @@ -17583,7 +17583,7 @@ dependencies = [ [[package]] name = "sp-api" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "hash-db", @@ -17605,7 +17605,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "Inflector", "blake2 0.10.6", @@ -17619,7 +17619,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -17631,7 +17631,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "27.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "integer-sqrt", @@ -17645,7 +17645,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -17657,7 +17657,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "sp-api", "sp-inherents", @@ -17667,7 +17667,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "futures", "parity-scale-codec", @@ -17686,7 +17686,7 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "futures", @@ -17700,7 +17700,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "parity-scale-codec", @@ -17716,7 +17716,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "parity-scale-codec", @@ -17734,7 +17734,7 @@ dependencies = [ [[package]] name = "sp-consensus-beefy" version = "25.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -17742,7 +17742,7 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-io", "sp-keystore", "sp-mmr-primitives", @@ -17754,7 +17754,7 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "finality-grandpa", "log", @@ -17771,7 +17771,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -17782,7 +17782,7 @@ dependencies = [ [[package]] name = "sp-core" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "ark-vrf", "array-bytes 6.2.3", @@ -17813,7 +17813,7 @@ dependencies = [ "secrecy 0.8.0", "serde", "sha2 0.10.9", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", @@ -17830,7 +17830,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.16.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -17864,7 +17864,7 @@ dependencies = [ [[package]] name = "sp-crypto-hashing" version = "0.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "blake2b_simd", "byteorder", @@ -17877,17 +17877,17 @@ dependencies = [ [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "syn 2.0.106", ] [[package]] name = "sp-database" version = "10.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "kvdb", "parking_lot 0.12.5", @@ -17896,7 +17896,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "proc-macro2", "quote", @@ -17906,7 +17906,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.30.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "environmental", "parity-scale-codec", @@ -17916,7 +17916,7 @@ dependencies = [ [[package]] name = "sp-genesis-builder" version = "0.18.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -17928,7 +17928,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -17941,7 +17941,7 @@ dependencies = [ [[package]] name = "sp-io" version = "41.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bytes", "docify", @@ -17953,7 +17953,7 @@ dependencies = [ "rustversion", "secp256k1 0.28.2", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-externalities", "sp-keystore", "sp-runtime-interface", @@ -17967,7 +17967,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "sp-core", "sp-runtime", @@ -17977,7 +17977,7 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "parking_lot 0.12.5", @@ -17988,7 +17988,7 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "11.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "thiserror 1.0.69", "zstd 0.12.4", @@ -17997,7 +17997,7 @@ dependencies = [ [[package]] name = "sp-metadata-ir" version = "0.11.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-metadata 23.0.0", "parity-scale-codec", @@ -18007,7 +18007,7 @@ dependencies = [ [[package]] name = "sp-mixnet" version = "0.15.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -18018,7 +18018,7 @@ dependencies = [ [[package]] name = "sp-mmr-primitives" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "log", "parity-scale-codec", @@ -18035,7 +18035,7 @@ dependencies = [ [[package]] name = "sp-npos-elections" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -18048,7 +18048,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "sp-api", "sp-core", @@ -18058,7 +18058,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "13.0.2" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "backtrace", "regex", @@ -18067,7 +18067,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "35.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "rustc-hash 1.1.0", "serde", @@ -18077,7 +18077,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "binary-merkle-tree", "docify", @@ -18106,7 +18106,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "30.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -18125,7 +18125,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "19.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "Inflector", "expander", @@ -18138,7 +18138,7 @@ dependencies = [ [[package]] name = "sp-session" version = "39.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -18152,7 +18152,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "39.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -18165,7 +18165,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.46.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "hash-db", "log", @@ -18185,7 +18185,7 @@ dependencies = [ [[package]] name = "sp-statement-store" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "aes-gcm", "curve25519-dalek", @@ -18198,7 +18198,7 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", "sp-externalities", "sp-runtime", "sp-runtime-interface", @@ -18209,12 +18209,12 @@ dependencies = [ [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" [[package]] name = "sp-storage" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "impl-serde", "parity-scale-codec", @@ -18226,7 +18226,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "parity-scale-codec", @@ -18238,7 +18238,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "17.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "tracing", @@ -18249,7 +18249,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "sp-api", "sp-runtime", @@ -18258,7 +18258,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "async-trait", "parity-scale-codec", @@ -18272,7 +18272,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "ahash 0.8.12", "foldhash 0.1.5", @@ -18297,7 +18297,7 @@ dependencies = [ [[package]] name = "sp-version" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "impl-serde", "parity-scale-codec", @@ -18314,7 +18314,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "15.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "proc-macro-warning", @@ -18326,7 +18326,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -18338,7 +18338,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "32.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "bounded-collections 0.2.4", "parity-scale-codec", @@ -18512,7 +18512,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "staging-chain-spec-builder" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "clap", "docify", @@ -18525,7 +18525,7 @@ dependencies = [ [[package]] name = "staging-node-inspect" version = "0.29.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "clap", "parity-scale-codec", @@ -18543,7 +18543,7 @@ dependencies = [ [[package]] name = "staging-parachain-info" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -18556,7 +18556,7 @@ dependencies = [ [[package]] name = "staging-xcm" version = "17.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "bounded-collections 0.2.4", @@ -18577,7 +18577,7 @@ dependencies = [ [[package]] name = "staging-xcm-builder" version = "21.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "environmental", "frame-support", @@ -18601,7 +18601,7 @@ dependencies = [ [[package]] name = "staging-xcm-executor" version = "20.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "environmental", "frame-benchmarking", @@ -18655,7 +18655,7 @@ dependencies = [ [[package]] name = "stc-shield" version = "0.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "anyhow", "async-trait", @@ -18676,7 +18676,7 @@ dependencies = [ [[package]] name = "stp-shield" version = "0.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "parity-scale-codec", "scale-info", @@ -18746,7 +18746,7 @@ dependencies = [ [[package]] name = "substrate-bip39" version = "0.6.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "hmac 0.12.1", "pbkdf2 0.12.2", @@ -18771,7 +18771,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "11.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" [[package]] name = "substrate-fixed" @@ -18787,7 +18787,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "45.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "docify", "frame-system-rpc-runtime-api", @@ -18807,7 +18807,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.17.6" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "http-body-util", "hyper 1.7.0", @@ -18821,7 +18821,7 @@ dependencies = [ [[package]] name = "substrate-state-trie-migration-rpc" version = "44.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -18848,7 +18848,7 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "27.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "array-bytes 6.2.3", "build-helper", @@ -19957,7 +19957,7 @@ dependencies = [ [[package]] name = "tracing-gum" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "coarsetime", "polkadot-primitives", @@ -19968,7 +19968,7 @@ dependencies = [ [[package]] name = "tracing-gum-proc-macro" version = "5.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "expander", "proc-macro-crate 3.4.0", @@ -20973,7 +20973,7 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "westend-runtime" version = "24.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "binary-merkle-tree", "bitvec", @@ -21080,7 +21080,7 @@ dependencies = [ [[package]] name = "westend-runtime-constants" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "polkadot-primitives", @@ -21730,7 +21730,7 @@ dependencies = [ [[package]] name = "xcm-procedural" version = "11.0.2" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "Inflector", "proc-macro2", @@ -21741,7 +21741,7 @@ dependencies = [ [[package]] name = "xcm-runtime-apis" version = "0.8.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "parity-scale-codec", @@ -21755,7 +21755,7 @@ dependencies = [ [[package]] name = "xcm-simulator" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=a08c7b0f0b6429910a953cbbaec4b4138294fa38#a08c7b0f0b6429910a953cbbaec4b4138294fa38" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" dependencies = [ "frame-support", "frame-system", diff --git a/Cargo.toml b/Cargo.toml index ecd5b0997e..3247664d7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,8 +79,8 @@ subtensor-runtime-common = { default-features = false, path = "common" } subtensor-swap-interface = { default-features = false, path = "primitives/swap-interface" } subtensor-transaction-fee = { default-features = false, path = "pallets/transaction-fee" } subtensor-chain-extensions = { default-features = false, path = "chain-extensions" } -stp-shield = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -stc-shield = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +stp-shield = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +stc-shield = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } ed25519-dalek = { version = "2.1.0", default-features = false } async-trait = "0.1" @@ -138,122 +138,122 @@ num_enum = { version = "0.7.4", default-features = false } environmental = { version = "1.1.4", default-features = false } tokio = { version = "1.38", default-features = false } -frame = { package = "polkadot-sdk-frame", git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-executive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-system-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-try-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-benchmarking-cli = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -frame-metadata-hash-extension = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +frame = { package = "polkadot-sdk-frame", git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-executive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-system-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-try-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-benchmarking-cli = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-metadata-hash-extension = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } frame-metadata = { version = "23.0.0", default-features = false } pallet-subtensor-proxy = { path = "pallets/proxy", default-features = false } pallet-subtensor-utility = { path = "pallets/utility", default-features = false } -pallet-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-balances = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-insecure-randomness-collective-flip = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-multisig = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-preimage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-safe-mode = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-scheduler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-sudo = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-transaction-payment = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-transaction-payment-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-root-testing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-contracts = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +pallet-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-balances = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-multisig = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-preimage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-safe-mode = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-scheduler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-sudo = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-transaction-payment = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-transaction-payment-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-root-testing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-contracts = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } # NPoS -frame-election-provider-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-authorship = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-bags-list = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-election-provider-multi-phase = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-fast-unstake = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-nomination-pools = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-nomination-pools-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-staking-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-staking-reward-fn = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-staking-reward-curve = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -pallet-offences = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +frame-election-provider-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-authorship = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-bags-list = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-election-provider-multi-phase = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-fast-unstake = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-nomination-pools = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-nomination-pools-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-staking-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-staking-reward-fn = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-staking-reward-curve = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-offences = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-basic-authorship = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-cli = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-client-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus-babe-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus-grandpa-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus-epochs = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-chain-spec-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-chain-spec = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-executor = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-network = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-rpc-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-service = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-telemetry = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-transaction-pool-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-consensus-manual-seal = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sc-network-sync = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +sc-basic-authorship = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-cli = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-client-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus-babe-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus-grandpa-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus-epochs = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-chain-spec-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-chain-spec = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-executor = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-network = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-rpc-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-service = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-telemetry = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-transaction-pool-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-consensus-manual-seal = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-network-sync = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-arithmetic = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-blockchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-npos-elections = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-genesis-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-inherents = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-keyring = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-storage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-version = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-weights = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-crypto-hashing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-application-crypto = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-debug-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-externalities = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-runtime-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-arithmetic = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-blockchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-npos-elections = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-genesis-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-inherents = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-keyring = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-storage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-version = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-weights = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-crypto-hashing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-application-crypto = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-debug-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-externalities = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-runtime-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -substrate-build-script-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +substrate-build-script-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } substrate-fixed = { git = "https://github.com/encointer/substrate-fixed.git", tag = "v0.6.0", default-features = false } -substrate-frame-rpc-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -substrate-wasm-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -substrate-prometheus-endpoint = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +substrate-frame-rpc-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +substrate-wasm-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +substrate-prometheus-endpoint = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -polkadot-sdk = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +polkadot-sdk = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -runtime-common = { package = "polkadot-runtime-common", git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +runtime-common = { package = "polkadot-runtime-common", git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } # Frontier # Vendored via `git subtree` from RaoFoundation/frontier @@ -292,8 +292,8 @@ pallet-hotfix-sufficients = { path = "vendor/frontier/frame/hotfix-sufficients", #DRAND pallet-drand = { path = "pallets/drand", default-features = false } -sp-crypto-ec-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } -sp-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false } +sp-crypto-ec-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } w3f-bls = { path = "vendor/w3f-bls", default-features = false } ark-crypto-primitives = { version = "0.4.0", default-features = false } ark-scale = { version = "0.0.11", default-features = false } @@ -344,104 +344,104 @@ zstd-safe = { git = "https://github.com/gztensor/zstd-safe", rev = "42cc34ef6abe # build. Redirect the frontier-side polkadot-sdk crates to the RaoFoundation # remote at the same rev so the whole graph resolves to a single copy. [patch."https://github.com/opentensor/polkadot-sdk"] -binary-merkle-tree = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -cumulus-primitives-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -cumulus-primitives-proof-size-hostfunction = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -cumulus-primitives-storage-weight-reclaim = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -fork-tree = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -frame-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -frame-support-procedural = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -frame-support-procedural-tools = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -frame-support-procedural-tools-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -polkadot-core-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -polkadot-parachain-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -polkadot-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-allocator = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-chain-spec = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-chain-spec-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-client-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-client-db = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-consensus-epochs = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-executor = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-executor-common = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-executor-polkavm = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-executor-wasmtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-informant = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-mixnet = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-network = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-network-common = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-network-light = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-network-sync = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-network-transactions = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-network-types = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-rpc-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-rpc-server = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-rpc-spec-v2 = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-service = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-state-db = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-sysinfo = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-telemetry = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-tracing-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-transaction-pool-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sc-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-api-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-application-crypto = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-arithmetic = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-blockchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-crypto-hashing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-crypto-hashing-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-database = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-debug-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-externalities = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-genesis-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-inherents = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-maybe-compressed-blob = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-metadata-ir = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-mixnet = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-panic-handler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-runtime-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-runtime-interface-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-state-machine = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-statement-store = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-storage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-transaction-storage-proof = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-trie = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-version = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-version-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-wasm-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -sp-weights = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -staging-xcm = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -substrate-bip39 = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -substrate-prometheus-endpoint = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } -xcm-procedural = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38" } +binary-merkle-tree = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +cumulus-primitives-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +cumulus-primitives-proof-size-hostfunction = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +cumulus-primitives-storage-weight-reclaim = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +fork-tree = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +frame-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +frame-support-procedural = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +frame-support-procedural-tools = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +frame-support-procedural-tools-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +polkadot-core-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +polkadot-parachain-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +polkadot-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-allocator = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-chain-spec = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-chain-spec-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-client-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-client-db = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-consensus-epochs = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-executor = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-executor-common = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-executor-polkavm = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-executor-wasmtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-informant = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-mixnet = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-network = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-network-common = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-network-light = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-network-sync = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-network-transactions = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-network-types = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-rpc-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-rpc-server = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-rpc-spec-v2 = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-service = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-state-db = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-sysinfo = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-telemetry = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-tracing-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-transaction-pool-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sc-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-api-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-application-crypto = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-arithmetic = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-blockchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-crypto-hashing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-crypto-hashing-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-database = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-debug-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-externalities = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-genesis-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-inherents = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-maybe-compressed-blob = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-metadata-ir = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-mixnet = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-panic-handler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-runtime-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-runtime-interface-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-state-machine = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-statement-store = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-storage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-transaction-storage-proof = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-trie = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-version = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-version-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-wasm-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +sp-weights = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +staging-xcm = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +substrate-bip39 = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +substrate-prometheus-endpoint = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +xcm-procedural = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } diff --git a/eco-tests/Cargo.toml b/eco-tests/Cargo.toml index e8b88598d2..6beea8484c 100644 --- a/eco-tests/Cargo.toml +++ b/eco-tests/Cargo.toml @@ -23,22 +23,22 @@ useless_conversion = "allow" time = { version = "0.3.47", default-features = false } pallet-subtensor = { path = "../pallets/subtensor", default-features = false, features = ["std"] } pallet-alpha-assets = { path = "../pallets/alpha-assets", default-features = false, features = ["std"] } -frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } -frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } -sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } -sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } -sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } -sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } +frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } codec = { package = "parity-scale-codec", version = "3.7.5", default-features = false, features = ["derive", "std"] } scale-info = { version = "2.11.2", default-features = false, features = ["derive", "std"] } -pallet-balances = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } -pallet-scheduler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } -pallet-preimage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } +pallet-balances = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +pallet-scheduler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +pallet-preimage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } pallet-drand = { path = "../pallets/drand", default-features = false, features = ["std"] } pallet-subtensor-swap = { path = "../pallets/swap", default-features = false, features = ["std"] } pallet-subtensor-swap-runtime-api = { path = "../pallets/swap/runtime-api", default-features = false, features = ["std"] } subtensor-custom-rpc-runtime-api = { path = "../pallets/subtensor/runtime-api", default-features = false, features = ["std"] } -sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } +sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } pallet-crowdloan = { path = "../pallets/crowdloan", default-features = false, features = ["std"] } pallet-subtensor-proxy = { path = "../pallets/proxy", default-features = false, features = ["std"] } pallet-subtensor-utility = { path = "../pallets/utility", default-features = false, features = ["std"] } @@ -50,7 +50,7 @@ substrate-fixed = { git = "https://github.com/encointer/substrate-fixed.git", ta safe-math = { path = "../primitives/safe-math", default-features = false, features = ["std"] } log = { version = "0.4.21", default-features = false, features = ["std"] } approx = "0.5" -sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "a08c7b0f0b6429910a953cbbaec4b4138294fa38", default-features = false, features = ["std"] } +sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } tracing = "0.1" tracing-log = "0.2" tracing-subscriber = { version = "0.3.20", features = ["fmt", "env-filter"] } diff --git a/node/src/service/grandpa_warp_sync.rs b/node/src/service/grandpa_warp_sync.rs index 79b5cc05a1..16507168f5 100644 --- a/node/src/service/grandpa_warp_sync.rs +++ b/node/src/service/grandpa_warp_sync.rs @@ -54,7 +54,6 @@ fn testnet_authorities() -> AuthorityList { hex_literal::hex!("ee70f7b52998c2b4f3d42e509e8360cda92b0cd4ca100cd4d32be5a1ac297909"), hex_literal::hex!("b57a038c9139a060358f3b654df74a1cb6d15bcdb8438bcebd64ce67ec4301eb"), hex_literal::hex!("755f75dfc66aaa3b1e761a8845249509b8bd2fdf0d94cb74e1e12e1e0f4d3519"), - hex_literal::hex!("d97a64267f177505b0565a18677c9f5d4284d7f2eb96d515556e7e52217f82e9"), ] .into_iter() .map(|bytes| { @@ -76,7 +75,7 @@ fn testnet_checkpoints() -> Vec> { hex_literal::hex!("2b001bfdec34d007ab2ac07f712e64d0cb1a6fb4b51f7d47bfb3c7d7336a689b"), ), ( - 3, + 2, 5_534_451, hex_literal::hex!("4d643da5fd7cd2b9ceb795091643e7223819e2a01f942ac049c5b928f7e30dc4"), ), @@ -129,14 +128,14 @@ mod tests { "2b001bfdec34d007ab2ac07f712e64d0cb1a6fb4b51f7d47bfb3c7d7336a689b" )) ); - assert_eq!((second.set_id, second.block.1), (3, 5_534_451)); + assert_eq!((second.set_id, second.block.1), (2, 5_534_451)); assert_eq!( second.block.0, H256::from(hex_literal::hex!( "4d643da5fd7cd2b9ceb795091643e7223819e2a01f942ac049c5b928f7e30dc4" )) ); - assert_eq!(first.authorities.len(), 6); + assert_eq!(first.authorities.len(), 5); assert_eq!(first.authorities, second.authorities); let authority_ids: Vec<&[u8]> = first .authorities @@ -149,7 +148,6 @@ mod tests { hex_literal::hex!("ee70f7b52998c2b4f3d42e509e8360cda92b0cd4ca100cd4d32be5a1ac297909"), hex_literal::hex!("b57a038c9139a060358f3b654df74a1cb6d15bcdb8438bcebd64ce67ec4301eb"), hex_literal::hex!("755f75dfc66aaa3b1e761a8845249509b8bd2fdf0d94cb74e1e12e1e0f4d3519"), - hex_literal::hex!("d97a64267f177505b0565a18677c9f5d4284d7f2eb96d515556e7e52217f82e9"), ]; let expected_authority_ids = expected_authority_ids .iter() From 2da90f547474a8c5dc73a126c1664ce02bcc5142 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Thu, 6 Aug 2026 03:05:40 +0200 Subject: [PATCH 32/58] chore: pin merged SDK GRANDPA fixes --- Cargo.lock | 764 +++++++++++++++++++++---------------------- Cargo.toml | 418 +++++++++++------------ eco-tests/Cargo.toml | 22 +- 3 files changed, 602 insertions(+), 602 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5cd24d9b79..80d546694e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1114,7 +1114,7 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "assets-common" version = "0.22.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "ethereum-standards", @@ -1499,7 +1499,7 @@ checksum = "5a45f9771ced8a774de5e5ebffbe520f52e3943bf5a9a6baa3a5d14a5de1afe6" [[package]] name = "binary-merkle-tree" version = "16.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "hash-db", "log", @@ -1870,7 +1870,7 @@ dependencies = [ [[package]] name = "bp-header-chain" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-runtime", "finality-grandpa", @@ -1887,7 +1887,7 @@ dependencies = [ [[package]] name = "bp-messages" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-runtime", @@ -1903,7 +1903,7 @@ dependencies = [ [[package]] name = "bp-parachains" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-polkadot-core", @@ -1920,7 +1920,7 @@ dependencies = [ [[package]] name = "bp-polkadot-core" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-messages", "bp-runtime", @@ -1936,7 +1936,7 @@ dependencies = [ [[package]] name = "bp-relayers" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-messages", @@ -1954,7 +1954,7 @@ dependencies = [ [[package]] name = "bp-runtime" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -1977,7 +1977,7 @@ dependencies = [ [[package]] name = "bp-test-utils" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-parachains", @@ -1997,7 +1997,7 @@ dependencies = [ [[package]] name = "bp-xcm-bridge-hub" version = "0.7.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-messages", "bp-runtime", @@ -2014,7 +2014,7 @@ dependencies = [ [[package]] name = "bp-xcm-bridge-hub-router" version = "0.18.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -2026,7 +2026,7 @@ dependencies = [ [[package]] name = "bridge-hub-common" version = "0.14.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2045,7 +2045,7 @@ dependencies = [ [[package]] name = "bridge-runtime-common" version = "0.22.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-messages", @@ -2958,7 +2958,7 @@ dependencies = [ [[package]] name = "cumulus-client-bootnodes" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -2984,7 +2984,7 @@ dependencies = [ [[package]] name = "cumulus-client-cli" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "clap", "parity-scale-codec", @@ -3001,7 +3001,7 @@ dependencies = [ [[package]] name = "cumulus-client-collator" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", @@ -3024,7 +3024,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-client-collator", @@ -3071,7 +3071,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-client-pov-recovery", @@ -3103,7 +3103,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-proposer" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "anyhow", "async-trait", @@ -3118,7 +3118,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-relay-chain" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -3141,7 +3141,7 @@ dependencies = [ [[package]] name = "cumulus-client-network" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-relay-chain-interface", @@ -3168,7 +3168,7 @@ dependencies = [ [[package]] name = "cumulus-client-parachain-inherent" version = "0.18.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3178,7 +3178,7 @@ dependencies = [ "parity-scale-codec", "sc-client-api", "sc-consensus-babe", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-inherents", "sp-runtime", "sp-state-machine", @@ -3189,7 +3189,7 @@ dependencies = [ [[package]] name = "cumulus-client-pov-recovery" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3217,7 +3217,7 @@ dependencies = [ [[package]] name = "cumulus-client-service" version = "0.25.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-channel 1.9.0", "cumulus-client-cli", @@ -3257,7 +3257,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-aura-ext" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-pallet-parachain-system", "frame-support", @@ -3274,7 +3274,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-dmp-queue" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "frame-benchmarking", @@ -3291,7 +3291,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bytes", "cumulus-pallet-parachain-system-proc-macro", @@ -3328,7 +3328,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.6.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -3339,7 +3339,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-session-benchmarking" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -3352,7 +3352,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-solo-to-para" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-pallet-parachain-system", "frame-support", @@ -3367,7 +3367,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-weight-reclaim" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-storage-weight-reclaim", "derive-where", @@ -3386,7 +3386,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -3401,7 +3401,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "approx", "bounded-collections 0.2.4", @@ -3426,7 +3426,7 @@ dependencies = [ [[package]] name = "cumulus-ping" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-pallet-xcm", "cumulus-primitives-core", @@ -3441,7 +3441,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-aura" version = "0.18.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "sp-api", "sp-consensus-aura", @@ -3450,7 +3450,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", @@ -3467,7 +3467,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3481,7 +3481,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-proof-size-hostfunction" version = "0.13.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "sp-externalities", "sp-runtime-interface", @@ -3491,7 +3491,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-storage-weight-reclaim" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "cumulus-primitives-proof-size-hostfunction", @@ -3508,7 +3508,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -3525,7 +3525,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-inprocess-interface" version = "0.25.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-channel 1.9.0", "async-trait", @@ -3553,7 +3553,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-interface" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3573,7 +3573,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-minimal-node" version = "0.25.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -3609,7 +3609,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-rpc-interface" version = "0.24.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -3650,7 +3650,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-streams" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-relay-chain-interface", "futures", @@ -3664,7 +3664,7 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -4471,7 +4471,7 @@ dependencies = [ [[package]] name = "ethereum-standards" version = "0.1.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "alloy-core", ] @@ -4853,7 +4853,7 @@ dependencies = [ "rustc-hex", "serde", "serde_json", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", ] [[package]] @@ -5036,7 +5036,7 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fork-tree" version = "13.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", ] @@ -5156,7 +5156,7 @@ checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" [[package]] name = "frame-benchmarking" version = "41.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-support-procedural", @@ -5180,7 +5180,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "49.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "Inflector", "array-bytes 6.2.3", @@ -5245,7 +5245,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-pallet-pov" version = "31.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -5273,7 +5273,7 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" version = "16.1.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -5284,7 +5284,7 @@ dependencies = [ [[package]] name = "frame-election-provider-support" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -5301,7 +5301,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "41.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "aquamarine", "frame-support", @@ -5354,7 +5354,7 @@ dependencies = [ [[package]] name = "frame-metadata-hash-extension" version = "0.9.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "const-hex", @@ -5370,7 +5370,7 @@ dependencies = [ [[package]] name = "frame-storage-access-test-runtime" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-pallet-parachain-system", "parity-scale-codec", @@ -5384,7 +5384,7 @@ dependencies = [ [[package]] name = "frame-support" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "aquamarine", "array-bytes 6.2.3", @@ -5425,7 +5425,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "34.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "Inflector", "cfg-expr", @@ -5439,14 +5439,14 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "syn 2.0.106", ] [[package]] name = "frame-support-procedural-core" version = "34.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cfg-expr", "frame-support-procedural-tools 13.0.1", @@ -5471,7 +5471,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "13.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support-procedural-tools-derive 12.0.0", "proc-macro-crate 3.4.0", @@ -5494,7 +5494,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro2", "quote", @@ -5504,7 +5504,7 @@ dependencies = [ [[package]] name = "frame-system" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cfg-if", "docify", @@ -5523,7 +5523,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -5537,7 +5537,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "parity-scale-codec", @@ -5547,7 +5547,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.47.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "parity-scale-codec", @@ -8287,7 +8287,7 @@ dependencies = [ [[package]] name = "mmr-gadget" version = "46.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "log", @@ -8306,7 +8306,7 @@ dependencies = [ [[package]] name = "mmr-rpc" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -9284,7 +9284,7 @@ dependencies = [ [[package]] name = "pallet-alliance" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "frame-benchmarking", @@ -9296,7 +9296,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-io", "sp-runtime", ] @@ -9320,7 +9320,7 @@ dependencies = [ [[package]] name = "pallet-asset-conversion" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9338,7 +9338,7 @@ dependencies = [ [[package]] name = "pallet-asset-conversion-ops" version = "0.9.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9356,7 +9356,7 @@ dependencies = [ [[package]] name = "pallet-asset-conversion-tx-payment" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9371,7 +9371,7 @@ dependencies = [ [[package]] name = "pallet-asset-rate" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9385,7 +9385,7 @@ dependencies = [ [[package]] name = "pallet-asset-rewards" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9403,7 +9403,7 @@ dependencies = [ [[package]] name = "pallet-asset-tx-payment" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9419,7 +9419,7 @@ dependencies = [ [[package]] name = "pallet-assets" version = "43.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "ethereum-standards", "frame-benchmarking", @@ -9437,7 +9437,7 @@ dependencies = [ [[package]] name = "pallet-assets-freezer" version = "0.8.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "pallet-assets", @@ -9449,7 +9449,7 @@ dependencies = [ [[package]] name = "pallet-assets-holder" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9464,7 +9464,7 @@ dependencies = [ [[package]] name = "pallet-atomic-swap" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -9474,7 +9474,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -9490,7 +9490,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -9505,7 +9505,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -9518,7 +9518,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9541,7 +9541,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "aquamarine", "docify", @@ -9562,7 +9562,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -9591,7 +9591,7 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -9610,7 +9610,7 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "binary-merkle-tree", @@ -9635,7 +9635,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9652,7 +9652,7 @@ dependencies = [ [[package]] name = "pallet-bridge-grandpa" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-runtime", @@ -9671,7 +9671,7 @@ dependencies = [ [[package]] name = "pallet-bridge-messages" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-messages", @@ -9690,7 +9690,7 @@ dependencies = [ [[package]] name = "pallet-bridge-parachains" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-parachains", @@ -9710,7 +9710,7 @@ dependencies = [ [[package]] name = "pallet-bridge-relayers" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-header-chain", "bp-messages", @@ -9733,7 +9733,7 @@ dependencies = [ [[package]] name = "pallet-broker" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "frame-benchmarking", @@ -9751,7 +9751,7 @@ dependencies = [ [[package]] name = "pallet-child-bounties" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9769,7 +9769,7 @@ dependencies = [ [[package]] name = "pallet-collator-selection" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9788,7 +9788,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -9805,7 +9805,7 @@ dependencies = [ [[package]] name = "pallet-collective-content" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9846,7 +9846,7 @@ dependencies = [ [[package]] name = "pallet-contracts" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "environmental", "frame-benchmarking", @@ -9877,7 +9877,7 @@ dependencies = [ [[package]] name = "pallet-contracts-mock-network" version = "18.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -9908,7 +9908,7 @@ dependencies = [ [[package]] name = "pallet-contracts-proc-macro" version = "23.0.3" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro2", "quote", @@ -9918,7 +9918,7 @@ dependencies = [ [[package]] name = "pallet-contracts-uapi" version = "14.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitflags 1.3.2", "parity-scale-codec", @@ -9929,7 +9929,7 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "assert_matches", "frame-benchmarking", @@ -9945,7 +9945,7 @@ dependencies = [ [[package]] name = "pallet-core-fellowship" version = "25.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9983,7 +9983,7 @@ dependencies = [ [[package]] name = "pallet-delegated-staking" version = "8.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -9998,7 +9998,7 @@ dependencies = [ [[package]] name = "pallet-democracy" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10015,7 +10015,7 @@ dependencies = [ [[package]] name = "pallet-dev-mode" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -10064,7 +10064,7 @@ dependencies = [ [[package]] name = "pallet-dummy-dim" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10082,7 +10082,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-block" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10103,7 +10103,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10124,7 +10124,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-support-benchmarking" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10137,7 +10137,7 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10256,7 +10256,7 @@ dependencies = [ [[package]] name = "pallet-fast-unstake" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -10274,7 +10274,7 @@ dependencies = [ [[package]] name = "pallet-glutton" version = "27.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "blake2 0.10.6", "frame-benchmarking", @@ -10292,7 +10292,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10328,7 +10328,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "enumflags2", "frame-benchmarking", @@ -10344,7 +10344,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10363,7 +10363,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10378,7 +10378,7 @@ dependencies = [ [[package]] name = "pallet-insecure-randomness-collective-flip" version = "29.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -10411,7 +10411,7 @@ dependencies = [ [[package]] name = "pallet-lottery" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10424,7 +10424,7 @@ dependencies = [ [[package]] name = "pallet-membership" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10440,7 +10440,7 @@ dependencies = [ [[package]] name = "pallet-message-queue" version = "44.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "environmental", "frame-benchmarking", @@ -10459,7 +10459,7 @@ dependencies = [ [[package]] name = "pallet-meta-tx" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -10477,7 +10477,7 @@ dependencies = [ [[package]] name = "pallet-migrations" version = "11.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -10496,7 +10496,7 @@ dependencies = [ [[package]] name = "pallet-mixnet" version = "0.17.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "parity-scale-codec", @@ -10510,7 +10510,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "parity-scale-codec", @@ -10522,7 +10522,7 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "parity-scale-codec", @@ -10533,7 +10533,7 @@ dependencies = [ [[package]] name = "pallet-nft-fractionalization" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "pallet-assets", @@ -10546,7 +10546,7 @@ dependencies = [ [[package]] name = "pallet-nfts" version = "35.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "enumflags2", "frame-benchmarking", @@ -10563,7 +10563,7 @@ dependencies = [ [[package]] name = "pallet-nis" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -10573,7 +10573,7 @@ dependencies = [ [[package]] name = "pallet-node-authorization" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "parity-scale-codec", @@ -10584,7 +10584,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" version = "39.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -10602,7 +10602,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" version = "39.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10622,7 +10622,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -10632,7 +10632,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -10647,7 +10647,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -10670,7 +10670,7 @@ dependencies = [ [[package]] name = "pallet-origin-restriction" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10688,7 +10688,7 @@ dependencies = [ [[package]] name = "pallet-paged-list" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "parity-scale-codec", @@ -10699,7 +10699,7 @@ dependencies = [ [[package]] name = "pallet-parameters" version = "0.12.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -10716,7 +10716,7 @@ dependencies = [ [[package]] name = "pallet-people" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10734,7 +10734,7 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10750,7 +10750,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -10762,7 +10762,7 @@ dependencies = [ [[package]] name = "pallet-ranked-collective" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10780,7 +10780,7 @@ dependencies = [ [[package]] name = "pallet-recovery" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -10790,7 +10790,7 @@ dependencies = [ [[package]] name = "pallet-referenda" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "assert_matches", "frame-benchmarking", @@ -10808,7 +10808,7 @@ dependencies = [ [[package]] name = "pallet-remark" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -10823,7 +10823,7 @@ dependencies = [ [[package]] name = "pallet-revive" version = "0.7.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "alloy-core", "derive_more 0.99.20", @@ -10869,7 +10869,7 @@ dependencies = [ [[package]] name = "pallet-revive-fixtures" version = "0.4.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "anyhow", "cargo_metadata", @@ -10883,7 +10883,7 @@ dependencies = [ [[package]] name = "pallet-revive-proc-macro" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro2", "quote", @@ -10893,7 +10893,7 @@ dependencies = [ [[package]] name = "pallet-revive-uapi" version = "0.5.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitflags 1.3.2", "pallet-revive-proc-macro", @@ -10905,7 +10905,7 @@ dependencies = [ [[package]] name = "pallet-root-offences" version = "38.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -10921,7 +10921,7 @@ dependencies = [ [[package]] name = "pallet-root-testing" version = "17.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -10934,7 +10934,7 @@ dependencies = [ [[package]] name = "pallet-safe-mode" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "pallet-balances", @@ -10948,7 +10948,7 @@ dependencies = [ [[package]] name = "pallet-salary" version = "26.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "pallet-ranked-collective", @@ -10960,7 +10960,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -10977,7 +10977,7 @@ dependencies = [ [[package]] name = "pallet-scored-pool" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -10990,7 +10990,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -11011,7 +11011,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11057,7 +11057,7 @@ dependencies = [ [[package]] name = "pallet-skip-feeless-payment" version = "16.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -11069,7 +11069,7 @@ dependencies = [ [[package]] name = "pallet-society" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11086,7 +11086,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -11108,7 +11108,7 @@ dependencies = [ [[package]] name = "pallet-staking-async" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -11131,7 +11131,7 @@ dependencies = [ [[package]] name = "pallet-staking-async-ah-client" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -11150,7 +11150,7 @@ dependencies = [ [[package]] name = "pallet-staking-async-rc-client" version = "0.2.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -11167,7 +11167,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -11178,7 +11178,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-fn" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "sp-arithmetic", @@ -11187,7 +11187,7 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" version = "27.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "sp-api", @@ -11197,7 +11197,7 @@ dependencies = [ [[package]] name = "pallet-state-trie-migration" version = "46.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11213,7 +11213,7 @@ dependencies = [ [[package]] name = "pallet-statement" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", @@ -11377,7 +11377,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -11392,7 +11392,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -11410,7 +11410,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11428,7 +11428,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11443,7 +11443,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "44.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -11459,7 +11459,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -11471,7 +11471,7 @@ dependencies = [ [[package]] name = "pallet-transaction-storage" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "frame-benchmarking", @@ -11490,7 +11490,7 @@ dependencies = [ [[package]] name = "pallet-treasury" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -11509,7 +11509,7 @@ dependencies = [ [[package]] name = "pallet-tx-pause" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "parity-scale-codec", @@ -11520,7 +11520,7 @@ dependencies = [ [[package]] name = "pallet-uniques" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11534,7 +11534,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11549,7 +11549,7 @@ dependencies = [ [[package]] name = "pallet-verify-signature" version = "0.4.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11564,7 +11564,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11578,7 +11578,7 @@ dependencies = [ [[package]] name = "pallet-whitelist" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "polkadot-sdk-frame", @@ -11588,7 +11588,7 @@ dependencies = [ [[package]] name = "pallet-xcm" version = "20.1.3" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bounded-collections 0.2.4", "frame-benchmarking", @@ -11614,7 +11614,7 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-benchmarking", "frame-support", @@ -11631,7 +11631,7 @@ dependencies = [ [[package]] name = "pallet-xcm-bridge-hub" version = "0.17.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-messages", "bp-runtime", @@ -11653,7 +11653,7 @@ dependencies = [ [[package]] name = "pallet-xcm-bridge-hub-router" version = "0.19.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-xcm-bridge-hub-router", "frame-benchmarking", @@ -11673,7 +11673,7 @@ dependencies = [ [[package]] name = "parachains-common" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "cumulus-primitives-utility", @@ -12035,7 +12035,7 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "polkadot-approval-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "futures-timer", @@ -12053,7 +12053,7 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "futures-timer", @@ -12068,7 +12068,7 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "fatality", "futures", @@ -12091,7 +12091,7 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "fatality", @@ -12124,7 +12124,7 @@ dependencies = [ [[package]] name = "polkadot-cli" version = "25.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "clap", "frame-benchmarking-cli", @@ -12148,7 +12148,7 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "fatality", @@ -12171,7 +12171,7 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" version = "18.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -12182,7 +12182,7 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "fatality", "futures", @@ -12204,7 +12204,7 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -12218,7 +12218,7 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" version = "24.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "futures-timer", @@ -12231,7 +12231,7 @@ dependencies = [ "sc-network", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-keystore", "tracing-gum", ] @@ -12239,7 +12239,7 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "always-assert", "async-trait", @@ -12262,7 +12262,7 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "parity-scale-codec", @@ -12280,7 +12280,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "bitvec", @@ -12312,7 +12312,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting-parallel" version = "0.7.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -12336,7 +12336,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "futures", @@ -12355,7 +12355,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "fatality", @@ -12376,7 +12376,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "polkadot-node-subsystem", @@ -12391,7 +12391,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -12413,7 +12413,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "polkadot-node-metrics", @@ -12427,7 +12427,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "futures-timer", @@ -12443,7 +12443,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "fatality", "futures", @@ -12461,7 +12461,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -12478,7 +12478,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-prospective-parachains" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "fatality", "futures", @@ -12492,7 +12492,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "fatality", @@ -12509,7 +12509,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "always-assert", "array-bytes 6.2.3", @@ -12537,7 +12537,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-checker" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "polkadot-node-subsystem", @@ -12550,7 +12550,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-common" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cpu-time", "futures", @@ -12565,7 +12565,7 @@ dependencies = [ "sc-executor-wasmtime", "seccompiler", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-externalities", "sp-io", "sp-tracing", @@ -12576,7 +12576,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-runtime-api" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "polkadot-node-metrics", @@ -12591,7 +12591,7 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bs58", "futures", @@ -12608,7 +12608,7 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-channel 1.9.0", "async-trait", @@ -12633,7 +12633,7 @@ dependencies = [ [[package]] name = "polkadot-node-primitives" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "bounded-vec", @@ -12657,7 +12657,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "polkadot-node-subsystem-types", "polkadot-overseer", @@ -12666,7 +12666,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "derive_more 0.99.20", @@ -12694,7 +12694,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" version = "24.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "fatality", "futures", @@ -12725,7 +12725,7 @@ dependencies = [ [[package]] name = "polkadot-omni-node-lib" version = "0.7.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "clap", @@ -12813,7 +12813,7 @@ dependencies = [ [[package]] name = "polkadot-overseer" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -12833,7 +12833,7 @@ dependencies = [ [[package]] name = "polkadot-parachain-primitives" version = "17.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bounded-collections 0.2.4", "derive_more 0.99.20", @@ -12849,7 +12849,7 @@ dependencies = [ [[package]] name = "polkadot-primitives" version = "19.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "bounded-collections 0.2.4", @@ -12878,7 +12878,7 @@ dependencies = [ [[package]] name = "polkadot-rpc" version = "25.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "jsonrpsee", "mmr-rpc", @@ -12911,7 +12911,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "frame-benchmarking", @@ -12961,7 +12961,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-metrics" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bs58", "frame-benchmarking", @@ -12973,7 +12973,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" version = "20.0.2" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitflags 1.3.2", "bitvec", @@ -13021,7 +13021,7 @@ dependencies = [ [[package]] name = "polkadot-sdk" version = "2506.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "assets-common", "bridge-hub-common", @@ -13179,7 +13179,7 @@ dependencies = [ [[package]] name = "polkadot-sdk-frame" version = "0.10.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-benchmarking", @@ -13214,7 +13214,7 @@ dependencies = [ [[package]] name = "polkadot-service" version = "25.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "frame-benchmarking", @@ -13324,7 +13324,7 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitvec", "fatality", @@ -13344,7 +13344,7 @@ dependencies = [ [[package]] name = "polkadot-statement-table" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -13651,7 +13651,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "syn 2.0.106", ] @@ -13833,7 +13833,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "syn 2.0.106", ] @@ -14673,7 +14673,7 @@ dependencies = [ [[package]] name = "rococo-runtime" version = "24.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "binary-merkle-tree", "bitvec", @@ -14771,7 +14771,7 @@ dependencies = [ [[package]] name = "rococo-runtime-constants" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "polkadot-primitives", @@ -15201,7 +15201,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "32.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "sp-core", @@ -15212,7 +15212,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -15243,7 +15243,7 @@ dependencies = [ [[package]] name = "sc-basic-authorship" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "log", @@ -15265,7 +15265,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.45.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "sp-api", @@ -15280,7 +15280,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "44.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "clap", @@ -15296,7 +15296,7 @@ dependencies = [ "serde_json", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-genesis-builder", "sp-io", "sp-runtime", @@ -15307,7 +15307,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -15318,7 +15318,7 @@ dependencies = [ [[package]] name = "sc-cli" version = "0.53.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "chrono", @@ -15360,7 +15360,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "fnv", "futures", @@ -15386,7 +15386,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.47.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "hash-db", "kvdb", @@ -15414,7 +15414,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -15437,7 +15437,7 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -15466,7 +15466,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "fork-tree", @@ -15491,7 +15491,7 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-slots", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-inherents", "sp-keystore", "sp-runtime", @@ -15502,7 +15502,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "jsonrpsee", @@ -15524,7 +15524,7 @@ dependencies = [ [[package]] name = "sc-consensus-beefy" version = "30.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15558,7 +15558,7 @@ dependencies = [ [[package]] name = "sc-consensus-beefy-rpc" version = "30.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "jsonrpsee", @@ -15578,7 +15578,7 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "fork-tree", "parity-scale-codec", @@ -15591,7 +15591,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" version = "0.36.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "ahash 0.8.12", "array-bytes 6.2.3", @@ -15625,7 +15625,7 @@ dependencies = [ "sp-consensus", "sp-consensus-grandpa", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", @@ -15635,7 +15635,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa-rpc" version = "0.36.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "finality-grandpa", "futures", @@ -15655,7 +15655,7 @@ dependencies = [ [[package]] name = "sc-consensus-manual-seal" version = "0.52.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "assert_matches", "async-trait", @@ -15690,7 +15690,7 @@ dependencies = [ [[package]] name = "sc-consensus-slots" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -15713,7 +15713,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "parking_lot 0.12.5", @@ -15736,7 +15736,7 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.39.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "polkavm 0.24.0", "sc-allocator", @@ -15749,7 +15749,7 @@ dependencies = [ [[package]] name = "sc-executor-polkavm" version = "0.36.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "polkavm 0.24.0", @@ -15760,7 +15760,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.39.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "anyhow", "log", @@ -15776,7 +15776,7 @@ dependencies = [ [[package]] name = "sc-informant" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "console", "futures", @@ -15792,7 +15792,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "36.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "parking_lot 0.12.5", @@ -15806,7 +15806,7 @@ dependencies = [ [[package]] name = "sc-mixnet" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "arrayvec 0.7.6", @@ -15834,7 +15834,7 @@ dependencies = [ [[package]] name = "sc-network" version = "0.51.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15884,7 +15884,7 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.49.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bitflags 1.3.2", "parity-scale-codec", @@ -15894,7 +15894,7 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "ahash 0.8.12", "futures", @@ -15913,7 +15913,7 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15934,7 +15934,7 @@ dependencies = [ [[package]] name = "sc-network-statement" version = "0.33.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15954,7 +15954,7 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "async-channel 1.9.0", @@ -15989,7 +15989,7 @@ dependencies = [ [[package]] name = "sc-network-transactions" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "futures", @@ -16008,7 +16008,7 @@ dependencies = [ [[package]] name = "sc-network-types" version = "0.17.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bs58", "bytes", @@ -16029,7 +16029,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "46.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bytes", "fnv", @@ -16063,7 +16063,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.20.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -16072,7 +16072,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "46.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "jsonrpsee", @@ -16104,7 +16104,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.50.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -16124,7 +16124,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "dyn-clone", "forwarded-header-value", @@ -16148,7 +16148,7 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "futures", @@ -16181,13 +16181,13 @@ dependencies = [ [[package]] name = "sc-runtime-utilities" version = "0.3.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "sc-executor", "sc-executor-common", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-state-machine", "sp-wasm-interface", "thiserror 1.0.69", @@ -16196,7 +16196,7 @@ dependencies = [ [[package]] name = "sc-service" version = "0.52.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "directories", @@ -16260,7 +16260,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.39.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "parity-scale-codec", @@ -16271,7 +16271,7 @@ dependencies = [ [[package]] name = "sc-statement-store" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "parity-db", @@ -16290,7 +16290,7 @@ dependencies = [ [[package]] name = "sc-storage-monitor" version = "0.25.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "clap", "fs4", @@ -16303,7 +16303,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.51.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -16322,7 +16322,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "43.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "derive_more 0.99.20", "futures", @@ -16335,14 +16335,14 @@ dependencies = [ "serde", "serde_json", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-io", ] [[package]] name = "sc-telemetry" version = "29.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "chrono", "futures", @@ -16361,7 +16361,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "chrono", "console", @@ -16389,7 +16389,7 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "11.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -16400,7 +16400,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool" version = "40.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -16417,7 +16417,7 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-runtime", "sp-tracing", "sp-transaction-pool", @@ -16431,7 +16431,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -16448,7 +16448,7 @@ dependencies = [ [[package]] name = "sc-utils" version = "19.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-channel 1.9.0", "futures", @@ -17204,7 +17204,7 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "slot-range-helper" version = "18.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "enumn", "parity-scale-codec", @@ -17488,7 +17488,7 @@ dependencies = [ [[package]] name = "snowbridge-core" version = "0.14.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bp-relayers", "frame-support", @@ -17583,7 +17583,7 @@ dependencies = [ [[package]] name = "sp-api" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "hash-db", @@ -17605,7 +17605,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "23.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "Inflector", "blake2 0.10.6", @@ -17619,7 +17619,7 @@ dependencies = [ [[package]] name = "sp-application-crypto" version = "41.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -17631,7 +17631,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "27.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "integer-sqrt", @@ -17645,7 +17645,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -17657,7 +17657,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "sp-api", "sp-inherents", @@ -17667,7 +17667,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "futures", "parity-scale-codec", @@ -17686,7 +17686,7 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "futures", @@ -17700,7 +17700,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "parity-scale-codec", @@ -17716,7 +17716,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "parity-scale-codec", @@ -17734,7 +17734,7 @@ dependencies = [ [[package]] name = "sp-consensus-beefy" version = "25.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -17742,7 +17742,7 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-io", "sp-keystore", "sp-mmr-primitives", @@ -17754,7 +17754,7 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" version = "24.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "finality-grandpa", "log", @@ -17771,7 +17771,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -17782,7 +17782,7 @@ dependencies = [ [[package]] name = "sp-core" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "ark-vrf", "array-bytes 6.2.3", @@ -17813,7 +17813,7 @@ dependencies = [ "secrecy 0.8.0", "serde", "sha2 0.10.9", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", @@ -17830,7 +17830,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.16.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -17864,7 +17864,7 @@ dependencies = [ [[package]] name = "sp-crypto-hashing" version = "0.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "blake2b_simd", "byteorder", @@ -17877,17 +17877,17 @@ dependencies = [ [[package]] name = "sp-crypto-hashing-proc-macro" version = "0.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "quote", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "syn 2.0.106", ] [[package]] name = "sp-database" version = "10.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "kvdb", "parking_lot 0.12.5", @@ -17896,7 +17896,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "proc-macro2", "quote", @@ -17906,7 +17906,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.30.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "environmental", "parity-scale-codec", @@ -17916,7 +17916,7 @@ dependencies = [ [[package]] name = "sp-genesis-builder" version = "0.18.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -17928,7 +17928,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -17941,7 +17941,7 @@ dependencies = [ [[package]] name = "sp-io" version = "41.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bytes", "docify", @@ -17953,7 +17953,7 @@ dependencies = [ "rustversion", "secp256k1 0.28.2", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-externalities", "sp-keystore", "sp-runtime-interface", @@ -17967,7 +17967,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "sp-core", "sp-runtime", @@ -17977,7 +17977,7 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.43.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "parking_lot 0.12.5", @@ -17988,7 +17988,7 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "11.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "thiserror 1.0.69", "zstd 0.12.4", @@ -17997,7 +17997,7 @@ dependencies = [ [[package]] name = "sp-metadata-ir" version = "0.11.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-metadata 23.0.0", "parity-scale-codec", @@ -18007,7 +18007,7 @@ dependencies = [ [[package]] name = "sp-mixnet" version = "0.15.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -18018,7 +18018,7 @@ dependencies = [ [[package]] name = "sp-mmr-primitives" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "log", "parity-scale-codec", @@ -18035,7 +18035,7 @@ dependencies = [ [[package]] name = "sp-npos-elections" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -18048,7 +18048,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "sp-api", "sp-core", @@ -18058,7 +18058,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "13.0.2" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "backtrace", "regex", @@ -18067,7 +18067,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "35.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "rustc-hash 1.1.0", "serde", @@ -18077,7 +18077,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "42.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "binary-merkle-tree", "docify", @@ -18106,7 +18106,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "30.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -18125,7 +18125,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "19.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "Inflector", "expander", @@ -18138,7 +18138,7 @@ dependencies = [ [[package]] name = "sp-session" version = "39.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -18152,7 +18152,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "39.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -18165,7 +18165,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.46.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "hash-db", "log", @@ -18185,7 +18185,7 @@ dependencies = [ [[package]] name = "sp-statement-store" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "aes-gcm", "curve25519-dalek", @@ -18198,7 +18198,7 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-core", - "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd)", + "sp-crypto-hashing 0.1.0 (git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a)", "sp-externalities", "sp-runtime", "sp-runtime-interface", @@ -18209,12 +18209,12 @@ dependencies = [ [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" [[package]] name = "sp-storage" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "impl-serde", "parity-scale-codec", @@ -18226,7 +18226,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "parity-scale-codec", @@ -18238,7 +18238,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "17.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "tracing", @@ -18249,7 +18249,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "sp-api", "sp-runtime", @@ -18258,7 +18258,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "37.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "async-trait", "parity-scale-codec", @@ -18272,7 +18272,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "ahash 0.8.12", "foldhash 0.1.5", @@ -18297,7 +18297,7 @@ dependencies = [ [[package]] name = "sp-version" version = "40.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "impl-serde", "parity-scale-codec", @@ -18314,7 +18314,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "15.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "proc-macro-warning", @@ -18326,7 +18326,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "22.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -18338,7 +18338,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "32.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "bounded-collections 0.2.4", "parity-scale-codec", @@ -18512,7 +18512,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "staging-chain-spec-builder" version = "12.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "clap", "docify", @@ -18525,7 +18525,7 @@ dependencies = [ [[package]] name = "staging-node-inspect" version = "0.29.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "clap", "parity-scale-codec", @@ -18543,7 +18543,7 @@ dependencies = [ [[package]] name = "staging-parachain-info" version = "0.21.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -18556,7 +18556,7 @@ dependencies = [ [[package]] name = "staging-xcm" version = "17.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "bounded-collections 0.2.4", @@ -18577,7 +18577,7 @@ dependencies = [ [[package]] name = "staging-xcm-builder" version = "21.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "environmental", "frame-support", @@ -18601,7 +18601,7 @@ dependencies = [ [[package]] name = "staging-xcm-executor" version = "20.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "environmental", "frame-benchmarking", @@ -18655,7 +18655,7 @@ dependencies = [ [[package]] name = "stc-shield" version = "0.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "anyhow", "async-trait", @@ -18676,7 +18676,7 @@ dependencies = [ [[package]] name = "stp-shield" version = "0.1.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "parity-scale-codec", "scale-info", @@ -18746,7 +18746,7 @@ dependencies = [ [[package]] name = "substrate-bip39" version = "0.6.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "hmac 0.12.1", "pbkdf2 0.12.2", @@ -18771,7 +18771,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "11.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" [[package]] name = "substrate-fixed" @@ -18787,7 +18787,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "45.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "docify", "frame-system-rpc-runtime-api", @@ -18807,7 +18807,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.17.6" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "http-body-util", "hyper 1.7.0", @@ -18821,7 +18821,7 @@ dependencies = [ [[package]] name = "substrate-state-trie-migration-rpc" version = "44.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -18848,7 +18848,7 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "27.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "array-bytes 6.2.3", "build-helper", @@ -19957,7 +19957,7 @@ dependencies = [ [[package]] name = "tracing-gum" version = "20.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "coarsetime", "polkadot-primitives", @@ -19968,7 +19968,7 @@ dependencies = [ [[package]] name = "tracing-gum-proc-macro" version = "5.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "expander", "proc-macro-crate 3.4.0", @@ -20973,7 +20973,7 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "westend-runtime" version = "24.0.1" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "binary-merkle-tree", "bitvec", @@ -21080,7 +21080,7 @@ dependencies = [ [[package]] name = "westend-runtime-constants" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "polkadot-primitives", @@ -21730,7 +21730,7 @@ dependencies = [ [[package]] name = "xcm-procedural" version = "11.0.2" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "Inflector", "proc-macro2", @@ -21741,7 +21741,7 @@ dependencies = [ [[package]] name = "xcm-runtime-apis" version = "0.8.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "parity-scale-codec", @@ -21755,7 +21755,7 @@ dependencies = [ [[package]] name = "xcm-simulator" version = "21.0.0" -source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd#be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" +source = "git+https://github.com/RaoFoundation/polkadot-sdk.git?rev=cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a#cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" dependencies = [ "frame-support", "frame-system", diff --git a/Cargo.toml b/Cargo.toml index 3247664d7a..c65e70952e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,8 +79,8 @@ subtensor-runtime-common = { default-features = false, path = "common" } subtensor-swap-interface = { default-features = false, path = "primitives/swap-interface" } subtensor-transaction-fee = { default-features = false, path = "pallets/transaction-fee" } subtensor-chain-extensions = { default-features = false, path = "chain-extensions" } -stp-shield = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -stc-shield = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +stp-shield = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +stc-shield = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } ed25519-dalek = { version = "2.1.0", default-features = false } async-trait = "0.1" @@ -138,122 +138,122 @@ num_enum = { version = "0.7.4", default-features = false } environmental = { version = "1.1.4", default-features = false } tokio = { version = "1.38", default-features = false } -frame = { package = "polkadot-sdk-frame", git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-executive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-system-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-try-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-benchmarking-cli = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -frame-metadata-hash-extension = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame = { package = "polkadot-sdk-frame", git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-executive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-system-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-try-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-benchmarking-cli = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +frame-metadata-hash-extension = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } frame-metadata = { version = "23.0.0", default-features = false } pallet-subtensor-proxy = { path = "pallets/proxy", default-features = false } pallet-subtensor-utility = { path = "pallets/utility", default-features = false } -pallet-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-balances = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-insecure-randomness-collective-flip = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-multisig = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-preimage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-safe-mode = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-scheduler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-sudo = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-transaction-payment = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-transaction-payment-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-root-testing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-contracts = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +pallet-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-balances = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-multisig = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-preimage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-safe-mode = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-scheduler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-sudo = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-transaction-payment = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-transaction-payment-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-root-testing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-contracts = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } # NPoS -frame-election-provider-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-authorship = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-bags-list = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-election-provider-multi-phase = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-fast-unstake = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-nomination-pools = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-nomination-pools-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-staking-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-staking-reward-fn = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-staking-reward-curve = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -pallet-offences = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +frame-election-provider-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-authorship = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-bags-list = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-election-provider-multi-phase = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-fast-unstake = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-nomination-pools = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-nomination-pools-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-staking-runtime-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-staking-reward-fn = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-staking-reward-curve = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +pallet-offences = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } -sc-basic-authorship = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-cli = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-client-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus-babe-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus-grandpa-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus-epochs = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-chain-spec-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-chain-spec = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-executor = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-network = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-rpc-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-service = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-telemetry = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-transaction-pool-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-consensus-manual-seal = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sc-network-sync = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sc-basic-authorship = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-cli = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-client-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus-babe-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus-grandpa-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus-epochs = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-chain-spec-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-chain-spec = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-executor = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-network = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-rpc-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-service = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-telemetry = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-transaction-pool-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-consensus-manual-seal = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sc-network-sync = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } -sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-arithmetic = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-blockchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-npos-elections = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-genesis-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-inherents = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-keyring = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-storage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-version = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-weights = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-crypto-hashing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-application-crypto = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-debug-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-externalities = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-runtime-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-arithmetic = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-blockchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-npos-elections = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-genesis-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-inherents = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-keyring = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-storage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-version = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-weights = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-crypto-hashing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-application-crypto = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-debug-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-externalities = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-runtime-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } -substrate-build-script-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +substrate-build-script-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } substrate-fixed = { git = "https://github.com/encointer/substrate-fixed.git", tag = "v0.6.0", default-features = false } -substrate-frame-rpc-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -substrate-wasm-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -substrate-prometheus-endpoint = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +substrate-frame-rpc-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +substrate-wasm-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +substrate-prometheus-endpoint = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } -polkadot-sdk = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +polkadot-sdk = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } -runtime-common = { package = "polkadot-runtime-common", git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +runtime-common = { package = "polkadot-runtime-common", git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } # Frontier # Vendored via `git subtree` from RaoFoundation/frontier @@ -292,8 +292,8 @@ pallet-hotfix-sufficients = { path = "vendor/frontier/frame/hotfix-sufficients", #DRAND pallet-drand = { path = "pallets/drand", default-features = false } -sp-crypto-ec-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } -sp-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false } +sp-crypto-ec-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } +sp-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false } w3f-bls = { path = "vendor/w3f-bls", default-features = false } ark-crypto-primitives = { version = "0.4.0", default-features = false } ark-scale = { version = "0.0.11", default-features = false } @@ -344,104 +344,104 @@ zstd-safe = { git = "https://github.com/gztensor/zstd-safe", rev = "42cc34ef6abe # build. Redirect the frontier-side polkadot-sdk crates to the RaoFoundation # remote at the same rev so the whole graph resolves to a single copy. [patch."https://github.com/opentensor/polkadot-sdk"] -binary-merkle-tree = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -cumulus-primitives-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -cumulus-primitives-proof-size-hostfunction = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -cumulus-primitives-storage-weight-reclaim = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -fork-tree = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -frame-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -frame-support-procedural = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -frame-support-procedural-tools = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -frame-support-procedural-tools-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -polkadot-core-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -polkadot-parachain-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -polkadot-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-allocator = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-chain-spec = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-chain-spec-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-client-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-client-db = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-consensus-epochs = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-executor = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-executor-common = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-executor-polkavm = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-executor-wasmtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-informant = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-mixnet = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-network = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-network-common = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-network-light = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-network-sync = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-network-transactions = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-network-types = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-rpc-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-rpc-server = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-rpc-spec-v2 = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-service = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-state-db = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-sysinfo = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-telemetry = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-tracing-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-transaction-pool-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sc-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-api-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-application-crypto = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-arithmetic = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-blockchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-crypto-hashing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-crypto-hashing-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-database = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-debug-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-externalities = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-genesis-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-inherents = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-maybe-compressed-blob = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-metadata-ir = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-mixnet = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-panic-handler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-runtime-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-runtime-interface-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-state-machine = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-statement-store = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-storage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-transaction-storage-proof = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-trie = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-version = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-version-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-wasm-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -sp-weights = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -staging-xcm = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -substrate-bip39 = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -substrate-prometheus-endpoint = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } -xcm-procedural = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd" } +binary-merkle-tree = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +cumulus-primitives-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +cumulus-primitives-proof-size-hostfunction = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +cumulus-primitives-storage-weight-reclaim = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +fork-tree = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +frame-benchmarking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +frame-support-procedural = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +frame-support-procedural-tools = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +frame-support-procedural-tools-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +polkadot-core-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +polkadot-parachain-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +polkadot-primitives = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-allocator = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-chain-spec = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-chain-spec-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-client-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-client-db = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-consensus-epochs = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-executor = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-executor-common = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-executor-polkavm = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-executor-wasmtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-informant = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-mixnet = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-network = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-network-common = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-network-light = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-network-sync = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-network-transactions = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-network-types = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-rpc-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-rpc-server = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-rpc-spec-v2 = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-service = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-state-db = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-sysinfo = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-telemetry = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-tracing-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-transaction-pool-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sc-utils = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-api-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-application-crypto = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-arithmetic = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-authority-discovery = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-block-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-blockchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-consensus = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-consensus-aura = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-consensus-babe = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-consensus-grandpa = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-consensus-slots = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-crypto-hashing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-crypto-hashing-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-database = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-debug-derive = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-externalities = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-genesis-builder = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-inherents = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-keystore = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-maybe-compressed-blob = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-metadata-ir = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-mixnet = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-offchain = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-panic-handler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-rpc = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-runtime-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-runtime-interface-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-session = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-staking = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-state-machine = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-statement-store = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-storage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-timestamp = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-transaction-pool = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-transaction-storage-proof = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-trie = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-version = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-version-proc-macro = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-wasm-interface = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +sp-weights = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +staging-xcm = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +substrate-bip39 = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +substrate-prometheus-endpoint = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } +xcm-procedural = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a" } diff --git a/eco-tests/Cargo.toml b/eco-tests/Cargo.toml index 6beea8484c..d485228e5a 100644 --- a/eco-tests/Cargo.toml +++ b/eco-tests/Cargo.toml @@ -23,22 +23,22 @@ useless_conversion = "allow" time = { version = "0.3.47", default-features = false } pallet-subtensor = { path = "../pallets/subtensor", default-features = false, features = ["std"] } pallet-alpha-assets = { path = "../pallets/alpha-assets", default-features = false, features = ["std"] } -frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } -frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } -sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } -sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } -sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } -sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +frame-support = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } +frame-system = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } +sp-core = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } +sp-io = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } +sp-runtime = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } +sp-std = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } codec = { package = "parity-scale-codec", version = "3.7.5", default-features = false, features = ["derive", "std"] } scale-info = { version = "2.11.2", default-features = false, features = ["derive", "std"] } -pallet-balances = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } -pallet-scheduler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } -pallet-preimage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +pallet-balances = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } +pallet-scheduler = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } +pallet-preimage = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } pallet-drand = { path = "../pallets/drand", default-features = false, features = ["std"] } pallet-subtensor-swap = { path = "../pallets/swap", default-features = false, features = ["std"] } pallet-subtensor-swap-runtime-api = { path = "../pallets/swap/runtime-api", default-features = false, features = ["std"] } subtensor-custom-rpc-runtime-api = { path = "../pallets/subtensor/runtime-api", default-features = false, features = ["std"] } -sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +sp-api = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } pallet-crowdloan = { path = "../pallets/crowdloan", default-features = false, features = ["std"] } pallet-subtensor-proxy = { path = "../pallets/proxy", default-features = false, features = ["std"] } pallet-subtensor-utility = { path = "../pallets/utility", default-features = false, features = ["std"] } @@ -50,7 +50,7 @@ substrate-fixed = { git = "https://github.com/encointer/substrate-fixed.git", ta safe-math = { path = "../primitives/safe-math", default-features = false, features = ["std"] } log = { version = "0.4.21", default-features = false, features = ["std"] } approx = "0.5" -sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "be7cc3b1e89a909c0e2dc34fac9cc3488f39e2bd", default-features = false, features = ["std"] } +sp-tracing = { git = "https://github.com/RaoFoundation/polkadot-sdk.git", rev = "cacb4310f20c7cac83eb3ccd8ed5a5ad4212608a", default-features = false, features = ["std"] } tracing = "0.1" tracing-log = "0.2" tracing-subscriber = { version = "0.3.20", features = ["fmt", "env-filter"] } From c1b8d0b48e677d077dcdd952a65dd06bcdc70406 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Thu, 6 Aug 2026 03:45:15 +0200 Subject: [PATCH 33/58] feat: combine btcli v11 UX and wallet compatibility Combine the btcli UX, multisig, dry-run, secret-handling, name-resolution, SDK compatibility, and alpha-fee runtime updates into a single signed change. --- docs/guides/multisig.mdx | 58 +- docs/tx/add-stake.mdx | 13 +- docs/tx/stake-burn.mdx | 20 +- runtime/src/check_nonce.rs | 60 +- runtime/tests/alpha_only_coldkey_fees.rs | 197 ++ sdk/bittensor-core-py/pyproject.toml | 2 +- sdk/bittensor-core/src/keyfiles/mod.rs | 284 ++- sdk/bittensor-core/src/keys/mod.rs | 52 +- sdk/python/bittensor/cli/call.py | 33 +- sdk/python/bittensor/cli/call_names.py | 240 +++ sdk/python/bittensor/cli/commands/evm/keys.py | 72 +- sdk/python/bittensor/cli/commands/root.py | 2 +- sdk/python/bittensor/cli/commands/stake.py | 1 + sdk/python/bittensor/cli/commands/wallet.py | 168 +- sdk/python/bittensor/cli/context.py | 182 +- sdk/python/bittensor/cli/globals.py | 1 + sdk/python/bittensor/cli/helpers.py | 71 +- sdk/python/bittensor/cli/intent_prompts.py | 148 ++ sdk/python/bittensor/cli/main.py | 25 +- sdk/python/bittensor/cli/multisig_helpers.py | 195 +- sdk/python/bittensor/cli/output.py | 22 +- sdk/python/bittensor/cli/prompt.py | 125 +- sdk/python/bittensor/cli/root_helpers.py | 12 +- sdk/python/bittensor/cli/secrets.py | 75 + sdk/python/bittensor/cli/stake_picker.py | 131 +- sdk/python/bittensor/cli/tx.py | 43 +- sdk/python/bittensor/executor.py | 2 + sdk/python/bittensor/intents/governance.py | 33 +- sdk/python/bittensor/intents/multisig.py | 46 +- sdk/python/bittensor/intents/plan.py | 19 +- sdk/python/bittensor/intents/staking.py | 68 +- sdk/python/bittensor/multisig.py | 214 +- sdk/python/bittensor/wallet.py | 14 +- sdk/python/bittensor/wallets.py | 8 +- sdk/python/pyproject.toml | 4 +- sdk/python/tests/unit/test_cli.py | 149 +- .../tests/unit/test_cli_intent_prompts.py | 44 + sdk/python/uv.lock | 1800 ++++++++--------- .../public/catalog/intents.json | 23 +- 39 files changed, 3451 insertions(+), 1205 deletions(-) create mode 100644 runtime/tests/alpha_only_coldkey_fees.rs create mode 100644 sdk/python/bittensor/cli/call_names.py create mode 100644 sdk/python/bittensor/cli/intent_prompts.py create mode 100644 sdk/python/bittensor/cli/secrets.py create mode 100644 sdk/python/tests/unit/test_cli_intent_prompts.py diff --git a/docs/guides/multisig.mdx b/docs/guides/multisig.mdx index 9a10dad796..3b826639c6 100644 --- a/docs/guides/multisig.mdx +++ b/docs/guides/multisig.mdx @@ -138,12 +138,40 @@ btcli wallet regen-coldkeypub -w team-treasury --ss58 5Fmulti...sigAddress btcli wallet balance team-treasury ``` -## Step 4 — spend: open the operation +## Step 4 — spend: treat the multisig like a wallet -Alice proposes paying 10 TAO out of the treasury. The inner call is an intent -spec — `{"op": , ...args}`, same shape as a batch child — with -fully explicit arguments. As always, `--dry-run` previews fee and effects -without submitting: +Once the signer set is saved (`btcli multisig add`), pass the **multisig name** +as `-w`. Any coldkey-signed command — transfer, stake, raw `call`, … — detects +the book entry, picks a local member coldkey to sign, and opens or completes the +approval round. Co-signers re-run the **same** command; the CLI fills the +pending timepoint automatically: + +```bash +# Alice (has the alice coldkey locally) +btcli wallet transfer --dest 5DevPayee... --amount-tao 10 -w team-treasury + +# Bob (has the bob coldkey locally) — identical command +btcli wallet transfer --dest 5DevPayee... --amount-tao 10 -w team-treasury +``` + +Works the same for intents and the raw-call escape hatch: + +```bash +btcli tx add-stake --netuid 1 --amount-tao 5 -w team-treasury +btcli call Balances.transfer_keep_alive \ + --args '{"dest":"5DevPayee...","value":10000000000}' \ + -w team-treasury +``` + +If several member coldkeys are present locally, the CLI prompts which one +signs (or pass `-w alice --multisig team-treasury` to pin one). Each member +still needs a little free TAO for fees and the opener's deposit. + +### Manual approval round (optional) + +You can still drive the round explicitly with intent specs — useful when you +want to paste exact co-signer commands. `--other-signatories` lists every +member *except* the signer: ```bash btcli tx multisig-execute \ @@ -159,16 +187,10 @@ btcli tx multisig-execute \ -w alice ``` -`--other-signatories` lists every member *except* the signer; the CLI adds -Alice's coldkey and sorts the set. Since no timepoint was passed, this opens -the operation: Alice's deposit is reserved, and nothing executes yet. - After submission the CLI prints the operation's `call_hash`, `call_data`, the opening `timepoint`, and **ready-to-run commands for each remaining -co-signer** — copy-paste them to Bob and Carol over your team channel. The -opening extrinsic embeds the full call, so co-signers can also recover -everything from chain state alone (next step); no out-of-band call data is -required. +co-signer**. The opening extrinsic embeds the full call, so co-signers can also +recover everything from chain state alone (next step). ## Step 5 — view pending operations @@ -199,9 +221,13 @@ compromised — don't co-sign, and rotate that member out. ## Step 6 — approve and execute -Bob was handed a ready-to-run command by `pending` (or by Alice). Because his -approval is the one that reaches the threshold, it must be -`multisig-execute` with the full call — the chain needs the call to run it. +Prefer the short form from step 4: Bob runs the same `btcli wallet transfer +-w team-treasury ...` (or whatever command Alice opened). The CLI finds the +pending operation by call hash and supplies the timepoint. + +For the explicit path, Bob was handed a ready-to-run command by `pending` (or +by Alice). Because his approval is the one that reaches the threshold, it must +be `multisig-execute` with the full call — the chain needs the call to run it. The timepoint identifies the pending operation: ```bash diff --git a/docs/tx/add-stake.mdx b/docs/tx/add-stake.mdx index 1d6486936a..d1171a56a0 100644 --- a/docs/tx/add-stake.mdx +++ b/docs/tx/add-stake.mdx @@ -14,11 +14,12 @@ than `rate_tolerance` (5%) above the price at submission — raise the tolerance or set `slippage_protection` to False to execute at any price, or use `add_stake_limit` to set an explicit limit price. The position's value then follows the pool price and the validator's performance, and can -be exited later with `remove_stake`. Fails if the coldkey's free balance -cannot cover the amount plus the transaction fee, and with `AmountTooLow` -when the amount is below the chain minimum of 0.002 TAO plus the swap fee. -Dynamic subnets also reject a single swap larger than 1000x the pool's TAO -reserve (`InsufficientLiquidity`). +be exited later with `remove_stake`. Pass `all` to stake the whole free +balance minus the existential deposit and a small fee headroom. Fails if +the coldkey's free balance cannot cover the amount plus the transaction +fee, and with `AmountTooLow` when the amount is below the chain minimum +of 0.002 TAO plus the swap fee. Dynamic subnets also reject a single swap +larger than 1000x the pool's TAO reserve (`InsufficientLiquidity`). | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | @@ -30,7 +31,7 @@ reserve (`InsufficientLiquidity`). | --- | --- | --- | --- | | `hotkey_ss58` | string | yes | Hotkey the stake is added to (the validator you are backing). | | `netuid` | integer | yes | Subnet the stake lives on (netuid 0 is the root network). | -| `amount_tao` | number \| `"all"` | yes | How much of the coldkey's free balance to stake. | +| `amount_tao` | number \| `"all"` | yes | How much of the coldkey's free balance to stake, or `all` (everything minus the existential deposit and fee headroom). | | `slippage_protection` | boolean | no | Bound the price the swap may execute at (on by default): the call fails (`SlippageTooHigh`) instead of filling once the pool price moves more than `rate_tolerance` from the price at submission. Disable to execute at any price. | | `rate_tolerance` | number | no | Maximum price move slippage protection accepts, as a fraction (0.05 = 5%). Ignored when slippage protection is disabled. | diff --git a/docs/tx/stake-burn.mdx b/docs/tx/stake-burn.mdx index aafd47b7ac..887a20652f 100644 --- a/docs/tx/stake-burn.mdx +++ b/docs/tx/stake-burn.mdx @@ -11,10 +11,11 @@ signer's stake. The TAO is spent permanently — nothing lands in your stake, so this is not an investment call; use a regular add-stake intent to acquire a position. Fails on the root subnet (`CannotBurnOrRecycleOnRootSubnet`). The chain accepts an optional -limit (omitted = market order), but this intent always requires -`limit_price` and executes all-or-nothing: the swap fails instead of -partially filling at a worse rate. Counts against a configured spend -cap. +limit (omitted = market order), but this intent always submits one and +executes all-or-nothing: the swap fails instead of partially filling at +a worse rate. When `limit_price` is omitted, the limit is derived from +the current pool price plus `rate_tolerance` (5% by default). Counts +against a configured spend cap. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | @@ -26,7 +27,8 @@ cap. | --- | --- | --- | --- | | `netuid` | integer | yes | Subnet whose alpha is bought and burned. | | `amount_tao` | number \| `"all"` | yes | Spent from the coldkey to buy alpha that is then burned. | -| `limit_price` | integer | yes | Worst acceptable price in rao per alpha; the call fails rather than filling beyond it. | +| `limit_price` | integer | no | Worst acceptable price in rao per alpha; the call fails rather than filling beyond it. Defaults to the current pool price plus `rate_tolerance`. | +| `rate_tolerance` | number | no | Maximum price move accepted when `limit_price` is omitted, as a fraction (0.05 = 5%). Ignored when `limit_price` is given. | | `hotkey_ss58` | string | no | Hotkey the burn is routed through; defaults to the wallet's hotkey. | Address parameters (`--hotkey`, `--coldkey`, `--dest`, ...) accept a raw ss58 @@ -40,12 +42,10 @@ submitting), then submit: ```bash btcli tx stake-burn \ --netuid \ - --amount-tao \ - --limit-price --dry-run + --amount-tao --dry-run btcli tx stake-burn \ --netuid \ - --amount-tao \ - --limit-price -w my_coldkey + --amount-tao -w my_coldkey ``` ## Python @@ -55,7 +55,7 @@ import bittensor as bt from bittensor.wallet import Wallet wallet = Wallet(name="my_coldkey", hotkey="my_hotkey") -intent = bt.StakeBurn(netuid=1, amount_tao=1.0, limit_price=0) +intent = bt.StakeBurn(netuid=1, amount_tao=1.0) sub = bt.Subtensor() plan = sub.plan(intent, wallet) # fee, effects, policy — no submission diff --git a/runtime/src/check_nonce.rs b/runtime/src/check_nonce.rs index 7ec9488d0d..52e32efd55 100644 --- a/runtime/src/check_nonce.rs +++ b/runtime/src/check_nonce.rs @@ -47,6 +47,26 @@ impl CheckNonce { } } +impl CheckNonce { + /// Whether `who` holds alpha stake on any hotkey. + /// + /// A coldkey that received stake (e.g. via `transfer_stake`) but never held + /// TAO has no provider or sufficient reference, yet the transaction-fee + /// handler can charge its fee by unstaking alpha (`fees_in_alpha`). Without + /// this escape hatch such an account is stuck: every signed extrinsic — + /// including the `remove_stake` that would give it TAO — dies here with + /// `Payment` before fee logic even runs. + /// + /// `StakingHotkeys` may retain hotkeys whose stake has since dropped to + /// zero, so this can over-approximate. That is safe: passing this guard + /// only admits the transaction to fee validation, where an account that + /// cannot actually pay (in TAO or alpha) is still rejected before any + /// nonce storage is written. + fn holds_alpha_stake(who: &::AccountId) -> bool { + pallet_subtensor::StakingHotkeys::::decode_len(who).unwrap_or(0) > 0 + } +} + impl sp_std::fmt::Debug for CheckNonce { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { @@ -78,34 +98,38 @@ pub enum Pre { Refund(Weight), } -impl TransactionExtension for CheckNonce +impl TransactionExtension<::RuntimeCall> + for CheckNonce where - T::RuntimeCall: Dispatchable, - ::RuntimeOrigin: AsSystemOriginSigner + Clone, + ::RuntimeCall: Dispatchable, + <::RuntimeCall as Dispatchable>::RuntimeOrigin: + AsSystemOriginSigner<::AccountId> + Clone, { const IDENTIFIER: &'static str = "CheckNonce"; type Implicit = (); type Val = Val; type Pre = Pre; - fn weight(&self, _: &T::RuntimeCall) -> Weight { + fn weight(&self, _: &::RuntimeCall) -> Weight { // Account for the account-nonce storage ops the extension performs on // signed transactions: one `Account::get` read in `validate`, plus one - // `Account::mutate` (read + write) in `prepare` to bump the nonce. - // Non-signed calls refund this weight in full via `Val::Refund`. - T::DbWeight::get().reads_writes(2, 1) + // `Account::mutate` (read + write) in `prepare` to bump the nonce, plus + // the worst-case `StakingHotkeys` length read for reference-less + // signers. Non-signed calls refund this weight in full via + // `Val::Refund`. + ::DbWeight::get().reads_writes(3, 1) } fn validate( &self, origin: ::RuntimeOrigin, - call: &T::RuntimeCall, - info: &DispatchInfoOf, + call: &::RuntimeCall, + info: &DispatchInfoOf<::RuntimeCall>, _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, _source: TransactionSource, - ) -> ValidateResult { + ) -> ValidateResult::RuntimeCall> { let Some(who) = origin.as_system_origin_signer() else { return Ok((Default::default(), Val::Refund(self.weight(call)), origin)); }; @@ -113,6 +137,7 @@ where if info.pays_fee == Pays::Yes && account.providers.is_zero() && account.sufficients.is_zero() + && !Self::holds_alpha_stake(who) { // Nonce storage not paid for return Err(InvalidTransaction::Payment.into()); @@ -146,9 +171,9 @@ where fn prepare( self, val: Self::Val, - _origin: &T::RuntimeOrigin, - _call: &T::RuntimeCall, - _info: &DispatchInfoOf, + _origin: &::RuntimeOrigin, + _call: &::RuntimeCall, + _info: &DispatchInfoOf<::RuntimeCall>, _len: usize, ) -> Result { let (who, mut nonce) = match val { @@ -160,7 +185,7 @@ where if self.0 > nonce { return Err(InvalidTransaction::Future.into()); } - nonce += T::Nonce::one(); + nonce += ::Nonce::one(); frame_system::Account::::mutate(who, |account| account.nonce = nonce); Ok(Pre::NonceChecked) } @@ -168,7 +193,7 @@ where fn post_dispatch_details( pre: Self::Pre, _info: &DispatchInfo, - _post_info: &PostDispatchInfoOf, + _post_info: &PostDispatchInfoOf<::RuntimeCall>, _len: usize, _result: &DispatchResult, ) -> Result { @@ -189,10 +214,11 @@ mod tests { fn check_nonce_weight_accounts_for_account_storage_ops() { let ext = CheckNonce::::from(<::Nonce>::zero()); let call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); - // validate performs one `Account::get` read; prepare performs one + // validate performs one `Account::get` read plus, for reference-less + // signers, one `StakingHotkeys` length read; prepare performs one // `Account::mutate` (read + write). The declared extension weight must // reflect those ops, not zero. - let expected = ::DbWeight::get().reads_writes(2, 1); + let expected = ::DbWeight::get().reads_writes(3, 1); assert_eq!(ext.weight(&call), expected); assert!(!ext.weight(&call).is_zero()); } diff --git a/runtime/tests/alpha_only_coldkey_fees.rs b/runtime/tests/alpha_only_coldkey_fees.rs new file mode 100644 index 0000000000..054de4fb7e --- /dev/null +++ b/runtime/tests/alpha_only_coldkey_fees.rs @@ -0,0 +1,197 @@ +//! A coldkey whose only holding is alpha stake (e.g. received via +//! `transfer_stake`, never funded with TAO) has no provider or sufficient +//! reference on its system account. The custom `CheckNonce` extension used to +//! reject every fee-paying extrinsic from such a signer with +//! `InvalidTransaction::Payment` ("Inability to pay some fees") before the +//! transaction-fee pallet's pay-in-alpha fallback was ever consulted — locking +//! the stake: even the `remove_stake` that would give the account TAO was +//! rejected. +//! +//! These tests reproduce that scenario end to end through the real +//! `transfer_stake` extrinsic and assert that `CheckNonce` now admits the +//! signer while fee validation (`ChargeTransactionPaymentWrapper`) accepts the +//! alpha-paid fee, and that accounts with no alpha at all are still rejected. + +#![allow( + clippy::unwrap_used, + clippy::expect_used, + clippy::arithmetic_side_effects +)] + +use frame_support::assert_ok; +use frame_support::dispatch::{GetDispatchInfo, Pays}; +use frame_support::pallet_prelude::Zero; +use frame_support::traits::Get; +use node_subtensor_runtime::{ + BuildStorage, Runtime, RuntimeCall, RuntimeGenesisConfig, RuntimeOrigin, SubtensorModule, + check_nonce, transaction_payment_wrapper::ChargeTransactionPaymentWrapper, +}; +use sp_runtime::traits::{TransactionExtension, TxBaseImplication}; +use sp_runtime::transaction_validity::{ + InvalidTransaction, TransactionSource, TransactionValidityError, +}; +use subtensor_runtime_common::{AccountId, AlphaBalance, NetUid, TaoBalance, Token}; + +fn netuid() -> NetUid { + NetUid::from(1) +} + +fn origin_coldkey() -> AccountId { + AccountId::from([1_u8; 32]) +} + +fn hotkey() -> AccountId { + AccountId::from([2_u8; 32]) +} + +/// The coldkey under test: receives alpha, never holds TAO. +fn alpha_only_coldkey() -> AccountId { + AccountId::from([3_u8; 32]) +} + +/// A coldkey with neither TAO nor alpha. +fn empty_coldkey() -> AccountId { + AccountId::from([4_u8; 32]) +} + +fn new_test_ext() -> sp_io::TestExternalities { + sp_tracing::try_init_simple(); + let mut ext: sp_io::TestExternalities = RuntimeGenesisConfig::default() + .build_storage() + .unwrap() + .into(); + ext.execute_with(|| frame_system::Pallet::::set_block_number(1)); + ext +} + +fn add_balance_to_coldkey_account(coldkey: &AccountId, tao: TaoBalance) { + let credit = SubtensorModule::mint_tao(tao); + let _ = SubtensorModule::spend_tao(coldkey, credit, tao); +} + +/// Stand up a stable-mechanism subnet (1 TAO : 1 alpha, no AMM liquidity +/// needed) with a staked position for `origin_coldkey`, then move that whole +/// position to the TAO-less destination via the real `transfer_stake` +/// extrinsic — Tegridy's exact scenario from the Church of Rao report. +fn setup_alpha_only_coldkey() -> AlphaBalance { + SubtensorModule::init_new_network(netuid(), 0); + pallet_subtensor::SubnetMechanism::::insert(netuid(), 0u16); + pallet_subtensor::SubtokenEnabled::::insert(netuid(), true); + + let stake: AlphaBalance = + (pallet_subtensor::DefaultMinStake::::get().to_u64() * 100).into(); + + add_balance_to_coldkey_account(&origin_coldkey(), TaoBalance::from(stake.to_u64() * 10)); + let subnet_account = SubtensorModule::get_subnet_account_id(netuid()).unwrap(); + add_balance_to_coldkey_account(&subnet_account, TaoBalance::from(stake.to_u64())); + + let _ = SubtensorModule::create_account_if_non_existent(&origin_coldkey(), &hotkey()); + SubtensorModule::increase_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey(), + &origin_coldkey(), + netuid(), + stake, + ); + + assert_ok!(SubtensorModule::transfer_stake( + RuntimeOrigin::signed(origin_coldkey()), + alpha_only_coldkey(), + hotkey(), + netuid(), + netuid(), + stake, + )); + + let received = SubtensorModule::get_stake_for_hotkey_and_coldkey_on_subnet( + &hotkey(), + &alpha_only_coldkey(), + netuid(), + ); + assert!( + !received.is_zero(), + "destination coldkey must hold the transferred alpha" + ); + received +} + +fn remove_stake_call(amount: AlphaBalance) -> RuntimeCall { + RuntimeCall::SubtensorModule(pallet_subtensor::Call::remove_stake { + hotkey: hotkey(), + netuid: netuid(), + amount_unstaked: amount, + }) +} + +fn validate_check_nonce( + who: AccountId, + call: &RuntimeCall, +) -> Result<(), TransactionValidityError> { + let ext = check_nonce::CheckNonce::::from(0); + let info = call.get_dispatch_info(); + assert_eq!( + info.pays_fee, + Pays::Yes, + "the guard under test only applies to fee-paying calls" + ); + ext.validate( + RuntimeOrigin::signed(who), + call, + &info, + 0, + (), + &TxBaseImplication(()), + TransactionSource::External, + ) + .map(|_| ()) +} + +#[test] +fn alpha_only_coldkey_can_submit_remove_stake() { + new_test_ext().execute_with(|| { + let received = setup_alpha_only_coldkey(); + + // The destination coldkey never held TAO: no system account references. + let account = frame_system::Account::::get(alpha_only_coldkey()); + assert_eq!(account.providers, 0); + assert_eq!(account.sufficients, 0); + + let call = remove_stake_call(received); + + // CheckNonce must admit the alpha-holding signer... + assert_ok!(validate_check_nonce(alpha_only_coldkey(), &call)); + + // ...and fee validation accepts the transaction because the fee is + // payable in alpha, so the extrinsic is valid end to end. + let payment = ChargeTransactionPaymentWrapper::::new(TaoBalance::new(0)); + let info = call.get_dispatch_info(); + assert_ok!( + payment + .validate( + RuntimeOrigin::signed(alpha_only_coldkey()), + &call, + &info, + 0, + (), + &TxBaseImplication(()), + TransactionSource::External, + ) + .map(|_| ()) + ); + }); +} + +#[test] +fn coldkey_without_tao_or_alpha_is_still_rejected() { + new_test_ext().execute_with(|| { + setup_alpha_only_coldkey(); + + let call = remove_stake_call(AlphaBalance::from(1_000_000u64)); + assert_eq!( + validate_check_nonce(empty_coldkey(), &call), + Err(TransactionValidityError::Invalid( + InvalidTransaction::Payment + )), + "the storage-bloat guard must still reject signers with no on-chain value" + ); + }); +} diff --git a/sdk/bittensor-core-py/pyproject.toml b/sdk/bittensor-core-py/pyproject.toml index 3024e05c3c..10d288c947 100644 --- a/sdk/bittensor-core-py/pyproject.toml +++ b/sdk/bittensor-core-py/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "maturin" name = "bittensor-core" # Static (not read from Cargo.toml) so the release train can stamp PEP 440 # rc/dev suffixes that cargo's semver would reject. -version = "0.1.2" +version = "0.1.3" description = "The chain-defined compute core for Bittensor clients: sp-core keys, keyfiles, drand timelock, ML-KEM, SCALE codec, and RFC-0078 metadata digest, built from the bittensor monorepo" readme = "README.md" requires-python = ">=3.10" diff --git a/sdk/bittensor-core/src/keyfiles/mod.rs b/sdk/bittensor-core/src/keyfiles/mod.rs index b58c5db187..340ee8ae74 100644 --- a/sdk/bittensor-core/src/keyfiles/mod.rs +++ b/sdk/bittensor-core/src/keyfiles/mod.rs @@ -17,7 +17,7 @@ use sodiumoxide::crypto::secretbox; use zeroize::{Zeroize, Zeroizing}; use crate::error::CoreError; -use crate::keys::{ensure_sodium, Keypair, CRYPTO_SR25519}; +use crate::keys::{ensure_sodium, Keypair, CRYPTO_ED25519, CRYPTO_SR25519}; const NACL_SALT: &[u8] = b"\x13q\x83\xdf\xf1Z\t\xbc\x9c\x90\xb5Q\x879\xe9\xb1"; const LEGACY_SALT: &[u8] = b"Iguesscyborgslikemyselfhaveatendencytobeparanoidaboutourorigins"; @@ -184,6 +184,17 @@ pub fn serialized_keypair_to_keyfile_data(keypair: &Keypair) -> Result, data.insert("accountId", json!(format!("0x{public_key_str}"))); data.insert("publicKey", json!(format!("0x{public_key_str}"))); + // Legacy btwallet keyfiles always carried secretPhrase/secretSeed, and + // third-party parsers (subnet tooling, struct-based Rust readers) can + // require them. Write them whenever the keypair retained them so files + // created here stay parseable by legacy readers. + if let Some(mnemonic) = keypair.mnemonic() { + data.insert("secretPhrase", json!(mnemonic)); + } + if let Some(seed) = keypair.seed_bytes() { + data.insert("secretSeed", json!(format!("0x{}", hex::encode(seed)))); + } + if let Some(private_key) = keypair.private_key_bytes() { let private_key_str = hex::encode(private_key); data.insert("privateKey", json!(format!("0x{private_key_str}"))); @@ -197,17 +208,120 @@ pub fn serialized_keypair_to_keyfile_data(keypair: &Keypair) -> Result, .map_err(|error| key_err(format!("serialization error: {error}"))) } +/// Stored ss58Address, including the legacy leading-space `" ss58Address"` +/// key some old btwallet files carry. +fn stored_ss58(keyfile_dict: &serde_json::Value) -> Option<&str> { + keyfile_dict + .get("ss58Address") + .or_else(|| keyfile_dict.get(" ss58Address")) + .and_then(|value| value.as_str()) +} + +/// Derive a keypair and cross-check it against the keyfile's stored +/// ss58Address. Legacy keyfiles sometimes omit or mislabel cryptoType, so on +/// a mismatch the other crypto type is tried before giving up: the stored +/// address is the ground truth for which key the file holds. +fn resolve_checked( + keyfile_dict: &serde_json::Value, + crypto_type: u8, + derived_from: &str, + derive: F, +) -> Result +where + F: Fn(u8) -> Result, +{ + let keypair = derive(crypto_type)?; + let Some(stored) = stored_ss58(keyfile_dict) else { + return Ok(keypair); + }; + if keypair.ss58_address() == stored { + return Ok(keypair); + } + let alternate = if crypto_type == CRYPTO_SR25519 { + CRYPTO_ED25519 + } else { + CRYPTO_SR25519 + }; + if let Ok(alternate_keypair) = derive(alternate) { + if alternate_keypair.ss58_address() == stored { + return Ok(alternate_keypair); + } + } + Err(key_err(format!( + "ss58Address in keyfile does not match the address derived from {derived_from} \ + (check the keyfile's cryptoType)", + ))) +} + +/// Whether raw (non-JSON) keyfile content looks like a bare BIP39 phrase, as +/// written by pre-JSON-era bittensor wallets. +fn looks_like_mnemonic(text: &str) -> bool { + let words: Vec<&str> = text.split_whitespace().collect(); + matches!(words.len(), 12 | 15 | 18 | 21 | 24) + && words + .iter() + .all(|word| word.chars().all(|c| c.is_ascii_lowercase())) +} + +/// Fallback for raw (non-JSON) keyfile payloads: a bare hex seed/private key +/// or a bare mnemonic, as written by pre-JSON-era bittensor wallets. +fn keypair_from_raw_text(text: &str) -> Option { + let trimmed = text.trim(); + let hex_body = trimmed.strip_prefix("0x").unwrap_or(trimmed); + if matches!(hex_body.len(), 64 | 128) && hex_body.chars().all(|c| c.is_ascii_hexdigit()) { + if hex_body.len() == 64 { + return hex::decode(hex_body) + .ok() + .and_then(|bytes| Keypair::from_seed(&bytes, CRYPTO_SR25519).ok()); + } + return Keypair::from_private_key(trimmed, CRYPTO_SR25519).ok(); + } + if looks_like_mnemonic(trimmed) { + if let Ok(keypair) = Keypair::from_mnemonic(trimmed, CRYPTO_SR25519, None) { + return Some(keypair); + } + } + None +} + pub fn deserialize_keypair_from_keyfile_data(keyfile_data: &[u8]) -> Result { - let decoded = - std::str::from_utf8(keyfile_data).map_err(|_| key_err("failed to decode keyfile data"))?; + let decoded = std::str::from_utf8(keyfile_data).map_err(|_| { + if keyfile_data_is_encrypted(keyfile_data) { + key_err("keyfile is encrypted; decrypt it with its password first") + } else { + key_err("failed to decode keyfile data: not utf-8 text (unknown or corrupt format)") + } + })?; - let keyfile_dict: serde_json::Value = - serde_json::from_str(decoded).map_err(|_| key_err("failed to parse keyfile data"))?; + let keyfile_dict: serde_json::Value = match serde_json::from_str(decoded) { + Ok(value) => value, + Err(_) => { + if let Some(keypair) = keypair_from_raw_text(decoded) { + return Ok(keypair); + } + return Err(key_err( + "failed to parse keyfile data: not keyfile JSON, a raw hex seed, or a mnemonic", + )); + } + }; + + // A polkadot.js / mobile-app keystore export is valid JSON but a wholly + // different (password-encrypted) format; name it instead of failing with + // a generic parse error. + if keyfile_dict.get("encoded").is_some() && keyfile_dict.get("encoding").is_some() { + return Err(key_err( + "this keyfile is a polkadot.js / mobile-app JSON export, not a btcli keyfile; \ + import it with `btcli wallet regen-coldkey --json-path `", + )); + } + // Historical writers disagree on the cryptoType JSON type: python btwallet + // wrote a number, some JS tooling wrote a numeric string. let crypto_type = keyfile_dict .get("cryptoType") .and_then(|value| match value { serde_json::Value::Number(number) => number.to_string().parse::().ok(), + serde_json::Value::String(text) => text.trim().parse::().ok(), _ => None, }) .unwrap_or(CRYPTO_SR25519); @@ -216,7 +330,9 @@ pub fn deserialize_keypair_from_keyfile_data(keyfile_data: &[u8]) -> Result Result Result>().join(", ")) + .unwrap_or_else(|| "none".to_string()); + Err(key_err(format!( + "keypair could not be created from keyfile data: no secretPhrase, secretSeed, \ + privateKey, or ss58Address field (found: {found_fields})", + ))) } #[cfg(test)] @@ -324,9 +438,15 @@ mod tests { #[test] fn legacy_keyfile_without_crypto_type_defaults_sr25519() { - let json = r#"{"secretPhrase":"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about","ss58Address":"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"}"#; + let expected = Keypair::from_mnemonic(&test_mnemonic(), CRYPTO_SR25519, None).unwrap(); + let json = format!( + r#"{{"secretPhrase":"{}","ss58Address":"{}"}}"#, + test_mnemonic(), + expected.ss58_address() + ); let keypair = deserialize_keypair_from_keyfile_data(json.as_bytes()).unwrap(); assert_eq!(keypair.crypto_type(), CRYPTO_SR25519); + assert_eq!(keypair.ss58_address(), expected.ss58_address()); } #[test] @@ -337,4 +457,122 @@ mod tests { assert_eq!(restored.crypto_type(), CRYPTO_ED25519); assert_eq!(restored.ss58_address(), original.ss58_address()); } + + #[test] + fn mnemonic_keypair_writes_legacy_secret_fields() { + let keypair = Keypair::from_mnemonic(&test_mnemonic(), CRYPTO_SR25519, None).unwrap(); + let data = serialized_keypair_to_keyfile_data(&keypair).unwrap(); + let parsed: serde_json::Value = serde_json::from_slice(&data).unwrap(); + assert_eq!( + parsed.get("secretPhrase").and_then(|v| v.as_str()), + Some(test_mnemonic().as_str()) + ); + let seed = parsed + .get("secretSeed") + .and_then(|v| v.as_str()) + .expect("secretSeed present"); + assert!(seed.starts_with("0x") && seed.len() == 66); + assert!(parsed.get("privateKey").is_some()); + assert!(parsed.get("accountId").is_some()); + + // The seed alone re-derives the same key. + let seed_bytes = hex::decode(seed.trim_start_matches("0x")).unwrap(); + let from_seed = Keypair::from_seed(&seed_bytes, CRYPTO_SR25519).unwrap(); + assert_eq!(from_seed.ss58_address(), keypair.ss58_address()); + } + + #[test] + fn mnemonic_with_derivation_password_omits_phrase_keeps_seed() { + let keypair = + Keypair::from_mnemonic(&test_mnemonic(), CRYPTO_SR25519, Some("hunter2")).unwrap(); + let data = serialized_keypair_to_keyfile_data(&keypair).unwrap(); + let parsed: serde_json::Value = serde_json::from_slice(&data).unwrap(); + assert!(parsed.get("secretPhrase").is_none()); + assert!(parsed.get("secretSeed").is_some()); + let restored = deserialize_keypair_from_keyfile_data(&data).unwrap(); + assert_eq!(restored.ss58_address(), keypair.ss58_address()); + } + + #[test] + fn crypto_type_as_string_is_accepted() { + let keypair = Keypair::from_mnemonic(&test_mnemonic(), CRYPTO_ED25519, None).unwrap(); + let json = format!( + r#"{{"secretPhrase":"{}","cryptoType":"{}","ss58Address":"{}"}}"#, + test_mnemonic(), + CRYPTO_ED25519, + keypair.ss58_address() + ); + let restored = deserialize_keypair_from_keyfile_data(json.as_bytes()).unwrap(); + assert_eq!(restored.crypto_type(), CRYPTO_ED25519); + assert_eq!(restored.ss58_address(), keypair.ss58_address()); + } + + #[test] + fn missing_crypto_type_recovered_from_stored_ss58() { + // A legacy ed25519 keyfile without cryptoType: the sr25519 default + // mismatches the stored address, so the reader retries as ed25519. + let keypair = Keypair::from_mnemonic(&test_mnemonic(), CRYPTO_ED25519, None).unwrap(); + let json = format!( + r#"{{"secretPhrase":"{}","ss58Address":"{}"}}"#, + test_mnemonic(), + keypair.ss58_address() + ); + let restored = deserialize_keypair_from_keyfile_data(json.as_bytes()).unwrap(); + assert_eq!(restored.crypto_type(), CRYPTO_ED25519); + assert_eq!(restored.ss58_address(), keypair.ss58_address()); + } + + #[test] + fn stored_ss58_mismatch_is_rejected() { + let json = format!( + r#"{{"secretPhrase":"{}","ss58Address":"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"}}"#, + test_mnemonic() + ); + let error = deserialize_keypair_from_keyfile_data(json.as_bytes()) + .err() + .expect("mismatch must fail"); + assert!(error.to_string().contains("does not match")); + } + + #[test] + fn raw_hex_seed_fallback() { + let keypair = Keypair::from_mnemonic(&test_mnemonic(), CRYPTO_SR25519, None).unwrap(); + let seed_hex = format!("0x{}", hex::encode(keypair.seed_bytes().unwrap())); + let restored = deserialize_keypair_from_keyfile_data(seed_hex.as_bytes()).unwrap(); + assert_eq!(restored.ss58_address(), keypair.ss58_address()); + } + + #[test] + fn raw_hex_private_key_fallback() { + let keypair = Keypair::from_mnemonic(&test_mnemonic(), CRYPTO_SR25519, None).unwrap(); + let private_key = keypair.private_key_bytes().unwrap(); + assert_eq!(private_key.len(), 64); + let private_hex = format!("0x{}", hex::encode(private_key)); + let restored = deserialize_keypair_from_keyfile_data(private_hex.as_bytes()).unwrap(); + assert_eq!(restored.ss58_address(), keypair.ss58_address()); + } + + #[test] + fn raw_mnemonic_fallback() { + let keypair = Keypair::from_mnemonic(&test_mnemonic(), CRYPTO_SR25519, None).unwrap(); + let restored = deserialize_keypair_from_keyfile_data(test_mnemonic().as_bytes()).unwrap(); + assert_eq!(restored.ss58_address(), keypair.ss58_address()); + } + + #[test] + fn polkadotjs_export_gets_actionable_error() { + let json = r#"{"encoded":"abc","encoding":{"content":["pkcs8","sr25519"],"type":["scrypt","xsalsa20-poly1305"],"version":"3"},"address":"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY","meta":{}}"#; + let error = deserialize_keypair_from_keyfile_data(json.as_bytes()) + .err() + .expect("polkadotjs export must fail"); + assert!(error.to_string().contains("regen-coldkey --json-path")); + } + + #[test] + fn unknown_json_error_names_found_fields() { + let error = deserialize_keypair_from_keyfile_data(br#"{"foo":1}"#) + .err() + .expect("unknown fields must fail"); + assert!(error.to_string().contains("foo")); + } } diff --git a/sdk/bittensor-core/src/keys/mod.rs b/sdk/bittensor-core/src/keys/mod.rs index a33bfc49a7..7e52a25bd1 100644 --- a/sdk/bittensor-core/src/keys/mod.rs +++ b/sdk/bittensor-core/src/keys/mod.rs @@ -151,6 +151,14 @@ impl KeypairInner { pub struct Keypair { inner: KeypairInner, ss58_format: u16, + /// The BIP39 phrase this keypair was derived from, when known and + /// sufficient on its own to re-derive the key (no derivation password). + /// Written to keyfiles as ``secretPhrase`` for parity with the legacy + /// btwallet format that third-party tools parse. + mnemonic: Option>, + /// The raw seed this keypair was derived from, when known. Written to + /// keyfiles as ``secretSeed`` (legacy-format parity). + seed: Option>>, } impl Keypair { @@ -194,6 +202,8 @@ impl Keypair { crypto_type, }, ss58_format, + mnemonic: None, + seed: None, }) } @@ -203,22 +213,29 @@ impl Keypair { crypto_type: u8, password: Option<&str>, ) -> Result { - let inner = match crypto_type { + let (inner, seed) = match crypto_type { CRYPTO_SR25519 => { - let (pair, _seed) = sr25519::Pair::from_phrase(mnemonic, password) + let (pair, seed) = sr25519::Pair::from_phrase(mnemonic, password) .map_err(|e| crypto_err(format!("invalid mnemonic: {e:?}")))?; - KeypairInner::Sr25519(pair) + (KeypairInner::Sr25519(pair), seed.to_vec()) } CRYPTO_ED25519 => { - let (pair, _seed) = ed25519::Pair::from_phrase(mnemonic, password) + let (pair, seed) = ed25519::Pair::from_phrase(mnemonic, password) .map_err(|e| crypto_err(format!("invalid mnemonic: {e:?}")))?; - KeypairInner::Ed25519(pair) + (KeypairInner::Ed25519(pair), seed.to_vec()) } other => return Err(crypto_err(format!("unknown crypto type {other}"))), }; Ok(Self { inner, ss58_format: DEFAULT_SS58_FORMAT, + // A phrase with a derivation password cannot re-derive the key on + // its own, so only a passwordless phrase is kept (and written to + // keyfiles); the derived seed is always sufficient. + mnemonic: password + .is_none() + .then(|| Zeroizing::new(mnemonic.to_string())), + seed: Some(Zeroizing::new(seed)), }) } @@ -238,6 +255,8 @@ impl Keypair { Ok(Self { inner, ss58_format: DEFAULT_SS58_FORMAT, + mnemonic: None, + seed: Some(Zeroizing::new(seed.to_vec())), }) } @@ -254,9 +273,13 @@ impl Keypair { ), other => return Err(crypto_err(format!("unknown crypto type {other}"))), }; + // A URI may carry derivation junctions, so neither the phrase nor a + // bare seed is retained. Ok(Self { inner, ss58_format: DEFAULT_SS58_FORMAT, + mnemonic: None, + seed: None, }) } @@ -290,6 +313,8 @@ impl Keypair { Ok(Self { inner, ss58_format: DEFAULT_SS58_FORMAT, + mnemonic: None, + seed: None, }) } @@ -342,9 +367,24 @@ impl Keypair { self.inner.private_key_bytes() } + /// The BIP39 phrase this keypair was derived from, when retained. + pub fn mnemonic(&self) -> Option<&str> { + self.mnemonic.as_deref().map(String::as_str) + } + + /// The raw seed this keypair was derived from, when retained. + pub fn seed_bytes(&self) -> Option<&[u8]> { + self.seed.as_deref().map(Vec::as_slice) + } + #[cfg(feature = "host")] pub(crate) fn from_inner(inner: KeypairInner, ss58_format: u16) -> Self { - Self { inner, ss58_format } + Self { + inner, + ss58_format, + mnemonic: None, + seed: None, + } } /// Sign a message; returns the raw 64-byte signature. diff --git a/sdk/python/bittensor/cli/call.py b/sdk/python/bittensor/cli/call.py index 3994573344..38cf31691b 100644 --- a/sdk/python/bittensor/cli/call.py +++ b/sdk/python/bittensor/cli/call.py @@ -54,8 +54,10 @@ from .. import calls from ..intents.proxy import ProxyTypeChoice from . import multisig_helpers as ms_helpers +from .call_names import resolve_builder_params from .context import ctx_of from .globals import with_tx_globals +from .prompt import replay_command _MAX_SHOWN = 80 # truncate long param values (e.g. a wasm blob) in dry-run output @@ -193,22 +195,42 @@ def call( signatories=signatories, other_signatories=other_signatories, signer=signer, + wallet_default=app_ctx.wallet_name, ) builder = _resolve_builder(target) - params = _load_params(args, args_file) + params = resolve_builder_params(app_ctx, target, _load_params(args, args_file)) if proxy_for is not None: proxy_for = app_ctx.resolve_address("proxy_for", proxy_for) proxy_type_value = force_proxy_type.value if force_proxy_type else None - signing = app_ctx.signer(signer) - label = target + (" via Sudo.sudo" if sudo else "") - if proxy_for: - label += f" as {proxy_for} via proxy" via_multisig = threshold is not None if via_multisig and len(sigs) < threshold: raise typer.BadParameter( f"need at least {threshold} signatories, got {len(sigs)}", param_hint="--signatories", ) + # ``-w `` (no separate signatory wallet): pick a local member. + if via_multisig: + signer_ss58 = None + try: + signer_ss58 = app_ctx.wallet().coldkeypub.ss58_address + except Exception: + signer_ss58 = None + if signer_ss58 not in sigs: + try: + member_name, _ss58 = ms_helpers.pick_local_signatory( + app_ctx, + preset=preset or app_ctx.wallet_name, + signatories=sigs, + ) + except ValueError as error: + raise typer.BadParameter(str(error), param_hint="--wallet") from error + app_ctx.multisig_wallet_name = preset or app_ctx.wallet_name + app_ctx.wallet_name = member_name + app_ctx.wallet_given = True + signing = app_ctx.signer(signer) + label = target + (" via Sudo.sudo" if sudo else "") + if proxy_for: + label += f" as {proxy_for} via proxy" async def prepare(client): """Build the call against live metadata, nesting the wrappers inside-out: @@ -250,6 +272,7 @@ async def _dry_run_multisig(client): fields["multisig_preset"] = preset else: app_ctx.run(lambda client: _compose_only(client, prepare)) + fields["command"] = replay_command() app_ctx.output.detail("dry run: raw call", fields) return diff --git a/sdk/python/bittensor/cli/call_names.py b/sdk/python/bittensor/cli/call_names.py new file mode 100644 index 0000000000..729db32077 --- /dev/null +++ b/sdk/python/bittensor/cli/call_names.py @@ -0,0 +1,240 @@ +"""Resolve address-book / wallet names inside raw call parameters. + +``btcli call --args`` and the intent specs nested inside ``btcli tx`` options +(a multisig inner ``--call``, batch children) take call parameters as JSON, +where the flag-level name resolution never runs. A user who writes an +address-book name ("izzi") where the chain expects an AccountId would only +see the codec's cryptic "Base 58 requirement is violated". + +This module closes that gap through the same canonical lookup the flags use — +address book, proxy book, saved multisigs, and local wallet keys — plus a +did-you-mean error for anything unresolvable. Account-typed values are +recognized two ways: + +- generated call builders (``bittensor.calls``) annotate scalar account + params as ``AccountId32`` / ``MultiAddress``; known signatory-list fields + are resolved explicitly because structural ``Vec`` annotations + currently degrade to ``Any`` in codegen; +- intent specs resolve their ``*_ss58`` args and signatory lists. + +Both paths recurse through nested call structures: sudo-wrapped and batch +call dicts resolve against their own builders' annotations, multisig inner +calls and batch children resolve as intent specs. +""" + +from __future__ import annotations + +import difflib +from typing import Any, Optional + +import typer + +from .. import config as cfg +from .. import wallets +from .._generated import calls +from ..wallets import is_bittensor_address + +# Scalar annotations on generated call builders that mean "an account". +_ACCOUNT_ANNOTATIONS = {"AccountId32", "MultiAddress"} + +# The nested-call dict shapes accepted inside raw params: the generated Call +# tuple's field names, and the substrate-conventional call_* keys. +_CALL_SPEC_KEYS = ( + ("module", "function", "params"), + ("call_module", "call_function", "call_args"), +) + +# Intent fields that hold a list of accounts without the *_ss58 suffix. +_SIGNATORY_FIELDS = ("other_signatories", "signatories") + + +# --- raw builder params (`btcli call --args`) --------------------------------------------- + + +def resolve_builder_params( + app_ctx, target: str, params: dict, *, param_hint: str = "--args" +) -> dict: + """Resolve names in raw ``Pallet.function`` params, recursively. + + Unknown targets pass through untouched — composing against live metadata + reports those with the chain's own error. + """ + builder = _builder(target) + annotations = getattr(builder, "__annotations__", {}) if builder is not None else {} + return { + name: _resolve_value(app_ctx, name, annotations.get(name), value, param_hint) + for name, value in params.items() + } + + +def _builder(target: str): + pallet_name, _, function = target.partition(".") + pallet = getattr(calls, pallet_name, None) + builder = getattr(pallet, function, None) if isinstance(pallet, type) else None + return builder if callable(builder) else None + + +def _resolve_value(app_ctx, param: str, annotation: Optional[str], value: Any, hint: str) -> Any: + if isinstance(value, str) and annotation in _ACCOUNT_ANNOTATIONS: + return _resolve_account(app_ctx, param, value, hint) + if _is_nested_call(value): + return _resolve_nested_call(app_ctx, value, hint) + if isinstance(value, list) and value: + if all(_is_nested_call(item) for item in value): + return [_resolve_nested_call(app_ctx, item, hint) for item in value] + if param in _SIGNATORY_FIELDS and all(isinstance(item, str) for item in value): + return [_resolve_account(app_ctx, param, item, hint) for item in value] + return value + + +def _is_nested_call(value: Any) -> bool: + return _call_spec_keys(value) is not None or _variant_call(value) is not None + + +def _call_spec_keys(value: Any) -> Optional[tuple[str, str, str]]: + """The (module, function, params) key names when ``value`` is a keyed call dict.""" + if not isinstance(value, dict): + return None + for keys in _CALL_SPEC_KEYS: + if keys[0] in value and keys[1] in value: + return keys + return None + + +def _variant_call(value: Any) -> Optional[tuple[str, str, dict]]: + """(module, function, args) when ``value`` is a variant-shaped nested call — + ``{"Balances": {"transfer_keep_alive": {...}}}``, the shape the codec + encodes a ``RuntimeCall`` param from. Requiring a known generated builder + keeps single-key data dicts (e.g. a MultiAddress ``{"Id": ...}``) out. + """ + if not (isinstance(value, dict) and len(value) == 1): + return None + module, inner = next(iter(value.items())) + if not (isinstance(inner, dict) and len(inner) == 1): + return None + function, args = next(iter(inner.items())) + if not isinstance(args, dict) or _builder(f"{module}.{function}") is None: + return None + return module, function, args + + +def _resolve_nested_call(app_ctx, value: dict, hint: str) -> dict: + keys = _call_spec_keys(value) + if keys: + module_key, function_key, params_key = keys + inner = value.get(params_key) + if not isinstance(inner, (dict, type(None))): + return value + target = f"{value[module_key]}.{value[function_key]}" + resolved = dict(value) + resolved[params_key] = resolve_builder_params(app_ctx, target, inner or {}, param_hint=hint) + return resolved + module, function, args = _variant_call(value) + return { + module: { + function: resolve_builder_params(app_ctx, f"{module}.{function}", args, param_hint=hint) + } + } + + +# --- intent specs (`btcli tx` args, multisig inner calls, batch children) ------------------ + + +def resolve_intent_args(app_ctx, args: dict, *, param_hint: Optional[str] = None) -> dict: + """Resolve names in an intent's args: ``*_ss58`` strings, signatory lists, + and nested intent specs (a multisig inner ``call``, batch ``intents``).""" + out = dict(args) + for name, value in args.items(): + hint = param_hint or "--" + name.replace("_", "-") + if name.endswith("_ss58") and isinstance(value, str): + out[name] = _resolve_account(app_ctx, name, value, hint) + elif name in _SIGNATORY_FIELDS and isinstance(value, list): + out[name] = [ + _resolve_account(app_ctx, name, item, hint) if isinstance(item, str) else item + for item in value + ] + elif _is_intent_spec(value): + out[name] = _resolve_intent_spec(app_ctx, value, hint) + elif isinstance(value, list): + out[name] = [ + _resolve_intent_spec(app_ctx, item, hint) if _is_intent_spec(item) else item + for item in value + ] + return out + + +def _is_intent_spec(value: Any) -> bool: + return isinstance(value, dict) and "op" in value + + +def _resolve_intent_spec(app_ctx, spec: dict, hint: str) -> dict: + args = {name: value for name, value in spec.items() if name != "op"} + return {**spec, **resolve_intent_args(app_ctx, args, param_hint=hint)} + + +# --- the shared account resolver ------------------------------------------------------------ + + +def _resolve_account(app_ctx, param: str, value: str, hint: str) -> str: + """An ss58 address for ``value``: as-is when valid, otherwise looked up in + the address book, proxy book, or local wallets — or a did-you-mean error.""" + if is_bittensor_address(value): + return value + found = _lookup(app_ctx, param, value) + if found is None: + raise typer.BadParameter(_unresolved(app_ctx, param, value), param_hint=hint) + address, source = found + app_ctx.output.name_address(address, value) + app_ctx.output.classify_address(address, "hotkey" if "hotkey" in param else "coldkey") + app_ctx.output.message(f"[dim]{param}: resolved {source} to {address}[/dim]") + return address + + +def _lookup(app_ctx, param: str, name: str) -> Optional[tuple[str, str]]: + """(address, source description) for a known name, or None. + + Uses the same canonical lookup as ordinary CLI flags, including saved + multisig names for coldkey parameters. + """ + try: + resolved = app_ctx.resolve_address_ref(param, name) + except Exception: + return None + return resolved.address, resolved.source + + +def _unresolved(app_ctx, param: str, value: str) -> str: + base = f"{param}: {value!r} is not a valid ss58 address" + suggestion = _closest_name(app_ctx, value) + if suggestion: + name, address, source = suggestion + return f"{base} — did you mean {source} {name!r} ({address})?" + return f"{base} and matches no address-book, proxy-book, or wallet name" + + +def _closest_name(app_ctx, value: str) -> Optional[tuple[str, str, str]]: + """The known name closest to ``value`` as (name, address, source), or None.""" + candidates: dict[str, tuple[str, str]] = {} + for entry in cfg.load_addresses(): + name, address = entry.get("name"), entry.get("address") + if name and isinstance(address, str): + candidates.setdefault(name, (address, "address-book entry")) + for entry in cfg.load_proxies(): + name, address = entry.get("name"), entry.get("address") + if name and isinstance(address, str): + candidates.setdefault(name, (address, "proxy-book entry")) + try: + for info in wallets.list_wallets_detailed(app_ctx.wallet_path): + if info.ss58: + candidates.setdefault(info.name, (info.ss58, "wallet")) + for hk in info.hotkeys: + if hk.ss58: + candidates.setdefault(f"{info.name}/{hk.name}", (hk.ss58, "hotkey")) + except OSError: + pass # unreadable wallet dir; suggestions are cosmetic + close = difflib.get_close_matches(value, candidates, n=1, cutoff=0.6) + if not close: + return None + name = close[0] + address, source = candidates[name] + return name, address, source diff --git a/sdk/python/bittensor/cli/commands/evm/keys.py b/sdk/python/bittensor/cli/commands/evm/keys.py index a55ce5e887..5bd75ff7f9 100644 --- a/sdk/python/bittensor/cli/commands/evm/keys.py +++ b/sdk/python/bittensor/cli/commands/evm/keys.py @@ -2,6 +2,8 @@ from __future__ import annotations +import re +import sys from pathlib import Path from typing import Optional @@ -11,6 +13,8 @@ from ....evm.keys import write_keystore_file from ...context import ctx_of from ...globals import with_globals, with_unlock_globals +from ...prompt import interactive +from ...secrets import copy_secret_to_clipboard, warn_argv_secrets from ._shared import ( EVM_KEY_HELP, _key_fields, @@ -22,6 +26,8 @@ key_app, ) +_PRIVATE_KEY_RE = re.compile(r"(0x)?[0-9a-fA-F]{64}") + @key_app.command("new") @with_unlock_globals @@ -63,7 +69,11 @@ def key_import( ctx: typer.Context, name: str = typer.Option("default", "--name", help="Name to store the key under."), private_key: Optional[str] = typer.Option( - None, "--private-key", help="Raw 0x-hex private key (prompted for if flag given empty)." + None, + "--private-key", + help="Raw 0x-hex private key. Prompted for securely if no source is given; " + "avoid passing on the command line (it leaks to shell history and the " + "process list).", ), keystore: Optional[str] = typer.Option( None, "--keystore", help="Path to a keystore V3 JSON file (e.g. a MetaMask export)." @@ -81,8 +91,36 @@ def key_import( ), overwrite: bool = typer.Option(False, "--overwrite", help="Replace an existing key."), ): - """Import an EVM key from a private key, keystore file, or mnemonic.""" + """Import an EVM key from a private key, keystore file, or mnemonic. + + Pass one of --private-key, --keystore, or --mnemonic; if none are given + you are prompted securely on the terminal (a 64-hex-char answer is taken + as a private key, anything else as a mnemonic). + """ app_ctx = ctx_of(ctx) + warn_argv_secrets( + app_ctx.output, + { + "--private-key": private_key, + "--mnemonic": mnemonic, + "--keystore-password": keystore_password, + }, + ) + # An empty flag value (the old "prompt me" convention) counts as omitted. + private_key = private_key or None + mnemonic = mnemonic or None + if not private_key and not keystore and not mnemonic: + if not interactive(app_ctx): + app_ctx.output.error( + "missing key source: `--private-key`, `--keystore`, or `--mnemonic`", + help="pass one explicitly, or run on a terminal to be prompted", + ) + raise typer.Exit(2) + answer = typer.prompt("EVM private key or mnemonic", hide_input=True).strip() + if _PRIVATE_KEY_RE.fullmatch(answer): + private_key = answer + else: + mnemonic = answer keystore_json = None if keystore is not None: try: @@ -120,16 +158,24 @@ def key_export( private_key: bool = typer.Option( False, "--private-key", - help="Decrypt and print the raw 0x-hex private key (for ETH_PRIVATE_KEY " - "in Hardhat/Foundry). Prefer the encrypted keystore where the tool " - "supports it.", + help="Decrypt the raw 0x-hex private key (for ETH_PRIVATE_KEY in " + "Hardhat/Foundry). Copied to the clipboard on a terminal; printed when " + "piped, in --json mode, or with --show. Prefer the encrypted keystore " + "where the tool supports it.", + ), + show: bool = typer.Option( + False, + "--show", + help="With --private-key: print the raw key to the terminal instead of " + "copying it to the clipboard.", ), ): """Export a key's keystore V3 JSON (still encrypted) for MetaMask/geth/ethers. - With `--private-key`, decrypts and prints the raw key instead — the shape - JS toolchains want in an environment variable: - `export ETH_PRIVATE_KEY=$(btcli evm key export --private-key)`. + With `--private-key`, decrypts the raw key instead. On a terminal it goes + to the clipboard (pass --show to print); piped output still prints, so + `export ETH_PRIVATE_KEY=$(btcli evm key export --private-key)` keeps + working. """ app_ctx = ctx_of(ctx) info = _key_info(app_ctx, key) @@ -141,11 +187,19 @@ def key_export( ) raise typer.Exit(2) account = _unlock(app_ctx, key) + raw = "0x" + account.key.hex().removeprefix("0x") + # Piped stdout and JSON mode are data flows (agents, `$(...)`); a real + # terminal defaults to the clipboard so the key stays out of scrollback. + to_terminal = show or app_ctx.output.json_mode or not sys.stdout.isatty() + if not to_terminal and copy_secret_to_clipboard( + app_ctx.output, raw, f"private key for {info.name} ({info.address})" + ): + return app_ctx.output.message( f"raw private key for {info.name} ({info.address}) — anyone with this " "controls the account; it never expires and cannot be revoked" ) - app_ctx.output.value("0x" + account.key.hex().removeprefix("0x")) + app_ctx.output.value(raw) return keystore = evm_keys.export_evm_key(info.name, _key_ref(app_ctx, key)[0], app_ctx.wallet_path) if out: diff --git a/sdk/python/bittensor/cli/commands/root.py b/sdk/python/bittensor/cli/commands/root.py index 54798bab50..d2bc6e2920 100644 --- a/sdk/python/bittensor/cli/commands/root.py +++ b/sdk/python/bittensor/cli/commands/root.py @@ -107,7 +107,7 @@ def root_list( app_ctx.output.table( title, position_columns(all_wallets), - position_rows(shown), + position_rows(shown, all_wallets), shown_records, ) app_ctx.output.message( diff --git a/sdk/python/bittensor/cli/commands/stake.py b/sdk/python/bittensor/cli/commands/stake.py index 70b15b2417..8939967774 100644 --- a/sdk/python/bittensor/cli/commands/stake.py +++ b/sdk/python/bittensor/cli/commands/stake.py @@ -44,6 +44,7 @@ ("move", "move_stake"), ("transfer", "transfer_stake"), ("swap", "swap_stake"), + ("burn", "stake_burn"), ("unstake-all", "unstake_all"), ("unstake-all-alpha", "unstake_all_alpha"), ): diff --git a/sdk/python/bittensor/cli/commands/wallet.py b/sdk/python/bittensor/cli/commands/wallet.py index a4382fe296..177efdd8d2 100644 --- a/sdk/python/bittensor/cli/commands/wallet.py +++ b/sdk/python/bittensor/cli/commands/wallet.py @@ -46,6 +46,7 @@ wallet_overview_rows, ) from ..prompt import PromptSpec, confirm_wallet, fill_missing, interactive +from ..secrets import copy_secret_to_clipboard, warn_argv_secrets from ..tx import _parse_money app = typer.Typer(no_args_is_help=True, help="Create and manage wallets.") @@ -72,6 +73,13 @@ "line (it leaks to shell history and the process list)." ) +_PRIVATE_KEY_HELP = ( + "64-byte hex private key as stored in a decrypted coldkey/hotkey keyfile " + "(128 hex characters, optional 0x prefix). This is not the same as --seed: " + "the first 32 bytes of an sr25519 private key are not a usable seed. Avoid " + "passing on the command line (it leaks to shell history and the process list)." +) + _N_WORDS_HELP = ( "Number of words in the generated mnemonic: 12, 15, 18, 21, or 24. " "More words means more entropy." @@ -98,50 +106,71 @@ ) _SEED_RE = re.compile(r"(0x)?[0-9a-fA-F]{64}") +_PRIVATE_KEY_RE = re.compile(r"(0x)?[0-9a-fA-F]{128}") def _resolve_key_secret( - app_ctx: AppContext, kind: str, mnemonic: Optional[str], seed: Optional[str] -) -> tuple[Optional[str], Optional[str]]: - """Settle the (mnemonic, seed) pair for a regen command: exactly one of the - two, prompted for securely when neither was passed (btcli-style, the answer - is auto-detected — a 64-hex-char token is a seed, anything else a mnemonic).""" - if mnemonic and seed: - app_ctx.output.error("pass only one of `--mnemonic` or `--seed`") + app_ctx: AppContext, + kind: str, + mnemonic: Optional[str], + seed: Optional[str], + private_key: Optional[str] = None, +) -> tuple[Optional[str], Optional[str], Optional[str]]: + """Settle mnemonic / seed / private_key for a regen command. + + Exactly one source. When none are passed, prompt securely and auto-detect: + 128 hex chars → private key, 64 hex chars → seed, anything else → mnemonic. + """ + provided = sum(bool(value) for value in (mnemonic, seed, private_key)) + if provided > 1: + app_ctx.output.error("pass only one of `--mnemonic`, `--seed`, or `--private-key`") raise typer.Exit(2) + if private_key is not None: + if not _PRIVATE_KEY_RE.fullmatch(private_key): + app_ctx.output.error( + "private key must be 64 bytes of hex (128 hex characters, optional 0x prefix)" + ) + raise typer.Exit(2) + return None, None, private_key if seed is not None: # Validate here: the wallet lib panics (rust) on malformed hex. if not _SEED_RE.fullmatch(seed): app_ctx.output.error( - "seed must be 32 bytes of hex (64 hex characters, optional 0x prefix)" + "seed must be 32 bytes of hex (64 hex characters, optional 0x prefix); " + "for a 64-byte keyfile privateKey use --private-key" ) raise typer.Exit(2) - return None, seed + return None, seed, None if mnemonic is not None: - return mnemonic, None + return mnemonic, None, None if not interactive(app_ctx): app_ctx.output.error( - "missing required option: `--mnemonic` or `--seed`", + "missing required option: `--mnemonic`, `--seed`, or `--private-key`", help="pass one explicitly, or run on a terminal to be prompted", ) raise typer.Exit(2) - answer = typer.prompt(f"{kind} mnemonic or hex seed", hide_input=True).strip() + answer = typer.prompt(f"{kind} mnemonic, hex seed, or private key", hide_input=True).strip() + if _PRIVATE_KEY_RE.fullmatch(answer): + return None, None, answer if _SEED_RE.fullmatch(answer): - return None, answer - return answer, None + return None, answer, None + return answer, None, None def _resolve_coldkey_source( app_ctx: AppContext, mnemonic: Optional[str], seed: Optional[str], + private_key: Optional[str], json_path: Optional[str], json_password: Optional[str], -) -> tuple[Optional[str], Optional[str], Optional[tuple[str, str]]]: - """Resolve exactly one coldkey source: mnemonic, seed, or encrypted JSON.""" - provided = sum(bool(value) for value in (mnemonic, seed, json_path)) +) -> tuple[Optional[str], Optional[str], Optional[str], Optional[tuple[str, str]]]: + """Resolve exactly one coldkey source: mnemonic, seed, private key, or JSON.""" + provided = sum(bool(value) for value in (mnemonic, seed, private_key, json_path)) if provided > 1: - app_ctx.output.error("pass only one of `--mnemonic`, `--seed`, or `--json-path`") + app_ctx.output.error( + "pass only one of `--mnemonic`, `--seed`, `--private-key`, or `--json-path`" + ) raise typer.Exit(2) if json_path: @@ -165,10 +194,12 @@ def _resolve_coldkey_source( if not json_password: app_ctx.output.error("JSON keystore password cannot be empty") raise typer.Exit(2) - return None, None, (json_data, json_password) + return None, None, None, (json_data, json_password) - mnemonic, seed = _resolve_key_secret(app_ctx, "Coldkey", mnemonic, seed) - return mnemonic, seed, None + mnemonic, seed, private_key = _resolve_key_secret( + app_ctx, "Coldkey", mnemonic, seed, private_key + ) + return mnemonic, seed, private_key, None def _resolve_crypto_type(app_ctx: AppContext, value: str) -> int: @@ -372,6 +403,7 @@ def regen_coldkey( "the command line (it leaks to shell history and the process list).", ), seed: str = typer.Option(None, "--seed", help=_SEED_HELP), + private_key: str = typer.Option(None, "--private-key", help=_PRIVATE_KEY_HELP), json_path: str | None = typer.Option( None, "--json-path", @@ -387,19 +419,30 @@ def regen_coldkey( overwrite: bool = typer.Option(False, "--overwrite", help=_OVERWRITE_HELP), crypto_type: str = typer.Option("sr25519", "--crypto-type", help=_CRYPTO_TYPE_HELP), ): - """Regenerate a coldkey from a mnemonic, hex seed, or encrypted JSON keystore. - - Pass exactly one of --mnemonic, --seed, or --json-path; if none are given you - are prompted securely on the terminal. Rewrites the wallet's coldkey files on - disk and prompts for a new encryption password unless --no-password is given. - When importing from JSON, the key type is read from the keystore; --crypto-type - applies only to mnemonic/seed regeneration. + """Regenerate a coldkey from a mnemonic, seed, private key, or JSON keystore. + + Pass exactly one of --mnemonic, --seed, --private-key, or --json-path; if + none are given you are prompted securely on the terminal (128-hex → private + key, 64-hex → seed, otherwise mnemonic). Rewrites the wallet's coldkey + files on disk and prompts for a new encryption password unless --no-password + is given. When importing from JSON, the key type is read from the keystore; + --crypto-type applies only to mnemonic/seed/private-key regeneration. """ app_ctx: AppContext = ctx_of(ctx) - mnemonic, seed, json_keystore = _resolve_coldkey_source( + warn_argv_secrets( + app_ctx.output, + { + "--mnemonic": mnemonic, + "--seed": seed, + "--private-key": private_key, + "--json-password": json_password, + }, + ) + mnemonic, seed, private_key, json_keystore = _resolve_coldkey_source( app_ctx, mnemonic, seed, + private_key, json_path, json_password, ) @@ -409,6 +452,7 @@ def regen_coldkey( wallet = wallets.regen_coldkey( mnemonic=mnemonic, seed=seed, + private_key=private_key, json=json_keystore, name=app_ctx.wallet_name, path=app_ctx.wallet_path, @@ -441,19 +485,26 @@ def regen_hotkey( help="Hotkey mnemonic. Prompted for securely if omitted.", ), seed: str = typer.Option(None, "--seed", help=_SEED_HELP), + private_key: str = typer.Option(None, "--private-key", help=_PRIVATE_KEY_HELP), overwrite: bool = typer.Option(False, "--overwrite", help=_OVERWRITE_HELP), crypto_type: str = typer.Option("sr25519", "--crypto-type", help=_CRYPTO_TYPE_HELP), ): - """Regenerate a hotkey from a mnemonic or hex seed. + """Regenerate a hotkey from a mnemonic, hex seed, or private key. - Pass exactly one of --mnemonic or --seed; if neither is given you are - prompted securely on the terminal. Rewrites the hotkey file (stored - unencrypted) under the wallet path. The crypto type must match the one - the key was created with, or the regenerated key will have a different - address. + Pass exactly one of --mnemonic, --seed, or --private-key; if none are given + you are prompted securely on the terminal (128-hex → private key, 64-hex → + seed, otherwise mnemonic). Rewrites the hotkey file (stored unencrypted) + under the wallet path. The crypto type must match the one the key was + created with, or the regenerated key will have a different address. """ app_ctx: AppContext = ctx_of(ctx) - mnemonic, seed = _resolve_key_secret(app_ctx, "Hotkey", mnemonic, seed) + warn_argv_secrets( + app_ctx.output, + {"--mnemonic": mnemonic, "--seed": seed, "--private-key": private_key}, + ) + mnemonic, seed, private_key = _resolve_key_secret( + app_ctx, "Hotkey", mnemonic, seed, private_key + ) confirm_wallet( app_ctx, help_text="Wallet to regenerate the hotkey in.", @@ -465,6 +516,7 @@ def regen_hotkey( wallet = wallets.regen_hotkey( mnemonic=mnemonic, seed=seed, + private_key=private_key, name=app_ctx.wallet_name, hotkey=app_ctx.hotkey_name, path=app_ctx.wallet_path, @@ -656,14 +708,26 @@ def decrypt( use_hotkey: bool = typer.Option( False, "--use-hotkey", help="Decrypt with the hotkey instead of the coldkey." ), + copy: bool = typer.Option( + False, + "--copy", + help="Copy the decrypted message to the clipboard instead of printing it " + "(keeps secrets out of terminal scrollback).", + ), ): """Decrypt a message with the wallet key. Uses the coldkey by default, which requires unlocking it (you may be prompted for the wallet password). The decrypted plaintext is printed to - the terminal. + the terminal, or copied to the clipboard with --copy. """ app_ctx: AppContext = ctx_of(ctx) + if copy and app_ctx.output.json_mode: + app_ctx.output.error( + "`--copy` does not apply in --json mode", + help="drop --copy; JSON output prints the decrypted message", + ) + raise typer.Exit(2) confirm_wallet( app_ctx, help_text="Wallet that decrypts the message.", require_coldkey=not use_hotkey ) @@ -679,6 +743,8 @@ def decrypt( except Exception as error: app_ctx.output.error(f"decryption failed: {error}") raise typer.Exit(1) + if copy and copy_secret_to_clipboard(app_ctx.output, plaintext, "decrypted message"): + return app_ctx.output.detail("decrypted", {"message": plaintext}) @@ -888,8 +954,8 @@ def wallet_balance( ctx: typer.Context, address: Optional[str] = typer.Argument( None, - help="Coldkey ss58 address or a local wallet name. " - "Defaults to the configured wallet's coldkey.", + help="Coldkey ss58 address, a local wallet name, or an address-book / " + "saved multisig name. Defaults to the configured wallet's coldkey.", ), all_wallets: bool = typer.Option( False, "--all", "-a", help="Show balances for every wallet under --wallet-path." @@ -974,7 +1040,14 @@ def _amount(display: object, tao: float) -> str: return resolved = app_ctx.resolve_address("coldkey_ss58", address) - row = app_ctx.run(lambda client: wallet_balance_row(client, app_ctx.wallet_name, resolved)) + # Label the row with the name that was actually queried, not the configured + # wallet, when a positional name (wallet, book, or multisig) was given. + label = ( + address + if address is not None and not wallets.is_bittensor_address(address) + else app_ctx.wallet_name + ) + row = app_ctx.run(lambda client: wallet_balance_row(client, label, resolved)) app_ctx.output.detail(None, human_balance_fields(row), json_fields=row) @@ -991,7 +1064,11 @@ def wallet_overview( "JSON always includes every position.", ), ): - """Show free TAO and per-subnet stake for a wallet (or all wallets with --all).""" + """Show free TAO and per-subnet stake for a wallet (or all wallets with --all). + + Positions whose hotkey is registered on the subnet show the hotkey's UID + there, so registrations are visible at a glance. + """ app_ctx: AppContext = ctx_of(ctx) if all_wallets: targets = list_coldkeys(app_ctx.wallet_path) @@ -1003,7 +1080,9 @@ def wallet_overview( known_names = local_address_names(app_ctx.wallet_path) async def _fetch(client): - rows, valuations, lock_ctx = await wallet_overview_rows(client, targets, netuid=netuid) + rows, valuations, lock_ctx, uids = await wallet_overview_rows( + client, targets, netuid=netuid + ) unnamed = [ s["hotkey"] for row in rows for s in row["stakes"] if s["hotkey"] not in known_names ] @@ -1011,9 +1090,9 @@ async def _fetch(client): for lock in locks_by_netuid.values(): if lock["hotkey"] not in known_names: unnamed.append(lock["hotkey"]) - return rows, valuations, lock_ctx, await chain_identity_names(client, unnamed) + return rows, valuations, lock_ctx, uids, await chain_identity_names(client, unnamed) - rows, valuations, lock_ctx, identity_names = app_ctx.run(_fetch) + rows, valuations, lock_ctx, uids, identity_names = app_ctx.run(_fetch) out = app_ctx.output if out.json_mode: out.value(rows) @@ -1041,6 +1120,7 @@ async def _fetch(client): known_names, identity_names, {"wallet": name} if all_wallets else None, + uids=uids, ) locks_by_netuid, availability_by_netuid = lock_ctx[ss58] annotate_stake_groups_with_locks( diff --git a/sdk/python/bittensor/cli/context.py b/sdk/python/bittensor/cli/context.py index fcc37f9841..ff3cf59376 100644 --- a/sdk/python/bittensor/cli/context.py +++ b/sdk/python/bittensor/cli/context.py @@ -11,7 +11,7 @@ import asyncio import contextlib import sys -from dataclasses import dataclass, replace +from dataclasses import dataclass, field, replace from types import SimpleNamespace from typing import Awaitable, Callable, Optional, TypeVar @@ -69,12 +69,23 @@ def ss58_param_help(param: str) -> str: if param == "hotkey_ss58": text += " Defaults to your wallet's hotkey." else: - text = f"ss58 address, {book}or a local wallet name (uses its coldkey)." + text = ( + f"ss58 address, {book}saved multisig name, or a local wallet name (uses its coldkey)." + ) if param == "coldkey_ss58": text += " Defaults to your wallet's coldkey." return text +@dataclass(frozen=True) +class ResolvedAddress: + """A locally resolved account reference and how it was resolved.""" + + address: str + source: str + name: Optional[str] = None + + @dataclass class AppContext: network: str @@ -95,6 +106,10 @@ class AppContext: # Same for --wallet-hotkey/-H (or BT_WALLET_HOTKEY): hotkey-scoped commands # confirm the hotkey name when it was only defaulted. hotkey_given: bool = False + # When ``-w`` named a saved multisig and submit rewrote the intent, the + # multisig book name lives here while ``wallet_name`` is the local member + # coldkey that actually signs. + multisig_wallet_name: Optional[str] = None # Diagnostic log verbosity (-v count); kept so per-command --quiet/--verbose # overrides can reconfigure logging without losing the root-level setting. verbosity: int = 0 @@ -118,6 +133,9 @@ class AppContext: _extension_bridge_ws_url: Optional[str] = None _ledger_signer: Optional[object] = None _vault_signer: Optional[VaultSigner] = None + # Multisig names currently being derived by ``resolve_address`` — breaks + # the recursion when a saved multisig lists itself among its signatories. + _resolving_multisigs: set = field(default_factory=set) def reset_extension_session(self) -> None: self._extension_selection = None @@ -301,18 +319,59 @@ def signer(self, role: str = "coldkey"): keychain=self.keychain_password, ) + def resolve_address_ref(self, param: str, value: str) -> ResolvedAddress: + """Resolve one explicit account reference without prompting or exiting. + + This is the canonical lookup path shared by ordinary CLI flags and + account values nested inside raw-call / intent JSON. Callers own error + presentation; lookup failures from local wallet access are allowed to + propagate with their original context. + """ + kind = "hotkey" if "hotkey" in param else "coldkey" + if is_bittensor_address(value): + booked = next( + (e["name"] for e in cfg.load_addresses() if e.get("address") == value), None + ) + return ResolvedAddress(value, "ss58 address", booked) + + booked = cfg.get_address(value) + if booked: + return ResolvedAddress(booked, f"address-book entry {value!r}", value) + + proxy_entry = cfg.get_proxy(value) + proxied = proxy_entry.get("address") if proxy_entry else None + if isinstance(proxied, str) and proxied: + return ResolvedAddress(proxied, f"proxy-book entry {value!r}", value) + + if kind == "coldkey": + derived = self._saved_multisig_address(value) + if derived: + return ResolvedAddress(derived, f"saved multisig {value!r}", value) + + if kind == "hotkey": + wallet_name, _, hotkey = value.rpartition("/") + handle = wallets.open_wallet(wallet_name or self.wallet_name, hotkey, self.wallet_path) + return ResolvedAddress(handle.hotkey.ss58_address, f"hotkey {value!r}", value) + + address = wallets.open_wallet(name=value, path=self.wallet_path).coldkeypub.ss58_address + return ResolvedAddress(address, f"wallet {value!r}", value) + def resolve_address(self, param: str, value: Optional[str]) -> Optional[str]: """Resolve an address-typed CLI value (any ``*_ss58`` param) to an ss58 address. - Five accepted forms: + Six accepted forms: - a raw ss58 address: used as-is; - an address-book name (``btcli addresses NAME SS58``); - a proxy-book name (``btcli proxy book add``); + - a saved multisig name (``btcli multisig add``), coldkey params only: + resolved to the derived multisig account address, so a multisig + behaves like a wallet for read-only queries; - a local key reference: hotkey params take ``HOTKEY`` (in the configured wallet) or ``WALLET/HOTKEY``; coldkey params take a ``WALLET`` name (resolved to its coldkey); - omitted: only the canonical ``hotkey_ss58`` / ``coldkey_ss58`` params - fall back to the configured wallet's own key. Destination-style params + fall back to the configured wallet's own key (or its multisig address + when ``-w`` names a saved multisig). Destination-style params (``--dest``, ``--destination-hotkey``, ...) never default. """ kind = "hotkey" if "hotkey" in param else "coldkey" @@ -321,61 +380,75 @@ def resolve_address(self, param: str, value: Optional[str]) -> Optional[str]: # top-level import here would be circular. from .prompt import confirm_wallet - confirm_wallet( + # These keys are command *targets*, never signers, so a pasted ss58 + # or address-book name is accepted and used directly (the key does + # not have to exist locally). + value = confirm_wallet( self, help_text=f"Wallet whose {kind} this command targets.", require_coldkey=param == "coldkey_ss58", hotkey_help=("Hotkey this command targets." if param == "hotkey_ss58" else None), + accept_address=True, ) - if value is not None and is_bittensor_address(value): - booked = next( - (e["name"] for e in cfg.load_addresses() if e.get("address") == value), None - ) - self.output.name_address(value, booked) - self.output.classify_address(value, kind) - return value if value is not None: - booked = cfg.get_address(value) - if booked: - self.output.name_address(booked, value) - self.output.classify_address(booked, kind) - return booked - proxy_entry = cfg.get_proxy(value) - proxied = proxy_entry.get("address") if proxy_entry else None - if isinstance(proxied, str) and proxied: - self.output.name_address(proxied, value) - self.output.classify_address(proxied, kind) - return proxied + try: + resolved = self.resolve_address_ref(param, value) + except typer.Exit: + raise + except Exception as error: + self.output.error(f"cannot resolve {address_cli_name(param)} {value!r}: {error}") + raise typer.Exit(1) + self.output.name_address(resolved.address, resolved.name) + self.output.classify_address(resolved.address, kind) + return resolved.address try: - if value is None: - if param == "hotkey_ss58": - address = self.wallet().hotkey.ss58_address - self.output.name_address(address, f"{self.wallet_name}/{self.hotkey_name}") - self.output.classify_address(address, "hotkey") - return address - if param == "coldkey_ss58": - address = self.wallet().coldkeypub.ss58_address - self.output.name_address(address, self.wallet_name) - self.output.classify_address(address, "coldkey") - return address - return None - if "hotkey" in param: - wallet_name, _, hotkey = value.rpartition("/") - handle = wallets.open_wallet( - wallet_name or self.wallet_name, hotkey, self.wallet_path - ) - self.output.name_address(handle.hotkey.ss58_address, value) - self.output.classify_address(handle.hotkey.ss58_address, "hotkey") - return handle.hotkey.ss58_address - address = wallets.open_wallet(name=value, path=self.wallet_path).coldkeypub.ss58_address - self.output.name_address(address, value) - self.output.classify_address(address, "coldkey") - return address + if param == "hotkey_ss58": + address = self.wallet().hotkey.ss58_address + self.output.name_address(address, f"{self.wallet_name}/{self.hotkey_name}") + self.output.classify_address(address, "hotkey") + return address + if param == "coldkey_ss58": + # Same precedence as the write path: `-w ` means + # the multisig account, even if a wallet dir shares the name. + derived = self._saved_multisig_address(self.wallet_name) + if derived: + self.output.name_address(derived, self.wallet_name) + self.output.classify_address(derived, "coldkey") + return derived + address = self.wallet().coldkeypub.ss58_address + self.output.name_address(address, self.wallet_name) + self.output.classify_address(address, "coldkey") + return address + return None except Exception as error: - shown = value if value is not None else f"{self.wallet_name}/{self.hotkey_name}" + shown = f"{self.wallet_name}/{self.hotkey_name}" self.output.error(f"cannot resolve {address_cli_name(param)} {shown!r}: {error}") raise typer.Exit(1) + def _saved_multisig_address(self, name: Optional[str]) -> Optional[str]: + """Derived ss58 for a saved multisig ``name``, or None when not in the book. + + The derivation runs offline from the resolved signer set and threshold + (the same account-id derivation the chain uses), so read paths can + treat a multisig book name like a wallet without a connection. + """ + if not name or cfg.get_multisig(name) is None: + return None + if name in self._resolving_multisigs: + self.output.error( + f"multisig {name!r} refers to itself through its signatories", + help=f"fix the signer set with `btcli multisig add {name} --overwrite`", + ) + raise typer.Exit(2) + self._resolving_multisigs.add(name) + try: + return ms_helpers.derive_saved_multisig_address(self, name) + except ValueError as error: + self.output.error(f"cannot resolve multisig {name!r}: {error}") + raise typer.Exit(2) + finally: + self._resolving_multisigs.discard(name) + def resolve_signatory_list(self, raw: str) -> list[str]: """Resolve comma-separated signatory refs (ss58, address-book name, wallet).""" parts = [part.strip() for part in raw.split(",") if part.strip()] @@ -436,7 +509,7 @@ def submit( """ # Inline import: prompt.py imports AppContext from this module, so a # top-level import here would be circular. - from .prompt import confirm_wallet + from .prompt import confirm_wallet, replay_command if proxy_for == "self": proxy_for = None @@ -449,6 +522,15 @@ def submit( "— pass `--proxy-for self` to sign directly[/dim]" ) + # ``-w ``: rewrite any coldkey intent as a multisig approval + # signed by a local member. Must run before confirm_wallet / wallet() + # because the multisig name is not a coldkey directory. + try: + intent = ms_helpers.wrap_intent_for_multisig_wallet(self, intent) + except ValueError as error: + self.output.error(str(error)) + raise typer.Exit(2) from error + # MEV shielding: explicit flag > persistent config > the intent's own # default. `forced` distinguishes "the user asked for shielding" (hard # failure when it can't be honored) from "the built-in stake default" @@ -628,7 +710,7 @@ async def _shield_fee_warning(client): shortfall = self.run(_shield_fee_warning) if shortfall is not None: plan.warnings.append(shortfall) - self.output.plan(plan) + self.output.plan(plan, command=replay_command()) if not plan.ok: raise typer.Exit(1) return None diff --git a/sdk/python/bittensor/cli/globals.py b/sdk/python/bittensor/cli/globals.py index 8cb4067224..5091eaf864 100644 --- a/sdk/python/bittensor/cli/globals.py +++ b/sdk/python/bittensor/cli/globals.py @@ -163,6 +163,7 @@ False, "--yes", "-y", + "--no-prompt", # the v9 btcli spelling, kept as an alias help="Skip confirmation prompts.", rich_help_panel=PANEL_EXECUTION, ), diff --git a/sdk/python/bittensor/cli/helpers.py b/sdk/python/bittensor/cli/helpers.py index cb562616cd..1653130cd2 100644 --- a/sdk/python/bittensor/cli/helpers.py +++ b/sdk/python/bittensor/cli/helpers.py @@ -15,6 +15,7 @@ from .. import config as cfg from .. import wallets from .._generated import runtime_apis as api +from .._generated import storage as st from ..balance import Balance from ..client import Client from ..reads import StakePosition, StakeValuation @@ -118,6 +119,7 @@ def netuid_groups( identity_names: Optional[dict[str, str]] = None, extra: Optional[dict] = None, takes: Optional[dict[tuple[int, str], float]] = None, + uids: Optional[dict[tuple[int, str], int]] = None, ) -> list[dict]: """Collapse positions to per-netuid groups for the human view: the subnet total plus a per-hotkey breakdown (largest first), hotkeys labeled with @@ -126,9 +128,14 @@ def netuid_groups( ``takes`` maps ``(netuid, hotkey)`` to a delegate's take fraction; matching positions carry it so the renderer can annotate delegated stake in place (zero takes are dropped — they'd annotate almost every leaf with noise). + + ``uids`` maps ``(netuid, hotkey)`` to the hotkey's UID on that subnet (see + :func:`position_uids`); matching positions carry it so the renderer can + show where the hotkey is registered. """ identity_names = identity_names or {} takes = takes or {} + uids = uids or {} by_netuid: dict[int, list[StakePosition]] = {} for pos in positions: by_netuid.setdefault(pos.netuid, []).append(pos) @@ -156,6 +163,7 @@ def netuid_groups( "named": p.hotkey in hotkey_names, "identity": p.hotkey not in hotkey_names and p.hotkey in identity_names, "take": takes.get((p.netuid, p.hotkey)) or None, + "uid": uids.get((p.netuid, p.hotkey)), } for p in sorted(group, key=lambda p: -p.stake.rao) ], @@ -382,28 +390,65 @@ def _stake_record(position: StakePosition, valuation: StakeValuation) -> dict[st "stake_unit": "TAO" if position.netuid == 0 else f"alpha (netuid {position.netuid})", "value": str(value), "value_tao": value.tao, + "registered": position.is_registered, } +async def position_uids( + client: Client, positions: list[StakePosition] +) -> dict[tuple[int, str], int]: + """UID per ``(netuid, hotkey)`` for registered positions, in one batched query. + + Positions whose hotkey is not registered on the subnet are skipped (they + have no UID); everything else resolves against one block. + """ + pairs = sorted({(p.netuid, p.hotkey) for p in positions if p.is_registered}) + if not pairs: + return {} + values = await client.query_batch( + st.SubtensorModule.Uids, [[netuid, hotkey] for netuid, hotkey in pairs] + ) + return {pair: int(value) for pair, value in zip(pairs, values) if value is not None} + + async def wallet_overview_rows( client: Client, coldkeys: list[tuple[str, str]], netuid: Optional[int] = None, -) -> tuple[list[dict[str, object]], dict[str, StakeValuation], dict[str, tuple[dict, dict]]]: +) -> tuple[ + list[dict[str, object]], + dict[str, StakeValuation], + dict[str, tuple[dict, dict]], + dict[tuple[int, str], int], +]: """Stake overview for many coldkeys in a few batched RPC calls at one block. Returns the JSON-shaped rows plus the underlying valuations (positions and - spot prices) and per-coldkey lock contexts (see :func:`coldkey_lock_context`) - for human renderings that need more than the flat records. Rows whose - coldkey holds conviction locks carry the locked spot value and subnet count; - their stake records carry the locked/free split via + spot prices), per-coldkey lock contexts (see :func:`coldkey_lock_context`), + and the ``(netuid, hotkey) -> uid`` map for registered positions, for human + renderings that need more than the flat records. Rows whose coldkey holds + conviction locks carry the locked spot value and subnet count; their stake + records carry the locked/free split via :func:`enrich_stake_records_with_locks`. """ if not coldkeys: - return [], {}, {} + return [], {}, {}, {} free_by_addr, valuations = await fetch_coldkey_balances_and_valuations(client, coldkeys) - contexts = await asyncio.gather( - *[coldkey_lock_context(client, ss58, valuations[ss58].positions) for _, ss58 in coldkeys] + contexts, uids = await asyncio.gather( + asyncio.gather( + *[ + coldkey_lock_context(client, ss58, valuations[ss58].positions) + for _, ss58 in coldkeys + ] + ), + position_uids( + client, + [ + position + for _, ss58 in coldkeys + for position in filter_stakes(valuations[ss58].positions, netuid) + ], + ), ) lock_ctx = {ss58: ctx for (_, ss58), ctx in zip(coldkeys, contexts)} rows: list[dict[str, object]] = [] @@ -415,7 +460,13 @@ async def wallet_overview_rows( locked_value = Balance( sum(valuations[ss58].spot_value(row["locked"]).rao for row in locked_rows) ) - records = [_stake_record(position, valuations[ss58]) for position in stakes] + records = [ + { + **_stake_record(position, valuations[ss58]), + "uid": uids.get((position.netuid, position.hotkey)), + } + for position in stakes + ] enrich_stake_records_with_locks(records, locks_by_netuid, availability_by_netuid) rows.append( { @@ -433,7 +484,7 @@ async def wallet_overview_rows( "stakes": records, } ) - return rows, valuations, lock_ctx + return rows, valuations, lock_ctx, uids def _delegation_record(delegation, valuation: StakeValuation) -> dict[str, object]: diff --git a/sdk/python/bittensor/cli/intent_prompts.py b/sdk/python/bittensor/cli/intent_prompts.py new file mode 100644 index 0000000000..b51b6220c1 --- /dev/null +++ b/sdk/python/bittensor/cli/intent_prompts.py @@ -0,0 +1,148 @@ +"""Declarative prompt policies for generated transaction commands. + +The generated command runner should not grow an ``if intent.op == ...`` branch +for every richer prompt. Intent-specific choices live in this registry; the +runner applies the same small transformation pipeline to every operation. +""" + +from __future__ import annotations + +import functools +from dataclasses import dataclass +from typing import Callable, Optional + +import typer + +from .context import AppContext +from .prompt import PromptSpec, interactive +from .root_helpers import claim_root_source_spec +from .stake_picker import stake_source_spec, stake_target_spec, with_free_balance + + +@dataclass(frozen=True) +class PromptRule: + """Replace one ordinary prompt with a richer prompt at a stable position.""" + + field: str + build: Callable[[], PromptSpec] + before: Optional[str] = None + + +@dataclass(frozen=True) +class PromptDecorator: + """Wrap the ordinary prompt for ``field`` without changing its position.""" + + field: str + apply: Callable[[PromptSpec], PromptSpec] + + +@dataclass(frozen=True) +class IntentPromptPolicy: + rules: tuple[PromptRule, ...] = () + decorators: tuple[PromptDecorator, ...] = () + notice: Optional[Callable[[dict], Optional[str]]] = None + required_after_prompt: tuple[str, ...] = () + + +def _source(field: str, netuid_field: Optional[str]) -> PromptRule: + return PromptRule(field, functools.partial(stake_source_spec, field, netuid_field)) + + +def _target(field: str, amount_field: str) -> PromptRule: + return PromptRule(field, functools.partial(stake_target_spec, field), before=amount_field) + + +def _remove_stake_notice(kwargs: dict) -> Optional[str]: + if kwargs.get("netuid") is not None: + return None + if str(kwargs.get("amount_alpha") or "").strip().lower() != "all": + return None + return ( + "note: `--amount all` unstakes everything on a single subnet (--netuid); " + "to unstake every position across all subnets, use `btcli stake unstake-all`" + ) + + +_POLICIES: dict[str, IntentPromptPolicy] = { + "remove_stake": IntentPromptPolicy( + rules=(_source("hotkey_ss58", "netuid"),), notice=_remove_stake_notice + ), + "remove_stake_limit": IntentPromptPolicy(rules=(_source("hotkey_ss58", "netuid"),)), + "unstake_all": IntentPromptPolicy(rules=(_source("hotkey_ss58", None),)), + "unstake_all_alpha": IntentPromptPolicy(rules=(_source("hotkey_ss58", None),)), + "swap_stake": IntentPromptPolicy(rules=(_source("hotkey_ss58", "origin_netuid"),)), + "transfer_stake": IntentPromptPolicy(rules=(_source("hotkey_ss58", "origin_netuid"),)), + "move_stake": IntentPromptPolicy(rules=(_source("origin_hotkey_ss58", "origin_netuid"),)), + "claim_root_with_hotkey": IntentPromptPolicy( + rules=(PromptRule("hotkey_ss58", claim_root_source_spec),), + required_after_prompt=("hotkey_ss58",), + ), + "add_stake": IntentPromptPolicy( + rules=(_target("hotkey_ss58", "amount_tao"),), + decorators=(PromptDecorator("amount_tao", with_free_balance),), + ), + "add_stake_limit": IntentPromptPolicy( + rules=(_target("hotkey_ss58", "amount_tao"),), + decorators=(PromptDecorator("amount_tao", with_free_balance),), + ), + "stake_burn": IntentPromptPolicy( + decorators=(PromptDecorator("amount_tao", with_free_balance),) + ), +} + + +def apply_intent_prompt_policy( + app_ctx: AppContext, + op: str, + missing: list[PromptSpec], + kwargs: dict, +) -> list[PromptSpec]: + """Apply ``op``'s declarative prompt policy to the missing prompt list.""" + policy = _POLICIES.get(op) + if policy is None: + return missing + + if policy.notice is not None and (notice := policy.notice(kwargs)): + app_ctx.output.message(notice) + + prompts_ok = ( + not app_ctx.assume_yes and not app_ctx.uses_extension_signer() and interactive(app_ctx) + ) + if not prompts_ok: + return missing + + for rule in policy.rules: + if kwargs.get(rule.field) is not None: + continue + missing = [spec for spec in missing if spec.field != rule.field] + index = ( + next( + (i for i, spec in enumerate(missing) if spec.field == rule.before), + len(missing), + ) + if rule.before is not None + else 0 + ) + missing.insert(index, rule.build()) + + for decorator in policy.decorators: + missing = [ + decorator.apply(spec) if spec.field == decorator.field else spec for spec in missing + ] + return missing + + +def validate_intent_prompt_policy(app_ctx: AppContext, op: str, kwargs: dict) -> None: + """Enforce values that cannot silently fall back after policy prompting.""" + policy = _POLICIES.get(op) + if policy is None: + return + missing = [field for field in policy.required_after_prompt if kwargs.get(field) is None] + if not missing: + return + flags = ", ".join(f"`--{field.removesuffix('_ss58').replace('_', '-')}`" for field in missing) + app_ctx.output.error( + f"missing required option: {flags}", + help="pass it explicitly, or run on a terminal to pick one", + ) + raise typer.Exit(2) diff --git a/sdk/python/bittensor/cli/main.py b/sdk/python/bittensor/cli/main.py index 9a0242e973..b41e3b50e8 100644 --- a/sdk/python/bittensor/cli/main.py +++ b/sdk/python/bittensor/cli/main.py @@ -14,6 +14,7 @@ import importlib.metadata import json import sys +from pathlib import Path from typing import Optional import typer @@ -21,12 +22,13 @@ from .. import __version__, wallets from .._generated.errors import ERRORS +from ..config import config_path from ..config import get as config_default from ..error_descriptions import DESCRIPTIONS from ..error_map import DISPATCH_ERRORS from ..intents import list_tools from ..result import EXPLANATIONS, REMEDIATION, ChainError, ErrorCode, classify_error -from ..settings import DEFAULT_NETWORK, chain_error_docs_url, error_docs_url +from ..settings import DEFAULT_NETWORK, DOCS_URL, chain_error_docs_url, error_docs_url from . import globals as g from . import help_theme # noqa: F401 (restyles typer's --help at import) from .call import call as call_command @@ -208,6 +210,7 @@ def main_callback( False, "--yes", "-y", + "--no-prompt", # the v9 btcli spelling, kept as an alias help="Skip confirmation prompts.", rich_help_panel=g.PANEL_EXECUTION, ), @@ -488,10 +491,30 @@ def _warn_if_legacy_cli_installed() -> None: ) +def _warn_if_legacy_config() -> None: + """One-line stderr warning when a v9-era ``~/.bittensor/config.yml`` exists. + + This CLI never reads it, so settings people expect (network, wallet, ...) + silently fall back to defaults — the most common migration confusion. Warn + until the stale file is renamed or removed. + """ + legacy = Path.home() / ".bittensor" / "config.yml" + if not legacy.is_file(): + return + print( + f"warning: {legacy} is the legacy (v9) btcli config and is ignored by this CLI; " + f"migrate values with `btcli config set` (stored in {config_path()}), then rename " + f"or delete the old file to silence this warning. " + f"Migration guide: {DOCS_URL}/migration", + file=sys.stderr, + ) + + def main() -> None: from bittensor.wallets import is_bittensor_address _warn_if_legacy_cli_installed() + _warn_if_legacy_config() argv = sys.argv[1:] if ( len(argv) >= 3 diff --git a/sdk/python/bittensor/cli/multisig_helpers.py b/sdk/python/bittensor/cli/multisig_helpers.py index 78330c5616..37626972b4 100644 --- a/sdk/python/bittensor/cli/multisig_helpers.py +++ b/sdk/python/bittensor/cli/multisig_helpers.py @@ -11,6 +11,7 @@ from .. import config as cfg from .. import wallets from .._generated import storage as st +from .._transport.codec import multisig_account from ..result import ChainError, ExtrinsicResult from ..wallets import is_bittensor_address @@ -165,14 +166,17 @@ def build_replay_command( if force_proxy_type: parts.append(f"--force-proxy-type {shlex.quote(force_proxy_type)}") if preset: - parts.append(f"--multisig {shlex.quote(preset)}") + # ``-w `` auto-picks a local member and wraps the call; each + # co-signer can paste the same command on their machine. + parts.append(f"-w {shlex.quote(preset)}") elif other_signatory_labels: parts.append(f"--multisig-threshold {threshold}") parts.append(f"--other-signatories {shlex.quote(','.join(other_signatory_labels))}") + parts.append(f"-w {shlex.quote(wallet_label)}") else: parts.append(f"--multisig-threshold {threshold}") parts.append(f"--signatories {shlex.quote(','.join(signatories))}") - parts.append(f"-w {shlex.quote(wallet_label)}") + parts.append(f"-w {shlex.quote(wallet_label)}") if signer_role != "coldkey": parts.append(f"--signer {signer_role}") return " ".join(parts) @@ -242,6 +246,21 @@ def resolve_multisig( return threshold, sigs, None, refs +def derive_saved_multisig_address(app_ctx, name: str) -> Optional[str]: + """Derived ss58 of the saved multisig ``name``, or None when not in the book. + + Fully offline: signatory refs (ss58, book names, wallet names) resolve + locally and the account id derivation is deterministic, so read-only + commands can treat a multisig book name like any other address without a + chain connection. + """ + entry = cfg.get_multisig(name) + if entry is None: + return None + signatories = _resolve_stored_signatories(app_ctx, list(entry["signatories"])) + return multisig_account(signatories, int(entry["threshold"])).ss58_address + + def resolve_multisig_preset(app_ctx, name: str) -> tuple[int, list[str], list[str]]: """Return threshold, resolved ss58 signatories, and preset refs.""" threshold, signatories, _, refs = resolve_multisig(app_ctx, multisig_name=name) @@ -250,6 +269,178 @@ def resolve_multisig_preset(app_ctx, name: str) -> tuple[int, list[str], list[st return threshold, signatories, refs +_MULTISIG_OPS = frozenset( + { + "multisig_approve", + "multisig_cancel", + "multisig_execute", + "multisig_threshold_1", + } +) + + +def local_signatory_wallets(app_ctx, signatories: list[str]) -> list[tuple[str, str]]: + """Local coldkey wallets whose ss58 is in ``signatories``: ``(name, ss58)``.""" + wanted = set(signatories) + found: list[tuple[str, str]] = [] + try: + for coldkey in wallets.list_wallets_detailed(app_ctx.wallet_path): + if coldkey.ss58 in wanted: + found.append((coldkey.name, coldkey.ss58)) + except Exception: + return [] + # Stable order matching the resolved signatory list. + order = {ss58: index for index, ss58 in enumerate(signatories)} + found.sort(key=lambda item: order.get(item[1], len(order))) + return found + + +def pick_local_signatory(app_ctx, *, preset: str, signatories: list[str]) -> tuple[str, str]: + """Choose which local member coldkey signs for a saved multisig. + + Returns ``(wallet_name, ss58)``. Auto-selects when exactly one member is + present locally; prompts when several are; errors when none are. + """ + from .prompt import PromptSpec, fill_missing, interactive + + locals_ = local_signatory_wallets(app_ctx, signatories) + if not locals_: + raise ValueError( + f"no local signatory wallet for multisig {preset!r}; " + "install one of its member coldkeys under --wallet-path, or pass " + f"`--multisig {preset} -w `" + ) + if len(locals_) == 1: + name, ss58 = locals_[0] + app_ctx.output.message( + f"[dim]signing as local member {format_signatory_display(ss58, name)} " + f"for multisig {preset}[/dim]" + ) + return name, ss58 + + by_name = {name: ss58 for name, ss58 in locals_} + if app_ctx.assume_yes or not interactive(app_ctx): + raise ValueError( + f"multisig {preset!r} has {len(locals_)} local member wallets " + f"({', '.join(by_name)}); pass `-w ` (with " + f"`--multisig {preset}`) to choose one non-interactively" + ) + + def _parse(app_ctx_, raw: str) -> str: + if raw not in by_name: + known = ", ".join(sorted(by_name)) + raise ValueError(f"unknown local signatory {raw!r}; choose one of: {known}") + return raw + + answers: dict = {} + fill_missing( + app_ctx, + [ + PromptSpec( + field="signatory_wallet", + flag="--wallet", + help=f"Which local member of multisig {preset!r} signs this approval.", + parse=_parse, + default=locals_[0][0], + ) + ], + answers, + ) + name = answers["signatory_wallet"] + return name, by_name[name] + + +async def pending_timepoint_for_call( + client, + *, + signatories: list[str], + threshold: int, + call_hash: str, + signer_ss58: str, +) -> Optional[dict[str, int]]: + """Return the opening timepoint for a pending op matching ``call_hash``. + + Errors if this signer already approved. Returns ``None`` when nothing is + pending (caller should open a new operation). + """ + ms = await client.multisig(signatories, threshold) + wanted = hex_bytes(call_hash) + for row in await list_pending_multisig_ops(client, ms.address): + if row["call_hash"] != wanted: + continue + if signer_ss58 in row.get("approvals") or []: + raise ValueError( + f"this signatory already approved pending call {wanted}; " + "wait for another member, or cancel the operation" + ) + return dict(row["timepoint"]) + return None + + +def wrap_intent_for_multisig_wallet(app_ctx, intent): + """If ``-w`` names a saved multisig, rewrite ``intent`` as a multisig approval. + + Picks a local member coldkey to sign, converts the original intent into a + ``multisig_execute`` / ``multisig_threshold_1`` wrapper (same shape as + ``btcli call --multisig``), and auto-fills the opening ``timepoint`` when a + matching pending operation already exists — so every co-signer can re-run + the same ``btcli wallet transfer -w ...`` command. + + Raises ``ValueError`` when the preset or local signatory set is unusable. + """ + from ..intents.multisig import MultisigExecute, MultisigThreshold1, _compose_inner + + if getattr(intent, "signer", None) != "coldkey": + return intent + if getattr(intent, "op", None) in _MULTISIG_OPS: + return intent + preset = app_ctx.wallet_name + if not preset or cfg.get_multisig(preset) is None: + return intent + + threshold, signatories, _refs = resolve_multisig_preset(app_ctx, preset) + member_name, signer_ss58 = pick_local_signatory(app_ctx, preset=preset, signatories=signatories) + + # Remember the multisig account name for summaries; the signing wallet is + # the local member that actually unlocks a coldkey. + app_ctx.multisig_wallet_name = preset + app_ctx.wallet_name = member_name + app_ctx.wallet_given = True + + others = [ss58 for ss58 in signatories if ss58 != signer_ss58] + call_dict = intent.to_dict() + + if threshold == 1: + app_ctx.output.message( + f"[dim]dispatching via 1-of-{len(signatories)} multisig {preset}[/dim]" + ) + return MultisigThreshold1(other_signatories=others, call=call_dict) + + async def _timepoint(client): + wallet = wallets.open_wallet(member_name, path=app_ctx.wallet_path) + inner = await _compose_inner(client._substrate, wallet, call_dict) + return await pending_timepoint_for_call( + client, + signatories=signatories, + threshold=threshold, + call_hash=inner.call_hash, + signer_ss58=signer_ss58, + ) + + timepoint = app_ctx.run(_timepoint) + action = "approving" if timepoint else "opening" + app_ctx.output.message( + f"[dim]{action} via {threshold}-of-{len(signatories)} multisig {preset} " + f"as {format_signatory_display(signer_ss58, member_name)}[/dim]" + ) + return MultisigExecute( + threshold=threshold, + other_signatories=others, + call=call_dict, + timepoint=timepoint, + ) + + async def multisig_list_records( client, app_ctx, diff --git a/sdk/python/bittensor/cli/output.py b/sdk/python/bittensor/cli/output.py index 80d0a6e19c..5324c48302 100644 --- a/sdk/python/bittensor/cli/output.py +++ b/sdk/python/bittensor/cli/output.py @@ -933,6 +933,8 @@ def stake_list( if url: label_style = f"{label_style} link {url}" leaf.append(str(position["label"]), style=label_style) + if position.get("uid") is not None: + leaf.append(f" uid {position['uid']}", style="dim") if position.get("take") is not None: leaf.append(f" take {position['take']:.1%}", style="dim") if position.get("note"): @@ -1378,10 +1380,19 @@ def _print_copyable(self, text: str, *, prefix: str = " ") -> None: line.append(text, style=STYLE_COMMAND) self._out.print(line, soft_wrap=True) - def plan(self, plan: Plan) -> None: - """Render a dry-run plan (fee, effects, warnings, policy).""" + def plan(self, plan: Plan, *, command: Optional[str] = None) -> None: + """Render a dry-run plan (fee, effects, warnings, policy). + + ``command`` is the replay command that submits this exact invocation + for real: shown as a copy-paste line, and carried in the JSON record + so an agent can pre-approve the plan and hand a human (or a later + automation step) the one command to run. + """ if self.json_mode: - self._json(plan.to_dict()) + record = plan.to_dict() + if command: + record["command"] = command + self._json(record) return summary = Text() summary.append("dry run:", style="dim") @@ -1417,6 +1428,11 @@ def plan(self, plan: Plan) -> None: ) if not plan.ok: self._out.print(f" [{STYLE_ERROR}]blocked by policy[/{STYLE_ERROR}]") + if command and plan.ok: + line = Text(" ") + line.append("run for real ", style=STYLE_HINT) + line.append(command, style=STYLE_COMMAND) + self._out.print(line, soft_wrap=True) # The docs page carries parameters, verify reads, and the on-chain # implementation with source links. self._sub_diag("see", tx_docs_url(plan.op), console=self._out) diff --git a/sdk/python/bittensor/cli/prompt.py b/sdk/python/bittensor/cli/prompt.py index c796d3f71b..3bf18fa5f9 100644 --- a/sdk/python/bittensor/cli/prompt.py +++ b/sdk/python/bittensor/cli/prompt.py @@ -37,6 +37,7 @@ exceptions as click_exceptions, ) +from .. import config as cfg from .. import wallets from .context import AppContext from .output import STYLE_COMMAND, STYLE_HINT @@ -88,7 +89,7 @@ def _missing_error(app_ctx: AppContext, flags: list[str]) -> None: raise typer.Exit(2) -def _ask(console: Console, app_ctx: AppContext, spec: PromptSpec) -> tuple[Any, str]: +def ask(console: Console, app_ctx: AppContext, spec: PromptSpec) -> tuple[Any, str]: """Prompt for one option until an answer parses; returns (value, raw text).""" if spec.help: hint = Text(" ") @@ -151,7 +152,7 @@ def fill_missing(app_ctx: AppContext, missing: list[PromptSpec], kwargs: dict[st _entered_tokens.extend(spec.custom(console, app_ctx, kwargs)) console.print() continue - kwargs[spec.field], raw = _ask(console, app_ctx, spec) + kwargs[spec.field], raw = ask(console, app_ctx, spec) _entered_tokens.extend([raw] if spec.positional else [spec.flag, raw]) console.print() @@ -172,11 +173,20 @@ def _parse_wallet(app_ctx: AppContext, raw: str, *, require_coldkey: bool = True A bad name re-prompts with the wallets that *are* available. The coldkey is only demanded when it is the signing key (hotkey-signed intents may use a - coldkey-less wallet dir). + coldkey-less wallet dir). Saved multisig book names are also accepted — + ``AppContext.submit`` rewrites the intent to a multisig approval signed by + a local member. """ known = wallets.list_wallets(app_ctx.wallet_path) if raw not in known: - raise _unknown_name_error("wallet", raw, sorted(known)) + if cfg.get_multisig(raw) is not None: + app_ctx.wallet_name = raw + app_ctx.wallet_given = True + return raw + suggestions = sorted( + set(known) | {str(entry["name"]) for entry in cfg.load_multisigs() if entry.get("name")} + ) + raise _unknown_name_error("wallet", raw, suggestions) try: address = wallets.open_wallet( raw, app_ctx.hotkey_name, app_ctx.wallet_path @@ -222,6 +232,49 @@ def _parse_hotkey(app_ctx: AppContext, raw: str) -> str: return raw +def _parse_target_hotkey(app_ctx: AppContext, raw: str) -> str: + """Parse a *target* hotkey: local names keep the normal path, but a pasted + ss58 address, an address-book name, or ``WALLET/HOTKEY`` also work — the + target of a command never has to exist locally (only signers do).""" + known = wallets.list_wallets(app_ctx.wallet_path).get(app_ctx.wallet_name, []) + if raw in known: + return _parse_hotkey(app_ctx, raw) + if wallets.is_bittensor_address(raw): + return raw + booked = cfg.get_address(raw) + if booked: + app_ctx.output.name_address(booked, raw) + return booked + if "/" in raw: + wallet_name, _, hotkey = raw.rpartition("/") + try: + handle = wallets.open_wallet( + wallet_name or app_ctx.wallet_name, hotkey, app_ctx.wallet_path + ) + address = handle.hotkey.ss58_address + except Exception as error: + raise ValueError(f"cannot open hotkey {raw!r}: {error}") + app_ctx.output.name_address(address, raw) + return address + error = _unknown_name_error(f"hotkey in wallet {app_ctx.wallet_name!r}", raw, sorted(known)) + raise ValueError(f"{error} — or paste an ss58 address / address-book name") + + +def _parse_target_wallet(app_ctx: AppContext, raw: str, *, require_coldkey: bool = True) -> str: + """Parse a *target* coldkey: a local wallet name as usual, but a pasted + ss58 address or address-book name also works (no signature needed).""" + if wallets.is_bittensor_address(raw): + return raw + booked = cfg.get_address(raw) + if booked: + app_ctx.output.name_address(booked, raw) + return booked + try: + return _parse_wallet(app_ctx, raw, require_coldkey=require_coldkey) + except ValueError as error: + raise ValueError(f"{error} — or paste an ss58 address / address-book name") + + def confirm_wallet( app_ctx: AppContext, *, @@ -230,7 +283,8 @@ def confirm_wallet( must_exist: bool = True, hotkey_help: Optional[str] = None, hotkey_must_exist: bool = True, -) -> None: + accept_address: bool = False, +) -> Optional[str]: """Confirm the target wallet (and optionally hotkey) when only defaulted. Wallet-scoped commands call this so a bare invocation doesn't silently act @@ -244,12 +298,24 @@ def confirm_wallet( Hotkey-scoped commands additionally pass ``hotkey_help`` so the hotkey name is confirmed in the same round (skipped by ``--wallet-hotkey``/``-H`` or ``BT_WALLET_HOTKEY``); ``hotkey_must_exist=False`` accepts any name. + + With ``accept_address`` (used when the key being confirmed is a command + *target*, not a signer) a pasted ss58 address or address-book name is also + accepted — the key doesn't have to exist locally. The pasted address is + returned so the caller can use it directly; local selections return None. """ skip = app_ctx.assume_yes or app_ctx.uses_external_signer() specs: list[PromptSpec] = [] if not app_ctx.wallet_given and not skip: + # A paste is only meaningful at the last prompt of the round: with a + # hotkey prompt following, the wallet answer selects whose hotkeys are + # on offer and stays a local name. + wallet_is_target = accept_address and hotkey_help is None parse: Parser = ( - functools.partial(_parse_wallet, require_coldkey=require_coldkey) + functools.partial( + _parse_target_wallet if wallet_is_target else _parse_wallet, + require_coldkey=require_coldkey, + ) if must_exist else _parse_wallet_name ) @@ -263,22 +329,46 @@ def confirm_wallet( ) ) if hotkey_help is not None and not app_ctx.hotkey_given and not skip: + if accept_address: + known = sorted(wallets.list_wallets(app_ctx.wallet_path).get(app_ctx.wallet_name, [])) + if known: + listing = ", ".join(known[:8]) + (", …" if len(known) > 8 else "") + hotkey_help += ( + f" A local hotkey ({listing}), a pasted ss58 address, or an address-book name." + ) + else: + hotkey_help += ( + f" Wallet {app_ctx.wallet_name!r} has no local hotkeys — paste the " + "hotkey's ss58 address or an address-book name." + ) + hotkey_parse: Parser = _parse_target_hotkey + hotkey_default = app_ctx.hotkey_name if app_ctx.hotkey_name in known else None + else: + hotkey_parse = _parse_hotkey if hotkey_must_exist else _parse_hotkey_name + hotkey_default = app_ctx.hotkey_name specs.append( PromptSpec( field="wallet_hotkey", flag="--wallet-hotkey", help=hotkey_help, - parse=_parse_hotkey if hotkey_must_exist else _parse_hotkey_name, - default=app_ctx.hotkey_name, + parse=hotkey_parse, + default=hotkey_default, ) ) + answers: dict[str, Any] = {} if specs: - fill_missing(app_ctx, specs, {}) + fill_missing(app_ctx, specs, answers) # Confirmed (or silently kept in a non-interactive session) — later # default fallbacks in the same invocation must not ask again. app_ctx.wallet_given = True if hotkey_help is not None: app_ctx.hotkey_given = True + if accept_address: + for key in ("wallet_hotkey", "wallet"): + answer = answers.get(key) + if isinstance(answer, str) and wallets.is_bittensor_address(answer): + return answer + return None def signer_specs( @@ -316,6 +406,21 @@ def signer_specs( return specs +def replay_command() -> str: + """The command that submits this invocation for real: the current argv plus + any prompted answers, minus ``--dry-run`` and ``--json``, quoted for + copy-paste. This is what a dry run hands to whoever actually runs it — the + confirmation prompt is kept (no ``--yes`` is injected), so the human still + sees the summary before signing; automation can append ``--yes --json``. + """ + drop = {"--dry-run", "--json"} + tokens = [ + Path(sys.argv[0]).name, + *(token for token in [*sys.argv[1:], *_entered_tokens] if token not in drop), + ] + return " ".join(shlex.quote(part) for part in tokens) + + def _flush_command_hint(exit_code: int) -> None: """Echo the equivalent non-interactive command so the flags are learnable. @@ -489,7 +594,7 @@ def _run_app(app: typer.Typer) -> None: console = Console(stderr=True, highlight=False) console.print() for spec in specs: - _, raw = _ask(console, app_ctx, spec) + _, raw = ask(console, app_ctx, spec) entered = [raw] if spec.positional else [spec.flag, raw] args += entered _entered_tokens.extend(entered) diff --git a/sdk/python/bittensor/cli/root_helpers.py b/sdk/python/bittensor/cli/root_helpers.py index a88920a604..73ecb08c4e 100644 --- a/sdk/python/bittensor/cli/root_helpers.py +++ b/sdk/python/bittensor/cli/root_helpers.py @@ -474,6 +474,10 @@ def print_command_hint(console: Console, argv_prefix: list[str]) -> None: def render_validator_detail( app_ctx: AppContext, summary: dict, yours: Optional[RootPosition] ) -> None: + if app_ctx.output.json_mode: + app_ctx.output.value(summary) + return + hotkey = summary["hotkey"] weights = summary.get("weights") or [] holdings = summary.get("holdings") or [] @@ -491,7 +495,6 @@ def render_validator_detail( f"weights of {hotkey}", ["netuid", "share", "weight (u16)"], weight_rows, - weights, ) else: app_ctx.output.message( @@ -513,7 +516,6 @@ def render_validator_detail( f"fund holdings of {hotkey}", ["netuid", "holding", "realizable", "spot"], table_rows, - summary, ) lifetime = summary.get("lifetime_return") @@ -524,10 +526,10 @@ def render_validator_detail( ) -def position_rows(positions: list[RootPosition]) -> list[list[str]]: +def position_rows(positions: list[RootPosition], all_wallets: bool) -> list[list[str]]: return [ - [ - pos.wallet or "—", + ([pos.wallet or "—"] if all_wallets else []) + + [ pos.hotkey, str(pos.staked), str(pos.accrued), diff --git a/sdk/python/bittensor/cli/secrets.py b/sdk/python/bittensor/cli/secrets.py new file mode 100644 index 0000000000..72726a07bd --- /dev/null +++ b/sdk/python/bittensor/cli/secrets.py @@ -0,0 +1,75 @@ +"""Helpers for handling secret material at the CLI boundary. + +Secrets passed as command-line flags leak into shell history and ``ps`` +output; secrets printed to the terminal land in scrollback. These helpers +warn about the former and route the latter to the system clipboard. +""" + +from __future__ import annotations + +import shutil +import subprocess + +from .output import STYLE_WARNING, Output + +# Tried in order; the first tool on PATH wins. pbcopy is macOS, wl-copy is +# Wayland, xclip/xsel are X11. +_CLIPBOARD_COMMANDS: tuple[tuple[str, ...], ...] = ( + ("pbcopy",), + ("wl-copy",), + ("xclip", "-selection", "clipboard"), + ("xsel", "--clipboard", "--input"), +) + + +def warn_argv_secrets(output: Output, provided: dict[str, object]) -> None: + """Warn when secret-bearing flags were given on the command line. + + ``provided`` maps flag spelling (``--mnemonic``) to the value the command + received. Only flags with a non-empty value warn: these options have no + env or config source, so a value at command entry can only have come from + argv (secure-prompt fallbacks fill in *after* this check). + """ + flags = [flag for flag, value in provided.items() if value] + if not flags: + return + names = ", ".join(f"`{flag}`" for flag in flags) + output.message( + f"[{STYLE_WARNING}]warning:[/{STYLE_WARNING}] secrets passed as flags ({names}) " + "land in shell history and `ps` output — omit the flag to be prompted without echo" + ) + + +def copy_to_clipboard(text: str) -> bool: + """Copy ``text`` to the system clipboard; True when a tool succeeded.""" + for command in _CLIPBOARD_COMMANDS: + if shutil.which(command[0]) is None: + continue + try: + subprocess.run( + command, + input=text.encode(), + check=True, + capture_output=True, + timeout=10, + ) + except (OSError, subprocess.SubprocessError): + continue + return True + return False + + +def copy_secret_to_clipboard(output: Output, text: str, label: str) -> bool: + """Copy a secret to the clipboard, confirming without echoing it. + + Returns False (after a warning) when no clipboard tool is available, in + which case the caller should fall back to printing. + """ + if copy_to_clipboard(text): + output.message(f"{label} copied to clipboard (not printed)") + return True + output.message( + f"[{STYLE_WARNING}]warning:[/{STYLE_WARNING}] no clipboard tool found " + "(pbcopy, wl-copy, xclip, or xsel) — printing instead" + ) + return False diff --git a/sdk/python/bittensor/cli/stake_picker.py b/sdk/python/bittensor/cli/stake_picker.py index b9c466c410..e98af6edda 100644 --- a/sdk/python/bittensor/cli/stake_picker.py +++ b/sdk/python/bittensor/cli/stake_picker.py @@ -12,35 +12,140 @@ from __future__ import annotations import asyncio -from dataclasses import dataclass +from dataclasses import dataclass, replace from typing import Callable, Optional import typer from rich.console import Console from rich.text import Text +from .. import wallets from ..balance import Balance from ..reads import StakePosition, StakeValuation from .context import AppContext, address_cli_name from .helpers import chain_identity_names, local_address_names from .output import STYLE_COMMAND, STYLE_HINT, STYLE_KEY, STYLE_NAME, Output -from .prompt import PromptSpec +from .prompt import PromptSpec, ask # Positions whose spot value is below this are dust: hidden from the pickers # (unless everything is dust) but still selectable by typing the netuid/hotkey. _DUST_RAO = 1_000_000 # τ0.001 -# op -> (hotkey field the stake comes from, netuid field naming its subnet). -# A None netuid field means the op spans every subnet the hotkey is staked on. -STAKE_SOURCE_FIELDS: dict[str, tuple[str, Optional[str]]] = { - "remove_stake": ("hotkey_ss58", "netuid"), - "remove_stake_limit": ("hotkey_ss58", "netuid"), - "unstake_all": ("hotkey_ss58", None), - "unstake_all_alpha": ("hotkey_ss58", None), - "swap_stake": ("hotkey_ss58", "origin_netuid"), - "transfer_stake": ("hotkey_ss58", "origin_netuid"), - "move_stake": ("origin_hotkey_ss58", "origin_netuid"), -} + +def stake_target_spec(hotkey_field: str) -> PromptSpec: + """A PromptSpec whose custom flow picks the destination hotkey to stake to.""" + return PromptSpec( + field=hotkey_field, + flag=address_cli_name(hotkey_field), + help=None, + parse=lambda _app_ctx, raw: raw, # unused: the custom flow does everything + custom=lambda console, app_ctx, kwargs: _pick_target( + console, app_ctx, kwargs, hotkey_field + ), + ) + + +def _pick_target( + console: Console, + app_ctx: AppContext, + kwargs: dict, + hotkey_field: str, +) -> list[str]: + """List the wallet's local hotkeys and ask which validator to stake to. + + Any answer the flag form would take also works: a list number, a local + hotkey name (or ``WALLET/HOTKEY``), an address-book name, or a pasted + ss58 — the target does not have to exist locally. + """ + local = next( + ( + ck.hotkeys + for ck in wallets.list_wallets_detailed(app_ctx.wallet_path) + if ck.name == app_ctx.wallet_name + ), + [], + ) + local = [hk for hk in local if hk.ss58] + flag = address_cli_name(hotkey_field) + + hint = Text(" ") + hint.append(flag, style=STYLE_COMMAND) + hint.append(" ") + hint.append( + "Validator hotkey the stake goes to — it does not have to be a local key.", + style=STYLE_HINT, + ) + console.print(hint) + if local: + labels = [f"{app_ctx.wallet_name}/{hk.name}" for hk in local] + label_width = max(len(label) for label in labels) + number_width = len(str(len(local))) + for index, (hk, label) in enumerate(zip(local, labels), start=1): + line = Text(" ", overflow="ignore", no_wrap=True) + line.append(str(index).rjust(number_width), style=STYLE_COMMAND) + line.append(" ") + line.append(label.ljust(label_width), style=STYLE_NAME) + line.append(f" {hk.ss58}", style="dim") + console.print(line, soft_wrap=True) + console.print( + " [dim]a number above, or any hotkey: ss58 address, address-book name, " + "or WALLET/HOTKEY[/dim]" + ) + else: + console.print( + f" [dim]wallet {app_ctx.wallet_name!r} has no local hotkeys — paste the " + "validator's ss58 address or an address-book name[/dim]" + ) + + prompt = Text(" ") + prompt.append(flag.lstrip("-"), style=STYLE_COMMAND) + prompt.append(": ", style=STYLE_COMMAND) + while True: + try: + raw = console.input(prompt).strip() + except (KeyboardInterrupt, EOFError): + console.print() + app_ctx.output.message("aborted.") + raise typer.Exit(130) + if not raw: + console.print(" a value is required", style=STYLE_HINT) + continue + if raw.isdigit() and local: + index = int(raw) + if 1 <= index <= len(local): + chosen = local[index - 1] + app_ctx.output.name_address(chosen.ss58, f"{app_ctx.wallet_name}/{chosen.name}") + kwargs[hotkey_field] = chosen.ss58 + return [flag, chosen.ss58] + console.print(f" enter a number between 1 and {len(local)}", style=STYLE_HINT) + continue + try: + address = app_ctx.resolve_address(hotkey_field, raw) + except typer.Exit: + continue # the resolver already printed its own error + kwargs[hotkey_field] = address + return [flag, address] + + +def with_free_balance(spec: PromptSpec) -> PromptSpec: + """Wrap an amount PromptSpec so the prompt leads with the free balance. + + The amount these ops spend comes straight out of the coldkey's free + balance, so it is read (from the proxied account with --proxy-for, + otherwise the signing wallet) and shown before asking. Parsing and the + skip-the-prompts hint stay exactly as the plain spec would have them. + """ + + def _flow(console: Console, app_ctx: AppContext, kwargs: dict) -> list[str]: + owner, owner_label = _stake_owner(app_ctx, kwargs) + with console.status("[dim]reading balance…[/dim]"): + balance = app_ctx.run(lambda c: c.read("balance", coldkey_ss58=owner)) + console.print(f" [dim]free balance of {owner_label}: {balance}[/dim]") + value, raw = ask(console, app_ctx, replace(spec, custom=None)) + kwargs[spec.field] = value + return [spec.flag, raw] + + return replace(spec, custom=_flow) def stake_source_spec(hotkey_field: str, netuid_field: Optional[str]) -> PromptSpec: diff --git a/sdk/python/bittensor/cli/tx.py b/sdk/python/bittensor/cli/tx.py index 55f3cb19b7..0db292f49d 100644 --- a/sdk/python/bittensor/cli/tx.py +++ b/sdk/python/bittensor/cli/tx.py @@ -26,10 +26,10 @@ from ..intents.proxy import ProxyTypeChoice from ..settings import tx_docs_url from . import globals as g +from .call_names import resolve_intent_args from .context import AppContext, address_cli_name, ctx_of, ss58_param_help -from .prompt import PromptSpec, fill_missing, interactive, signer_specs -from .root_helpers import claim_root_source_spec -from .stake_picker import STAKE_SOURCE_FIELDS, stake_source_spec +from .intent_prompts import apply_intent_prompt_policy, validate_intent_prompt_policy +from .prompt import PromptSpec, fill_missing, signer_specs # Field annotation (as a string, under PEP 563) -> the Python type Typer should # parse the option as. List/complex fields are taken as strings and parsed in the @@ -241,31 +241,7 @@ def command(ctx: typer.Context, **kwargs: Any) -> None: if kwargs.get(netuid_field) is None: kwargs[netuid_field] = netuid missing = [spec for spec in prompt_specs if kwargs.get(spec.field) is None] - # Unstake-style ops pick their source hotkey from the coldkey's live - # stake positions instead of a bare text prompt (or, worse, a silent - # fallback to the wallet's own hotkey, which rarely holds the stake). - source = STAKE_SOURCE_FIELDS.get(intent_cls.op) - if ( - source is not None - and kwargs.get(source[0]) is None - and not app_ctx.assume_yes - and not app_ctx.uses_extension_signer() - and interactive(app_ctx) - ): - hotkey_field, netuid_field = source - missing = [spec for spec in missing if spec.field != hotkey_field] - missing.insert(0, stake_source_spec(hotkey_field, netuid_field)) - # claim_root_with_hotkey targets one validator; pick from accrued yield, - # not the wallet's own hotkey (which rarely holds the claimable position). - if ( - intent_cls.op == "claim_root_with_hotkey" - and kwargs.get("hotkey_ss58") is None - and not app_ctx.assume_yes - and not app_ctx.uses_extension_signer() - and interactive(app_ctx) - ): - missing = [spec for spec in missing if spec.field != "hotkey_ss58"] - missing.insert(0, claim_root_source_spec("hotkey_ss58")) + missing = apply_intent_prompt_policy(app_ctx, intent_cls.op, missing, kwargs) # The signing wallet is confirmed too (Enter accepts the configured # default); --yes and the extension signer keep the flag-only flow. if not app_ctx.assume_yes and not app_ctx.uses_extension_signer(): @@ -280,12 +256,7 @@ def command(ctx: typer.Context, **kwargs: Any) -> None: ) if missing: fill_missing(app_ctx, missing, kwargs) - if intent_cls.op == "claim_root_with_hotkey" and kwargs.get("hotkey_ss58") is None: - app_ctx.output.error( - "missing required option: `--hotkey`", - help="pass the validator hotkey to claim from, or run on a terminal to pick one", - ) - raise typer.Exit(2) + validate_intent_prompt_policy(app_ctx, intent_cls.op, kwargs) # `self` is a sentinel (bypass the configured proxy_for default, see # AppContext.submit), so it must reach submit unresolved. raw_proxy_for = kwargs.pop("proxy_for", None) @@ -318,6 +289,10 @@ def command(ctx: typer.Context, **kwargs: Any) -> None: for f in specs if kwargs.get(f.name) is not None } + # Flag-level resolution above only covers top-level *_ss58 options; + # this pass reaches names inside JSON-shaped fields too (signatory + # lists, a multisig inner --call, batch children). + args = resolve_intent_args(app_ctx, args) app_ctx.submit( intent_cls.from_args(args), proxy_for=proxy_for, force_proxy_type=force_proxy_type ) diff --git a/sdk/python/bittensor/executor.py b/sdk/python/bittensor/executor.py index 5a7dab1e53..a72bafed51 100644 --- a/sdk/python/bittensor/executor.py +++ b/sdk/python/bittensor/executor.py @@ -523,6 +523,8 @@ async def plan( violations=violations, call=call, extras=extras, + spend=intent.spend(), + args={k: v for k, v in intent.to_dict().items() if k != "op"}, ) async def execute( diff --git a/sdk/python/bittensor/intents/governance.py b/sdk/python/bittensor/intents/governance.py index e7e944591a..fb7b9efb08 100644 --- a/sdk/python/bittensor/intents/governance.py +++ b/sdk/python/bittensor/intents/governance.py @@ -9,6 +9,7 @@ from ._money import Money, Spend, tao_amount from .base import Intent from .registry import register +from .staking import DEFAULT_RATE_TOLERANCE, _alpha_price_rao, _check_rate_tolerance @register @@ -63,25 +64,35 @@ class StakeBurn(Intent): so this is not an investment call; use a regular add-stake intent to acquire a position. Fails on the root subnet (``CannotBurnOrRecycleOnRootSubnet``). The chain accepts an optional - limit (omitted = market order), but this intent always requires - ``limit_price`` and executes all-or-nothing: the swap fails instead of - partially filling at a worse rate. Counts against a configured spend - cap. + limit (omitted = market order), but this intent always submits one and + executes all-or-nothing: the swap fails instead of partially filling at + a worse rate. When ``limit_price`` is omitted, the limit is derived from + the current pool price plus ``rate_tolerance`` (5% by default). Counts + against a configured spend cap. """ op = "stake_burn" signer = "coldkey" wraps = (("SubtensorModule", "add_stake_burn"),) + mev_shield_default = True netuid: int = field(metadata={"help": "Subnet whose alpha is bought and burned."}) amount_tao: Money = field( metadata={"help": "Spent from the coldkey to buy alpha that is then burned."} ) - limit_price: int = field( + limit_price: Optional[int] = field( + default=None, metadata={ "help": "Worst acceptable price in rao per alpha; the call fails rather than " - "filling beyond it." - } + "filling beyond it. Defaults to the current pool price plus `rate_tolerance`." + }, + ) + rate_tolerance: float = field( + default=DEFAULT_RATE_TOLERANCE, + metadata={ + "help": "Maximum price move accepted when `limit_price` is omitted, as a " + "fraction (0.05 = 5%). Ignored when `limit_price` is given." + }, ) hotkey_ss58: Optional[str] = field( default=None, @@ -90,15 +101,21 @@ class StakeBurn(Intent): def __post_init__(self): self.amount_tao = tao_amount(self.amount_tao) + _check_rate_tolerance(self.rate_tolerance) async def build(self, substrate, wallet: Any): hotkey = self.hotkey_address(wallet, self.hotkey_ss58) + if self.limit_price is not None: + limit = self.limit_price + else: + price = await _alpha_price_rao(substrate, self.netuid) + limit = int(price * (1 + self.rate_tolerance)) return await substrate.compose( calls.SubtensorModule.add_stake_burn( hotkey=hotkey, netuid=self.netuid, amount=self.amount_tao.rao, - limit=self.limit_price, + limit=limit, ) ) diff --git a/sdk/python/bittensor/intents/multisig.py b/sdk/python/bittensor/intents/multisig.py index 012d5ce269..904e7208a5 100644 --- a/sdk/python/bittensor/intents/multisig.py +++ b/sdk/python/bittensor/intents/multisig.py @@ -22,6 +22,7 @@ from typing import Any, Optional from .._generated import calls +from ..multisig import check_multisig_funds, multisig_opening_shortfall from ..signing import public_view from ..sp_core import ss58_decode from .base import BuiltCall, Intent @@ -180,7 +181,8 @@ class MultisigExecute(Intent): async def build(self, substrate, wallet: Any): _validate_multisig(self.threshold, self.other_signatories, self.coldkey_address(wallet)) inner = await _compose_inner(substrate, wallet, self.call) - max_weight = await substrate.estimate_weight(inner, public_view(wallet, "coldkey")) + view = public_view(wallet, "coldkey") + max_weight = await substrate.estimate_weight(inner, view) composed = await substrate.compose( calls.Multisig.as_multi( threshold=self.threshold, @@ -190,8 +192,28 @@ async def build(self, substrate, wallet: Any): max_weight=max_weight, ) ) + # Opening (no timepoint) reserves the deposit from the signer; fail + # here, before anything signs, instead of on-chain with a bare + # "cannot cover the transaction fee". + await check_multisig_funds( + substrate, + signer_ss58=view.ss58_address, + threshold=self.threshold, + opening=self.timepoint is None, + outer_call=composed, + fee_keypair=view, + signer_label=getattr(wallet, "name", None), + ) return BuiltCall(composed, _inner_call_extras(inner)) + async def warnings(self, substrate, signer_address: str) -> list[str]: + if self.timepoint is not None: + return [] + warning = await multisig_opening_shortfall( + substrate, signer_ss58=signer_address, threshold=self.threshold + ) + return [warning] if warning else [] + def summary(self) -> str: return ( f"multisig {self.threshold}-of-{len(self.other_signatories) + 1} " @@ -228,7 +250,8 @@ class MultisigApprove(Intent): async def build(self, substrate, wallet: Any): _validate_multisig(self.threshold, self.other_signatories, self.coldkey_address(wallet)) inner = await _compose_inner(substrate, wallet, self.call) - max_weight = await substrate.estimate_weight(inner, public_view(wallet, "coldkey")) + view = public_view(wallet, "coldkey") + max_weight = await substrate.estimate_weight(inner, view) if self.timepoint is None: # Opening approval: as_multi with the call embedded. With one # approval the threshold (>= 2) cannot be met, so nothing executes; @@ -254,8 +277,27 @@ async def build(self, substrate, wallet: Any): max_weight=max_weight, ) ) + # Same funding preflight as multisig_execute: the opening approval + # (no timepoint) reserves the deposit, later ones only pay the fee. + await check_multisig_funds( + substrate, + signer_ss58=view.ss58_address, + threshold=self.threshold, + opening=self.timepoint is None, + outer_call=composed, + fee_keypair=view, + signer_label=getattr(wallet, "name", None), + ) return BuiltCall(composed, _inner_call_extras(inner)) + async def warnings(self, substrate, signer_address: str) -> list[str]: + if self.timepoint is not None: + return [] + warning = await multisig_opening_shortfall( + substrate, signer_ss58=signer_address, threshold=self.threshold + ) + return [warning] if warning else [] + def summary(self) -> str: return ( f"multisig {self.threshold}-of-{len(self.other_signatories) + 1} " diff --git a/sdk/python/bittensor/intents/plan.py b/sdk/python/bittensor/intents/plan.py index a1866ba38e..b50ed86583 100644 --- a/sdk/python/bittensor/intents/plan.py +++ b/sdk/python/bittensor/intents/plan.py @@ -13,7 +13,7 @@ from ..balance import Balance from ..settings import tx_docs_url -from ._money import UNBOUNDED, Money, tao_amount +from ._money import UNBOUNDED, Money, Spend, tao_amount from .base import Intent @@ -86,7 +86,15 @@ def check(self, intent: Intent, fee: Optional[Balance]) -> list[str]: @dataclass class Plan: - """A previewed, not-yet-submitted intent.""" + """A previewed, not-yet-submitted intent. + + ``to_dict`` is the machine-readable pre-approval record: alongside the + fee, effects, warnings, and policy verdict it carries the exact spend + (``spend_tao``, or ``spend_unbounded`` when the amount cannot be bounded + before execution — full-balance sweeps and ownership transfers) and the + intent's exact parsed arguments, so an agent can verify precisely what + would run before anyone signs. + """ op: str summary: str @@ -98,6 +106,10 @@ class Plan: violations: list[str] = field(default_factory=list) call: Any = field(default=None, repr=False) # built call; not serialized extras: dict[str, Any] = field(default_factory=dict) # build-time data for the result + # TAO leaving the signer: a Balance when bounded, UNBOUNDED, or None. + spend: Spend = None + # The intent's own parameters, JSON-native (money as exact decimal strings). + args: Optional[dict[str, Any]] = None @property def ok(self) -> bool: @@ -110,7 +122,10 @@ def to_dict(self) -> dict[str, Any]: "summary": self.summary, "signer": self.signer, "signer_address": self.signer_address, + "args": self.args, "fee_tao": self.fee.tao if self.fee is not None else None, + "spend_tao": self.spend.tao if isinstance(self.spend, Balance) else None, + "spend_unbounded": self.spend is UNBOUNDED, "effects": self.effects, "warnings": self.warnings, "violations": self.violations, diff --git a/sdk/python/bittensor/intents/staking.py b/sdk/python/bittensor/intents/staking.py index 0379a351b3..d46b5af15e 100644 --- a/sdk/python/bittensor/intents/staking.py +++ b/sdk/python/bittensor/intents/staking.py @@ -6,7 +6,7 @@ from dataclasses import dataclass, field from typing import Any, ClassVar, Optional -from .._generated import calls +from .._generated import calls, constants from .._generated import storage as st from .._generated.runtime_apis import BetaBasketRuntimeApi, StakeInfoRuntimeApi, SwapRuntimeApi from ..balance import Balance @@ -74,6 +74,30 @@ async def _alpha_price_rao(substrate, netuid: int) -> int: return int(price) +# Reserved on top of the existential deposit when staking ``all``, so the +# transaction fee never makes the build unaffordable (typical fees are ~τ0.000125). +_ALL_STAKE_FEE_HEADROOM_RAO = 500_000 # τ0.0005 + + +async def _stakeable_rao(substrate, wallet: Any) -> int: + """The coldkey's free balance minus the existential deposit and a fee headroom. + + Resolves an ``amount = "all"`` for ``add_stake`` at build time; refuses to + build when the remainder is nothing. + """ + coldkey = public_view(wallet, "coldkey").ss58_address + account = await substrate.query(*st.System.Account, [coldkey]) + free = int(((account or {}).get("data") or {}).get("free") or 0) + deposit = int(await substrate.constant(*constants.Balances.ExistentialDeposit)) + rao = free - deposit - _ALL_STAKE_FEE_HEADROOM_RAO + if rao <= 0: + raise BittensorError( + f"nothing to stake: free balance {Balance.from_rao(free)} does not cover " + "the existential deposit plus the transaction fee" + ) + return rao + + async def _staked_rao(substrate, wallet: Any, hotkey_ss58: str, netuid: int) -> int: """Current stake (rao) the signing coldkey holds on ``hotkey_ss58`` at ``netuid``. @@ -154,23 +178,30 @@ class AddStake(Intent): tolerance or set ``slippage_protection`` to False to execute at any price, or use ``add_stake_limit`` to set an explicit limit price. The position's value then follows the pool price and the validator's performance, and can - be exited later with ``remove_stake``. Fails if the coldkey's free balance - cannot cover the amount plus the transaction fee, and with ``AmountTooLow`` - when the amount is below the chain minimum of 0.002 TAO plus the swap fee. - Dynamic subnets also reject a single swap larger than 1000x the pool's TAO - reserve (``InsufficientLiquidity``). + be exited later with ``remove_stake``. Pass ``all`` to stake the whole free + balance minus the existential deposit and a small fee headroom. Fails if + the coldkey's free balance cannot cover the amount plus the transaction + fee, and with ``AmountTooLow`` when the amount is below the chain minimum + of 0.002 TAO plus the swap fee. Dynamic subnets also reject a single swap + larger than 1000x the pool's TAO reserve (``InsufficientLiquidity``). """ op = "add_stake" signer = "coldkey" wraps = (("SubtensorModule", "add_stake"), ("SubtensorModule", "add_stake_limit")) mev_shield_default = True + all_amount_fields: ClassVar[tuple[str, ...]] = ("amount_tao",) hotkey_ss58: str = field( metadata={"help": "Hotkey the stake is added to (the validator you are backing)."} ) netuid: int = field(metadata={"help": NETUID_HELP}) - amount_tao: Money = field(metadata={"help": "How much of the coldkey's free balance to stake."}) + amount_tao: Money = field( + metadata={ + "help": "How much of the coldkey's free balance to stake, or `all` " + "(everything minus the existential deposit and fee headroom)." + } + ) slippage_protection: bool = field(default=True, metadata={"help": SLIPPAGE_PROTECTION_HELP}) rate_tolerance: float = field( default=DEFAULT_RATE_TOLERANCE, metadata={"help": RATE_TOLERANCE_HELP} @@ -178,18 +209,22 @@ class AddStake(Intent): def __post_init__(self): self.amount_tao = call_amount( - self.amount_tao, self.wraps[0], "amount_staked", netuid=self.netuid + self.amount_tao, self.wraps[0], "amount_staked", netuid=self.netuid, allow_all=True ) _check_rate_tolerance(self.rate_tolerance) async def build(self, substrate, wallet: Any): + if self.amount_tao == ALL: + rao = await _stakeable_rao(substrate, wallet) + else: + rao = self.amount_tao.rao if self.slippage_protection: price = await _alpha_price_rao(substrate, self.netuid) return await substrate.compose( calls.SubtensorModule.add_stake_limit( hotkey=self.hotkey_ss58, netuid=self.netuid, - amount_staked=self.amount_tao.rao, + amount_staked=rao, limit_price=int(price * (1 + self.rate_tolerance)), allow_partial=False, ) @@ -198,19 +233,30 @@ async def build(self, substrate, wallet: Any): calls.SubtensorModule.add_stake( hotkey=self.hotkey_ss58, netuid=self.netuid, - amount_staked=self.amount_tao.rao, + amount_staked=rao, ) ) def summary(self) -> str: + amount = "ALL free TAO" if self.amount_tao == ALL else str(self.amount_tao) note = ( f" (fails if price moves >{self.rate_tolerance:.2%})" if self.slippage_protection else " (no slippage protection)" ) - return f"stake {self.amount_tao} to {self.hotkey_ss58} on netuid {self.netuid}{note}" + return f"stake {amount} to {self.hotkey_ss58} on netuid {self.netuid}{note}" + + async def warnings(self, substrate, signer_address: str) -> list[str]: + if self.amount_tao == ALL: + return [ + "stakes the entire free balance (minus the existential deposit and fee headroom)" + ] + return [] def spend(self) -> Spend: + if self.amount_tao == ALL: + # Unbounded: a max_spend policy should block draining the whole account. + return UNBOUNDED return self.amount_tao diff --git a/sdk/python/bittensor/multisig.py b/sdk/python/bittensor/multisig.py index 6529266265..2159d846af 100644 --- a/sdk/python/bittensor/multisig.py +++ b/sdk/python/bittensor/multisig.py @@ -13,15 +13,180 @@ from __future__ import annotations +import asyncio from dataclasses import dataclass -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Optional -from .signing import WalletLike, resolve_signer +from ._generated import calls as generated_calls +from ._generated import constants as generated_constants +from ._generated import storage as generated_storage +from .result import ChainError, ErrorCode +from .signing import WalletLike, public_view, resolve_signer +from .sp_core import ss58_decode if TYPE_CHECKING: from .client import Client +class MultisigFundingError(ChainError): + """Raised before submission when the signer cannot pay for a multisig approval. + + The opening approval reserves ``DepositBase + threshold * DepositFactor`` + from the signer on top of the transaction fee (the deposit is returned when + the operation executes or is cancelled); failing client-side keeps the + exact funding requirement in the diagnostic instead of the chain's bare + "cannot cover the transaction fee". + """ + + def __init__(self, message: str, *, fund_help: str): + super().__init__(message, code=ErrorCode.INSUFFICIENT_BALANCE) + self.fund_help = fund_help + + @property + def remediation(self) -> str: + return self.fund_help + + +def _tao(rao: int) -> str: + """Exact τ display with trailing zeros trimmed (``τ0.2808``).""" + whole, frac = divmod(int(rao), 10**9) + text = f"{whole}.{frac:09d}".rstrip("0").rstrip(".") + return f"τ{text}" + + +def _tao_ceil(rao: int, decimals: int = 3) -> str: + """τ amount rounded UP to ``decimals`` places, for suggested funding.""" + step = 10 ** (9 - decimals) + units = -(-int(rao) // step) + whole, frac = divmod(units, 10**decimals) + text = f"{whole}.{frac:0{decimals}d}".rstrip("0").rstrip(".") + return f"τ{text}" + + +async def multisig_deposit_rao(substrate, threshold: int) -> int: + """The deposit the opener reserves: ``DepositBase + threshold * DepositFactor``.""" + base, factor = await asyncio.gather( + substrate.constant(*generated_constants.Multisig.DepositBase), + substrate.constant(*generated_constants.Multisig.DepositFactor), + ) + return int(base) + int(threshold) * int(factor) + + +async def _free_balance_rao(substrate, ss58: str) -> int: + account = await substrate.query(*generated_storage.System.Account, [ss58]) + if not account: + return 0 + return int(account["data"]["free"]) + + +def _signer_display(ss58: str, label: Optional[str]) -> str: + if label and label != ss58: + return f"{ss58} ({label})" + return ss58 + + +def _funding_error( + *, + signer_ss58: str, + signer_label: Optional[str], + free_rao: int, + fee_rao: int, + deposit_rao: int, +) -> MultisigFundingError: + display = _signer_display(signer_ss58, signer_label) + # Suggest the deposit plus twice the estimated fee so fee-estimate drift + # cannot leave the account short a second time. + amount = _tao_ceil(max(deposit_rao + 2 * fee_rao - free_rao, 0)) + # The message carries the bare ss58 (the CLI decorates known addresses + # with local names itself); the help line spells out ``ss58 (name)``. + if deposit_rao: + message = ( + "the signing account cannot cover the multisig deposit plus the " + f"transaction fee: {signer_ss58} holds {_tao(free_rao)} free, but " + f"opening this operation reserves a {_tao(deposit_rao)} deposit on " + f"top of a ~{_tao(fee_rao)} fee" + ) + fund_help = f"fund {display} with ≥ {amount} — the deposit is returned when the op executes" + else: + message = ( + "the signing account cannot cover the transaction fee: " + f"{signer_ss58} holds {_tao(free_rao)} free, but this approval " + f"costs a ~{_tao(fee_rao)} fee" + ) + fund_help = f"fund {display} with ≥ {amount}" + return MultisigFundingError(message, fund_help=fund_help) + + +async def check_multisig_funds( + substrate, + *, + signer_ss58: str, + threshold: int, + opening: bool, + outer_call: Any = None, + fee_keypair: Any = None, + signer_label: Optional[str] = None, +) -> None: + """Fail early when the signer cannot pay for a multisig approval. + + An opening approval reserves the multisig deposit from the signer on top + of the fee; later approvals only pay the fee. Best-effort: any failure + reading chain state skips the check (the chain stays the authority), so + this can never block an otherwise submittable call. + """ + try: + deposit = 0 + if opening and threshold >= 2: + deposit = await multisig_deposit_rao(substrate, threshold) + fee = 0 + if outer_call is not None and fee_keypair is not None: + fee = int((await substrate.estimate_fee(outer_call, fee_keypair)).rao) + if deposit == 0 and fee == 0: + return + free = await _free_balance_rao(substrate, signer_ss58) + except Exception: + return + if free >= deposit + fee: + return + raise _funding_error( + signer_ss58=signer_ss58, + signer_label=signer_label, + free_rao=free, + fee_rao=fee, + deposit_rao=deposit, + ) + + +# Covers the fee when only the deposit is known (finney fees are well under this). +_FEE_ALLOWANCE_RAO = 5_000_000 + + +async def multisig_opening_shortfall( + substrate, *, signer_ss58: str, threshold: int +) -> Optional[str]: + """Warning text when the signer cannot cover an opening deposit, or None. + + The cheap variant of :func:`check_multisig_funds` for pre-confirm warnings: + no call is available yet, so it compares the free balance against the + deposit alone (with a small fee allowance in the suggested amount). + """ + if threshold < 2: + return None + try: + deposit = await multisig_deposit_rao(substrate, threshold) + free = await _free_balance_rao(substrate, signer_ss58) + except Exception: + return None + if free >= deposit: + return None + amount = _tao_ceil(deposit + _FEE_ALLOWANCE_RAO - free) + return ( + f"the opening approval reserves a {_tao(deposit)} multisig deposit the " + f"signer cannot cover: fund {signer_ss58} with ≥ {amount} — the deposit " + "is returned when the op executes" + ) + + @dataclass class Multisig: """An M-of-N signer set and its derived account address. @@ -55,6 +220,7 @@ async def approve( call for the on-chain hashes to match. """ composed = await self._client.compose(call) + await self._preflight_funds(composed, wallet, signer) keypair = resolve_signer(wallet, signer) return await self._client._substrate.submit_multisig( composed, @@ -64,6 +230,50 @@ async def approve( wait_for_finalization=wait_for_finalization, ) + async def _preflight_funds(self, composed, wallet: WalletLike, signer: str) -> None: + """Refuse an approval whose signer cannot pay, before anything signs. + + Whether this approval *opens* the operation (and so reserves the + deposit) is read from pending state: no entry for this call hash means + the signer is the opener. The fee is estimated against the same + ``as_multi`` wrapper the transport will submit. Everything up to the + comparison is best-effort — a failure here must not block submission. + """ + substrate = self._client._substrate + try: + pub = public_view(wallet, signer) + call_hash = "0x" + bytes(composed.call_hash).hex() + pending = await substrate.query( + *generated_storage.Multisig.Multisigs, [self.address, call_hash] + ) + outer = None + if self.threshold >= 2: + others = sorted( + (s for s in self.signatories if s != pub.ss58_address), + key=lambda s: bytes(ss58_decode(s)), + ) + max_weight = await substrate.estimate_weight(composed, pub) + outer = await self._client.compose( + generated_calls.Multisig.as_multi( + threshold=self.threshold, + other_signatories=others, + maybe_timepoint=None, + call=composed, + max_weight=max_weight, + ) + ) + except Exception: + return + await check_multisig_funds( + substrate, + signer_ss58=pub.ss58_address, + threshold=self.threshold, + opening=not pending, + outer_call=outer, + fee_keypair=pub, + signer_label=getattr(wallet, "name", None), + ) + def __repr__(self) -> str: return ( f"Multisig(address={self.address!r}, " diff --git a/sdk/python/bittensor/wallet.py b/sdk/python/bittensor/wallet.py index a165270e8d..b145ad2cf6 100644 --- a/sdk/python/bittensor/wallet.py +++ b/sdk/python/bittensor/wallet.py @@ -222,6 +222,7 @@ def regenerate_coldkey( self, mnemonic: str | None = None, seed: str | bytes | None = None, + private_key: str | None = None, json: tuple[str, str] | None = None, use_password: bool = True, overwrite: bool = False, @@ -235,6 +236,10 @@ def regenerate_coldkey( if not suppress: print(f"Regenerating coldkey from mnemonic\nMnemonic: {mnemonic}") keypair = Keypair.create_from_mnemonic(mnemonic, crypto_type) + elif private_key is not None: + if not suppress: + print("Regenerating coldkey from private key") + keypair = Keypair.create_from_private_key(private_key, crypto_type) elif seed is not None: keypair = Keypair.create_from_seed(_seed_bytes(seed), crypto_type) elif json is not None: @@ -247,7 +252,7 @@ def regenerate_coldkey( print("Regenerating coldkey from encrypted JSON keystore") keypair = Keypair.create_from_encrypted_json(json_data, passphrase) else: - raise ValueError("either mnemonic, seed, or json must be provided") + raise ValueError("either mnemonic, seed, private_key, or json must be provided") if coldkey_password is not None: use_password = True @@ -265,6 +270,7 @@ def regenerate_hotkey( self, mnemonic: str | None = None, seed: str | bytes | None = None, + private_key: str | None = None, use_password: bool = False, overwrite: bool = False, suppress: bool = False, @@ -277,10 +283,14 @@ def regenerate_hotkey( if not suppress: print(f"Regenerating hotkey from mnemonic\nMnemonic: {mnemonic}") keypair = Keypair.create_from_mnemonic(mnemonic, crypto_type) + elif private_key is not None: + if not suppress: + print("Regenerating hotkey from private key") + keypair = Keypair.create_from_private_key(private_key, crypto_type) elif seed is not None: keypair = Keypair.create_from_seed(_seed_bytes(seed), crypto_type) else: - raise ValueError("either mnemonic or seed must be provided") + raise ValueError("either mnemonic, seed, or private_key must be provided") if hotkey_password is not None: use_password = True diff --git a/sdk/python/bittensor/wallets.py b/sdk/python/bittensor/wallets.py index be08a3d2c4..668c72274b 100644 --- a/sdk/python/bittensor/wallets.py +++ b/sdk/python/bittensor/wallets.py @@ -244,18 +244,20 @@ def regen_coldkey( path: str = DEFAULT_WALLET_PATH, *, seed: str | None = None, + private_key: str | None = None, json: tuple[str, str] | None = None, use_password: bool = True, overwrite: bool = False, crypto_type: int = DEFAULT_CRYPTO_TYPE, ) -> Wallet: - """Regenerate a coldkey from a mnemonic, 32-byte hex seed, or encrypted JSON.""" + """Regenerate a coldkey from a mnemonic, seed, private key, or encrypted JSON.""" wallet = Wallet(name=name, path=path) # suppress=True stops the wallet lib from echoing the mnemonic back to stdout; # the caller already supplied it, so reprinting only widens secret exposure. wallet.regenerate_coldkey( mnemonic=mnemonic, seed=seed, + private_key=private_key, json=json, use_password=use_password, overwrite=overwrite, @@ -272,14 +274,16 @@ def regen_hotkey( path: str = DEFAULT_WALLET_PATH, *, seed: str | None = None, + private_key: str | None = None, overwrite: bool = False, crypto_type: int = DEFAULT_CRYPTO_TYPE, ) -> Wallet: - """Regenerate a hotkey from a mnemonic or a 32-byte hex seed (exactly one).""" + """Regenerate a hotkey from a mnemonic, 32-byte hex seed, or 64-byte private key.""" wallet = Wallet(name=name, hotkey=hotkey, path=path) wallet.regenerate_hotkey( mnemonic=mnemonic, seed=seed, + private_key=private_key, use_password=False, overwrite=overwrite, suppress=True, diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index fa73ff8b6e..3b2af3f4e6 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "bittensor" -version = "11.0.2.dev0" +version = "11.1.0.dev0" description = "A lean Python SDK (import bittensor) and CLI (btcli) for the Bittensor chain." readme = "README.md" requires-python = ">=3.10,<3.15" @@ -18,7 +18,7 @@ dependencies = [ # Keys, keyfiles, timelock, ML-KEM crypto, and the SCALE codec/runtime # engine: the in-repo Rust core, built against the same crate revisions # as the runtime. - "bittensor-core>=0.1.2,<0.2.0", + "bittensor-core>=0.1.3,<0.2.0", # `btcli` terminal UI. The CLI is a first-class part of the package, so # its dependencies are unconditional. "typer>=0.12.0", diff --git a/sdk/python/tests/unit/test_cli.py b/sdk/python/tests/unit/test_cli.py index b11dcfaa9b..ea2384858d 100644 --- a/sdk/python/tests/unit/test_cli.py +++ b/sdk/python/tests/unit/test_cli.py @@ -14,9 +14,14 @@ import pytest from typer.testing import CliRunner +import bittensor.cli.commands.root as root_commands import bittensor.cli.context as cli_context -from bittensor import RpcConnectionError, RpcPolicyError, __version__, wallets +from bittensor import RpcConnectionError, RpcPolicyError, __version__, config, wallets +from bittensor.balance import Balance +from bittensor.cli.call_names import resolve_builder_params from bittensor.cli.main import app +from bittensor.cli.output import Output +from bittensor.cli.root_helpers import RootPosition, position_columns, position_rows from bittensor.client import Client from bittensor.intents import REGISTRY from tests.harness.fake_substrate import FakeSubstrate @@ -65,6 +70,29 @@ def invoke(*args: str): return runner.invoke(app, list(args)) +def seed_root_validator_summary(fake: FakeSubstrate) -> None: + fake.seed_runtime( + "BetaBasketRuntimeApi", + "get_validator_basket_summary", + { + "hotkey": BOB, + "nav_tao": 1_250_000_000, + "spot_nav_tao": 1_500_000_000, + "deposited_tao": 1_000_000_000, + "redeemed_tao": 0, + "weights": [(1, 65535)], + "holdings": [ + { + "netuid": 1, + "alpha": 2_000_000_000, + "spot_tao": 1_500_000_000, + "realizable_tao": 1_250_000_000, + } + ], + }, + ) + + class TestOffline: """Commands that never open a connection.""" @@ -219,6 +247,125 @@ def test_wallet_balance_by_address(self, fake: FakeSubstrate): assert payload["free_tao"] == pytest.approx(2.5) +class TestAddressResolution: + @staticmethod + def app_context(wallet_dir: str) -> cli_context.AppContext: + return cli_context.AppContext( + network="finney", + wallet_name=_WALLET_NAME, + hotkey_name="default", + wallet_path=wallet_dir, + assume_yes=True, + dry_run=False, + output=Output(json_mode=True), + ) + + def test_raw_call_uses_canonical_saved_multisig_resolution(self, fake, wallet_dir): + config.add_multisig({"name": "treasury", "threshold": 1, "signatories": [BOB]}) + app_ctx = self.app_context(wallet_dir) + expected = app_ctx.resolve_address_ref("new_coldkey", "treasury") + + params = resolve_builder_params( + app_ctx, + "SubtensorModule.schedule_swap_coldkey", + {"new_coldkey": "treasury"}, + ) + + assert params["new_coldkey"] == expected.address + assert expected.source == "saved multisig 'treasury'" + + def test_raw_call_does_not_guess_arbitrary_string_lists_are_accounts(self, fake, wallet_dir): + app_ctx = self.app_context(wallet_dir) + params = {"remark": [BOB, "ordinary memo text"]} + + assert resolve_builder_params(app_ctx, "System.remark", params) == params + + +class TestRoot: + @pytest.mark.parametrize("all_wallets", [False, True]) + def test_position_rows_match_columns(self, all_wallets): + position = RootPosition( + hotkey=BOB, + staked=Balance.from_tao(1), + accrued=Balance.from_tao("0.25"), + wallet=_WALLET_NAME if all_wallets else None, + ) + + rows = position_rows([position], all_wallets) + + assert all(len(row) == len(position_columns(all_wallets)) for row in rows) + + def test_list_single_coldkey_renders_human_table(self, fake: FakeSubstrate, monkeypatch): + async def root_positions(_client, _coldkey_ss58): + return [ + RootPosition( + hotkey=BOB, + staked=Balance.from_tao(1), + accrued=Balance.from_tao("0.25"), + ) + ] + + monkeypatch.setattr(root_commands, "fetch_root_positions", root_positions) + + result = invoke("root", "list", "--coldkey", BOB) + + assert result.exit_code == 0, result.exception + assert "root positions of" in result.output + assert "staked (τ)" in result.output + assert "τ1.250000000" in result.output + + def test_list_all_wallets_renders_wallet_column(self, fake: FakeSubstrate, monkeypatch): + async def all_root_positions(_client, _coldkeys): + return [ + RootPosition( + hotkey=BOB, + staked=Balance.from_tao(1), + accrued=Balance.from_tao("0.25"), + wallet=_WALLET_NAME, + coldkey=BOB, + ) + ] + + monkeypatch.setattr(root_commands, "list_coldkeys", lambda _path: [(_WALLET_NAME, BOB)]) + monkeypatch.setattr(root_commands, "fetch_all_root_positions", all_root_positions) + + result = invoke("root", "list", "--all") + + assert result.exit_code == 0, result.exception + assert "wallet" in result.output + assert _WALLET_NAME in result.output + assert "τ1.250000000" in result.output + + def test_show_explicit_hotkey_renders_human_detail(self, fake: FakeSubstrate, monkeypatch): + async def root_positions(_client, _coldkey_ss58): + return [] + + monkeypatch.setattr(root_commands, "fetch_root_positions", root_positions) + seed_root_validator_summary(fake) + + result = invoke("root", "show", "--hotkey", BOB, "--coldkey", BOB) + + assert result.exit_code == 0, result.exception + assert "weights of" in result.output + assert "fund holdings of" in result.output + assert "fund nav: τ1.250000000" in result.output + + def test_show_explicit_hotkey_json_emits_one_document(self, fake: FakeSubstrate, monkeypatch): + async def root_positions(_client, _coldkey_ss58): + return [] + + monkeypatch.setattr(root_commands, "fetch_root_positions", root_positions) + seed_root_validator_summary(fake) + + result = invoke("--json", "root", "show", "--hotkey", BOB, "--coldkey", BOB) + + assert result.exit_code == 0, result.exception + payload = json.loads(result.output) + assert payload["hotkey"] == BOB + assert payload["nav_tao"] == "τ1.250000000" + assert payload["weights"] == [{"netuid": 1, "weight": 65535, "share": 1.0}] + + class TestTransactions: def test_dry_run_renders_plan_without_submitting(self, fake: FakeSubstrate): result = invoke( diff --git a/sdk/python/tests/unit/test_cli_intent_prompts.py b/sdk/python/tests/unit/test_cli_intent_prompts.py new file mode 100644 index 0000000000..d8ede60f00 --- /dev/null +++ b/sdk/python/tests/unit/test_cli_intent_prompts.py @@ -0,0 +1,44 @@ +from __future__ import annotations + +from types import SimpleNamespace + +from bittensor.cli import intent_prompts +from bittensor.cli.prompt import PromptSpec + + +def _spec(field: str) -> PromptSpec: + return PromptSpec( + field=field, + flag=f"--{field.replace('_', '-')}", + help=None, + parse=lambda _ctx, value: value, + ) + + +def _context(): + return SimpleNamespace( + assume_yes=False, + uses_extension_signer=lambda: False, + output=SimpleNamespace(message=lambda _message: None), + ) + + +def test_add_stake_policy_places_target_before_decorated_amount(monkeypatch): + monkeypatch.setattr(intent_prompts, "interactive", lambda _ctx: True) + missing = [_spec("netuid"), _spec("hotkey_ss58"), _spec("amount_tao")] + + result = intent_prompts.apply_intent_prompt_policy(_context(), "add_stake", missing, {}) + + assert [spec.field for spec in result] == ["netuid", "hotkey_ss58", "amount_tao"] + assert result[1].custom is not None + assert result[2].custom is not None + + +def test_remove_stake_policy_moves_source_picker_first(monkeypatch): + monkeypatch.setattr(intent_prompts, "interactive", lambda _ctx: True) + missing = [_spec("netuid"), _spec("hotkey_ss58"), _spec("amount_alpha")] + + result = intent_prompts.apply_intent_prompt_policy(_context(), "remove_stake", missing, {}) + + assert [spec.field for spec in result] == ["hotkey_ss58", "netuid", "amount_alpha"] + assert result[0].custom is not None diff --git a/sdk/python/uv.lock b/sdk/python/uv.lock index 397f3667c3..7f3f5ff393 100644 --- a/sdk/python/uv.lock +++ b/sdk/python/uv.lock @@ -1,122 +1,123 @@ version = 1 +revision = 3 requires-python = ">=3.10, <3.15" [[package]] name = "annotated-doc" version = "0.0.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288 } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303 }, + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, ] [[package]] name = "annotated-types" version = "0.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] [[package]] name = "backports-asyncio-runner" version = "1.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8e/ff/70dca7d7cb1cbc0edb2c6cc0c38b65cba36cccc491eca64cabd5fe7f8670/backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162", size = 69893 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/ff/70dca7d7cb1cbc0edb2c6cc0c38b65cba36cccc491eca64cabd5fe7f8670/backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162", size = 69893, upload-time = "2025-07-02T02:27:15.685Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313 }, + { url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313, upload-time = "2025-07-02T02:27:14.263Z" }, ] [[package]] name = "bitarray" version = "3.8.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bb/9b/ca307b554eaa233d004cae07d5594f9d45affd1f8e118687059aa06fcc6b/bitarray-3.8.2.tar.gz", hash = "sha256:2675a0c17c0b2d12d0fbcf3b27eb833f96936a588da47ac445c0743c5aa69e6b", size = 153516 } +sdist = { url = "https://files.pythonhosted.org/packages/bb/9b/ca307b554eaa233d004cae07d5594f9d45affd1f8e118687059aa06fcc6b/bitarray-3.8.2.tar.gz", hash = "sha256:2675a0c17c0b2d12d0fbcf3b27eb833f96936a588da47ac445c0743c5aa69e6b", size = 153516, upload-time = "2026-06-17T17:22:23.921Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/48/f7/f3dc5577d53e311c7a7650472e847a29361fbd79a5c8c7a34b4be4eae974/bitarray-3.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f5930731b736e3f9654029f3e9082bfb1721d81f04bff9e6eab8eb38b4dfed", size = 150023 }, - { url = "https://files.pythonhosted.org/packages/74/56/b847e84d0310c19b8a127eda77be2e3429d548d485a6a81ef1ee32a6d91e/bitarray-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e835f33ab5aa297a9ce21b7813222c22ff1618b8f8c5e6f921e54b4ae8b8f43", size = 146927 }, - { url = "https://files.pythonhosted.org/packages/90/71/1aa47086b72034b25b55388335765a6640bc232a5e0aad5dabb4ea677d68/bitarray-3.8.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1061cb959efbe3b747c38d550d8d7f0794090a757dd552eae8cf614a5f8d76b6", size = 325474 }, - { url = "https://files.pythonhosted.org/packages/9f/f5/1092c5a3e34a09bbe11149bc9e19c6c23b82c7383ac61d2aef8bb205eda6/bitarray-3.8.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82a6574e98bdddfb7fdac4d41c1176e90e1fcaaed97fda39836a9e0d8b247ec3", size = 353442 }, - { url = "https://files.pythonhosted.org/packages/f7/c0/99755ded6bcde8e577374722f1d14bf43d98a9ceb8bae07e5ad445ff10b8/bitarray-3.8.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9a34663e05bf79ccb92e931e720fbd281e84007ed996d38754aadfbc33e71c24", size = 363901 }, - { url = "https://files.pythonhosted.org/packages/51/b3/312207693283b29d59c9a28ee662e6daa1d762a475dce21811929fb3bd77/bitarray-3.8.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:819f93a1aa7e711ccbb083647a8995bbb0da8f741c8b691576ff1bf5b5018c51", size = 331861 }, - { url = "https://files.pythonhosted.org/packages/cc/70/83e0698a8d32322e0ed5c35eda339f85e5a828d8e30e24cbafcaa36e74d9/bitarray-3.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:07c20505dc8935b55d6de0bb1cc7e0e35de792d5f118d60b177dee53771a474f", size = 323169 }, - { url = "https://files.pythonhosted.org/packages/28/55/c77597c5d5fab09a24b67b7e626d9de505d91fa03dac728d153663ab8149/bitarray-3.8.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:874c6806c2c7b861da0f0e9eead173bb3b9b7a62fcfadc01be51c32d50d7f71c", size = 351476 }, - { url = "https://files.pythonhosted.org/packages/b6/17/fff630b5584985f9f203f89eb16f50a860e5198265eb94e6f4c3af482c96/bitarray-3.8.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4403e5b4da88ec195afe3eab5969b34358157d196e1c63e93328e64e632abbed", size = 347982 }, - { url = "https://files.pythonhosted.org/packages/39/60/7e0c8c84d25251a93a0f56419738a914efe3134923e17f8ead6dbbb336a0/bitarray-3.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8a23e06e87cfa2ba361040eae87479ac197502ba10533c0f2de03d3d93cce91b", size = 328606 }, - { url = "https://files.pythonhosted.org/packages/c6/15/77d9d43e478f2bf9fc84ce2414b845a97369ebfb46d1a3c3e8da72cb4e5a/bitarray-3.8.2-cp310-cp310-win32.whl", hash = "sha256:e65b91b68aa072732d144fa11d86518324b8b27af7e2474bd7a50c88648dc5d4", size = 143238 }, - { url = "https://files.pythonhosted.org/packages/18/8f/17808e4980e88ec314fb40404308d49b648e41092c19e2fb71d2a9e0d058/bitarray-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:156c6d964111e1c0029c5bb41148a73aa870ca10c03a03279b5597fa68ac6761", size = 149868 }, - { url = "https://files.pythonhosted.org/packages/42/75/285f2c9315a6ca19fec9281737f2fb31a3401584ccf82e4d689f6142d266/bitarray-3.8.2-cp310-cp310-win_arm64.whl", hash = "sha256:1b7c6fd8755dda32bc83b171e0a0f625fea545bb6f8a70a7481244dc847b1c9e", size = 147722 }, - { url = "https://files.pythonhosted.org/packages/48/85/c19b7928447d4259418b915857200f7a471920e88241d5a27083a4ceedb2/bitarray-3.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7540de3e7609693b208020cb3cb28cb16395eb915dff742bdcdd9909d475bf3d", size = 150025 }, - { url = "https://files.pythonhosted.org/packages/27/a2/3faeec7783733b596f63b887eb29fd6abfda6937195a269dc1fc6236ac76/bitarray-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c073cd936904e520990339745a2d561ceabc9daa1cefcaf9592196a3355eb1cd", size = 146925 }, - { url = "https://files.pythonhosted.org/packages/68/75/b8e778aaa9d184b1361560a96974d99400c43e70f389a17382951969165e/bitarray-3.8.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4c1c97c5712ad45c6c1427b70bb6524f40532e4a544ca2b7e0375ca61c09244", size = 333297 }, - { url = "https://files.pythonhosted.org/packages/74/18/4c52fa2ec6dac3db01fd51ab2fdccba0a3e86b9b3eb9c76ab6e6e9190008/bitarray-3.8.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7627bfa750a609f5df05c1da337984b8f3821927591aaf861ba70f38bc5f6da1", size = 361658 }, - { url = "https://files.pythonhosted.org/packages/8e/ff/3e34aef8ad52ef63eb426dada698de6240cf45a99a6949b4678954e96814/bitarray-3.8.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ff06e0511682f117d0c24828f0ef1b4f2c3617d38984c7b3ce78d107bee016ab", size = 372260 }, - { url = "https://files.pythonhosted.org/packages/f2/26/6a7e0f9254753b7c81ef3a7465533e7de0aa7da882aec6c19e993329d4d7/bitarray-3.8.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bcaeccab426b0a6e26c10bd8d8c21c15f81757320ad158a8c9e3e953ab81d223", size = 339446 }, - { url = "https://files.pythonhosted.org/packages/37/2f/e866171e3b4ab8f12378d8fbd0d24944a12af623c130126b1e8d145deecc/bitarray-3.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:385045390630f5f433c89caeed9bca9f5b40e3986ae2d7e829e93098c1a96b94", size = 331180 }, - { url = "https://files.pythonhosted.org/packages/be/ee/9371212756ab3e9c0f3247709ec3b341015ca8fc7d9de4a3a2f30c2b4439/bitarray-3.8.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:30541722bfa0f8213d8e621772bef538204fe9eeb4357f4261d404688c2281a5", size = 359108 }, - { url = "https://files.pythonhosted.org/packages/75/4c/97d2ced53249890cbb6f16569da2fd4c73f767faf70bbbc03bd7329caa02/bitarray-3.8.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3daf8f1e040d48bf7ee664bd5c9df9d029c55780c671221d753f6f4fc769f10a", size = 356253 }, - { url = "https://files.pythonhosted.org/packages/a6/cc/68d2d511182c5cced2734086ca6b5b7fc778ce1babcfbe5e43d33fffde48/bitarray-3.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c223cf53e4a458b05b9f78723d88d5a1221fa11fb00cd1a696ccd483dcae3f8c", size = 336632 }, - { url = "https://files.pythonhosted.org/packages/b6/b4/739981ea2ea25e8199c3f58e3ac6b52749d26f4999db5bf673dadabef83f/bitarray-3.8.2-cp311-cp311-win32.whl", hash = "sha256:d9367a5eb2a3dda6958a129ca939ce7dd1555a3b13967eb2e7c9dc8df2cdffa0", size = 143420 }, - { url = "https://files.pythonhosted.org/packages/52/f1/841be2f5c3d1c79ab319eaf52871afb6616f8c7e6ef916517ef13b7e4c47/bitarray-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:2d0af077831aff8f44d8befe6459544bea1cd8fbce6b5b2a30ae1cb086a50620", size = 150060 }, - { url = "https://files.pythonhosted.org/packages/82/de/5d275dcb5abc23ccf3139b478e304efc41d7bd7dc78901bfcc5ef3f251ff/bitarray-3.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:a78778a0899c682537ac612b1a03ecd4ad30063c118825d0138d0f7518270e54", size = 148006 }, - { url = "https://files.pythonhosted.org/packages/52/20/53916ba8d01bc92e01d89c03cd7745107df48923de091b5f957578ff38ff/bitarray-3.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d5dcca2b64bbfce46dc43d77a2973d0b949e2260d74e8bd4e9a766de3afd0e70", size = 150156 }, - { url = "https://files.pythonhosted.org/packages/18/a8/bfa7c8f4141b3119decc54ff6656b8e2f6d4303dc71577021f2d4b42cf42/bitarray-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c78dfbb8883133caeb11aa4ec375165ff1b456a28898cbe45536173369accb24", size = 146884 }, - { url = "https://files.pythonhosted.org/packages/f5/60/fb0e9118dce7e1858fc4f608d0c13460207b227fc13819a23c6f3c70ec78/bitarray-3.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c32189234e4206c3832f947ebdf1735926dea0dbe0e966effd62771884dedf63", size = 336496 }, - { url = "https://files.pythonhosted.org/packages/be/b5/8d50bb4d55113535919812adb66dcdb590a95a032d5975254d951146c2b4/bitarray-3.8.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:26490091d3ad8c039829b33ab1bc776941ce359ecdcf8beef3c1efc330fcf1a5", size = 364673 }, - { url = "https://files.pythonhosted.org/packages/f2/c2/90ca21488fb0ac791a00b98c49c3dbab7ca1aca59e8745dabe073133370f/bitarray-3.8.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8ad858bd35dbb554de248c277ba9052f31d8e153c133195ef40c198303725dc8", size = 375966 }, - { url = "https://files.pythonhosted.org/packages/3b/39/f414699060068ef15b886353e6ae6d2f476715e5c7db205b47710e5e7b4c/bitarray-3.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:58aeaf943929716b411a4ff24422c2b8bbf2c2d8ef3e23bbf08dc7d47c49e2ae", size = 343994 }, - { url = "https://files.pythonhosted.org/packages/32/84/70a8ae25ba927f0b7656041c7cceea011296cbf6cc3770788bc331a5be88/bitarray-3.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b016d736e2b4aa8962962724b69893adce076622374cf4a275503049f5c7207", size = 334129 }, - { url = "https://files.pythonhosted.org/packages/4e/20/3ec71a1e9a8cab12e7306cbfcf0f6e6ae7726f11ca4a7aa2bd047d8d105e/bitarray-3.8.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6871b2b1680580e54fbf0196b3ab7b40a417b4d1fdb3ebda0debf3948e9b8604", size = 361708 }, - { url = "https://files.pythonhosted.org/packages/90/fc/6cae06eac8a25e5715f5607de6bae4bc3ec3b0634f790d5e22debab1802d/bitarray-3.8.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a4c6bb948d011bf18642e09a0a4d1dd067f0722db09d2d4b5d6cce292d71b448", size = 359888 }, - { url = "https://files.pythonhosted.org/packages/c0/cc/078932ee7b41862571e8b3cfb7dc4e03af5c4843b8246a5a663af8678773/bitarray-3.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:78622f067a89360e8acf146be7878f62deafe687db40feb16dabfc808a20717c", size = 340969 }, - { url = "https://files.pythonhosted.org/packages/f6/19/719edf77615864263a12351287832979b02a6277b4058ec6b53669ecbf7e/bitarray-3.8.2-cp312-cp312-win32.whl", hash = "sha256:75999de62a7c4686b901458d441bc3c6c03dade68d1dfbe808439e748d086ea3", size = 143759 }, - { url = "https://files.pythonhosted.org/packages/e9/af/6806f09441de299ccd42b361c2e25138425457331c0e59aef23aba0e901e/bitarray-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:3e44247fcf5dffa86031d5412b20278a953e4dcef4033012c93ebd9985d48fec", size = 150393 }, - { url = "https://files.pythonhosted.org/packages/99/e0/b9c738cfc16a59fcb4b17dd4f699d235257d2d3074e403892d4cd37ccc53/bitarray-3.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:f823fa67f074c0ede82014fd5c2020f301b88f351635f5ba7b802f53b5e0eade", size = 148168 }, - { url = "https://files.pythonhosted.org/packages/48/99/01fb3b90cbf8a930d2326945df2b28a5f046380c0f966ea78cada00dae45/bitarray-3.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:71d7350c801eea43afb0a8679fd7475b0fd9868fd15352f0d3069f335b44af06", size = 150167 }, - { url = "https://files.pythonhosted.org/packages/e7/ce/b26a94753fcfd9e7652805a539df60a83085997319be81ef6d59192ad37c/bitarray-3.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa3be101ed71c4e4989899da744a926d1f55f5d5f7f93242c32f727f7c11350b", size = 146882 }, - { url = "https://files.pythonhosted.org/packages/a9/8e/0bdf36618f4f585d5c35cb033f6a5611337d873d8718feca41d27453cc54/bitarray-3.8.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f684eb138bae893a5d98c811d99ecd89fa4a1af4700b0e512b8e2b794c9cabd", size = 335677 }, - { url = "https://files.pythonhosted.org/packages/cc/99/5588cbe69640d7fa2386be315ddb0e1bde6de8e922c025dccee769cc6d9e/bitarray-3.8.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:94e7da622b723705caddd59ee681cee0355b444901cc6fb2bcdc24bafba85911", size = 363773 }, - { url = "https://files.pythonhosted.org/packages/80/4f/7d2946d88ae77306833bd5b91746d212404d5a86347341274b61d08c3f7e/bitarray-3.8.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3110786b00b28a756fd948c8d63e6ca3a74810b2d115582d85593d9d48035c49", size = 375005 }, - { url = "https://files.pythonhosted.org/packages/fd/be/9a645b2e1bb0da4779dd9cab5a075d7c5bb68a16d8c90f051d47393bbcfe/bitarray-3.8.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd40cf27e2b54b5e30d0ce1da4f59bc16dd7c8363a20786b6e9deeb0b8ebe8e0", size = 343273 }, - { url = "https://files.pythonhosted.org/packages/98/8d/73c658d200671c5e023225163be6aa545f675a676e960e5a4e19ac21274b/bitarray-3.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:24c6b97f27bd3868e28b201e1d777f5e168805862b7d9528099138bbb8c6a636", size = 333403 }, - { url = "https://files.pythonhosted.org/packages/94/bc/819abd376bd6a892ce27840a1d5a4378be228be1ab3bca41845203ee672b/bitarray-3.8.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:786dedb4b1ced22dfeaaa89902561616f7edfa91774702b1aac31df3a6073c88", size = 360846 }, - { url = "https://files.pythonhosted.org/packages/83/59/b8ea1e31928d06db1f2b12187631b51bb3c83186b18581754bc008cec0aa/bitarray-3.8.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:01bf9ff247117533c11963a81f3529bc12283c600dd195cf3b28a97b095f5d1c", size = 359168 }, - { url = "https://files.pythonhosted.org/packages/6e/31/ef3b2f58517f7dbba8119f2592c1ea556a687bc8d405dd93c07f9c28d514/bitarray-3.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cc7a76e77c158e793d7c1e0b6c2240374087ac690a8bcacc8f18c427e5d9e20c", size = 340091 }, - { url = "https://files.pythonhosted.org/packages/8f/83/bf92dcfec4eefd59fa4d8491504e100ae86e11b8cec353ae5532b25708e6/bitarray-3.8.2-cp313-cp313-win32.whl", hash = "sha256:db9add8dcc87154c0f011e0e1ce9b856e5948fbcf6faf44305aa140e525ec9a7", size = 143786 }, - { url = "https://files.pythonhosted.org/packages/1c/29/1f57913a96bffb27bed486a9ca592021dd8161f6c95fd632aad7d4f0bb95/bitarray-3.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:cf4926098970d2d1a14156c0fbddb47554124347db4acf3ba616064fb021cd1e", size = 150414 }, - { url = "https://files.pythonhosted.org/packages/17/9c/f36b91fcb93af54c9a28e3bd1fbf39ef7706fc623a526f3450113c0a0dae/bitarray-3.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:5c8281d0eb35e8685235e1d50f9b26156803dad398d0e7868ce9aae254c3777d", size = 148197 }, - { url = "https://files.pythonhosted.org/packages/c6/86/aa2f29699763f4867359289a946ff3597d45239470c20f6ccb8dba48e7af/bitarray-3.8.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cbe96e7384e36963a2cdf5bc4ac9d0a78ae0d87fc78c53159cd5ac08c661ff34", size = 150139 }, - { url = "https://files.pythonhosted.org/packages/56/1f/0d759c53a7129e4979c3c03b3f2372291c4c5a1cc851d9e749273b34ddf8/bitarray-3.8.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8b4fcecbbd0969988cc115bee74119c767636e48606fad318361eb9fe40a13c6", size = 146888 }, - { url = "https://files.pythonhosted.org/packages/49/2e/0611d057e6cb010ccaf55ec6630ef41d3e7546a285383dfa2a99f545e440/bitarray-3.8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48798fc274e8a0329ca75185a0dc1e0a93ff627ea8f30c339bdf0a2ef26b1723", size = 335581 }, - { url = "https://files.pythonhosted.org/packages/11/0d/201befb06fbb6275046ffe2d21cbe3b059e4f5c6b258da6e6b41f53dd9af/bitarray-3.8.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4205ae045129e58e7b7a9abe929ea0b9a3c63fad39d760e6e3b90062b6e5aa5", size = 363929 }, - { url = "https://files.pythonhosted.org/packages/b6/3c/2639aaa97eb81cabc453f78277493ea31ff49b3514e17eca56129d613279/bitarray-3.8.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:49c16cdedbd3c4d6bf64aca7b370ea02456e9be030201e80c282d8df6af36d19", size = 374562 }, - { url = "https://files.pythonhosted.org/packages/52/1d/f11ba5b55f6a0f0007985f435c0e32c7a3459775cdee308cfb5938628670/bitarray-3.8.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5cad241cd0ceb79a0e4f76e86b36660c22d36c32efb364badcf7609ed5a9e5c", size = 343166 }, - { url = "https://files.pythonhosted.org/packages/4b/b9/2f8f62e1cd42f60f20ca55ed3de57ff2295b85a70eff119501ae2f0e8c48/bitarray-3.8.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3b44650aba323cb1c2285c310ffa6b1adfd5293acecd7f84aaa91afa27c802c", size = 333564 }, - { url = "https://files.pythonhosted.org/packages/22/de/1525e32e7663980b82098ae0c6e032823782b9190cabed6a1f09e67c7831/bitarray-3.8.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5fc8fa50c6a89b1e75edcea4ae17787a0a9b424cdbaa03485e73a837262eca27", size = 361034 }, - { url = "https://files.pythonhosted.org/packages/df/55/7bfe6af3fa577f5132380209c3f3ec560149c0af4e540ce16d84f8b76599/bitarray-3.8.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5f246319a26221e36eaf3f6aed9cd98172f81e91740bbf5cdf31b4490ecfb87a", size = 358728 }, - { url = "https://files.pythonhosted.org/packages/9d/c8/85898711f7b4cf5b06c49d8e36a6702a303f1990cb21cbb39dbe186730a0/bitarray-3.8.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e76c01ae0f191c5572c12b1fda333243bfe4d58ad1d601048f9e4928d94db0c5", size = 339747 }, - { url = "https://files.pythonhosted.org/packages/5b/56/94cc5250be3d530c52d15e41bdbf5f891a492aeebb9e978914aa4559c00a/bitarray-3.8.2-cp314-cp314-win32.whl", hash = "sha256:a1df20419ccc23a0326ee0cb391d1c524ee3c338856e66528d73f4dcec0389d0", size = 142830 }, - { url = "https://files.pythonhosted.org/packages/b4/eb/b9ba05ae59d56a9e5cb8e812072d33be38076717db6579302e1ee85fd688/bitarray-3.8.2-cp314-cp314-win_amd64.whl", hash = "sha256:4bfbeba9156834455ab107936ebd461728f1ed35ded8f15aafde2c3dac9badf5", size = 148912 }, - { url = "https://files.pythonhosted.org/packages/b6/07/e279a5ba7cd114398f00d853026e6c72e198035b925c74866e3c1973daca/bitarray-3.8.2-cp314-cp314-win_arm64.whl", hash = "sha256:4149aeb7c8cad12f9ea13783550ab5508e6d553eeefead5e3da659ce6724c5a5", size = 147373 }, - { url = "https://files.pythonhosted.org/packages/94/a4/4014952965ef7edf80076f8004df31484bccecba97af7b3e9c99269a053d/bitarray-3.8.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f6f6cf5ec3be7e1bd32bfe1f4b24f7d1de28d72394d7f58789b9f9042d19f5f6", size = 151073 }, - { url = "https://files.pythonhosted.org/packages/ff/00/850095c3bc551797c97a4b54c7755fc46eb115ce288fcf6962d8e8c5b678/bitarray-3.8.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2b9790847024cf1de275c8b2495331fe0982d099e407be1c1413ed40ddf2b5d", size = 148009 }, - { url = "https://files.pythonhosted.org/packages/dd/4d/74f0440d95d00f086a80e6c429e3333ebb29cecf55a8d401ceb0c65a3b4b/bitarray-3.8.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c172161b8847f91e9f9ea9ae2e31fcfa784ec5d0cd413900c82574999e21ad05", size = 343487 }, - { url = "https://files.pythonhosted.org/packages/78/e9/ea9c182ff0edb671853bb7a54b790572dc0b73d4a3b13e358f42aa34dca0/bitarray-3.8.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5fcc57961bc78885091a45b9ced5a5924b3b1fdd439a0e1d4b7e3aedf0c31ae2", size = 372305 }, - { url = "https://files.pythonhosted.org/packages/d5/ff/307cacc432e2ec304b870676189852c3f34a803d15b26f73bb36c549166b/bitarray-3.8.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b5fdb5399f0f2c42abcca87f8167d7ad746cf6ca7decadb4f5ad432280cc3a2f", size = 382242 }, - { url = "https://files.pythonhosted.org/packages/b8/ae/757a10ce90e2090dd2dff8c5059a47439122a8d68f5fa9cf06ed07a1dc74/bitarray-3.8.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bb6195a2edafceee0e9ee12c13aad2162e9578d91a24e7c501c3bd4ab90511a", size = 348509 }, - { url = "https://files.pythonhosted.org/packages/ef/d3/a035bb2c459e1f7bc86974fd43057aa8bb76466dd6bd75787d8eb9c534ed/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ce3b3dd599d4eca214f9c7fb7ac2343ccab41d91f3da7aa3b75ddbbea49ec2d5", size = 340539 }, - { url = "https://files.pythonhosted.org/packages/bc/6d/e7af02d167c227d143d208cd1c54d8e4f024d8d0bb59a0f2c38c32d56ad0/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:11cd9766ce95199bef5010ff63f73c880d9c0b6ba9c4c233aeeebc11ab1dfbb3", size = 369505 }, - { url = "https://files.pythonhosted.org/packages/9d/1d/29d0538ac245941127a25735d33f7b6658be6612c35115bcac60ef7c3c1c/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:7a4bbbad17d3db92615497302b74cf77504f821eb9585b7948d92093017d5e70", size = 365262 }, - { url = "https://files.pythonhosted.org/packages/1c/c8/2feabadbbc365e000821c7af82906e71366b29719329ef5709d64707fd4c/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e715498f3dc9af954b9d0977470aa352cb3fe1c39e80c32f5ac4c0348e461f6d", size = 344014 }, - { url = "https://files.pythonhosted.org/packages/6c/88/dc465cbfe5c74b7da8c19b9dc2565d8a4391fad418c48e1559a0267fd00b/bitarray-3.8.2-cp314-cp314t-win32.whl", hash = "sha256:c85569fb99cf9d4aa964d2dbba3c095c7580b4368f63f51252e85b939fcd0a2c", size = 143775 }, - { url = "https://files.pythonhosted.org/packages/08/75/50f2ef697d8ce46ba0986830f2d1288bff883e7f4833590076956a073496/bitarray-3.8.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7de416b313fc8e8aa1e323b83d2ba86b7c84161f7ebbaf986bdab80f9d06a2fb", size = 149884 }, - { url = "https://files.pythonhosted.org/packages/df/0e/6aa2133fffbac3efcb468c7c12163eff7bbe55b86a0d6a1c687ef57e2654/bitarray-3.8.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7199451493d34a5c62cb7c9077fcfd238499af4e0d13a32d33760afe73054135", size = 148321 }, + { url = "https://files.pythonhosted.org/packages/48/f7/f3dc5577d53e311c7a7650472e847a29361fbd79a5c8c7a34b4be4eae974/bitarray-3.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f5930731b736e3f9654029f3e9082bfb1721d81f04bff9e6eab8eb38b4dfed", size = 150023, upload-time = "2026-06-17T17:19:57.898Z" }, + { url = "https://files.pythonhosted.org/packages/74/56/b847e84d0310c19b8a127eda77be2e3429d548d485a6a81ef1ee32a6d91e/bitarray-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e835f33ab5aa297a9ce21b7813222c22ff1618b8f8c5e6f921e54b4ae8b8f43", size = 146927, upload-time = "2026-06-17T17:19:59.585Z" }, + { url = "https://files.pythonhosted.org/packages/90/71/1aa47086b72034b25b55388335765a6640bc232a5e0aad5dabb4ea677d68/bitarray-3.8.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1061cb959efbe3b747c38d550d8d7f0794090a757dd552eae8cf614a5f8d76b6", size = 325474, upload-time = "2026-06-17T17:20:00.806Z" }, + { url = "https://files.pythonhosted.org/packages/9f/f5/1092c5a3e34a09bbe11149bc9e19c6c23b82c7383ac61d2aef8bb205eda6/bitarray-3.8.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82a6574e98bdddfb7fdac4d41c1176e90e1fcaaed97fda39836a9e0d8b247ec3", size = 353442, upload-time = "2026-06-17T17:20:02.082Z" }, + { url = "https://files.pythonhosted.org/packages/f7/c0/99755ded6bcde8e577374722f1d14bf43d98a9ceb8bae07e5ad445ff10b8/bitarray-3.8.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9a34663e05bf79ccb92e931e720fbd281e84007ed996d38754aadfbc33e71c24", size = 363901, upload-time = "2026-06-17T17:20:03.418Z" }, + { url = "https://files.pythonhosted.org/packages/51/b3/312207693283b29d59c9a28ee662e6daa1d762a475dce21811929fb3bd77/bitarray-3.8.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:819f93a1aa7e711ccbb083647a8995bbb0da8f741c8b691576ff1bf5b5018c51", size = 331861, upload-time = "2026-06-17T17:20:04.69Z" }, + { url = "https://files.pythonhosted.org/packages/cc/70/83e0698a8d32322e0ed5c35eda339f85e5a828d8e30e24cbafcaa36e74d9/bitarray-3.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:07c20505dc8935b55d6de0bb1cc7e0e35de792d5f118d60b177dee53771a474f", size = 323169, upload-time = "2026-06-17T17:20:05.986Z" }, + { url = "https://files.pythonhosted.org/packages/28/55/c77597c5d5fab09a24b67b7e626d9de505d91fa03dac728d153663ab8149/bitarray-3.8.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:874c6806c2c7b861da0f0e9eead173bb3b9b7a62fcfadc01be51c32d50d7f71c", size = 351476, upload-time = "2026-06-17T17:20:07.249Z" }, + { url = "https://files.pythonhosted.org/packages/b6/17/fff630b5584985f9f203f89eb16f50a860e5198265eb94e6f4c3af482c96/bitarray-3.8.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4403e5b4da88ec195afe3eab5969b34358157d196e1c63e93328e64e632abbed", size = 347982, upload-time = "2026-06-17T17:20:08.616Z" }, + { url = "https://files.pythonhosted.org/packages/39/60/7e0c8c84d25251a93a0f56419738a914efe3134923e17f8ead6dbbb336a0/bitarray-3.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8a23e06e87cfa2ba361040eae87479ac197502ba10533c0f2de03d3d93cce91b", size = 328606, upload-time = "2026-06-17T17:20:09.741Z" }, + { url = "https://files.pythonhosted.org/packages/c6/15/77d9d43e478f2bf9fc84ce2414b845a97369ebfb46d1a3c3e8da72cb4e5a/bitarray-3.8.2-cp310-cp310-win32.whl", hash = "sha256:e65b91b68aa072732d144fa11d86518324b8b27af7e2474bd7a50c88648dc5d4", size = 143238, upload-time = "2026-06-17T17:20:10.924Z" }, + { url = "https://files.pythonhosted.org/packages/18/8f/17808e4980e88ec314fb40404308d49b648e41092c19e2fb71d2a9e0d058/bitarray-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:156c6d964111e1c0029c5bb41148a73aa870ca10c03a03279b5597fa68ac6761", size = 149868, upload-time = "2026-06-17T17:20:11.981Z" }, + { url = "https://files.pythonhosted.org/packages/42/75/285f2c9315a6ca19fec9281737f2fb31a3401584ccf82e4d689f6142d266/bitarray-3.8.2-cp310-cp310-win_arm64.whl", hash = "sha256:1b7c6fd8755dda32bc83b171e0a0f625fea545bb6f8a70a7481244dc847b1c9e", size = 147722, upload-time = "2026-06-17T17:20:13.038Z" }, + { url = "https://files.pythonhosted.org/packages/48/85/c19b7928447d4259418b915857200f7a471920e88241d5a27083a4ceedb2/bitarray-3.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7540de3e7609693b208020cb3cb28cb16395eb915dff742bdcdd9909d475bf3d", size = 150025, upload-time = "2026-06-17T17:20:14.573Z" }, + { url = "https://files.pythonhosted.org/packages/27/a2/3faeec7783733b596f63b887eb29fd6abfda6937195a269dc1fc6236ac76/bitarray-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c073cd936904e520990339745a2d561ceabc9daa1cefcaf9592196a3355eb1cd", size = 146925, upload-time = "2026-06-17T17:20:15.747Z" }, + { url = "https://files.pythonhosted.org/packages/68/75/b8e778aaa9d184b1361560a96974d99400c43e70f389a17382951969165e/bitarray-3.8.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4c1c97c5712ad45c6c1427b70bb6524f40532e4a544ca2b7e0375ca61c09244", size = 333297, upload-time = "2026-06-17T17:20:16.851Z" }, + { url = "https://files.pythonhosted.org/packages/74/18/4c52fa2ec6dac3db01fd51ab2fdccba0a3e86b9b3eb9c76ab6e6e9190008/bitarray-3.8.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7627bfa750a609f5df05c1da337984b8f3821927591aaf861ba70f38bc5f6da1", size = 361658, upload-time = "2026-06-17T17:20:18.242Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ff/3e34aef8ad52ef63eb426dada698de6240cf45a99a6949b4678954e96814/bitarray-3.8.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ff06e0511682f117d0c24828f0ef1b4f2c3617d38984c7b3ce78d107bee016ab", size = 372260, upload-time = "2026-06-17T17:20:19.438Z" }, + { url = "https://files.pythonhosted.org/packages/f2/26/6a7e0f9254753b7c81ef3a7465533e7de0aa7da882aec6c19e993329d4d7/bitarray-3.8.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bcaeccab426b0a6e26c10bd8d8c21c15f81757320ad158a8c9e3e953ab81d223", size = 339446, upload-time = "2026-06-17T17:20:20.794Z" }, + { url = "https://files.pythonhosted.org/packages/37/2f/e866171e3b4ab8f12378d8fbd0d24944a12af623c130126b1e8d145deecc/bitarray-3.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:385045390630f5f433c89caeed9bca9f5b40e3986ae2d7e829e93098c1a96b94", size = 331180, upload-time = "2026-06-17T17:20:21.904Z" }, + { url = "https://files.pythonhosted.org/packages/be/ee/9371212756ab3e9c0f3247709ec3b341015ca8fc7d9de4a3a2f30c2b4439/bitarray-3.8.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:30541722bfa0f8213d8e621772bef538204fe9eeb4357f4261d404688c2281a5", size = 359108, upload-time = "2026-06-17T17:20:23.112Z" }, + { url = "https://files.pythonhosted.org/packages/75/4c/97d2ced53249890cbb6f16569da2fd4c73f767faf70bbbc03bd7329caa02/bitarray-3.8.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3daf8f1e040d48bf7ee664bd5c9df9d029c55780c671221d753f6f4fc769f10a", size = 356253, upload-time = "2026-06-17T17:20:24.447Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cc/68d2d511182c5cced2734086ca6b5b7fc778ce1babcfbe5e43d33fffde48/bitarray-3.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c223cf53e4a458b05b9f78723d88d5a1221fa11fb00cd1a696ccd483dcae3f8c", size = 336632, upload-time = "2026-06-17T17:20:25.786Z" }, + { url = "https://files.pythonhosted.org/packages/b6/b4/739981ea2ea25e8199c3f58e3ac6b52749d26f4999db5bf673dadabef83f/bitarray-3.8.2-cp311-cp311-win32.whl", hash = "sha256:d9367a5eb2a3dda6958a129ca939ce7dd1555a3b13967eb2e7c9dc8df2cdffa0", size = 143420, upload-time = "2026-06-17T17:20:26.906Z" }, + { url = "https://files.pythonhosted.org/packages/52/f1/841be2f5c3d1c79ab319eaf52871afb6616f8c7e6ef916517ef13b7e4c47/bitarray-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:2d0af077831aff8f44d8befe6459544bea1cd8fbce6b5b2a30ae1cb086a50620", size = 150060, upload-time = "2026-06-17T17:20:28.094Z" }, + { url = "https://files.pythonhosted.org/packages/82/de/5d275dcb5abc23ccf3139b478e304efc41d7bd7dc78901bfcc5ef3f251ff/bitarray-3.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:a78778a0899c682537ac612b1a03ecd4ad30063c118825d0138d0f7518270e54", size = 148006, upload-time = "2026-06-17T17:20:29.193Z" }, + { url = "https://files.pythonhosted.org/packages/52/20/53916ba8d01bc92e01d89c03cd7745107df48923de091b5f957578ff38ff/bitarray-3.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d5dcca2b64bbfce46dc43d77a2973d0b949e2260d74e8bd4e9a766de3afd0e70", size = 150156, upload-time = "2026-06-17T17:20:30.372Z" }, + { url = "https://files.pythonhosted.org/packages/18/a8/bfa7c8f4141b3119decc54ff6656b8e2f6d4303dc71577021f2d4b42cf42/bitarray-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c78dfbb8883133caeb11aa4ec375165ff1b456a28898cbe45536173369accb24", size = 146884, upload-time = "2026-06-17T17:20:31.615Z" }, + { url = "https://files.pythonhosted.org/packages/f5/60/fb0e9118dce7e1858fc4f608d0c13460207b227fc13819a23c6f3c70ec78/bitarray-3.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c32189234e4206c3832f947ebdf1735926dea0dbe0e966effd62771884dedf63", size = 336496, upload-time = "2026-06-17T17:20:32.944Z" }, + { url = "https://files.pythonhosted.org/packages/be/b5/8d50bb4d55113535919812adb66dcdb590a95a032d5975254d951146c2b4/bitarray-3.8.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:26490091d3ad8c039829b33ab1bc776941ce359ecdcf8beef3c1efc330fcf1a5", size = 364673, upload-time = "2026-06-17T17:20:34.394Z" }, + { url = "https://files.pythonhosted.org/packages/f2/c2/90ca21488fb0ac791a00b98c49c3dbab7ca1aca59e8745dabe073133370f/bitarray-3.8.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8ad858bd35dbb554de248c277ba9052f31d8e153c133195ef40c198303725dc8", size = 375966, upload-time = "2026-06-17T17:20:35.555Z" }, + { url = "https://files.pythonhosted.org/packages/3b/39/f414699060068ef15b886353e6ae6d2f476715e5c7db205b47710e5e7b4c/bitarray-3.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:58aeaf943929716b411a4ff24422c2b8bbf2c2d8ef3e23bbf08dc7d47c49e2ae", size = 343994, upload-time = "2026-06-17T17:20:37.24Z" }, + { url = "https://files.pythonhosted.org/packages/32/84/70a8ae25ba927f0b7656041c7cceea011296cbf6cc3770788bc331a5be88/bitarray-3.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b016d736e2b4aa8962962724b69893adce076622374cf4a275503049f5c7207", size = 334129, upload-time = "2026-06-17T17:20:38.476Z" }, + { url = "https://files.pythonhosted.org/packages/4e/20/3ec71a1e9a8cab12e7306cbfcf0f6e6ae7726f11ca4a7aa2bd047d8d105e/bitarray-3.8.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6871b2b1680580e54fbf0196b3ab7b40a417b4d1fdb3ebda0debf3948e9b8604", size = 361708, upload-time = "2026-06-17T17:20:40.302Z" }, + { url = "https://files.pythonhosted.org/packages/90/fc/6cae06eac8a25e5715f5607de6bae4bc3ec3b0634f790d5e22debab1802d/bitarray-3.8.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a4c6bb948d011bf18642e09a0a4d1dd067f0722db09d2d4b5d6cce292d71b448", size = 359888, upload-time = "2026-06-17T17:20:42.132Z" }, + { url = "https://files.pythonhosted.org/packages/c0/cc/078932ee7b41862571e8b3cfb7dc4e03af5c4843b8246a5a663af8678773/bitarray-3.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:78622f067a89360e8acf146be7878f62deafe687db40feb16dabfc808a20717c", size = 340969, upload-time = "2026-06-17T17:20:43.326Z" }, + { url = "https://files.pythonhosted.org/packages/f6/19/719edf77615864263a12351287832979b02a6277b4058ec6b53669ecbf7e/bitarray-3.8.2-cp312-cp312-win32.whl", hash = "sha256:75999de62a7c4686b901458d441bc3c6c03dade68d1dfbe808439e748d086ea3", size = 143759, upload-time = "2026-06-17T17:20:44.753Z" }, + { url = "https://files.pythonhosted.org/packages/e9/af/6806f09441de299ccd42b361c2e25138425457331c0e59aef23aba0e901e/bitarray-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:3e44247fcf5dffa86031d5412b20278a953e4dcef4033012c93ebd9985d48fec", size = 150393, upload-time = "2026-06-17T17:20:45.983Z" }, + { url = "https://files.pythonhosted.org/packages/99/e0/b9c738cfc16a59fcb4b17dd4f699d235257d2d3074e403892d4cd37ccc53/bitarray-3.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:f823fa67f074c0ede82014fd5c2020f301b88f351635f5ba7b802f53b5e0eade", size = 148168, upload-time = "2026-06-17T17:20:47.169Z" }, + { url = "https://files.pythonhosted.org/packages/48/99/01fb3b90cbf8a930d2326945df2b28a5f046380c0f966ea78cada00dae45/bitarray-3.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:71d7350c801eea43afb0a8679fd7475b0fd9868fd15352f0d3069f335b44af06", size = 150167, upload-time = "2026-06-17T17:20:48.408Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ce/b26a94753fcfd9e7652805a539df60a83085997319be81ef6d59192ad37c/bitarray-3.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa3be101ed71c4e4989899da744a926d1f55f5d5f7f93242c32f727f7c11350b", size = 146882, upload-time = "2026-06-17T17:20:49.58Z" }, + { url = "https://files.pythonhosted.org/packages/a9/8e/0bdf36618f4f585d5c35cb033f6a5611337d873d8718feca41d27453cc54/bitarray-3.8.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f684eb138bae893a5d98c811d99ecd89fa4a1af4700b0e512b8e2b794c9cabd", size = 335677, upload-time = "2026-06-17T17:20:50.856Z" }, + { url = "https://files.pythonhosted.org/packages/cc/99/5588cbe69640d7fa2386be315ddb0e1bde6de8e922c025dccee769cc6d9e/bitarray-3.8.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:94e7da622b723705caddd59ee681cee0355b444901cc6fb2bcdc24bafba85911", size = 363773, upload-time = "2026-06-17T17:20:52.143Z" }, + { url = "https://files.pythonhosted.org/packages/80/4f/7d2946d88ae77306833bd5b91746d212404d5a86347341274b61d08c3f7e/bitarray-3.8.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3110786b00b28a756fd948c8d63e6ca3a74810b2d115582d85593d9d48035c49", size = 375005, upload-time = "2026-06-17T17:20:53.525Z" }, + { url = "https://files.pythonhosted.org/packages/fd/be/9a645b2e1bb0da4779dd9cab5a075d7c5bb68a16d8c90f051d47393bbcfe/bitarray-3.8.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd40cf27e2b54b5e30d0ce1da4f59bc16dd7c8363a20786b6e9deeb0b8ebe8e0", size = 343273, upload-time = "2026-06-17T17:20:54.938Z" }, + { url = "https://files.pythonhosted.org/packages/98/8d/73c658d200671c5e023225163be6aa545f675a676e960e5a4e19ac21274b/bitarray-3.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:24c6b97f27bd3868e28b201e1d777f5e168805862b7d9528099138bbb8c6a636", size = 333403, upload-time = "2026-06-17T17:20:56.533Z" }, + { url = "https://files.pythonhosted.org/packages/94/bc/819abd376bd6a892ce27840a1d5a4378be228be1ab3bca41845203ee672b/bitarray-3.8.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:786dedb4b1ced22dfeaaa89902561616f7edfa91774702b1aac31df3a6073c88", size = 360846, upload-time = "2026-06-17T17:20:57.862Z" }, + { url = "https://files.pythonhosted.org/packages/83/59/b8ea1e31928d06db1f2b12187631b51bb3c83186b18581754bc008cec0aa/bitarray-3.8.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:01bf9ff247117533c11963a81f3529bc12283c600dd195cf3b28a97b095f5d1c", size = 359168, upload-time = "2026-06-17T17:20:59.48Z" }, + { url = "https://files.pythonhosted.org/packages/6e/31/ef3b2f58517f7dbba8119f2592c1ea556a687bc8d405dd93c07f9c28d514/bitarray-3.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cc7a76e77c158e793d7c1e0b6c2240374087ac690a8bcacc8f18c427e5d9e20c", size = 340091, upload-time = "2026-06-17T17:21:01.183Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/bf92dcfec4eefd59fa4d8491504e100ae86e11b8cec353ae5532b25708e6/bitarray-3.8.2-cp313-cp313-win32.whl", hash = "sha256:db9add8dcc87154c0f011e0e1ce9b856e5948fbcf6faf44305aa140e525ec9a7", size = 143786, upload-time = "2026-06-17T17:21:02.43Z" }, + { url = "https://files.pythonhosted.org/packages/1c/29/1f57913a96bffb27bed486a9ca592021dd8161f6c95fd632aad7d4f0bb95/bitarray-3.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:cf4926098970d2d1a14156c0fbddb47554124347db4acf3ba616064fb021cd1e", size = 150414, upload-time = "2026-06-17T17:21:03.649Z" }, + { url = "https://files.pythonhosted.org/packages/17/9c/f36b91fcb93af54c9a28e3bd1fbf39ef7706fc623a526f3450113c0a0dae/bitarray-3.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:5c8281d0eb35e8685235e1d50f9b26156803dad398d0e7868ce9aae254c3777d", size = 148197, upload-time = "2026-06-17T17:21:04.892Z" }, + { url = "https://files.pythonhosted.org/packages/c6/86/aa2f29699763f4867359289a946ff3597d45239470c20f6ccb8dba48e7af/bitarray-3.8.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cbe96e7384e36963a2cdf5bc4ac9d0a78ae0d87fc78c53159cd5ac08c661ff34", size = 150139, upload-time = "2026-06-17T17:21:06.258Z" }, + { url = "https://files.pythonhosted.org/packages/56/1f/0d759c53a7129e4979c3c03b3f2372291c4c5a1cc851d9e749273b34ddf8/bitarray-3.8.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8b4fcecbbd0969988cc115bee74119c767636e48606fad318361eb9fe40a13c6", size = 146888, upload-time = "2026-06-17T17:21:07.515Z" }, + { url = "https://files.pythonhosted.org/packages/49/2e/0611d057e6cb010ccaf55ec6630ef41d3e7546a285383dfa2a99f545e440/bitarray-3.8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48798fc274e8a0329ca75185a0dc1e0a93ff627ea8f30c339bdf0a2ef26b1723", size = 335581, upload-time = "2026-06-17T17:21:08.808Z" }, + { url = "https://files.pythonhosted.org/packages/11/0d/201befb06fbb6275046ffe2d21cbe3b059e4f5c6b258da6e6b41f53dd9af/bitarray-3.8.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4205ae045129e58e7b7a9abe929ea0b9a3c63fad39d760e6e3b90062b6e5aa5", size = 363929, upload-time = "2026-06-17T17:21:10.225Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3c/2639aaa97eb81cabc453f78277493ea31ff49b3514e17eca56129d613279/bitarray-3.8.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:49c16cdedbd3c4d6bf64aca7b370ea02456e9be030201e80c282d8df6af36d19", size = 374562, upload-time = "2026-06-17T17:21:11.771Z" }, + { url = "https://files.pythonhosted.org/packages/52/1d/f11ba5b55f6a0f0007985f435c0e32c7a3459775cdee308cfb5938628670/bitarray-3.8.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5cad241cd0ceb79a0e4f76e86b36660c22d36c32efb364badcf7609ed5a9e5c", size = 343166, upload-time = "2026-06-17T17:21:13.101Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b9/2f8f62e1cd42f60f20ca55ed3de57ff2295b85a70eff119501ae2f0e8c48/bitarray-3.8.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3b44650aba323cb1c2285c310ffa6b1adfd5293acecd7f84aaa91afa27c802c", size = 333564, upload-time = "2026-06-17T17:21:14.629Z" }, + { url = "https://files.pythonhosted.org/packages/22/de/1525e32e7663980b82098ae0c6e032823782b9190cabed6a1f09e67c7831/bitarray-3.8.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5fc8fa50c6a89b1e75edcea4ae17787a0a9b424cdbaa03485e73a837262eca27", size = 361034, upload-time = "2026-06-17T17:21:16.318Z" }, + { url = "https://files.pythonhosted.org/packages/df/55/7bfe6af3fa577f5132380209c3f3ec560149c0af4e540ce16d84f8b76599/bitarray-3.8.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5f246319a26221e36eaf3f6aed9cd98172f81e91740bbf5cdf31b4490ecfb87a", size = 358728, upload-time = "2026-06-17T17:21:17.598Z" }, + { url = "https://files.pythonhosted.org/packages/9d/c8/85898711f7b4cf5b06c49d8e36a6702a303f1990cb21cbb39dbe186730a0/bitarray-3.8.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e76c01ae0f191c5572c12b1fda333243bfe4d58ad1d601048f9e4928d94db0c5", size = 339747, upload-time = "2026-06-17T17:21:19.092Z" }, + { url = "https://files.pythonhosted.org/packages/5b/56/94cc5250be3d530c52d15e41bdbf5f891a492aeebb9e978914aa4559c00a/bitarray-3.8.2-cp314-cp314-win32.whl", hash = "sha256:a1df20419ccc23a0326ee0cb391d1c524ee3c338856e66528d73f4dcec0389d0", size = 142830, upload-time = "2026-06-17T17:21:20.347Z" }, + { url = "https://files.pythonhosted.org/packages/b4/eb/b9ba05ae59d56a9e5cb8e812072d33be38076717db6579302e1ee85fd688/bitarray-3.8.2-cp314-cp314-win_amd64.whl", hash = "sha256:4bfbeba9156834455ab107936ebd461728f1ed35ded8f15aafde2c3dac9badf5", size = 148912, upload-time = "2026-06-17T17:21:21.556Z" }, + { url = "https://files.pythonhosted.org/packages/b6/07/e279a5ba7cd114398f00d853026e6c72e198035b925c74866e3c1973daca/bitarray-3.8.2-cp314-cp314-win_arm64.whl", hash = "sha256:4149aeb7c8cad12f9ea13783550ab5508e6d553eeefead5e3da659ce6724c5a5", size = 147373, upload-time = "2026-06-17T17:21:23.051Z" }, + { url = "https://files.pythonhosted.org/packages/94/a4/4014952965ef7edf80076f8004df31484bccecba97af7b3e9c99269a053d/bitarray-3.8.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f6f6cf5ec3be7e1bd32bfe1f4b24f7d1de28d72394d7f58789b9f9042d19f5f6", size = 151073, upload-time = "2026-06-17T17:21:24.285Z" }, + { url = "https://files.pythonhosted.org/packages/ff/00/850095c3bc551797c97a4b54c7755fc46eb115ce288fcf6962d8e8c5b678/bitarray-3.8.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2b9790847024cf1de275c8b2495331fe0982d099e407be1c1413ed40ddf2b5d", size = 148009, upload-time = "2026-06-17T17:21:25.595Z" }, + { url = "https://files.pythonhosted.org/packages/dd/4d/74f0440d95d00f086a80e6c429e3333ebb29cecf55a8d401ceb0c65a3b4b/bitarray-3.8.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c172161b8847f91e9f9ea9ae2e31fcfa784ec5d0cd413900c82574999e21ad05", size = 343487, upload-time = "2026-06-17T17:21:26.96Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/ea9c182ff0edb671853bb7a54b790572dc0b73d4a3b13e358f42aa34dca0/bitarray-3.8.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5fcc57961bc78885091a45b9ced5a5924b3b1fdd439a0e1d4b7e3aedf0c31ae2", size = 372305, upload-time = "2026-06-17T17:21:28.399Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ff/307cacc432e2ec304b870676189852c3f34a803d15b26f73bb36c549166b/bitarray-3.8.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b5fdb5399f0f2c42abcca87f8167d7ad746cf6ca7decadb4f5ad432280cc3a2f", size = 382242, upload-time = "2026-06-17T17:21:29.77Z" }, + { url = "https://files.pythonhosted.org/packages/b8/ae/757a10ce90e2090dd2dff8c5059a47439122a8d68f5fa9cf06ed07a1dc74/bitarray-3.8.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bb6195a2edafceee0e9ee12c13aad2162e9578d91a24e7c501c3bd4ab90511a", size = 348509, upload-time = "2026-06-17T17:21:31.195Z" }, + { url = "https://files.pythonhosted.org/packages/ef/d3/a035bb2c459e1f7bc86974fd43057aa8bb76466dd6bd75787d8eb9c534ed/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ce3b3dd599d4eca214f9c7fb7ac2343ccab41d91f3da7aa3b75ddbbea49ec2d5", size = 340539, upload-time = "2026-06-17T17:21:32.652Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6d/e7af02d167c227d143d208cd1c54d8e4f024d8d0bb59a0f2c38c32d56ad0/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:11cd9766ce95199bef5010ff63f73c880d9c0b6ba9c4c233aeeebc11ab1dfbb3", size = 369505, upload-time = "2026-06-17T17:21:34.115Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/29d0538ac245941127a25735d33f7b6658be6612c35115bcac60ef7c3c1c/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:7a4bbbad17d3db92615497302b74cf77504f821eb9585b7948d92093017d5e70", size = 365262, upload-time = "2026-06-17T17:21:35.829Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c8/2feabadbbc365e000821c7af82906e71366b29719329ef5709d64707fd4c/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e715498f3dc9af954b9d0977470aa352cb3fe1c39e80c32f5ac4c0348e461f6d", size = 344014, upload-time = "2026-06-17T17:21:37.228Z" }, + { url = "https://files.pythonhosted.org/packages/6c/88/dc465cbfe5c74b7da8c19b9dc2565d8a4391fad418c48e1559a0267fd00b/bitarray-3.8.2-cp314-cp314t-win32.whl", hash = "sha256:c85569fb99cf9d4aa964d2dbba3c095c7580b4368f63f51252e85b939fcd0a2c", size = 143775, upload-time = "2026-06-17T17:21:38.789Z" }, + { url = "https://files.pythonhosted.org/packages/08/75/50f2ef697d8ce46ba0986830f2d1288bff883e7f4833590076956a073496/bitarray-3.8.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7de416b313fc8e8aa1e323b83d2ba86b7c84161f7ebbaf986bdab80f9d06a2fb", size = 149884, upload-time = "2026-06-17T17:21:40.315Z" }, + { url = "https://files.pythonhosted.org/packages/df/0e/6aa2133fffbac3efcb468c7c12163eff7bbe55b86a0d6a1c687ef57e2654/bitarray-3.8.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7199451493d34a5c62cb7c9077fcfd238499af4e0d13a32d33760afe73054135", size = 148321, upload-time = "2026-06-17T17:21:41.804Z" }, ] [[package]] name = "bittensor" -version = "11.0.2.dev0" +version = "11.1.0.dev0" source = { editable = "." } dependencies = [ { name = "bittensor-core" }, @@ -149,6 +150,7 @@ requires-dist = [ { name = "typing-extensions", marker = "python_full_version < '3.11'", specifier = ">=4.0.0" }, { name = "websockets", specifier = ">=14.1,<17" }, ] +provides-extras = ["evm", "cli"] [package.metadata.requires-dev] dev = [ @@ -163,170 +165,170 @@ dev = [ [[package]] name = "bittensor-core" -version = "0.1.2" +version = "0.1.3" source = { directory = "../bittensor-core-py" } [[package]] name = "ckzg" version = "2.1.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/44/fdb579a0d035a1e510511e3c3b9ca98ba2ea240a24f112b1882478bfc2ff/ckzg-2.1.7.tar.gz", hash = "sha256:a0c61c5fd573af0267bcb435ef0f499911289ceb05e863480779ea284a3bb928", size = 1127878 } +sdist = { url = "https://files.pythonhosted.org/packages/12/44/fdb579a0d035a1e510511e3c3b9ca98ba2ea240a24f112b1882478bfc2ff/ckzg-2.1.7.tar.gz", hash = "sha256:a0c61c5fd573af0267bcb435ef0f499911289ceb05e863480779ea284a3bb928", size = 1127878, upload-time = "2026-03-11T14:11:13.745Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/13/543f474f03dc293828abbfc8a2efed2c3bd5bb10c78d0b6527d4cc880140/ckzg-2.1.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:21fbb7f5689413994d224046c0c06cb8385fb8de33c5171b2c057151710cffed", size = 96363 }, - { url = "https://files.pythonhosted.org/packages/ca/6e/8fb39b7aa945da20652e9ca5f44a2186a3b65564b106bacaf8b9fdf317df/ckzg-2.1.7-cp310-cp310-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:83f56b03c54fd9a610aeefd9fd241bb2af960cb703f208c7806b37ccc9fb7fb8", size = 179526 }, - { url = "https://files.pythonhosted.org/packages/15/4c/47e3865ffe4ae97232b67c4757b8a633f73465955d819e9d82ceb75029d7/ckzg-2.1.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8bfa41d97ee31a2053d0b2f2a53793f67745bfa694f48b6d091ae499a04c272f", size = 165238 }, - { url = "https://files.pythonhosted.org/packages/33/0f/8c809f835702a1f0c519ff35d9085783155ba44f921704fd5869b499ccc6/ckzg-2.1.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:244acf422fb727dbc376a082f71d66f6f2787b570ec27d17d20c3c3b85aef6fb", size = 174946 }, - { url = "https://files.pythonhosted.org/packages/77/e6/e61ba4caa703a84a9535c10c78180cec0c39279fd21361931dc147dab96a/ckzg-2.1.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8705f73a7efe0f01b8ce67677320be99c7d7c7077311d255bbf2d4e55fdc6a9b", size = 172853 }, - { url = "https://files.pythonhosted.org/packages/a1/c0/b76384bf8716acb7115a6a032c7e3362cb0466dd93a7567bde5c17a5b9b2/ckzg-2.1.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c6b29572b2a4f678991a1edc2426f1802e9190eb763510cf1e9bafe797f004ba", size = 187908 }, - { url = "https://files.pythonhosted.org/packages/51/32/86f473ee8b6cb9f7ffdf0007ee54fc30431d9bdf79f10240d6af2b4ab0f9/ckzg-2.1.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6ce04e32c1c459afae80edd32304956340a1dc5464a9f732f115f1119e3ec51d", size = 182481 }, - { url = "https://files.pythonhosted.org/packages/3b/59/bdbd795e51402e654652693cbaa44573b7bc2b91cb9a662b7575d46bc5aa/ckzg-2.1.7-cp310-cp310-win_amd64.whl", hash = "sha256:f537529bebfc58de21a6326100ad33e7d7ee98b0d49e44ee7f53d17ef899dfd5", size = 99827 }, - { url = "https://files.pythonhosted.org/packages/78/f1/aa4fac509f986ada4718517a2d167b7ce7efae9624c0f7f71c113c4debbd/ckzg-2.1.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c9172f571ac7ec6d90207ad1903d921c38e48482bc028f723d6908720af1add6", size = 96366 }, - { url = "https://files.pythonhosted.org/packages/96/c6/30cdc5b43928221c67b3853c10c54a21c525802a10af23cbfc188f6ad2d8/ckzg-2.1.7-cp311-cp311-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:c5494f39edeffedfa085fe85614a1c05ddd895ceb9d6c1800dc5355f9132a8f9", size = 180266 }, - { url = "https://files.pythonhosted.org/packages/e5/97/86f6030cb6daff6d87b8d0c2a666f09360b5b179fdc3507bcc60ef26318e/ckzg-2.1.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb67250207b93d2df7f694bb74bd6b4a15fb2bb67d6a78977ae8ff431678c7e7", size = 165983 }, - { url = "https://files.pythonhosted.org/packages/19/85/547814b4c6a09ebd27af9f682b7066c5c4569acd4fea74841cfe8964e5ab/ckzg-2.1.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7828cb549e2e8368e966c9dab87f3a51456647f1a3e79bdac9194e17bbc4d54", size = 175698 }, - { url = "https://files.pythonhosted.org/packages/30/a0/890e33ac991222aaa919a092e0de397e59df75baa92ec17f89370062863d/ckzg-2.1.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23eacac20c6d3be2c87e592c11d02e4a1912e799d77e2559502455e85113e7b4", size = 173516 }, - { url = "https://files.pythonhosted.org/packages/a8/71/ec6f713fb1056a647d4a7fad4ced15faedcd5d7b2a6f34ece81a9d1dbdd8/ckzg-2.1.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dd2afdc41f063e57eb569034b81088ba724240d3247ca78ea6591a1e04df50d", size = 188621 }, - { url = "https://files.pythonhosted.org/packages/d8/86/04572a67546e66b809946a7234cac0e3aa67bfa4a256d8440eefb1deaf87/ckzg-2.1.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b3af91c230982d59afe6f42c9c2a4c74412424a566bd09a42ffdfb451872335a", size = 183257 }, - { url = "https://files.pythonhosted.org/packages/da/c1/3060e997955e61699e4f6a431ff3cd3f780cd8ccfab0a2e0462848680185/ckzg-2.1.7-cp311-cp311-win_amd64.whl", hash = "sha256:f959a3bbc6d7aa7a653946e67dadaa78c0c79828aaa93b125a26f171a602b8fa", size = 99823 }, - { url = "https://files.pythonhosted.org/packages/09/40/8c2d610066a2efd4048553ff12aa832c916822ec9c888ca924565e520a7b/ckzg-2.1.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:126050ffb23b504c34c4c2073c54bd8b42f4a3034798a631c9e85911e26caf47", size = 96386 }, - { url = "https://files.pythonhosted.org/packages/29/b6/092bd10eb35e9fe3d316410791d9055039c5dd29caf03c72cc86fce45624/ckzg-2.1.7-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:936b4bffc1a6fa2bf261eb5e673f4fcc59feaf70c6c07aac1b02e3e1f942fdb6", size = 180447 }, - { url = "https://files.pythonhosted.org/packages/53/7e/f1c15ec078bee7660a2cafa103c4efdf9686256a348565ef6a1cb70ff1c4/ckzg-2.1.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:902c03b689d13684cd8b61c8e1b7a65528fdd5e1ab9d76338ddb2e902b5fd1ea", size = 166242 }, - { url = "https://files.pythonhosted.org/packages/bf/de/c22535e16163a836f76d7c3606a6e579a7a02862b4797b832cd6de5f6a1d/ckzg-2.1.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e635e5e1f6ff8ffc05d2961ccfc4b3e8c95e50c87d9765b2dfe09e32474c402", size = 176015 }, - { url = "https://files.pythonhosted.org/packages/af/4f/56c303eab20d92e5d140f96881c8c7e2eaa05976d6cb887ab574d780d09d/ckzg-2.1.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cbedb5e4732d37c87fe45a2b25891d00f434d4e0f4dd612daa034fe2011e5939", size = 173682 }, - { url = "https://files.pythonhosted.org/packages/85/0a/0feb878383e9c83d6dcd760b8de2f3095546cc09b1717ae65cbb47f90b20/ckzg-2.1.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:665d0094466b576e390b4a5e1caf199f1165841e99bf7b3cc65117f12ba4ea74", size = 188873 }, - { url = "https://files.pythonhosted.org/packages/48/29/c2eb07882465c32478e575334311ad6cea21c5d76d54da6c900dd6cb8e62/ckzg-2.1.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f5d4d1fb20eda15b901fc393a4bfd39b1be661008218f9f0db47d4e143d25d62", size = 183566 }, - { url = "https://files.pythonhosted.org/packages/c8/48/4d1f5c470cc6eb73aaba30125e6fb62759ce69bbdb2a74c160f69f601236/ckzg-2.1.7-cp312-cp312-win_amd64.whl", hash = "sha256:b580f65e61f3d89a99bfeeac0e256cf68c63d29df1c1e5e788785085083a303b", size = 99811 }, - { url = "https://files.pythonhosted.org/packages/87/32/495600f43a277bcb413d08f23f594dc548ac0d7927ad1ce7db28e58afadd/ckzg-2.1.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e23e10b227209bfae11f6f1f88ff2a8b0a2232248f985321e5e844c9dd7a4c5f", size = 96394 }, - { url = "https://files.pythonhosted.org/packages/e4/fe/c3708cfdbc228298c0f5fa4d08ceee7cc01cb7f7d105bfc9ebc68c39060d/ckzg-2.1.7-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:382c015860e7159b1ec5a85642127d4b55f6b36eef5f73d664fc409d26a3b367", size = 180484 }, - { url = "https://files.pythonhosted.org/packages/28/55/d689769ea0f9b2c2c16d8390f4c3cf7cd7dea0df68542b2a435c341df0b0/ckzg-2.1.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6666801e925d2f1d7c045fe943c1265c39b90444f88288735cc1245c4fa8018a", size = 166301 }, - { url = "https://files.pythonhosted.org/packages/16/ff/e172b4ae4bef05bf88bb8f27d2b9858b56c9984ad1708eeef82ac787fe7c/ckzg-2.1.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e823de2fd4103abc4b51512d27aa3e14107e84718e11a596eefcddc6f313b25", size = 176052 }, - { url = "https://files.pythonhosted.org/packages/61/0a/dcf28e0126e5a6f8f8b7505b4b5b637ca25e1095272fbee73f8967e3a545/ckzg-2.1.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a65c7be0bb72a159c5a4b98cc3c759b868274697de11d8248f5dde32f2400776", size = 173691 }, - { url = "https://files.pythonhosted.org/packages/2a/d2/fe404ad0bd79aaeb1e75fb4981d21e37364e59517813f7f085914026a7f6/ckzg-2.1.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62523b275f74f2729fc788d02b26e447dabfd7706ffe8882ee96d776db54b920", size = 188909 }, - { url = "https://files.pythonhosted.org/packages/55/d7/ef2d30c88270ab1a0daffa8a0f8453b72035569d3295ad3dcaba9b5250a6/ckzg-2.1.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5d998cd6d0f8e37e969c96315ac8c1e87fcf581cf27ab970bd33e62dc1c43357", size = 183597 }, - { url = "https://files.pythonhosted.org/packages/93/77/1e04840c866284bec3489154caec22855829b0c2d028bd1de771655175e3/ckzg-2.1.7-cp313-cp313-win_amd64.whl", hash = "sha256:d48b75fca9e928b2ea288fc079b0522fb91af5742b5eb4f2fdea4fc33a1b7b4e", size = 99808 }, - { url = "https://files.pythonhosted.org/packages/24/ab/11eb63c520cae074195b05cd644bf45be061b910b5c97abdaae02876a50e/ckzg-2.1.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c19b98f29f4459587e1ec4cce3e2e10963a6974293cf3143d13ce43c30542806", size = 96400 }, - { url = "https://files.pythonhosted.org/packages/31/7d/3678cbb22f31a50dd354b9d3efcb9366dd5b97cdddbf270213a66b03ad41/ckzg-2.1.7-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:d31583a24cf8166d81c36f1e424de1f343c1d604dbc8c68d938a908236ae11a3", size = 180492 }, - { url = "https://files.pythonhosted.org/packages/48/a5/355f898c75e19ac6426798c28a9767bdc734bebb40c4cd15572f644745ba/ckzg-2.1.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:baf6ac696e6a40b33ddb57aa0729d5e39230bd13fa4f1e40fe9236e8920d83fe", size = 166322 }, - { url = "https://files.pythonhosted.org/packages/ff/f5/7ffc482dc628c43d9c7a1b19392e1a920ccfd1da8d2e07d7dcc79c3e3bd2/ckzg-2.1.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bbdf89f9327e442415a810beca692729c35664e154a6830296124a5c6f05470", size = 176061 }, - { url = "https://files.pythonhosted.org/packages/26/56/f79ee2a177b4522fe47709e9f7e48407cd54a63c3d7bc1ca3002c705b3a7/ckzg-2.1.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:716c2dde0a91c0095797b843f78a6425e20a3d8945ecb4f90550b5c681b6be05", size = 173746 }, - { url = "https://files.pythonhosted.org/packages/b9/a7/95b160707b22161817245de8b9e44ea143b9a2083b0c625e5e5cd4a2e20a/ckzg-2.1.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2a9f1a05ed44512b80581e47918b1f4546974e8e924ee0e8de84ab32de197326", size = 188923 }, - { url = "https://files.pythonhosted.org/packages/33/d4/ecfbecf763d42606dba8ab9d7de557d01816afad1e2f3cb1cc7efd6fc254/ckzg-2.1.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:42005c188e37c2f65d44f3a2585e89de18e0e229bc667a600d8716808ea2c33b", size = 183607 }, - { url = "https://files.pythonhosted.org/packages/4a/72/becb801d8f1224de265f299790f5b2c95e71546ab7ab24a1fd3ebb99519e/ckzg-2.1.7-cp314-cp314-win_amd64.whl", hash = "sha256:14fbc642b1e81893df76a1636fddc169173da5dcdb55fc08a030658cd186150e", size = 102517 }, - { url = "https://files.pythonhosted.org/packages/a8/6c/b310f05a6a27baaa53915b43483cc061080e3245c7facaa3c5b3a3cd7c5e/ckzg-2.1.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:da1a07e25ecaeb341ad4caf583fdec12c6af1ef3642289bb7dfcad2ca1b73dd3", size = 96609 }, - { url = "https://files.pythonhosted.org/packages/0d/96/e1ccbf3f90595d50aa98a8a9c3c1327e6be0575ddbf8292b26b0cfa69b06/ckzg-2.1.7-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:c657892f93eb70e3295b4f385e25380644c40f8bfebfcd55659f5017257c5b8c", size = 183315 }, - { url = "https://files.pythonhosted.org/packages/bc/94/2c7ff1983f82756b29011ad612bc0e1d8f4a1989073c94fd66868bc296d3/ckzg-2.1.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03af4cf053be82c22a893c8ef971d17687182dd2e75bcc2fab320bc27a62b7cb", size = 169457 }, - { url = "https://files.pythonhosted.org/packages/98/cd/8c7247181843185ff5e34ebd400594e0fbe2d81e03324f124834f377ea74/ckzg-2.1.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ecd9c44427a0035a8a9cb3dc18b4b3c72347f7be7c9f6866b8eddd6598bf0a9", size = 178841 }, - { url = "https://files.pythonhosted.org/packages/da/cb/cf2ed4cf461bd2891792317615075745053e2585d8a2cf26a8414ad01983/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:16e313e6029e88a564724217dd8eddd6226fbf0a0c07bf65a210bf3512c7b8ad", size = 176489 }, - { url = "https://files.pythonhosted.org/packages/50/65/8b7d9cf8883f0df1a15cb20ecec99dfc02fc7bf05bf53509bb270e3a1db0/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8461ec7d69ccb450d4a4d031494a86dc6c15ad54b671967d4a8bdcd8158155b2", size = 191690 }, - { url = "https://files.pythonhosted.org/packages/83/56/a1fba1b4a2f90d5fc48d3e62f59f0791c90e85b6ebb600ffeee81ea9cfa6/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:53f420a3fa55a92265e23394caa2aac5b0e1e63ee6489d414cafeb0accde9a9e", size = 186204 }, - { url = "https://files.pythonhosted.org/packages/c7/a9/a3284a64216f31a886ff216621c6b3806ca7ad7388908f68fcab9007c881/ckzg-2.1.7-cp314-cp314t-win_amd64.whl", hash = "sha256:2cdcc023d842900564d6070e397cab0d04fd393e6af07d60bdd1c97dc3ff09fd", size = 102660 }, + { url = "https://files.pythonhosted.org/packages/e4/13/543f474f03dc293828abbfc8a2efed2c3bd5bb10c78d0b6527d4cc880140/ckzg-2.1.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:21fbb7f5689413994d224046c0c06cb8385fb8de33c5171b2c057151710cffed", size = 96363, upload-time = "2026-03-11T14:10:06.585Z" }, + { url = "https://files.pythonhosted.org/packages/ca/6e/8fb39b7aa945da20652e9ca5f44a2186a3b65564b106bacaf8b9fdf317df/ckzg-2.1.7-cp310-cp310-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:83f56b03c54fd9a610aeefd9fd241bb2af960cb703f208c7806b37ccc9fb7fb8", size = 179526, upload-time = "2026-03-11T14:10:07.936Z" }, + { url = "https://files.pythonhosted.org/packages/15/4c/47e3865ffe4ae97232b67c4757b8a633f73465955d819e9d82ceb75029d7/ckzg-2.1.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8bfa41d97ee31a2053d0b2f2a53793f67745bfa694f48b6d091ae499a04c272f", size = 165238, upload-time = "2026-03-11T14:10:09.031Z" }, + { url = "https://files.pythonhosted.org/packages/33/0f/8c809f835702a1f0c519ff35d9085783155ba44f921704fd5869b499ccc6/ckzg-2.1.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:244acf422fb727dbc376a082f71d66f6f2787b570ec27d17d20c3c3b85aef6fb", size = 174946, upload-time = "2026-03-11T14:10:10.096Z" }, + { url = "https://files.pythonhosted.org/packages/77/e6/e61ba4caa703a84a9535c10c78180cec0c39279fd21361931dc147dab96a/ckzg-2.1.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8705f73a7efe0f01b8ce67677320be99c7d7c7077311d255bbf2d4e55fdc6a9b", size = 172853, upload-time = "2026-03-11T14:10:11.048Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c0/b76384bf8716acb7115a6a032c7e3362cb0466dd93a7567bde5c17a5b9b2/ckzg-2.1.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c6b29572b2a4f678991a1edc2426f1802e9190eb763510cf1e9bafe797f004ba", size = 187908, upload-time = "2026-03-11T14:10:12.018Z" }, + { url = "https://files.pythonhosted.org/packages/51/32/86f473ee8b6cb9f7ffdf0007ee54fc30431d9bdf79f10240d6af2b4ab0f9/ckzg-2.1.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6ce04e32c1c459afae80edd32304956340a1dc5464a9f732f115f1119e3ec51d", size = 182481, upload-time = "2026-03-11T14:10:13.013Z" }, + { url = "https://files.pythonhosted.org/packages/3b/59/bdbd795e51402e654652693cbaa44573b7bc2b91cb9a662b7575d46bc5aa/ckzg-2.1.7-cp310-cp310-win_amd64.whl", hash = "sha256:f537529bebfc58de21a6326100ad33e7d7ee98b0d49e44ee7f53d17ef899dfd5", size = 99827, upload-time = "2026-03-11T14:10:14.224Z" }, + { url = "https://files.pythonhosted.org/packages/78/f1/aa4fac509f986ada4718517a2d167b7ce7efae9624c0f7f71c113c4debbd/ckzg-2.1.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c9172f571ac7ec6d90207ad1903d921c38e48482bc028f723d6908720af1add6", size = 96366, upload-time = "2026-03-11T14:10:15.098Z" }, + { url = "https://files.pythonhosted.org/packages/96/c6/30cdc5b43928221c67b3853c10c54a21c525802a10af23cbfc188f6ad2d8/ckzg-2.1.7-cp311-cp311-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:c5494f39edeffedfa085fe85614a1c05ddd895ceb9d6c1800dc5355f9132a8f9", size = 180266, upload-time = "2026-03-11T14:10:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/e5/97/86f6030cb6daff6d87b8d0c2a666f09360b5b179fdc3507bcc60ef26318e/ckzg-2.1.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb67250207b93d2df7f694bb74bd6b4a15fb2bb67d6a78977ae8ff431678c7e7", size = 165983, upload-time = "2026-03-11T14:10:17.407Z" }, + { url = "https://files.pythonhosted.org/packages/19/85/547814b4c6a09ebd27af9f682b7066c5c4569acd4fea74841cfe8964e5ab/ckzg-2.1.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7828cb549e2e8368e966c9dab87f3a51456647f1a3e79bdac9194e17bbc4d54", size = 175698, upload-time = "2026-03-11T14:10:18.35Z" }, + { url = "https://files.pythonhosted.org/packages/30/a0/890e33ac991222aaa919a092e0de397e59df75baa92ec17f89370062863d/ckzg-2.1.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23eacac20c6d3be2c87e592c11d02e4a1912e799d77e2559502455e85113e7b4", size = 173516, upload-time = "2026-03-11T14:10:19.615Z" }, + { url = "https://files.pythonhosted.org/packages/a8/71/ec6f713fb1056a647d4a7fad4ced15faedcd5d7b2a6f34ece81a9d1dbdd8/ckzg-2.1.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dd2afdc41f063e57eb569034b81088ba724240d3247ca78ea6591a1e04df50d", size = 188621, upload-time = "2026-03-11T14:10:20.865Z" }, + { url = "https://files.pythonhosted.org/packages/d8/86/04572a67546e66b809946a7234cac0e3aa67bfa4a256d8440eefb1deaf87/ckzg-2.1.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b3af91c230982d59afe6f42c9c2a4c74412424a566bd09a42ffdfb451872335a", size = 183257, upload-time = "2026-03-11T14:10:21.808Z" }, + { url = "https://files.pythonhosted.org/packages/da/c1/3060e997955e61699e4f6a431ff3cd3f780cd8ccfab0a2e0462848680185/ckzg-2.1.7-cp311-cp311-win_amd64.whl", hash = "sha256:f959a3bbc6d7aa7a653946e67dadaa78c0c79828aaa93b125a26f171a602b8fa", size = 99823, upload-time = "2026-03-11T14:10:22.674Z" }, + { url = "https://files.pythonhosted.org/packages/09/40/8c2d610066a2efd4048553ff12aa832c916822ec9c888ca924565e520a7b/ckzg-2.1.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:126050ffb23b504c34c4c2073c54bd8b42f4a3034798a631c9e85911e26caf47", size = 96386, upload-time = "2026-03-11T14:10:23.532Z" }, + { url = "https://files.pythonhosted.org/packages/29/b6/092bd10eb35e9fe3d316410791d9055039c5dd29caf03c72cc86fce45624/ckzg-2.1.7-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:936b4bffc1a6fa2bf261eb5e673f4fcc59feaf70c6c07aac1b02e3e1f942fdb6", size = 180447, upload-time = "2026-03-11T14:10:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/53/7e/f1c15ec078bee7660a2cafa103c4efdf9686256a348565ef6a1cb70ff1c4/ckzg-2.1.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:902c03b689d13684cd8b61c8e1b7a65528fdd5e1ab9d76338ddb2e902b5fd1ea", size = 166242, upload-time = "2026-03-11T14:10:25.671Z" }, + { url = "https://files.pythonhosted.org/packages/bf/de/c22535e16163a836f76d7c3606a6e579a7a02862b4797b832cd6de5f6a1d/ckzg-2.1.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e635e5e1f6ff8ffc05d2961ccfc4b3e8c95e50c87d9765b2dfe09e32474c402", size = 176015, upload-time = "2026-03-11T14:10:26.976Z" }, + { url = "https://files.pythonhosted.org/packages/af/4f/56c303eab20d92e5d140f96881c8c7e2eaa05976d6cb887ab574d780d09d/ckzg-2.1.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cbedb5e4732d37c87fe45a2b25891d00f434d4e0f4dd612daa034fe2011e5939", size = 173682, upload-time = "2026-03-11T14:10:27.857Z" }, + { url = "https://files.pythonhosted.org/packages/85/0a/0feb878383e9c83d6dcd760b8de2f3095546cc09b1717ae65cbb47f90b20/ckzg-2.1.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:665d0094466b576e390b4a5e1caf199f1165841e99bf7b3cc65117f12ba4ea74", size = 188873, upload-time = "2026-03-11T14:10:28.85Z" }, + { url = "https://files.pythonhosted.org/packages/48/29/c2eb07882465c32478e575334311ad6cea21c5d76d54da6c900dd6cb8e62/ckzg-2.1.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f5d4d1fb20eda15b901fc393a4bfd39b1be661008218f9f0db47d4e143d25d62", size = 183566, upload-time = "2026-03-11T14:10:29.777Z" }, + { url = "https://files.pythonhosted.org/packages/c8/48/4d1f5c470cc6eb73aaba30125e6fb62759ce69bbdb2a74c160f69f601236/ckzg-2.1.7-cp312-cp312-win_amd64.whl", hash = "sha256:b580f65e61f3d89a99bfeeac0e256cf68c63d29df1c1e5e788785085083a303b", size = 99811, upload-time = "2026-03-11T14:10:30.719Z" }, + { url = "https://files.pythonhosted.org/packages/87/32/495600f43a277bcb413d08f23f594dc548ac0d7927ad1ce7db28e58afadd/ckzg-2.1.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e23e10b227209bfae11f6f1f88ff2a8b0a2232248f985321e5e844c9dd7a4c5f", size = 96394, upload-time = "2026-03-11T14:10:31.535Z" }, + { url = "https://files.pythonhosted.org/packages/e4/fe/c3708cfdbc228298c0f5fa4d08ceee7cc01cb7f7d105bfc9ebc68c39060d/ckzg-2.1.7-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:382c015860e7159b1ec5a85642127d4b55f6b36eef5f73d664fc409d26a3b367", size = 180484, upload-time = "2026-03-11T14:10:32.418Z" }, + { url = "https://files.pythonhosted.org/packages/28/55/d689769ea0f9b2c2c16d8390f4c3cf7cd7dea0df68542b2a435c341df0b0/ckzg-2.1.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6666801e925d2f1d7c045fe943c1265c39b90444f88288735cc1245c4fa8018a", size = 166301, upload-time = "2026-03-11T14:10:33.363Z" }, + { url = "https://files.pythonhosted.org/packages/16/ff/e172b4ae4bef05bf88bb8f27d2b9858b56c9984ad1708eeef82ac787fe7c/ckzg-2.1.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e823de2fd4103abc4b51512d27aa3e14107e84718e11a596eefcddc6f313b25", size = 176052, upload-time = "2026-03-11T14:10:34.621Z" }, + { url = "https://files.pythonhosted.org/packages/61/0a/dcf28e0126e5a6f8f8b7505b4b5b637ca25e1095272fbee73f8967e3a545/ckzg-2.1.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a65c7be0bb72a159c5a4b98cc3c759b868274697de11d8248f5dde32f2400776", size = 173691, upload-time = "2026-03-11T14:10:35.577Z" }, + { url = "https://files.pythonhosted.org/packages/2a/d2/fe404ad0bd79aaeb1e75fb4981d21e37364e59517813f7f085914026a7f6/ckzg-2.1.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62523b275f74f2729fc788d02b26e447dabfd7706ffe8882ee96d776db54b920", size = 188909, upload-time = "2026-03-11T14:10:36.798Z" }, + { url = "https://files.pythonhosted.org/packages/55/d7/ef2d30c88270ab1a0daffa8a0f8453b72035569d3295ad3dcaba9b5250a6/ckzg-2.1.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5d998cd6d0f8e37e969c96315ac8c1e87fcf581cf27ab970bd33e62dc1c43357", size = 183597, upload-time = "2026-03-11T14:10:37.812Z" }, + { url = "https://files.pythonhosted.org/packages/93/77/1e04840c866284bec3489154caec22855829b0c2d028bd1de771655175e3/ckzg-2.1.7-cp313-cp313-win_amd64.whl", hash = "sha256:d48b75fca9e928b2ea288fc079b0522fb91af5742b5eb4f2fdea4fc33a1b7b4e", size = 99808, upload-time = "2026-03-11T14:10:38.701Z" }, + { url = "https://files.pythonhosted.org/packages/24/ab/11eb63c520cae074195b05cd644bf45be061b910b5c97abdaae02876a50e/ckzg-2.1.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c19b98f29f4459587e1ec4cce3e2e10963a6974293cf3143d13ce43c30542806", size = 96400, upload-time = "2026-03-11T14:10:39.59Z" }, + { url = "https://files.pythonhosted.org/packages/31/7d/3678cbb22f31a50dd354b9d3efcb9366dd5b97cdddbf270213a66b03ad41/ckzg-2.1.7-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:d31583a24cf8166d81c36f1e424de1f343c1d604dbc8c68d938a908236ae11a3", size = 180492, upload-time = "2026-03-11T14:10:40.766Z" }, + { url = "https://files.pythonhosted.org/packages/48/a5/355f898c75e19ac6426798c28a9767bdc734bebb40c4cd15572f644745ba/ckzg-2.1.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:baf6ac696e6a40b33ddb57aa0729d5e39230bd13fa4f1e40fe9236e8920d83fe", size = 166322, upload-time = "2026-03-11T14:10:41.752Z" }, + { url = "https://files.pythonhosted.org/packages/ff/f5/7ffc482dc628c43d9c7a1b19392e1a920ccfd1da8d2e07d7dcc79c3e3bd2/ckzg-2.1.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bbdf89f9327e442415a810beca692729c35664e154a6830296124a5c6f05470", size = 176061, upload-time = "2026-03-11T14:10:42.649Z" }, + { url = "https://files.pythonhosted.org/packages/26/56/f79ee2a177b4522fe47709e9f7e48407cd54a63c3d7bc1ca3002c705b3a7/ckzg-2.1.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:716c2dde0a91c0095797b843f78a6425e20a3d8945ecb4f90550b5c681b6be05", size = 173746, upload-time = "2026-03-11T14:10:43.657Z" }, + { url = "https://files.pythonhosted.org/packages/b9/a7/95b160707b22161817245de8b9e44ea143b9a2083b0c625e5e5cd4a2e20a/ckzg-2.1.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2a9f1a05ed44512b80581e47918b1f4546974e8e924ee0e8de84ab32de197326", size = 188923, upload-time = "2026-03-11T14:10:44.635Z" }, + { url = "https://files.pythonhosted.org/packages/33/d4/ecfbecf763d42606dba8ab9d7de557d01816afad1e2f3cb1cc7efd6fc254/ckzg-2.1.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:42005c188e37c2f65d44f3a2585e89de18e0e229bc667a600d8716808ea2c33b", size = 183607, upload-time = "2026-03-11T14:10:45.846Z" }, + { url = "https://files.pythonhosted.org/packages/4a/72/becb801d8f1224de265f299790f5b2c95e71546ab7ab24a1fd3ebb99519e/ckzg-2.1.7-cp314-cp314-win_amd64.whl", hash = "sha256:14fbc642b1e81893df76a1636fddc169173da5dcdb55fc08a030658cd186150e", size = 102517, upload-time = "2026-03-11T14:10:47.079Z" }, + { url = "https://files.pythonhosted.org/packages/a8/6c/b310f05a6a27baaa53915b43483cc061080e3245c7facaa3c5b3a3cd7c5e/ckzg-2.1.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:da1a07e25ecaeb341ad4caf583fdec12c6af1ef3642289bb7dfcad2ca1b73dd3", size = 96609, upload-time = "2026-03-11T14:10:48.019Z" }, + { url = "https://files.pythonhosted.org/packages/0d/96/e1ccbf3f90595d50aa98a8a9c3c1327e6be0575ddbf8292b26b0cfa69b06/ckzg-2.1.7-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:c657892f93eb70e3295b4f385e25380644c40f8bfebfcd55659f5017257c5b8c", size = 183315, upload-time = "2026-03-11T14:10:49.224Z" }, + { url = "https://files.pythonhosted.org/packages/bc/94/2c7ff1983f82756b29011ad612bc0e1d8f4a1989073c94fd66868bc296d3/ckzg-2.1.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03af4cf053be82c22a893c8ef971d17687182dd2e75bcc2fab320bc27a62b7cb", size = 169457, upload-time = "2026-03-11T14:10:50.601Z" }, + { url = "https://files.pythonhosted.org/packages/98/cd/8c7247181843185ff5e34ebd400594e0fbe2d81e03324f124834f377ea74/ckzg-2.1.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ecd9c44427a0035a8a9cb3dc18b4b3c72347f7be7c9f6866b8eddd6598bf0a9", size = 178841, upload-time = "2026-03-11T14:10:51.598Z" }, + { url = "https://files.pythonhosted.org/packages/da/cb/cf2ed4cf461bd2891792317615075745053e2585d8a2cf26a8414ad01983/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:16e313e6029e88a564724217dd8eddd6226fbf0a0c07bf65a210bf3512c7b8ad", size = 176489, upload-time = "2026-03-11T14:10:52.905Z" }, + { url = "https://files.pythonhosted.org/packages/50/65/8b7d9cf8883f0df1a15cb20ecec99dfc02fc7bf05bf53509bb270e3a1db0/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8461ec7d69ccb450d4a4d031494a86dc6c15ad54b671967d4a8bdcd8158155b2", size = 191690, upload-time = "2026-03-11T14:10:53.855Z" }, + { url = "https://files.pythonhosted.org/packages/83/56/a1fba1b4a2f90d5fc48d3e62f59f0791c90e85b6ebb600ffeee81ea9cfa6/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:53f420a3fa55a92265e23394caa2aac5b0e1e63ee6489d414cafeb0accde9a9e", size = 186204, upload-time = "2026-03-11T14:10:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a9/a3284a64216f31a886ff216621c6b3806ca7ad7388908f68fcab9007c881/ckzg-2.1.7-cp314-cp314t-win_amd64.whl", hash = "sha256:2cdcc023d842900564d6070e397cab0d04fd393e6af07d60bdd1c97dc3ff09fd", size = 102660, upload-time = "2026-03-11T14:10:55.974Z" }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] [[package]] name = "coverage" version = "7.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cc/8b/adeb62ea8951f13c4c7fef2e7a85e1a06b499c8d8237ea589d496029e53f/coverage-7.15.0.tar.gz", hash = "sha256:9ac3fe7a1435986463eaa8ee253ae2f2a268709ba4ae5c7dd1f52a05391ad78f", size = 925362 } +sdist = { url = "https://files.pythonhosted.org/packages/cc/8b/adeb62ea8951f13c4c7fef2e7a85e1a06b499c8d8237ea589d496029e53f/coverage-7.15.0.tar.gz", hash = "sha256:9ac3fe7a1435986463eaa8ee253ae2f2a268709ba4ae5c7dd1f52a05391ad78f", size = 925362, upload-time = "2026-07-02T13:10:50.535Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/97/c52dc440c390b6cfa87be9432b141a956e2d56d9b9f5fc8bd71c5f471722/coverage-7.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50913d4bf5ddafa6ca3693da5e4dd833dd1b772e0283c99ca7f7d287db67331a", size = 220539 }, - { url = "https://files.pythonhosted.org/packages/3f/26/602de8c2aec7e2e3e99ebfb8e04ba65598f746275396eea5f6794ff4673f/coverage-7.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:359e141ccd33893ce3f1ad5525f8b96083003677c82182e5907d62d4ea5799fc", size = 221058 }, - { url = "https://files.pythonhosted.org/packages/fc/13/ebab0743138891c1d646d61e247ec29639afcbb6c4e1905e6a0f0c75291a/coverage-7.15.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3200b6204935f928c64b2ca1f923ab8c1acb7c9de45ec61569711b34d25cccaf", size = 247797 }, - { url = "https://files.pythonhosted.org/packages/d3/b7/b6ffb9e042aa48dc4144a8a65529affaec8dca0685309353614a2a7386ad/coverage-7.15.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:be616bf61346883b2cfdc5178669647e03531d81ab761a7e378558b7e8bcb628", size = 249626 }, - { url = "https://files.pythonhosted.org/packages/9c/06/243ff05b652333d8e3d060c11223efc2723b19cacf6605e433fa686ab5d4/coverage-7.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7bafc3fe1059463a8fdd97ca79972d6e2bf819d775c7d54991b5b1971201d6", size = 251493 }, - { url = "https://files.pythonhosted.org/packages/d3/2b/867faa17030a806114dae388b32a3fa929d8cd4bf39226fbc11f6e6bb705/coverage-7.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b713aa7fcf325a01d4184d848acb46fd84f78fdb0978470c636b23a06a753d91", size = 253406 }, - { url = "https://files.pythonhosted.org/packages/94/c0/d789ce18f6605afc4895db75723424be2ef494282f77f61d8e5832923183/coverage-7.15.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e38e6fba2d56652fdfaf0231f8f78aeb805234a912de25dc291ee5cce5b8faa4", size = 248512 }, - { url = "https://files.pythonhosted.org/packages/c9/b6/b2673c30739f4a2e06649a0a38ad8b093c4d865462dc7bab0e9524a2c3b1/coverage-7.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:884499f42e382675be80770391983b90e0c0c774d87dbeeebf5f991cf6612b20", size = 249532 }, - { url = "https://files.pythonhosted.org/packages/3c/2e/acd79e9a41beabee92b623afe4f30b549916f48566271475f2907e752828/coverage-7.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:840481b12e083dbcbafab14794a8781a958edf327c8d3d70b4eee42f9b8253aa", size = 247537 }, - { url = "https://files.pythonhosted.org/packages/12/d4/2d301c4d1b3238d7c88b70ab9d13fd53ed9505662a7ff1b46ba1e2e4e3c3/coverage-7.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:276646e9481703d09f854f3b2f018f24e19fd7049ae670a92570043eb97203b1", size = 251348 }, - { url = "https://files.pythonhosted.org/packages/35/bb/c67708b2bc00f32e12805ec23d5fa677a0a51652f449341a89f9d6b1b715/coverage-7.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4de4b4d3f5545aa6c60dc4efd9c63b5b5dcc3bf00fe83146b2bdfffb8f6613bd", size = 247806 }, - { url = "https://files.pythonhosted.org/packages/eb/6c/57c4f653c47a6e917748f8938e389e72fbcae44e3643cd906664f0477a13/coverage-7.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5c504097b2a89b1e85bc6070d920df77daec701337e3aeef2c17775a5dd0ca90", size = 248410 }, - { url = "https://files.pythonhosted.org/packages/6c/94/bb083041aef828903668f134273f319f2bd49224962875359c52faa5497f/coverage-7.15.0-cp310-cp310-win32.whl", hash = "sha256:f6e80ed91f98316e86b9c137206b04b2bcfbffccbdff49bd2eb09dddb1cf14e0", size = 222588 }, - { url = "https://files.pythonhosted.org/packages/ef/94/a09d8ee618956f626741b0734854bac4425a00e10c0565f5abca64e7e751/coverage-7.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:b3b3e22030f3f6f5e01a5ce69936552a5c0f6992b7698777377b99041961031f", size = 223214 }, - { url = "https://files.pythonhosted.org/packages/ae/23/82e910835ef4b8391047025e1d53aa48d66029f444eb8b25373c849bf503/coverage-7.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:003fff99412ea848c0aaebcc78ed2b6ce7d8a1227ed17e68470672770b78a02a", size = 220662 }, - { url = "https://files.pythonhosted.org/packages/6d/0d/c7b213dde2f1579de5231062b386d8413f79c11667eb58c39319b25991da/coverage-7.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5cbd804bf2784ce7b45114516050f346ecd50f960c4bb630a7ee9e1d78fa2118", size = 221168 }, - { url = "https://files.pythonhosted.org/packages/33/77/d000aeedfac085088337b3c7becdad328474b1f8a9e4c9368a0c99605d68/coverage-7.15.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8773e15c23305b58882a4611fb9b2755977eae0dc2e515366a1b6c98866cc4c2", size = 251587 }, - { url = "https://files.pythonhosted.org/packages/cc/e0/86787c56b9df17afd370d5e293515dd4d9a107a561d13054873eefad8ecc/coverage-7.15.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f50e40081494c1dc4239ebb202014cbcc3306ea96fb6302a34c8cc0967fc5ae8", size = 253497 }, - { url = "https://files.pythonhosted.org/packages/3f/02/181bc917359299c07dead6270f94e411151c8b60cec905c33499da69afe6/coverage-7.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daf96f37f5fc3a7b6c6da862eb4aee61c426bd63da236ed4a73ef0e503b4bca5", size = 255607 }, - { url = "https://files.pythonhosted.org/packages/b9/35/ca5e7427699913da6788c4f910e73ab16c5f4b59ec5d3a999dce2a45112f/coverage-7.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:51aa20f6ae2788fd197747766edf4cd8234fd9423309b934257fa6b21a592723", size = 257563 }, - { url = "https://files.pythonhosted.org/packages/0b/4d/b8220bacc2fc3c4e9078e27c32e99fb411479a4718a72bdd00036a9891c8/coverage-7.15.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03d1f922757662eb7af586e77834792274cff776bc7b1d1a0b66a49ea9d84735", size = 251726 }, - { url = "https://files.pythonhosted.org/packages/c4/e4/2e145da1991d72189b9c3cf7eca05c716ee7080d099aaea6757cfc7df008/coverage-7.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a6d6acc9a7666245e6133dd15144ca038a85a9cd5026bb06d6bbae9e77440dc9", size = 253301 }, - { url = "https://files.pythonhosted.org/packages/72/28/d2c841d698bf762e481f08bd4839d370246b6d9b61dab085a7b20b201a08/coverage-7.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ac2c4c27c7df851dc9a017c2d7de00b69147e84ba3d96f37a530b0b6fb51035", size = 251361 }, - { url = "https://files.pythonhosted.org/packages/9d/ed/55d9ffde994fba3897c0c783f77a7d053b0c18787f6892ed5b0aed73f469/coverage-7.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b761a1d504fd4bd1f20f418753964dca9f5862a511fc854dac58296b3b223671", size = 255129 }, - { url = "https://files.pythonhosted.org/packages/1d/c0/ecbf33b8c460ea2718aeb813e2df8140d0370e5f67261c31524ceb0a2a8d/coverage-7.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e43b045e11c16e897895758ae90e4a90cf99e93d58549e2f90c0e2272e155695", size = 251081 }, - { url = "https://files.pythonhosted.org/packages/a9/de/fb87b4261f54448dd2b9504ef19a58be42cef0d9520595fbfe1219b15234/coverage-7.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589b54513e901739f4b4582c705ce96b80c96f57641b1464607e2367a270e540", size = 251988 }, - { url = "https://files.pythonhosted.org/packages/df/27/3494d5f291b9a4cb868f73c11221a8bd2d5bd761a8f9acea61ff57128dd1/coverage-7.15.0-cp311-cp311-win32.whl", hash = "sha256:106781b8482749162d0b47056937ba0933508e5d9447f65a5e7d5c422f0d6bb4", size = 222754 }, - { url = "https://files.pythonhosted.org/packages/2a/ee/cd4847ebc9be6a9c0123d763645a6f1f3be6b8c58c962706368b79cbac07/coverage-7.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:821e92b3631d762a339695824cadbbc73020354eba2a23a551a99ad34938fbe6", size = 223225 }, - { url = "https://files.pythonhosted.org/packages/57/37/5011581aa7f2be498b97dcc7c9902192442a42f4f9a748aeadb3d6506b42/coverage-7.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:309990eb5fb8014b9f67cb211f7fd41876ec8a88a88d3ae76de0ed1d611e3640", size = 222774 }, - { url = "https://files.pythonhosted.org/packages/2a/74/fd4c0901137c4f8d81a76ada99e43c65163b4c94a02ece107a4ec0c6b615/coverage-7.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b75ee5e8cb7575636ac598719b4307ac529ec8fcd79608a35c3cd4d4dada812d", size = 220838 }, - { url = "https://files.pythonhosted.org/packages/0f/2e/2347583467bd7f0402635101a916961915cc68fce652cd0db5f173ea04fc/coverage-7.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffb31267816b93b075302248cc1737506081b4f163df4401e9df1a6424aafabe", size = 221197 }, - { url = "https://files.pythonhosted.org/packages/f0/17/99fa688541ae1d6e84543a0e544f83de0c944815b63e9e7b1ed411d15036/coverage-7.15.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e4d0bb73455bf97ab243a8f12c37c686ccf1c13bb614b7b85f1d062f06f42b2c", size = 252705 }, - { url = "https://files.pythonhosted.org/packages/fb/02/6a95a5cd83b74839017ef9cf48d2d8c9ae60af919e17a3f336e6f9f1b7bd/coverage-7.15.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:20d9ccc4ebd0edc434d86dfd2a1dd2a8efa6b6b3073d0485a394fee86459ebb4", size = 255441 }, - { url = "https://files.pythonhosted.org/packages/67/f2/406f6c57d600f68185942422c4c00f1a3255d60aee6e5fd961425cd9987e/coverage-7.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c8a976c365c8cb12f0cbd099508772ea41fb5fa80657a8506df0e11bd278c5", size = 256556 }, - { url = "https://files.pythonhosted.org/packages/74/8e/d3fa48489c15ecdec1ba48fd61f68798555dddd2f6716f9ad42adeb1a2a9/coverage-7.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f948fd5ba1b9cbca91f0ae08b4c1ce2b139509149a435e2585d056d57d70bf01", size = 258815 }, - { url = "https://files.pythonhosted.org/packages/47/2e/2d40ddd110462c6a2769677cf7f1c119a52b45f568978fc6c98e4cc0dd0f/coverage-7.15.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f58185f06edf6ad68ec9fb155d63ef650c82f3fbd7e1770e2867751fb13158f4", size = 253117 }, - { url = "https://files.pythonhosted.org/packages/51/c0/310782f0d7c3cb2b5ac05ba8d205fe91f24a36f6bf3256098f1782181c38/coverage-7.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02adc79a920c73c647c5d117f55747df7f2de94571884758ce8bc58e04f0a796", size = 254475 }, - { url = "https://files.pythonhosted.org/packages/86/f7/702da6c275f8ae6ade423d2877243122932c9b27f5403003b9ef8c927d12/coverage-7.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6eb7c300fbed667fd6e3588eba71c1904cdb06110ca6fdf908c26bdd88b8e382", size = 252619 }, - { url = "https://files.pythonhosted.org/packages/fb/84/c5b15a7e5ecba4e56218d772d99fe80a63e63f8d11f12783723a6005ab45/coverage-7.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b5fb23fa2de9dce1f5c36c09066d8fcda16cd96e8e26686caa2d7cb9b567d65c", size = 256689 }, - { url = "https://files.pythonhosted.org/packages/95/2f/c8b07559b57701230c61b23a953858c052890c12ef568d81780c6c46e92e/coverage-7.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cec79341dbe6281484024979976d0c7f22beae08b4a254655decd25d42cbe766", size = 252189 }, - { url = "https://files.pythonhosted.org/packages/6b/80/6d2f049dd3fd3dbfd60b62ba6b2162a04009e2c002ce70b24cf3878dec7a/coverage-7.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c664c5444b1d970b1b2a450e21fb19ee5c9cfdf151ded2dda37260031cca0da", size = 254059 }, - { url = "https://files.pythonhosted.org/packages/ce/92/b0287a2c42031d25c628f815f89a3cd9f8268ee78bb1252c9356cda1c689/coverage-7.15.0-cp312-cp312-win32.whl", hash = "sha256:5f764a3fa339bde6b3aa97657f5a6a3a9451e4a5b4ea98a2892c773a43525f77", size = 222893 }, - { url = "https://files.pythonhosted.org/packages/a9/69/e34c481915fecb499b3146975061dac528752e37706edc1804f32c822469/coverage-7.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:52f9a4d2c4c56c8848bc2f524916698354b0211488b38c49ad9ae54f6cafbff6", size = 223429 }, - { url = "https://files.pythonhosted.org/packages/fe/98/6e878f0b571d32684ef3f38d7c03db241ca5b82a5da8a5391596a8f209c4/coverage-7.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:31e5c3e70c85307ea35a12964e2e40f56ca2ee4b1c8c721ccf4609d17071080b", size = 222810 }, - { url = "https://files.pythonhosted.org/packages/76/04/145a3748098bcc86b631a85408d2c3dc5c104e0bd86d605468239b25b6c4/coverage-7.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be4caf3b28836f078abe700f8944dac4a65d78f16d6c600c89cb624e5535782", size = 220863 }, - { url = "https://files.pythonhosted.org/packages/a4/5c/4ed55708fed2c64b63c9bc5715daef670872202101938869b7fe5d5fbb8f/coverage-7.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dd58ad1404704303ca8d4f4b8a1095e7cbc7040ef17a66df1e6619aa10176430", size = 221230 }, - { url = "https://files.pythonhosted.org/packages/7b/19/3a80b97d3b2a5c77a01ae359c6bed20c13738fe3d9380f08616d4fec0281/coverage-7.15.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bbcbb317c2e5ded5b21104af81c29f391be2af98d065693ffbe8d23949b948e5", size = 252227 }, - { url = "https://files.pythonhosted.org/packages/a1/fa/b70062750686bd7da454da27927622f48bbac6990ac7a4c4a4653e7b0036/coverage-7.15.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:27f31ecb458da3f859aab3f15ada871eb7a7768807d88df4a9f186bb17737970", size = 254823 }, - { url = "https://files.pythonhosted.org/packages/a9/09/dad6a75a2e561b9dc5086a8c5257a7591d584246f67e23e70d2995b89ab6/coverage-7.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fb759be317fdc62e0f56bffdf61cfcb45c7761ad6b71e3e583e71a67ae753c", size = 256059 }, - { url = "https://files.pythonhosted.org/packages/e6/e7/b5d2941fa9564573d44b693a871ff3156f0c42cbefe977a09fa7fdc59971/coverage-7.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5cf007add5ab4bb8fa9f4c77e3732127c9e6cad501d7db43355fbfafca0be84", size = 258190 }, - { url = "https://files.pythonhosted.org/packages/7c/1d/8e895bcde3c57ccd46d896dda5f2b3d5df761a1b0c6c9d450d175dedc632/coverage-7.15.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc78d9843bd576fbe2118248258d485e968dc535f95ed504a7b0867ba9b51389", size = 252456 }, - { url = "https://files.pythonhosted.org/packages/14/4c/f6997da343ddeb959be82c3b05322793f92c071ad45f7cb8a96336e2dd5f/coverage-7.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a263060f1de0b4b74b4e089c2a70b8003b3781c733329a9c8fd54995328f9950", size = 254192 }, - { url = "https://files.pythonhosted.org/packages/17/27/a0bc09d032267b9da89d95a2d874cfbef2a5aebbf0e87cf7aba221d79a99/coverage-7.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c48decf16e0dfd5b049c7d5e82200c23c08126719142998d4f172444e3d0529e", size = 252153 }, - { url = "https://files.pythonhosted.org/packages/54/c0/77fc233d9fba07b244c40948c53fe27308b8f21732fb3417f87fbd6fd992/coverage-7.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08fb028000ed0aaa0a4cbdfbb98be7cb42f370db973fbbb469733505ab20e13e", size = 256310 }, - { url = "https://files.pythonhosted.org/packages/d5/24/601cecfb5825becacb8d45219a018a3b55b9dbaec624efdb0ea249d08be2/coverage-7.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb7dc0c3b7d8a1077abea0b8546ebc5e26d6ef6ecefc2f0f5ad2b8a53bdad837", size = 251974 }, - { url = "https://files.pythonhosted.org/packages/47/1e/6f45e5a5b3d5484318d368702af6716b5ab8913b0428bec981a562fcf296/coverage-7.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cb3602054ccbe9f0d8c2dc04bbeba90d5719236e2cd06e042ddd6d3fc7b6e37", size = 253745 }, - { url = "https://files.pythonhosted.org/packages/8e/db/4df027a77bd11d0e527f44c53557c76e54ad027413d0304252ea3a78d67e/coverage-7.15.0-cp313-cp313-win32.whl", hash = "sha256:0bf781da64326b677be344df505171435b6f58716108606621d5d27d964fff8b", size = 222902 }, - { url = "https://files.pythonhosted.org/packages/a0/10/0355894d34e231f2c5449e71287e81a50793a325df2e2b027b7bcd9dfd19/coverage-7.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:2c57a275078ee3fa185f83e400f765bc764a549de66d99b47881645cbd4ea629", size = 223444 }, - { url = "https://files.pythonhosted.org/packages/06/ef/bb725f263befaaff851203ab338e68af15e195d7f7b5f323162532d9b6a8/coverage-7.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:3812c61afc6685c7999b39320779ab8f43b7a3081fdb0def39976e56fbdb9a21", size = 222839 }, - { url = "https://files.pythonhosted.org/packages/4f/9c/1e3ca54f72a3185ece06c58d871099898c48f0ed6430d17b6ab75f0d180a/coverage-7.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:41cb79af843222e11da87127ad0ecbfa878abadd0f770a4a99391a27d3887324", size = 220906 }, - { url = "https://files.pythonhosted.org/packages/09/37/f718613d83b274880382f6b67e78f3802549ae39b0b3e65ae5b5974df56e/coverage-7.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d2008989ef8fe54188d3f3bfa2e3099b025af11e90a6a1b9e7dc433d04263d8", size = 221239 }, - { url = "https://files.pythonhosted.org/packages/a7/ce/22bae91e0b75445f68d365c7643ed0aa4880bbf77450ee74ca65bdae53a7/coverage-7.15.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:769e8ece11a596315ebf5aa7ec383aeeed016c091d2bf6363ffb996d41529092", size = 252286 }, - { url = "https://files.pythonhosted.org/packages/dd/1e/bec5e32aa508615d9d7a2790effb25fb4dc28606e995816afe400b25ece3/coverage-7.15.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:65a6b6164ee5c39e2f3803f314292d6c61a607ba7fee253d1e03c42dc3903502", size = 254789 }, - { url = "https://files.pythonhosted.org/packages/17/29/0e865435b4354e4a7c03b1b7920046d31d0a273d55decefea27e011cb9bf/coverage-7.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75128817f95a5c45bb01d65fd2d8b9cb54bbe03d81608fb70e3e14b437ad56c2", size = 256135 }, - { url = "https://files.pythonhosted.org/packages/84/ff/33a870b58a13325d62fc0a6c8f01fa0ff667cef60c7498e2382a147dfa18/coverage-7.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9887bb428fe2d4cd4bee89bac1a6c9932f484afd5b36fbd4ff6ea5f825bb1f5e", size = 258449 }, - { url = "https://files.pythonhosted.org/packages/18/7b/6fffe596bf3ddba8462758d02c5dad730fd91055a6634aa2e4226229181a/coverage-7.15.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0bfc0be1f702042207a93a00523b1065ee1fe951e96edf311581c0bbc2e34888", size = 252313 }, - { url = "https://files.pythonhosted.org/packages/58/1b/11468dd6c1676ab831a70cb9a8d4e198e8607fa0b7220ab918b73fe9bfbd/coverage-7.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f64627d55def5a43282d70e08396672692f77e4da610a5bb8bb4060b432b6859", size = 254142 }, - { url = "https://files.pythonhosted.org/packages/79/41/29328e21d16b1b95092c30dd700e08cf915bd3734f836df8f3bdb0e8fa9f/coverage-7.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2c6f0fa473003905c6d5bac328ee4eba9fbea654f15bc24b8a3274b23363fa99", size = 252108 }, - { url = "https://files.pythonhosted.org/packages/9b/de/05ccfb990439655b35afbfd8e0d13fe66677565a7d4eb38c3f5ef2635e1c/coverage-7.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2bcf9afaf064172c6ec3c58a325a9957ad1178c05dd934e25f253321776e0676", size = 256385 }, - { url = "https://files.pythonhosted.org/packages/51/0e/486828a3d2695ea7a2609f17ff572f6b01905e608379440a11da4b8dffbe/coverage-7.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:baf06bc987115d6fb938d403f7eab684a057766c490367999a2b71a6883110c6", size = 251923 }, - { url = "https://files.pythonhosted.org/packages/18/c7/03582b6715f078e5e558354c87616d945b9894cda2dace8e4009b17035e4/coverage-7.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f0405f2ff97b1c4c0e782cb32e02f32369bcf2e6b618b591d67e1ea754575dfe", size = 253580 }, - { url = "https://files.pythonhosted.org/packages/db/dc/9e578bbaf2ecb4959a81b7e7601ad8cca772cba2892e8d144cb749b4a71a/coverage-7.15.0-cp314-cp314-win32.whl", hash = "sha256:ab282853ed5fbd64bbb162f19cb8fcb7087187508a6374b4f9c34ec1577c4e8f", size = 223107 }, - { url = "https://files.pythonhosted.org/packages/ae/3e/c8c3b75d8dbe0e35f7b0cc3ff5e949fc59500f70b21d0398813f66740664/coverage-7.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bb3040e9f4bbe26fcb0cd7cc85ac63e630d3f3a9c74f027abf4caa27e706663", size = 223597 }, - { url = "https://files.pythonhosted.org/packages/cd/bc/3cbc9fb036eb388519bccd521f783499c39b64256013fbc362782f196fe1/coverage-7.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:346771144d34f7fa84ec28386f78e0f31653f33cf35e19d253d5b35f9e8201da", size = 223020 }, - { url = "https://files.pythonhosted.org/packages/28/00/199c4a8d656dff63102577a056c0fce2ff6a79e40adac092fc986c49cbf1/coverage-7.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d34a010905fb6401324ba016b5da03d574967f7b21ce48ea41e66f0f1f95f641", size = 221638 }, - { url = "https://files.pythonhosted.org/packages/ba/8e/9d0092c96a3d3a26951ecc7020826aa57bcb1b119ca81acbba996884ab13/coverage-7.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bb25d825d885ca8036795dacfc3924d33091fc76d71ebc99420c6b79e77d96fa", size = 221903 }, - { url = "https://files.pythonhosted.org/packages/6d/b4/c0ca3028f42c9a08e51feb4561ef1192e5de99797cd1db5b04590c215bda/coverage-7.15.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:94c9686bfe8a9a6810297aecbd99beaa3445f9e8dc2f80b1382cca0d86b64461", size = 263267 }, - { url = "https://files.pythonhosted.org/packages/5f/aa/a375e3846e5d3c013dc600b2a3231089055c73d77f5393dd2192a8d64da6/coverage-7.15.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9bd671c25f9d85f09d7ec481d0e43d5139f486c06a37139847a7ce569788af72", size = 265390 }, - { url = "https://files.pythonhosted.org/packages/92/e1/5783cdabb797305e1c9e4809fea496d31834c51fa772514f73dc148bcfc9/coverage-7.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110cbdf8d2e216577312cf06ccf85539c0e5a5420ef747e4a4719b5e483c88cd", size = 267811 }, - { url = "https://files.pythonhosted.org/packages/85/31/96d8bbf58b8e9193bc8389574a91a0db48355ee98feb66aa6bf8d1b32eea/coverage-7.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2c5d4619214f1d9993e7b00a8600d14614b7e9d84e89507460b126aa5e6559e5", size = 268928 }, - { url = "https://files.pythonhosted.org/packages/5e/7a/5294567e811a1cb7eda93140c628fa050d66189da28da320f93d1d815c73/coverage-7.15.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:781a704516e2d8346fbbd5be6c6f3412dd824785146528b3a01816f26c081007", size = 262378 }, - { url = "https://files.pythonhosted.org/packages/69/3f/3f48538421f899f28946f90a3d272136a4686e1abf461cc9249a783ee0f3/coverage-7.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd4a1b44bcb65ee29e947ac92bbee04956df3a6bfc6143641bb6cae7ede00fc9", size = 265263 }, - { url = "https://files.pythonhosted.org/packages/ce/d3/092df15efcab8a9c1467ee960eb8019bbad3f9300d115d89ea6195f369ff/coverage-7.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0e4950c9d6d3e39c64c991814ff315e2d0b9cb8152363594212c9e55208c0a8f", size = 262866 }, - { url = "https://files.pythonhosted.org/packages/e5/ab/0254d2b88665efb2c57ad368cc77ab5de3435bd8d5add4729c1b0e79431e/coverage-7.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:fe9c87ff42e5472d80d21704972e1f96e104a0a599d77c5e35db5a3c562e2571", size = 266599 }, - { url = "https://files.pythonhosted.org/packages/a8/79/1cfa4023e489ce6fbc7be4a5d442dbc375edb4f4fda39a352cedb53263c2/coverage-7.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f00d5ae1dd2fe13fb8186e3e7d37bcbd8b25c0d764ff7d1b32cef9be058510a8", size = 261714 }, - { url = "https://files.pythonhosted.org/packages/b7/eb/fee5c8665656be63f497418d410484637c438172568688e8ac92e06574e7/coverage-7.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:363ab38cc78b615f11c9cac3cf1d7eef950c18b9fdedfb9066f59461dcf84d68", size = 264025 }, - { url = "https://files.pythonhosted.org/packages/ab/99/63005db722f91edc81abc16302f9cc2f6228c1679e46e15be9ae144b14d0/coverage-7.15.0-cp314-cp314t-win32.whl", hash = "sha256:54fd9c53a5fafff509195f1b6a3f9be615d8e8362a3629ff1de23d270c03c86b", size = 223413 }, - { url = "https://files.pythonhosted.org/packages/c1/e8/2bc6181c4fb06f1a6b981eb85330cc57bfad7e3f710fc9c9d350013ba228/coverage-7.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:87b47553097ba185ed964866078e7e63adea9f5f51b5f39691c34f30afd21080", size = 224245 }, - { url = "https://files.pythonhosted.org/packages/79/b8/4d959bf9cc45d0cfed2f4d35cafcab978cdb6ea02eb5100009cd740632a3/coverage-7.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aeefb2dd178fe7eee79f0ad25d75855cb35ee9ed472db2c5ea06f5b4fd00cec5", size = 223558 }, - { url = "https://files.pythonhosted.org/packages/52/30/21b2ad45959cd50e909e02ebac1e30b4ceb7162e91c11d4c570223a458b7/coverage-7.15.0-py3-none-any.whl", hash = "sha256:56da6a4cbe8f7e9e80bd072ca9cefe67d7106a440a7ec06519ec6507ac94ad19", size = 212632 }, + { url = "https://files.pythonhosted.org/packages/2a/97/c52dc440c390b6cfa87be9432b141a956e2d56d9b9f5fc8bd71c5f471722/coverage-7.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50913d4bf5ddafa6ca3693da5e4dd833dd1b772e0283c99ca7f7d287db67331a", size = 220539, upload-time = "2026-07-02T13:08:19.252Z" }, + { url = "https://files.pythonhosted.org/packages/3f/26/602de8c2aec7e2e3e99ebfb8e04ba65598f746275396eea5f6794ff4673f/coverage-7.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:359e141ccd33893ce3f1ad5525f8b96083003677c82182e5907d62d4ea5799fc", size = 221058, upload-time = "2026-07-02T13:08:21.013Z" }, + { url = "https://files.pythonhosted.org/packages/fc/13/ebab0743138891c1d646d61e247ec29639afcbb6c4e1905e6a0f0c75291a/coverage-7.15.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3200b6204935f928c64b2ca1f923ab8c1acb7c9de45ec61569711b34d25cccaf", size = 247797, upload-time = "2026-07-02T13:08:22.474Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b7/b6ffb9e042aa48dc4144a8a65529affaec8dca0685309353614a2a7386ad/coverage-7.15.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:be616bf61346883b2cfdc5178669647e03531d81ab761a7e378558b7e8bcb628", size = 249626, upload-time = "2026-07-02T13:08:23.803Z" }, + { url = "https://files.pythonhosted.org/packages/9c/06/243ff05b652333d8e3d060c11223efc2723b19cacf6605e433fa686ab5d4/coverage-7.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7bafc3fe1059463a8fdd97ca79972d6e2bf819d775c7d54991b5b1971201d6", size = 251493, upload-time = "2026-07-02T13:08:25.397Z" }, + { url = "https://files.pythonhosted.org/packages/d3/2b/867faa17030a806114dae388b32a3fa929d8cd4bf39226fbc11f6e6bb705/coverage-7.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b713aa7fcf325a01d4184d848acb46fd84f78fdb0978470c636b23a06a753d91", size = 253406, upload-time = "2026-07-02T13:08:26.842Z" }, + { url = "https://files.pythonhosted.org/packages/94/c0/d789ce18f6605afc4895db75723424be2ef494282f77f61d8e5832923183/coverage-7.15.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e38e6fba2d56652fdfaf0231f8f78aeb805234a912de25dc291ee5cce5b8faa4", size = 248512, upload-time = "2026-07-02T13:08:28.398Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b6/b2673c30739f4a2e06649a0a38ad8b093c4d865462dc7bab0e9524a2c3b1/coverage-7.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:884499f42e382675be80770391983b90e0c0c774d87dbeeebf5f991cf6612b20", size = 249532, upload-time = "2026-07-02T13:08:29.731Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/acd79e9a41beabee92b623afe4f30b549916f48566271475f2907e752828/coverage-7.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:840481b12e083dbcbafab14794a8781a958edf327c8d3d70b4eee42f9b8253aa", size = 247537, upload-time = "2026-07-02T13:08:31.173Z" }, + { url = "https://files.pythonhosted.org/packages/12/d4/2d301c4d1b3238d7c88b70ab9d13fd53ed9505662a7ff1b46ba1e2e4e3c3/coverage-7.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:276646e9481703d09f854f3b2f018f24e19fd7049ae670a92570043eb97203b1", size = 251348, upload-time = "2026-07-02T13:08:32.63Z" }, + { url = "https://files.pythonhosted.org/packages/35/bb/c67708b2bc00f32e12805ec23d5fa677a0a51652f449341a89f9d6b1b715/coverage-7.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4de4b4d3f5545aa6c60dc4efd9c63b5b5dcc3bf00fe83146b2bdfffb8f6613bd", size = 247806, upload-time = "2026-07-02T13:08:33.931Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6c/57c4f653c47a6e917748f8938e389e72fbcae44e3643cd906664f0477a13/coverage-7.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5c504097b2a89b1e85bc6070d920df77daec701337e3aeef2c17775a5dd0ca90", size = 248410, upload-time = "2026-07-02T13:08:35.189Z" }, + { url = "https://files.pythonhosted.org/packages/6c/94/bb083041aef828903668f134273f319f2bd49224962875359c52faa5497f/coverage-7.15.0-cp310-cp310-win32.whl", hash = "sha256:f6e80ed91f98316e86b9c137206b04b2bcfbffccbdff49bd2eb09dddb1cf14e0", size = 222588, upload-time = "2026-07-02T13:08:36.486Z" }, + { url = "https://files.pythonhosted.org/packages/ef/94/a09d8ee618956f626741b0734854bac4425a00e10c0565f5abca64e7e751/coverage-7.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:b3b3e22030f3f6f5e01a5ce69936552a5c0f6992b7698777377b99041961031f", size = 223214, upload-time = "2026-07-02T13:08:37.885Z" }, + { url = "https://files.pythonhosted.org/packages/ae/23/82e910835ef4b8391047025e1d53aa48d66029f444eb8b25373c849bf503/coverage-7.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:003fff99412ea848c0aaebcc78ed2b6ce7d8a1227ed17e68470672770b78a02a", size = 220662, upload-time = "2026-07-02T13:08:39.205Z" }, + { url = "https://files.pythonhosted.org/packages/6d/0d/c7b213dde2f1579de5231062b386d8413f79c11667eb58c39319b25991da/coverage-7.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5cbd804bf2784ce7b45114516050f346ecd50f960c4bb630a7ee9e1d78fa2118", size = 221168, upload-time = "2026-07-02T13:08:40.471Z" }, + { url = "https://files.pythonhosted.org/packages/33/77/d000aeedfac085088337b3c7becdad328474b1f8a9e4c9368a0c99605d68/coverage-7.15.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8773e15c23305b58882a4611fb9b2755977eae0dc2e515366a1b6c98866cc4c2", size = 251587, upload-time = "2026-07-02T13:08:42.033Z" }, + { url = "https://files.pythonhosted.org/packages/cc/e0/86787c56b9df17afd370d5e293515dd4d9a107a561d13054873eefad8ecc/coverage-7.15.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f50e40081494c1dc4239ebb202014cbcc3306ea96fb6302a34c8cc0967fc5ae8", size = 253497, upload-time = "2026-07-02T13:08:43.387Z" }, + { url = "https://files.pythonhosted.org/packages/3f/02/181bc917359299c07dead6270f94e411151c8b60cec905c33499da69afe6/coverage-7.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daf96f37f5fc3a7b6c6da862eb4aee61c426bd63da236ed4a73ef0e503b4bca5", size = 255607, upload-time = "2026-07-02T13:08:44.897Z" }, + { url = "https://files.pythonhosted.org/packages/b9/35/ca5e7427699913da6788c4f910e73ab16c5f4b59ec5d3a999dce2a45112f/coverage-7.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:51aa20f6ae2788fd197747766edf4cd8234fd9423309b934257fa6b21a592723", size = 257563, upload-time = "2026-07-02T13:08:46.334Z" }, + { url = "https://files.pythonhosted.org/packages/0b/4d/b8220bacc2fc3c4e9078e27c32e99fb411479a4718a72bdd00036a9891c8/coverage-7.15.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03d1f922757662eb7af586e77834792274cff776bc7b1d1a0b66a49ea9d84735", size = 251726, upload-time = "2026-07-02T13:08:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e4/2e145da1991d72189b9c3cf7eca05c716ee7080d099aaea6757cfc7df008/coverage-7.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a6d6acc9a7666245e6133dd15144ca038a85a9cd5026bb06d6bbae9e77440dc9", size = 253301, upload-time = "2026-07-02T13:08:49.5Z" }, + { url = "https://files.pythonhosted.org/packages/72/28/d2c841d698bf762e481f08bd4839d370246b6d9b61dab085a7b20b201a08/coverage-7.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ac2c4c27c7df851dc9a017c2d7de00b69147e84ba3d96f37a530b0b6fb51035", size = 251361, upload-time = "2026-07-02T13:08:51.304Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ed/55d9ffde994fba3897c0c783f77a7d053b0c18787f6892ed5b0aed73f469/coverage-7.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b761a1d504fd4bd1f20f418753964dca9f5862a511fc854dac58296b3b223671", size = 255129, upload-time = "2026-07-02T13:08:52.661Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c0/ecbf33b8c460ea2718aeb813e2df8140d0370e5f67261c31524ceb0a2a8d/coverage-7.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e43b045e11c16e897895758ae90e4a90cf99e93d58549e2f90c0e2272e155695", size = 251081, upload-time = "2026-07-02T13:08:54.188Z" }, + { url = "https://files.pythonhosted.org/packages/a9/de/fb87b4261f54448dd2b9504ef19a58be42cef0d9520595fbfe1219b15234/coverage-7.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589b54513e901739f4b4582c705ce96b80c96f57641b1464607e2367a270e540", size = 251988, upload-time = "2026-07-02T13:08:55.726Z" }, + { url = "https://files.pythonhosted.org/packages/df/27/3494d5f291b9a4cb868f73c11221a8bd2d5bd761a8f9acea61ff57128dd1/coverage-7.15.0-cp311-cp311-win32.whl", hash = "sha256:106781b8482749162d0b47056937ba0933508e5d9447f65a5e7d5c422f0d6bb4", size = 222754, upload-time = "2026-07-02T13:08:57.091Z" }, + { url = "https://files.pythonhosted.org/packages/2a/ee/cd4847ebc9be6a9c0123d763645a6f1f3be6b8c58c962706368b79cbac07/coverage-7.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:821e92b3631d762a339695824cadbbc73020354eba2a23a551a99ad34938fbe6", size = 223225, upload-time = "2026-07-02T13:08:58.594Z" }, + { url = "https://files.pythonhosted.org/packages/57/37/5011581aa7f2be498b97dcc7c9902192442a42f4f9a748aeadb3d6506b42/coverage-7.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:309990eb5fb8014b9f67cb211f7fd41876ec8a88a88d3ae76de0ed1d611e3640", size = 222774, upload-time = "2026-07-02T13:09:00.074Z" }, + { url = "https://files.pythonhosted.org/packages/2a/74/fd4c0901137c4f8d81a76ada99e43c65163b4c94a02ece107a4ec0c6b615/coverage-7.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b75ee5e8cb7575636ac598719b4307ac529ec8fcd79608a35c3cd4d4dada812d", size = 220838, upload-time = "2026-07-02T13:09:02.084Z" }, + { url = "https://files.pythonhosted.org/packages/0f/2e/2347583467bd7f0402635101a916961915cc68fce652cd0db5f173ea04fc/coverage-7.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffb31267816b93b075302248cc1737506081b4f163df4401e9df1a6424aafabe", size = 221197, upload-time = "2026-07-02T13:09:03.617Z" }, + { url = "https://files.pythonhosted.org/packages/f0/17/99fa688541ae1d6e84543a0e544f83de0c944815b63e9e7b1ed411d15036/coverage-7.15.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e4d0bb73455bf97ab243a8f12c37c686ccf1c13bb614b7b85f1d062f06f42b2c", size = 252705, upload-time = "2026-07-02T13:09:05.059Z" }, + { url = "https://files.pythonhosted.org/packages/fb/02/6a95a5cd83b74839017ef9cf48d2d8c9ae60af919e17a3f336e6f9f1b7bd/coverage-7.15.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:20d9ccc4ebd0edc434d86dfd2a1dd2a8efa6b6b3073d0485a394fee86459ebb4", size = 255441, upload-time = "2026-07-02T13:09:06.559Z" }, + { url = "https://files.pythonhosted.org/packages/67/f2/406f6c57d600f68185942422c4c00f1a3255d60aee6e5fd961425cd9987e/coverage-7.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c8a976c365c8cb12f0cbd099508772ea41fb5fa80657a8506df0e11bd278c5", size = 256556, upload-time = "2026-07-02T13:09:08.197Z" }, + { url = "https://files.pythonhosted.org/packages/74/8e/d3fa48489c15ecdec1ba48fd61f68798555dddd2f6716f9ad42adeb1a2a9/coverage-7.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f948fd5ba1b9cbca91f0ae08b4c1ce2b139509149a435e2585d056d57d70bf01", size = 258815, upload-time = "2026-07-02T13:09:09.691Z" }, + { url = "https://files.pythonhosted.org/packages/47/2e/2d40ddd110462c6a2769677cf7f1c119a52b45f568978fc6c98e4cc0dd0f/coverage-7.15.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f58185f06edf6ad68ec9fb155d63ef650c82f3fbd7e1770e2867751fb13158f4", size = 253117, upload-time = "2026-07-02T13:09:11.212Z" }, + { url = "https://files.pythonhosted.org/packages/51/c0/310782f0d7c3cb2b5ac05ba8d205fe91f24a36f6bf3256098f1782181c38/coverage-7.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02adc79a920c73c647c5d117f55747df7f2de94571884758ce8bc58e04f0a796", size = 254475, upload-time = "2026-07-02T13:09:13.029Z" }, + { url = "https://files.pythonhosted.org/packages/86/f7/702da6c275f8ae6ade423d2877243122932c9b27f5403003b9ef8c927d12/coverage-7.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6eb7c300fbed667fd6e3588eba71c1904cdb06110ca6fdf908c26bdd88b8e382", size = 252619, upload-time = "2026-07-02T13:09:14.699Z" }, + { url = "https://files.pythonhosted.org/packages/fb/84/c5b15a7e5ecba4e56218d772d99fe80a63e63f8d11f12783723a6005ab45/coverage-7.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b5fb23fa2de9dce1f5c36c09066d8fcda16cd96e8e26686caa2d7cb9b567d65c", size = 256689, upload-time = "2026-07-02T13:09:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/95/2f/c8b07559b57701230c61b23a953858c052890c12ef568d81780c6c46e92e/coverage-7.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cec79341dbe6281484024979976d0c7f22beae08b4a254655decd25d42cbe766", size = 252189, upload-time = "2026-07-02T13:09:17.828Z" }, + { url = "https://files.pythonhosted.org/packages/6b/80/6d2f049dd3fd3dbfd60b62ba6b2162a04009e2c002ce70b24cf3878dec7a/coverage-7.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c664c5444b1d970b1b2a450e21fb19ee5c9cfdf151ded2dda37260031cca0da", size = 254059, upload-time = "2026-07-02T13:09:19.304Z" }, + { url = "https://files.pythonhosted.org/packages/ce/92/b0287a2c42031d25c628f815f89a3cd9f8268ee78bb1252c9356cda1c689/coverage-7.15.0-cp312-cp312-win32.whl", hash = "sha256:5f764a3fa339bde6b3aa97657f5a6a3a9451e4a5b4ea98a2892c773a43525f77", size = 222893, upload-time = "2026-07-02T13:09:20.812Z" }, + { url = "https://files.pythonhosted.org/packages/a9/69/e34c481915fecb499b3146975061dac528752e37706edc1804f32c822469/coverage-7.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:52f9a4d2c4c56c8848bc2f524916698354b0211488b38c49ad9ae54f6cafbff6", size = 223429, upload-time = "2026-07-02T13:09:22.315Z" }, + { url = "https://files.pythonhosted.org/packages/fe/98/6e878f0b571d32684ef3f38d7c03db241ca5b82a5da8a5391596a8f209c4/coverage-7.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:31e5c3e70c85307ea35a12964e2e40f56ca2ee4b1c8c721ccf4609d17071080b", size = 222810, upload-time = "2026-07-02T13:09:23.812Z" }, + { url = "https://files.pythonhosted.org/packages/76/04/145a3748098bcc86b631a85408d2c3dc5c104e0bd86d605468239b25b6c4/coverage-7.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be4caf3b28836f078abe700f8944dac4a65d78f16d6c600c89cb624e5535782", size = 220863, upload-time = "2026-07-02T13:09:25.371Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5c/4ed55708fed2c64b63c9bc5715daef670872202101938869b7fe5d5fbb8f/coverage-7.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dd58ad1404704303ca8d4f4b8a1095e7cbc7040ef17a66df1e6619aa10176430", size = 221230, upload-time = "2026-07-02T13:09:26.897Z" }, + { url = "https://files.pythonhosted.org/packages/7b/19/3a80b97d3b2a5c77a01ae359c6bed20c13738fe3d9380f08616d4fec0281/coverage-7.15.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bbcbb317c2e5ded5b21104af81c29f391be2af98d065693ffbe8d23949b948e5", size = 252227, upload-time = "2026-07-02T13:09:28.543Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/b70062750686bd7da454da27927622f48bbac6990ac7a4c4a4653e7b0036/coverage-7.15.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:27f31ecb458da3f859aab3f15ada871eb7a7768807d88df4a9f186bb17737970", size = 254823, upload-time = "2026-07-02T13:09:30.177Z" }, + { url = "https://files.pythonhosted.org/packages/a9/09/dad6a75a2e561b9dc5086a8c5257a7591d584246f67e23e70d2995b89ab6/coverage-7.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fb759be317fdc62e0f56bffdf61cfcb45c7761ad6b71e3e583e71a67ae753c", size = 256059, upload-time = "2026-07-02T13:09:31.979Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e7/b5d2941fa9564573d44b693a871ff3156f0c42cbefe977a09fa7fdc59971/coverage-7.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5cf007add5ab4bb8fa9f4c77e3732127c9e6cad501d7db43355fbfafca0be84", size = 258190, upload-time = "2026-07-02T13:09:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/7c/1d/8e895bcde3c57ccd46d896dda5f2b3d5df761a1b0c6c9d450d175dedc632/coverage-7.15.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc78d9843bd576fbe2118248258d485e968dc535f95ed504a7b0867ba9b51389", size = 252456, upload-time = "2026-07-02T13:09:35.765Z" }, + { url = "https://files.pythonhosted.org/packages/14/4c/f6997da343ddeb959be82c3b05322793f92c071ad45f7cb8a96336e2dd5f/coverage-7.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a263060f1de0b4b74b4e089c2a70b8003b3781c733329a9c8fd54995328f9950", size = 254192, upload-time = "2026-07-02T13:09:37.445Z" }, + { url = "https://files.pythonhosted.org/packages/17/27/a0bc09d032267b9da89d95a2d874cfbef2a5aebbf0e87cf7aba221d79a99/coverage-7.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c48decf16e0dfd5b049c7d5e82200c23c08126719142998d4f172444e3d0529e", size = 252153, upload-time = "2026-07-02T13:09:39.422Z" }, + { url = "https://files.pythonhosted.org/packages/54/c0/77fc233d9fba07b244c40948c53fe27308b8f21732fb3417f87fbd6fd992/coverage-7.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08fb028000ed0aaa0a4cbdfbb98be7cb42f370db973fbbb469733505ab20e13e", size = 256310, upload-time = "2026-07-02T13:09:41.006Z" }, + { url = "https://files.pythonhosted.org/packages/d5/24/601cecfb5825becacb8d45219a018a3b55b9dbaec624efdb0ea249d08be2/coverage-7.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb7dc0c3b7d8a1077abea0b8546ebc5e26d6ef6ecefc2f0f5ad2b8a53bdad837", size = 251974, upload-time = "2026-07-02T13:09:42.733Z" }, + { url = "https://files.pythonhosted.org/packages/47/1e/6f45e5a5b3d5484318d368702af6716b5ab8913b0428bec981a562fcf296/coverage-7.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cb3602054ccbe9f0d8c2dc04bbeba90d5719236e2cd06e042ddd6d3fc7b6e37", size = 253745, upload-time = "2026-07-02T13:09:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/8e/db/4df027a77bd11d0e527f44c53557c76e54ad027413d0304252ea3a78d67e/coverage-7.15.0-cp313-cp313-win32.whl", hash = "sha256:0bf781da64326b677be344df505171435b6f58716108606621d5d27d964fff8b", size = 222902, upload-time = "2026-07-02T13:09:46.122Z" }, + { url = "https://files.pythonhosted.org/packages/a0/10/0355894d34e231f2c5449e71287e81a50793a325df2e2b027b7bcd9dfd19/coverage-7.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:2c57a275078ee3fa185f83e400f765bc764a549de66d99b47881645cbd4ea629", size = 223444, upload-time = "2026-07-02T13:09:47.687Z" }, + { url = "https://files.pythonhosted.org/packages/06/ef/bb725f263befaaff851203ab338e68af15e195d7f7b5f323162532d9b6a8/coverage-7.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:3812c61afc6685c7999b39320779ab8f43b7a3081fdb0def39976e56fbdb9a21", size = 222839, upload-time = "2026-07-02T13:09:49.717Z" }, + { url = "https://files.pythonhosted.org/packages/4f/9c/1e3ca54f72a3185ece06c58d871099898c48f0ed6430d17b6ab75f0d180a/coverage-7.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:41cb79af843222e11da87127ad0ecbfa878abadd0f770a4a99391a27d3887324", size = 220906, upload-time = "2026-07-02T13:09:51.339Z" }, + { url = "https://files.pythonhosted.org/packages/09/37/f718613d83b274880382f6b67e78f3802549ae39b0b3e65ae5b5974df56e/coverage-7.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d2008989ef8fe54188d3f3bfa2e3099b025af11e90a6a1b9e7dc433d04263d8", size = 221239, upload-time = "2026-07-02T13:09:53.138Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/22bae91e0b75445f68d365c7643ed0aa4880bbf77450ee74ca65bdae53a7/coverage-7.15.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:769e8ece11a596315ebf5aa7ec383aeeed016c091d2bf6363ffb996d41529092", size = 252286, upload-time = "2026-07-02T13:09:54.996Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1e/bec5e32aa508615d9d7a2790effb25fb4dc28606e995816afe400b25ece3/coverage-7.15.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:65a6b6164ee5c39e2f3803f314292d6c61a607ba7fee253d1e03c42dc3903502", size = 254789, upload-time = "2026-07-02T13:09:56.678Z" }, + { url = "https://files.pythonhosted.org/packages/17/29/0e865435b4354e4a7c03b1b7920046d31d0a273d55decefea27e011cb9bf/coverage-7.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75128817f95a5c45bb01d65fd2d8b9cb54bbe03d81608fb70e3e14b437ad56c2", size = 256135, upload-time = "2026-07-02T13:09:58.343Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/33a870b58a13325d62fc0a6c8f01fa0ff667cef60c7498e2382a147dfa18/coverage-7.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9887bb428fe2d4cd4bee89bac1a6c9932f484afd5b36fbd4ff6ea5f825bb1f5e", size = 258449, upload-time = "2026-07-02T13:10:00.057Z" }, + { url = "https://files.pythonhosted.org/packages/18/7b/6fffe596bf3ddba8462758d02c5dad730fd91055a6634aa2e4226229181a/coverage-7.15.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0bfc0be1f702042207a93a00523b1065ee1fe951e96edf311581c0bbc2e34888", size = 252313, upload-time = "2026-07-02T13:10:01.946Z" }, + { url = "https://files.pythonhosted.org/packages/58/1b/11468dd6c1676ab831a70cb9a8d4e198e8607fa0b7220ab918b73fe9bfbd/coverage-7.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f64627d55def5a43282d70e08396672692f77e4da610a5bb8bb4060b432b6859", size = 254142, upload-time = "2026-07-02T13:10:04.065Z" }, + { url = "https://files.pythonhosted.org/packages/79/41/29328e21d16b1b95092c30dd700e08cf915bd3734f836df8f3bdb0e8fa9f/coverage-7.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2c6f0fa473003905c6d5bac328ee4eba9fbea654f15bc24b8a3274b23363fa99", size = 252108, upload-time = "2026-07-02T13:10:06.11Z" }, + { url = "https://files.pythonhosted.org/packages/9b/de/05ccfb990439655b35afbfd8e0d13fe66677565a7d4eb38c3f5ef2635e1c/coverage-7.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2bcf9afaf064172c6ec3c58a325a9957ad1178c05dd934e25f253321776e0676", size = 256385, upload-time = "2026-07-02T13:10:08.141Z" }, + { url = "https://files.pythonhosted.org/packages/51/0e/486828a3d2695ea7a2609f17ff572f6b01905e608379440a11da4b8dffbe/coverage-7.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:baf06bc987115d6fb938d403f7eab684a057766c490367999a2b71a6883110c6", size = 251923, upload-time = "2026-07-02T13:10:10.179Z" }, + { url = "https://files.pythonhosted.org/packages/18/c7/03582b6715f078e5e558354c87616d945b9894cda2dace8e4009b17035e4/coverage-7.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f0405f2ff97b1c4c0e782cb32e02f32369bcf2e6b618b591d67e1ea754575dfe", size = 253580, upload-time = "2026-07-02T13:10:12.052Z" }, + { url = "https://files.pythonhosted.org/packages/db/dc/9e578bbaf2ecb4959a81b7e7601ad8cca772cba2892e8d144cb749b4a71a/coverage-7.15.0-cp314-cp314-win32.whl", hash = "sha256:ab282853ed5fbd64bbb162f19cb8fcb7087187508a6374b4f9c34ec1577c4e8f", size = 223107, upload-time = "2026-07-02T13:10:13.994Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3e/c8c3b75d8dbe0e35f7b0cc3ff5e949fc59500f70b21d0398813f66740664/coverage-7.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bb3040e9f4bbe26fcb0cd7cc85ac63e630d3f3a9c74f027abf4caa27e706663", size = 223597, upload-time = "2026-07-02T13:10:15.906Z" }, + { url = "https://files.pythonhosted.org/packages/cd/bc/3cbc9fb036eb388519bccd521f783499c39b64256013fbc362782f196fe1/coverage-7.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:346771144d34f7fa84ec28386f78e0f31653f33cf35e19d253d5b35f9e8201da", size = 223020, upload-time = "2026-07-02T13:10:17.844Z" }, + { url = "https://files.pythonhosted.org/packages/28/00/199c4a8d656dff63102577a056c0fce2ff6a79e40adac092fc986c49cbf1/coverage-7.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d34a010905fb6401324ba016b5da03d574967f7b21ce48ea41e66f0f1f95f641", size = 221638, upload-time = "2026-07-02T13:10:19.703Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8e/9d0092c96a3d3a26951ecc7020826aa57bcb1b119ca81acbba996884ab13/coverage-7.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bb25d825d885ca8036795dacfc3924d33091fc76d71ebc99420c6b79e77d96fa", size = 221903, upload-time = "2026-07-02T13:10:21.514Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b4/c0ca3028f42c9a08e51feb4561ef1192e5de99797cd1db5b04590c215bda/coverage-7.15.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:94c9686bfe8a9a6810297aecbd99beaa3445f9e8dc2f80b1382cca0d86b64461", size = 263267, upload-time = "2026-07-02T13:10:23.261Z" }, + { url = "https://files.pythonhosted.org/packages/5f/aa/a375e3846e5d3c013dc600b2a3231089055c73d77f5393dd2192a8d64da6/coverage-7.15.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9bd671c25f9d85f09d7ec481d0e43d5139f486c06a37139847a7ce569788af72", size = 265390, upload-time = "2026-07-02T13:10:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/92/e1/5783cdabb797305e1c9e4809fea496d31834c51fa772514f73dc148bcfc9/coverage-7.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110cbdf8d2e216577312cf06ccf85539c0e5a5420ef747e4a4719b5e483c88cd", size = 267811, upload-time = "2026-07-02T13:10:27.249Z" }, + { url = "https://files.pythonhosted.org/packages/85/31/96d8bbf58b8e9193bc8389574a91a0db48355ee98feb66aa6bf8d1b32eea/coverage-7.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2c5d4619214f1d9993e7b00a8600d14614b7e9d84e89507460b126aa5e6559e5", size = 268928, upload-time = "2026-07-02T13:10:29.242Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7a/5294567e811a1cb7eda93140c628fa050d66189da28da320f93d1d815c73/coverage-7.15.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:781a704516e2d8346fbbd5be6c6f3412dd824785146528b3a01816f26c081007", size = 262378, upload-time = "2026-07-02T13:10:31.107Z" }, + { url = "https://files.pythonhosted.org/packages/69/3f/3f48538421f899f28946f90a3d272136a4686e1abf461cc9249a783ee0f3/coverage-7.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd4a1b44bcb65ee29e947ac92bbee04956df3a6bfc6143641bb6cae7ede00fc9", size = 265263, upload-time = "2026-07-02T13:10:32.942Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d3/092df15efcab8a9c1467ee960eb8019bbad3f9300d115d89ea6195f369ff/coverage-7.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0e4950c9d6d3e39c64c991814ff315e2d0b9cb8152363594212c9e55208c0a8f", size = 262866, upload-time = "2026-07-02T13:10:35.104Z" }, + { url = "https://files.pythonhosted.org/packages/e5/ab/0254d2b88665efb2c57ad368cc77ab5de3435bd8d5add4729c1b0e79431e/coverage-7.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:fe9c87ff42e5472d80d21704972e1f96e104a0a599d77c5e35db5a3c562e2571", size = 266599, upload-time = "2026-07-02T13:10:37.05Z" }, + { url = "https://files.pythonhosted.org/packages/a8/79/1cfa4023e489ce6fbc7be4a5d442dbc375edb4f4fda39a352cedb53263c2/coverage-7.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f00d5ae1dd2fe13fb8186e3e7d37bcbd8b25c0d764ff7d1b32cef9be058510a8", size = 261714, upload-time = "2026-07-02T13:10:38.966Z" }, + { url = "https://files.pythonhosted.org/packages/b7/eb/fee5c8665656be63f497418d410484637c438172568688e8ac92e06574e7/coverage-7.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:363ab38cc78b615f11c9cac3cf1d7eef950c18b9fdedfb9066f59461dcf84d68", size = 264025, upload-time = "2026-07-02T13:10:40.789Z" }, + { url = "https://files.pythonhosted.org/packages/ab/99/63005db722f91edc81abc16302f9cc2f6228c1679e46e15be9ae144b14d0/coverage-7.15.0-cp314-cp314t-win32.whl", hash = "sha256:54fd9c53a5fafff509195f1b6a3f9be615d8e8362a3629ff1de23d270c03c86b", size = 223413, upload-time = "2026-07-02T13:10:42.597Z" }, + { url = "https://files.pythonhosted.org/packages/c1/e8/2bc6181c4fb06f1a6b981eb85330cc57bfad7e3f710fc9c9d350013ba228/coverage-7.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:87b47553097ba185ed964866078e7e63adea9f5f51b5f39691c34f30afd21080", size = 224245, upload-time = "2026-07-02T13:10:44.47Z" }, + { url = "https://files.pythonhosted.org/packages/79/b8/4d959bf9cc45d0cfed2f4d35cafcab978cdb6ea02eb5100009cd740632a3/coverage-7.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aeefb2dd178fe7eee79f0ad25d75855cb35ee9ed472db2c5ea06f5b4fd00cec5", size = 223558, upload-time = "2026-07-02T13:10:46.368Z" }, + { url = "https://files.pythonhosted.org/packages/52/30/21b2ad45959cd50e909e02ebac1e30b4ceb7162e91c11d4c570223a458b7/coverage-7.15.0-py3-none-any.whl", hash = "sha256:56da6a4cbe8f7e9e80bd072ca9cefe67d7106a440a7ec06519ec6507ac94ad19", size = 212632, upload-time = "2026-07-02T13:10:48.641Z" }, ] [package.optional-dependencies] @@ -341,160 +343,160 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "toolz" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bd/d4/16916f3dc20a3f5455b63c35dcb260b3716f59ce27a93586804e70e431d5/cytoolz-1.1.0.tar.gz", hash = "sha256:13a7bf254c3c0d28b12e2290b82aed0f0977a4c2a2bf84854fcdc7796a29f3b0", size = 642510 } +sdist = { url = "https://files.pythonhosted.org/packages/bd/d4/16916f3dc20a3f5455b63c35dcb260b3716f59ce27a93586804e70e431d5/cytoolz-1.1.0.tar.gz", hash = "sha256:13a7bf254c3c0d28b12e2290b82aed0f0977a4c2a2bf84854fcdc7796a29f3b0", size = 642510, upload-time = "2025-10-19T00:44:56.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/7a/3244e6e3587be9abfee3b1c320e43a279831b3c3a31fe5d08c1ee6193e6b/cytoolz-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:72d7043a88ea5e61ba9d17ea0d1c1eff10f645d7edfcc4e56a31ef78be287644", size = 1307813 }, - { url = "https://files.pythonhosted.org/packages/32/7e/eaf504ca59addce323ef4d4ffedc2913d83c121ec19f6419bc402f7702dc/cytoolz-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d759e9ed421bacfeb456d47af8d734c057b9912b5f2441f95b27ca35e5efab07", size = 985777 }, - { url = "https://files.pythonhosted.org/packages/d4/a1/ec95443f0cf4cd0dbc574fa26ac85a0442d35f3b601a90a0e3dda077f614/cytoolz-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fdb5be8fbcc0396141189022724155a4c1c93712ac4aef8c03829af0c2a816d7", size = 982865 }, - { url = "https://files.pythonhosted.org/packages/a7/1b/8503604b0c0534977363fb77d371019395dfa031a216f9b1d8729d1280e4/cytoolz-1.1.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c8c0a513dc89bc05cc72893609118815bced5ef201f1a317b4cc3423b3a0e750", size = 2597969 }, - { url = "https://files.pythonhosted.org/packages/4e/e5/30748da06417cb2d4bc58e380b0c11d8c6539f4e289dc1e4f4b4fc248d0e/cytoolz-1.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce94db4f8ebe842c30c0ece42ff5de977c47859088c2c363dede5a68f6906484", size = 2692230 }, - { url = "https://files.pythonhosted.org/packages/d6/84/e06580b74deb97dfd3513e4e6b660c2dedc220c7653f5bd3e4f772f4d885/cytoolz-1.1.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b622d4f54e370c853ded94a668f94fe72c6d70e06ac102f17a2746661c27ab52", size = 2565243 }, - { url = "https://files.pythonhosted.org/packages/91/5e/79c0122a34c33afcb5aaee1fec35be24fe16cecefb9bb8890f2908feae56/cytoolz-1.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:375a65baa5a5b4ff6a0c5ff17e170cf23312e4c710755771ca966144c24216b5", size = 2868602 }, - { url = "https://files.pythonhosted.org/packages/3f/84/404698ff02b32292db1e39cc4a2fbdabe15164b092cc364902984c3ce0f4/cytoolz-1.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c0d51bcdb3203a062a78f66bbe33db5e3123048e24a5f0e1402422d79df8ee2d", size = 2905121 }, - { url = "https://files.pythonhosted.org/packages/9f/33/afad6593829ba73fc87b5ae64441e380fc937f79f24a1cda60d23cb99b8c/cytoolz-1.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1010869529bb05dc9802b6d776a34ca1b6d48b9deec70ad5e2918ae175be5c2f", size = 2684382 }, - { url = "https://files.pythonhosted.org/packages/ce/86/7900013a82ca9c6cadbfb22bf50d0fbfc3b192915d2bdd9fab3f69a9afba/cytoolz-1.1.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11a8f2e83295bdb33f35454d6bafcb7845b03b5881dcaed66ecbd726c7f16772", size = 2518183 }, - { url = "https://files.pythonhosted.org/packages/c3/4b/acf9be2953fed6a6d795fb66de37c367915037a998a5b3d3b69476cf91fe/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0499c5e0a8e688ed367a2e51cc13792ae8f08226c15f7d168589fc44b9b9cada", size = 2609368 }, - { url = "https://files.pythonhosted.org/packages/fd/ec/3e30455fd526f5cc37bd3dd2a0e2aafb803ae4d271e50ce53bfc30810053/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:87d44e6033d4c5e95a7d39ba59b8e105ba1c29b1ccd1d215f26477cc1d64be39", size = 2561458 }, - { url = "https://files.pythonhosted.org/packages/49/27/e5815c85bb18cdf95780f9596dcfd76dee910a4d635a1924648cb8a636c6/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a68cef396a7de237f7b97422a6a450dfb111722296ba217ba5b34551832f1f6e", size = 2578236 }, - { url = "https://files.pythonhosted.org/packages/17/db/588e266eff397670398ea335a809152e77b02ee92e0ec42091115b42f09b/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:06ad4c95b258141f138a93ebfdc1d76ac087afc1a82f1401100a1f44b44ba656", size = 2770523 }, - { url = "https://files.pythonhosted.org/packages/ab/ad/82be0b999c7a0a0b362cedfc183eb090b872fd42937af2d6e97d58bc70f8/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ada59a4b3c59d4ac7162e0ed08667ffa78abf48e975c8a9f9d5b9bc50720f4fd", size = 2512909 }, - { url = "https://files.pythonhosted.org/packages/25/21/45f07ab0339a20c518bc9006100922babc397ab7ea5ef40a395db83b9cdd/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a8957bcaea1ba01327a9b219d2adb84144377684f51444253890dab500ca171f", size = 2755345 }, - { url = "https://files.pythonhosted.org/packages/8b/a7/e530bf2b304206f79b36d793caba1ff9448348713a41bb1ad0197714a0f2/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6d8cdc299d67eb0f3b9ecdafeeb55eb3b7b7470e2d950ac34b05ed4c7a5572b8", size = 2617790 }, - { url = "https://files.pythonhosted.org/packages/9f/77/7f53092121d7431589344c7d65c3d43c4111547aafabb21d3ca9032d126c/cytoolz-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d8e08464c5cdea4f6df31e84b11ed6bfd79cedb99fbcbfdc15eb9361a6053c5a", size = 900209 }, - { url = "https://files.pythonhosted.org/packages/84/e4/902578658303b9bc76b1704d3ed85e6d307d311bd9fa0b919581bea56e62/cytoolz-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7e49922a7ed54262d41960bf3b835a7700327bf79cff1e9bfc73d79021132ff8", size = 944802 }, - { url = "https://files.pythonhosted.org/packages/71/9f/56a7003617b4eabd8ddfb470aacc240425cbe6ddeb756adfbbaadaa175f1/cytoolz-1.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:943a662d2e72ffc4438d43ab5a1de8d852237775a423236594a3b3e381b8032c", size = 904835 }, - { url = "https://files.pythonhosted.org/packages/69/82/edf1d0c32b6222f2c22e5618d6db855d44eb59f9b6f22436ff963c5d0a5c/cytoolz-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dba8e5a8c6e3c789d27b0eb5e7ce5ed7d032a7a9aae17ca4ba5147b871f6e327", size = 1314345 }, - { url = "https://files.pythonhosted.org/packages/2d/b5/0e3c1edaa26c2bd9db90cba0ac62c85bbca84224c7ae1c2e0072c4ea64c5/cytoolz-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:44b31c05addb0889167a720123b3b497b28dd86f8a0aeaf3ae4ffa11e2c85d55", size = 989259 }, - { url = "https://files.pythonhosted.org/packages/09/aa/e2b2ee9fc684867e817640764ea5807f9d25aa1e7bdba02dd4b249aab0f7/cytoolz-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:653cb18c4fc5d8a8cfce2bce650aabcbe82957cd0536827367d10810566d5294", size = 986551 }, - { url = "https://files.pythonhosted.org/packages/39/9f/4e8ee41acf6674f10a9c2c9117b2f219429a5a0f09bba6135f34ca4f08a6/cytoolz-1.1.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:853a5b4806915020c890e1ce70cc056bbc1dd8bc44f2d74d555cccfd7aefba7d", size = 2688378 }, - { url = "https://files.pythonhosted.org/packages/78/94/ef006f3412bc22444d855a0fc9ecb81424237fb4e5c1a1f8f5fb79ac978f/cytoolz-1.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7b44e9de86bea013fe84fd8c399d6016bbb96c37c5290769e5c99460b9c53e5", size = 2798299 }, - { url = "https://files.pythonhosted.org/packages/df/aa/365953926ee8b4f2e07df7200c0d73632155908c8867af14b2d19cc9f1f7/cytoolz-1.1.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:098d628a801dc142e9740126be5624eb7aef1d732bc7a5719f60a2095547b485", size = 2639311 }, - { url = "https://files.pythonhosted.org/packages/7c/ee/62beaaee7df208f22590ad07ef8875519af49c52ca39d99460b14a00f15a/cytoolz-1.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:779ee4096ed7a82cffab89372ffc339631c285079dbf33dbe7aff1f6174985df", size = 2979532 }, - { url = "https://files.pythonhosted.org/packages/c5/04/2211251e450bed111ada1194dc42c461da9aea441de62a01e4085ea6de9f/cytoolz-1.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f2ce18dd99533d077e9712f9faa852f389f560351b1efd2f2bdb193a95eddde2", size = 3018632 }, - { url = "https://files.pythonhosted.org/packages/ed/a2/4a3400e4d07d3916172bf74fede08020d7b4df01595d8a97f1e9507af5ae/cytoolz-1.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac266a34437812cf841cecbfe19f355ab9c3dd1ef231afc60415d40ff12a76e4", size = 2788579 }, - { url = "https://files.pythonhosted.org/packages/fe/82/bb88caa53a41f600e7763c517d50e2efbbe6427ea395716a92b83f44882a/cytoolz-1.1.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1920b9b9c13d60d0bb6cd14594b3bce0870022eccb430618c37156da5f2b7a55", size = 2593024 }, - { url = "https://files.pythonhosted.org/packages/09/a8/8b25e59570da16c7a0f173b8c6ec0aa6f3abd47fd385c007485acb459896/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47caa376dafd2bdc29f8a250acf59c810ec9105cd6f7680b9a9d070aae8490ec", size = 2715304 }, - { url = "https://files.pythonhosted.org/packages/d4/56/faec7696f235521b926ffdf92c102f5b029f072d28e1020364e55b084820/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5ab2c97d8aaa522b038cca9187b1153347af22309e7c998b14750c6fdec7b1cb", size = 2654461 }, - { url = "https://files.pythonhosted.org/packages/aa/82/f790ed167c04b8d2a33bed30770a9b7066fc4f573321d797190e5f05685f/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4bce006121b120e8b359244ee140bb0b1093908efc8b739db8dbaa3f8fb42139", size = 2672077 }, - { url = "https://files.pythonhosted.org/packages/d9/b3/80b8183e7eee44f45bfa3cdd3ebdadf3dd43ffc686f96d442a6c4dded45d/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fc0f1e4e9bb384d26e73c6657bbc26abdae4ff66a95933c00f3d578be89181b", size = 2881589 }, - { url = "https://files.pythonhosted.org/packages/8f/05/ac5ba5ddb88a3ba7ecea4bf192194a838af564d22ea7a4812cbb6bd106ce/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:dd3f894ff972da1994d06ac6157d74e40dda19eb31fe5e9b7863ca4278c3a167", size = 2589924 }, - { url = "https://files.pythonhosted.org/packages/8e/cd/100483cae3849d24351c8333a815dc6adaf3f04912486e59386d86d9db9a/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0846f49cf8a4496bd42659040e68bd0484ce6af819709cae234938e039203ba0", size = 2868059 }, - { url = "https://files.pythonhosted.org/packages/34/6e/3a7c56b325772d39397fc3aafb4dc054273982097178b6c3917c6dad48de/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:16a3af394ade1973226d64bb2f9eb3336adbdea03ed5b134c1bbec5a3b20028e", size = 2721692 }, - { url = "https://files.pythonhosted.org/packages/fa/ca/9fdaee32c3bc769dfb7e7991d9499136afccea67e423d097b8fb3c5acbc1/cytoolz-1.1.0-cp311-cp311-win32.whl", hash = "sha256:b786c9c8aeab76cc2f76011e986f7321a23a56d985b77d14f155d5e5514ea781", size = 899349 }, - { url = "https://files.pythonhosted.org/packages/fd/04/2ab98edeea90311e4029e1643e43d2027b54da61453292d9ea51a103ee87/cytoolz-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:ebf06d1c5344fb22fee71bf664234733e55db72d74988f2ecb7294b05e4db30c", size = 945831 }, - { url = "https://files.pythonhosted.org/packages/b4/8d/777d86ea6bcc68b0fc926b0ef8ab51819e2176b37aadea072aac949d5231/cytoolz-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:b63f5f025fac893393b186e132e3e242de8ee7265d0cd3f5bdd4dda93f6616c9", size = 904076 }, - { url = "https://files.pythonhosted.org/packages/c6/ec/01426224f7acf60183d3921b25e1a8e71713d3d39cb464d64ac7aace6ea6/cytoolz-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:99f8e134c9be11649342853ec8c90837af4089fc8ff1e8f9a024a57d1fa08514", size = 1327800 }, - { url = "https://files.pythonhosted.org/packages/b4/07/e07e8fedd332ac9626ad58bea31416dda19bfd14310731fa38b16a97e15f/cytoolz-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0a6f44cf9319c30feb9a50aa513d777ef51efec16f31c404409e7deb8063df64", size = 997118 }, - { url = "https://files.pythonhosted.org/packages/ab/72/c0f766d63ed2f9ea8dc8e1628d385d99b41fb834ce17ac3669e3f91e115d/cytoolz-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:945580dc158c557172fca899a35a99a16fbcebf6db0c77cb6621084bc82189f9", size = 991169 }, - { url = "https://files.pythonhosted.org/packages/df/4b/1f757353d1bf33e56a7391ecc9bc49c1e529803b93a9d2f67fe5f92906fe/cytoolz-1.1.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:257905ec050d04f2f856854620d1e25556fd735064cebd81b460f54939b9f9d5", size = 2700680 }, - { url = "https://files.pythonhosted.org/packages/25/73/9b25bb7ed8d419b9d6ff2ae0b3d06694de79a3f98f5169a1293ff7ad3a3f/cytoolz-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82779049f352fb3ab5e8c993ab45edbb6e02efb1f17f0b50f4972c706cc51d76", size = 2824951 }, - { url = "https://files.pythonhosted.org/packages/0c/93/9c787f7c909e75670fff467f2504725d06d8c3f51d6dfe22c55a08c8ccd4/cytoolz-1.1.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7d3e405e435320e08c5a1633afaf285a392e2d9cef35c925d91e2a31dfd7a688", size = 2679635 }, - { url = "https://files.pythonhosted.org/packages/50/aa/9ee92c302cccf7a41a7311b325b51ebeff25d36c1f82bdc1bbe3f58dc947/cytoolz-1.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:923df8f5591e0d20543060c29909c149ab1963a7267037b39eee03a83dbc50a8", size = 2938352 }, - { url = "https://files.pythonhosted.org/packages/6a/a3/3b58c5c1692c3bacd65640d0d5c7267a7ebb76204f7507aec29de7063d2f/cytoolz-1.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:25db9e4862f22ea0ae2e56c8bec9fc9fd756b655ae13e8c7b5625d7ed1c582d4", size = 3022121 }, - { url = "https://files.pythonhosted.org/packages/e1/93/c647bc3334355088c57351a536c2d4a83dd45f7de591fab383975e45bff9/cytoolz-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7a98deb11ccd8e5d9f9441ef2ff3352aab52226a2b7d04756caaa53cd612363", size = 2857656 }, - { url = "https://files.pythonhosted.org/packages/b2/c2/43fea146bf4141deea959e19dcddf268c5ed759dec5c2ed4a6941d711933/cytoolz-1.1.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dce4ee9fc99104bc77efdea80f32ca5a650cd653bcc8a1d984a931153d3d9b58", size = 2551284 }, - { url = "https://files.pythonhosted.org/packages/6f/df/cdc7a81ce5cfcde7ef523143d545635fc37e80ccacce140ae58483a21da3/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80d6da158f7d20c15819701bbda1c041f0944ede2f564f5c739b1bc80a9ffb8b", size = 2721673 }, - { url = "https://files.pythonhosted.org/packages/45/be/f8524bb9ad8812ad375e61238dcaa3177628234d1b908ad0b74e3657cafd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3b5c5a192abda123ad45ef716ec9082b4cf7d95e9ada8291c5c2cc5558be858b", size = 2722884 }, - { url = "https://files.pythonhosted.org/packages/23/e6/6bb8e4f9c267ad42d1ff77b6d2e4984665505afae50a216290e1d7311431/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5b399ce7d967b1cb6280250818b786be652aa8ddffd3c0bb5c48c6220d945ab5", size = 2685486 }, - { url = "https://files.pythonhosted.org/packages/d7/dd/88619f9c8d2b682562c0c886bbb7c35720cb83fda2ac9a41bdd14073d9bd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e7e29a1a03f00b4322196cfe8e2c38da9a6c8d573566052c586df83aacc5663c", size = 2839661 }, - { url = "https://files.pythonhosted.org/packages/b8/8d/4478ebf471ee78dd496d254dc0f4ad729cd8e6ba8257de4f0a98a2838ef2/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5291b117d71652a817ec164e7011f18e6a51f8a352cc9a70ed5b976c51102fda", size = 2547095 }, - { url = "https://files.pythonhosted.org/packages/e6/68/f1dea33367b0b3f64e199c230a14a6b6f243c189020effafd31e970ca527/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8caef62f846a9011676c51bda9189ae394cdd6bb17f2946ecaedc23243268320", size = 2870901 }, - { url = "https://files.pythonhosted.org/packages/4a/9a/33591c09dfe799b8fb692cf2ad383e2c41ab6593cc960b00d1fc8a145655/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:de425c5a8e3be7bb3a195e19191d28d9eb3c2038046064a92edc4505033ec9cb", size = 2765422 }, - { url = "https://files.pythonhosted.org/packages/60/2b/a8aa233c9416df87f004e57ae4280bd5e1f389b4943d179f01020c6ec629/cytoolz-1.1.0-cp312-cp312-win32.whl", hash = "sha256:296440a870e8d1f2e1d1edf98f60f1532b9d3ab8dfbd4b25ec08cd76311e79e5", size = 901933 }, - { url = "https://files.pythonhosted.org/packages/ad/33/4c9bdf8390dc01d2617c7f11930697157164a52259b6818ddfa2f94f89f4/cytoolz-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:07156987f224c6dac59aa18fb8bf91e1412f5463961862716a3381bf429c8699", size = 947989 }, - { url = "https://files.pythonhosted.org/packages/35/ac/6e2708835875f5acb52318462ed296bf94ed0cb8c7cb70e62fbd03f709e3/cytoolz-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:23e616b38f5b3160c7bb45b0f84a8f3deb4bd26b29fb2dfc716f241c738e27b8", size = 903913 }, - { url = "https://files.pythonhosted.org/packages/71/4a/b3ddb3ee44fe0045e95dd973746f93f033b6f92cce1fc3cbbe24b329943c/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:76c9b58555300be6dde87a41faf1f97966d79b9a678b7a526fcff75d28ef4945", size = 976728 }, - { url = "https://files.pythonhosted.org/packages/42/21/a3681434aa425875dd828bb515924b0f12c37a55c7d2bc5c0c5de3aeb0b4/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d1d638b10d3144795655e9395566ce35807df09219fd7cacd9e6acbdef67946a", size = 986057 }, - { url = "https://files.pythonhosted.org/packages/d9/cb/efc1b29e211e0670a6953222afaac84dcbba5cb940b130c0e49858978040/cytoolz-1.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:26801c1a165e84786a99e03c9c9973356caaca002d66727b761fb1042878ef06", size = 992632 }, - { url = "https://files.pythonhosted.org/packages/be/b0/e50621d21e939338c97faab651f58ea7fa32101226a91de79ecfb89d71e1/cytoolz-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a9a464542912d3272f6dccc5142df057c71c6a5cbd30439389a732df401afb7", size = 1317534 }, - { url = "https://files.pythonhosted.org/packages/0d/6b/25aa9739b0235a5bc4c1ea293186bc6822a4c6607acfe1422423287e7400/cytoolz-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ed6104fa942aa5784bf54f339563de637557e3443b105760bc4de8f16a7fc79b", size = 992336 }, - { url = "https://files.pythonhosted.org/packages/e1/53/5f4deb0ff958805309d135d899c764364c1e8a632ce4994bd7c45fb98df2/cytoolz-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56161f0ab60dc4159ec343509abaf809dc88e85c7e420e354442c62e3e7cbb77", size = 986118 }, - { url = "https://files.pythonhosted.org/packages/1c/e3/f6255b76c8cc0debbe1c0779130777dc0434da6d9b28a90d9f76f8cb67cd/cytoolz-1.1.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:832bd36cc9123535f1945acf6921f8a2a15acc19cfe4065b1c9b985a28671886", size = 2679563 }, - { url = "https://files.pythonhosted.org/packages/59/8a/acc6e39a84e930522b965586ad3a36694f9bf247b23188ee0eb47b1c9ed1/cytoolz-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1842636b6e034f229bf084c2bcdcfd36c8437e752eefd2c74ce9e2f10415cb6e", size = 2813020 }, - { url = "https://files.pythonhosted.org/packages/db/f5/0083608286ad1716eda7c41f868e85ac549f6fd6b7646993109fa0bdfd98/cytoolz-1.1.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:823df012ab90d2f2a0f92fea453528539bf71ac1879e518524cd0c86aa6df7b9", size = 2669312 }, - { url = "https://files.pythonhosted.org/packages/47/a8/d16080b575520fe5da00cede1ece4e0a4180ec23f88dcdc6a2f5a90a7f7f/cytoolz-1.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f1fcf9e7e7b3487883ff3f815abc35b89dcc45c4cf81c72b7ee457aa72d197b", size = 2922147 }, - { url = "https://files.pythonhosted.org/packages/7e/bc/716c9c1243701e58cad511eb3937fd550e645293c5ed1907639c5d66f194/cytoolz-1.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4cdb3fa1772116827f263f25b0cdd44c663b6701346a56411960534a06c082de", size = 2981602 }, - { url = "https://files.pythonhosted.org/packages/14/bc/571b232996846b27f4ac0c957dc8bf60261e9b4d0d01c8d955e82329544e/cytoolz-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1b5c95041741b81430454db65183e133976f45ac3c03454cfa8147952568529", size = 2830103 }, - { url = "https://files.pythonhosted.org/packages/5b/55/c594afb46ecd78e4b7e1fb92c947ed041807875661ceda73baaf61baba4f/cytoolz-1.1.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b2079fd9f1a65f4c61e6278c8a6d4f85edf30c606df8d5b32f1add88cbbe2286", size = 2533802 }, - { url = "https://files.pythonhosted.org/packages/93/83/1edcf95832555a78fc43b975f3ebe8ceadcc9664dd47fd33747a14df5069/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a92a320d72bef1c7e2d4c6d875125cf57fc38be45feb3fac1bfa64ea401f54a4", size = 2706071 }, - { url = "https://files.pythonhosted.org/packages/e2/df/035a408df87f25cfe3611557818b250126cd2281b2104cd88395de205583/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06d1c79aa51e6a92a90b0e456ebce2288f03dd6a76c7f582bfaa3eda7692e8a5", size = 2707575 }, - { url = "https://files.pythonhosted.org/packages/7a/a4/ef78e13e16e93bf695a9331321d75fbc834a088d941f1c19e6b63314e257/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e1d7be25f6971e986a52b6d3a0da28e1941850985417c35528f6823aef2cfec5", size = 2660486 }, - { url = "https://files.pythonhosted.org/packages/30/7a/2c3d60682b26058d435416c4e90d4a94db854de5be944dfd069ed1be648a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:964b248edc31efc50a65e9eaa0c845718503823439d2fa5f8d2c7e974c2b5409", size = 2819605 }, - { url = "https://files.pythonhosted.org/packages/45/92/19b722a1d83cc443fbc0c16e0dc376f8a451437890d3d9ee370358cf0709/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c9ff2b3c57c79b65cb5be14a18c6fd4a06d5036fb3f33e973a9f70e9ac13ca28", size = 2533559 }, - { url = "https://files.pythonhosted.org/packages/1d/15/fa3b7891da51115204416f14192081d3dea0eaee091f123fdc1347de8dd1/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:22290b73086af600042d99f5ce52a43d4ad9872c382610413176e19fc1d4fd2d", size = 2839171 }, - { url = "https://files.pythonhosted.org/packages/46/40/d3519d5cd86eebebf1e8b7174ec32dfb6ecec67b48b0cfb92bf226659b5a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a2ade74fccd080ea793382968913ee38d7a35c921df435bbf0a6aeecf0d17574", size = 2743379 }, - { url = "https://files.pythonhosted.org/packages/93/e2/a9e7511f0a13fdbefa5bf73cf8e4763878140de9453fd3e50d6ac57b6be7/cytoolz-1.1.0-cp313-cp313-win32.whl", hash = "sha256:db5dbcfda1c00e937426cbf9bdc63c24ebbc358c3263bfcbc1ab4a88dc52aa8e", size = 900844 }, - { url = "https://files.pythonhosted.org/packages/d6/a4/fb7eb403c6a4c81e5a30363f34a71adcc8bf5292dc8ea32e2440aa5668f2/cytoolz-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9e2d3fe3b45c3eb7233746f7aca37789be3dceec3e07dcc406d3e045ea0f7bdc", size = 946461 }, - { url = "https://files.pythonhosted.org/packages/93/bb/1c8c33d353548d240bc6e8677ee8c3560ce5fa2f084e928facf7c35a6dcf/cytoolz-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:32c559f95ff44a9ebcbd934acaa1e6dc8f3e6ffce4762a79a88528064873d6d5", size = 902673 }, - { url = "https://files.pythonhosted.org/packages/c4/ba/4a53acc60f59030fcaf48c7766e3c4c81bd997379425aa45b129396557b5/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9e2cd93b28f667c5870a070ab2b8bb4397470a85c4b204f2454b0ad001cd1ca3", size = 1372336 }, - { url = "https://files.pythonhosted.org/packages/ac/90/f28fd8ad8319d8f5c8da69a2c29b8cf52a6d2c0161602d92b366d58926ab/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f494124e141a9361f31d79875fe7ea459a3be2b9dadd90480427c0c52a0943d4", size = 1011930 }, - { url = "https://files.pythonhosted.org/packages/c9/95/4561c4e0ad1c944f7673d6d916405d68080f10552cfc5d69a1cf2475a9a1/cytoolz-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53a3262bf221f19437ed544bf8c0e1980c81ac8e2a53d87a9bc075dba943d36f", size = 1020610 }, - { url = "https://files.pythonhosted.org/packages/c3/14/b2e1ffa4995ec36e1372e243411ff36325e4e6d7ffa34eb4098f5357d176/cytoolz-1.1.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:47663e57d3f3f124921f38055e86a1022d0844c444ede2e8f090d3bbf80deb65", size = 2917327 }, - { url = "https://files.pythonhosted.org/packages/4a/29/7cab6c609b4514ac84cca2f7dca6c509977a8fc16d27c3a50e97f105fa6a/cytoolz-1.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5a8755c4104ee4e3d5ba434c543b5f85fdee6a1f1df33d93f518294da793a60", size = 3108951 }, - { url = "https://files.pythonhosted.org/packages/9a/71/1d1103b819458679277206ad07d78ca6b31c4bb88d6463fd193e19bfb270/cytoolz-1.1.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4d96ff3d381423af1b105295f97de86d1db51732c9566eb37378bab6670c5010", size = 2807149 }, - { url = "https://files.pythonhosted.org/packages/1a/d4/3d83a05a21e7d2ed2b9e6daf489999c29934b005de9190272b8a2e3735d0/cytoolz-1.1.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0ec96b3d537cdf47d4e76ded199f7440715f4c71029b45445cff92c1248808c2", size = 3111608 }, - { url = "https://files.pythonhosted.org/packages/51/88/96f68354c3d4af68de41f0db4fe41a23b96a50a4a416636cea325490cfeb/cytoolz-1.1.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:208e2f2ef90a32b0acbff3303d90d89b13570a228d491d2e622a7883a3c68148", size = 3179373 }, - { url = "https://files.pythonhosted.org/packages/ce/50/ed87a5cd8e6f27ffbb64c39e9730e18ec66c37631db2888ae711909f10c9/cytoolz-1.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d416a81bb0bd517558668e49d30a7475b5445f9bbafaab7dcf066f1e9adba36", size = 3003120 }, - { url = "https://files.pythonhosted.org/packages/d3/a7/acde155b050d6eaa8e9c7845c98fc5fb28501568e78e83ebbf44f8855274/cytoolz-1.1.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f32e94c91ffe49af04835ee713ebd8e005c85ebe83e7e1fdcc00f27164c2d636", size = 2703225 }, - { url = "https://files.pythonhosted.org/packages/1b/b6/9d518597c5bdea626b61101e8d2ff94124787a42259dafd9f5fc396f346a/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15d0c6405efc040499c46df44056a5c382f551a7624a41cf3e4c84a96b988a15", size = 2956033 }, - { url = "https://files.pythonhosted.org/packages/89/7a/93e5f860926165538c85e1c5e1670ad3424f158df810f8ccd269da652138/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:bf069c5381d757debae891401b88b3a346ba3a28ca45ba9251103b282463fad8", size = 2862950 }, - { url = "https://files.pythonhosted.org/packages/76/e6/99d6af00487bedc27597b54c9fcbfd5c833a69c6b7a9b9f0fff777bfc7aa/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d5cf15892e63411ec1bd67deff0e84317d974e6ab2cdfefdd4a7cea2989df66", size = 2861757 }, - { url = "https://files.pythonhosted.org/packages/71/ca/adfa1fb7949478135a37755cb8e88c20cd6b75c22a05f1128f05f3ab2c60/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3e3872c21170f8341656f8692f8939e8800dcee6549ad2474d4c817bdefd62cd", size = 2979049 }, - { url = "https://files.pythonhosted.org/packages/70/4c/7bf47a03a4497d500bc73d4204e2d907771a017fa4457741b2a1d7c09319/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b9ddeff8e8fd65eb1fcefa61018100b2b627e759ea6ad275d2e2a93ffac147bf", size = 2699492 }, - { url = "https://files.pythonhosted.org/packages/7e/e7/3d034b0e4817314f07aa465d5864e9b8df9d25cb260a53dd84583e491558/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:02feeeda93e1fa3b33414eb57c2b0aefd1db8f558dd33fdfcce664a0f86056e4", size = 2995646 }, - { url = "https://files.pythonhosted.org/packages/c1/62/be357181c71648d9fe1d1ce91cd42c63457dcf3c158e144416fd51dced83/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d08154ad45349162b6c37f12d5d1b2e6eef338e657b85e1621e4e6a4a69d64cb", size = 2919481 }, - { url = "https://files.pythonhosted.org/packages/62/d5/bf5434fde726c4f80cb99912b2d8e0afa1587557e2a2d7e0315eb942f2de/cytoolz-1.1.0-cp313-cp313t-win32.whl", hash = "sha256:10ae4718a056948d73ca3e1bb9ab1f95f897ec1e362f829b9d37cc29ab566c60", size = 951595 }, - { url = "https://files.pythonhosted.org/packages/64/29/39c161e9204a9715321ddea698cbd0abc317e78522c7c642363c20589e71/cytoolz-1.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:1bb77bc6197e5cb19784b6a42bb0f8427e81737a630d9d7dda62ed31733f9e6c", size = 1004445 }, - { url = "https://files.pythonhosted.org/packages/e2/5a/7cbff5e9a689f558cb0bdf277f9562b2ac51acf7cd15e055b8c3efb0e1ef/cytoolz-1.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:563dda652c6ff52d215704fbe6b491879b78d7bbbb3a9524ec8e763483cb459f", size = 926207 }, - { url = "https://files.pythonhosted.org/packages/b7/e8/297a85ba700f437c01eba962428e6ab4572f6c3e68e8ff442ce5c9d3a496/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d542cee7c7882d2a914a33dec4d3600416fb336734df979473249d4c53d207a1", size = 980613 }, - { url = "https://files.pythonhosted.org/packages/e8/d7/2b02c9d18e9cc263a0e22690f78080809f1eafe72f26b29ccc115d3bf5c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31922849b701b0f24bb62e56eb2488dcd3aa6ae3057694bd6b3b7c4c2bc27c2f", size = 990476 }, - { url = "https://files.pythonhosted.org/packages/89/26/b6b159d2929310fca0eff8a4989cd4b1ecbdf7c46fdff46c7a20fcae55c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e68308d32afd31943314735c1335e4ab5696110e96b405f6bdb8f2a8dc771a16", size = 992712 }, - { url = "https://files.pythonhosted.org/packages/42/a0/f7c572aa151ed466b0fce4a327c3cc916d3ef3c82e341be59ea4b9bee9e4/cytoolz-1.1.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fc4bb48b3b866e1867f7c6411a4229e5b44be3989060663713e10efc24c9bd5f", size = 1322596 }, - { url = "https://files.pythonhosted.org/packages/72/7c/a55d035e20b77b6725e85c8f1a418b3a4c23967288b8b0c2d1a40f158cbe/cytoolz-1.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:456f77207d1445025d7ef262b8370a05492dcb1490cb428b0f3bf1bd744a89b0", size = 992825 }, - { url = "https://files.pythonhosted.org/packages/03/af/39d2d3db322136e12e9336a1f13bab51eab88b386bfb11f91d3faff8ba34/cytoolz-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:174ebc71ebb20a9baeffce6ee07ee2cd913754325c93f99d767380d8317930f7", size = 990525 }, - { url = "https://files.pythonhosted.org/packages/a6/bd/65d7a869d307f9b10ad45c2c1cbb40b81a8d0ed1138fa17fd904f5c83298/cytoolz-1.1.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8b3604fef602bcd53415055a4f68468339192fd17be39e687ae24f476d23d56e", size = 2672409 }, - { url = "https://files.pythonhosted.org/packages/2d/fb/74dfd844bfd67e810bd36e8e3903a143035447245828e7fcd7c81351d775/cytoolz-1.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3604b959a01f64c366e7d10ec7634d5f5cfe10301e27a8f090f6eb3b2a628a18", size = 2808477 }, - { url = "https://files.pythonhosted.org/packages/d6/1f/587686c43e31c19241ec317da66438d093523921ea7749bbc65558a30df9/cytoolz-1.1.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6db2127a3c1bc2f59f08010d2ae53a760771a9de2f67423ad8d400e9ba4276e8", size = 2636881 }, - { url = "https://files.pythonhosted.org/packages/bc/6d/90468cd34f77cb38a11af52c4dc6199efcc97a486395a21bef72e9b7602e/cytoolz-1.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56584745ac647993a016a21bc76399113b7595e312f8d0a1b140c9fcf9b58a27", size = 2937315 }, - { url = "https://files.pythonhosted.org/packages/d9/50/7b92cd78c613b92e3509e6291d3fb7e0d72ebda999a8df806a96c40ca9ab/cytoolz-1.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db2c4c3a7f7bd7e03bb1a236a125c8feb86c75802f4ecda6ecfaf946610b2930", size = 2959988 }, - { url = "https://files.pythonhosted.org/packages/44/d5/34b5a28a8d9bb329f984b4c2259407ca3f501d1abeb01bacea07937d85d1/cytoolz-1.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48cb8a692111a285d2b9acd16d185428176bfbffa8a7c274308525fccd01dd42", size = 2795116 }, - { url = "https://files.pythonhosted.org/packages/f5/d9/5dd829e33273ec03bdc3c812e6c3281987ae2c5c91645582f6c331544a64/cytoolz-1.1.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d2f344ba5eb17dcf38ee37fdde726f69053f54927db8f8a1bed6ac61e5b1890d", size = 2535390 }, - { url = "https://files.pythonhosted.org/packages/87/1f/7f9c58068a8eec2183110df051bc6b69dd621143f84473eeb6dc1b32905a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:abf76b1c1abd031f098f293b6d90ee08bdaa45f8b5678430e331d991b82684b1", size = 2704834 }, - { url = "https://files.pythonhosted.org/packages/d2/90/667def5665333575d01a65fe3ec0ca31b897895f6e3bc1a42d6ea3659369/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ddf9a38a5b686091265ff45b53d142e44a538cd6c2e70610d3bc6be094219032", size = 2658441 }, - { url = "https://files.pythonhosted.org/packages/23/79/6615f9a14960bd29ac98b823777b6589357833f65cf1a11b5abc1587c120/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:946786755274f07bb2be0400f28adb31d7d85a7c7001873c0a8e24a503428fb3", size = 2654766 }, - { url = "https://files.pythonhosted.org/packages/b0/99/be59c6e0ae02153ef10ae1ff0f380fb19d973c651b50cf829a731f6c9e79/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b8f78b9fed79cf185ad4ddec099abeef45951bdcb416c5835ba05f0a1242c7", size = 2827649 }, - { url = "https://files.pythonhosted.org/packages/19/b7/854ddcf9f9618844108677c20d48f4611b5c636956adea0f0e85e027608f/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fccde6efefdbc02e676ccb352a2ccc8a8e929f59a1c6d3d60bb78e923a49ca44", size = 2533456 }, - { url = "https://files.pythonhosted.org/packages/45/66/bfe6fbb2bdcf03c8377c8c2f542576e15f3340c905a09d78a6cb3badd39a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:717b7775313da5f51b0fbf50d865aa9c39cb241bd4cb605df3cf2246d6567397", size = 2826455 }, - { url = "https://files.pythonhosted.org/packages/c3/0c/cce4047bd927e95f59e73319c02c9bc86bd3d76392e0eb9e41a1147a479c/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5158744a09d0e0e4a4f82225e3a3c4ebf38f9ae74467aaa905467270e52f2794", size = 2714897 }, - { url = "https://files.pythonhosted.org/packages/ac/9a/061323bb289b565802bad14fb7ab59fcd8713105df142bcf4dd9ff64f8ac/cytoolz-1.1.0-cp314-cp314-win32.whl", hash = "sha256:1ed534bdbbf063b2bb28fca7d0f6723a3e5a72b086e7c7fe6d74ae8c3e4d00e2", size = 901490 }, - { url = "https://files.pythonhosted.org/packages/a3/20/1f3a733d710d2a25d6f10b463bef55ada52fe6392a5d233c8d770191f48a/cytoolz-1.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:472c1c9a085f5ad973ec0ad7f0b9ba0969faea6f96c9e397f6293d386f3a25ec", size = 946730 }, - { url = "https://files.pythonhosted.org/packages/f2/22/2d657db4a5d1c10a152061800f812caba9ef20d7bd2406f51a5fd800c180/cytoolz-1.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:a7ad7ca3386fa86bd301be3fa36e7f0acb024f412f665937955acfc8eb42deff", size = 905722 }, - { url = "https://files.pythonhosted.org/packages/19/97/b4a8c76796a9a8b9bc90c7992840fa1589a1af8e0426562dea4ce9b384a7/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:64b63ed4b71b1ba813300ad0f06b8aff19a12cf51116e0e4f1ed837cea4debcf", size = 1372606 }, - { url = "https://files.pythonhosted.org/packages/08/d4/a1bb1a32b454a2d650db8374ff3bf875ba0fc1c36e6446ec02a83b9140a1/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a60ba6f2ed9eb0003a737e1ee1e9fa2258e749da6477946008d4324efa25149f", size = 1012189 }, - { url = "https://files.pythonhosted.org/packages/21/4b/2f5cbbd81588918ee7dd70cffb66731608f578a9b72166aafa991071af7d/cytoolz-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1aa58e2434d732241f7f051e6f17657e969a89971025e24578b5cbc6f1346485", size = 1020624 }, - { url = "https://files.pythonhosted.org/packages/f5/99/c4954dd86cd593cd776a038b36795a259b8b5c12cbab6363edf5f6d9c909/cytoolz-1.1.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6965af3fc7214645970e312deb9bd35a213a1eaabcfef4f39115e60bf2f76867", size = 2917016 }, - { url = "https://files.pythonhosted.org/packages/b2/7c/f1f70a17e272b433232bc8a27df97e46b202d6cc07e3b0d63f7f41ba0f2d/cytoolz-1.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddd2863f321d67527d3b67a93000a378ad6f967056f68c06467fe011278a6d0e", size = 3107634 }, - { url = "https://files.pythonhosted.org/packages/8f/bd/c3226a57474b4aef1f90040510cba30d0decd3515fed48dc229b37c2f898/cytoolz-1.1.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4e6b428e9eb5126053c2ae0efa62512ff4b38ed3951f4d0888ca7005d63e56f5", size = 2806221 }, - { url = "https://files.pythonhosted.org/packages/c3/47/2f7bfe4aaa1e07dc9828bea228ed744faf73b26aee0c1bdf3b5520bf1909/cytoolz-1.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d758e5ef311d2671e0ae8c214c52e44617cf1e58bef8f022b547b9802a5a7f30", size = 3107671 }, - { url = "https://files.pythonhosted.org/packages/4d/12/6ff3b04fbd1369d0fcd5f8b5910ba6e427e33bf113754c4c35ec3f747924/cytoolz-1.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a95416eca473e6c1179b48d86adcf528b59c63ce78f4cb9934f2e413afa9b56b", size = 3176350 }, - { url = "https://files.pythonhosted.org/packages/e6/8c/6691d986b728e77b5d2872743ebcd962d37a2d0f7e9ad95a81b284fbf905/cytoolz-1.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36c8ede93525cf11e2cc787b7156e5cecd7340193ef800b816a16f1404a8dc6d", size = 3001173 }, - { url = "https://files.pythonhosted.org/packages/7a/cb/f59d83a5058e1198db5a1f04e4a124c94d60390e4fa89b6d2e38ee8288a0/cytoolz-1.1.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c949755b6d8a649c5fbc888bc30915926f1b09fe42fea9f289e297c2f6ddd3", size = 2701374 }, - { url = "https://files.pythonhosted.org/packages/b7/f0/1ae6d28df503b0bdae094879da2072b8ba13db5919cd3798918761578411/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e1b6d37545816905a76d9ed59fa4e332f929e879f062a39ea0f6f620405cdc27", size = 2953081 }, - { url = "https://files.pythonhosted.org/packages/f4/06/d86fe811c6222dc32d3e08f5d88d2be598a6055b4d0590e7c1428d55c386/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:05332112d4087904842b36954cd1d3fc0e463a2f4a7ef9477bd241427c593c3b", size = 2862228 }, - { url = "https://files.pythonhosted.org/packages/ae/32/978ef6f42623be44a0a03ae9de875ab54aa26c7e38c5c4cd505460b0927d/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:31538ca2fad2d688cbd962ccc3f1da847329e2258a52940f10a2ac0719e526be", size = 2861971 }, - { url = "https://files.pythonhosted.org/packages/ee/f7/74c69497e756b752b359925d1feef68b91df024a4124a823740f675dacd3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:747562aa70abf219ea16f07d50ac0157db856d447f7f498f592e097cbc77df0b", size = 2975304 }, - { url = "https://files.pythonhosted.org/packages/5b/2b/3ce0e6889a6491f3418ad4d84ae407b8456b02169a5a1f87990dbba7433b/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:3dc15c48b20c0f467e15e341e102896c8422dccf8efc6322def5c1b02f074629", size = 2697371 }, - { url = "https://files.pythonhosted.org/packages/15/87/c616577f0891d97860643c845f7221e95240aa589586de727e28a5eb6e52/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3c03137ee6103ba92d5d6ad6a510e86fded69cd67050bd8a1843f15283be17ac", size = 2992436 }, - { url = "https://files.pythonhosted.org/packages/e7/9f/490c81bffb3428ab1fa114051fbb5ba18aaa2e2fe4da5bf4170ca524e6b3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:be8e298d88f88bd172b59912240558be3b7a04959375646e7fd4996401452941", size = 2917612 }, - { url = "https://files.pythonhosted.org/packages/66/35/0fec2769660ca6472bbf3317ab634675827bb706d193e3240aaf20eab961/cytoolz-1.1.0-cp314-cp314t-win32.whl", hash = "sha256:3d407140f5604a89578285d4aac7b18b8eafa055cf776e781aabb89c48738fad", size = 960842 }, - { url = "https://files.pythonhosted.org/packages/46/b4/b7ce3d3cd20337becfec978ecfa6d0ef64884d0cf32d44edfed8700914b9/cytoolz-1.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:56e5afb69eb6e1b3ffc34716ee5f92ffbdb5cb003b3a5ca4d4b0fe700e217162", size = 1020835 }, - { url = "https://files.pythonhosted.org/packages/2c/1f/0498009aa563a9c5d04f520aadc6e1c0942434d089d0b2f51ea986470f55/cytoolz-1.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:27b19b4a286b3ff52040efa42dbe403730aebe5fdfd2def704eb285e2125c63e", size = 927963 }, - { url = "https://files.pythonhosted.org/packages/84/32/0522207170294cf691112a93c70a8ef942f60fa9ff8e793b63b1f09cedc0/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f32e93a55681d782fc6af939f6df36509d65122423cbc930be39b141064adff8", size = 922014 }, - { url = "https://files.pythonhosted.org/packages/4c/49/9be2d24adaa18fa307ff14e3e43f02b2ae4b69c4ce51cee6889eb2114990/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5d9bc596751cbda8073e65be02ca11706f00029768fbbbc81e11a8c290bb41aa", size = 918134 }, - { url = "https://files.pythonhosted.org/packages/5c/b3/6a76c3b94c6c87c72ea822e7e67405be6b649c2e37778eeac7c0c0c69de8/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9b16660d01c3931951fab49db422c627897c38c1a1f0393a97582004019a4887", size = 981970 }, - { url = "https://files.pythonhosted.org/packages/f6/8a/606e4c7ed14aa6a86aee6ca84a2cb804754dc6c4905b8f94e09e49f1ce60/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b7de5718e2113d4efccea3f06055758cdbc17388ecc3341ba4d1d812837d7c1a", size = 978877 }, - { url = "https://files.pythonhosted.org/packages/97/ec/ad474dcb1f6c1ebfdda3c2ad2edbb1af122a0e79c9ff2cb901ffb5f59662/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a12a2a1a6bc44099491c05a12039efa08cc33a3d0f8c7b0566185e085e139283", size = 964279 }, - { url = "https://files.pythonhosted.org/packages/68/8c/d245fd416c69d27d51f14d5ad62acc4ee5971088ee31c40ffe1cc109af68/cytoolz-1.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:047defa7f5f9a32f82373dbc3957289562e8a3fa58ae02ec8e4dca4f43a33a21", size = 916630 }, + { url = "https://files.pythonhosted.org/packages/a7/7a/3244e6e3587be9abfee3b1c320e43a279831b3c3a31fe5d08c1ee6193e6b/cytoolz-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:72d7043a88ea5e61ba9d17ea0d1c1eff10f645d7edfcc4e56a31ef78be287644", size = 1307813, upload-time = "2025-10-19T00:39:34.198Z" }, + { url = "https://files.pythonhosted.org/packages/32/7e/eaf504ca59addce323ef4d4ffedc2913d83c121ec19f6419bc402f7702dc/cytoolz-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d759e9ed421bacfeb456d47af8d734c057b9912b5f2441f95b27ca35e5efab07", size = 985777, upload-time = "2025-10-19T00:39:36.545Z" }, + { url = "https://files.pythonhosted.org/packages/d4/a1/ec95443f0cf4cd0dbc574fa26ac85a0442d35f3b601a90a0e3dda077f614/cytoolz-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fdb5be8fbcc0396141189022724155a4c1c93712ac4aef8c03829af0c2a816d7", size = 982865, upload-time = "2025-10-19T00:39:38.19Z" }, + { url = "https://files.pythonhosted.org/packages/a7/1b/8503604b0c0534977363fb77d371019395dfa031a216f9b1d8729d1280e4/cytoolz-1.1.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c8c0a513dc89bc05cc72893609118815bced5ef201f1a317b4cc3423b3a0e750", size = 2597969, upload-time = "2025-10-19T00:39:40.26Z" }, + { url = "https://files.pythonhosted.org/packages/4e/e5/30748da06417cb2d4bc58e380b0c11d8c6539f4e289dc1e4f4b4fc248d0e/cytoolz-1.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce94db4f8ebe842c30c0ece42ff5de977c47859088c2c363dede5a68f6906484", size = 2692230, upload-time = "2025-10-19T00:39:42.327Z" }, + { url = "https://files.pythonhosted.org/packages/d6/84/e06580b74deb97dfd3513e4e6b660c2dedc220c7653f5bd3e4f772f4d885/cytoolz-1.1.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b622d4f54e370c853ded94a668f94fe72c6d70e06ac102f17a2746661c27ab52", size = 2565243, upload-time = "2025-10-19T00:39:44.403Z" }, + { url = "https://files.pythonhosted.org/packages/91/5e/79c0122a34c33afcb5aaee1fec35be24fe16cecefb9bb8890f2908feae56/cytoolz-1.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:375a65baa5a5b4ff6a0c5ff17e170cf23312e4c710755771ca966144c24216b5", size = 2868602, upload-time = "2025-10-19T00:39:46.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/84/404698ff02b32292db1e39cc4a2fbdabe15164b092cc364902984c3ce0f4/cytoolz-1.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c0d51bcdb3203a062a78f66bbe33db5e3123048e24a5f0e1402422d79df8ee2d", size = 2905121, upload-time = "2025-10-19T00:39:48.078Z" }, + { url = "https://files.pythonhosted.org/packages/9f/33/afad6593829ba73fc87b5ae64441e380fc937f79f24a1cda60d23cb99b8c/cytoolz-1.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1010869529bb05dc9802b6d776a34ca1b6d48b9deec70ad5e2918ae175be5c2f", size = 2684382, upload-time = "2025-10-19T00:39:49.766Z" }, + { url = "https://files.pythonhosted.org/packages/ce/86/7900013a82ca9c6cadbfb22bf50d0fbfc3b192915d2bdd9fab3f69a9afba/cytoolz-1.1.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11a8f2e83295bdb33f35454d6bafcb7845b03b5881dcaed66ecbd726c7f16772", size = 2518183, upload-time = "2025-10-19T00:39:51.433Z" }, + { url = "https://files.pythonhosted.org/packages/c3/4b/acf9be2953fed6a6d795fb66de37c367915037a998a5b3d3b69476cf91fe/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0499c5e0a8e688ed367a2e51cc13792ae8f08226c15f7d168589fc44b9b9cada", size = 2609368, upload-time = "2025-10-19T00:39:53.458Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ec/3e30455fd526f5cc37bd3dd2a0e2aafb803ae4d271e50ce53bfc30810053/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:87d44e6033d4c5e95a7d39ba59b8e105ba1c29b1ccd1d215f26477cc1d64be39", size = 2561458, upload-time = "2025-10-19T00:39:55.493Z" }, + { url = "https://files.pythonhosted.org/packages/49/27/e5815c85bb18cdf95780f9596dcfd76dee910a4d635a1924648cb8a636c6/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a68cef396a7de237f7b97422a6a450dfb111722296ba217ba5b34551832f1f6e", size = 2578236, upload-time = "2025-10-19T00:39:57.512Z" }, + { url = "https://files.pythonhosted.org/packages/17/db/588e266eff397670398ea335a809152e77b02ee92e0ec42091115b42f09b/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:06ad4c95b258141f138a93ebfdc1d76ac087afc1a82f1401100a1f44b44ba656", size = 2770523, upload-time = "2025-10-19T00:39:59.194Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ad/82be0b999c7a0a0b362cedfc183eb090b872fd42937af2d6e97d58bc70f8/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ada59a4b3c59d4ac7162e0ed08667ffa78abf48e975c8a9f9d5b9bc50720f4fd", size = 2512909, upload-time = "2025-10-19T00:40:01.199Z" }, + { url = "https://files.pythonhosted.org/packages/25/21/45f07ab0339a20c518bc9006100922babc397ab7ea5ef40a395db83b9cdd/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a8957bcaea1ba01327a9b219d2adb84144377684f51444253890dab500ca171f", size = 2755345, upload-time = "2025-10-19T00:40:03.322Z" }, + { url = "https://files.pythonhosted.org/packages/8b/a7/e530bf2b304206f79b36d793caba1ff9448348713a41bb1ad0197714a0f2/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6d8cdc299d67eb0f3b9ecdafeeb55eb3b7b7470e2d950ac34b05ed4c7a5572b8", size = 2617790, upload-time = "2025-10-19T00:40:05.03Z" }, + { url = "https://files.pythonhosted.org/packages/9f/77/7f53092121d7431589344c7d65c3d43c4111547aafabb21d3ca9032d126c/cytoolz-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d8e08464c5cdea4f6df31e84b11ed6bfd79cedb99fbcbfdc15eb9361a6053c5a", size = 900209, upload-time = "2025-10-19T00:40:06.647Z" }, + { url = "https://files.pythonhosted.org/packages/84/e4/902578658303b9bc76b1704d3ed85e6d307d311bd9fa0b919581bea56e62/cytoolz-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7e49922a7ed54262d41960bf3b835a7700327bf79cff1e9bfc73d79021132ff8", size = 944802, upload-time = "2025-10-19T00:40:08.983Z" }, + { url = "https://files.pythonhosted.org/packages/71/9f/56a7003617b4eabd8ddfb470aacc240425cbe6ddeb756adfbbaadaa175f1/cytoolz-1.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:943a662d2e72ffc4438d43ab5a1de8d852237775a423236594a3b3e381b8032c", size = 904835, upload-time = "2025-10-19T00:40:11.024Z" }, + { url = "https://files.pythonhosted.org/packages/69/82/edf1d0c32b6222f2c22e5618d6db855d44eb59f9b6f22436ff963c5d0a5c/cytoolz-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dba8e5a8c6e3c789d27b0eb5e7ce5ed7d032a7a9aae17ca4ba5147b871f6e327", size = 1314345, upload-time = "2025-10-19T00:40:13.273Z" }, + { url = "https://files.pythonhosted.org/packages/2d/b5/0e3c1edaa26c2bd9db90cba0ac62c85bbca84224c7ae1c2e0072c4ea64c5/cytoolz-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:44b31c05addb0889167a720123b3b497b28dd86f8a0aeaf3ae4ffa11e2c85d55", size = 989259, upload-time = "2025-10-19T00:40:15.196Z" }, + { url = "https://files.pythonhosted.org/packages/09/aa/e2b2ee9fc684867e817640764ea5807f9d25aa1e7bdba02dd4b249aab0f7/cytoolz-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:653cb18c4fc5d8a8cfce2bce650aabcbe82957cd0536827367d10810566d5294", size = 986551, upload-time = "2025-10-19T00:40:16.831Z" }, + { url = "https://files.pythonhosted.org/packages/39/9f/4e8ee41acf6674f10a9c2c9117b2f219429a5a0f09bba6135f34ca4f08a6/cytoolz-1.1.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:853a5b4806915020c890e1ce70cc056bbc1dd8bc44f2d74d555cccfd7aefba7d", size = 2688378, upload-time = "2025-10-19T00:40:18.552Z" }, + { url = "https://files.pythonhosted.org/packages/78/94/ef006f3412bc22444d855a0fc9ecb81424237fb4e5c1a1f8f5fb79ac978f/cytoolz-1.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7b44e9de86bea013fe84fd8c399d6016bbb96c37c5290769e5c99460b9c53e5", size = 2798299, upload-time = "2025-10-19T00:40:20.191Z" }, + { url = "https://files.pythonhosted.org/packages/df/aa/365953926ee8b4f2e07df7200c0d73632155908c8867af14b2d19cc9f1f7/cytoolz-1.1.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:098d628a801dc142e9740126be5624eb7aef1d732bc7a5719f60a2095547b485", size = 2639311, upload-time = "2025-10-19T00:40:22.289Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ee/62beaaee7df208f22590ad07ef8875519af49c52ca39d99460b14a00f15a/cytoolz-1.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:779ee4096ed7a82cffab89372ffc339631c285079dbf33dbe7aff1f6174985df", size = 2979532, upload-time = "2025-10-19T00:40:24.006Z" }, + { url = "https://files.pythonhosted.org/packages/c5/04/2211251e450bed111ada1194dc42c461da9aea441de62a01e4085ea6de9f/cytoolz-1.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f2ce18dd99533d077e9712f9faa852f389f560351b1efd2f2bdb193a95eddde2", size = 3018632, upload-time = "2025-10-19T00:40:26.175Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a2/4a3400e4d07d3916172bf74fede08020d7b4df01595d8a97f1e9507af5ae/cytoolz-1.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac266a34437812cf841cecbfe19f355ab9c3dd1ef231afc60415d40ff12a76e4", size = 2788579, upload-time = "2025-10-19T00:40:27.878Z" }, + { url = "https://files.pythonhosted.org/packages/fe/82/bb88caa53a41f600e7763c517d50e2efbbe6427ea395716a92b83f44882a/cytoolz-1.1.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1920b9b9c13d60d0bb6cd14594b3bce0870022eccb430618c37156da5f2b7a55", size = 2593024, upload-time = "2025-10-19T00:40:29.601Z" }, + { url = "https://files.pythonhosted.org/packages/09/a8/8b25e59570da16c7a0f173b8c6ec0aa6f3abd47fd385c007485acb459896/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47caa376dafd2bdc29f8a250acf59c810ec9105cd6f7680b9a9d070aae8490ec", size = 2715304, upload-time = "2025-10-19T00:40:31.151Z" }, + { url = "https://files.pythonhosted.org/packages/d4/56/faec7696f235521b926ffdf92c102f5b029f072d28e1020364e55b084820/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5ab2c97d8aaa522b038cca9187b1153347af22309e7c998b14750c6fdec7b1cb", size = 2654461, upload-time = "2025-10-19T00:40:32.884Z" }, + { url = "https://files.pythonhosted.org/packages/aa/82/f790ed167c04b8d2a33bed30770a9b7066fc4f573321d797190e5f05685f/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4bce006121b120e8b359244ee140bb0b1093908efc8b739db8dbaa3f8fb42139", size = 2672077, upload-time = "2025-10-19T00:40:34.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b3/80b8183e7eee44f45bfa3cdd3ebdadf3dd43ffc686f96d442a6c4dded45d/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fc0f1e4e9bb384d26e73c6657bbc26abdae4ff66a95933c00f3d578be89181b", size = 2881589, upload-time = "2025-10-19T00:40:36.315Z" }, + { url = "https://files.pythonhosted.org/packages/8f/05/ac5ba5ddb88a3ba7ecea4bf192194a838af564d22ea7a4812cbb6bd106ce/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:dd3f894ff972da1994d06ac6157d74e40dda19eb31fe5e9b7863ca4278c3a167", size = 2589924, upload-time = "2025-10-19T00:40:38.317Z" }, + { url = "https://files.pythonhosted.org/packages/8e/cd/100483cae3849d24351c8333a815dc6adaf3f04912486e59386d86d9db9a/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0846f49cf8a4496bd42659040e68bd0484ce6af819709cae234938e039203ba0", size = 2868059, upload-time = "2025-10-19T00:40:40.025Z" }, + { url = "https://files.pythonhosted.org/packages/34/6e/3a7c56b325772d39397fc3aafb4dc054273982097178b6c3917c6dad48de/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:16a3af394ade1973226d64bb2f9eb3336adbdea03ed5b134c1bbec5a3b20028e", size = 2721692, upload-time = "2025-10-19T00:40:41.621Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ca/9fdaee32c3bc769dfb7e7991d9499136afccea67e423d097b8fb3c5acbc1/cytoolz-1.1.0-cp311-cp311-win32.whl", hash = "sha256:b786c9c8aeab76cc2f76011e986f7321a23a56d985b77d14f155d5e5514ea781", size = 899349, upload-time = "2025-10-19T00:40:43.183Z" }, + { url = "https://files.pythonhosted.org/packages/fd/04/2ab98edeea90311e4029e1643e43d2027b54da61453292d9ea51a103ee87/cytoolz-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:ebf06d1c5344fb22fee71bf664234733e55db72d74988f2ecb7294b05e4db30c", size = 945831, upload-time = "2025-10-19T00:40:44.693Z" }, + { url = "https://files.pythonhosted.org/packages/b4/8d/777d86ea6bcc68b0fc926b0ef8ab51819e2176b37aadea072aac949d5231/cytoolz-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:b63f5f025fac893393b186e132e3e242de8ee7265d0cd3f5bdd4dda93f6616c9", size = 904076, upload-time = "2025-10-19T00:40:46.678Z" }, + { url = "https://files.pythonhosted.org/packages/c6/ec/01426224f7acf60183d3921b25e1a8e71713d3d39cb464d64ac7aace6ea6/cytoolz-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:99f8e134c9be11649342853ec8c90837af4089fc8ff1e8f9a024a57d1fa08514", size = 1327800, upload-time = "2025-10-19T00:40:48.674Z" }, + { url = "https://files.pythonhosted.org/packages/b4/07/e07e8fedd332ac9626ad58bea31416dda19bfd14310731fa38b16a97e15f/cytoolz-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0a6f44cf9319c30feb9a50aa513d777ef51efec16f31c404409e7deb8063df64", size = 997118, upload-time = "2025-10-19T00:40:50.919Z" }, + { url = "https://files.pythonhosted.org/packages/ab/72/c0f766d63ed2f9ea8dc8e1628d385d99b41fb834ce17ac3669e3f91e115d/cytoolz-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:945580dc158c557172fca899a35a99a16fbcebf6db0c77cb6621084bc82189f9", size = 991169, upload-time = "2025-10-19T00:40:52.887Z" }, + { url = "https://files.pythonhosted.org/packages/df/4b/1f757353d1bf33e56a7391ecc9bc49c1e529803b93a9d2f67fe5f92906fe/cytoolz-1.1.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:257905ec050d04f2f856854620d1e25556fd735064cebd81b460f54939b9f9d5", size = 2700680, upload-time = "2025-10-19T00:40:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/25/73/9b25bb7ed8d419b9d6ff2ae0b3d06694de79a3f98f5169a1293ff7ad3a3f/cytoolz-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82779049f352fb3ab5e8c993ab45edbb6e02efb1f17f0b50f4972c706cc51d76", size = 2824951, upload-time = "2025-10-19T00:40:56.137Z" }, + { url = "https://files.pythonhosted.org/packages/0c/93/9c787f7c909e75670fff467f2504725d06d8c3f51d6dfe22c55a08c8ccd4/cytoolz-1.1.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7d3e405e435320e08c5a1633afaf285a392e2d9cef35c925d91e2a31dfd7a688", size = 2679635, upload-time = "2025-10-19T00:40:57.799Z" }, + { url = "https://files.pythonhosted.org/packages/50/aa/9ee92c302cccf7a41a7311b325b51ebeff25d36c1f82bdc1bbe3f58dc947/cytoolz-1.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:923df8f5591e0d20543060c29909c149ab1963a7267037b39eee03a83dbc50a8", size = 2938352, upload-time = "2025-10-19T00:40:59.49Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a3/3b58c5c1692c3bacd65640d0d5c7267a7ebb76204f7507aec29de7063d2f/cytoolz-1.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:25db9e4862f22ea0ae2e56c8bec9fc9fd756b655ae13e8c7b5625d7ed1c582d4", size = 3022121, upload-time = "2025-10-19T00:41:01.209Z" }, + { url = "https://files.pythonhosted.org/packages/e1/93/c647bc3334355088c57351a536c2d4a83dd45f7de591fab383975e45bff9/cytoolz-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7a98deb11ccd8e5d9f9441ef2ff3352aab52226a2b7d04756caaa53cd612363", size = 2857656, upload-time = "2025-10-19T00:41:03.456Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c2/43fea146bf4141deea959e19dcddf268c5ed759dec5c2ed4a6941d711933/cytoolz-1.1.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dce4ee9fc99104bc77efdea80f32ca5a650cd653bcc8a1d984a931153d3d9b58", size = 2551284, upload-time = "2025-10-19T00:41:05.347Z" }, + { url = "https://files.pythonhosted.org/packages/6f/df/cdc7a81ce5cfcde7ef523143d545635fc37e80ccacce140ae58483a21da3/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80d6da158f7d20c15819701bbda1c041f0944ede2f564f5c739b1bc80a9ffb8b", size = 2721673, upload-time = "2025-10-19T00:41:07.528Z" }, + { url = "https://files.pythonhosted.org/packages/45/be/f8524bb9ad8812ad375e61238dcaa3177628234d1b908ad0b74e3657cafd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3b5c5a192abda123ad45ef716ec9082b4cf7d95e9ada8291c5c2cc5558be858b", size = 2722884, upload-time = "2025-10-19T00:41:09.698Z" }, + { url = "https://files.pythonhosted.org/packages/23/e6/6bb8e4f9c267ad42d1ff77b6d2e4984665505afae50a216290e1d7311431/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5b399ce7d967b1cb6280250818b786be652aa8ddffd3c0bb5c48c6220d945ab5", size = 2685486, upload-time = "2025-10-19T00:41:11.349Z" }, + { url = "https://files.pythonhosted.org/packages/d7/dd/88619f9c8d2b682562c0c886bbb7c35720cb83fda2ac9a41bdd14073d9bd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e7e29a1a03f00b4322196cfe8e2c38da9a6c8d573566052c586df83aacc5663c", size = 2839661, upload-time = "2025-10-19T00:41:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/b8/8d/4478ebf471ee78dd496d254dc0f4ad729cd8e6ba8257de4f0a98a2838ef2/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5291b117d71652a817ec164e7011f18e6a51f8a352cc9a70ed5b976c51102fda", size = 2547095, upload-time = "2025-10-19T00:41:16.054Z" }, + { url = "https://files.pythonhosted.org/packages/e6/68/f1dea33367b0b3f64e199c230a14a6b6f243c189020effafd31e970ca527/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8caef62f846a9011676c51bda9189ae394cdd6bb17f2946ecaedc23243268320", size = 2870901, upload-time = "2025-10-19T00:41:17.727Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9a/33591c09dfe799b8fb692cf2ad383e2c41ab6593cc960b00d1fc8a145655/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:de425c5a8e3be7bb3a195e19191d28d9eb3c2038046064a92edc4505033ec9cb", size = 2765422, upload-time = "2025-10-19T00:41:20.075Z" }, + { url = "https://files.pythonhosted.org/packages/60/2b/a8aa233c9416df87f004e57ae4280bd5e1f389b4943d179f01020c6ec629/cytoolz-1.1.0-cp312-cp312-win32.whl", hash = "sha256:296440a870e8d1f2e1d1edf98f60f1532b9d3ab8dfbd4b25ec08cd76311e79e5", size = 901933, upload-time = "2025-10-19T00:41:21.646Z" }, + { url = "https://files.pythonhosted.org/packages/ad/33/4c9bdf8390dc01d2617c7f11930697157164a52259b6818ddfa2f94f89f4/cytoolz-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:07156987f224c6dac59aa18fb8bf91e1412f5463961862716a3381bf429c8699", size = 947989, upload-time = "2025-10-19T00:41:23.288Z" }, + { url = "https://files.pythonhosted.org/packages/35/ac/6e2708835875f5acb52318462ed296bf94ed0cb8c7cb70e62fbd03f709e3/cytoolz-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:23e616b38f5b3160c7bb45b0f84a8f3deb4bd26b29fb2dfc716f241c738e27b8", size = 903913, upload-time = "2025-10-19T00:41:24.992Z" }, + { url = "https://files.pythonhosted.org/packages/71/4a/b3ddb3ee44fe0045e95dd973746f93f033b6f92cce1fc3cbbe24b329943c/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:76c9b58555300be6dde87a41faf1f97966d79b9a678b7a526fcff75d28ef4945", size = 976728, upload-time = "2025-10-19T00:41:26.5Z" }, + { url = "https://files.pythonhosted.org/packages/42/21/a3681434aa425875dd828bb515924b0f12c37a55c7d2bc5c0c5de3aeb0b4/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d1d638b10d3144795655e9395566ce35807df09219fd7cacd9e6acbdef67946a", size = 986057, upload-time = "2025-10-19T00:41:28.911Z" }, + { url = "https://files.pythonhosted.org/packages/d9/cb/efc1b29e211e0670a6953222afaac84dcbba5cb940b130c0e49858978040/cytoolz-1.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:26801c1a165e84786a99e03c9c9973356caaca002d66727b761fb1042878ef06", size = 992632, upload-time = "2025-10-19T00:41:30.612Z" }, + { url = "https://files.pythonhosted.org/packages/be/b0/e50621d21e939338c97faab651f58ea7fa32101226a91de79ecfb89d71e1/cytoolz-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a9a464542912d3272f6dccc5142df057c71c6a5cbd30439389a732df401afb7", size = 1317534, upload-time = "2025-10-19T00:41:32.625Z" }, + { url = "https://files.pythonhosted.org/packages/0d/6b/25aa9739b0235a5bc4c1ea293186bc6822a4c6607acfe1422423287e7400/cytoolz-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ed6104fa942aa5784bf54f339563de637557e3443b105760bc4de8f16a7fc79b", size = 992336, upload-time = "2025-10-19T00:41:34.073Z" }, + { url = "https://files.pythonhosted.org/packages/e1/53/5f4deb0ff958805309d135d899c764364c1e8a632ce4994bd7c45fb98df2/cytoolz-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56161f0ab60dc4159ec343509abaf809dc88e85c7e420e354442c62e3e7cbb77", size = 986118, upload-time = "2025-10-19T00:41:35.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e3/f6255b76c8cc0debbe1c0779130777dc0434da6d9b28a90d9f76f8cb67cd/cytoolz-1.1.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:832bd36cc9123535f1945acf6921f8a2a15acc19cfe4065b1c9b985a28671886", size = 2679563, upload-time = "2025-10-19T00:41:37.926Z" }, + { url = "https://files.pythonhosted.org/packages/59/8a/acc6e39a84e930522b965586ad3a36694f9bf247b23188ee0eb47b1c9ed1/cytoolz-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1842636b6e034f229bf084c2bcdcfd36c8437e752eefd2c74ce9e2f10415cb6e", size = 2813020, upload-time = "2025-10-19T00:41:39.935Z" }, + { url = "https://files.pythonhosted.org/packages/db/f5/0083608286ad1716eda7c41f868e85ac549f6fd6b7646993109fa0bdfd98/cytoolz-1.1.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:823df012ab90d2f2a0f92fea453528539bf71ac1879e518524cd0c86aa6df7b9", size = 2669312, upload-time = "2025-10-19T00:41:41.55Z" }, + { url = "https://files.pythonhosted.org/packages/47/a8/d16080b575520fe5da00cede1ece4e0a4180ec23f88dcdc6a2f5a90a7f7f/cytoolz-1.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f1fcf9e7e7b3487883ff3f815abc35b89dcc45c4cf81c72b7ee457aa72d197b", size = 2922147, upload-time = "2025-10-19T00:41:43.252Z" }, + { url = "https://files.pythonhosted.org/packages/7e/bc/716c9c1243701e58cad511eb3937fd550e645293c5ed1907639c5d66f194/cytoolz-1.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4cdb3fa1772116827f263f25b0cdd44c663b6701346a56411960534a06c082de", size = 2981602, upload-time = "2025-10-19T00:41:45.354Z" }, + { url = "https://files.pythonhosted.org/packages/14/bc/571b232996846b27f4ac0c957dc8bf60261e9b4d0d01c8d955e82329544e/cytoolz-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1b5c95041741b81430454db65183e133976f45ac3c03454cfa8147952568529", size = 2830103, upload-time = "2025-10-19T00:41:47.959Z" }, + { url = "https://files.pythonhosted.org/packages/5b/55/c594afb46ecd78e4b7e1fb92c947ed041807875661ceda73baaf61baba4f/cytoolz-1.1.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b2079fd9f1a65f4c61e6278c8a6d4f85edf30c606df8d5b32f1add88cbbe2286", size = 2533802, upload-time = "2025-10-19T00:41:49.683Z" }, + { url = "https://files.pythonhosted.org/packages/93/83/1edcf95832555a78fc43b975f3ebe8ceadcc9664dd47fd33747a14df5069/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a92a320d72bef1c7e2d4c6d875125cf57fc38be45feb3fac1bfa64ea401f54a4", size = 2706071, upload-time = "2025-10-19T00:41:51.386Z" }, + { url = "https://files.pythonhosted.org/packages/e2/df/035a408df87f25cfe3611557818b250126cd2281b2104cd88395de205583/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06d1c79aa51e6a92a90b0e456ebce2288f03dd6a76c7f582bfaa3eda7692e8a5", size = 2707575, upload-time = "2025-10-19T00:41:53.305Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a4/ef78e13e16e93bf695a9331321d75fbc834a088d941f1c19e6b63314e257/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e1d7be25f6971e986a52b6d3a0da28e1941850985417c35528f6823aef2cfec5", size = 2660486, upload-time = "2025-10-19T00:41:55.542Z" }, + { url = "https://files.pythonhosted.org/packages/30/7a/2c3d60682b26058d435416c4e90d4a94db854de5be944dfd069ed1be648a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:964b248edc31efc50a65e9eaa0c845718503823439d2fa5f8d2c7e974c2b5409", size = 2819605, upload-time = "2025-10-19T00:41:58.257Z" }, + { url = "https://files.pythonhosted.org/packages/45/92/19b722a1d83cc443fbc0c16e0dc376f8a451437890d3d9ee370358cf0709/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c9ff2b3c57c79b65cb5be14a18c6fd4a06d5036fb3f33e973a9f70e9ac13ca28", size = 2533559, upload-time = "2025-10-19T00:42:00.324Z" }, + { url = "https://files.pythonhosted.org/packages/1d/15/fa3b7891da51115204416f14192081d3dea0eaee091f123fdc1347de8dd1/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:22290b73086af600042d99f5ce52a43d4ad9872c382610413176e19fc1d4fd2d", size = 2839171, upload-time = "2025-10-19T00:42:01.881Z" }, + { url = "https://files.pythonhosted.org/packages/46/40/d3519d5cd86eebebf1e8b7174ec32dfb6ecec67b48b0cfb92bf226659b5a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a2ade74fccd080ea793382968913ee38d7a35c921df435bbf0a6aeecf0d17574", size = 2743379, upload-time = "2025-10-19T00:42:03.809Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/a9e7511f0a13fdbefa5bf73cf8e4763878140de9453fd3e50d6ac57b6be7/cytoolz-1.1.0-cp313-cp313-win32.whl", hash = "sha256:db5dbcfda1c00e937426cbf9bdc63c24ebbc358c3263bfcbc1ab4a88dc52aa8e", size = 900844, upload-time = "2025-10-19T00:42:05.967Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a4/fb7eb403c6a4c81e5a30363f34a71adcc8bf5292dc8ea32e2440aa5668f2/cytoolz-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9e2d3fe3b45c3eb7233746f7aca37789be3dceec3e07dcc406d3e045ea0f7bdc", size = 946461, upload-time = "2025-10-19T00:42:07.983Z" }, + { url = "https://files.pythonhosted.org/packages/93/bb/1c8c33d353548d240bc6e8677ee8c3560ce5fa2f084e928facf7c35a6dcf/cytoolz-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:32c559f95ff44a9ebcbd934acaa1e6dc8f3e6ffce4762a79a88528064873d6d5", size = 902673, upload-time = "2025-10-19T00:42:09.982Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/4a53acc60f59030fcaf48c7766e3c4c81bd997379425aa45b129396557b5/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9e2cd93b28f667c5870a070ab2b8bb4397470a85c4b204f2454b0ad001cd1ca3", size = 1372336, upload-time = "2025-10-19T00:42:12.104Z" }, + { url = "https://files.pythonhosted.org/packages/ac/90/f28fd8ad8319d8f5c8da69a2c29b8cf52a6d2c0161602d92b366d58926ab/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f494124e141a9361f31d79875fe7ea459a3be2b9dadd90480427c0c52a0943d4", size = 1011930, upload-time = "2025-10-19T00:42:14.231Z" }, + { url = "https://files.pythonhosted.org/packages/c9/95/4561c4e0ad1c944f7673d6d916405d68080f10552cfc5d69a1cf2475a9a1/cytoolz-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53a3262bf221f19437ed544bf8c0e1980c81ac8e2a53d87a9bc075dba943d36f", size = 1020610, upload-time = "2025-10-19T00:42:15.877Z" }, + { url = "https://files.pythonhosted.org/packages/c3/14/b2e1ffa4995ec36e1372e243411ff36325e4e6d7ffa34eb4098f5357d176/cytoolz-1.1.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:47663e57d3f3f124921f38055e86a1022d0844c444ede2e8f090d3bbf80deb65", size = 2917327, upload-time = "2025-10-19T00:42:17.706Z" }, + { url = "https://files.pythonhosted.org/packages/4a/29/7cab6c609b4514ac84cca2f7dca6c509977a8fc16d27c3a50e97f105fa6a/cytoolz-1.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5a8755c4104ee4e3d5ba434c543b5f85fdee6a1f1df33d93f518294da793a60", size = 3108951, upload-time = "2025-10-19T00:42:19.363Z" }, + { url = "https://files.pythonhosted.org/packages/9a/71/1d1103b819458679277206ad07d78ca6b31c4bb88d6463fd193e19bfb270/cytoolz-1.1.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4d96ff3d381423af1b105295f97de86d1db51732c9566eb37378bab6670c5010", size = 2807149, upload-time = "2025-10-19T00:42:20.964Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d4/3d83a05a21e7d2ed2b9e6daf489999c29934b005de9190272b8a2e3735d0/cytoolz-1.1.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0ec96b3d537cdf47d4e76ded199f7440715f4c71029b45445cff92c1248808c2", size = 3111608, upload-time = "2025-10-19T00:42:22.684Z" }, + { url = "https://files.pythonhosted.org/packages/51/88/96f68354c3d4af68de41f0db4fe41a23b96a50a4a416636cea325490cfeb/cytoolz-1.1.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:208e2f2ef90a32b0acbff3303d90d89b13570a228d491d2e622a7883a3c68148", size = 3179373, upload-time = "2025-10-19T00:42:24.395Z" }, + { url = "https://files.pythonhosted.org/packages/ce/50/ed87a5cd8e6f27ffbb64c39e9730e18ec66c37631db2888ae711909f10c9/cytoolz-1.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d416a81bb0bd517558668e49d30a7475b5445f9bbafaab7dcf066f1e9adba36", size = 3003120, upload-time = "2025-10-19T00:42:26.18Z" }, + { url = "https://files.pythonhosted.org/packages/d3/a7/acde155b050d6eaa8e9c7845c98fc5fb28501568e78e83ebbf44f8855274/cytoolz-1.1.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f32e94c91ffe49af04835ee713ebd8e005c85ebe83e7e1fdcc00f27164c2d636", size = 2703225, upload-time = "2025-10-19T00:42:27.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b6/9d518597c5bdea626b61101e8d2ff94124787a42259dafd9f5fc396f346a/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15d0c6405efc040499c46df44056a5c382f551a7624a41cf3e4c84a96b988a15", size = 2956033, upload-time = "2025-10-19T00:42:29.993Z" }, + { url = "https://files.pythonhosted.org/packages/89/7a/93e5f860926165538c85e1c5e1670ad3424f158df810f8ccd269da652138/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:bf069c5381d757debae891401b88b3a346ba3a28ca45ba9251103b282463fad8", size = 2862950, upload-time = "2025-10-19T00:42:31.803Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/99d6af00487bedc27597b54c9fcbfd5c833a69c6b7a9b9f0fff777bfc7aa/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d5cf15892e63411ec1bd67deff0e84317d974e6ab2cdfefdd4a7cea2989df66", size = 2861757, upload-time = "2025-10-19T00:42:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/71/ca/adfa1fb7949478135a37755cb8e88c20cd6b75c22a05f1128f05f3ab2c60/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3e3872c21170f8341656f8692f8939e8800dcee6549ad2474d4c817bdefd62cd", size = 2979049, upload-time = "2025-10-19T00:42:35.377Z" }, + { url = "https://files.pythonhosted.org/packages/70/4c/7bf47a03a4497d500bc73d4204e2d907771a017fa4457741b2a1d7c09319/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b9ddeff8e8fd65eb1fcefa61018100b2b627e759ea6ad275d2e2a93ffac147bf", size = 2699492, upload-time = "2025-10-19T00:42:37.133Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e7/3d034b0e4817314f07aa465d5864e9b8df9d25cb260a53dd84583e491558/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:02feeeda93e1fa3b33414eb57c2b0aefd1db8f558dd33fdfcce664a0f86056e4", size = 2995646, upload-time = "2025-10-19T00:42:38.912Z" }, + { url = "https://files.pythonhosted.org/packages/c1/62/be357181c71648d9fe1d1ce91cd42c63457dcf3c158e144416fd51dced83/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d08154ad45349162b6c37f12d5d1b2e6eef338e657b85e1621e4e6a4a69d64cb", size = 2919481, upload-time = "2025-10-19T00:42:40.85Z" }, + { url = "https://files.pythonhosted.org/packages/62/d5/bf5434fde726c4f80cb99912b2d8e0afa1587557e2a2d7e0315eb942f2de/cytoolz-1.1.0-cp313-cp313t-win32.whl", hash = "sha256:10ae4718a056948d73ca3e1bb9ab1f95f897ec1e362f829b9d37cc29ab566c60", size = 951595, upload-time = "2025-10-19T00:42:42.877Z" }, + { url = "https://files.pythonhosted.org/packages/64/29/39c161e9204a9715321ddea698cbd0abc317e78522c7c642363c20589e71/cytoolz-1.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:1bb77bc6197e5cb19784b6a42bb0f8427e81737a630d9d7dda62ed31733f9e6c", size = 1004445, upload-time = "2025-10-19T00:42:44.855Z" }, + { url = "https://files.pythonhosted.org/packages/e2/5a/7cbff5e9a689f558cb0bdf277f9562b2ac51acf7cd15e055b8c3efb0e1ef/cytoolz-1.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:563dda652c6ff52d215704fbe6b491879b78d7bbbb3a9524ec8e763483cb459f", size = 926207, upload-time = "2025-10-19T00:42:46.456Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e8/297a85ba700f437c01eba962428e6ab4572f6c3e68e8ff442ce5c9d3a496/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d542cee7c7882d2a914a33dec4d3600416fb336734df979473249d4c53d207a1", size = 980613, upload-time = "2025-10-19T00:42:47.988Z" }, + { url = "https://files.pythonhosted.org/packages/e8/d7/2b02c9d18e9cc263a0e22690f78080809f1eafe72f26b29ccc115d3bf5c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31922849b701b0f24bb62e56eb2488dcd3aa6ae3057694bd6b3b7c4c2bc27c2f", size = 990476, upload-time = "2025-10-19T00:42:49.653Z" }, + { url = "https://files.pythonhosted.org/packages/89/26/b6b159d2929310fca0eff8a4989cd4b1ecbdf7c46fdff46c7a20fcae55c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e68308d32afd31943314735c1335e4ab5696110e96b405f6bdb8f2a8dc771a16", size = 992712, upload-time = "2025-10-19T00:42:51.306Z" }, + { url = "https://files.pythonhosted.org/packages/42/a0/f7c572aa151ed466b0fce4a327c3cc916d3ef3c82e341be59ea4b9bee9e4/cytoolz-1.1.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fc4bb48b3b866e1867f7c6411a4229e5b44be3989060663713e10efc24c9bd5f", size = 1322596, upload-time = "2025-10-19T00:42:52.978Z" }, + { url = "https://files.pythonhosted.org/packages/72/7c/a55d035e20b77b6725e85c8f1a418b3a4c23967288b8b0c2d1a40f158cbe/cytoolz-1.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:456f77207d1445025d7ef262b8370a05492dcb1490cb428b0f3bf1bd744a89b0", size = 992825, upload-time = "2025-10-19T00:42:55.026Z" }, + { url = "https://files.pythonhosted.org/packages/03/af/39d2d3db322136e12e9336a1f13bab51eab88b386bfb11f91d3faff8ba34/cytoolz-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:174ebc71ebb20a9baeffce6ee07ee2cd913754325c93f99d767380d8317930f7", size = 990525, upload-time = "2025-10-19T00:42:56.666Z" }, + { url = "https://files.pythonhosted.org/packages/a6/bd/65d7a869d307f9b10ad45c2c1cbb40b81a8d0ed1138fa17fd904f5c83298/cytoolz-1.1.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8b3604fef602bcd53415055a4f68468339192fd17be39e687ae24f476d23d56e", size = 2672409, upload-time = "2025-10-19T00:42:58.81Z" }, + { url = "https://files.pythonhosted.org/packages/2d/fb/74dfd844bfd67e810bd36e8e3903a143035447245828e7fcd7c81351d775/cytoolz-1.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3604b959a01f64c366e7d10ec7634d5f5cfe10301e27a8f090f6eb3b2a628a18", size = 2808477, upload-time = "2025-10-19T00:43:00.577Z" }, + { url = "https://files.pythonhosted.org/packages/d6/1f/587686c43e31c19241ec317da66438d093523921ea7749bbc65558a30df9/cytoolz-1.1.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6db2127a3c1bc2f59f08010d2ae53a760771a9de2f67423ad8d400e9ba4276e8", size = 2636881, upload-time = "2025-10-19T00:43:02.24Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6d/90468cd34f77cb38a11af52c4dc6199efcc97a486395a21bef72e9b7602e/cytoolz-1.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56584745ac647993a016a21bc76399113b7595e312f8d0a1b140c9fcf9b58a27", size = 2937315, upload-time = "2025-10-19T00:43:03.954Z" }, + { url = "https://files.pythonhosted.org/packages/d9/50/7b92cd78c613b92e3509e6291d3fb7e0d72ebda999a8df806a96c40ca9ab/cytoolz-1.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db2c4c3a7f7bd7e03bb1a236a125c8feb86c75802f4ecda6ecfaf946610b2930", size = 2959988, upload-time = "2025-10-19T00:43:05.758Z" }, + { url = "https://files.pythonhosted.org/packages/44/d5/34b5a28a8d9bb329f984b4c2259407ca3f501d1abeb01bacea07937d85d1/cytoolz-1.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48cb8a692111a285d2b9acd16d185428176bfbffa8a7c274308525fccd01dd42", size = 2795116, upload-time = "2025-10-19T00:43:07.411Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d9/5dd829e33273ec03bdc3c812e6c3281987ae2c5c91645582f6c331544a64/cytoolz-1.1.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d2f344ba5eb17dcf38ee37fdde726f69053f54927db8f8a1bed6ac61e5b1890d", size = 2535390, upload-time = "2025-10-19T00:43:09.104Z" }, + { url = "https://files.pythonhosted.org/packages/87/1f/7f9c58068a8eec2183110df051bc6b69dd621143f84473eeb6dc1b32905a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:abf76b1c1abd031f098f293b6d90ee08bdaa45f8b5678430e331d991b82684b1", size = 2704834, upload-time = "2025-10-19T00:43:10.942Z" }, + { url = "https://files.pythonhosted.org/packages/d2/90/667def5665333575d01a65fe3ec0ca31b897895f6e3bc1a42d6ea3659369/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ddf9a38a5b686091265ff45b53d142e44a538cd6c2e70610d3bc6be094219032", size = 2658441, upload-time = "2025-10-19T00:43:12.655Z" }, + { url = "https://files.pythonhosted.org/packages/23/79/6615f9a14960bd29ac98b823777b6589357833f65cf1a11b5abc1587c120/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:946786755274f07bb2be0400f28adb31d7d85a7c7001873c0a8e24a503428fb3", size = 2654766, upload-time = "2025-10-19T00:43:14.325Z" }, + { url = "https://files.pythonhosted.org/packages/b0/99/be59c6e0ae02153ef10ae1ff0f380fb19d973c651b50cf829a731f6c9e79/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b8f78b9fed79cf185ad4ddec099abeef45951bdcb416c5835ba05f0a1242c7", size = 2827649, upload-time = "2025-10-19T00:43:16.132Z" }, + { url = "https://files.pythonhosted.org/packages/19/b7/854ddcf9f9618844108677c20d48f4611b5c636956adea0f0e85e027608f/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fccde6efefdbc02e676ccb352a2ccc8a8e929f59a1c6d3d60bb78e923a49ca44", size = 2533456, upload-time = "2025-10-19T00:43:17.764Z" }, + { url = "https://files.pythonhosted.org/packages/45/66/bfe6fbb2bdcf03c8377c8c2f542576e15f3340c905a09d78a6cb3badd39a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:717b7775313da5f51b0fbf50d865aa9c39cb241bd4cb605df3cf2246d6567397", size = 2826455, upload-time = "2025-10-19T00:43:19.561Z" }, + { url = "https://files.pythonhosted.org/packages/c3/0c/cce4047bd927e95f59e73319c02c9bc86bd3d76392e0eb9e41a1147a479c/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5158744a09d0e0e4a4f82225e3a3c4ebf38f9ae74467aaa905467270e52f2794", size = 2714897, upload-time = "2025-10-19T00:43:21.291Z" }, + { url = "https://files.pythonhosted.org/packages/ac/9a/061323bb289b565802bad14fb7ab59fcd8713105df142bcf4dd9ff64f8ac/cytoolz-1.1.0-cp314-cp314-win32.whl", hash = "sha256:1ed534bdbbf063b2bb28fca7d0f6723a3e5a72b086e7c7fe6d74ae8c3e4d00e2", size = 901490, upload-time = "2025-10-19T00:43:22.895Z" }, + { url = "https://files.pythonhosted.org/packages/a3/20/1f3a733d710d2a25d6f10b463bef55ada52fe6392a5d233c8d770191f48a/cytoolz-1.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:472c1c9a085f5ad973ec0ad7f0b9ba0969faea6f96c9e397f6293d386f3a25ec", size = 946730, upload-time = "2025-10-19T00:43:24.838Z" }, + { url = "https://files.pythonhosted.org/packages/f2/22/2d657db4a5d1c10a152061800f812caba9ef20d7bd2406f51a5fd800c180/cytoolz-1.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:a7ad7ca3386fa86bd301be3fa36e7f0acb024f412f665937955acfc8eb42deff", size = 905722, upload-time = "2025-10-19T00:43:26.439Z" }, + { url = "https://files.pythonhosted.org/packages/19/97/b4a8c76796a9a8b9bc90c7992840fa1589a1af8e0426562dea4ce9b384a7/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:64b63ed4b71b1ba813300ad0f06b8aff19a12cf51116e0e4f1ed837cea4debcf", size = 1372606, upload-time = "2025-10-19T00:43:28.491Z" }, + { url = "https://files.pythonhosted.org/packages/08/d4/a1bb1a32b454a2d650db8374ff3bf875ba0fc1c36e6446ec02a83b9140a1/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a60ba6f2ed9eb0003a737e1ee1e9fa2258e749da6477946008d4324efa25149f", size = 1012189, upload-time = "2025-10-19T00:43:30.177Z" }, + { url = "https://files.pythonhosted.org/packages/21/4b/2f5cbbd81588918ee7dd70cffb66731608f578a9b72166aafa991071af7d/cytoolz-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1aa58e2434d732241f7f051e6f17657e969a89971025e24578b5cbc6f1346485", size = 1020624, upload-time = "2025-10-19T00:43:31.712Z" }, + { url = "https://files.pythonhosted.org/packages/f5/99/c4954dd86cd593cd776a038b36795a259b8b5c12cbab6363edf5f6d9c909/cytoolz-1.1.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6965af3fc7214645970e312deb9bd35a213a1eaabcfef4f39115e60bf2f76867", size = 2917016, upload-time = "2025-10-19T00:43:33.531Z" }, + { url = "https://files.pythonhosted.org/packages/b2/7c/f1f70a17e272b433232bc8a27df97e46b202d6cc07e3b0d63f7f41ba0f2d/cytoolz-1.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddd2863f321d67527d3b67a93000a378ad6f967056f68c06467fe011278a6d0e", size = 3107634, upload-time = "2025-10-19T00:43:35.57Z" }, + { url = "https://files.pythonhosted.org/packages/8f/bd/c3226a57474b4aef1f90040510cba30d0decd3515fed48dc229b37c2f898/cytoolz-1.1.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4e6b428e9eb5126053c2ae0efa62512ff4b38ed3951f4d0888ca7005d63e56f5", size = 2806221, upload-time = "2025-10-19T00:43:37.707Z" }, + { url = "https://files.pythonhosted.org/packages/c3/47/2f7bfe4aaa1e07dc9828bea228ed744faf73b26aee0c1bdf3b5520bf1909/cytoolz-1.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d758e5ef311d2671e0ae8c214c52e44617cf1e58bef8f022b547b9802a5a7f30", size = 3107671, upload-time = "2025-10-19T00:43:39.401Z" }, + { url = "https://files.pythonhosted.org/packages/4d/12/6ff3b04fbd1369d0fcd5f8b5910ba6e427e33bf113754c4c35ec3f747924/cytoolz-1.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a95416eca473e6c1179b48d86adcf528b59c63ce78f4cb9934f2e413afa9b56b", size = 3176350, upload-time = "2025-10-19T00:43:41.148Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/6691d986b728e77b5d2872743ebcd962d37a2d0f7e9ad95a81b284fbf905/cytoolz-1.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36c8ede93525cf11e2cc787b7156e5cecd7340193ef800b816a16f1404a8dc6d", size = 3001173, upload-time = "2025-10-19T00:43:42.923Z" }, + { url = "https://files.pythonhosted.org/packages/7a/cb/f59d83a5058e1198db5a1f04e4a124c94d60390e4fa89b6d2e38ee8288a0/cytoolz-1.1.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c949755b6d8a649c5fbc888bc30915926f1b09fe42fea9f289e297c2f6ddd3", size = 2701374, upload-time = "2025-10-19T00:43:44.716Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f0/1ae6d28df503b0bdae094879da2072b8ba13db5919cd3798918761578411/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e1b6d37545816905a76d9ed59fa4e332f929e879f062a39ea0f6f620405cdc27", size = 2953081, upload-time = "2025-10-19T00:43:47.103Z" }, + { url = "https://files.pythonhosted.org/packages/f4/06/d86fe811c6222dc32d3e08f5d88d2be598a6055b4d0590e7c1428d55c386/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:05332112d4087904842b36954cd1d3fc0e463a2f4a7ef9477bd241427c593c3b", size = 2862228, upload-time = "2025-10-19T00:43:49.353Z" }, + { url = "https://files.pythonhosted.org/packages/ae/32/978ef6f42623be44a0a03ae9de875ab54aa26c7e38c5c4cd505460b0927d/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:31538ca2fad2d688cbd962ccc3f1da847329e2258a52940f10a2ac0719e526be", size = 2861971, upload-time = "2025-10-19T00:43:51.028Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f7/74c69497e756b752b359925d1feef68b91df024a4124a823740f675dacd3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:747562aa70abf219ea16f07d50ac0157db856d447f7f498f592e097cbc77df0b", size = 2975304, upload-time = "2025-10-19T00:43:52.99Z" }, + { url = "https://files.pythonhosted.org/packages/5b/2b/3ce0e6889a6491f3418ad4d84ae407b8456b02169a5a1f87990dbba7433b/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:3dc15c48b20c0f467e15e341e102896c8422dccf8efc6322def5c1b02f074629", size = 2697371, upload-time = "2025-10-19T00:43:55.312Z" }, + { url = "https://files.pythonhosted.org/packages/15/87/c616577f0891d97860643c845f7221e95240aa589586de727e28a5eb6e52/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3c03137ee6103ba92d5d6ad6a510e86fded69cd67050bd8a1843f15283be17ac", size = 2992436, upload-time = "2025-10-19T00:43:57.253Z" }, + { url = "https://files.pythonhosted.org/packages/e7/9f/490c81bffb3428ab1fa114051fbb5ba18aaa2e2fe4da5bf4170ca524e6b3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:be8e298d88f88bd172b59912240558be3b7a04959375646e7fd4996401452941", size = 2917612, upload-time = "2025-10-19T00:43:59.423Z" }, + { url = "https://files.pythonhosted.org/packages/66/35/0fec2769660ca6472bbf3317ab634675827bb706d193e3240aaf20eab961/cytoolz-1.1.0-cp314-cp314t-win32.whl", hash = "sha256:3d407140f5604a89578285d4aac7b18b8eafa055cf776e781aabb89c48738fad", size = 960842, upload-time = "2025-10-19T00:44:01.143Z" }, + { url = "https://files.pythonhosted.org/packages/46/b4/b7ce3d3cd20337becfec978ecfa6d0ef64884d0cf32d44edfed8700914b9/cytoolz-1.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:56e5afb69eb6e1b3ffc34716ee5f92ffbdb5cb003b3a5ca4d4b0fe700e217162", size = 1020835, upload-time = "2025-10-19T00:44:03.246Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1f/0498009aa563a9c5d04f520aadc6e1c0942434d089d0b2f51ea986470f55/cytoolz-1.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:27b19b4a286b3ff52040efa42dbe403730aebe5fdfd2def704eb285e2125c63e", size = 927963, upload-time = "2025-10-19T00:44:04.85Z" }, + { url = "https://files.pythonhosted.org/packages/84/32/0522207170294cf691112a93c70a8ef942f60fa9ff8e793b63b1f09cedc0/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f32e93a55681d782fc6af939f6df36509d65122423cbc930be39b141064adff8", size = 922014, upload-time = "2025-10-19T00:44:44.911Z" }, + { url = "https://files.pythonhosted.org/packages/4c/49/9be2d24adaa18fa307ff14e3e43f02b2ae4b69c4ce51cee6889eb2114990/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5d9bc596751cbda8073e65be02ca11706f00029768fbbbc81e11a8c290bb41aa", size = 918134, upload-time = "2025-10-19T00:44:47.122Z" }, + { url = "https://files.pythonhosted.org/packages/5c/b3/6a76c3b94c6c87c72ea822e7e67405be6b649c2e37778eeac7c0c0c69de8/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9b16660d01c3931951fab49db422c627897c38c1a1f0393a97582004019a4887", size = 981970, upload-time = "2025-10-19T00:44:48.906Z" }, + { url = "https://files.pythonhosted.org/packages/f6/8a/606e4c7ed14aa6a86aee6ca84a2cb804754dc6c4905b8f94e09e49f1ce60/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b7de5718e2113d4efccea3f06055758cdbc17388ecc3341ba4d1d812837d7c1a", size = 978877, upload-time = "2025-10-19T00:44:50.819Z" }, + { url = "https://files.pythonhosted.org/packages/97/ec/ad474dcb1f6c1ebfdda3c2ad2edbb1af122a0e79c9ff2cb901ffb5f59662/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a12a2a1a6bc44099491c05a12039efa08cc33a3d0f8c7b0566185e085e139283", size = 964279, upload-time = "2025-10-19T00:44:52.476Z" }, + { url = "https://files.pythonhosted.org/packages/68/8c/d245fd416c69d27d51f14d5ad62acc4ee5971088ee31c40ffe1cc109af68/cytoolz-1.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:047defa7f5f9a32f82373dbc3957289562e8a3fa58ae02ec8e4dca4f43a33a21", size = 916630, upload-time = "2025-10-19T00:44:54.059Z" }, ] [[package]] @@ -506,9 +508,9 @@ dependencies = [ { name = "eth-utils" }, { name = "parsimonious" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/71/d9e1380bd77fd22f98b534699af564f189b56d539cc2b9dab908d4e4c242/eth_abi-5.2.0.tar.gz", hash = "sha256:178703fa98c07d8eecd5ae569e7e8d159e493ebb6eeb534a8fe973fbc4e40ef0", size = 49797 } +sdist = { url = "https://files.pythonhosted.org/packages/00/71/d9e1380bd77fd22f98b534699af564f189b56d539cc2b9dab908d4e4c242/eth_abi-5.2.0.tar.gz", hash = "sha256:178703fa98c07d8eecd5ae569e7e8d159e493ebb6eeb534a8fe973fbc4e40ef0", size = 49797, upload-time = "2025-01-14T16:29:34.629Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/b4/2f3982c4cbcbf5eeb6aec62df1533c0e63c653b3021ff338d44944405676/eth_abi-5.2.0-py3-none-any.whl", hash = "sha256:17abe47560ad753f18054f5b3089fcb588f3e3a092136a416b6c1502cb7e8877", size = 28511 }, + { url = "https://files.pythonhosted.org/packages/7a/b4/2f3982c4cbcbf5eeb6aec62df1533c0e63c653b3021ff338d44944405676/eth_abi-5.2.0-py3-none-any.whl", hash = "sha256:17abe47560ad753f18054f5b3089fcb588f3e3a092136a416b6c1502cb7e8877", size = 28511, upload-time = "2025-01-14T16:29:31.862Z" }, ] [[package]] @@ -527,18 +529,18 @@ dependencies = [ { name = "pydantic" }, { name = "rlp" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/cf/20f76a29be97339c969fd765f1237154286a565a1d61be98e76bb7af946a/eth_account-0.13.7.tar.gz", hash = "sha256:5853ecbcbb22e65411176f121f5f24b8afeeaf13492359d254b16d8b18c77a46", size = 935998 } +sdist = { url = "https://files.pythonhosted.org/packages/74/cf/20f76a29be97339c969fd765f1237154286a565a1d61be98e76bb7af946a/eth_account-0.13.7.tar.gz", hash = "sha256:5853ecbcbb22e65411176f121f5f24b8afeeaf13492359d254b16d8b18c77a46", size = 935998, upload-time = "2025-04-21T21:11:21.204Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/18/088fb250018cbe665bc2111974301b2d59f294a565aff7564c4df6878da2/eth_account-0.13.7-py3-none-any.whl", hash = "sha256:39727de8c94d004ff61d10da7587509c04d2dc7eac71e04830135300bdfc6d24", size = 587452 }, + { url = "https://files.pythonhosted.org/packages/46/18/088fb250018cbe665bc2111974301b2d59f294a565aff7564c4df6878da2/eth_account-0.13.7-py3-none-any.whl", hash = "sha256:39727de8c94d004ff61d10da7587509c04d2dc7eac71e04830135300bdfc6d24", size = 587452, upload-time = "2025-04-21T21:11:18.346Z" }, ] [[package]] name = "eth-hash" version = "0.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3c/f5/c67fc24f2f676aa9b7ab29679d44f113f314c817207cd4319353356f62da/eth_hash-0.8.0.tar.gz", hash = "sha256:b009752b620da2e9c7668014849d1f5fadbe4f138603f1871cc5d4ca706896b1", size = 12225 } +sdist = { url = "https://files.pythonhosted.org/packages/3c/f5/c67fc24f2f676aa9b7ab29679d44f113f314c817207cd4319353356f62da/eth_hash-0.8.0.tar.gz", hash = "sha256:b009752b620da2e9c7668014849d1f5fadbe4f138603f1871cc5d4ca706896b1", size = 12225, upload-time = "2026-03-25T16:36:55.099Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/87/b36792150ca0b28e4df683a34be15a61461ca0e349e5b5cf3ec8f694edb9/eth_hash-0.8.0-py3-none-any.whl", hash = "sha256:523718a51b369ab89866b929a5c93c52978cd866ea309192ad980dd8271f9fac", size = 7965 }, + { url = "https://files.pythonhosted.org/packages/87/87/b36792150ca0b28e4df683a34be15a61461ca0e349e5b5cf3ec8f694edb9/eth_hash-0.8.0-py3-none-any.whl", hash = "sha256:523718a51b369ab89866b929a5c93c52978cd866ea309192ad980dd8271f9fac", size = 7965, upload-time = "2026-03-25T16:36:54.205Z" }, ] [[package]] @@ -550,9 +552,9 @@ dependencies = [ { name = "eth-utils" }, { name = "pycryptodome" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/35/66/dd823b1537befefbbff602e2ada88f1477c5b40ec3731e3d9bc676c5f716/eth_keyfile-0.8.1.tar.gz", hash = "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1", size = 12267 } +sdist = { url = "https://files.pythonhosted.org/packages/35/66/dd823b1537befefbbff602e2ada88f1477c5b40ec3731e3d9bc676c5f716/eth_keyfile-0.8.1.tar.gz", hash = "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1", size = 12267, upload-time = "2024-04-23T20:28:53.862Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/fc/48a586175f847dd9e05e5b8994d2fe8336098781ec2e9836a2ad94280281/eth_keyfile-0.8.1-py3-none-any.whl", hash = "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64", size = 7510 }, + { url = "https://files.pythonhosted.org/packages/88/fc/48a586175f847dd9e05e5b8994d2fe8336098781ec2e9836a2ad94280281/eth_keyfile-0.8.1-py3-none-any.whl", hash = "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64", size = 7510, upload-time = "2024-04-23T20:28:51.063Z" }, ] [[package]] @@ -563,9 +565,9 @@ dependencies = [ { name = "eth-typing" }, { name = "eth-utils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/58/11/1ed831c50bd74f57829aa06e58bd82a809c37e070ee501c953b9ac1f1552/eth_keys-0.7.0.tar.gz", hash = "sha256:79d24fd876201df67741de3e3fefb3f4dbcbb6ace66e47e6fe662851a4547814", size = 30166 } +sdist = { url = "https://files.pythonhosted.org/packages/58/11/1ed831c50bd74f57829aa06e58bd82a809c37e070ee501c953b9ac1f1552/eth_keys-0.7.0.tar.gz", hash = "sha256:79d24fd876201df67741de3e3fefb3f4dbcbb6ace66e47e6fe662851a4547814", size = 30166, upload-time = "2025-04-07T17:40:21.697Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/25/0ae00f2b0095e559d61ad3dc32171bd5a29dfd95ab04b4edd641f7c75f72/eth_keys-0.7.0-py3-none-any.whl", hash = "sha256:b0cdda8ffe8e5ba69c7c5ca33f153828edcace844f67aabd4542d7de38b159cf", size = 20656 }, + { url = "https://files.pythonhosted.org/packages/4d/25/0ae00f2b0095e559d61ad3dc32171bd5a29dfd95ab04b4edd641f7c75f72/eth_keys-0.7.0-py3-none-any.whl", hash = "sha256:b0cdda8ffe8e5ba69c7c5ca33f153828edcace844f67aabd4542d7de38b159cf", size = 20656, upload-time = "2025-04-07T17:40:20.441Z" }, ] [[package]] @@ -578,9 +580,9 @@ dependencies = [ { name = "rlp" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7f/ea/ad39d001fa9fed07fad66edb00af701e29b48be0ed44a3bcf58cb3adf130/eth_rlp-2.2.0.tar.gz", hash = "sha256:5e4b2eb1b8213e303d6a232dfe35ab8c29e2d3051b86e8d359def80cd21db83d", size = 7720 } +sdist = { url = "https://files.pythonhosted.org/packages/7f/ea/ad39d001fa9fed07fad66edb00af701e29b48be0ed44a3bcf58cb3adf130/eth_rlp-2.2.0.tar.gz", hash = "sha256:5e4b2eb1b8213e303d6a232dfe35ab8c29e2d3051b86e8d359def80cd21db83d", size = 7720, upload-time = "2025-02-04T21:51:08.134Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/3b/57efe2bc2df0980680d57c01a36516cd3171d2319ceb30e675de19fc2cc5/eth_rlp-2.2.0-py3-none-any.whl", hash = "sha256:5692d595a741fbaef1203db6a2fedffbd2506d31455a6ad378c8449ee5985c47", size = 4446 }, + { url = "https://files.pythonhosted.org/packages/99/3b/57efe2bc2df0980680d57c01a36516cd3171d2319ceb30e675de19fc2cc5/eth_rlp-2.2.0-py3-none-any.whl", hash = "sha256:5692d595a741fbaef1203db6a2fedffbd2506d31455a6ad378c8449ee5985c47", size = 4446, upload-time = "2025-02-04T21:51:05.823Z" }, ] [[package]] @@ -590,9 +592,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/37/e7/06c5af99ad40494f6d10126a9030ff4eb14c5b773f2a4076017efb0a163a/eth_typing-6.0.0.tar.gz", hash = "sha256:315dd460dc0b71c15a6cd51e3c0b70d237eec8771beb844144f3a1fb4adb2392", size = 21852 } +sdist = { url = "https://files.pythonhosted.org/packages/37/e7/06c5af99ad40494f6d10126a9030ff4eb14c5b773f2a4076017efb0a163a/eth_typing-6.0.0.tar.gz", hash = "sha256:315dd460dc0b71c15a6cd51e3c0b70d237eec8771beb844144f3a1fb4adb2392", size = 21852, upload-time = "2026-03-25T16:41:57.444Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/0d/e756622fab29f404d846d7464f929d642a7ee6eff5b38bcc79e7c64ac630/eth_typing-6.0.0-py3-none-any.whl", hash = "sha256:ee74fb641eb36dd885e1c42c2a3055314efa532b3e71480816df70a94d35cfb9", size = 19191 }, + { url = "https://files.pythonhosted.org/packages/aa/0d/e756622fab29f404d846d7464f929d642a7ee6eff5b38bcc79e7c64ac630/eth_typing-6.0.0-py3-none-any.whl", hash = "sha256:ee74fb641eb36dd885e1c42c2a3055314efa532b3e71480816df70a94d35cfb9", size = 19191, upload-time = "2026-03-25T16:41:55.544Z" }, ] [[package]] @@ -606,9 +608,9 @@ dependencies = [ { name = "pydantic" }, { name = "toolz", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e9/1b/0b8548da7b31eba87ed58bca1d0de5dcb13a6c113e02c09019ec5a6716ed/eth_utils-6.0.0.tar.gz", hash = "sha256:eb54b2f82dd300d3142c49a89da195e823f5e5284d43203593f87c67bad92a96", size = 123457 } +sdist = { url = "https://files.pythonhosted.org/packages/e9/1b/0b8548da7b31eba87ed58bca1d0de5dcb13a6c113e02c09019ec5a6716ed/eth_utils-6.0.0.tar.gz", hash = "sha256:eb54b2f82dd300d3142c49a89da195e823f5e5284d43203593f87c67bad92a96", size = 123457, upload-time = "2026-03-25T17:11:51.433Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/53/45/a20b907227b9d1aea2e36f7b12818d055629ca9bc65fc282b45738f28ca3/eth_utils-6.0.0-py3-none-any.whl", hash = "sha256:63cf48ee32c45541cb5748751909a8345c470432fb6f0fed4bd7c53fd6400469", size = 102473 }, + { url = "https://files.pythonhosted.org/packages/53/45/a20b907227b9d1aea2e36f7b12818d055629ca9bc65fc282b45738f28ca3/eth_utils-6.0.0-py3-none-any.whl", hash = "sha256:63cf48ee32c45541cb5748751909a8345c470432fb6f0fed4bd7c53fd6400469", size = 102473, upload-time = "2026-03-25T17:11:49.953Z" }, ] [[package]] @@ -616,29 +618,29 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371 } +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740 }, + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] name = "execnet" version = "2.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622 } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708 }, + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, ] [[package]] name = "hexbytes" version = "1.3.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7f/87/adf4635b4b8c050283d74e6db9a81496063229c9263e6acc1903ab79fbec/hexbytes-1.3.1.tar.gz", hash = "sha256:a657eebebdfe27254336f98d8af6e2236f3f83aed164b87466b6cf6c5f5a4765", size = 8633 } +sdist = { url = "https://files.pythonhosted.org/packages/7f/87/adf4635b4b8c050283d74e6db9a81496063229c9263e6acc1903ab79fbec/hexbytes-1.3.1.tar.gz", hash = "sha256:a657eebebdfe27254336f98d8af6e2236f3f83aed164b87466b6cf6c5f5a4765", size = 8633, upload-time = "2025-05-14T16:45:17.5Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/e0/3b31492b1c89da3c5a846680517871455b30c54738486fc57ac79a5761bd/hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7", size = 5074 }, + { url = "https://files.pythonhosted.org/packages/8d/e0/3b31492b1c89da3c5a846680517871455b30c54738486fc57ac79a5761bd/hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7", size = 5074, upload-time = "2025-05-14T16:45:16.179Z" }, ] [[package]] @@ -649,74 +651,74 @@ dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/41/96/35022710908b82d20af0c57ab8be4d4a3e4045a74d3ae9c806eb4443297c/hypothesis-6.161.0.tar.gz", hash = "sha256:c357150f826fc7492304621d535a23e8f1b7440a3b10a337c23bea52102e2e7f", size = 485855 } +sdist = { url = "https://files.pythonhosted.org/packages/41/96/35022710908b82d20af0c57ab8be4d4a3e4045a74d3ae9c806eb4443297c/hypothesis-6.161.0.tar.gz", hash = "sha256:c357150f826fc7492304621d535a23e8f1b7440a3b10a337c23bea52102e2e7f", size = 485855, upload-time = "2026-07-23T07:17:40.745Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/b9/c8b80fb7517e6f3039d0ef9a5df6aaee53667935e62c6c9d9d635436708d/hypothesis-6.161.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c9f877e288dfb46207b5c3bfcc8ab28e2613e529be8621816423960403377286", size = 766230 }, - { url = "https://files.pythonhosted.org/packages/90/16/e5c1287fee682f7c1e9afccc91c07ae36a6855a5863d0b3c15d7bfa0b322/hypothesis-6.161.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b7b6980265cb04605b2b42132dc8ef5735917fc482869298611a49d2e06dc322", size = 761883 }, - { url = "https://files.pythonhosted.org/packages/c9/b8/d9792e24e53f82bb1455935f79cf3b56ccf556fac325c8a90f7968180706/hypothesis-6.161.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f10253cac459922cad3bc09e397718188e57dffefe810e5db1d444e7113d7fb5", size = 1091083 }, - { url = "https://files.pythonhosted.org/packages/f7/15/33cba9c6bee8a80ab18f48e40669038275bf4b82e8dfb0fa9fe716925265/hypothesis-6.161.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:232ab78dd8cb0a891914d20697e0fd340ca1e6d4d8d5855df5e433d8161173e2", size = 1140530 }, - { url = "https://files.pythonhosted.org/packages/bb/f6/30c421822cd65b8edd56b2b90a5e1acf4a624d5619067957668027ab7e46/hypothesis-6.161.0-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:264336ca1e9f31edd24a8885c4020db8e18986c51a255613db28c076ac4289a8", size = 1132680 }, - { url = "https://files.pythonhosted.org/packages/e9/db/d18e45339b2ffda57a52395e03df6166bc4e428bc90e878dd3f20a7423c0/hypothesis-6.161.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:323aac4347e6ffa86929407b7f386cbf54e1c66faf923ffd6b4b86c21815d117", size = 1264892 }, - { url = "https://files.pythonhosted.org/packages/c7/7e/f4b7600272fbc9a2b28c95b96059d89cf5093ae705e52360a818df8154a5/hypothesis-6.161.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5dc83c8e83b9d133babcf9468703cece0ddb25413983561f2516927edddcc52d", size = 1307563 }, - { url = "https://files.pythonhosted.org/packages/d6/28/fa4f2d50c7434076ec7653a8372750531576e4d11cd5f3316ad83e12a553/hypothesis-6.161.0-cp310-abi3-win32.whl", hash = "sha256:75a3036121e6ae2cf55b7433f1953834cc9eca97c2e4e4be3369fe080c86b237", size = 652098 }, - { url = "https://files.pythonhosted.org/packages/93/5c/6811eee772a5cc33f9bf863326983f493977e9aee9535c8dbb6c172575d3/hypothesis-6.161.0-cp310-abi3-win_amd64.whl", hash = "sha256:e3f5b2527789a748b54d6ef46b2b042f3225164d54c24ba74a137ddb10a39407", size = 658272 }, - { url = "https://files.pythonhosted.org/packages/97/97/49216c1087962033451cc6e3093deb765b0d14eed7dda2980f6d8dfc9062/hypothesis-6.161.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:38eea270b81398c9e2c7eed028f53ba51dc7005eb97fa681c7c90007ba029423", size = 766930 }, - { url = "https://files.pythonhosted.org/packages/9a/6d/766a280bea353045ae7311ba847a50ebb939155e2a990fd08040be2b6b5b/hypothesis-6.161.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6b7183980c7729d7cf084ab26c127e4c591876536278ecb84ed2449d4d93f4e", size = 762699 }, - { url = "https://files.pythonhosted.org/packages/62/86/f28648668b5ce18bba7ae846c629c54427aa622a76280309c3bc3dca4f2d/hypothesis-6.161.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3e60bbe528d6005373146808bd0b5e618bf1a20e912c0568ae56802e8c455fc", size = 1091551 }, - { url = "https://files.pythonhosted.org/packages/52/e3/3ae24ad1056e1c992dade22e9c784c93d57ea0dc3ff9fa6a48683548489d/hypothesis-6.161.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3167e3153a9b8a8ad43284a22cbe1e3c1819d6d944f727f9810bb115a9c2ade", size = 1141106 }, - { url = "https://files.pythonhosted.org/packages/c4/37/fa3a21edcd7c4a104d6782ee98135af8ef86ae42d39ea9eb55072f84b668/hypothesis-6.161.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1489ef3b86688fc0051d0c86db238ff8f3732bd353dc4b6b28a81c3897bd756e", size = 1265529 }, - { url = "https://files.pythonhosted.org/packages/6e/2e/f377a5ea8aba231213da1b26f333a6af29c43fcdac7dda790304dd9c3ffc/hypothesis-6.161.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28a450d338067845870b03a8c61ba6d83cccf5d1ed360a6b1cfebb4f42818791", size = 1307881 }, - { url = "https://files.pythonhosted.org/packages/8f/73/276defee614d45462a1512888283d4a9bdf852e3f9d74f564bd8d6cecd09/hypothesis-6.161.0-cp310-cp310-win_amd64.whl", hash = "sha256:170fc6fe2157c8e813818a08709d78c79ffa9171b015389c50f5538eab3de1bb", size = 658159 }, - { url = "https://files.pythonhosted.org/packages/dc/1f/07054e18c7696fe5aa127952e1ff2b74c7917100e0998d77405f9aea7bbf/hypothesis-6.161.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2658a95ac7cf1943b9397725d58481373a1709e79b6867628108f695b202ff3f", size = 766737 }, - { url = "https://files.pythonhosted.org/packages/21/1b/6a04fbda729f5889b486aa3b20912ee6c7391c8db0a2926346a1b3ad0834/hypothesis-6.161.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:584906b4f8f9504d7c9d6fd3c42bf991fa42ab64c3a4490a84d6e4acf69fe7fe", size = 762514 }, - { url = "https://files.pythonhosted.org/packages/35/12/609a956b716ab20cb81263d8e0cecfe442fb46e4d54ae9b82b453f2465fe/hypothesis-6.161.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87a996d0a1c865173ed67a0b3537efbe6736bcf9f58ac28826712a48ed8d2d23", size = 1091414 }, - { url = "https://files.pythonhosted.org/packages/fc/99/093bc8aca6dddc05e88dd0baa64c5586e031737d798c66e770fbeb034510/hypothesis-6.161.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0250e209ed2401cf6c80c956c5c1906097b537d05fa748f03e9c53060a837d3f", size = 1140888 }, - { url = "https://files.pythonhosted.org/packages/65/fc/f681828dc1ca13243622eb6ddc3f7370efb1cb7931ea7505f8ade4d37ba6/hypothesis-6.161.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:210024a6e84c361803545ca055218bcae06e17fcb53d5956db7db6a1e14d7769", size = 1265245 }, - { url = "https://files.pythonhosted.org/packages/53/d4/98deace31c31369196ece4d6f32bb8c1820bf5cf5584721bda791bffa0cc/hypothesis-6.161.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c3e39be8141496a73115f1ea2c8fd7146f78d26f148e884f3d4a68dec06418a0", size = 1307841 }, - { url = "https://files.pythonhosted.org/packages/c3/5d/d9bbe1fc769e46b21d368497d4739375fcb17270eba611bac1117473e337/hypothesis-6.161.0-cp311-cp311-win_amd64.whl", hash = "sha256:e234937af9de105e28dc7ffdac5d7932265abb5881f0264aff01d3515baee732", size = 657953 }, - { url = "https://files.pythonhosted.org/packages/01/f5/b01692ea422f9995260435a5c2a425dd558ceb0b6544cf4037d312b52927/hypothesis-6.161.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8cf6149e5bcb1deaa3d029280c2c9a47fede2186ea58d8dc3e71864428b748b5", size = 767859 }, - { url = "https://files.pythonhosted.org/packages/1e/ea/147f96f352a1c62f4fa4d46ec2d8b103d39cafce236826531aba9dfbf6fc/hypothesis-6.161.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:439b9ccefc2b87b9752752d2ec6c9d40f92de2acaf07f4da94c2ebcbde4eb660", size = 759491 }, - { url = "https://files.pythonhosted.org/packages/44/05/c1ddd72ca9af054332a05bdb19b666b1dbb4ff904cac2b6e04bc483518fa/hypothesis-6.161.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35c577d4b635b914e2cdd59d144448e0de82e47f8422d8373cbb48daa5571686", size = 1089838 }, - { url = "https://files.pythonhosted.org/packages/46/79/0d9adc2ca7fe226e4f81e0e9ff88ab9a2025395a705e55e8447e8833b2e2/hypothesis-6.161.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:894af9777f2fd51bca9625fd07573456c1fa67b6bed3f6aa1659cb60255594e0", size = 1139915 }, - { url = "https://files.pythonhosted.org/packages/50/48/c557ee9899ab58e6d373712dcfe019b4eb65035f5bbffcb7624201984bd4/hypothesis-6.161.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c9f15d18d3041216d80d2a3203c1b8881efb7c20296f068651e2ad34f3852392", size = 1262692 }, - { url = "https://files.pythonhosted.org/packages/1c/37/8eede820af48d8f7a73c0741c659b4839ffe9825b020affe43d52f58acb5/hypothesis-6.161.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f5588bde17a517c943b5ef6172cacfce6ef2d542c9249cc1bd86ce3c4c07161b", size = 1306904 }, - { url = "https://files.pythonhosted.org/packages/ba/6b/16282f58b92b6698dbed7b23d7015fb9f7d5dfb78e7ba2e4b44c88116bca/hypothesis-6.161.0-cp312-cp312-win_amd64.whl", hash = "sha256:c7994d32bcca19b7cbf3c087172245fe9f4d55b21bccef81693efd5a0637d4d9", size = 655392 }, - { url = "https://files.pythonhosted.org/packages/27/13/50b3fabaa9a52f82905d6bf70b0027cbc61972f0b60dcf68506e4a85674f/hypothesis-6.161.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d5217e3df508ab71303bf1288b412548e96483eef195f6008b6472770e4fe4ed", size = 767734 }, - { url = "https://files.pythonhosted.org/packages/72/0c/0176f7722896dffef2aa677699df75cd2a53ed00d4dc6b2959c40c1c8389/hypothesis-6.161.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ad4899908abec1888d0d16eb70acd54c9d8198b58410ec26a346ba35d384fc0d", size = 759394 }, - { url = "https://files.pythonhosted.org/packages/97/1d/5ade6e0c80ce8160bbcd55c300d95a5450cdb82fa04fdcdd8a33f6198441/hypothesis-6.161.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fee553e5150af6d66ee058f3ccbc3b5b83e6df62139e8935abd0510254a2d4a7", size = 1089752 }, - { url = "https://files.pythonhosted.org/packages/99/02/14c6d54e60159ba9991a52b14ea5a9b6935d4878ffe9d0a8fabd2d166767/hypothesis-6.161.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f8110cd815f3a79e2351700654c21771eec47d98a78db56cc81879d41f08ed1", size = 1139731 }, - { url = "https://files.pythonhosted.org/packages/36/98/c099c382b0fbf6dfd209d35961e6ee9739ad1d787288a40eb364b278217a/hypothesis-6.161.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16aacb26a277d25da7466f0588c2687811334455753d513c55d8ca4dbbc5174e", size = 1262736 }, - { url = "https://files.pythonhosted.org/packages/f1/3a/6b1fbde6e2a1c9bd54acb1e5d8fa866c6fef59a829a67ca310f5d12a8fbe/hypothesis-6.161.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eb24cf5f7f301ad3db14caa4462ebc2e693fe38815d793ff6dbc116820b18dff", size = 1306628 }, - { url = "https://files.pythonhosted.org/packages/8b/c2/033da1694f956f0c566b12a1f0667138ad06a3b0a67837f17c6873cc2513/hypothesis-6.161.0-cp313-cp313-win_amd64.whl", hash = "sha256:e4f715f5598444a0d569aa8a3e74ebc14a46c67a873193db38c8542b2838e91f", size = 655355 }, - { url = "https://files.pythonhosted.org/packages/2b/26/29582b8ba467eedf270515422f41cb564d06b4eef38bdf06e236cc841546/hypothesis-6.161.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:a046954e17a1edd20b6c95e9d29f1df7bc20ccab94c01aa8b4177552896230fb", size = 767928 }, - { url = "https://files.pythonhosted.org/packages/f7/25/bb7cfd851f6b0f4b0130485785a3447621523116b89f8d82042fb9897752/hypothesis-6.161.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2d503b0fdb916371d536b33fad0c4f909846af2fc4273d3049ca6fe661aa81ff", size = 759542 }, - { url = "https://files.pythonhosted.org/packages/d9/ab/bc31d4aa5840c2438e011a615095b0e2fae5de94c3abfc18a01686825ea7/hypothesis-6.161.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df011a94870dc3e1b5fb4fb8d2c68dd641b412a3b73050288d85af1467c9a689", size = 1090304 }, - { url = "https://files.pythonhosted.org/packages/51/ee/6304f6184aee6a1b91fff746a767b4f3aab58c29e48e64cc16d56fc6dedc/hypothesis-6.161.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4678e3988503b3bd5be0ed995f84cc15ac4f99c168bade32456a08c04868f3f3", size = 1139915 }, - { url = "https://files.pythonhosted.org/packages/f5/6d/23efce26bf7f1773346732c58a23cbe33ed4f171da1bb3aa11bf349fdb4c/hypothesis-6.161.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74c6e5b5623f37eb6af8be6f861d138fac3ee3528ee30c3b48ff11c39f7be4b7", size = 1263070 }, - { url = "https://files.pythonhosted.org/packages/0b/a2/e0b4bf410630f16661eea6fdf9c3970e47c749a837de12098d63c81bb01b/hypothesis-6.161.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b841c25267ab360812a523d1861e0b0ed0f5cc4e6d7bcecc9d9eddd3f835aa0f", size = 1306929 }, - { url = "https://files.pythonhosted.org/packages/03/13/58047eb148a31ae7cce26ec0b2f0e980c46874c6673c1110c53684ba181a/hypothesis-6.161.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:a0f3830c1e816e34bd8cd940244c8c877dedc2ecfea771d2ecea252bc35eb21d", size = 599455 }, - { url = "https://files.pythonhosted.org/packages/f0/0e/a206013edd7dfd44b9a81ae1946a1ea30d878974850d60a61fa128cc170d/hypothesis-6.161.0-cp314-cp314-win_amd64.whl", hash = "sha256:d1d38f05acb9c25181157f1756f5faaa1759b4641ff6b32cb1d2ab1d55d6af2d", size = 655306 }, - { url = "https://files.pythonhosted.org/packages/e2/74/32d224a0ccf4ca9af6acc1d805047e12cd13105e0769d54ac00a86f25850/hypothesis-6.161.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:81570959521eebd0172ea9132ffab71b90050e7cd44d045da67210aa9a594376", size = 766503 }, - { url = "https://files.pythonhosted.org/packages/ce/5d/8b61c3490fd8195a25fdc37e951ccba3ae4df2c74839ffe6a6d5720fdb79/hypothesis-6.161.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:46a6039181337b85a995666e9bf87cc2390282720ba345479bb9be9c867914da", size = 758013 }, - { url = "https://files.pythonhosted.org/packages/d9/11/ac4ab15ec4586a23bb4e2acdcbed814517e341f2940eeb74fbf428dac243/hypothesis-6.161.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f2d4141c952f522d6aae0e493d170f9b0127c001319bd312ee9cfba7ed419d4", size = 1088871 }, - { url = "https://files.pythonhosted.org/packages/27/13/fd83965bcdd44dc5002c67fe8e8e2e974ed45c82dc6864e104c1c70093d5/hypothesis-6.161.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ed3e1b9c036954bfabe64899072a18e6b5113703d32a96645c6656a8cfc43e", size = 1138801 }, - { url = "https://files.pythonhosted.org/packages/2d/e7/a4ad5f3b0b805fd2e583d193e2a762cd413465b524ef07829452521dca6d/hypothesis-6.161.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:aba1508da6c317819305e875bf6c4d4dd0922193c76416d4cc907447ebe08fea", size = 1261305 }, - { url = "https://files.pythonhosted.org/packages/38/54/35e1b62ece96c24921e9a1e811179d54a6429d9611a2cd49504f5b95382e/hypothesis-6.161.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:981acb3efa88df363a0d31e0f4bacd36ef739104eee789a6b12c7f7200a457fc", size = 1305689 }, - { url = "https://files.pythonhosted.org/packages/04/87/6491e9a36d8e8df67a3b9c3eeb5a85c12c6b0d5302b5ce395b5427698b52/hypothesis-6.161.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e71e229f2dec694685245b8e55e908855b475c17ab8337bcf848768b4c32aa97", size = 655436 }, - { url = "https://files.pythonhosted.org/packages/54/e2/0782e45562fb091cd75bd12f69932c8aa55a9e3bb699599f43e5258d013c/hypothesis-6.161.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:33a19886dc05b489f0ab632c89b8ca9dc6f89a0b380b6405671cecb2b0d5b5c4", size = 767674 }, - { url = "https://files.pythonhosted.org/packages/03/46/eaccb5375ed83396be3153857f9de808b5d5ecc001fab8e30bf8e30d33d4/hypothesis-6.161.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b4fd38d0e757ae290583774b3695ab0d7f0da80e924c6473de84483449c6da8d", size = 763579 }, - { url = "https://files.pythonhosted.org/packages/99/48/31ca6b9414cf30388ba825c740b13ab74f6afcf856a194a9256f7f1ca38d/hypothesis-6.161.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59dc6871e2fbbfd2d28e7e6f33d19bd8513a3b7510bd0b224a59bbebdd5cc1b3", size = 1092394 }, - { url = "https://files.pythonhosted.org/packages/75/1d/709c03af162418c0b3e0cf624549b13ecacd8df0f2ca09d53214702cb1f8/hypothesis-6.161.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55ff16ec4b4e98bfd97e9a2a44905eaf7a3ec8f3f157d8c7eac2385a88059a29", size = 1142170 }, - { url = "https://files.pythonhosted.org/packages/3a/ae/63458a5f80db8433beb7556482e3de1a6789b6c469a5f2f99c21aaa7fdef/hypothesis-6.161.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:77ae374d9ed7046b15443053b11f5b05e185bca24b3b849c3f473a9e4cc85451", size = 659069 }, + { url = "https://files.pythonhosted.org/packages/f5/b9/c8b80fb7517e6f3039d0ef9a5df6aaee53667935e62c6c9d9d635436708d/hypothesis-6.161.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c9f877e288dfb46207b5c3bfcc8ab28e2613e529be8621816423960403377286", size = 766230, upload-time = "2026-07-23T07:16:54.313Z" }, + { url = "https://files.pythonhosted.org/packages/90/16/e5c1287fee682f7c1e9afccc91c07ae36a6855a5863d0b3c15d7bfa0b322/hypothesis-6.161.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b7b6980265cb04605b2b42132dc8ef5735917fc482869298611a49d2e06dc322", size = 761883, upload-time = "2026-07-23T07:17:05.884Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b8/d9792e24e53f82bb1455935f79cf3b56ccf556fac325c8a90f7968180706/hypothesis-6.161.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f10253cac459922cad3bc09e397718188e57dffefe810e5db1d444e7113d7fb5", size = 1091083, upload-time = "2026-07-23T07:17:10.987Z" }, + { url = "https://files.pythonhosted.org/packages/f7/15/33cba9c6bee8a80ab18f48e40669038275bf4b82e8dfb0fa9fe716925265/hypothesis-6.161.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:232ab78dd8cb0a891914d20697e0fd340ca1e6d4d8d5855df5e433d8161173e2", size = 1140530, upload-time = "2026-07-23T07:16:14.195Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f6/30c421822cd65b8edd56b2b90a5e1acf4a624d5619067957668027ab7e46/hypothesis-6.161.0-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:264336ca1e9f31edd24a8885c4020db8e18986c51a255613db28c076ac4289a8", size = 1132680, upload-time = "2026-07-23T07:16:49.73Z" }, + { url = "https://files.pythonhosted.org/packages/e9/db/d18e45339b2ffda57a52395e03df6166bc4e428bc90e878dd3f20a7423c0/hypothesis-6.161.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:323aac4347e6ffa86929407b7f386cbf54e1c66faf923ffd6b4b86c21815d117", size = 1264892, upload-time = "2026-07-23T07:16:21.657Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7e/f4b7600272fbc9a2b28c95b96059d89cf5093ae705e52360a818df8154a5/hypothesis-6.161.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5dc83c8e83b9d133babcf9468703cece0ddb25413983561f2516927edddcc52d", size = 1307563, upload-time = "2026-07-23T07:16:43.15Z" }, + { url = "https://files.pythonhosted.org/packages/d6/28/fa4f2d50c7434076ec7653a8372750531576e4d11cd5f3316ad83e12a553/hypothesis-6.161.0-cp310-abi3-win32.whl", hash = "sha256:75a3036121e6ae2cf55b7433f1953834cc9eca97c2e4e4be3369fe080c86b237", size = 652098, upload-time = "2026-07-23T07:16:24.134Z" }, + { url = "https://files.pythonhosted.org/packages/93/5c/6811eee772a5cc33f9bf863326983f493977e9aee9535c8dbb6c172575d3/hypothesis-6.161.0-cp310-abi3-win_amd64.whl", hash = "sha256:e3f5b2527789a748b54d6ef46b2b042f3225164d54c24ba74a137ddb10a39407", size = 658272, upload-time = "2026-07-23T07:16:51.173Z" }, + { url = "https://files.pythonhosted.org/packages/97/97/49216c1087962033451cc6e3093deb765b0d14eed7dda2980f6d8dfc9062/hypothesis-6.161.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:38eea270b81398c9e2c7eed028f53ba51dc7005eb97fa681c7c90007ba029423", size = 766930, upload-time = "2026-07-23T07:17:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/9a/6d/766a280bea353045ae7311ba847a50ebb939155e2a990fd08040be2b6b5b/hypothesis-6.161.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6b7183980c7729d7cf084ab26c127e4c591876536278ecb84ed2449d4d93f4e", size = 762699, upload-time = "2026-07-23T07:17:38.977Z" }, + { url = "https://files.pythonhosted.org/packages/62/86/f28648668b5ce18bba7ae846c629c54427aa622a76280309c3bc3dca4f2d/hypothesis-6.161.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3e60bbe528d6005373146808bd0b5e618bf1a20e912c0568ae56802e8c455fc", size = 1091551, upload-time = "2026-07-23T07:16:28.499Z" }, + { url = "https://files.pythonhosted.org/packages/52/e3/3ae24ad1056e1c992dade22e9c784c93d57ea0dc3ff9fa6a48683548489d/hypothesis-6.161.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3167e3153a9b8a8ad43284a22cbe1e3c1819d6d944f727f9810bb115a9c2ade", size = 1141106, upload-time = "2026-07-23T07:17:19.854Z" }, + { url = "https://files.pythonhosted.org/packages/c4/37/fa3a21edcd7c4a104d6782ee98135af8ef86ae42d39ea9eb55072f84b668/hypothesis-6.161.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1489ef3b86688fc0051d0c86db238ff8f3732bd353dc4b6b28a81c3897bd756e", size = 1265529, upload-time = "2026-07-23T07:16:44.815Z" }, + { url = "https://files.pythonhosted.org/packages/6e/2e/f377a5ea8aba231213da1b26f333a6af29c43fcdac7dda790304dd9c3ffc/hypothesis-6.161.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28a450d338067845870b03a8c61ba6d83cccf5d1ed360a6b1cfebb4f42818791", size = 1307881, upload-time = "2026-07-23T07:16:18.438Z" }, + { url = "https://files.pythonhosted.org/packages/8f/73/276defee614d45462a1512888283d4a9bdf852e3f9d74f564bd8d6cecd09/hypothesis-6.161.0-cp310-cp310-win_amd64.whl", hash = "sha256:170fc6fe2157c8e813818a08709d78c79ffa9171b015389c50f5538eab3de1bb", size = 658159, upload-time = "2026-07-23T07:16:38.473Z" }, + { url = "https://files.pythonhosted.org/packages/dc/1f/07054e18c7696fe5aa127952e1ff2b74c7917100e0998d77405f9aea7bbf/hypothesis-6.161.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2658a95ac7cf1943b9397725d58481373a1709e79b6867628108f695b202ff3f", size = 766737, upload-time = "2026-07-23T07:16:27.055Z" }, + { url = "https://files.pythonhosted.org/packages/21/1b/6a04fbda729f5889b486aa3b20912ee6c7391c8db0a2926346a1b3ad0834/hypothesis-6.161.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:584906b4f8f9504d7c9d6fd3c42bf991fa42ab64c3a4490a84d6e4acf69fe7fe", size = 762514, upload-time = "2026-07-23T07:17:25.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/12/609a956b716ab20cb81263d8e0cecfe442fb46e4d54ae9b82b453f2465fe/hypothesis-6.161.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87a996d0a1c865173ed67a0b3537efbe6736bcf9f58ac28826712a48ed8d2d23", size = 1091414, upload-time = "2026-07-23T07:16:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/fc/99/093bc8aca6dddc05e88dd0baa64c5586e031737d798c66e770fbeb034510/hypothesis-6.161.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0250e209ed2401cf6c80c956c5c1906097b537d05fa748f03e9c53060a837d3f", size = 1140888, upload-time = "2026-07-23T07:17:07.579Z" }, + { url = "https://files.pythonhosted.org/packages/65/fc/f681828dc1ca13243622eb6ddc3f7370efb1cb7931ea7505f8ade4d37ba6/hypothesis-6.161.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:210024a6e84c361803545ca055218bcae06e17fcb53d5956db7db6a1e14d7769", size = 1265245, upload-time = "2026-07-23T07:16:56.103Z" }, + { url = "https://files.pythonhosted.org/packages/53/d4/98deace31c31369196ece4d6f32bb8c1820bf5cf5584721bda791bffa0cc/hypothesis-6.161.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c3e39be8141496a73115f1ea2c8fd7146f78d26f148e884f3d4a68dec06418a0", size = 1307841, upload-time = "2026-07-23T07:16:59.457Z" }, + { url = "https://files.pythonhosted.org/packages/c3/5d/d9bbe1fc769e46b21d368497d4739375fcb17270eba611bac1117473e337/hypothesis-6.161.0-cp311-cp311-win_amd64.whl", hash = "sha256:e234937af9de105e28dc7ffdac5d7932265abb5881f0264aff01d3515baee732", size = 657953, upload-time = "2026-07-23T07:17:18.224Z" }, + { url = "https://files.pythonhosted.org/packages/01/f5/b01692ea422f9995260435a5c2a425dd558ceb0b6544cf4037d312b52927/hypothesis-6.161.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8cf6149e5bcb1deaa3d029280c2c9a47fede2186ea58d8dc3e71864428b748b5", size = 767859, upload-time = "2026-07-23T07:16:31.301Z" }, + { url = "https://files.pythonhosted.org/packages/1e/ea/147f96f352a1c62f4fa4d46ec2d8b103d39cafce236826531aba9dfbf6fc/hypothesis-6.161.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:439b9ccefc2b87b9752752d2ec6c9d40f92de2acaf07f4da94c2ebcbde4eb660", size = 759491, upload-time = "2026-07-23T07:17:37.046Z" }, + { url = "https://files.pythonhosted.org/packages/44/05/c1ddd72ca9af054332a05bdb19b666b1dbb4ff904cac2b6e04bc483518fa/hypothesis-6.161.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35c577d4b635b914e2cdd59d144448e0de82e47f8422d8373cbb48daa5571686", size = 1089838, upload-time = "2026-07-23T07:16:52.774Z" }, + { url = "https://files.pythonhosted.org/packages/46/79/0d9adc2ca7fe226e4f81e0e9ff88ab9a2025395a705e55e8447e8833b2e2/hypothesis-6.161.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:894af9777f2fd51bca9625fd07573456c1fa67b6bed3f6aa1659cb60255594e0", size = 1139915, upload-time = "2026-07-23T07:16:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/50/48/c557ee9899ab58e6d373712dcfe019b4eb65035f5bbffcb7624201984bd4/hypothesis-6.161.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c9f15d18d3041216d80d2a3203c1b8881efb7c20296f068651e2ad34f3852392", size = 1262692, upload-time = "2026-07-23T07:17:09.328Z" }, + { url = "https://files.pythonhosted.org/packages/1c/37/8eede820af48d8f7a73c0741c659b4839ffe9825b020affe43d52f58acb5/hypothesis-6.161.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f5588bde17a517c943b5ef6172cacfce6ef2d542c9249cc1bd86ce3c4c07161b", size = 1306904, upload-time = "2026-07-23T07:16:32.698Z" }, + { url = "https://files.pythonhosted.org/packages/ba/6b/16282f58b92b6698dbed7b23d7015fb9f7d5dfb78e7ba2e4b44c88116bca/hypothesis-6.161.0-cp312-cp312-win_amd64.whl", hash = "sha256:c7994d32bcca19b7cbf3c087172245fe9f4d55b21bccef81693efd5a0637d4d9", size = 655392, upload-time = "2026-07-23T07:16:16.988Z" }, + { url = "https://files.pythonhosted.org/packages/27/13/50b3fabaa9a52f82905d6bf70b0027cbc61972f0b60dcf68506e4a85674f/hypothesis-6.161.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d5217e3df508ab71303bf1288b412548e96483eef195f6008b6472770e4fe4ed", size = 767734, upload-time = "2026-07-23T07:16:35.638Z" }, + { url = "https://files.pythonhosted.org/packages/72/0c/0176f7722896dffef2aa677699df75cd2a53ed00d4dc6b2959c40c1c8389/hypothesis-6.161.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ad4899908abec1888d0d16eb70acd54c9d8198b58410ec26a346ba35d384fc0d", size = 759394, upload-time = "2026-07-23T07:16:57.551Z" }, + { url = "https://files.pythonhosted.org/packages/97/1d/5ade6e0c80ce8160bbcd55c300d95a5450cdb82fa04fdcdd8a33f6198441/hypothesis-6.161.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fee553e5150af6d66ee058f3ccbc3b5b83e6df62139e8935abd0510254a2d4a7", size = 1089752, upload-time = "2026-07-23T07:16:34.18Z" }, + { url = "https://files.pythonhosted.org/packages/99/02/14c6d54e60159ba9991a52b14ea5a9b6935d4878ffe9d0a8fabd2d166767/hypothesis-6.161.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f8110cd815f3a79e2351700654c21771eec47d98a78db56cc81879d41f08ed1", size = 1139731, upload-time = "2026-07-23T07:17:28.51Z" }, + { url = "https://files.pythonhosted.org/packages/36/98/c099c382b0fbf6dfd209d35961e6ee9739ad1d787288a40eb364b278217a/hypothesis-6.161.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16aacb26a277d25da7466f0588c2687811334455753d513c55d8ca4dbbc5174e", size = 1262736, upload-time = "2026-07-23T07:16:07.875Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3a/6b1fbde6e2a1c9bd54acb1e5d8fa866c6fef59a829a67ca310f5d12a8fbe/hypothesis-6.161.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eb24cf5f7f301ad3db14caa4462ebc2e693fe38815d793ff6dbc116820b18dff", size = 1306628, upload-time = "2026-07-23T07:16:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c2/033da1694f956f0c566b12a1f0667138ad06a3b0a67837f17c6873cc2513/hypothesis-6.161.0-cp313-cp313-win_amd64.whl", hash = "sha256:e4f715f5598444a0d569aa8a3e74ebc14a46c67a873193db38c8542b2838e91f", size = 655355, upload-time = "2026-07-23T07:16:48.054Z" }, + { url = "https://files.pythonhosted.org/packages/2b/26/29582b8ba467eedf270515422f41cb564d06b4eef38bdf06e236cc841546/hypothesis-6.161.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:a046954e17a1edd20b6c95e9d29f1df7bc20ccab94c01aa8b4177552896230fb", size = 767928, upload-time = "2026-07-23T07:17:12.935Z" }, + { url = "https://files.pythonhosted.org/packages/f7/25/bb7cfd851f6b0f4b0130485785a3447621523116b89f8d82042fb9897752/hypothesis-6.161.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2d503b0fdb916371d536b33fad0c4f909846af2fc4273d3049ca6fe661aa81ff", size = 759542, upload-time = "2026-07-23T07:16:41.736Z" }, + { url = "https://files.pythonhosted.org/packages/d9/ab/bc31d4aa5840c2438e011a615095b0e2fae5de94c3abfc18a01686825ea7/hypothesis-6.161.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df011a94870dc3e1b5fb4fb8d2c68dd641b412a3b73050288d85af1467c9a689", size = 1090304, upload-time = "2026-07-23T07:16:19.817Z" }, + { url = "https://files.pythonhosted.org/packages/51/ee/6304f6184aee6a1b91fff746a767b4f3aab58c29e48e64cc16d56fc6dedc/hypothesis-6.161.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4678e3988503b3bd5be0ed995f84cc15ac4f99c168bade32456a08c04868f3f3", size = 1139915, upload-time = "2026-07-23T07:17:14.565Z" }, + { url = "https://files.pythonhosted.org/packages/f5/6d/23efce26bf7f1773346732c58a23cbe33ed4f171da1bb3aa11bf349fdb4c/hypothesis-6.161.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74c6e5b5623f37eb6af8be6f861d138fac3ee3528ee30c3b48ff11c39f7be4b7", size = 1263070, upload-time = "2026-07-23T07:16:15.695Z" }, + { url = "https://files.pythonhosted.org/packages/0b/a2/e0b4bf410630f16661eea6fdf9c3970e47c749a837de12098d63c81bb01b/hypothesis-6.161.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b841c25267ab360812a523d1861e0b0ed0f5cc4e6d7bcecc9d9eddd3f835aa0f", size = 1306929, upload-time = "2026-07-23T07:16:37.086Z" }, + { url = "https://files.pythonhosted.org/packages/03/13/58047eb148a31ae7cce26ec0b2f0e980c46874c6673c1110c53684ba181a/hypothesis-6.161.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:a0f3830c1e816e34bd8cd940244c8c877dedc2ecfea771d2ecea252bc35eb21d", size = 599455, upload-time = "2026-07-23T07:16:25.552Z" }, + { url = "https://files.pythonhosted.org/packages/f0/0e/a206013edd7dfd44b9a81ae1946a1ea30d878974850d60a61fa128cc170d/hypothesis-6.161.0-cp314-cp314-win_amd64.whl", hash = "sha256:d1d38f05acb9c25181157f1756f5faaa1759b4641ff6b32cb1d2ab1d55d6af2d", size = 655306, upload-time = "2026-07-23T07:17:30.273Z" }, + { url = "https://files.pythonhosted.org/packages/e2/74/32d224a0ccf4ca9af6acc1d805047e12cd13105e0769d54ac00a86f25850/hypothesis-6.161.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:81570959521eebd0172ea9132ffab71b90050e7cd44d045da67210aa9a594376", size = 766503, upload-time = "2026-07-23T07:16:10.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5d/8b61c3490fd8195a25fdc37e951ccba3ae4df2c74839ffe6a6d5720fdb79/hypothesis-6.161.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:46a6039181337b85a995666e9bf87cc2390282720ba345479bb9be9c867914da", size = 758013, upload-time = "2026-07-23T07:17:26.71Z" }, + { url = "https://files.pythonhosted.org/packages/d9/11/ac4ab15ec4586a23bb4e2acdcbed814517e341f2940eeb74fbf428dac243/hypothesis-6.161.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f2d4141c952f522d6aae0e493d170f9b0127c001319bd312ee9cfba7ed419d4", size = 1088871, upload-time = "2026-07-23T07:17:02.884Z" }, + { url = "https://files.pythonhosted.org/packages/27/13/fd83965bcdd44dc5002c67fe8e8e2e974ed45c82dc6864e104c1c70093d5/hypothesis-6.161.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ed3e1b9c036954bfabe64899072a18e6b5113703d32a96645c6656a8cfc43e", size = 1138801, upload-time = "2026-07-23T07:17:35.354Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e7/a4ad5f3b0b805fd2e583d193e2a762cd413465b524ef07829452521dca6d/hypothesis-6.161.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:aba1508da6c317819305e875bf6c4d4dd0922193c76416d4cc907447ebe08fea", size = 1261305, upload-time = "2026-07-23T07:17:23.201Z" }, + { url = "https://files.pythonhosted.org/packages/38/54/35e1b62ece96c24921e9a1e811179d54a6429d9611a2cd49504f5b95382e/hypothesis-6.161.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:981acb3efa88df363a0d31e0f4bacd36ef739104eee789a6b12c7f7200a457fc", size = 1305689, upload-time = "2026-07-23T07:17:21.476Z" }, + { url = "https://files.pythonhosted.org/packages/04/87/6491e9a36d8e8df67a3b9c3eeb5a85c12c6b0d5302b5ce395b5427698b52/hypothesis-6.161.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e71e229f2dec694685245b8e55e908855b475c17ab8337bcf848768b4c32aa97", size = 655436, upload-time = "2026-07-23T07:17:04.424Z" }, + { url = "https://files.pythonhosted.org/packages/54/e2/0782e45562fb091cd75bd12f69932c8aa55a9e3bb699599f43e5258d013c/hypothesis-6.161.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:33a19886dc05b489f0ab632c89b8ca9dc6f89a0b380b6405671cecb2b0d5b5c4", size = 767674, upload-time = "2026-07-23T07:17:16.37Z" }, + { url = "https://files.pythonhosted.org/packages/03/46/eaccb5375ed83396be3153857f9de808b5d5ecc001fab8e30bf8e30d33d4/hypothesis-6.161.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b4fd38d0e757ae290583774b3695ab0d7f0da80e924c6473de84483449c6da8d", size = 763579, upload-time = "2026-07-23T07:16:46.309Z" }, + { url = "https://files.pythonhosted.org/packages/99/48/31ca6b9414cf30388ba825c740b13ab74f6afcf856a194a9256f7f1ca38d/hypothesis-6.161.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59dc6871e2fbbfd2d28e7e6f33d19bd8513a3b7510bd0b224a59bbebdd5cc1b3", size = 1092394, upload-time = "2026-07-23T07:17:01.136Z" }, + { url = "https://files.pythonhosted.org/packages/75/1d/709c03af162418c0b3e0cf624549b13ecacd8df0f2ca09d53214702cb1f8/hypothesis-6.161.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55ff16ec4b4e98bfd97e9a2a44905eaf7a3ec8f3f157d8c7eac2385a88059a29", size = 1142170, upload-time = "2026-07-23T07:17:32.044Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ae/63458a5f80db8433beb7556482e3de1a6789b6c469a5f2f99c21aaa7fdef/hypothesis-6.161.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:77ae374d9ed7046b15443053b11f5b05e185bca24b3b849c3f473a9e4cc85451", size = 659069, upload-time = "2026-07-23T07:16:12.922Z" }, ] [[package]] name = "iniconfig" version = "2.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503 } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484 }, + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] [[package]] @@ -726,27 +728,27 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454 } +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687 }, + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] [[package]] name = "packaging" version = "26.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134 } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195 }, + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, ] [[package]] @@ -756,55 +758,53 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "regex" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7b/91/abdc50c4ef06fdf8d047f60ee777ca9b2a7885e1a9cea81343fbecda52d7/parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c", size = 52172 } +sdist = { url = "https://files.pythonhosted.org/packages/7b/91/abdc50c4ef06fdf8d047f60ee777ca9b2a7885e1a9cea81343fbecda52d7/parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c", size = 52172, upload-time = "2022-09-03T17:01:17.004Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/0f/c8b64d9b54ea631fcad4e9e3c8dbe8c11bb32a623be94f22974c88e71eaf/parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f", size = 48427 }, + { url = "https://files.pythonhosted.org/packages/aa/0f/c8b64d9b54ea631fcad4e9e3c8dbe8c11bb32a623be94f22974c88e71eaf/parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f", size = 48427, upload-time = "2022-09-03T17:01:13.814Z" }, ] [[package]] name = "pluggy" version = "1.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412 } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538 }, + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] [[package]] name = "pycryptodome" version = "3.23.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152 }, - { url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348 }, - { url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033 }, - { url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142 }, - { url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384 }, - { url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237 }, - { url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898 }, - { url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197 }, - { url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600 }, - { url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740 }, - { url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685 }, - { url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627 }, - { url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362 }, - { url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625 }, - { url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954 }, - { url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534 }, - { url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853 }, - { url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465 }, - { url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414 }, - { url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484 }, - { url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636 }, - { url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675 }, - { url = "https://files.pythonhosted.org/packages/9f/7c/f5b0556590e7b4e710509105e668adb55aa9470a9f0e4dea9c40a4a11ce1/pycryptodome-3.23.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:350ebc1eba1da729b35ab7627a833a1a355ee4e852d8ba0447fafe7b14504d56", size = 1705791 }, - { url = "https://files.pythonhosted.org/packages/33/38/dcc795578d610ea1aaffef4b148b8cafcfcf4d126b1e58231ddc4e475c70/pycryptodome-3.23.0-pp27-pypy_73-win32.whl", hash = "sha256:93837e379a3e5fd2bb00302a47aee9fdf7940d83595be3915752c74033d17ca7", size = 1780265 }, - { url = "https://files.pythonhosted.org/packages/d9/12/e33935a0709c07de084d7d58d330ec3f4daf7910a18e77937affdb728452/pycryptodome-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddb95b49df036ddd264a0ad246d1be5b672000f12d6961ea2c267083a5e19379", size = 1623886 }, - { url = "https://files.pythonhosted.org/packages/22/0b/aa8f9419f25870889bebf0b26b223c6986652bdf071f000623df11212c90/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e95564beb8782abfd9e431c974e14563a794a4944c29d6d3b7b5ea042110b4", size = 1672151 }, - { url = "https://files.pythonhosted.org/packages/d4/5e/63f5cbde2342b7f70a39e591dbe75d9809d6338ce0b07c10406f1a140cdc/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e15c081e912c4b0d75632acd8382dfce45b258667aa3c67caf7a4d4c13f630", size = 1664461 }, - { url = "https://files.pythonhosted.org/packages/d6/92/608fbdad566ebe499297a86aae5f2a5263818ceeecd16733006f1600403c/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fc76bf273353dc7e5207d172b83f569540fc9a28d63171061c42e361d22353", size = 1702440 }, - { url = "https://files.pythonhosted.org/packages/d1/92/2eadd1341abd2989cce2e2740b4423608ee2014acb8110438244ee97d7ff/pycryptodome-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:45c69ad715ca1a94f778215a11e66b7ff989d792a4d63b68dc586a1da1392ff5", size = 1803005 }, + { url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" }, + { url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" }, + { url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" }, + { url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" }, + { url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" }, + { url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" }, + { url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" }, + { url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" }, + { url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" }, + { url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" }, + { url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" }, + { url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" }, + { url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" }, + { url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" }, + { url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" }, + { url = "https://files.pythonhosted.org/packages/d9/12/e33935a0709c07de084d7d58d330ec3f4daf7910a18e77937affdb728452/pycryptodome-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddb95b49df036ddd264a0ad246d1be5b672000f12d6961ea2c267083a5e19379", size = 1623886, upload-time = "2025-05-17T17:21:20.614Z" }, + { url = "https://files.pythonhosted.org/packages/22/0b/aa8f9419f25870889bebf0b26b223c6986652bdf071f000623df11212c90/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e95564beb8782abfd9e431c974e14563a794a4944c29d6d3b7b5ea042110b4", size = 1672151, upload-time = "2025-05-17T17:21:22.666Z" }, + { url = "https://files.pythonhosted.org/packages/d4/5e/63f5cbde2342b7f70a39e591dbe75d9809d6338ce0b07c10406f1a140cdc/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e15c081e912c4b0d75632acd8382dfce45b258667aa3c67caf7a4d4c13f630", size = 1664461, upload-time = "2025-05-17T17:21:25.225Z" }, + { url = "https://files.pythonhosted.org/packages/d6/92/608fbdad566ebe499297a86aae5f2a5263818ceeecd16733006f1600403c/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fc76bf273353dc7e5207d172b83f569540fc9a28d63171061c42e361d22353", size = 1702440, upload-time = "2025-05-17T17:21:27.991Z" }, + { url = "https://files.pythonhosted.org/packages/d1/92/2eadd1341abd2989cce2e2740b4423608ee2014acb8110438244ee97d7ff/pycryptodome-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:45c69ad715ca1a94f778215a11e66b7ff989d792a4d63b68dc586a1da1392ff5", size = 1803005, upload-time = "2025-05-17T17:21:31.37Z" }, ] [[package]] @@ -817,9 +817,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775 } +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262 }, + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, ] [[package]] @@ -829,122 +829,122 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464 } +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/08/f1ba952f1c8ae5581c70fa9c6da89f247b83e3dd8c09c035d5d7931fc23d/pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4", size = 2113146 }, - { url = "https://files.pythonhosted.org/packages/56/c6/65f646c7ff09bd257f660434adb45c4dfcbbcebcc030562fecf6f5bf887d/pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5", size = 1949769 }, - { url = "https://files.pythonhosted.org/packages/64/ba/bfb1d928fd5b49e1258935ff104ae356e9fd89384a55bf9f847e9193ad40/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba", size = 1974958 }, - { url = "https://files.pythonhosted.org/packages/4e/74/76223bfb117b64af743c9b6670d1364516f5c0604f96b48f3272f6af6cc6/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b", size = 2042118 }, - { url = "https://files.pythonhosted.org/packages/cb/7b/848732968bc8f48f3187542f08358b9d842db564147b256669426ebb1652/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c", size = 2222876 }, - { url = "https://files.pythonhosted.org/packages/b5/2f/e90b63ee2e14bd8d3db8f705a6d75d64e6ee1b7c2c8833747ce706e1e0ce/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50", size = 2286703 }, - { url = "https://files.pythonhosted.org/packages/ba/1e/acc4d70f88a0a277e4a1fa77ebb985ceabaf900430f875bf9338e11c9420/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd", size = 2092042 }, - { url = "https://files.pythonhosted.org/packages/a9/da/0a422b57bf8504102bf3c4ccea9c41bab5a5cee6a54650acf8faf67f5a24/pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01", size = 2117231 }, - { url = "https://files.pythonhosted.org/packages/bd/2a/2ac13c3af305843e23c5078c53d135656b3f05a2fd78cb7bbbb12e97b473/pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d", size = 2168388 }, - { url = "https://files.pythonhosted.org/packages/72/04/2beacf7e1607e93eefe4aed1b4709f079b905fb77530179d4f7c71745f22/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4", size = 2184769 }, - { url = "https://files.pythonhosted.org/packages/9e/29/d2b9fd9f539133548eaf622c06a4ce176cb46ac59f32d0359c4abc0de047/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f", size = 2319312 }, - { url = "https://files.pythonhosted.org/packages/7c/af/0f7a5b85fec6075bea96e3ef9187de38fccced0de92c1e7feda8d5cc7bb9/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39", size = 2361817 }, - { url = "https://files.pythonhosted.org/packages/25/a4/73363fec545fd3ec025490bdda2743c56d0dd5b6266b1a53bbe9e4265375/pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d", size = 1987085 }, - { url = "https://files.pythonhosted.org/packages/01/aa/62f082da2c91fac1c234bc9ee0066257ce83f0604abd72e4c9d5991f2d84/pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf", size = 2074311 }, - { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872 }, - { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255 }, - { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827 }, - { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051 }, - { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314 }, - { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146 }, - { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685 }, - { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420 }, - { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122 }, - { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573 }, - { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139 }, - { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433 }, - { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513 }, - { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114 }, - { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298 }, - { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158 }, - { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724 }, - { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742 }, - { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418 }, - { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274 }, - { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940 }, - { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516 }, - { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854 }, - { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306 }, - { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044 }, - { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133 }, - { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464 }, - { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823 }, - { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919 }, - { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604 }, - { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306 }, - { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906 }, - { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802 }, - { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446 }, - { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757 }, - { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275 }, - { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467 }, - { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417 }, - { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782 }, - { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782 }, - { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334 }, - { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986 }, - { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693 }, - { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819 }, - { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411 }, - { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079 }, - { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179 }, - { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926 }, - { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785 }, - { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733 }, - { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534 }, - { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732 }, - { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627 }, - { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141 }, - { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325 }, - { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990 }, - { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978 }, - { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354 }, - { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238 }, - { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251 }, - { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593 }, - { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226 }, - { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605 }, - { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777 }, - { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641 }, - { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404 }, - { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219 }, - { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594 }, - { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542 }, - { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146 }, - { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309 }, - { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736 }, - { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575 }, - { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624 }, - { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325 }, - { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589 }, - { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552 }, - { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984 }, - { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417 }, - { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527 }, - { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024 }, - { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696 }, - { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590 }, - { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782 }, - { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146 }, - { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492 }, - { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604 }, - { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828 }, - { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000 }, - { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286 }, - { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071 }, + { url = "https://files.pythonhosted.org/packages/e7/08/f1ba952f1c8ae5581c70fa9c6da89f247b83e3dd8c09c035d5d7931fc23d/pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4", size = 2113146, upload-time = "2026-05-06T13:37:36.537Z" }, + { url = "https://files.pythonhosted.org/packages/56/c6/65f646c7ff09bd257f660434adb45c4dfcbbcebcc030562fecf6f5bf887d/pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5", size = 1949769, upload-time = "2026-05-06T13:37:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/64/ba/bfb1d928fd5b49e1258935ff104ae356e9fd89384a55bf9f847e9193ad40/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba", size = 1974958, upload-time = "2026-05-06T13:37:28.611Z" }, + { url = "https://files.pythonhosted.org/packages/4e/74/76223bfb117b64af743c9b6670d1364516f5c0604f96b48f3272f6af6cc6/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b", size = 2042118, upload-time = "2026-05-06T13:36:55.216Z" }, + { url = "https://files.pythonhosted.org/packages/cb/7b/848732968bc8f48f3187542f08358b9d842db564147b256669426ebb1652/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c", size = 2222876, upload-time = "2026-05-06T13:38:25.455Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2f/e90b63ee2e14bd8d3db8f705a6d75d64e6ee1b7c2c8833747ce706e1e0ce/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50", size = 2286703, upload-time = "2026-05-06T13:37:53.304Z" }, + { url = "https://files.pythonhosted.org/packages/ba/1e/acc4d70f88a0a277e4a1fa77ebb985ceabaf900430f875bf9338e11c9420/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd", size = 2092042, upload-time = "2026-05-06T13:38:46.981Z" }, + { url = "https://files.pythonhosted.org/packages/a9/da/0a422b57bf8504102bf3c4ccea9c41bab5a5cee6a54650acf8faf67f5a24/pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01", size = 2117231, upload-time = "2026-05-06T13:39:23.146Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2a/2ac13c3af305843e23c5078c53d135656b3f05a2fd78cb7bbbb12e97b473/pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d", size = 2168388, upload-time = "2026-05-06T13:40:08.06Z" }, + { url = "https://files.pythonhosted.org/packages/72/04/2beacf7e1607e93eefe4aed1b4709f079b905fb77530179d4f7c71745f22/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4", size = 2184769, upload-time = "2026-05-06T13:38:13.901Z" }, + { url = "https://files.pythonhosted.org/packages/9e/29/d2b9fd9f539133548eaf622c06a4ce176cb46ac59f32d0359c4abc0de047/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f", size = 2319312, upload-time = "2026-05-06T13:39:08.24Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/0f7a5b85fec6075bea96e3ef9187de38fccced0de92c1e7feda8d5cc7bb9/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39", size = 2361817, upload-time = "2026-05-06T13:38:43.2Z" }, + { url = "https://files.pythonhosted.org/packages/25/a4/73363fec545fd3ec025490bdda2743c56d0dd5b6266b1a53bbe9e4265375/pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d", size = 1987085, upload-time = "2026-05-06T13:39:25.497Z" }, + { url = "https://files.pythonhosted.org/packages/01/aa/62f082da2c91fac1c234bc9ee0066257ce83f0604abd72e4c9d5991f2d84/pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf", size = 2074311, upload-time = "2026-05-06T13:39:59.922Z" }, + { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" }, + { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" }, + { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" }, + { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" }, + { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" }, + { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" }, + { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" }, + { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513, upload-time = "2026-05-06T13:38:15.669Z" }, + { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114, upload-time = "2026-05-06T13:40:35.416Z" }, + { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298, upload-time = "2026-05-06T13:38:29.754Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" }, + { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, + { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" }, + { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" }, + { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" }, + { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" }, ] [[package]] name = "pygments" version = "2.20.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991 } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151 }, + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] [[package]] @@ -960,9 +960,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369 } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536 }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] @@ -974,9 +974,9 @@ dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514 } +sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930 }, + { url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930, upload-time = "2026-05-26T09:56:02.576Z" }, ] [[package]] @@ -988,9 +988,9 @@ dependencies = [ { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592 } +sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876 }, + { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] [[package]] @@ -1001,9 +1001,9 @@ dependencies = [ { name = "execnet" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069 } +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396 }, + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, ] [[package]] @@ -1013,130 +1013,130 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8f/b2/7fc2931bfae0af02d5f53b174e9cf701adbb35f39d69c2af63d4a39f81a9/qrcode-8.2.tar.gz", hash = "sha256:35c3f2a4172b33136ab9f6b3ef1c00260dd2f66f858f24d88418a015f446506c", size = 43317 } +sdist = { url = "https://files.pythonhosted.org/packages/8f/b2/7fc2931bfae0af02d5f53b174e9cf701adbb35f39d69c2af63d4a39f81a9/qrcode-8.2.tar.gz", hash = "sha256:35c3f2a4172b33136ab9f6b3ef1c00260dd2f66f858f24d88418a015f446506c", size = 43317, upload-time = "2025-05-01T15:44:24.726Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/b8/d2d6d731733f51684bbf76bf34dab3b70a9148e8f2cef2bb544fccec681a/qrcode-8.2-py3-none-any.whl", hash = "sha256:16e64e0716c14960108e85d853062c9e8bba5ca8252c0b4d0231b9df4060ff4f", size = 45986 }, + { url = "https://files.pythonhosted.org/packages/dd/b8/d2d6d731733f51684bbf76bf34dab3b70a9148e8f2cef2bb544fccec681a/qrcode-8.2-py3-none-any.whl", hash = "sha256:16e64e0716c14960108e85d853062c9e8bba5ca8252c0b4d0231b9df4060ff4f", size = 45986, upload-time = "2025-05-01T15:44:22.781Z" }, ] [[package]] name = "regex" version = "2026.6.28" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/05/e4f219230e11e774a6c9987d2ab0d0c6b8573e13a17e143d0015bee710ef/regex-2026.6.28.tar.gz", hash = "sha256:3cb4b6c5cb3060cc31efdc1fbb27c25fb9b29044afd87e40601a1c4d9db54342", size = 416101 } +sdist = { url = "https://files.pythonhosted.org/packages/f1/05/e4f219230e11e774a6c9987d2ab0d0c6b8573e13a17e143d0015bee710ef/regex-2026.6.28.tar.gz", hash = "sha256:3cb4b6c5cb3060cc31efdc1fbb27c25fb9b29044afd87e40601a1c4d9db54342", size = 416101, upload-time = "2026-06-28T19:56:55.302Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/dc/f7a8c9cf0768f704153d358fae2bc883199bc4ea1e4aa458f1be9d0ef2ce/regex-2026.6.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b83932645630965fd860fdb70ebbf964bf3e8007f08851ea424d01f8d35454a8", size = 489471 }, - { url = "https://files.pythonhosted.org/packages/44/b3/9786a4a2133e2f1cc5897ed3d2da3da29ff54b775ffa38bc5935fc24be82/regex-2026.6.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e81f1952355042e517dc9861ce65c676e4a098f42402993c40461786d1f794d4", size = 291294 }, - { url = "https://files.pythonhosted.org/packages/dd/1f/bfe5b529257f0853aa6b94146e0f6462f4d45aa4f3c05d5a828f415dfd40/regex-2026.6.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2097591101d70bcc108af64c46f6066bb698ee067fec5f75beac0be317639311", size = 289216 }, - { url = "https://files.pythonhosted.org/packages/25/56/f615165e90ac5f3b72b249240643439520bbac0ac60a9de06868528eba4c/regex-2026.6.28-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:31d7538a614b5842bf53ce329d07b43f97754ca7e6db8d69f347e071bce1c953", size = 784787 }, - { url = "https://files.pythonhosted.org/packages/04/94/c9e3ad31b3d5fbe1228fee8319e0c02a5460296624f220d08764547fe6ae/regex-2026.6.28-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5561e47bbe2b75373b695326507743fcdd4d2cc7f5022312024ccf39fa094e0", size = 852137 }, - { url = "https://files.pythonhosted.org/packages/c0/77/d506a428e446466ee298f5425a774737d0671d070425ed794bb3314d60c6/regex-2026.6.28-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c10f2c5a55ab3dd8318d8ad5f11b530e2691c0edebebde7713066f484902c3fb", size = 899525 }, - { url = "https://files.pythonhosted.org/packages/aa/72/becc00d839f19401f10a20168b44711c7b02f7f62bba875b2d8f98417435/regex-2026.6.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23f7e0cc60c72486b42a685f1ff4eec90d50d4fb05e4f9c7d5363b03aa02600d", size = 794116 }, - { url = "https://files.pythonhosted.org/packages/fa/11/ea2ca423eeaac2e18077a18b058614e9201f130750df2126d444e39acab2/regex-2026.6.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:76493755f79a88d5ed2c9e63a41d3c05997e0a7ffbe76ed8c4ded8be35b8b14c", size = 786257 }, - { url = "https://files.pythonhosted.org/packages/6d/9e/f5bf7ecbd14ff2086f015c54dc24fd0d74ba5327fef0de479213f8128615/regex-2026.6.28-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ff0f41a00f23ea5054acb61901380c41813d813eee3f80f800995710bcc52ecd", size = 769914 }, - { url = "https://files.pythonhosted.org/packages/43/04/f9040a5360a06241ba5b7f2e6f1c6184e104a84e6f6522535700e94bf8e2/regex-2026.6.28-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3c60b297292e7e1ef5d02a4759f9e452ee4c8bb95e168d8fd0b5db01bd806f9f", size = 775013 }, - { url = "https://files.pythonhosted.org/packages/73/97/4e46f7abf2f864319d2bcac609af3c0532968c66a3364337778fd232b83c/regex-2026.6.28-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a7cf03c87f7b9cbc25a8894cf9be83818406677b6b391b003ec7c884923387b5", size = 848814 }, - { url = "https://files.pythonhosted.org/packages/f7/b8/3d1f995727799a1e2e693e397acb7358094606e5591b6b5fd3128d2d1409/regex-2026.6.28-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:418208ea0af51cfed4f46eb9b1ea7cfc990ca284f0084ecbd951460fb089421e", size = 757702 }, - { url = "https://files.pythonhosted.org/packages/20/10/fd5653b8572910a4fe9055f8959b070d7d9443c94ce986529fcdb5fb2a3c/regex-2026.6.28-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:7635fa2cddb917a6bbfac7890602573d2d8c4e470703b0640e6f86a988817ec3", size = 837140 }, - { url = "https://files.pythonhosted.org/packages/5d/31/da77e3ef7b594a2aacbd03ce3d0050f33ab3e021df50c6901467c9006511/regex-2026.6.28-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7bb96c13d6cf5880d31bbef84ca701a64d738aa491c2b79975cc33f8ad00a31e", size = 782105 }, - { url = "https://files.pythonhosted.org/packages/cd/4d/c379001448d0f58b6946f168d4af96ad60a16c1553259c27b0df8701b640/regex-2026.6.28-cp310-cp310-win32.whl", hash = "sha256:56f05194c4843957dd8b3af87eb0c52d8cf0509e7f18e172d727f5f8ff840646", size = 266728 }, - { url = "https://files.pythonhosted.org/packages/f3/8f/cb656529efa87d74cce0d69e606c745537016da3bdfae78f342af2242ee3/regex-2026.6.28-cp310-cp310-win_amd64.whl", hash = "sha256:70710927033af3b54369f17aaba1343b97a23d0b1aa994fa1512b08b1b8c136a", size = 277901 }, - { url = "https://files.pythonhosted.org/packages/7b/ac/d35ccc309c9409406445ab2ef0b56f6a341a916ccff49ff9ac5cc6bb8e9b/regex-2026.6.28-cp310-cp310-win_arm64.whl", hash = "sha256:ed7b30185ee3f8b9b053b0be567b4d226016e2afbebc17fde1c6a4580937b688", size = 276880 }, - { url = "https://files.pythonhosted.org/packages/72/db/9051b36294bdbabaa9c7db57db0fbcdfbd17f7a106c539bb423d0323faea/regex-2026.6.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a71b51dd08b9b62f055fafab3dee8af8bd2ec81b373a44caef18d6c5ca28f43a", size = 489481 }, - { url = "https://files.pythonhosted.org/packages/35/3f/24097a3c3ff30f9a639888900faaecabcf5f54a5bc9c851c297e11b349ef/regex-2026.6.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9c26a47770d30a0f85c01e261d2a3ebc342c4af6fd666dbd8c1fe4cbf3adf726", size = 291292 }, - { url = "https://files.pythonhosted.org/packages/5e/cc/e0d762a189cfb4e8926d16e691720690d139a977b38fdb80230c259332ab/regex-2026.6.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5efbc1af38f97e300d43028e5a92e752d924bcfb7f465d8669d5d5a6e78c233", size = 289232 }, - { url = "https://files.pythonhosted.org/packages/4b/c8/ca0ac7f09cc88ca61e0c61c53f7db29334f660ffba5d0b52378e7c44723c/regex-2026.6.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1758df6fdd8c800620a5638958720e8a635e1da49a2f09df2dd63e94a24ec4a", size = 792332 }, - { url = "https://files.pythonhosted.org/packages/8e/92/04ae94cbe0dd1f478b2aef6c46f995bb6946d3e338d4b28605478b66a2b7/regex-2026.6.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ad73ecf20c1ef5c975639f8bf845a9370fcf7dada7edc1e3b0bca20e2f8202f6", size = 861743 }, - { url = "https://files.pythonhosted.org/packages/4c/ec/024d7638c807679ff8a0e6081d01d66c7762339af1cac71e45911587ff9a/regex-2026.6.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d80c798b0eec6ea3d45f8816a1e8886c5664615d347d89e8c075b576a1b5a5d", size = 906481 }, - { url = "https://files.pythonhosted.org/packages/cd/fd/93bfe5af45f0be4fa8983945455c0e6924e1aeb879cde227958869c1e71c/regex-2026.6.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a361feeaf1b6ba1df060f2ff5c5947092edf537a35ce78e76387ac56d3e0f4a4", size = 799867 }, - { url = "https://files.pythonhosted.org/packages/ee/fd/e5d965d41f2398c8ce0f37a4652f03bb297fd009bb796d390134225dda12/regex-2026.6.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8b92366d9c8bba9642989534073662abdd9b41faf7603a7ae71597833f3b88f0", size = 773632 }, - { url = "https://files.pythonhosted.org/packages/eb/d9/ff39afaec92b9ee2dba0302a4783976005091681069808938c31cf8df3b6/regex-2026.6.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:11251768cc23f097dd61b18f67966e70f74da822784d17e12a444eb6b29d4288", size = 781669 }, - { url = "https://files.pythonhosted.org/packages/45/4e/e2fd4bb8228e10c24af2d7ff867182372190e498eab9fd29cbe54c403c95/regex-2026.6.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad5c67786145ec28a71a267d9f9d92bdc8d70d65541eea852c253f520a01f918", size = 854497 }, - { url = "https://files.pythonhosted.org/packages/72/7c/f0340384a973082979064156d05f3d2cc1dced7371efcd7a1b45726a1a8a/regex-2026.6.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f1da438e739765c3e85175ede05816cbede3caaacb1e0680568bda6119bfdfca", size = 763335 }, - { url = "https://files.pythonhosted.org/packages/e1/32/90ce0d0898e205506cc22b9c81cfb16b722e06ca5f50fad51c053c2a727b/regex-2026.6.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d98b639046e51c5de64d9f77351532105e99ca271cb6f7640e1f903d6ab63032", size = 844615 }, - { url = "https://files.pythonhosted.org/packages/6a/ef/55abb149599dce1ade687170557129524011eeb3d92afe02429cea7754a2/regex-2026.6.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e164ace4dbab5c6ad4a4ac7c41a2638fe226d0c770a86f2eb041f594bac6ee7", size = 789193 }, - { url = "https://files.pythonhosted.org/packages/f8/ea/cf7f6f6f152e52fdad978b913bf24c14df647eca0f81ef31f3aee0be8982/regex-2026.6.28-cp311-cp311-win32.whl", hash = "sha256:3169a3159e4d99d9ae85ff0ed90ef3b8906cc3152653b6078b842ace6c8f72c3", size = 266731 }, - { url = "https://files.pythonhosted.org/packages/c6/cf/a48d8e8d406b22481cad146f48fa0dfca3c5f402b91f26d8e5a0fe4f513d/regex-2026.6.28-cp311-cp311-win_amd64.whl", hash = "sha256:5977295b0a74e8241df8a4b3b27b12412a831f6fa32ee8b755039592cd768c3d", size = 277918 }, - { url = "https://files.pythonhosted.org/packages/89/b2/a222392207db7ed86281a732a99f7cf7f2bb35d332799e892b8510be000e/regex-2026.6.28-cp311-cp311-win_arm64.whl", hash = "sha256:f5fbaef40c3e9282ccee4b075f5600a0d858aa0c34147732f1baa69c8188a95d", size = 276876 }, - { url = "https://files.pythonhosted.org/packages/da/21/44aa415873032056c43eac21c67285deb2cf66cddb2a964c3cdc8f803efc/regex-2026.6.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:81cc5793ad33a10444445e8d29d3c73e752c8fb2e120772d70fcb6d41df40fe1", size = 490480 }, - { url = "https://files.pythonhosted.org/packages/8b/5f/30d4116093c2128099f78b6990dfc1698fdbf3ee528f1e1c647378034c79/regex-2026.6.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e18225243250a1f7d7e5e5d883f3b96465cd79031acf5c6db902b7025f2125d9", size = 292137 }, - { url = "https://files.pythonhosted.org/packages/cb/0e/ca20a0e0de49837e6337603a91ab77556aa27033ac5b975615d98698cfb3/regex-2026.6.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ecd1638b1c2db1f2d01c182a4b0d3e2e88b0e99910320a745c1727ee3638ddab", size = 289623 }, - { url = "https://files.pythonhosted.org/packages/50/11/c013422a7e2c59946df8ac93e792a4922c98287f2a2181341603c78a5d98/regex-2026.6.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4303ebe16b74eeb3fe2715745023266fea92fd44a23f3e7bb2fb48c7a7bbc195", size = 796756 }, - { url = "https://files.pythonhosted.org/packages/b0/95/1309645a0e1ee6fb91d954501da57a0b33d50ad2a9acb313702851a7054e/regex-2026.6.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56b856b70b96c381d837f609eee442a1bd320cd2159f5c294b679552fb1a7eaf", size = 865465 }, - { url = "https://files.pythonhosted.org/packages/20/06/491802db47c6f5e2904ffa2518ad3ac27fe6bbf5a66d73210a95cc080d47/regex-2026.6.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f74675ab76ab1d005ffba4dee308e53e89efc22be6e9f9fae5b539a3f81bdff2", size = 912350 }, - { url = "https://files.pythonhosted.org/packages/5e/60/3ba57840bcc7e2367090360de0c15a5ba6ad22be89314251105f2e943f43/regex-2026.6.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90581684565a93f7258af1e5d3f41ef20d7d7c61f2a428183a342bcb65485e38", size = 801261 }, - { url = "https://files.pythonhosted.org/packages/eb/27/af1eb74e9a78c782b3e450b611a595e44906da8a5107e1227f4a7fd0480b/regex-2026.6.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:28f9e6c28f9b90f6f784595a33240a57e181e61b6ee3dc259b25c61e356d1aa3", size = 777072 }, - { url = "https://files.pythonhosted.org/packages/20/18/fdd4c883a39e3ed00d669062af1135809bfd3281bf528150849fbd68825b/regex-2026.6.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:378a71d861fc7c8806b04ac5b133d53c0e774f92f5d9663a539872d3fa2b0417", size = 785119 }, - { url = "https://files.pythonhosted.org/packages/1c/79/0aabe34b8482dcadf64355f70f96e22eba5ec6c1efb33563f89654f4061c/regex-2026.6.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4cc199874ecd6267a49b111052250825bfe19b5101b23b2ba80f54efa3e0994e", size = 860118 }, - { url = "https://files.pythonhosted.org/packages/a8/2c/c973323306a27c9db7d160e9584eb7e0ece2a96224ccb0d39060558b31f9/regex-2026.6.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b916a10431494ef4b4d62c6c89cab6426af7873125b8cd6c15811bf5fc58eec8", size = 765786 }, - { url = "https://files.pythonhosted.org/packages/e3/df/9ca3e378e352242a4cb45573a5e9162c3ee791507702a23966fa559e36b5/regex-2026.6.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e27727fba075f1e4409416d2f537d4c30fc11f012ea507f7bd74d3e19ecb57a", size = 852120 }, - { url = "https://files.pythonhosted.org/packages/a2/3e/3e31e255c4971f53cbce6306b5e3c76cbd3735a54f419bb3b2f194e9f68c/regex-2026.6.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:700fc6a7844bb2c4149292ac79d1df8841a00acd4d45cd32c1ebc7bcc1fd0da8", size = 789503 }, - { url = "https://files.pythonhosted.org/packages/72/01/d36561c21c3033d7eeb31d51b491916817de7861acefccc5fc9db8a5037c/regex-2026.6.28-cp312-cp312-win32.whl", hash = "sha256:03376d60b6a11aecb88a79fa2be06b40faa01c6693bc31ef69435cd4818b9463", size = 267109 }, - { url = "https://files.pythonhosted.org/packages/a0/59/bbbb0591f38b18c65977cd65ce64749eba1c1996c99ac04e900fc30c0dcb/regex-2026.6.28-cp312-cp312-win_amd64.whl", hash = "sha256:fbd2ded482bf99e6651992bbfcde460272724d4bbc49ef3d6b46d9312867ec84", size = 277711 }, - { url = "https://files.pythonhosted.org/packages/86/06/be4f6b337d773ae5739a1bc238f97c16926e72017243735853c030f4c628/regex-2026.6.28-cp312-cp312-win_arm64.whl", hash = "sha256:37294d3d7ddb64c7e89184b2894e0f8f0a19c514bc59513d71fe692c3a8d5fc6", size = 277022 }, - { url = "https://files.pythonhosted.org/packages/b6/53/d5c1b3cc0b5a0c985563ad6fac93d73ff2b300cb84342d89f044625d6bc7/regex-2026.6.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b295a83426e0e44e9e60fde99789e181bd26788a1890ae7fe2a24c69bb6246ca", size = 490329 }, - { url = "https://files.pythonhosted.org/packages/8d/9f/0c3503e819e91ca0e7a901a8e989ebf840ac7c7aea20b1fc7f31b6759f77/regex-2026.6.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c31665c0deb5c111557a1cac8c27bd5629e2f9e7fd5058900a03576c33b601c", size = 292039 }, - { url = "https://files.pythonhosted.org/packages/bb/7f/cd004e13fcad23b3794a82307dfd222e6365eb7f598bd3caab148a830bff/regex-2026.6.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6bf295f2c59de77d1ea7de053607ae4dc9ceb3d57bbb6c7ec51ef4acc4ccff94", size = 289488 }, - { url = "https://files.pythonhosted.org/packages/73/4c/293fb34586fbcdc47eac436069e9c11f71fae5dadfd4889b475d7d2e5f7a/regex-2026.6.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17c077586770f67e05bbffeba07fbee6b2b22244f4d4caf8d94e59d574befe04", size = 796772 }, - { url = "https://files.pythonhosted.org/packages/92/fa/c0cd1a90b7d12d9dc155cfc8bdea8df9720988ea5b07e8fa1eccbd0ab2dd/regex-2026.6.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e6cb5a61486f9062397d2e189573b39d38ecfaed698fd9fb6e2756a8ebb8762", size = 865467 }, - { url = "https://files.pythonhosted.org/packages/4e/db/0b479973046d005a1eaea299d5d536aeecb9488a16d9cbb8286338102e2d/regex-2026.6.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e86e91a2664f44c3a4e363a7d78fb17c27d5046882e30ea5a877f5e89b28d2ba", size = 912345 }, - { url = "https://files.pythonhosted.org/packages/5b/5b/d65adfbd02f32212431bca1f06d1e2eb763a20b12978b454bafaf23dacb7/regex-2026.6.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4dfd1331c49233998d84fc5f1f4436cf7a435a7655f6cf0f490229bb5c7254e5", size = 801291 }, - { url = "https://files.pythonhosted.org/packages/fc/09/2103686defaf9a0a31c1663782359d5b45f42524c64cca681f5481e44a5e/regex-2026.6.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cadea12805a1bce0b091c302b814207be26fb60a9c0e7f9ad2f9e21790a429fe", size = 777106 }, - { url = "https://files.pythonhosted.org/packages/85/5a/b57593c0aa23ed269ec332fbcf07852abcb6b746e811d9464e0d09b4e25f/regex-2026.6.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5f2c1682b67ad5d2376498f2a5a2a8f782fa2e4a06d0465b5e357799806e8a20", size = 785175 }, - { url = "https://files.pythonhosted.org/packages/79/59/c36e756ad29bf14d7b6c6d7138952476b21f6160286cedb98ac13481c993/regex-2026.6.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:64e142eb55e84868087da1375d7c36ff97d55010951849f515322a91d5fef1b4", size = 860186 }, - { url = "https://files.pythonhosted.org/packages/61/66/49808aea0da9649c300139360708fb91b7144be1f962fcebf96755fde948/regex-2026.6.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:abb4daabe7be63273787a62dfd6164dadf8f7a63fbec3d2730e5e5e7126d858c", size = 765754 }, - { url = "https://files.pythonhosted.org/packages/be/c5/52bbd436cf2200decdf48825fa38363eaaeebb77011ea9928a1ef9e0b9f2/regex-2026.6.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec2b2ad00ab8c16a2798cc8db80c53c4d5b8b3a2441f6cbaef06625f5ca25854", size = 852085 }, - { url = "https://files.pythonhosted.org/packages/f9/c3/0390b66e3019497143fe768b3ba567b64d8b24f3812d09506deb86f4a0f0/regex-2026.6.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bfc9677982c914d9085b8e1c3b3ae6e88f139fb56531c2416d6c8f338093c22b", size = 789600 }, - { url = "https://files.pythonhosted.org/packages/88/fd/ab5b03653a244975069fed93d73f4f5f7484c03a84cedb238292510d7182/regex-2026.6.28-cp313-cp313-win32.whl", hash = "sha256:bf54bc693fc4e0530e666ba5ec4bcba14dbe8f66b7cfc15c27317d1a6e40b9a5", size = 267088 }, - { url = "https://files.pythonhosted.org/packages/68/55/21022f7d3143210ae8d4ff905c45306237b657375cc0b97883f49db3d423/regex-2026.6.28-cp313-cp313-win_amd64.whl", hash = "sha256:e128feaf65bf3d9eb91bec92322a8f7e4835e9c798f3e9ea4b69f4def85620e3", size = 277680 }, - { url = "https://files.pythonhosted.org/packages/b6/99/7f664804f1aef924542b0b233996b78b3e4d0a52d9951358aac99f129f51/regex-2026.6.28-cp313-cp313-win_arm64.whl", hash = "sha256:695873e0ea8d3815ea9e92e2c68faf039cc450e2c0a62a31afe2049eb11be767", size = 277017 }, - { url = "https://files.pythonhosted.org/packages/cb/e1/9eb83518e159d719fd681c4932dc2aaff855ce72451e1d05d69466f25a96/regex-2026.6.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:189dbf9fc4252d9f1352bf4bd1bef885edb6cc4b7341df202a65f821aaa3891c", size = 494195 }, - { url = "https://files.pythonhosted.org/packages/fd/e2/e259c5f2f7be269d0e2fb54275c1fa6a13fb47019f389c3f3ae457447825/regex-2026.6.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9277a4c6503390aa39cb4483b87ec0384faee0850a23b5cea33d008b5d8d83f1", size = 293976 }, - { url = "https://files.pythonhosted.org/packages/8d/4e/9bdf444014d22b045d0c82ca114fac7e07a597b5b5331b7c4ce6328426e2/regex-2026.6.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17eddca4e8ea9af0b5739314776cdf0172a49731ab61f2e1ea66e066ddd46c97", size = 292340 }, - { url = "https://files.pythonhosted.org/packages/fd/3a/f49b11e59cbfe187ace0053a460bd72a0169b8cd52e7db9421a074ce7a43/regex-2026.6.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4466b8641e00c697aab5a73150150d2b2ea96b131c595691f42031abafd9f4d", size = 811704 }, - { url = "https://files.pythonhosted.org/packages/2f/fb/ad04c39e149bf8b6cf357df5fff78341733ec366780a00c803a36735818c/regex-2026.6.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9cfcd4b0bdcf768c498415c170d1ed2a25a99bf0b65fa253bbd02f68ceba6475", size = 871157 }, - { url = "https://files.pythonhosted.org/packages/7f/64/0e5ba31c11eb8ef7aac19a690c1211fc9aa9990caf09565785ebb0081b9a/regex-2026.6.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:80c7adf1ef647f6b1e8aa2ca280e517174cd08bdf7a2e412cdfb68bd6a0917cb", size = 917287 }, - { url = "https://files.pythonhosted.org/packages/11/75/6b78df2b858c2fcbbc4858fdc3f2975cf2703be374b2842db7d2c32591a7/regex-2026.6.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a043f5770e82283a22aed4cefef1a4e0f9dd8fd7184cb6ce0ad2e579e2134a9e", size = 816333 }, - { url = "https://files.pythonhosted.org/packages/b4/01/ecfe665a3694d5eda9f3ec686c856438ada0943947b6005e90556a1e2cdf/regex-2026.6.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3bd630a8dba06b55254ea5ee862194edab52ec783100d2ef1cd15a9c512fee27", size = 785518 }, - { url = "https://files.pythonhosted.org/packages/b4/0a/88f9cd88ff1e82881605c4ffd62d77ee67d051232cfe6f8e9a64b86cf0e8/regex-2026.6.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b77207e3cee13086f1906a6a2a12b41244c577e8ad9370d4b35ae1d548d354f3", size = 801371 }, - { url = "https://files.pythonhosted.org/packages/a8/97/601483732f93275482ceb9fed57813dfed7c47d3a019db6ec4a3bb6e23e0/regex-2026.6.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:6de82c268e5d101ee9e3ffd869924aa9a371e3a21e752cf4fa17b6ce50d219f7", size = 866517 }, - { url = "https://files.pythonhosted.org/packages/81/ed/385c2a0351b994a693453c1d1a6e9af9eb35db3c9460d76b5078acd70c62/regex-2026.6.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b15859e3908544fb99cf47341dcf0bfd089147d258c4c4d8a29e5b087f8085cb", size = 772834 }, - { url = "https://files.pythonhosted.org/packages/06/bc/bbf4a5b3b29770d7f307d3c28b5b1bca0105b0cb424be0a4eb1339bc92cf/regex-2026.6.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c91487a917edd48a1ea646fdf60d7936d304f0e686fa7ea8326e47efca51d816", size = 856606 }, - { url = "https://files.pythonhosted.org/packages/28/26/51d74fff82f682819979249f8d700267108ba5dc4eb284b0e11b9c85e4b3/regex-2026.6.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4ac65f3e3a99fd8f3a4a74e7a6610acd1ce9dfe9b8a03d346a4922380d68aeb", size = 803475 }, - { url = "https://files.pythonhosted.org/packages/7c/3e/6be10cefdc813533fe604dbf5d3c77d2638e7ee658b2749ebadc113b6b2e/regex-2026.6.28-cp313-cp313t-win32.whl", hash = "sha256:3f6316f258bc7e6c9c2acbe9954947bbd397a81be3742a637a555f1855d6618d", size = 269126 }, - { url = "https://files.pythonhosted.org/packages/3c/3c/32cda905ea1a6eeeb798291c294d8ec66ee0efe0cdba28b061e248b1d396/regex-2026.6.28-cp313-cp313t-win_amd64.whl", hash = "sha256:1484bdd6fba28422df9b5ebb04055b2e1b680e8e4f08490bb21ff0f3cc50d0ab", size = 279961 }, - { url = "https://files.pythonhosted.org/packages/ea/b9/69f4e5cd6fbe0bb420cb2dbae441ca118f2495bdda522a74da75aa9829e7/regex-2026.6.28-cp313-cp313t-win_arm64.whl", hash = "sha256:3f15020f0b69cafe57baa067ff65b29acef68ff6b1670a53bef1ca11d708e02d", size = 279266 }, - { url = "https://files.pythonhosted.org/packages/3b/fb/fad3b810a5bb1e09b9e5d6913fc6ba88cab738fdf283196827a3c59a4c10/regex-2026.6.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:f7c032b0c8a73739ff8ff1aaf30c281fa19c17bf7f1543256c8507390db7807c", size = 490407 }, - { url = "https://files.pythonhosted.org/packages/d6/52/b8c79d12276d93e90e707e939b396034c04980caf1235312ef790f8e11fc/regex-2026.6.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f6710f512c57b84f127a23d0f59560a03b64136eff419ae1be5ab557577fe5e3", size = 291988 }, - { url = "https://files.pythonhosted.org/packages/23/d2/6a911f18279daa8d7bb8b20d771ddb6ef31fabd35f5921f9d3ba21640e80/regex-2026.6.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c0013958f427bd82509a186b9ff206d66cb8d60a81fc797a4c717afd18c5b0ba", size = 289704 }, - { url = "https://files.pythonhosted.org/packages/fd/22/ad1955c47c669291a05804d53d7071cc0732dfdf166857be38003cedc2d1/regex-2026.6.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f06cdcd6421f8e194ad312ea608020381250df9b8a57661c1b57e9e5273878", size = 797017 }, - { url = "https://files.pythonhosted.org/packages/e5/67/a83159ff8703ab4d0c2cf99e76ebf289b7b4a501623241d09f88f3614f80/regex-2026.6.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec9689392f7494ff4e3f8e7e8522f9158f11023f337eaaf04a64542fc45bbf26", size = 866112 }, - { url = "https://files.pythonhosted.org/packages/b9/09/7bff2d6dbbd77421b3274aa51db1c887381cbc5b6eda93598c3e882ea345/regex-2026.6.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aa084684e6d2078bf6139e374d1fc2af5ddc1ac7122759a2db716d68169f6fd0", size = 911554 }, - { url = "https://files.pythonhosted.org/packages/29/44/ae59c3826e7ba492e56795cdf74ea2a7b5b7c5ea116afb79ee4956a5dff1/regex-2026.6.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:40455e6840dc4e96a6fe50f4cedc957de2752c954d91e789812be55d49be199a", size = 800665 }, - { url = "https://files.pythonhosted.org/packages/d6/19/6fd033d2ab00f35d445aaeaf3307c1e721424dcbfd48f6f65c857cb939cf/regex-2026.6.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:530b5c223b9ca5dd8370ac502e080aee0e4ded32be987c6564b425fb5523d581", size = 777243 }, - { url = "https://files.pythonhosted.org/packages/4e/9d/99730f26df4938049ab1e652ca75e967b4c6739444e18d9707bfdb8af20c/regex-2026.6.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e0ed273ecd1a89be84466c1749bfe58609cc2a32b5d5e05006c4625ba96411b", size = 785784 }, - { url = "https://files.pythonhosted.org/packages/48/49/105cd57162f5fc5c04cc917a1388a060cf8427e5c14353cd9044660fbf4d/regex-2026.6.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0ab0d5344311fc8e8667078942056c3b9c9b4a4b1cc99f2eb8a5af54554f4acc", size = 860914 }, - { url = "https://files.pythonhosted.org/packages/a2/a5/788245a95b69018f58bff2f4fd27d007cacaea088cdb390979743f1b2571/regex-2026.6.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:eacb79625323d9f7e7925366b917f492b8356fad58f5dc4fa12ff8c21d8f4ca9", size = 765915 }, - { url = "https://files.pythonhosted.org/packages/ca/01/292065a39a004b05e67a337b18213670a7cb919d6856ac2d7df7f1a10dbb/regex-2026.6.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:20f4d87702702aa1d572721e146f301660c50eef6fd6cb596e48a22b0ace17db", size = 851404 }, - { url = "https://files.pythonhosted.org/packages/98/9e/a93d865db0e13483ae1a01d81e2ce16d4a7fe2f9b9fe4aac4cc08590b136/regex-2026.6.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e693940a3b9e6d6e4dc2a54ecaa74b74934f77af1ef95f518a74261ef7cc1bc", size = 789373 }, - { url = "https://files.pythonhosted.org/packages/82/0c/38b1685ad4017d78efbc8fa7dbbf96d8113b53750c8aa2d3609defd46605/regex-2026.6.28-cp314-cp314-win32.whl", hash = "sha256:234a51e20ebc18ab83b2c0600cf28f2e884560a0e00f743878f0b7d8e7c4cf03", size = 272496 }, - { url = "https://files.pythonhosted.org/packages/55/50/e19f261ff9ba9b50722a529e09b1743ecf65eb348be99d0fd2cd7fcede1c/regex-2026.6.28-cp314-cp314-win_amd64.whl", hash = "sha256:7b15c437bc4604f03ceb3f8d37eae2f8930e320e1bc556b259848c639d9eec1a", size = 280754 }, - { url = "https://files.pythonhosted.org/packages/36/b8/c9e68f3a9e33be73f20990b2c065b144ff2d0aa242608a950d8c4f3b56e8/regex-2026.6.28-cp314-cp314-win_arm64.whl", hash = "sha256:c6e6f790d01380a74ad564f216c533b86504afb61bf66f2b2e11e7f1a3e287a7", size = 280979 }, - { url = "https://files.pythonhosted.org/packages/03/e6/21c425a37880c650d007c4171c6a80325446d830d85f5fbf335e7205b1e7/regex-2026.6.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3527a72adcbe9e3600f1553b497d397c1a371d227580d41d96c3c5964109b65c", size = 494282 }, - { url = "https://files.pythonhosted.org/packages/07/50/6647a7ccf5ffff995ba955a0b7d766440f4e58ce1666549c8ee998f2b972/regex-2026.6.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a644f6408692812f5ead82519eed680e08d5d546fddbd9f7d9514e3c73899aa5", size = 293977 }, - { url = "https://files.pythonhosted.org/packages/8c/dc/a3e141a4eaf125e50f63105570c01fa477c06ac5259dcfa95e9b90760e84/regex-2026.6.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8e2fae6bb883648346f84db270dc9aafc29d8e895f62b88a75ccc83b09519820", size = 292432 }, - { url = "https://files.pythonhosted.org/packages/35/ee/2ac1a6b9f167f8ff69f5a789938cc103b60cff41b24a6990daced8b88e34/regex-2026.6.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:debe623e09cee97ef9404575e936c610aac9bb08358c5099aaef14644a6871f2", size = 811877 }, - { url = "https://files.pythonhosted.org/packages/df/7b/9a5505ee92180bcae300b1018b9ff3d3c19962436e66f2505f255e9fde35/regex-2026.6.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc579c91fb4605773483a8d940b136bcc5b854fff44fa14a1572a038f46563f1", size = 871212 }, - { url = "https://files.pythonhosted.org/packages/24/4d/d61a702a9f9d1bd29b22cbef1aed6d477baa961232a7eb4d91b7775b0b3e/regex-2026.6.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7c42be203d84ecf7d487ff23f8a61ef0eb0534fa0fc317a2fce8c065d20618f", size = 917507 }, - { url = "https://files.pythonhosted.org/packages/d4/60/1308066f5966b65fbb6905b99ba37e9f1cd753dd0ac08485f8257334ee92/regex-2026.6.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8184b4e2fdaf9cdfe77e38f15a4d9dc149168c9c29eb0ea17c5481d3bb80546", size = 816389 }, - { url = "https://files.pythonhosted.org/packages/bd/5c/57ce2cb8d714ee0b7f11c7ee4cfe2af66df2b90f147feadcb538609a3a02/regex-2026.6.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:697f103104f5872d64078d8eeac59979960be8ee76115a2d3f31096312e2a400", size = 785890 }, - { url = "https://files.pythonhosted.org/packages/ff/fd/1d5350d3a8a327bff0fccacb911732baf7b5b6f5529c0e3fa602a23e7dad/regex-2026.6.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:714d2b1aa29beef0ddfcdc72ad0771c05326551a8bb0680b0ddf74bfaad87387", size = 801451 }, - { url = "https://files.pythonhosted.org/packages/f3/79/3c9e4f8a0306e030ad5a43bbbc01625fb28d58a813bc52d42fd1cc63fb2e/regex-2026.6.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0f09f62e450cc2f113018cc8412aeea3a120a04e1ca7e801a0d441583f9a3b06", size = 866504 }, - { url = "https://files.pythonhosted.org/packages/65/12/f747de475b54f4709efb24dd0fbc8467c64cec91f5db0d047b079646ee78/regex-2026.6.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:731ea12d5aeb2577eaef2393d6428b995f76eb35f68a89e03e15a97719d1de19", size = 773047 }, - { url = "https://files.pythonhosted.org/packages/58/3c/f02f860e0500c1b2d61a79dec7e214b37fb9656281dcddc92397edf96678/regex-2026.6.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:51e952c8783eabd4706d0f63922f219bcfc1bef9b8cb35941c0d1a0396578858", size = 856665 }, - { url = "https://files.pythonhosted.org/packages/4d/6c/28b3fa222513484be9dee26b7222bda109056c43ea28aa2314262ca48816/regex-2026.6.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43248fe4c0ab8fbb223588a0795b11268940072c97bba30ea8f9b49d8cdfde34", size = 803573 }, - { url = "https://files.pythonhosted.org/packages/fa/f0/8f86cf1a1fd85c5ab0c503c9fe4607ad4ad48978b2d8b435d94465e134c7/regex-2026.6.28-cp314-cp314t-win32.whl", hash = "sha256:fc1eddc25ad23c0f1344ab280d961ac595ead48292d7c779497975942373f493", size = 274515 }, - { url = "https://files.pythonhosted.org/packages/0f/de/f8613c03b36786ddef2c930d28f9bcae861fcd541cc9203a870956cf1e83/regex-2026.6.28-cp314-cp314t-win_amd64.whl", hash = "sha256:ede8d8e53b6dde0a50f7eca902f0af76d87ab02a55aba7542da68ae3e5dfe83d", size = 283650 }, - { url = "https://files.pythonhosted.org/packages/4d/f3/f5ec86839bbabe33b6dee649b62ff9a445d43de6b0ad780cf6b83c56f61e/regex-2026.6.28-cp314-cp314t-win_arm64.whl", hash = "sha256:4da6f6a72f8700b97a1a765e837fb7d5750bfd9f13acea7bae498f573e3a70a8", size = 283338 }, + { url = "https://files.pythonhosted.org/packages/d8/dc/f7a8c9cf0768f704153d358fae2bc883199bc4ea1e4aa458f1be9d0ef2ce/regex-2026.6.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b83932645630965fd860fdb70ebbf964bf3e8007f08851ea424d01f8d35454a8", size = 489471, upload-time = "2026-06-28T19:53:06.385Z" }, + { url = "https://files.pythonhosted.org/packages/44/b3/9786a4a2133e2f1cc5897ed3d2da3da29ff54b775ffa38bc5935fc24be82/regex-2026.6.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e81f1952355042e517dc9861ce65c676e4a098f42402993c40461786d1f794d4", size = 291294, upload-time = "2026-06-28T19:53:09.232Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1f/bfe5b529257f0853aa6b94146e0f6462f4d45aa4f3c05d5a828f415dfd40/regex-2026.6.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2097591101d70bcc108af64c46f6066bb698ee067fec5f75beac0be317639311", size = 289216, upload-time = "2026-06-28T19:53:10.682Z" }, + { url = "https://files.pythonhosted.org/packages/25/56/f615165e90ac5f3b72b249240643439520bbac0ac60a9de06868528eba4c/regex-2026.6.28-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:31d7538a614b5842bf53ce329d07b43f97754ca7e6db8d69f347e071bce1c953", size = 784787, upload-time = "2026-06-28T19:53:12.393Z" }, + { url = "https://files.pythonhosted.org/packages/04/94/c9e3ad31b3d5fbe1228fee8319e0c02a5460296624f220d08764547fe6ae/regex-2026.6.28-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5561e47bbe2b75373b695326507743fcdd4d2cc7f5022312024ccf39fa094e0", size = 852137, upload-time = "2026-06-28T19:53:14.287Z" }, + { url = "https://files.pythonhosted.org/packages/c0/77/d506a428e446466ee298f5425a774737d0671d070425ed794bb3314d60c6/regex-2026.6.28-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c10f2c5a55ab3dd8318d8ad5f11b530e2691c0edebebde7713066f484902c3fb", size = 899525, upload-time = "2026-06-28T19:53:15.987Z" }, + { url = "https://files.pythonhosted.org/packages/aa/72/becc00d839f19401f10a20168b44711c7b02f7f62bba875b2d8f98417435/regex-2026.6.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23f7e0cc60c72486b42a685f1ff4eec90d50d4fb05e4f9c7d5363b03aa02600d", size = 794116, upload-time = "2026-06-28T19:53:17.372Z" }, + { url = "https://files.pythonhosted.org/packages/fa/11/ea2ca423eeaac2e18077a18b058614e9201f130750df2126d444e39acab2/regex-2026.6.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:76493755f79a88d5ed2c9e63a41d3c05997e0a7ffbe76ed8c4ded8be35b8b14c", size = 786257, upload-time = "2026-06-28T19:53:18.712Z" }, + { url = "https://files.pythonhosted.org/packages/6d/9e/f5bf7ecbd14ff2086f015c54dc24fd0d74ba5327fef0de479213f8128615/regex-2026.6.28-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ff0f41a00f23ea5054acb61901380c41813d813eee3f80f800995710bcc52ecd", size = 769914, upload-time = "2026-06-28T19:53:20.564Z" }, + { url = "https://files.pythonhosted.org/packages/43/04/f9040a5360a06241ba5b7f2e6f1c6184e104a84e6f6522535700e94bf8e2/regex-2026.6.28-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3c60b297292e7e1ef5d02a4759f9e452ee4c8bb95e168d8fd0b5db01bd806f9f", size = 775013, upload-time = "2026-06-28T19:53:22.067Z" }, + { url = "https://files.pythonhosted.org/packages/73/97/4e46f7abf2f864319d2bcac609af3c0532968c66a3364337778fd232b83c/regex-2026.6.28-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a7cf03c87f7b9cbc25a8894cf9be83818406677b6b391b003ec7c884923387b5", size = 848814, upload-time = "2026-06-28T19:53:24.575Z" }, + { url = "https://files.pythonhosted.org/packages/f7/b8/3d1f995727799a1e2e693e397acb7358094606e5591b6b5fd3128d2d1409/regex-2026.6.28-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:418208ea0af51cfed4f46eb9b1ea7cfc990ca284f0084ecbd951460fb089421e", size = 757702, upload-time = "2026-06-28T19:53:26.215Z" }, + { url = "https://files.pythonhosted.org/packages/20/10/fd5653b8572910a4fe9055f8959b070d7d9443c94ce986529fcdb5fb2a3c/regex-2026.6.28-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:7635fa2cddb917a6bbfac7890602573d2d8c4e470703b0640e6f86a988817ec3", size = 837140, upload-time = "2026-06-28T19:53:27.655Z" }, + { url = "https://files.pythonhosted.org/packages/5d/31/da77e3ef7b594a2aacbd03ce3d0050f33ab3e021df50c6901467c9006511/regex-2026.6.28-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7bb96c13d6cf5880d31bbef84ca701a64d738aa491c2b79975cc33f8ad00a31e", size = 782105, upload-time = "2026-06-28T19:53:29.375Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4d/c379001448d0f58b6946f168d4af96ad60a16c1553259c27b0df8701b640/regex-2026.6.28-cp310-cp310-win32.whl", hash = "sha256:56f05194c4843957dd8b3af87eb0c52d8cf0509e7f18e172d727f5f8ff840646", size = 266728, upload-time = "2026-06-28T19:53:31.813Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8f/cb656529efa87d74cce0d69e606c745537016da3bdfae78f342af2242ee3/regex-2026.6.28-cp310-cp310-win_amd64.whl", hash = "sha256:70710927033af3b54369f17aaba1343b97a23d0b1aa994fa1512b08b1b8c136a", size = 277901, upload-time = "2026-06-28T19:53:33.293Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ac/d35ccc309c9409406445ab2ef0b56f6a341a916ccff49ff9ac5cc6bb8e9b/regex-2026.6.28-cp310-cp310-win_arm64.whl", hash = "sha256:ed7b30185ee3f8b9b053b0be567b4d226016e2afbebc17fde1c6a4580937b688", size = 276880, upload-time = "2026-06-28T19:53:35.029Z" }, + { url = "https://files.pythonhosted.org/packages/72/db/9051b36294bdbabaa9c7db57db0fbcdfbd17f7a106c539bb423d0323faea/regex-2026.6.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a71b51dd08b9b62f055fafab3dee8af8bd2ec81b373a44caef18d6c5ca28f43a", size = 489481, upload-time = "2026-06-28T19:53:36.684Z" }, + { url = "https://files.pythonhosted.org/packages/35/3f/24097a3c3ff30f9a639888900faaecabcf5f54a5bc9c851c297e11b349ef/regex-2026.6.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9c26a47770d30a0f85c01e261d2a3ebc342c4af6fd666dbd8c1fe4cbf3adf726", size = 291292, upload-time = "2026-06-28T19:53:38.39Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cc/e0d762a189cfb4e8926d16e691720690d139a977b38fdb80230c259332ab/regex-2026.6.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5efbc1af38f97e300d43028e5a92e752d924bcfb7f465d8669d5d5a6e78c233", size = 289232, upload-time = "2026-06-28T19:53:40.181Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c8/ca0ac7f09cc88ca61e0c61c53f7db29334f660ffba5d0b52378e7c44723c/regex-2026.6.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1758df6fdd8c800620a5638958720e8a635e1da49a2f09df2dd63e94a24ec4a", size = 792332, upload-time = "2026-06-28T19:53:41.782Z" }, + { url = "https://files.pythonhosted.org/packages/8e/92/04ae94cbe0dd1f478b2aef6c46f995bb6946d3e338d4b28605478b66a2b7/regex-2026.6.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ad73ecf20c1ef5c975639f8bf845a9370fcf7dada7edc1e3b0bca20e2f8202f6", size = 861743, upload-time = "2026-06-28T19:53:43.261Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ec/024d7638c807679ff8a0e6081d01d66c7762339af1cac71e45911587ff9a/regex-2026.6.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d80c798b0eec6ea3d45f8816a1e8886c5664615d347d89e8c075b576a1b5a5d", size = 906481, upload-time = "2026-06-28T19:53:44.948Z" }, + { url = "https://files.pythonhosted.org/packages/cd/fd/93bfe5af45f0be4fa8983945455c0e6924e1aeb879cde227958869c1e71c/regex-2026.6.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a361feeaf1b6ba1df060f2ff5c5947092edf537a35ce78e76387ac56d3e0f4a4", size = 799867, upload-time = "2026-06-28T19:53:46.997Z" }, + { url = "https://files.pythonhosted.org/packages/ee/fd/e5d965d41f2398c8ce0f37a4652f03bb297fd009bb796d390134225dda12/regex-2026.6.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8b92366d9c8bba9642989534073662abdd9b41faf7603a7ae71597833f3b88f0", size = 773632, upload-time = "2026-06-28T19:53:48.892Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d9/ff39afaec92b9ee2dba0302a4783976005091681069808938c31cf8df3b6/regex-2026.6.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:11251768cc23f097dd61b18f67966e70f74da822784d17e12a444eb6b29d4288", size = 781669, upload-time = "2026-06-28T19:53:50.693Z" }, + { url = "https://files.pythonhosted.org/packages/45/4e/e2fd4bb8228e10c24af2d7ff867182372190e498eab9fd29cbe54c403c95/regex-2026.6.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad5c67786145ec28a71a267d9f9d92bdc8d70d65541eea852c253f520a01f918", size = 854497, upload-time = "2026-06-28T19:53:52.323Z" }, + { url = "https://files.pythonhosted.org/packages/72/7c/f0340384a973082979064156d05f3d2cc1dced7371efcd7a1b45726a1a8a/regex-2026.6.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f1da438e739765c3e85175ede05816cbede3caaacb1e0680568bda6119bfdfca", size = 763335, upload-time = "2026-06-28T19:53:54.024Z" }, + { url = "https://files.pythonhosted.org/packages/e1/32/90ce0d0898e205506cc22b9c81cfb16b722e06ca5f50fad51c053c2a727b/regex-2026.6.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d98b639046e51c5de64d9f77351532105e99ca271cb6f7640e1f903d6ab63032", size = 844615, upload-time = "2026-06-28T19:53:56.216Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ef/55abb149599dce1ade687170557129524011eeb3d92afe02429cea7754a2/regex-2026.6.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e164ace4dbab5c6ad4a4ac7c41a2638fe226d0c770a86f2eb041f594bac6ee7", size = 789193, upload-time = "2026-06-28T19:53:57.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ea/cf7f6f6f152e52fdad978b913bf24c14df647eca0f81ef31f3aee0be8982/regex-2026.6.28-cp311-cp311-win32.whl", hash = "sha256:3169a3159e4d99d9ae85ff0ed90ef3b8906cc3152653b6078b842ace6c8f72c3", size = 266731, upload-time = "2026-06-28T19:53:59.938Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cf/a48d8e8d406b22481cad146f48fa0dfca3c5f402b91f26d8e5a0fe4f513d/regex-2026.6.28-cp311-cp311-win_amd64.whl", hash = "sha256:5977295b0a74e8241df8a4b3b27b12412a831f6fa32ee8b755039592cd768c3d", size = 277918, upload-time = "2026-06-28T19:54:01.502Z" }, + { url = "https://files.pythonhosted.org/packages/89/b2/a222392207db7ed86281a732a99f7cf7f2bb35d332799e892b8510be000e/regex-2026.6.28-cp311-cp311-win_arm64.whl", hash = "sha256:f5fbaef40c3e9282ccee4b075f5600a0d858aa0c34147732f1baa69c8188a95d", size = 276876, upload-time = "2026-06-28T19:54:03.411Z" }, + { url = "https://files.pythonhosted.org/packages/da/21/44aa415873032056c43eac21c67285deb2cf66cddb2a964c3cdc8f803efc/regex-2026.6.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:81cc5793ad33a10444445e8d29d3c73e752c8fb2e120772d70fcb6d41df40fe1", size = 490480, upload-time = "2026-06-28T19:54:05.392Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5f/30d4116093c2128099f78b6990dfc1698fdbf3ee528f1e1c647378034c79/regex-2026.6.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e18225243250a1f7d7e5e5d883f3b96465cd79031acf5c6db902b7025f2125d9", size = 292137, upload-time = "2026-06-28T19:54:07.088Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/ca20a0e0de49837e6337603a91ab77556aa27033ac5b975615d98698cfb3/regex-2026.6.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ecd1638b1c2db1f2d01c182a4b0d3e2e88b0e99910320a745c1727ee3638ddab", size = 289623, upload-time = "2026-06-28T19:54:08.762Z" }, + { url = "https://files.pythonhosted.org/packages/50/11/c013422a7e2c59946df8ac93e792a4922c98287f2a2181341603c78a5d98/regex-2026.6.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4303ebe16b74eeb3fe2715745023266fea92fd44a23f3e7bb2fb48c7a7bbc195", size = 796756, upload-time = "2026-06-28T19:54:10.616Z" }, + { url = "https://files.pythonhosted.org/packages/b0/95/1309645a0e1ee6fb91d954501da57a0b33d50ad2a9acb313702851a7054e/regex-2026.6.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56b856b70b96c381d837f609eee442a1bd320cd2159f5c294b679552fb1a7eaf", size = 865465, upload-time = "2026-06-28T19:54:12.742Z" }, + { url = "https://files.pythonhosted.org/packages/20/06/491802db47c6f5e2904ffa2518ad3ac27fe6bbf5a66d73210a95cc080d47/regex-2026.6.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f74675ab76ab1d005ffba4dee308e53e89efc22be6e9f9fae5b539a3f81bdff2", size = 912350, upload-time = "2026-06-28T19:54:14.508Z" }, + { url = "https://files.pythonhosted.org/packages/5e/60/3ba57840bcc7e2367090360de0c15a5ba6ad22be89314251105f2e943f43/regex-2026.6.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90581684565a93f7258af1e5d3f41ef20d7d7c61f2a428183a342bcb65485e38", size = 801261, upload-time = "2026-06-28T19:54:16.432Z" }, + { url = "https://files.pythonhosted.org/packages/eb/27/af1eb74e9a78c782b3e450b611a595e44906da8a5107e1227f4a7fd0480b/regex-2026.6.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:28f9e6c28f9b90f6f784595a33240a57e181e61b6ee3dc259b25c61e356d1aa3", size = 777072, upload-time = "2026-06-28T19:54:18.128Z" }, + { url = "https://files.pythonhosted.org/packages/20/18/fdd4c883a39e3ed00d669062af1135809bfd3281bf528150849fbd68825b/regex-2026.6.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:378a71d861fc7c8806b04ac5b133d53c0e774f92f5d9663a539872d3fa2b0417", size = 785119, upload-time = "2026-06-28T19:54:20.314Z" }, + { url = "https://files.pythonhosted.org/packages/1c/79/0aabe34b8482dcadf64355f70f96e22eba5ec6c1efb33563f89654f4061c/regex-2026.6.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4cc199874ecd6267a49b111052250825bfe19b5101b23b2ba80f54efa3e0994e", size = 860118, upload-time = "2026-06-28T19:54:22.368Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2c/c973323306a27c9db7d160e9584eb7e0ece2a96224ccb0d39060558b31f9/regex-2026.6.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b916a10431494ef4b4d62c6c89cab6426af7873125b8cd6c15811bf5fc58eec8", size = 765786, upload-time = "2026-06-28T19:54:24.265Z" }, + { url = "https://files.pythonhosted.org/packages/e3/df/9ca3e378e352242a4cb45573a5e9162c3ee791507702a23966fa559e36b5/regex-2026.6.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e27727fba075f1e4409416d2f537d4c30fc11f012ea507f7bd74d3e19ecb57a", size = 852120, upload-time = "2026-06-28T19:54:25.972Z" }, + { url = "https://files.pythonhosted.org/packages/a2/3e/3e31e255c4971f53cbce6306b5e3c76cbd3735a54f419bb3b2f194e9f68c/regex-2026.6.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:700fc6a7844bb2c4149292ac79d1df8841a00acd4d45cd32c1ebc7bcc1fd0da8", size = 789503, upload-time = "2026-06-28T19:54:27.678Z" }, + { url = "https://files.pythonhosted.org/packages/72/01/d36561c21c3033d7eeb31d51b491916817de7861acefccc5fc9db8a5037c/regex-2026.6.28-cp312-cp312-win32.whl", hash = "sha256:03376d60b6a11aecb88a79fa2be06b40faa01c6693bc31ef69435cd4818b9463", size = 267109, upload-time = "2026-06-28T19:54:29.316Z" }, + { url = "https://files.pythonhosted.org/packages/a0/59/bbbb0591f38b18c65977cd65ce64749eba1c1996c99ac04e900fc30c0dcb/regex-2026.6.28-cp312-cp312-win_amd64.whl", hash = "sha256:fbd2ded482bf99e6651992bbfcde460272724d4bbc49ef3d6b46d9312867ec84", size = 277711, upload-time = "2026-06-28T19:54:31.143Z" }, + { url = "https://files.pythonhosted.org/packages/86/06/be4f6b337d773ae5739a1bc238f97c16926e72017243735853c030f4c628/regex-2026.6.28-cp312-cp312-win_arm64.whl", hash = "sha256:37294d3d7ddb64c7e89184b2894e0f8f0a19c514bc59513d71fe692c3a8d5fc6", size = 277022, upload-time = "2026-06-28T19:54:32.97Z" }, + { url = "https://files.pythonhosted.org/packages/b6/53/d5c1b3cc0b5a0c985563ad6fac93d73ff2b300cb84342d89f044625d6bc7/regex-2026.6.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b295a83426e0e44e9e60fde99789e181bd26788a1890ae7fe2a24c69bb6246ca", size = 490329, upload-time = "2026-06-28T19:54:35.775Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9f/0c3503e819e91ca0e7a901a8e989ebf840ac7c7aea20b1fc7f31b6759f77/regex-2026.6.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c31665c0deb5c111557a1cac8c27bd5629e2f9e7fd5058900a03576c33b601c", size = 292039, upload-time = "2026-06-28T19:54:37.977Z" }, + { url = "https://files.pythonhosted.org/packages/bb/7f/cd004e13fcad23b3794a82307dfd222e6365eb7f598bd3caab148a830bff/regex-2026.6.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6bf295f2c59de77d1ea7de053607ae4dc9ceb3d57bbb6c7ec51ef4acc4ccff94", size = 289488, upload-time = "2026-06-28T19:54:39.545Z" }, + { url = "https://files.pythonhosted.org/packages/73/4c/293fb34586fbcdc47eac436069e9c11f71fae5dadfd4889b475d7d2e5f7a/regex-2026.6.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17c077586770f67e05bbffeba07fbee6b2b22244f4d4caf8d94e59d574befe04", size = 796772, upload-time = "2026-06-28T19:54:41.347Z" }, + { url = "https://files.pythonhosted.org/packages/92/fa/c0cd1a90b7d12d9dc155cfc8bdea8df9720988ea5b07e8fa1eccbd0ab2dd/regex-2026.6.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e6cb5a61486f9062397d2e189573b39d38ecfaed698fd9fb6e2756a8ebb8762", size = 865467, upload-time = "2026-06-28T19:54:43.485Z" }, + { url = "https://files.pythonhosted.org/packages/4e/db/0b479973046d005a1eaea299d5d536aeecb9488a16d9cbb8286338102e2d/regex-2026.6.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e86e91a2664f44c3a4e363a7d78fb17c27d5046882e30ea5a877f5e89b28d2ba", size = 912345, upload-time = "2026-06-28T19:54:46.091Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5b/d65adfbd02f32212431bca1f06d1e2eb763a20b12978b454bafaf23dacb7/regex-2026.6.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4dfd1331c49233998d84fc5f1f4436cf7a435a7655f6cf0f490229bb5c7254e5", size = 801291, upload-time = "2026-06-28T19:54:48.3Z" }, + { url = "https://files.pythonhosted.org/packages/fc/09/2103686defaf9a0a31c1663782359d5b45f42524c64cca681f5481e44a5e/regex-2026.6.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cadea12805a1bce0b091c302b814207be26fb60a9c0e7f9ad2f9e21790a429fe", size = 777106, upload-time = "2026-06-28T19:54:50.326Z" }, + { url = "https://files.pythonhosted.org/packages/85/5a/b57593c0aa23ed269ec332fbcf07852abcb6b746e811d9464e0d09b4e25f/regex-2026.6.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5f2c1682b67ad5d2376498f2a5a2a8f782fa2e4a06d0465b5e357799806e8a20", size = 785175, upload-time = "2026-06-28T19:54:52.172Z" }, + { url = "https://files.pythonhosted.org/packages/79/59/c36e756ad29bf14d7b6c6d7138952476b21f6160286cedb98ac13481c993/regex-2026.6.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:64e142eb55e84868087da1375d7c36ff97d55010951849f515322a91d5fef1b4", size = 860186, upload-time = "2026-06-28T19:54:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/61/66/49808aea0da9649c300139360708fb91b7144be1f962fcebf96755fde948/regex-2026.6.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:abb4daabe7be63273787a62dfd6164dadf8f7a63fbec3d2730e5e5e7126d858c", size = 765754, upload-time = "2026-06-28T19:54:56.04Z" }, + { url = "https://files.pythonhosted.org/packages/be/c5/52bbd436cf2200decdf48825fa38363eaaeebb77011ea9928a1ef9e0b9f2/regex-2026.6.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec2b2ad00ab8c16a2798cc8db80c53c4d5b8b3a2441f6cbaef06625f5ca25854", size = 852085, upload-time = "2026-06-28T19:54:57.988Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c3/0390b66e3019497143fe768b3ba567b64d8b24f3812d09506deb86f4a0f0/regex-2026.6.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bfc9677982c914d9085b8e1c3b3ae6e88f139fb56531c2416d6c8f338093c22b", size = 789600, upload-time = "2026-06-28T19:54:59.977Z" }, + { url = "https://files.pythonhosted.org/packages/88/fd/ab5b03653a244975069fed93d73f4f5f7484c03a84cedb238292510d7182/regex-2026.6.28-cp313-cp313-win32.whl", hash = "sha256:bf54bc693fc4e0530e666ba5ec4bcba14dbe8f66b7cfc15c27317d1a6e40b9a5", size = 267088, upload-time = "2026-06-28T19:55:02.159Z" }, + { url = "https://files.pythonhosted.org/packages/68/55/21022f7d3143210ae8d4ff905c45306237b657375cc0b97883f49db3d423/regex-2026.6.28-cp313-cp313-win_amd64.whl", hash = "sha256:e128feaf65bf3d9eb91bec92322a8f7e4835e9c798f3e9ea4b69f4def85620e3", size = 277680, upload-time = "2026-06-28T19:55:04.185Z" }, + { url = "https://files.pythonhosted.org/packages/b6/99/7f664804f1aef924542b0b233996b78b3e4d0a52d9951358aac99f129f51/regex-2026.6.28-cp313-cp313-win_arm64.whl", hash = "sha256:695873e0ea8d3815ea9e92e2c68faf039cc450e2c0a62a31afe2049eb11be767", size = 277017, upload-time = "2026-06-28T19:55:06.29Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e1/9eb83518e159d719fd681c4932dc2aaff855ce72451e1d05d69466f25a96/regex-2026.6.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:189dbf9fc4252d9f1352bf4bd1bef885edb6cc4b7341df202a65f821aaa3891c", size = 494195, upload-time = "2026-06-28T19:55:08.292Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e2/e259c5f2f7be269d0e2fb54275c1fa6a13fb47019f389c3f3ae457447825/regex-2026.6.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9277a4c6503390aa39cb4483b87ec0384faee0850a23b5cea33d008b5d8d83f1", size = 293976, upload-time = "2026-06-28T19:55:10.014Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4e/9bdf444014d22b045d0c82ca114fac7e07a597b5b5331b7c4ce6328426e2/regex-2026.6.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17eddca4e8ea9af0b5739314776cdf0172a49731ab61f2e1ea66e066ddd46c97", size = 292340, upload-time = "2026-06-28T19:55:11.88Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3a/f49b11e59cbfe187ace0053a460bd72a0169b8cd52e7db9421a074ce7a43/regex-2026.6.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4466b8641e00c697aab5a73150150d2b2ea96b131c595691f42031abafd9f4d", size = 811704, upload-time = "2026-06-28T19:55:13.612Z" }, + { url = "https://files.pythonhosted.org/packages/2f/fb/ad04c39e149bf8b6cf357df5fff78341733ec366780a00c803a36735818c/regex-2026.6.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9cfcd4b0bdcf768c498415c170d1ed2a25a99bf0b65fa253bbd02f68ceba6475", size = 871157, upload-time = "2026-06-28T19:55:15.797Z" }, + { url = "https://files.pythonhosted.org/packages/7f/64/0e5ba31c11eb8ef7aac19a690c1211fc9aa9990caf09565785ebb0081b9a/regex-2026.6.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:80c7adf1ef647f6b1e8aa2ca280e517174cd08bdf7a2e412cdfb68bd6a0917cb", size = 917287, upload-time = "2026-06-28T19:55:18.692Z" }, + { url = "https://files.pythonhosted.org/packages/11/75/6b78df2b858c2fcbbc4858fdc3f2975cf2703be374b2842db7d2c32591a7/regex-2026.6.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a043f5770e82283a22aed4cefef1a4e0f9dd8fd7184cb6ce0ad2e579e2134a9e", size = 816333, upload-time = "2026-06-28T19:55:20.973Z" }, + { url = "https://files.pythonhosted.org/packages/b4/01/ecfe665a3694d5eda9f3ec686c856438ada0943947b6005e90556a1e2cdf/regex-2026.6.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3bd630a8dba06b55254ea5ee862194edab52ec783100d2ef1cd15a9c512fee27", size = 785518, upload-time = "2026-06-28T19:55:23.003Z" }, + { url = "https://files.pythonhosted.org/packages/b4/0a/88f9cd88ff1e82881605c4ffd62d77ee67d051232cfe6f8e9a64b86cf0e8/regex-2026.6.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b77207e3cee13086f1906a6a2a12b41244c577e8ad9370d4b35ae1d548d354f3", size = 801371, upload-time = "2026-06-28T19:55:24.888Z" }, + { url = "https://files.pythonhosted.org/packages/a8/97/601483732f93275482ceb9fed57813dfed7c47d3a019db6ec4a3bb6e23e0/regex-2026.6.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:6de82c268e5d101ee9e3ffd869924aa9a371e3a21e752cf4fa17b6ce50d219f7", size = 866517, upload-time = "2026-06-28T19:55:27.232Z" }, + { url = "https://files.pythonhosted.org/packages/81/ed/385c2a0351b994a693453c1d1a6e9af9eb35db3c9460d76b5078acd70c62/regex-2026.6.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b15859e3908544fb99cf47341dcf0bfd089147d258c4c4d8a29e5b087f8085cb", size = 772834, upload-time = "2026-06-28T19:55:29.154Z" }, + { url = "https://files.pythonhosted.org/packages/06/bc/bbf4a5b3b29770d7f307d3c28b5b1bca0105b0cb424be0a4eb1339bc92cf/regex-2026.6.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c91487a917edd48a1ea646fdf60d7936d304f0e686fa7ea8326e47efca51d816", size = 856606, upload-time = "2026-06-28T19:55:32.186Z" }, + { url = "https://files.pythonhosted.org/packages/28/26/51d74fff82f682819979249f8d700267108ba5dc4eb284b0e11b9c85e4b3/regex-2026.6.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4ac65f3e3a99fd8f3a4a74e7a6610acd1ce9dfe9b8a03d346a4922380d68aeb", size = 803475, upload-time = "2026-06-28T19:55:34.328Z" }, + { url = "https://files.pythonhosted.org/packages/7c/3e/6be10cefdc813533fe604dbf5d3c77d2638e7ee658b2749ebadc113b6b2e/regex-2026.6.28-cp313-cp313t-win32.whl", hash = "sha256:3f6316f258bc7e6c9c2acbe9954947bbd397a81be3742a637a555f1855d6618d", size = 269126, upload-time = "2026-06-28T19:55:36.565Z" }, + { url = "https://files.pythonhosted.org/packages/3c/3c/32cda905ea1a6eeeb798291c294d8ec66ee0efe0cdba28b061e248b1d396/regex-2026.6.28-cp313-cp313t-win_amd64.whl", hash = "sha256:1484bdd6fba28422df9b5ebb04055b2e1b680e8e4f08490bb21ff0f3cc50d0ab", size = 279961, upload-time = "2026-06-28T19:55:38.456Z" }, + { url = "https://files.pythonhosted.org/packages/ea/b9/69f4e5cd6fbe0bb420cb2dbae441ca118f2495bdda522a74da75aa9829e7/regex-2026.6.28-cp313-cp313t-win_arm64.whl", hash = "sha256:3f15020f0b69cafe57baa067ff65b29acef68ff6b1670a53bef1ca11d708e02d", size = 279266, upload-time = "2026-06-28T19:55:40.62Z" }, + { url = "https://files.pythonhosted.org/packages/3b/fb/fad3b810a5bb1e09b9e5d6913fc6ba88cab738fdf283196827a3c59a4c10/regex-2026.6.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:f7c032b0c8a73739ff8ff1aaf30c281fa19c17bf7f1543256c8507390db7807c", size = 490407, upload-time = "2026-06-28T19:55:42.724Z" }, + { url = "https://files.pythonhosted.org/packages/d6/52/b8c79d12276d93e90e707e939b396034c04980caf1235312ef790f8e11fc/regex-2026.6.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f6710f512c57b84f127a23d0f59560a03b64136eff419ae1be5ab557577fe5e3", size = 291988, upload-time = "2026-06-28T19:55:44.549Z" }, + { url = "https://files.pythonhosted.org/packages/23/d2/6a911f18279daa8d7bb8b20d771ddb6ef31fabd35f5921f9d3ba21640e80/regex-2026.6.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c0013958f427bd82509a186b9ff206d66cb8d60a81fc797a4c717afd18c5b0ba", size = 289704, upload-time = "2026-06-28T19:55:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/fd/22/ad1955c47c669291a05804d53d7071cc0732dfdf166857be38003cedc2d1/regex-2026.6.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f06cdcd6421f8e194ad312ea608020381250df9b8a57661c1b57e9e5273878", size = 797017, upload-time = "2026-06-28T19:55:48.166Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/a83159ff8703ab4d0c2cf99e76ebf289b7b4a501623241d09f88f3614f80/regex-2026.6.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec9689392f7494ff4e3f8e7e8522f9158f11023f337eaaf04a64542fc45bbf26", size = 866112, upload-time = "2026-06-28T19:55:51.047Z" }, + { url = "https://files.pythonhosted.org/packages/b9/09/7bff2d6dbbd77421b3274aa51db1c887381cbc5b6eda93598c3e882ea345/regex-2026.6.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aa084684e6d2078bf6139e374d1fc2af5ddc1ac7122759a2db716d68169f6fd0", size = 911554, upload-time = "2026-06-28T19:55:53.707Z" }, + { url = "https://files.pythonhosted.org/packages/29/44/ae59c3826e7ba492e56795cdf74ea2a7b5b7c5ea116afb79ee4956a5dff1/regex-2026.6.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:40455e6840dc4e96a6fe50f4cedc957de2752c954d91e789812be55d49be199a", size = 800665, upload-time = "2026-06-28T19:55:55.875Z" }, + { url = "https://files.pythonhosted.org/packages/d6/19/6fd033d2ab00f35d445aaeaf3307c1e721424dcbfd48f6f65c857cb939cf/regex-2026.6.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:530b5c223b9ca5dd8370ac502e080aee0e4ded32be987c6564b425fb5523d581", size = 777243, upload-time = "2026-06-28T19:55:57.909Z" }, + { url = "https://files.pythonhosted.org/packages/4e/9d/99730f26df4938049ab1e652ca75e967b4c6739444e18d9707bfdb8af20c/regex-2026.6.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e0ed273ecd1a89be84466c1749bfe58609cc2a32b5d5e05006c4625ba96411b", size = 785784, upload-time = "2026-06-28T19:56:00.072Z" }, + { url = "https://files.pythonhosted.org/packages/48/49/105cd57162f5fc5c04cc917a1388a060cf8427e5c14353cd9044660fbf4d/regex-2026.6.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0ab0d5344311fc8e8667078942056c3b9c9b4a4b1cc99f2eb8a5af54554f4acc", size = 860914, upload-time = "2026-06-28T19:56:02.017Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/788245a95b69018f58bff2f4fd27d007cacaea088cdb390979743f1b2571/regex-2026.6.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:eacb79625323d9f7e7925366b917f492b8356fad58f5dc4fa12ff8c21d8f4ca9", size = 765915, upload-time = "2026-06-28T19:56:05.021Z" }, + { url = "https://files.pythonhosted.org/packages/ca/01/292065a39a004b05e67a337b18213670a7cb919d6856ac2d7df7f1a10dbb/regex-2026.6.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:20f4d87702702aa1d572721e146f301660c50eef6fd6cb596e48a22b0ace17db", size = 851404, upload-time = "2026-06-28T19:56:07.251Z" }, + { url = "https://files.pythonhosted.org/packages/98/9e/a93d865db0e13483ae1a01d81e2ce16d4a7fe2f9b9fe4aac4cc08590b136/regex-2026.6.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e693940a3b9e6d6e4dc2a54ecaa74b74934f77af1ef95f518a74261ef7cc1bc", size = 789373, upload-time = "2026-06-28T19:56:09.894Z" }, + { url = "https://files.pythonhosted.org/packages/82/0c/38b1685ad4017d78efbc8fa7dbbf96d8113b53750c8aa2d3609defd46605/regex-2026.6.28-cp314-cp314-win32.whl", hash = "sha256:234a51e20ebc18ab83b2c0600cf28f2e884560a0e00f743878f0b7d8e7c4cf03", size = 272496, upload-time = "2026-06-28T19:56:11.83Z" }, + { url = "https://files.pythonhosted.org/packages/55/50/e19f261ff9ba9b50722a529e09b1743ecf65eb348be99d0fd2cd7fcede1c/regex-2026.6.28-cp314-cp314-win_amd64.whl", hash = "sha256:7b15c437bc4604f03ceb3f8d37eae2f8930e320e1bc556b259848c639d9eec1a", size = 280754, upload-time = "2026-06-28T19:56:13.758Z" }, + { url = "https://files.pythonhosted.org/packages/36/b8/c9e68f3a9e33be73f20990b2c065b144ff2d0aa242608a950d8c4f3b56e8/regex-2026.6.28-cp314-cp314-win_arm64.whl", hash = "sha256:c6e6f790d01380a74ad564f216c533b86504afb61bf66f2b2e11e7f1a3e287a7", size = 280979, upload-time = "2026-06-28T19:56:15.928Z" }, + { url = "https://files.pythonhosted.org/packages/03/e6/21c425a37880c650d007c4171c6a80325446d830d85f5fbf335e7205b1e7/regex-2026.6.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3527a72adcbe9e3600f1553b497d397c1a371d227580d41d96c3c5964109b65c", size = 494282, upload-time = "2026-06-28T19:56:18.049Z" }, + { url = "https://files.pythonhosted.org/packages/07/50/6647a7ccf5ffff995ba955a0b7d766440f4e58ce1666549c8ee998f2b972/regex-2026.6.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a644f6408692812f5ead82519eed680e08d5d546fddbd9f7d9514e3c73899aa5", size = 293977, upload-time = "2026-06-28T19:56:20.145Z" }, + { url = "https://files.pythonhosted.org/packages/8c/dc/a3e141a4eaf125e50f63105570c01fa477c06ac5259dcfa95e9b90760e84/regex-2026.6.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8e2fae6bb883648346f84db270dc9aafc29d8e895f62b88a75ccc83b09519820", size = 292432, upload-time = "2026-06-28T19:56:22.345Z" }, + { url = "https://files.pythonhosted.org/packages/35/ee/2ac1a6b9f167f8ff69f5a789938cc103b60cff41b24a6990daced8b88e34/regex-2026.6.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:debe623e09cee97ef9404575e936c610aac9bb08358c5099aaef14644a6871f2", size = 811877, upload-time = "2026-06-28T19:56:25.056Z" }, + { url = "https://files.pythonhosted.org/packages/df/7b/9a5505ee92180bcae300b1018b9ff3d3c19962436e66f2505f255e9fde35/regex-2026.6.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc579c91fb4605773483a8d940b136bcc5b854fff44fa14a1572a038f46563f1", size = 871212, upload-time = "2026-06-28T19:56:27.352Z" }, + { url = "https://files.pythonhosted.org/packages/24/4d/d61a702a9f9d1bd29b22cbef1aed6d477baa961232a7eb4d91b7775b0b3e/regex-2026.6.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7c42be203d84ecf7d487ff23f8a61ef0eb0534fa0fc317a2fce8c065d20618f", size = 917507, upload-time = "2026-06-28T19:56:29.762Z" }, + { url = "https://files.pythonhosted.org/packages/d4/60/1308066f5966b65fbb6905b99ba37e9f1cd753dd0ac08485f8257334ee92/regex-2026.6.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8184b4e2fdaf9cdfe77e38f15a4d9dc149168c9c29eb0ea17c5481d3bb80546", size = 816389, upload-time = "2026-06-28T19:56:32.043Z" }, + { url = "https://files.pythonhosted.org/packages/bd/5c/57ce2cb8d714ee0b7f11c7ee4cfe2af66df2b90f147feadcb538609a3a02/regex-2026.6.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:697f103104f5872d64078d8eeac59979960be8ee76115a2d3f31096312e2a400", size = 785890, upload-time = "2026-06-28T19:56:34.492Z" }, + { url = "https://files.pythonhosted.org/packages/ff/fd/1d5350d3a8a327bff0fccacb911732baf7b5b6f5529c0e3fa602a23e7dad/regex-2026.6.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:714d2b1aa29beef0ddfcdc72ad0771c05326551a8bb0680b0ddf74bfaad87387", size = 801451, upload-time = "2026-06-28T19:56:36.749Z" }, + { url = "https://files.pythonhosted.org/packages/f3/79/3c9e4f8a0306e030ad5a43bbbc01625fb28d58a813bc52d42fd1cc63fb2e/regex-2026.6.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0f09f62e450cc2f113018cc8412aeea3a120a04e1ca7e801a0d441583f9a3b06", size = 866504, upload-time = "2026-06-28T19:56:38.994Z" }, + { url = "https://files.pythonhosted.org/packages/65/12/f747de475b54f4709efb24dd0fbc8467c64cec91f5db0d047b079646ee78/regex-2026.6.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:731ea12d5aeb2577eaef2393d6428b995f76eb35f68a89e03e15a97719d1de19", size = 773047, upload-time = "2026-06-28T19:56:41.061Z" }, + { url = "https://files.pythonhosted.org/packages/58/3c/f02f860e0500c1b2d61a79dec7e214b37fb9656281dcddc92397edf96678/regex-2026.6.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:51e952c8783eabd4706d0f63922f219bcfc1bef9b8cb35941c0d1a0396578858", size = 856665, upload-time = "2026-06-28T19:56:43.466Z" }, + { url = "https://files.pythonhosted.org/packages/4d/6c/28b3fa222513484be9dee26b7222bda109056c43ea28aa2314262ca48816/regex-2026.6.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43248fe4c0ab8fbb223588a0795b11268940072c97bba30ea8f9b49d8cdfde34", size = 803573, upload-time = "2026-06-28T19:56:45.791Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/8f86cf1a1fd85c5ab0c503c9fe4607ad4ad48978b2d8b435d94465e134c7/regex-2026.6.28-cp314-cp314t-win32.whl", hash = "sha256:fc1eddc25ad23c0f1344ab280d961ac595ead48292d7c779497975942373f493", size = 274515, upload-time = "2026-06-28T19:56:47.948Z" }, + { url = "https://files.pythonhosted.org/packages/0f/de/f8613c03b36786ddef2c930d28f9bcae861fcd541cc9203a870956cf1e83/regex-2026.6.28-cp314-cp314t-win_amd64.whl", hash = "sha256:ede8d8e53b6dde0a50f7eca902f0af76d87ab02a55aba7542da68ae3e5dfe83d", size = 283650, upload-time = "2026-06-28T19:56:50.614Z" }, + { url = "https://files.pythonhosted.org/packages/4d/f3/f5ec86839bbabe33b6dee649b62ff9a445d43de6b0ad780cf6b83c56f61e/regex-2026.6.28-cp314-cp314t-win_arm64.whl", hash = "sha256:4da6f6a72f8700b97a1a765e837fb7d5750bfd9f13acea7bae498f573e3a70a8", size = 283338, upload-time = "2026-06-28T19:56:52.879Z" }, ] [[package]] @@ -1147,9 +1147,9 @@ dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680 } +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654 }, + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, ] [[package]] @@ -1159,140 +1159,140 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "eth-utils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1b/2d/439b0728a92964a04d9c88ea1ca9ebb128893fbbd5834faa31f987f2fd4c/rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9", size = 33429 } +sdist = { url = "https://files.pythonhosted.org/packages/1b/2d/439b0728a92964a04d9c88ea1ca9ebb128893fbbd5834faa31f987f2fd4c/rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9", size = 33429, upload-time = "2025-02-04T22:05:59.089Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/fb/e4c0ced9893b84ac95b7181d69a9786ce5879aeb3bbbcbba80a164f85d6a/rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f", size = 19973 }, + { url = "https://files.pythonhosted.org/packages/99/fb/e4c0ced9893b84ac95b7181d69a9786ce5879aeb3bbbcbba80a164f85d6a/rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f", size = 19973, upload-time = "2025-02-04T22:05:57.05Z" }, ] [[package]] name = "ruff" version = "0.15.20" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489 } +sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665 }, - { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649 }, - { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638 }, - { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227 }, - { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882 }, - { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808 }, - { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094 }, - { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176 }, - { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767 }, - { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132 }, - { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828 }, - { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418 }, - { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770 }, - { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698 }, - { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322 }, - { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274 }, - { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498 }, + { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" }, + { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" }, + { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" }, + { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" }, + { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" }, ] [[package]] name = "shellingham" version = "1.5.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, ] [[package]] name = "sortedcontainers" version = "2.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, ] [[package]] name = "tomli" version = "2.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543 } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704 }, - { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454 }, - { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561 }, - { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824 }, - { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227 }, - { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859 }, - { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204 }, - { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084 }, - { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285 }, - { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924 }, - { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018 }, - { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948 }, - { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341 }, - { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159 }, - { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290 }, - { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141 }, - { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847 }, - { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088 }, - { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866 }, - { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887 }, - { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704 }, - { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628 }, - { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180 }, - { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674 }, - { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976 }, - { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755 }, - { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265 }, - { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726 }, - { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859 }, - { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713 }, - { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084 }, - { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973 }, - { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223 }, - { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973 }, - { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082 }, - { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490 }, - { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263 }, - { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736 }, - { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717 }, - { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461 }, - { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855 }, - { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144 }, - { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683 }, - { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196 }, - { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393 }, - { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583 }, + { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" }, + { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" }, + { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" }, + { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" }, + { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" }, + { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" }, + { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, ] [[package]] name = "toolz" version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613 } +sdist = { url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613, upload-time = "2025-10-17T04:03:21.661Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093 }, + { url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093, upload-time = "2025-10-17T04:03:20.435Z" }, ] [[package]] name = "ty" version = "0.0.56" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/55/07/fb29aea5235b0aa8ecfc4d1cc6ddf9fba8b863d67d96c6d345694d644c43/ty-0.0.56.tar.gz", hash = "sha256:84d114dc3796361c0fc72945016eabd74d46b9ee64f198cb0e485719704681e5", size = 6050123 } +sdist = { url = "https://files.pythonhosted.org/packages/55/07/fb29aea5235b0aa8ecfc4d1cc6ddf9fba8b863d67d96c6d345694d644c43/ty-0.0.56.tar.gz", hash = "sha256:84d114dc3796361c0fc72945016eabd74d46b9ee64f198cb0e485719704681e5", size = 6050123, upload-time = "2026-07-01T16:44:56.036Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/48/bce79e7ca5c1cc529d3e0d37ddd1121aea4b68a4f749974ad1cc77161871/ty-0.0.56-py3-none-linux_armv6l.whl", hash = "sha256:186d4a53e15747c947e1ec3d7eec8e345d8e40a1ca10e634c585db52497e87dd", size = 11643066 }, - { url = "https://files.pythonhosted.org/packages/80/d1/22555d8a1d719661f10050f3865d877bbf497da908961c75fe22217dd18a/ty-0.0.56-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aae1a980fd9535da0469b7ba2b2e1b54a907743a5e0f442dd57eee9f5bfd034c", size = 11407487 }, - { url = "https://files.pythonhosted.org/packages/cf/2d/b3b7a74ce8bc59ef48843ad80179bb0d9598bbd6cfc0d11d519bdf6b1352/ty-0.0.56-py3-none-macosx_11_0_arm64.whl", hash = "sha256:afd3058c0a6c5f241e814734f133008c93ee805f61c9cf4ce7412b8822b5d9ad", size = 10962270 }, - { url = "https://files.pythonhosted.org/packages/64/ac/6c2fd7de0304a8a7218a756af74f7e62a5e8540fdb175e0a869e51042345/ty-0.0.56-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058b52f7a823ac13aae3cae30809dd6b5145794b64d8478f9ef38c75d79b4483", size = 11471406 }, - { url = "https://files.pythonhosted.org/packages/50/b6/11d861156861c03c7726b74558f9a0e0092661aff83a4fda1279df28c425/ty-0.0.56-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c66e00c1522add1f2bbdd2e45828c953b35c306b7bef03ec9169c75a63699a0", size = 11445612 }, - { url = "https://files.pythonhosted.org/packages/fb/ba/09df108582090f3c0770ec4bc8675affed60248f6793a78d909be16211d9/ty-0.0.56-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40903d71c669a30691b5a5d5728056c7877a1bd6be4f233a38883a8b28cf34d7", size = 12093889 }, - { url = "https://files.pythonhosted.org/packages/d7/f7/dbb4b4ccb69cd64c209ae55b1ab788ace8222c2bc1f6845be9e7cbedbf25/ty-0.0.56-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63fe3947fe0c46c69a7d950e6832ee70a9ec17321fefbff3d2e3c20baf9e5bd0", size = 12666337 }, - { url = "https://files.pythonhosted.org/packages/86/e9/73f903fe4a3d9ea02f26f57c1eb07e3b1029ec92b0e8c2364718893440e3/ty-0.0.56-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71a0c1a72f9854532e710e119b6871ffe4542c8a65146f1f65dcd78fecd885b4", size = 12280247 }, - { url = "https://files.pythonhosted.org/packages/d6/90/cebd222495832f1a00dcd321ba25f3cab804221a4991b992c2178bec68ee/ty-0.0.56-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70d1665596494e24d8ebd198438872b5a56ec3cae5f2bcf6c673be797acc4e3c", size = 11991107 }, - { url = "https://files.pythonhosted.org/packages/b7/07/8f7337a07250f42d975cdb6decf47fc5b421e6c7da5e3e7be1e85f63a7e5/ty-0.0.56-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:778f99e51558afc1dbbe48ee38ab6aae7b31390ed8c1a1ef1499b295e9f1e82f", size = 12298970 }, - { url = "https://files.pythonhosted.org/packages/3c/b9/a52cd59034a48f5f18c6b155cc2cc36861d874b6d0af204b12c898024c3d/ty-0.0.56-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:867bc5708e0066bb4ff6c7db524bd5deea2676c62bfe71d3303138b3be850af0", size = 11425683 }, - { url = "https://files.pythonhosted.org/packages/1d/2e/48e42d33357d52eefb695c0c3fcfc96879b73668a7447d1d1e0ad774fedc/ty-0.0.56-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6012f4189c928edb330a37deb9930f982380bd4aa7c4b8e0428eec9651c7551", size = 11469258 }, - { url = "https://files.pythonhosted.org/packages/d5/01/ad1b4138be1e3fa97863af3925aa2134f17a593240c35dc38c3429fb5ad1/ty-0.0.56-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8ee83de1a7ff4cc32837ec06134ce391d441bc5b35ecd8d3cfe053f120f3e4c1", size = 11758736 }, - { url = "https://files.pythonhosted.org/packages/09/34/9d81967ff240eaa57e9249728ef7b7790747cf6d3c9a98ec86b2cfdcc8ee/ty-0.0.56-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:62619b3b0e2c6248ef30d3f0e2f2217ae9893040585be07f32324242f197cd6f", size = 12100242 }, - { url = "https://files.pythonhosted.org/packages/c3/36/f51d4666d2de6cf33c1f3a1fcc4bb6b70b197dd6ceaa491eef71d78fe8e8/ty-0.0.56-py3-none-win32.whl", hash = "sha256:b30687bb5cd9729d34c889a289edf32770388d9bb05243e534e723fb45e0381b", size = 11093759 }, - { url = "https://files.pythonhosted.org/packages/5e/b4/8fb5d4acfa4afb152245b20fa263069a7547bd1f8e4bfca4eda280c897d7/ty-0.0.56-py3-none-win_amd64.whl", hash = "sha256:ad4c8c47b6f4e3f9ed3fc0b1a5d650088d229e17dd8f63c1826d6bbe94cc3235", size = 12100327 }, - { url = "https://files.pythonhosted.org/packages/b8/fc/6a183e71edde90d0c35c2303f23f7a45b6891d1a2c45daf7b8f869831e19/ty-0.0.56-py3-none-win_arm64.whl", hash = "sha256:57538f273d444a5f1293fa7860e967178afe3917611fc5eff16b64e1204fe0d6", size = 11538780 }, + { url = "https://files.pythonhosted.org/packages/dc/48/bce79e7ca5c1cc529d3e0d37ddd1121aea4b68a4f749974ad1cc77161871/ty-0.0.56-py3-none-linux_armv6l.whl", hash = "sha256:186d4a53e15747c947e1ec3d7eec8e345d8e40a1ca10e634c585db52497e87dd", size = 11643066, upload-time = "2026-07-01T16:44:18.374Z" }, + { url = "https://files.pythonhosted.org/packages/80/d1/22555d8a1d719661f10050f3865d877bbf497da908961c75fe22217dd18a/ty-0.0.56-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aae1a980fd9535da0469b7ba2b2e1b54a907743a5e0f442dd57eee9f5bfd034c", size = 11407487, upload-time = "2026-07-01T16:44:20.956Z" }, + { url = "https://files.pythonhosted.org/packages/cf/2d/b3b7a74ce8bc59ef48843ad80179bb0d9598bbd6cfc0d11d519bdf6b1352/ty-0.0.56-py3-none-macosx_11_0_arm64.whl", hash = "sha256:afd3058c0a6c5f241e814734f133008c93ee805f61c9cf4ce7412b8822b5d9ad", size = 10962270, upload-time = "2026-07-01T16:44:22.959Z" }, + { url = "https://files.pythonhosted.org/packages/64/ac/6c2fd7de0304a8a7218a756af74f7e62a5e8540fdb175e0a869e51042345/ty-0.0.56-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058b52f7a823ac13aae3cae30809dd6b5145794b64d8478f9ef38c75d79b4483", size = 11471406, upload-time = "2026-07-01T16:44:25.327Z" }, + { url = "https://files.pythonhosted.org/packages/50/b6/11d861156861c03c7726b74558f9a0e0092661aff83a4fda1279df28c425/ty-0.0.56-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c66e00c1522add1f2bbdd2e45828c953b35c306b7bef03ec9169c75a63699a0", size = 11445612, upload-time = "2026-07-01T16:44:27.531Z" }, + { url = "https://files.pythonhosted.org/packages/fb/ba/09df108582090f3c0770ec4bc8675affed60248f6793a78d909be16211d9/ty-0.0.56-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40903d71c669a30691b5a5d5728056c7877a1bd6be4f233a38883a8b28cf34d7", size = 12093889, upload-time = "2026-07-01T16:44:29.548Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f7/dbb4b4ccb69cd64c209ae55b1ab788ace8222c2bc1f6845be9e7cbedbf25/ty-0.0.56-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63fe3947fe0c46c69a7d950e6832ee70a9ec17321fefbff3d2e3c20baf9e5bd0", size = 12666337, upload-time = "2026-07-01T16:44:31.586Z" }, + { url = "https://files.pythonhosted.org/packages/86/e9/73f903fe4a3d9ea02f26f57c1eb07e3b1029ec92b0e8c2364718893440e3/ty-0.0.56-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71a0c1a72f9854532e710e119b6871ffe4542c8a65146f1f65dcd78fecd885b4", size = 12280247, upload-time = "2026-07-01T16:44:33.637Z" }, + { url = "https://files.pythonhosted.org/packages/d6/90/cebd222495832f1a00dcd321ba25f3cab804221a4991b992c2178bec68ee/ty-0.0.56-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70d1665596494e24d8ebd198438872b5a56ec3cae5f2bcf6c673be797acc4e3c", size = 11991107, upload-time = "2026-07-01T16:44:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/b7/07/8f7337a07250f42d975cdb6decf47fc5b421e6c7da5e3e7be1e85f63a7e5/ty-0.0.56-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:778f99e51558afc1dbbe48ee38ab6aae7b31390ed8c1a1ef1499b295e9f1e82f", size = 12298970, upload-time = "2026-07-01T16:44:38.243Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b9/a52cd59034a48f5f18c6b155cc2cc36861d874b6d0af204b12c898024c3d/ty-0.0.56-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:867bc5708e0066bb4ff6c7db524bd5deea2676c62bfe71d3303138b3be850af0", size = 11425683, upload-time = "2026-07-01T16:44:40.473Z" }, + { url = "https://files.pythonhosted.org/packages/1d/2e/48e42d33357d52eefb695c0c3fcfc96879b73668a7447d1d1e0ad774fedc/ty-0.0.56-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6012f4189c928edb330a37deb9930f982380bd4aa7c4b8e0428eec9651c7551", size = 11469258, upload-time = "2026-07-01T16:44:42.513Z" }, + { url = "https://files.pythonhosted.org/packages/d5/01/ad1b4138be1e3fa97863af3925aa2134f17a593240c35dc38c3429fb5ad1/ty-0.0.56-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8ee83de1a7ff4cc32837ec06134ce391d441bc5b35ecd8d3cfe053f120f3e4c1", size = 11758736, upload-time = "2026-07-01T16:44:44.567Z" }, + { url = "https://files.pythonhosted.org/packages/09/34/9d81967ff240eaa57e9249728ef7b7790747cf6d3c9a98ec86b2cfdcc8ee/ty-0.0.56-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:62619b3b0e2c6248ef30d3f0e2f2217ae9893040585be07f32324242f197cd6f", size = 12100242, upload-time = "2026-07-01T16:44:46.584Z" }, + { url = "https://files.pythonhosted.org/packages/c3/36/f51d4666d2de6cf33c1f3a1fcc4bb6b70b197dd6ceaa491eef71d78fe8e8/ty-0.0.56-py3-none-win32.whl", hash = "sha256:b30687bb5cd9729d34c889a289edf32770388d9bb05243e534e723fb45e0381b", size = 11093759, upload-time = "2026-07-01T16:44:49.171Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b4/8fb5d4acfa4afb152245b20fa263069a7547bd1f8e4bfca4eda280c897d7/ty-0.0.56-py3-none-win_amd64.whl", hash = "sha256:ad4c8c47b6f4e3f9ed3fc0b1a5d650088d229e17dd8f63c1826d6bbe94cc3235", size = 12100327, upload-time = "2026-07-01T16:44:51.26Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fc/6a183e71edde90d0c35c2303f23f7a45b6891d1a2c45daf7b8f869831e19/ty-0.0.56-py3-none-win_arm64.whl", hash = "sha256:57538f273d444a5f1293fa7860e967178afe3917611fc5eff16b64e1204fe0d6", size = 11538780, upload-time = "2026-07-01T16:44:53.8Z" }, ] [[package]] @@ -1301,22 +1301,22 @@ version = "0.26.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7c/f7/68adc395201b20b872d68e975386832e8005ffeacedd43a1d837a32815be/typer-0.26.8.tar.gz", hash = "sha256:c244a6bd558886fe3f8780efb6bdd28bb9aff005a94eedebaa5cb32926fe2f7e", size = 202097 } +sdist = { url = "https://files.pythonhosted.org/packages/7c/f7/68adc395201b20b872d68e975386832e8005ffeacedd43a1d837a32815be/typer-0.26.8.tar.gz", hash = "sha256:c244a6bd558886fe3f8780efb6bdd28bb9aff005a94eedebaa5cb32926fe2f7e", size = 202097, upload-time = "2026-06-26T09:22:45.705Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/80/87/b9fd69c92c6102a066e1b86a35243f53e70bd4c709f2a26d9f4fee4f4dc0/typer-0.26.8-py3-none-any.whl", hash = "sha256:3512ca79ac5c11113414b36e80281b872884477722440691c89d1112e321a49c", size = 122564 }, + { url = "https://files.pythonhosted.org/packages/80/87/b9fd69c92c6102a066e1b86a35243f53e70bd4c709f2a26d9f4fee4f4dc0/typer-0.26.8-py3-none-any.whl", hash = "sha256:3512ca79ac5c11113414b36e80281b872884477722440691c89d1112e321a49c", size = 122564, upload-time = "2026-06-26T09:22:44.72Z" }, ] [[package]] name = "typing-extensions" version = "4.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555 } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571 }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] @@ -1326,75 +1326,75 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949 } +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611 }, + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] [[package]] name = "websockets" version = "16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346 } +sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343 }, - { url = "https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0", size = 175021 }, - { url = "https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957", size = 175320 }, - { url = "https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72", size = 183815 }, - { url = "https://files.pythonhosted.org/packages/86/26/d40eaa2a46d4302becec8d15b0fc5e45bdde05191e7628405a19cf491ccd/websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde", size = 185054 }, - { url = "https://files.pythonhosted.org/packages/b0/ba/6500a0efc94f7373ee8fefa8c271acdfd4dca8bd49a90d4be7ccabfc397e/websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3", size = 184565 }, - { url = "https://files.pythonhosted.org/packages/04/b4/96bf2cee7c8d8102389374a2616200574f5f01128d1082f44102140344cc/websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3", size = 183848 }, - { url = "https://files.pythonhosted.org/packages/02/8e/81f40fb00fd125357814e8c3025738fc4ffc3da4b6b4a4472a82ba304b41/websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9", size = 178249 }, - { url = "https://files.pythonhosted.org/packages/b4/5f/7e40efe8df57db9b91c88a43690ac66f7b7aa73a11aa6a66b927e44f26fa/websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35", size = 178685 }, - { url = "https://files.pythonhosted.org/packages/f2/db/de907251b4ff46ae804ad0409809504153b3f30984daf82a1d84a9875830/websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8", size = 177340 }, - { url = "https://files.pythonhosted.org/packages/f3/fa/abe89019d8d8815c8781e90d697dec52523fb8ebe308bf11664e8de1877e/websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad", size = 175022 }, - { url = "https://files.pythonhosted.org/packages/58/5d/88ea17ed1ded2079358b40d31d48abe90a73c9e5819dbcde1606e991e2ad/websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d", size = 175319 }, - { url = "https://files.pythonhosted.org/packages/d2/ae/0ee92b33087a33632f37a635e11e1d99d429d3d323329675a6022312aac2/websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe", size = 184631 }, - { url = "https://files.pythonhosted.org/packages/c8/c5/27178df583b6c5b31b29f526ba2da5e2f864ecc79c99dae630a85d68c304/websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b", size = 185870 }, - { url = "https://files.pythonhosted.org/packages/87/05/536652aa84ddc1c018dbb7e2c4cbcd0db884580bf8e95aece7593fde526f/websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5", size = 185361 }, - { url = "https://files.pythonhosted.org/packages/6d/e2/d5332c90da12b1e01f06fb1b85c50cfc489783076547415bf9f0a659ec19/websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64", size = 184615 }, - { url = "https://files.pythonhosted.org/packages/77/fb/d3f9576691cae9253b51555f841bc6600bf0a983a461c79500ace5a5b364/websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6", size = 178246 }, - { url = "https://files.pythonhosted.org/packages/54/67/eaff76b3dbaf18dcddabc3b8c1dba50b483761cccff67793897945b37408/websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac", size = 178684 }, - { url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365 }, - { url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038 }, - { url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328 }, - { url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915 }, - { url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152 }, - { url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583 }, - { url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880 }, - { url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261 }, - { url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693 }, - { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364 }, - { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039 }, - { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323 }, - { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975 }, - { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203 }, - { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653 }, - { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920 }, - { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255 }, - { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689 }, - { url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406 }, - { url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085 }, - { url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328 }, - { url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044 }, - { url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279 }, - { url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711 }, - { url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982 }, - { url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915 }, - { url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381 }, - { url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737 }, - { url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268 }, - { url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486 }, - { url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331 }, - { url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501 }, - { url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062 }, - { url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356 }, - { url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085 }, - { url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531 }, - { url = "https://files.pythonhosted.org/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d", size = 174947 }, - { url = "https://files.pythonhosted.org/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03", size = 175260 }, - { url = "https://files.pythonhosted.org/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da", size = 176071 }, - { url = "https://files.pythonhosted.org/packages/a5/8f/aea9c71cc92bf9b6cc0f7f70df8f0b420636b6c96ef4feee1e16f80f75dd/websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c", size = 176968 }, - { url = "https://files.pythonhosted.org/packages/9a/3f/f70e03f40ffc9a30d817eef7da1be72ee4956ba8d7255c399a01b135902a/websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767", size = 178735 }, - { url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598 }, + { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0", size = 175021, upload-time = "2026-01-10T09:22:22.696Z" }, + { url = "https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957", size = 175320, upload-time = "2026-01-10T09:22:23.94Z" }, + { url = "https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72", size = 183815, upload-time = "2026-01-10T09:22:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/26/d40eaa2a46d4302becec8d15b0fc5e45bdde05191e7628405a19cf491ccd/websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde", size = 185054, upload-time = "2026-01-10T09:22:27.101Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ba/6500a0efc94f7373ee8fefa8c271acdfd4dca8bd49a90d4be7ccabfc397e/websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3", size = 184565, upload-time = "2026-01-10T09:22:28.293Z" }, + { url = "https://files.pythonhosted.org/packages/04/b4/96bf2cee7c8d8102389374a2616200574f5f01128d1082f44102140344cc/websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3", size = 183848, upload-time = "2026-01-10T09:22:30.394Z" }, + { url = "https://files.pythonhosted.org/packages/02/8e/81f40fb00fd125357814e8c3025738fc4ffc3da4b6b4a4472a82ba304b41/websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9", size = 178249, upload-time = "2026-01-10T09:22:32.083Z" }, + { url = "https://files.pythonhosted.org/packages/b4/5f/7e40efe8df57db9b91c88a43690ac66f7b7aa73a11aa6a66b927e44f26fa/websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35", size = 178685, upload-time = "2026-01-10T09:22:33.345Z" }, + { url = "https://files.pythonhosted.org/packages/f2/db/de907251b4ff46ae804ad0409809504153b3f30984daf82a1d84a9875830/websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8", size = 177340, upload-time = "2026-01-10T09:22:34.539Z" }, + { url = "https://files.pythonhosted.org/packages/f3/fa/abe89019d8d8815c8781e90d697dec52523fb8ebe308bf11664e8de1877e/websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad", size = 175022, upload-time = "2026-01-10T09:22:36.332Z" }, + { url = "https://files.pythonhosted.org/packages/58/5d/88ea17ed1ded2079358b40d31d48abe90a73c9e5819dbcde1606e991e2ad/websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d", size = 175319, upload-time = "2026-01-10T09:22:37.602Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ae/0ee92b33087a33632f37a635e11e1d99d429d3d323329675a6022312aac2/websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe", size = 184631, upload-time = "2026-01-10T09:22:38.789Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c5/27178df583b6c5b31b29f526ba2da5e2f864ecc79c99dae630a85d68c304/websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b", size = 185870, upload-time = "2026-01-10T09:22:39.893Z" }, + { url = "https://files.pythonhosted.org/packages/87/05/536652aa84ddc1c018dbb7e2c4cbcd0db884580bf8e95aece7593fde526f/websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5", size = 185361, upload-time = "2026-01-10T09:22:41.016Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e2/d5332c90da12b1e01f06fb1b85c50cfc489783076547415bf9f0a659ec19/websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64", size = 184615, upload-time = "2026-01-10T09:22:42.442Z" }, + { url = "https://files.pythonhosted.org/packages/77/fb/d3f9576691cae9253b51555f841bc6600bf0a983a461c79500ace5a5b364/websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6", size = 178246, upload-time = "2026-01-10T09:22:43.654Z" }, + { url = "https://files.pythonhosted.org/packages/54/67/eaff76b3dbaf18dcddabc3b8c1dba50b483761cccff67793897945b37408/websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac", size = 178684, upload-time = "2026-01-10T09:22:44.941Z" }, + { url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365, upload-time = "2026-01-10T09:22:46.787Z" }, + { url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038, upload-time = "2026-01-10T09:22:47.999Z" }, + { url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328, upload-time = "2026-01-10T09:22:49.809Z" }, + { url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915, upload-time = "2026-01-10T09:22:51.071Z" }, + { url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152, upload-time = "2026-01-10T09:22:52.224Z" }, + { url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583, upload-time = "2026-01-10T09:22:53.443Z" }, + { url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" }, + { url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" }, + { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" }, + { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" }, + { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" }, + { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" }, + { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" }, + { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" }, + { url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" }, + { url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" }, + { url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044, upload-time = "2026-01-10T09:23:15.939Z" }, + { url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279, upload-time = "2026-01-10T09:23:17.148Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711, upload-time = "2026-01-10T09:23:18.372Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982, upload-time = "2026-01-10T09:23:19.652Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915, upload-time = "2026-01-10T09:23:21.458Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381, upload-time = "2026-01-10T09:23:22.715Z" }, + { url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737, upload-time = "2026-01-10T09:23:24.523Z" }, + { url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268, upload-time = "2026-01-10T09:23:25.781Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486, upload-time = "2026-01-10T09:23:27.033Z" }, + { url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331, upload-time = "2026-01-10T09:23:28.259Z" }, + { url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501, upload-time = "2026-01-10T09:23:29.449Z" }, + { url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062, upload-time = "2026-01-10T09:23:31.368Z" }, + { url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356, upload-time = "2026-01-10T09:23:32.627Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085, upload-time = "2026-01-10T09:23:33.816Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531, upload-time = "2026-01-10T09:23:35.016Z" }, + { url = "https://files.pythonhosted.org/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d", size = 174947, upload-time = "2026-01-10T09:23:36.166Z" }, + { url = "https://files.pythonhosted.org/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03", size = 175260, upload-time = "2026-01-10T09:23:37.409Z" }, + { url = "https://files.pythonhosted.org/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da", size = 176071, upload-time = "2026-01-10T09:23:39.158Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8f/aea9c71cc92bf9b6cc0f7f70df8f0b420636b6c96ef4feee1e16f80f75dd/websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c", size = 176968, upload-time = "2026-01-10T09:23:41.031Z" }, + { url = "https://files.pythonhosted.org/packages/9a/3f/f70e03f40ffc9a30d817eef7da1be72ee4956ba8d7255c399a01b135902a/websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767", size = 178735, upload-time = "2026-01-10T09:23:42.259Z" }, + { url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" }, ] diff --git a/website/apps/bittensor-website/public/catalog/intents.json b/website/apps/bittensor-website/public/catalog/intents.json index f74ba7d09e..fa8bcb427a 100644 --- a/website/apps/bittensor-website/public/catalog/intents.json +++ b/website/apps/bittensor-website/public/catalog/intents.json @@ -116,7 +116,7 @@ { "name": "add_stake", "summary": "Stake TAO from the coldkey onto a hotkey.", - "description": "Stake TAO from the coldkey onto a hotkey.\n\nSwaps TAO from the coldkey's free balance into the subnet's alpha at the\ncurrent pool price and credits the result to your stake on the hotkey; on\nnetuid 0 (root) the stake stays TAO-denominated. The swap moves the pool,\nso large amounts incur slippage. By default the call is slippage-protected:\nit fails (`SlippageTooHigh`) instead of filling once the price rises more\nthan `rate_tolerance` (5%) above the price at submission \u2014 raise the\ntolerance or set `slippage_protection` to False to execute at any price,\nor use `add_stake_limit` to set an explicit limit price. The position's\nvalue then follows the pool price and the validator's performance, and can\nbe exited later with `remove_stake`. Fails if the coldkey's free balance\ncannot cover the amount plus the transaction fee, and with `AmountTooLow`\nwhen the amount is below the chain minimum of 0.002 TAO plus the swap fee.\nDynamic subnets also reject a single swap larger than 1000x the pool's TAO\nreserve (`InsufficientLiquidity`).", + "description": "Stake TAO from the coldkey onto a hotkey.\n\nSwaps TAO from the coldkey's free balance into the subnet's alpha at the\ncurrent pool price and credits the result to your stake on the hotkey; on\nnetuid 0 (root) the stake stays TAO-denominated. The swap moves the pool,\nso large amounts incur slippage. By default the call is slippage-protected:\nit fails (`SlippageTooHigh`) instead of filling once the price rises more\nthan `rate_tolerance` (5%) above the price at submission \u2014 raise the\ntolerance or set `slippage_protection` to False to execute at any price,\nor use `add_stake_limit` to set an explicit limit price. The position's\nvalue then follows the pool price and the validator's performance, and can\nbe exited later with `remove_stake`. Pass `all` to stake the whole free\nbalance minus the existential deposit and a small fee headroom. Fails if\nthe coldkey's free balance cannot cover the amount plus the transaction\nfee, and with `AmountTooLow` when the amount is below the chain minimum\nof 0.002 TAO plus the swap fee. Dynamic subnets also reject a single swap\nlarger than 1000x the pool's TAO reserve (`InsufficientLiquidity`).", "signer": "coldkey", "origin": "signed", "verify": null, @@ -151,9 +151,15 @@ "type": "string", "pattern": "^\\d+(\\.\\d+)?$", "description": "decimal string, for amounts too large for an exact float" + }, + { + "type": "string", + "enum": [ + "all" + ] } ], - "description": "How much of the coldkey's free balance to stake." + "description": "How much of the coldkey's free balance to stake, or `all` (everything minus the existential deposit and fee headroom)." }, "slippage_protection": { "type": "boolean", @@ -3619,7 +3625,7 @@ { "name": "stake_burn", "summary": "Buy back / burn stake via the stake-burn extrinsic.", - "description": "Buy back / burn stake via the stake-burn extrinsic.\n\nSpends TAO from the signing coldkey to buy the subnet's alpha and burn it,\nreducing alpha supply (a buyback-and-burn) rather than adding to the\nsigner's stake. The TAO is spent permanently \u2014 nothing lands in your stake,\nso this is not an investment call; use a regular add-stake intent to\nacquire a position. Fails on the root subnet\n(`CannotBurnOrRecycleOnRootSubnet`). The chain accepts an optional\nlimit (omitted = market order), but this intent always requires\n`limit_price` and executes all-or-nothing: the swap fails instead of\npartially filling at a worse rate. Counts against a configured spend\ncap.", + "description": "Buy back / burn stake via the stake-burn extrinsic.\n\nSpends TAO from the signing coldkey to buy the subnet's alpha and burn it,\nreducing alpha supply (a buyback-and-burn) rather than adding to the\nsigner's stake. The TAO is spent permanently \u2014 nothing lands in your stake,\nso this is not an investment call; use a regular add-stake intent to\nacquire a position. Fails on the root subnet\n(`CannotBurnOrRecycleOnRootSubnet`). The chain accepts an optional\nlimit (omitted = market order), but this intent always submits one and\nexecutes all-or-nothing: the swap fails instead of partially filling at\na worse rate. When `limit_price` is omitted, the limit is derived from\nthe current pool price plus `rate_tolerance` (5% by default). Counts\nagainst a configured spend cap.", "signer": "coldkey", "origin": "signed", "verify": null, @@ -3652,7 +3658,11 @@ }, "limit_price": { "type": "integer", - "description": "Worst acceptable price in rao per alpha; the call fails rather than filling beyond it." + "description": "Worst acceptable price in rao per alpha; the call fails rather than filling beyond it. Defaults to the current pool price plus `rate_tolerance`." + }, + "rate_tolerance": { + "type": "number", + "description": "Maximum price move accepted when `limit_price` is omitted, as a fraction (0.05 = 5%). Ignored when `limit_price` is given." }, "hotkey_ss58": { "type": "string", @@ -3661,12 +3671,11 @@ }, "required": [ "netuid", - "amount_tao", - "limit_price" + "amount_tao" ], "additionalProperties": false }, - "cli": "btcli tx stake-burn --netuid --amount-tao --limit-price ", + "cli": "btcli tx stake-burn --netuid --amount-tao ", "python_class": "StakeBurn", "markdown_url": "/llms.mdx/docs/tx/stake-burn/content.md", "sources": [ From a4b252bcf4552e0d43ef421ea8432ef679d39c33 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Thu, 6 Aug 2026 04:22:55 +0200 Subject: [PATCH 34/58] fix: preserve intent safety through multisig dispatch --- sdk/python/bittensor/cli/context.py | 29 +++--- sdk/python/bittensor/cli/multisig_helpers.py | 14 ++- sdk/python/bittensor/executor.py | 4 +- sdk/python/bittensor/intents/base.py | 8 ++ sdk/python/bittensor/intents/multisig.py | 59 ++++++++++++ sdk/python/bittensor/intents/plan.py | 1 + sdk/python/tests/unit/test_multisig_safety.py | 94 +++++++++++++++++++ 7 files changed, 190 insertions(+), 19 deletions(-) create mode 100644 sdk/python/tests/unit/test_multisig_safety.py diff --git a/sdk/python/bittensor/cli/context.py b/sdk/python/bittensor/cli/context.py index ff3cf59376..a1a70e3b0a 100644 --- a/sdk/python/bittensor/cli/context.py +++ b/sdk/python/bittensor/cli/context.py @@ -530,6 +530,7 @@ def submit( except ValueError as error: self.output.error(str(error)) raise typer.Exit(2) from error + semantic_intent = intent.semantic_intent() # MEV shielding: explicit flag > persistent config > the intent's own # default. `forced` distinguishes "the user asked for shielding" (hard @@ -538,10 +539,10 @@ def submit( # `mev_shield_required` intents (collateral AMM buys) refuse the # unshielded opt-out entirely. configured_shield = cfg.get("mev_shield") - if intent.mev_shield_required: + if semantic_intent.mev_shield_required: if self.mev_shield is False or configured_shield is False: self.output.error( - f"{intent.op} must be submitted MEV-shielded", + f"{semantic_intent.op} must be submitted MEV-shielded", help=( "collateral / burned-registration AMM fills cannot run " "unshielded; omit --no-mev-shield" @@ -557,17 +558,17 @@ def submit( shield = bool(configured_shield) shield_forced = shield else: - shield = intent.mev_shield_default + shield = semantic_intent.mev_shield_default shield_forced = False if shield and (proxy_for is not None or self.uses_extension_signer()): blocker = "a proxied call" if proxy_for is not None else "the extension signer" - if shield_forced or intent.mev_shield_required: + if shield_forced or semantic_intent.mev_shield_required: self.output.error( f"MEV shielding cannot wrap {blocker}", help=( "collateral intents cannot fall back to unshielded; " "sign directly without a proxy/extension" - if intent.mev_shield_required + if semantic_intent.mev_shield_required else "pass --no-mev-shield to submit unshielded" ), ) @@ -607,12 +608,12 @@ async def _shield_fee_preflight(client): shortfall = self.run(_shield_fee_preflight) if shortfall is not None: - if shield_forced or intent.mev_shield_required: + if shield_forced or semantic_intent.mev_shield_required: self.output.error( "MEV-shielded submission needs free TAO for the outer carrier fee", help=( - f"{intent.op} cannot submit unshielded" - if intent.mev_shield_required + f"{semantic_intent.op} cannot submit unshielded" + if semantic_intent.mev_shield_required else "pass --no-mev-shield to submit unshielded " "(alpha fees work on the bare call), or fund the " "signing account with free TAO" @@ -816,13 +817,13 @@ async def _execute(client): # The MevShield pallet isn't active here (e.g. localnet). A # forced / required shield must fail loudly; the built-in # default degrades visibly so the command still works. - if shield_forced or intent.mev_shield_required: + if shield_forced or semantic_intent.mev_shield_required: raise BittensorError( "MEV shield is not active on this network " "(MevShield.NextKey is unset); " + ( - f"{intent.op} cannot submit unshielded" - if intent.mev_shield_required + f"{semantic_intent.op} cannot submit unshielded" + if semantic_intent.mev_shield_required else "pass --no-mev-shield to submit unshielded" ) ) @@ -844,13 +845,13 @@ async def _execute(client): else None ) if shortfall is not None: - if shield_forced or intent.mev_shield_required: + if shield_forced or semantic_intent.mev_shield_required: raise BittensorError( "MEV-shielded submission needs free TAO for the outer " "carrier fee; " + ( - f"{intent.op} cannot submit unshielded" - if intent.mev_shield_required + f"{semantic_intent.op} cannot submit unshielded" + if semantic_intent.mev_shield_required else "pass --no-mev-shield to submit unshielded " "(alpha fees work on the bare call)" ) diff --git a/sdk/python/bittensor/cli/multisig_helpers.py b/sdk/python/bittensor/cli/multisig_helpers.py index 37626972b4..48bd6456ef 100644 --- a/sdk/python/bittensor/cli/multisig_helpers.py +++ b/sdk/python/bittensor/cli/multisig_helpers.py @@ -388,7 +388,13 @@ def wrap_intent_for_multisig_wallet(app_ctx, intent): Raises ``ValueError`` when the preset or local signatory set is unusable. """ - from ..intents.multisig import MultisigExecute, MultisigThreshold1, _compose_inner + from ..intents.multisig import ( + MultisigExecute, + MultisigIntentAdapter, + MultisigThreshold1, + MultisigThreshold1IntentAdapter, + _compose_inner, + ) if getattr(intent, "signer", None) != "coldkey": return intent @@ -414,7 +420,8 @@ def wrap_intent_for_multisig_wallet(app_ctx, intent): app_ctx.output.message( f"[dim]dispatching via 1-of-{len(signatories)} multisig {preset}[/dim]" ) - return MultisigThreshold1(other_signatories=others, call=call_dict) + dispatch = MultisigThreshold1(other_signatories=others, call=call_dict) + return MultisigThreshold1IntentAdapter(dispatch=dispatch, semantic=intent) async def _timepoint(client): wallet = wallets.open_wallet(member_name, path=app_ctx.wallet_path) @@ -433,12 +440,13 @@ async def _timepoint(client): f"[dim]{action} via {threshold}-of-{len(signatories)} multisig {preset} " f"as {format_signatory_display(signer_ss58, member_name)}[/dim]" ) - return MultisigExecute( + dispatch = MultisigExecute( threshold=threshold, other_signatories=others, call=call_dict, timepoint=timepoint, ) + return MultisigIntentAdapter(dispatch=dispatch, semantic=intent) async def multisig_list_records( diff --git a/sdk/python/bittensor/executor.py b/sdk/python/bittensor/executor.py index a72bafed51..1309794eca 100644 --- a/sdk/python/bittensor/executor.py +++ b/sdk/python/bittensor/executor.py @@ -523,7 +523,7 @@ async def plan( violations=violations, call=call, extras=extras, - spend=intent.spend(), + spend=intent.semantic_intent().spend(), args={k: v for k, v in intent.to_dict().items() if k != "op"}, ) @@ -565,7 +565,7 @@ async def execute( return the queue receipt instead. ``registration_timeout`` and the optional ``on_progress(dict)`` callback apply only to that wait. """ - if intent.mev_shield_required: + if intent.semantic_intent().mev_shield_required: if proxy_for is not None: raise BittensorError( f"{intent.op} must be submitted MEV-shielded and cannot " diff --git a/sdk/python/bittensor/intents/base.py b/sdk/python/bittensor/intents/base.py index cc593e42b3..5f7eda0b78 100644 --- a/sdk/python/bittensor/intents/base.py +++ b/sdk/python/bittensor/intents/base.py @@ -244,6 +244,14 @@ def affects_all_subnets(self) -> bool: """True if the intent acts across every subnet (so any allowlist must fail it).""" return False + def semantic_intent(self) -> "Intent": + """Intent whose safety contract governs this submission. + + Execution adapters may wrap a call without changing the spend, subnet, + or MEV requirements of the operation being dispatched. + """ + return self + # Introspection ---------------------------------------------------------- @classmethod diff --git a/sdk/python/bittensor/intents/multisig.py b/sdk/python/bittensor/intents/multisig.py index 904e7208a5..5b281e1d35 100644 --- a/sdk/python/bittensor/intents/multisig.py +++ b/sdk/python/bittensor/intents/multisig.py @@ -221,6 +221,65 @@ def summary(self) -> str: ) +@dataclass +class MultisigIntentAdapter(Intent): + """Keep an inner intent's safety contract while dispatching it by multisig. + + Saved-multisig CLI wallets turn a regular coldkey intent into one of the + concrete multisig intents above. The concrete intent owns call composition, + while ``semantic`` remains authoritative for policy scope and MEV handling. + This adapter is internal and deliberately unregistered: it is execution + state, not a separate operation exposed by the SDK. + """ + + op = "multisig_execute" + signer = "coldkey" + + dispatch: MultisigExecute | MultisigThreshold1 = field(repr=False) + semantic: Intent = field(repr=False) + + @property + def threshold(self) -> int: + return int(getattr(self.dispatch, "threshold", 1)) + + @property + def other_signatories(self) -> list: + return self.dispatch.other_signatories + + async def build(self, substrate, wallet: Any): + return await self.dispatch.build(substrate, wallet) + + def summary(self) -> str: + return self.dispatch.summary() + + async def effects(self, substrate, signer_address: str) -> list[str]: + return await self.dispatch.effects(substrate, signer_address) + + async def warnings(self, substrate, signer_address: str) -> list[str]: + return await self.dispatch.warnings(substrate, signer_address) + + def spend(self): + return self.semantic.spend() + + def touches_netuids(self) -> list[int]: + return self.semantic.touches_netuids() + + def affects_all_subnets(self) -> bool: + return self.semantic.affects_all_subnets() + + def semantic_intent(self) -> Intent: + return self.semantic + + def to_dict(self) -> dict[str, Any]: + return self.dispatch.to_dict() + + +class MultisigThreshold1IntentAdapter(MultisigIntentAdapter): + """Safety-preserving adapter for immediate 1-of-N dispatch.""" + + op = "multisig_threshold_1" + + @register @dataclass class MultisigApprove(Intent): diff --git a/sdk/python/bittensor/intents/plan.py b/sdk/python/bittensor/intents/plan.py index b50ed86583..0cbdf4018f 100644 --- a/sdk/python/bittensor/intents/plan.py +++ b/sdk/python/bittensor/intents/plan.py @@ -49,6 +49,7 @@ def check_raw_call(self) -> list[str]: return ["raw call submission is disabled by policy (set allow_raw_calls=True)"] def check(self, intent: Intent, fee: Optional[Balance]) -> list[str]: + intent = intent.semantic_intent() violations: list[str] = [] if self.max_fee_tao is not None: # A fee cap must not fail open: an unavailable estimate blocks diff --git a/sdk/python/tests/unit/test_multisig_safety.py b/sdk/python/tests/unit/test_multisig_safety.py new file mode 100644 index 0000000000..720593e699 --- /dev/null +++ b/sdk/python/tests/unit/test_multisig_safety.py @@ -0,0 +1,94 @@ +"""Safety invariants for automatic saved-multisig intent wrapping.""" + +from types import SimpleNamespace +from unittest.mock import AsyncMock, Mock + +import pytest + +from bittensor import Policy +from bittensor.cli import multisig_helpers +from bittensor.client import Client +from bittensor.executor import Executor +from bittensor.intents._money import UNBOUNDED +from bittensor.intents.multisig import ( + MultisigThreshold1, + MultisigThreshold1IntentAdapter, +) +from bittensor.intents.registration import BurnedRegister +from tests.harness.fake_substrate import FakeSubstrate +from tests.harness.samples import ALICE, ALICE_HOT, BOB, dev_wallet + + +@pytest.mark.asyncio +async def test_saved_multisig_preserves_inner_policy_and_mev_contract(monkeypatch): + output = Mock() + app_ctx = SimpleNamespace( + wallet_name="treasury", + wallet_path="/unused", + wallet_given=True, + multisig_wallet_name=None, + output=output, + ) + monkeypatch.setattr(multisig_helpers.cfg, "get_multisig", lambda name: {"name": name}) + monkeypatch.setattr( + multisig_helpers, + "resolve_multisig_preset", + lambda _app_ctx, _preset: (1, [ALICE, BOB], ["alice", "bob"]), + ) + monkeypatch.setattr( + multisig_helpers, + "pick_local_signatory", + lambda _app_ctx, *, preset, signatories: ("alice", ALICE), + ) + semantic = BurnedRegister(netuid=7, hotkey_ss58=ALICE_HOT) + + wrapped = multisig_helpers.wrap_intent_for_multisig_wallet(app_ctx, semantic) + + assert isinstance(wrapped, MultisigThreshold1IntentAdapter) + assert wrapped.op == "multisig_threshold_1" + assert wrapped.semantic_intent() is semantic + assert wrapped.semantic_intent().mev_shield_default is True + assert wrapped.semantic_intent().mev_shield_required is True + assert wrapped.spend() is UNBOUNDED + assert wrapped.touches_netuids() == [7] + assert wrapped.affects_all_subnets() is False + + violations = Policy(max_spend_tao=1, allowed_netuids=[1]).check(wrapped, fee=None) + assert any("cannot be bounded" in violation for violation in violations) + assert any("netuid 7" in violation for violation in violations) + + plan = await Client("local", substrate=FakeSubstrate()).plan( + wrapped, + dev_wallet(), + policy=Policy(max_spend_tao=1, allowed_netuids=[1]), + ) + assert plan.spend is UNBOUNDED + assert plan.violations == violations + + assert app_ctx.multisig_wallet_name == "treasury" + assert app_ctx.wallet_name == "alice" + + +@pytest.mark.asyncio +async def test_required_mev_shield_survives_multisig_dispatch(): + semantic = BurnedRegister(netuid=7, hotkey_ss58=ALICE_HOT) + dispatch = MultisigThreshold1( + other_signatories=[BOB], + call=semantic.to_dict(), + ) + wrapped = MultisigThreshold1IntentAdapter(dispatch=dispatch, semantic=semantic) + executor = Executor(Mock()) + expected = Mock() + executor.submit_shielded = AsyncMock(return_value=expected) + wallet = Mock() + + result = await executor.execute(wrapped, wallet) + + assert result is expected + executor.submit_shielded.assert_awaited_once_with( + wrapped, + wallet, + policy=None, + wait_for_inclusion=True, + wait_for_finalization=True, + ) From 1a587cc8e938b01f8cfcca5b5ea111702e923fe3 Mon Sep 17 00:00:00 2001 From: unarbos Date: Thu, 6 Aug 2026 07:21:19 -0300 Subject: [PATCH 35/58] Remove miner-burn scaling from subnet emission shares Subnet emission shares were weighted by (1 - MinerBurned), penalizing subnets that route miner incentive to owner/burn hotkeys. Remove the term so shares are pure price-EMA through the emission gate, letting teams use the burn key again without hurting their emission. MinerBurned bookkeeping and the incentive recycle/burn path are kept unchanged; the proportion is now informational only (still surfaced by the website emission snapshot). Release v444: bump spec_version to 444, SDK to 11.0.3.dev0, bittensor-core to 0.1.3. Co-authored-by: Cursor --- .../subtensor/src/coinbase/run_coinbase.rs | 7 +- .../src/coinbase/subnet_emissions.rs | 35 +- runtime/src/lib.rs | 2 +- sdk/bittensor-core-py/pyproject.toml | 2 +- sdk/python/pyproject.toml | 4 +- sdk/python/uv.lock | 1800 ++++++++--------- 6 files changed, 909 insertions(+), 941 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index d8fa2af0eb..27275ef564 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -737,9 +737,10 @@ impl Pallet { "incentives: hotkey: {hotkey:?} is SN owner hotkey or associated hotkey, skipping {incentive:?}" ); // Miner emission directed to an owner (immune) hotkey is withheld from - // miners whether it is recycled or burned. Count both toward the withheld - // proportion so the emission penalty cannot be dodged by choosing Recycle - // and an unset RecycleOrBurn config is not uniquely penalized. + // miners whether it is recycled or burned. Count both toward the recorded + // withheld proportion so the metric is independent of the subnet's + // RecycleOrBurn configuration. The proportion is informational only and + // does not affect the subnet's emission share. withheld_incentive = withheld_incentive.saturating_add(incentive); // Check if we should recycle or burn the incentive match RecycleOrBurn::::try_get(netuid) { diff --git a/pallets/subtensor/src/coinbase/subnet_emissions.rs b/pallets/subtensor/src/coinbase/subnet_emissions.rs index 16cf4c60b2..8fc77e52db 100644 --- a/pallets/subtensor/src/coinbase/subnet_emissions.rs +++ b/pallets/subtensor/src/coinbase/subnet_emissions.rs @@ -353,40 +353,7 @@ impl Pallet { // `get_subnet_block_emissions`, so the effective emission is // e_i = gate(s_i) * s_i / sum(gate(s_j) * s_j) over emit-enabled subnets. pub(crate) fn get_shares(subnets_to_emit_to: &[NetUid]) -> BTreeMap { - let price_shares = Self::get_shares_price_ema(subnets_to_emit_to); - - // Weight each subnet's price share by (1 - miner_burned), then - // renormalize. The effective emission is proportional to - // price_i * (1 - miner_burned_i). - // - (1 - miner_burned) reallocates away from subnets that withhold miner emission. - let zero = U64F64::saturating_from_num(0); - let one = U64F64::saturating_from_num(1); - let weighted: BTreeMap = price_shares - .iter() - .map(|(netuid, share)| { - let burned = U64F64::saturating_from_num(MinerBurned::::get(netuid)).min(one); - let factor = one.saturating_sub(burned); - - (*netuid, share.saturating_mul(factor)) - }) - .collect(); - - let total_weight = weighted - .values() - .copied() - .fold(zero, |acc, w| acc.saturating_add(w)); - - let mut shares = if total_weight > zero { - weighted - .into_iter() - .map(|(netuid, w)| (netuid, w.safe_div(total_weight))) - .collect() - } else { - // The combined weight zeroes out for every subnet (e.g. no root stake, or - // every subnet burning all of its miner emission); fall back to the - // unweighted price shares so the block's emission is not stranded. - price_shares - }; + let mut shares = Self::get_shares_price_ema(subnets_to_emit_to); Self::maybe_update_emission_gate_bar(&shares); Self::apply_emission_gate(&mut shares); diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 27fe5f0c2c..36bb308c5e 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -235,7 +235,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 443, + spec_version: 444, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/sdk/bittensor-core-py/pyproject.toml b/sdk/bittensor-core-py/pyproject.toml index 3024e05c3c..10d288c947 100644 --- a/sdk/bittensor-core-py/pyproject.toml +++ b/sdk/bittensor-core-py/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "maturin" name = "bittensor-core" # Static (not read from Cargo.toml) so the release train can stamp PEP 440 # rc/dev suffixes that cargo's semver would reject. -version = "0.1.2" +version = "0.1.3" description = "The chain-defined compute core for Bittensor clients: sp-core keys, keyfiles, drand timelock, ML-KEM, SCALE codec, and RFC-0078 metadata digest, built from the bittensor monorepo" readme = "README.md" requires-python = ">=3.10" diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index fa73ff8b6e..87c263e325 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "bittensor" -version = "11.0.2.dev0" +version = "11.0.3.dev0" description = "A lean Python SDK (import bittensor) and CLI (btcli) for the Bittensor chain." readme = "README.md" requires-python = ">=3.10,<3.15" @@ -18,7 +18,7 @@ dependencies = [ # Keys, keyfiles, timelock, ML-KEM crypto, and the SCALE codec/runtime # engine: the in-repo Rust core, built against the same crate revisions # as the runtime. - "bittensor-core>=0.1.2,<0.2.0", + "bittensor-core>=0.1.3,<0.2.0", # `btcli` terminal UI. The CLI is a first-class part of the package, so # its dependencies are unconditional. "typer>=0.12.0", diff --git a/sdk/python/uv.lock b/sdk/python/uv.lock index 397f3667c3..d072f9aaca 100644 --- a/sdk/python/uv.lock +++ b/sdk/python/uv.lock @@ -1,122 +1,123 @@ version = 1 +revision = 3 requires-python = ">=3.10, <3.15" [[package]] name = "annotated-doc" version = "0.0.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288 } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303 }, + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, ] [[package]] name = "annotated-types" version = "0.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] [[package]] name = "backports-asyncio-runner" version = "1.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8e/ff/70dca7d7cb1cbc0edb2c6cc0c38b65cba36cccc491eca64cabd5fe7f8670/backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162", size = 69893 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/ff/70dca7d7cb1cbc0edb2c6cc0c38b65cba36cccc491eca64cabd5fe7f8670/backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162", size = 69893, upload-time = "2025-07-02T02:27:15.685Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313 }, + { url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313, upload-time = "2025-07-02T02:27:14.263Z" }, ] [[package]] name = "bitarray" version = "3.8.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bb/9b/ca307b554eaa233d004cae07d5594f9d45affd1f8e118687059aa06fcc6b/bitarray-3.8.2.tar.gz", hash = "sha256:2675a0c17c0b2d12d0fbcf3b27eb833f96936a588da47ac445c0743c5aa69e6b", size = 153516 } +sdist = { url = "https://files.pythonhosted.org/packages/bb/9b/ca307b554eaa233d004cae07d5594f9d45affd1f8e118687059aa06fcc6b/bitarray-3.8.2.tar.gz", hash = "sha256:2675a0c17c0b2d12d0fbcf3b27eb833f96936a588da47ac445c0743c5aa69e6b", size = 153516, upload-time = "2026-06-17T17:22:23.921Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/48/f7/f3dc5577d53e311c7a7650472e847a29361fbd79a5c8c7a34b4be4eae974/bitarray-3.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f5930731b736e3f9654029f3e9082bfb1721d81f04bff9e6eab8eb38b4dfed", size = 150023 }, - { url = "https://files.pythonhosted.org/packages/74/56/b847e84d0310c19b8a127eda77be2e3429d548d485a6a81ef1ee32a6d91e/bitarray-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e835f33ab5aa297a9ce21b7813222c22ff1618b8f8c5e6f921e54b4ae8b8f43", size = 146927 }, - { url = "https://files.pythonhosted.org/packages/90/71/1aa47086b72034b25b55388335765a6640bc232a5e0aad5dabb4ea677d68/bitarray-3.8.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1061cb959efbe3b747c38d550d8d7f0794090a757dd552eae8cf614a5f8d76b6", size = 325474 }, - { url = "https://files.pythonhosted.org/packages/9f/f5/1092c5a3e34a09bbe11149bc9e19c6c23b82c7383ac61d2aef8bb205eda6/bitarray-3.8.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82a6574e98bdddfb7fdac4d41c1176e90e1fcaaed97fda39836a9e0d8b247ec3", size = 353442 }, - { url = "https://files.pythonhosted.org/packages/f7/c0/99755ded6bcde8e577374722f1d14bf43d98a9ceb8bae07e5ad445ff10b8/bitarray-3.8.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9a34663e05bf79ccb92e931e720fbd281e84007ed996d38754aadfbc33e71c24", size = 363901 }, - { url = "https://files.pythonhosted.org/packages/51/b3/312207693283b29d59c9a28ee662e6daa1d762a475dce21811929fb3bd77/bitarray-3.8.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:819f93a1aa7e711ccbb083647a8995bbb0da8f741c8b691576ff1bf5b5018c51", size = 331861 }, - { url = "https://files.pythonhosted.org/packages/cc/70/83e0698a8d32322e0ed5c35eda339f85e5a828d8e30e24cbafcaa36e74d9/bitarray-3.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:07c20505dc8935b55d6de0bb1cc7e0e35de792d5f118d60b177dee53771a474f", size = 323169 }, - { url = "https://files.pythonhosted.org/packages/28/55/c77597c5d5fab09a24b67b7e626d9de505d91fa03dac728d153663ab8149/bitarray-3.8.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:874c6806c2c7b861da0f0e9eead173bb3b9b7a62fcfadc01be51c32d50d7f71c", size = 351476 }, - { url = "https://files.pythonhosted.org/packages/b6/17/fff630b5584985f9f203f89eb16f50a860e5198265eb94e6f4c3af482c96/bitarray-3.8.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4403e5b4da88ec195afe3eab5969b34358157d196e1c63e93328e64e632abbed", size = 347982 }, - { url = "https://files.pythonhosted.org/packages/39/60/7e0c8c84d25251a93a0f56419738a914efe3134923e17f8ead6dbbb336a0/bitarray-3.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8a23e06e87cfa2ba361040eae87479ac197502ba10533c0f2de03d3d93cce91b", size = 328606 }, - { url = "https://files.pythonhosted.org/packages/c6/15/77d9d43e478f2bf9fc84ce2414b845a97369ebfb46d1a3c3e8da72cb4e5a/bitarray-3.8.2-cp310-cp310-win32.whl", hash = "sha256:e65b91b68aa072732d144fa11d86518324b8b27af7e2474bd7a50c88648dc5d4", size = 143238 }, - { url = "https://files.pythonhosted.org/packages/18/8f/17808e4980e88ec314fb40404308d49b648e41092c19e2fb71d2a9e0d058/bitarray-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:156c6d964111e1c0029c5bb41148a73aa870ca10c03a03279b5597fa68ac6761", size = 149868 }, - { url = "https://files.pythonhosted.org/packages/42/75/285f2c9315a6ca19fec9281737f2fb31a3401584ccf82e4d689f6142d266/bitarray-3.8.2-cp310-cp310-win_arm64.whl", hash = "sha256:1b7c6fd8755dda32bc83b171e0a0f625fea545bb6f8a70a7481244dc847b1c9e", size = 147722 }, - { url = "https://files.pythonhosted.org/packages/48/85/c19b7928447d4259418b915857200f7a471920e88241d5a27083a4ceedb2/bitarray-3.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7540de3e7609693b208020cb3cb28cb16395eb915dff742bdcdd9909d475bf3d", size = 150025 }, - { url = "https://files.pythonhosted.org/packages/27/a2/3faeec7783733b596f63b887eb29fd6abfda6937195a269dc1fc6236ac76/bitarray-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c073cd936904e520990339745a2d561ceabc9daa1cefcaf9592196a3355eb1cd", size = 146925 }, - { url = "https://files.pythonhosted.org/packages/68/75/b8e778aaa9d184b1361560a96974d99400c43e70f389a17382951969165e/bitarray-3.8.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4c1c97c5712ad45c6c1427b70bb6524f40532e4a544ca2b7e0375ca61c09244", size = 333297 }, - { url = "https://files.pythonhosted.org/packages/74/18/4c52fa2ec6dac3db01fd51ab2fdccba0a3e86b9b3eb9c76ab6e6e9190008/bitarray-3.8.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7627bfa750a609f5df05c1da337984b8f3821927591aaf861ba70f38bc5f6da1", size = 361658 }, - { url = "https://files.pythonhosted.org/packages/8e/ff/3e34aef8ad52ef63eb426dada698de6240cf45a99a6949b4678954e96814/bitarray-3.8.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ff06e0511682f117d0c24828f0ef1b4f2c3617d38984c7b3ce78d107bee016ab", size = 372260 }, - { url = "https://files.pythonhosted.org/packages/f2/26/6a7e0f9254753b7c81ef3a7465533e7de0aa7da882aec6c19e993329d4d7/bitarray-3.8.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bcaeccab426b0a6e26c10bd8d8c21c15f81757320ad158a8c9e3e953ab81d223", size = 339446 }, - { url = "https://files.pythonhosted.org/packages/37/2f/e866171e3b4ab8f12378d8fbd0d24944a12af623c130126b1e8d145deecc/bitarray-3.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:385045390630f5f433c89caeed9bca9f5b40e3986ae2d7e829e93098c1a96b94", size = 331180 }, - { url = "https://files.pythonhosted.org/packages/be/ee/9371212756ab3e9c0f3247709ec3b341015ca8fc7d9de4a3a2f30c2b4439/bitarray-3.8.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:30541722bfa0f8213d8e621772bef538204fe9eeb4357f4261d404688c2281a5", size = 359108 }, - { url = "https://files.pythonhosted.org/packages/75/4c/97d2ced53249890cbb6f16569da2fd4c73f767faf70bbbc03bd7329caa02/bitarray-3.8.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3daf8f1e040d48bf7ee664bd5c9df9d029c55780c671221d753f6f4fc769f10a", size = 356253 }, - { url = "https://files.pythonhosted.org/packages/a6/cc/68d2d511182c5cced2734086ca6b5b7fc778ce1babcfbe5e43d33fffde48/bitarray-3.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c223cf53e4a458b05b9f78723d88d5a1221fa11fb00cd1a696ccd483dcae3f8c", size = 336632 }, - { url = "https://files.pythonhosted.org/packages/b6/b4/739981ea2ea25e8199c3f58e3ac6b52749d26f4999db5bf673dadabef83f/bitarray-3.8.2-cp311-cp311-win32.whl", hash = "sha256:d9367a5eb2a3dda6958a129ca939ce7dd1555a3b13967eb2e7c9dc8df2cdffa0", size = 143420 }, - { url = "https://files.pythonhosted.org/packages/52/f1/841be2f5c3d1c79ab319eaf52871afb6616f8c7e6ef916517ef13b7e4c47/bitarray-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:2d0af077831aff8f44d8befe6459544bea1cd8fbce6b5b2a30ae1cb086a50620", size = 150060 }, - { url = "https://files.pythonhosted.org/packages/82/de/5d275dcb5abc23ccf3139b478e304efc41d7bd7dc78901bfcc5ef3f251ff/bitarray-3.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:a78778a0899c682537ac612b1a03ecd4ad30063c118825d0138d0f7518270e54", size = 148006 }, - { url = "https://files.pythonhosted.org/packages/52/20/53916ba8d01bc92e01d89c03cd7745107df48923de091b5f957578ff38ff/bitarray-3.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d5dcca2b64bbfce46dc43d77a2973d0b949e2260d74e8bd4e9a766de3afd0e70", size = 150156 }, - { url = "https://files.pythonhosted.org/packages/18/a8/bfa7c8f4141b3119decc54ff6656b8e2f6d4303dc71577021f2d4b42cf42/bitarray-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c78dfbb8883133caeb11aa4ec375165ff1b456a28898cbe45536173369accb24", size = 146884 }, - { url = "https://files.pythonhosted.org/packages/f5/60/fb0e9118dce7e1858fc4f608d0c13460207b227fc13819a23c6f3c70ec78/bitarray-3.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c32189234e4206c3832f947ebdf1735926dea0dbe0e966effd62771884dedf63", size = 336496 }, - { url = "https://files.pythonhosted.org/packages/be/b5/8d50bb4d55113535919812adb66dcdb590a95a032d5975254d951146c2b4/bitarray-3.8.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:26490091d3ad8c039829b33ab1bc776941ce359ecdcf8beef3c1efc330fcf1a5", size = 364673 }, - { url = "https://files.pythonhosted.org/packages/f2/c2/90ca21488fb0ac791a00b98c49c3dbab7ca1aca59e8745dabe073133370f/bitarray-3.8.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8ad858bd35dbb554de248c277ba9052f31d8e153c133195ef40c198303725dc8", size = 375966 }, - { url = "https://files.pythonhosted.org/packages/3b/39/f414699060068ef15b886353e6ae6d2f476715e5c7db205b47710e5e7b4c/bitarray-3.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:58aeaf943929716b411a4ff24422c2b8bbf2c2d8ef3e23bbf08dc7d47c49e2ae", size = 343994 }, - { url = "https://files.pythonhosted.org/packages/32/84/70a8ae25ba927f0b7656041c7cceea011296cbf6cc3770788bc331a5be88/bitarray-3.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b016d736e2b4aa8962962724b69893adce076622374cf4a275503049f5c7207", size = 334129 }, - { url = "https://files.pythonhosted.org/packages/4e/20/3ec71a1e9a8cab12e7306cbfcf0f6e6ae7726f11ca4a7aa2bd047d8d105e/bitarray-3.8.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6871b2b1680580e54fbf0196b3ab7b40a417b4d1fdb3ebda0debf3948e9b8604", size = 361708 }, - { url = "https://files.pythonhosted.org/packages/90/fc/6cae06eac8a25e5715f5607de6bae4bc3ec3b0634f790d5e22debab1802d/bitarray-3.8.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a4c6bb948d011bf18642e09a0a4d1dd067f0722db09d2d4b5d6cce292d71b448", size = 359888 }, - { url = "https://files.pythonhosted.org/packages/c0/cc/078932ee7b41862571e8b3cfb7dc4e03af5c4843b8246a5a663af8678773/bitarray-3.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:78622f067a89360e8acf146be7878f62deafe687db40feb16dabfc808a20717c", size = 340969 }, - { url = "https://files.pythonhosted.org/packages/f6/19/719edf77615864263a12351287832979b02a6277b4058ec6b53669ecbf7e/bitarray-3.8.2-cp312-cp312-win32.whl", hash = "sha256:75999de62a7c4686b901458d441bc3c6c03dade68d1dfbe808439e748d086ea3", size = 143759 }, - { url = "https://files.pythonhosted.org/packages/e9/af/6806f09441de299ccd42b361c2e25138425457331c0e59aef23aba0e901e/bitarray-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:3e44247fcf5dffa86031d5412b20278a953e4dcef4033012c93ebd9985d48fec", size = 150393 }, - { url = "https://files.pythonhosted.org/packages/99/e0/b9c738cfc16a59fcb4b17dd4f699d235257d2d3074e403892d4cd37ccc53/bitarray-3.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:f823fa67f074c0ede82014fd5c2020f301b88f351635f5ba7b802f53b5e0eade", size = 148168 }, - { url = "https://files.pythonhosted.org/packages/48/99/01fb3b90cbf8a930d2326945df2b28a5f046380c0f966ea78cada00dae45/bitarray-3.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:71d7350c801eea43afb0a8679fd7475b0fd9868fd15352f0d3069f335b44af06", size = 150167 }, - { url = "https://files.pythonhosted.org/packages/e7/ce/b26a94753fcfd9e7652805a539df60a83085997319be81ef6d59192ad37c/bitarray-3.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa3be101ed71c4e4989899da744a926d1f55f5d5f7f93242c32f727f7c11350b", size = 146882 }, - { url = "https://files.pythonhosted.org/packages/a9/8e/0bdf36618f4f585d5c35cb033f6a5611337d873d8718feca41d27453cc54/bitarray-3.8.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f684eb138bae893a5d98c811d99ecd89fa4a1af4700b0e512b8e2b794c9cabd", size = 335677 }, - { url = "https://files.pythonhosted.org/packages/cc/99/5588cbe69640d7fa2386be315ddb0e1bde6de8e922c025dccee769cc6d9e/bitarray-3.8.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:94e7da622b723705caddd59ee681cee0355b444901cc6fb2bcdc24bafba85911", size = 363773 }, - { url = "https://files.pythonhosted.org/packages/80/4f/7d2946d88ae77306833bd5b91746d212404d5a86347341274b61d08c3f7e/bitarray-3.8.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3110786b00b28a756fd948c8d63e6ca3a74810b2d115582d85593d9d48035c49", size = 375005 }, - { url = "https://files.pythonhosted.org/packages/fd/be/9a645b2e1bb0da4779dd9cab5a075d7c5bb68a16d8c90f051d47393bbcfe/bitarray-3.8.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd40cf27e2b54b5e30d0ce1da4f59bc16dd7c8363a20786b6e9deeb0b8ebe8e0", size = 343273 }, - { url = "https://files.pythonhosted.org/packages/98/8d/73c658d200671c5e023225163be6aa545f675a676e960e5a4e19ac21274b/bitarray-3.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:24c6b97f27bd3868e28b201e1d777f5e168805862b7d9528099138bbb8c6a636", size = 333403 }, - { url = "https://files.pythonhosted.org/packages/94/bc/819abd376bd6a892ce27840a1d5a4378be228be1ab3bca41845203ee672b/bitarray-3.8.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:786dedb4b1ced22dfeaaa89902561616f7edfa91774702b1aac31df3a6073c88", size = 360846 }, - { url = "https://files.pythonhosted.org/packages/83/59/b8ea1e31928d06db1f2b12187631b51bb3c83186b18581754bc008cec0aa/bitarray-3.8.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:01bf9ff247117533c11963a81f3529bc12283c600dd195cf3b28a97b095f5d1c", size = 359168 }, - { url = "https://files.pythonhosted.org/packages/6e/31/ef3b2f58517f7dbba8119f2592c1ea556a687bc8d405dd93c07f9c28d514/bitarray-3.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cc7a76e77c158e793d7c1e0b6c2240374087ac690a8bcacc8f18c427e5d9e20c", size = 340091 }, - { url = "https://files.pythonhosted.org/packages/8f/83/bf92dcfec4eefd59fa4d8491504e100ae86e11b8cec353ae5532b25708e6/bitarray-3.8.2-cp313-cp313-win32.whl", hash = "sha256:db9add8dcc87154c0f011e0e1ce9b856e5948fbcf6faf44305aa140e525ec9a7", size = 143786 }, - { url = "https://files.pythonhosted.org/packages/1c/29/1f57913a96bffb27bed486a9ca592021dd8161f6c95fd632aad7d4f0bb95/bitarray-3.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:cf4926098970d2d1a14156c0fbddb47554124347db4acf3ba616064fb021cd1e", size = 150414 }, - { url = "https://files.pythonhosted.org/packages/17/9c/f36b91fcb93af54c9a28e3bd1fbf39ef7706fc623a526f3450113c0a0dae/bitarray-3.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:5c8281d0eb35e8685235e1d50f9b26156803dad398d0e7868ce9aae254c3777d", size = 148197 }, - { url = "https://files.pythonhosted.org/packages/c6/86/aa2f29699763f4867359289a946ff3597d45239470c20f6ccb8dba48e7af/bitarray-3.8.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cbe96e7384e36963a2cdf5bc4ac9d0a78ae0d87fc78c53159cd5ac08c661ff34", size = 150139 }, - { url = "https://files.pythonhosted.org/packages/56/1f/0d759c53a7129e4979c3c03b3f2372291c4c5a1cc851d9e749273b34ddf8/bitarray-3.8.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8b4fcecbbd0969988cc115bee74119c767636e48606fad318361eb9fe40a13c6", size = 146888 }, - { url = "https://files.pythonhosted.org/packages/49/2e/0611d057e6cb010ccaf55ec6630ef41d3e7546a285383dfa2a99f545e440/bitarray-3.8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48798fc274e8a0329ca75185a0dc1e0a93ff627ea8f30c339bdf0a2ef26b1723", size = 335581 }, - { url = "https://files.pythonhosted.org/packages/11/0d/201befb06fbb6275046ffe2d21cbe3b059e4f5c6b258da6e6b41f53dd9af/bitarray-3.8.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4205ae045129e58e7b7a9abe929ea0b9a3c63fad39d760e6e3b90062b6e5aa5", size = 363929 }, - { url = "https://files.pythonhosted.org/packages/b6/3c/2639aaa97eb81cabc453f78277493ea31ff49b3514e17eca56129d613279/bitarray-3.8.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:49c16cdedbd3c4d6bf64aca7b370ea02456e9be030201e80c282d8df6af36d19", size = 374562 }, - { url = "https://files.pythonhosted.org/packages/52/1d/f11ba5b55f6a0f0007985f435c0e32c7a3459775cdee308cfb5938628670/bitarray-3.8.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5cad241cd0ceb79a0e4f76e86b36660c22d36c32efb364badcf7609ed5a9e5c", size = 343166 }, - { url = "https://files.pythonhosted.org/packages/4b/b9/2f8f62e1cd42f60f20ca55ed3de57ff2295b85a70eff119501ae2f0e8c48/bitarray-3.8.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3b44650aba323cb1c2285c310ffa6b1adfd5293acecd7f84aaa91afa27c802c", size = 333564 }, - { url = "https://files.pythonhosted.org/packages/22/de/1525e32e7663980b82098ae0c6e032823782b9190cabed6a1f09e67c7831/bitarray-3.8.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5fc8fa50c6a89b1e75edcea4ae17787a0a9b424cdbaa03485e73a837262eca27", size = 361034 }, - { url = "https://files.pythonhosted.org/packages/df/55/7bfe6af3fa577f5132380209c3f3ec560149c0af4e540ce16d84f8b76599/bitarray-3.8.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5f246319a26221e36eaf3f6aed9cd98172f81e91740bbf5cdf31b4490ecfb87a", size = 358728 }, - { url = "https://files.pythonhosted.org/packages/9d/c8/85898711f7b4cf5b06c49d8e36a6702a303f1990cb21cbb39dbe186730a0/bitarray-3.8.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e76c01ae0f191c5572c12b1fda333243bfe4d58ad1d601048f9e4928d94db0c5", size = 339747 }, - { url = "https://files.pythonhosted.org/packages/5b/56/94cc5250be3d530c52d15e41bdbf5f891a492aeebb9e978914aa4559c00a/bitarray-3.8.2-cp314-cp314-win32.whl", hash = "sha256:a1df20419ccc23a0326ee0cb391d1c524ee3c338856e66528d73f4dcec0389d0", size = 142830 }, - { url = "https://files.pythonhosted.org/packages/b4/eb/b9ba05ae59d56a9e5cb8e812072d33be38076717db6579302e1ee85fd688/bitarray-3.8.2-cp314-cp314-win_amd64.whl", hash = "sha256:4bfbeba9156834455ab107936ebd461728f1ed35ded8f15aafde2c3dac9badf5", size = 148912 }, - { url = "https://files.pythonhosted.org/packages/b6/07/e279a5ba7cd114398f00d853026e6c72e198035b925c74866e3c1973daca/bitarray-3.8.2-cp314-cp314-win_arm64.whl", hash = "sha256:4149aeb7c8cad12f9ea13783550ab5508e6d553eeefead5e3da659ce6724c5a5", size = 147373 }, - { url = "https://files.pythonhosted.org/packages/94/a4/4014952965ef7edf80076f8004df31484bccecba97af7b3e9c99269a053d/bitarray-3.8.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f6f6cf5ec3be7e1bd32bfe1f4b24f7d1de28d72394d7f58789b9f9042d19f5f6", size = 151073 }, - { url = "https://files.pythonhosted.org/packages/ff/00/850095c3bc551797c97a4b54c7755fc46eb115ce288fcf6962d8e8c5b678/bitarray-3.8.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2b9790847024cf1de275c8b2495331fe0982d099e407be1c1413ed40ddf2b5d", size = 148009 }, - { url = "https://files.pythonhosted.org/packages/dd/4d/74f0440d95d00f086a80e6c429e3333ebb29cecf55a8d401ceb0c65a3b4b/bitarray-3.8.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c172161b8847f91e9f9ea9ae2e31fcfa784ec5d0cd413900c82574999e21ad05", size = 343487 }, - { url = "https://files.pythonhosted.org/packages/78/e9/ea9c182ff0edb671853bb7a54b790572dc0b73d4a3b13e358f42aa34dca0/bitarray-3.8.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5fcc57961bc78885091a45b9ced5a5924b3b1fdd439a0e1d4b7e3aedf0c31ae2", size = 372305 }, - { url = "https://files.pythonhosted.org/packages/d5/ff/307cacc432e2ec304b870676189852c3f34a803d15b26f73bb36c549166b/bitarray-3.8.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b5fdb5399f0f2c42abcca87f8167d7ad746cf6ca7decadb4f5ad432280cc3a2f", size = 382242 }, - { url = "https://files.pythonhosted.org/packages/b8/ae/757a10ce90e2090dd2dff8c5059a47439122a8d68f5fa9cf06ed07a1dc74/bitarray-3.8.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bb6195a2edafceee0e9ee12c13aad2162e9578d91a24e7c501c3bd4ab90511a", size = 348509 }, - { url = "https://files.pythonhosted.org/packages/ef/d3/a035bb2c459e1f7bc86974fd43057aa8bb76466dd6bd75787d8eb9c534ed/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ce3b3dd599d4eca214f9c7fb7ac2343ccab41d91f3da7aa3b75ddbbea49ec2d5", size = 340539 }, - { url = "https://files.pythonhosted.org/packages/bc/6d/e7af02d167c227d143d208cd1c54d8e4f024d8d0bb59a0f2c38c32d56ad0/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:11cd9766ce95199bef5010ff63f73c880d9c0b6ba9c4c233aeeebc11ab1dfbb3", size = 369505 }, - { url = "https://files.pythonhosted.org/packages/9d/1d/29d0538ac245941127a25735d33f7b6658be6612c35115bcac60ef7c3c1c/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:7a4bbbad17d3db92615497302b74cf77504f821eb9585b7948d92093017d5e70", size = 365262 }, - { url = "https://files.pythonhosted.org/packages/1c/c8/2feabadbbc365e000821c7af82906e71366b29719329ef5709d64707fd4c/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e715498f3dc9af954b9d0977470aa352cb3fe1c39e80c32f5ac4c0348e461f6d", size = 344014 }, - { url = "https://files.pythonhosted.org/packages/6c/88/dc465cbfe5c74b7da8c19b9dc2565d8a4391fad418c48e1559a0267fd00b/bitarray-3.8.2-cp314-cp314t-win32.whl", hash = "sha256:c85569fb99cf9d4aa964d2dbba3c095c7580b4368f63f51252e85b939fcd0a2c", size = 143775 }, - { url = "https://files.pythonhosted.org/packages/08/75/50f2ef697d8ce46ba0986830f2d1288bff883e7f4833590076956a073496/bitarray-3.8.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7de416b313fc8e8aa1e323b83d2ba86b7c84161f7ebbaf986bdab80f9d06a2fb", size = 149884 }, - { url = "https://files.pythonhosted.org/packages/df/0e/6aa2133fffbac3efcb468c7c12163eff7bbe55b86a0d6a1c687ef57e2654/bitarray-3.8.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7199451493d34a5c62cb7c9077fcfd238499af4e0d13a32d33760afe73054135", size = 148321 }, + { url = "https://files.pythonhosted.org/packages/48/f7/f3dc5577d53e311c7a7650472e847a29361fbd79a5c8c7a34b4be4eae974/bitarray-3.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f5930731b736e3f9654029f3e9082bfb1721d81f04bff9e6eab8eb38b4dfed", size = 150023, upload-time = "2026-06-17T17:19:57.898Z" }, + { url = "https://files.pythonhosted.org/packages/74/56/b847e84d0310c19b8a127eda77be2e3429d548d485a6a81ef1ee32a6d91e/bitarray-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e835f33ab5aa297a9ce21b7813222c22ff1618b8f8c5e6f921e54b4ae8b8f43", size = 146927, upload-time = "2026-06-17T17:19:59.585Z" }, + { url = "https://files.pythonhosted.org/packages/90/71/1aa47086b72034b25b55388335765a6640bc232a5e0aad5dabb4ea677d68/bitarray-3.8.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1061cb959efbe3b747c38d550d8d7f0794090a757dd552eae8cf614a5f8d76b6", size = 325474, upload-time = "2026-06-17T17:20:00.806Z" }, + { url = "https://files.pythonhosted.org/packages/9f/f5/1092c5a3e34a09bbe11149bc9e19c6c23b82c7383ac61d2aef8bb205eda6/bitarray-3.8.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82a6574e98bdddfb7fdac4d41c1176e90e1fcaaed97fda39836a9e0d8b247ec3", size = 353442, upload-time = "2026-06-17T17:20:02.082Z" }, + { url = "https://files.pythonhosted.org/packages/f7/c0/99755ded6bcde8e577374722f1d14bf43d98a9ceb8bae07e5ad445ff10b8/bitarray-3.8.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9a34663e05bf79ccb92e931e720fbd281e84007ed996d38754aadfbc33e71c24", size = 363901, upload-time = "2026-06-17T17:20:03.418Z" }, + { url = "https://files.pythonhosted.org/packages/51/b3/312207693283b29d59c9a28ee662e6daa1d762a475dce21811929fb3bd77/bitarray-3.8.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:819f93a1aa7e711ccbb083647a8995bbb0da8f741c8b691576ff1bf5b5018c51", size = 331861, upload-time = "2026-06-17T17:20:04.69Z" }, + { url = "https://files.pythonhosted.org/packages/cc/70/83e0698a8d32322e0ed5c35eda339f85e5a828d8e30e24cbafcaa36e74d9/bitarray-3.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:07c20505dc8935b55d6de0bb1cc7e0e35de792d5f118d60b177dee53771a474f", size = 323169, upload-time = "2026-06-17T17:20:05.986Z" }, + { url = "https://files.pythonhosted.org/packages/28/55/c77597c5d5fab09a24b67b7e626d9de505d91fa03dac728d153663ab8149/bitarray-3.8.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:874c6806c2c7b861da0f0e9eead173bb3b9b7a62fcfadc01be51c32d50d7f71c", size = 351476, upload-time = "2026-06-17T17:20:07.249Z" }, + { url = "https://files.pythonhosted.org/packages/b6/17/fff630b5584985f9f203f89eb16f50a860e5198265eb94e6f4c3af482c96/bitarray-3.8.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4403e5b4da88ec195afe3eab5969b34358157d196e1c63e93328e64e632abbed", size = 347982, upload-time = "2026-06-17T17:20:08.616Z" }, + { url = "https://files.pythonhosted.org/packages/39/60/7e0c8c84d25251a93a0f56419738a914efe3134923e17f8ead6dbbb336a0/bitarray-3.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8a23e06e87cfa2ba361040eae87479ac197502ba10533c0f2de03d3d93cce91b", size = 328606, upload-time = "2026-06-17T17:20:09.741Z" }, + { url = "https://files.pythonhosted.org/packages/c6/15/77d9d43e478f2bf9fc84ce2414b845a97369ebfb46d1a3c3e8da72cb4e5a/bitarray-3.8.2-cp310-cp310-win32.whl", hash = "sha256:e65b91b68aa072732d144fa11d86518324b8b27af7e2474bd7a50c88648dc5d4", size = 143238, upload-time = "2026-06-17T17:20:10.924Z" }, + { url = "https://files.pythonhosted.org/packages/18/8f/17808e4980e88ec314fb40404308d49b648e41092c19e2fb71d2a9e0d058/bitarray-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:156c6d964111e1c0029c5bb41148a73aa870ca10c03a03279b5597fa68ac6761", size = 149868, upload-time = "2026-06-17T17:20:11.981Z" }, + { url = "https://files.pythonhosted.org/packages/42/75/285f2c9315a6ca19fec9281737f2fb31a3401584ccf82e4d689f6142d266/bitarray-3.8.2-cp310-cp310-win_arm64.whl", hash = "sha256:1b7c6fd8755dda32bc83b171e0a0f625fea545bb6f8a70a7481244dc847b1c9e", size = 147722, upload-time = "2026-06-17T17:20:13.038Z" }, + { url = "https://files.pythonhosted.org/packages/48/85/c19b7928447d4259418b915857200f7a471920e88241d5a27083a4ceedb2/bitarray-3.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7540de3e7609693b208020cb3cb28cb16395eb915dff742bdcdd9909d475bf3d", size = 150025, upload-time = "2026-06-17T17:20:14.573Z" }, + { url = "https://files.pythonhosted.org/packages/27/a2/3faeec7783733b596f63b887eb29fd6abfda6937195a269dc1fc6236ac76/bitarray-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c073cd936904e520990339745a2d561ceabc9daa1cefcaf9592196a3355eb1cd", size = 146925, upload-time = "2026-06-17T17:20:15.747Z" }, + { url = "https://files.pythonhosted.org/packages/68/75/b8e778aaa9d184b1361560a96974d99400c43e70f389a17382951969165e/bitarray-3.8.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4c1c97c5712ad45c6c1427b70bb6524f40532e4a544ca2b7e0375ca61c09244", size = 333297, upload-time = "2026-06-17T17:20:16.851Z" }, + { url = "https://files.pythonhosted.org/packages/74/18/4c52fa2ec6dac3db01fd51ab2fdccba0a3e86b9b3eb9c76ab6e6e9190008/bitarray-3.8.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7627bfa750a609f5df05c1da337984b8f3821927591aaf861ba70f38bc5f6da1", size = 361658, upload-time = "2026-06-17T17:20:18.242Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ff/3e34aef8ad52ef63eb426dada698de6240cf45a99a6949b4678954e96814/bitarray-3.8.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ff06e0511682f117d0c24828f0ef1b4f2c3617d38984c7b3ce78d107bee016ab", size = 372260, upload-time = "2026-06-17T17:20:19.438Z" }, + { url = "https://files.pythonhosted.org/packages/f2/26/6a7e0f9254753b7c81ef3a7465533e7de0aa7da882aec6c19e993329d4d7/bitarray-3.8.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bcaeccab426b0a6e26c10bd8d8c21c15f81757320ad158a8c9e3e953ab81d223", size = 339446, upload-time = "2026-06-17T17:20:20.794Z" }, + { url = "https://files.pythonhosted.org/packages/37/2f/e866171e3b4ab8f12378d8fbd0d24944a12af623c130126b1e8d145deecc/bitarray-3.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:385045390630f5f433c89caeed9bca9f5b40e3986ae2d7e829e93098c1a96b94", size = 331180, upload-time = "2026-06-17T17:20:21.904Z" }, + { url = "https://files.pythonhosted.org/packages/be/ee/9371212756ab3e9c0f3247709ec3b341015ca8fc7d9de4a3a2f30c2b4439/bitarray-3.8.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:30541722bfa0f8213d8e621772bef538204fe9eeb4357f4261d404688c2281a5", size = 359108, upload-time = "2026-06-17T17:20:23.112Z" }, + { url = "https://files.pythonhosted.org/packages/75/4c/97d2ced53249890cbb6f16569da2fd4c73f767faf70bbbc03bd7329caa02/bitarray-3.8.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3daf8f1e040d48bf7ee664bd5c9df9d029c55780c671221d753f6f4fc769f10a", size = 356253, upload-time = "2026-06-17T17:20:24.447Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cc/68d2d511182c5cced2734086ca6b5b7fc778ce1babcfbe5e43d33fffde48/bitarray-3.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c223cf53e4a458b05b9f78723d88d5a1221fa11fb00cd1a696ccd483dcae3f8c", size = 336632, upload-time = "2026-06-17T17:20:25.786Z" }, + { url = "https://files.pythonhosted.org/packages/b6/b4/739981ea2ea25e8199c3f58e3ac6b52749d26f4999db5bf673dadabef83f/bitarray-3.8.2-cp311-cp311-win32.whl", hash = "sha256:d9367a5eb2a3dda6958a129ca939ce7dd1555a3b13967eb2e7c9dc8df2cdffa0", size = 143420, upload-time = "2026-06-17T17:20:26.906Z" }, + { url = "https://files.pythonhosted.org/packages/52/f1/841be2f5c3d1c79ab319eaf52871afb6616f8c7e6ef916517ef13b7e4c47/bitarray-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:2d0af077831aff8f44d8befe6459544bea1cd8fbce6b5b2a30ae1cb086a50620", size = 150060, upload-time = "2026-06-17T17:20:28.094Z" }, + { url = "https://files.pythonhosted.org/packages/82/de/5d275dcb5abc23ccf3139b478e304efc41d7bd7dc78901bfcc5ef3f251ff/bitarray-3.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:a78778a0899c682537ac612b1a03ecd4ad30063c118825d0138d0f7518270e54", size = 148006, upload-time = "2026-06-17T17:20:29.193Z" }, + { url = "https://files.pythonhosted.org/packages/52/20/53916ba8d01bc92e01d89c03cd7745107df48923de091b5f957578ff38ff/bitarray-3.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d5dcca2b64bbfce46dc43d77a2973d0b949e2260d74e8bd4e9a766de3afd0e70", size = 150156, upload-time = "2026-06-17T17:20:30.372Z" }, + { url = "https://files.pythonhosted.org/packages/18/a8/bfa7c8f4141b3119decc54ff6656b8e2f6d4303dc71577021f2d4b42cf42/bitarray-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c78dfbb8883133caeb11aa4ec375165ff1b456a28898cbe45536173369accb24", size = 146884, upload-time = "2026-06-17T17:20:31.615Z" }, + { url = "https://files.pythonhosted.org/packages/f5/60/fb0e9118dce7e1858fc4f608d0c13460207b227fc13819a23c6f3c70ec78/bitarray-3.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c32189234e4206c3832f947ebdf1735926dea0dbe0e966effd62771884dedf63", size = 336496, upload-time = "2026-06-17T17:20:32.944Z" }, + { url = "https://files.pythonhosted.org/packages/be/b5/8d50bb4d55113535919812adb66dcdb590a95a032d5975254d951146c2b4/bitarray-3.8.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:26490091d3ad8c039829b33ab1bc776941ce359ecdcf8beef3c1efc330fcf1a5", size = 364673, upload-time = "2026-06-17T17:20:34.394Z" }, + { url = "https://files.pythonhosted.org/packages/f2/c2/90ca21488fb0ac791a00b98c49c3dbab7ca1aca59e8745dabe073133370f/bitarray-3.8.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8ad858bd35dbb554de248c277ba9052f31d8e153c133195ef40c198303725dc8", size = 375966, upload-time = "2026-06-17T17:20:35.555Z" }, + { url = "https://files.pythonhosted.org/packages/3b/39/f414699060068ef15b886353e6ae6d2f476715e5c7db205b47710e5e7b4c/bitarray-3.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:58aeaf943929716b411a4ff24422c2b8bbf2c2d8ef3e23bbf08dc7d47c49e2ae", size = 343994, upload-time = "2026-06-17T17:20:37.24Z" }, + { url = "https://files.pythonhosted.org/packages/32/84/70a8ae25ba927f0b7656041c7cceea011296cbf6cc3770788bc331a5be88/bitarray-3.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b016d736e2b4aa8962962724b69893adce076622374cf4a275503049f5c7207", size = 334129, upload-time = "2026-06-17T17:20:38.476Z" }, + { url = "https://files.pythonhosted.org/packages/4e/20/3ec71a1e9a8cab12e7306cbfcf0f6e6ae7726f11ca4a7aa2bd047d8d105e/bitarray-3.8.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6871b2b1680580e54fbf0196b3ab7b40a417b4d1fdb3ebda0debf3948e9b8604", size = 361708, upload-time = "2026-06-17T17:20:40.302Z" }, + { url = "https://files.pythonhosted.org/packages/90/fc/6cae06eac8a25e5715f5607de6bae4bc3ec3b0634f790d5e22debab1802d/bitarray-3.8.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a4c6bb948d011bf18642e09a0a4d1dd067f0722db09d2d4b5d6cce292d71b448", size = 359888, upload-time = "2026-06-17T17:20:42.132Z" }, + { url = "https://files.pythonhosted.org/packages/c0/cc/078932ee7b41862571e8b3cfb7dc4e03af5c4843b8246a5a663af8678773/bitarray-3.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:78622f067a89360e8acf146be7878f62deafe687db40feb16dabfc808a20717c", size = 340969, upload-time = "2026-06-17T17:20:43.326Z" }, + { url = "https://files.pythonhosted.org/packages/f6/19/719edf77615864263a12351287832979b02a6277b4058ec6b53669ecbf7e/bitarray-3.8.2-cp312-cp312-win32.whl", hash = "sha256:75999de62a7c4686b901458d441bc3c6c03dade68d1dfbe808439e748d086ea3", size = 143759, upload-time = "2026-06-17T17:20:44.753Z" }, + { url = "https://files.pythonhosted.org/packages/e9/af/6806f09441de299ccd42b361c2e25138425457331c0e59aef23aba0e901e/bitarray-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:3e44247fcf5dffa86031d5412b20278a953e4dcef4033012c93ebd9985d48fec", size = 150393, upload-time = "2026-06-17T17:20:45.983Z" }, + { url = "https://files.pythonhosted.org/packages/99/e0/b9c738cfc16a59fcb4b17dd4f699d235257d2d3074e403892d4cd37ccc53/bitarray-3.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:f823fa67f074c0ede82014fd5c2020f301b88f351635f5ba7b802f53b5e0eade", size = 148168, upload-time = "2026-06-17T17:20:47.169Z" }, + { url = "https://files.pythonhosted.org/packages/48/99/01fb3b90cbf8a930d2326945df2b28a5f046380c0f966ea78cada00dae45/bitarray-3.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:71d7350c801eea43afb0a8679fd7475b0fd9868fd15352f0d3069f335b44af06", size = 150167, upload-time = "2026-06-17T17:20:48.408Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ce/b26a94753fcfd9e7652805a539df60a83085997319be81ef6d59192ad37c/bitarray-3.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa3be101ed71c4e4989899da744a926d1f55f5d5f7f93242c32f727f7c11350b", size = 146882, upload-time = "2026-06-17T17:20:49.58Z" }, + { url = "https://files.pythonhosted.org/packages/a9/8e/0bdf36618f4f585d5c35cb033f6a5611337d873d8718feca41d27453cc54/bitarray-3.8.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f684eb138bae893a5d98c811d99ecd89fa4a1af4700b0e512b8e2b794c9cabd", size = 335677, upload-time = "2026-06-17T17:20:50.856Z" }, + { url = "https://files.pythonhosted.org/packages/cc/99/5588cbe69640d7fa2386be315ddb0e1bde6de8e922c025dccee769cc6d9e/bitarray-3.8.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:94e7da622b723705caddd59ee681cee0355b444901cc6fb2bcdc24bafba85911", size = 363773, upload-time = "2026-06-17T17:20:52.143Z" }, + { url = "https://files.pythonhosted.org/packages/80/4f/7d2946d88ae77306833bd5b91746d212404d5a86347341274b61d08c3f7e/bitarray-3.8.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3110786b00b28a756fd948c8d63e6ca3a74810b2d115582d85593d9d48035c49", size = 375005, upload-time = "2026-06-17T17:20:53.525Z" }, + { url = "https://files.pythonhosted.org/packages/fd/be/9a645b2e1bb0da4779dd9cab5a075d7c5bb68a16d8c90f051d47393bbcfe/bitarray-3.8.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd40cf27e2b54b5e30d0ce1da4f59bc16dd7c8363a20786b6e9deeb0b8ebe8e0", size = 343273, upload-time = "2026-06-17T17:20:54.938Z" }, + { url = "https://files.pythonhosted.org/packages/98/8d/73c658d200671c5e023225163be6aa545f675a676e960e5a4e19ac21274b/bitarray-3.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:24c6b97f27bd3868e28b201e1d777f5e168805862b7d9528099138bbb8c6a636", size = 333403, upload-time = "2026-06-17T17:20:56.533Z" }, + { url = "https://files.pythonhosted.org/packages/94/bc/819abd376bd6a892ce27840a1d5a4378be228be1ab3bca41845203ee672b/bitarray-3.8.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:786dedb4b1ced22dfeaaa89902561616f7edfa91774702b1aac31df3a6073c88", size = 360846, upload-time = "2026-06-17T17:20:57.862Z" }, + { url = "https://files.pythonhosted.org/packages/83/59/b8ea1e31928d06db1f2b12187631b51bb3c83186b18581754bc008cec0aa/bitarray-3.8.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:01bf9ff247117533c11963a81f3529bc12283c600dd195cf3b28a97b095f5d1c", size = 359168, upload-time = "2026-06-17T17:20:59.48Z" }, + { url = "https://files.pythonhosted.org/packages/6e/31/ef3b2f58517f7dbba8119f2592c1ea556a687bc8d405dd93c07f9c28d514/bitarray-3.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cc7a76e77c158e793d7c1e0b6c2240374087ac690a8bcacc8f18c427e5d9e20c", size = 340091, upload-time = "2026-06-17T17:21:01.183Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/bf92dcfec4eefd59fa4d8491504e100ae86e11b8cec353ae5532b25708e6/bitarray-3.8.2-cp313-cp313-win32.whl", hash = "sha256:db9add8dcc87154c0f011e0e1ce9b856e5948fbcf6faf44305aa140e525ec9a7", size = 143786, upload-time = "2026-06-17T17:21:02.43Z" }, + { url = "https://files.pythonhosted.org/packages/1c/29/1f57913a96bffb27bed486a9ca592021dd8161f6c95fd632aad7d4f0bb95/bitarray-3.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:cf4926098970d2d1a14156c0fbddb47554124347db4acf3ba616064fb021cd1e", size = 150414, upload-time = "2026-06-17T17:21:03.649Z" }, + { url = "https://files.pythonhosted.org/packages/17/9c/f36b91fcb93af54c9a28e3bd1fbf39ef7706fc623a526f3450113c0a0dae/bitarray-3.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:5c8281d0eb35e8685235e1d50f9b26156803dad398d0e7868ce9aae254c3777d", size = 148197, upload-time = "2026-06-17T17:21:04.892Z" }, + { url = "https://files.pythonhosted.org/packages/c6/86/aa2f29699763f4867359289a946ff3597d45239470c20f6ccb8dba48e7af/bitarray-3.8.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cbe96e7384e36963a2cdf5bc4ac9d0a78ae0d87fc78c53159cd5ac08c661ff34", size = 150139, upload-time = "2026-06-17T17:21:06.258Z" }, + { url = "https://files.pythonhosted.org/packages/56/1f/0d759c53a7129e4979c3c03b3f2372291c4c5a1cc851d9e749273b34ddf8/bitarray-3.8.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8b4fcecbbd0969988cc115bee74119c767636e48606fad318361eb9fe40a13c6", size = 146888, upload-time = "2026-06-17T17:21:07.515Z" }, + { url = "https://files.pythonhosted.org/packages/49/2e/0611d057e6cb010ccaf55ec6630ef41d3e7546a285383dfa2a99f545e440/bitarray-3.8.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48798fc274e8a0329ca75185a0dc1e0a93ff627ea8f30c339bdf0a2ef26b1723", size = 335581, upload-time = "2026-06-17T17:21:08.808Z" }, + { url = "https://files.pythonhosted.org/packages/11/0d/201befb06fbb6275046ffe2d21cbe3b059e4f5c6b258da6e6b41f53dd9af/bitarray-3.8.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4205ae045129e58e7b7a9abe929ea0b9a3c63fad39d760e6e3b90062b6e5aa5", size = 363929, upload-time = "2026-06-17T17:21:10.225Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3c/2639aaa97eb81cabc453f78277493ea31ff49b3514e17eca56129d613279/bitarray-3.8.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:49c16cdedbd3c4d6bf64aca7b370ea02456e9be030201e80c282d8df6af36d19", size = 374562, upload-time = "2026-06-17T17:21:11.771Z" }, + { url = "https://files.pythonhosted.org/packages/52/1d/f11ba5b55f6a0f0007985f435c0e32c7a3459775cdee308cfb5938628670/bitarray-3.8.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5cad241cd0ceb79a0e4f76e86b36660c22d36c32efb364badcf7609ed5a9e5c", size = 343166, upload-time = "2026-06-17T17:21:13.101Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b9/2f8f62e1cd42f60f20ca55ed3de57ff2295b85a70eff119501ae2f0e8c48/bitarray-3.8.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3b44650aba323cb1c2285c310ffa6b1adfd5293acecd7f84aaa91afa27c802c", size = 333564, upload-time = "2026-06-17T17:21:14.629Z" }, + { url = "https://files.pythonhosted.org/packages/22/de/1525e32e7663980b82098ae0c6e032823782b9190cabed6a1f09e67c7831/bitarray-3.8.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5fc8fa50c6a89b1e75edcea4ae17787a0a9b424cdbaa03485e73a837262eca27", size = 361034, upload-time = "2026-06-17T17:21:16.318Z" }, + { url = "https://files.pythonhosted.org/packages/df/55/7bfe6af3fa577f5132380209c3f3ec560149c0af4e540ce16d84f8b76599/bitarray-3.8.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5f246319a26221e36eaf3f6aed9cd98172f81e91740bbf5cdf31b4490ecfb87a", size = 358728, upload-time = "2026-06-17T17:21:17.598Z" }, + { url = "https://files.pythonhosted.org/packages/9d/c8/85898711f7b4cf5b06c49d8e36a6702a303f1990cb21cbb39dbe186730a0/bitarray-3.8.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e76c01ae0f191c5572c12b1fda333243bfe4d58ad1d601048f9e4928d94db0c5", size = 339747, upload-time = "2026-06-17T17:21:19.092Z" }, + { url = "https://files.pythonhosted.org/packages/5b/56/94cc5250be3d530c52d15e41bdbf5f891a492aeebb9e978914aa4559c00a/bitarray-3.8.2-cp314-cp314-win32.whl", hash = "sha256:a1df20419ccc23a0326ee0cb391d1c524ee3c338856e66528d73f4dcec0389d0", size = 142830, upload-time = "2026-06-17T17:21:20.347Z" }, + { url = "https://files.pythonhosted.org/packages/b4/eb/b9ba05ae59d56a9e5cb8e812072d33be38076717db6579302e1ee85fd688/bitarray-3.8.2-cp314-cp314-win_amd64.whl", hash = "sha256:4bfbeba9156834455ab107936ebd461728f1ed35ded8f15aafde2c3dac9badf5", size = 148912, upload-time = "2026-06-17T17:21:21.556Z" }, + { url = "https://files.pythonhosted.org/packages/b6/07/e279a5ba7cd114398f00d853026e6c72e198035b925c74866e3c1973daca/bitarray-3.8.2-cp314-cp314-win_arm64.whl", hash = "sha256:4149aeb7c8cad12f9ea13783550ab5508e6d553eeefead5e3da659ce6724c5a5", size = 147373, upload-time = "2026-06-17T17:21:23.051Z" }, + { url = "https://files.pythonhosted.org/packages/94/a4/4014952965ef7edf80076f8004df31484bccecba97af7b3e9c99269a053d/bitarray-3.8.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f6f6cf5ec3be7e1bd32bfe1f4b24f7d1de28d72394d7f58789b9f9042d19f5f6", size = 151073, upload-time = "2026-06-17T17:21:24.285Z" }, + { url = "https://files.pythonhosted.org/packages/ff/00/850095c3bc551797c97a4b54c7755fc46eb115ce288fcf6962d8e8c5b678/bitarray-3.8.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2b9790847024cf1de275c8b2495331fe0982d099e407be1c1413ed40ddf2b5d", size = 148009, upload-time = "2026-06-17T17:21:25.595Z" }, + { url = "https://files.pythonhosted.org/packages/dd/4d/74f0440d95d00f086a80e6c429e3333ebb29cecf55a8d401ceb0c65a3b4b/bitarray-3.8.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c172161b8847f91e9f9ea9ae2e31fcfa784ec5d0cd413900c82574999e21ad05", size = 343487, upload-time = "2026-06-17T17:21:26.96Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/ea9c182ff0edb671853bb7a54b790572dc0b73d4a3b13e358f42aa34dca0/bitarray-3.8.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5fcc57961bc78885091a45b9ced5a5924b3b1fdd439a0e1d4b7e3aedf0c31ae2", size = 372305, upload-time = "2026-06-17T17:21:28.399Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ff/307cacc432e2ec304b870676189852c3f34a803d15b26f73bb36c549166b/bitarray-3.8.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b5fdb5399f0f2c42abcca87f8167d7ad746cf6ca7decadb4f5ad432280cc3a2f", size = 382242, upload-time = "2026-06-17T17:21:29.77Z" }, + { url = "https://files.pythonhosted.org/packages/b8/ae/757a10ce90e2090dd2dff8c5059a47439122a8d68f5fa9cf06ed07a1dc74/bitarray-3.8.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bb6195a2edafceee0e9ee12c13aad2162e9578d91a24e7c501c3bd4ab90511a", size = 348509, upload-time = "2026-06-17T17:21:31.195Z" }, + { url = "https://files.pythonhosted.org/packages/ef/d3/a035bb2c459e1f7bc86974fd43057aa8bb76466dd6bd75787d8eb9c534ed/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ce3b3dd599d4eca214f9c7fb7ac2343ccab41d91f3da7aa3b75ddbbea49ec2d5", size = 340539, upload-time = "2026-06-17T17:21:32.652Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6d/e7af02d167c227d143d208cd1c54d8e4f024d8d0bb59a0f2c38c32d56ad0/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:11cd9766ce95199bef5010ff63f73c880d9c0b6ba9c4c233aeeebc11ab1dfbb3", size = 369505, upload-time = "2026-06-17T17:21:34.115Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/29d0538ac245941127a25735d33f7b6658be6612c35115bcac60ef7c3c1c/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:7a4bbbad17d3db92615497302b74cf77504f821eb9585b7948d92093017d5e70", size = 365262, upload-time = "2026-06-17T17:21:35.829Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c8/2feabadbbc365e000821c7af82906e71366b29719329ef5709d64707fd4c/bitarray-3.8.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e715498f3dc9af954b9d0977470aa352cb3fe1c39e80c32f5ac4c0348e461f6d", size = 344014, upload-time = "2026-06-17T17:21:37.228Z" }, + { url = "https://files.pythonhosted.org/packages/6c/88/dc465cbfe5c74b7da8c19b9dc2565d8a4391fad418c48e1559a0267fd00b/bitarray-3.8.2-cp314-cp314t-win32.whl", hash = "sha256:c85569fb99cf9d4aa964d2dbba3c095c7580b4368f63f51252e85b939fcd0a2c", size = 143775, upload-time = "2026-06-17T17:21:38.789Z" }, + { url = "https://files.pythonhosted.org/packages/08/75/50f2ef697d8ce46ba0986830f2d1288bff883e7f4833590076956a073496/bitarray-3.8.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7de416b313fc8e8aa1e323b83d2ba86b7c84161f7ebbaf986bdab80f9d06a2fb", size = 149884, upload-time = "2026-06-17T17:21:40.315Z" }, + { url = "https://files.pythonhosted.org/packages/df/0e/6aa2133fffbac3efcb468c7c12163eff7bbe55b86a0d6a1c687ef57e2654/bitarray-3.8.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7199451493d34a5c62cb7c9077fcfd238499af4e0d13a32d33760afe73054135", size = 148321, upload-time = "2026-06-17T17:21:41.804Z" }, ] [[package]] name = "bittensor" -version = "11.0.2.dev0" +version = "11.0.3.dev0" source = { editable = "." } dependencies = [ { name = "bittensor-core" }, @@ -149,6 +150,7 @@ requires-dist = [ { name = "typing-extensions", marker = "python_full_version < '3.11'", specifier = ">=4.0.0" }, { name = "websockets", specifier = ">=14.1,<17" }, ] +provides-extras = ["evm", "cli"] [package.metadata.requires-dev] dev = [ @@ -163,170 +165,170 @@ dev = [ [[package]] name = "bittensor-core" -version = "0.1.2" +version = "0.1.3" source = { directory = "../bittensor-core-py" } [[package]] name = "ckzg" version = "2.1.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/44/fdb579a0d035a1e510511e3c3b9ca98ba2ea240a24f112b1882478bfc2ff/ckzg-2.1.7.tar.gz", hash = "sha256:a0c61c5fd573af0267bcb435ef0f499911289ceb05e863480779ea284a3bb928", size = 1127878 } +sdist = { url = "https://files.pythonhosted.org/packages/12/44/fdb579a0d035a1e510511e3c3b9ca98ba2ea240a24f112b1882478bfc2ff/ckzg-2.1.7.tar.gz", hash = "sha256:a0c61c5fd573af0267bcb435ef0f499911289ceb05e863480779ea284a3bb928", size = 1127878, upload-time = "2026-03-11T14:11:13.745Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/13/543f474f03dc293828abbfc8a2efed2c3bd5bb10c78d0b6527d4cc880140/ckzg-2.1.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:21fbb7f5689413994d224046c0c06cb8385fb8de33c5171b2c057151710cffed", size = 96363 }, - { url = "https://files.pythonhosted.org/packages/ca/6e/8fb39b7aa945da20652e9ca5f44a2186a3b65564b106bacaf8b9fdf317df/ckzg-2.1.7-cp310-cp310-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:83f56b03c54fd9a610aeefd9fd241bb2af960cb703f208c7806b37ccc9fb7fb8", size = 179526 }, - { url = "https://files.pythonhosted.org/packages/15/4c/47e3865ffe4ae97232b67c4757b8a633f73465955d819e9d82ceb75029d7/ckzg-2.1.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8bfa41d97ee31a2053d0b2f2a53793f67745bfa694f48b6d091ae499a04c272f", size = 165238 }, - { url = "https://files.pythonhosted.org/packages/33/0f/8c809f835702a1f0c519ff35d9085783155ba44f921704fd5869b499ccc6/ckzg-2.1.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:244acf422fb727dbc376a082f71d66f6f2787b570ec27d17d20c3c3b85aef6fb", size = 174946 }, - { url = "https://files.pythonhosted.org/packages/77/e6/e61ba4caa703a84a9535c10c78180cec0c39279fd21361931dc147dab96a/ckzg-2.1.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8705f73a7efe0f01b8ce67677320be99c7d7c7077311d255bbf2d4e55fdc6a9b", size = 172853 }, - { url = "https://files.pythonhosted.org/packages/a1/c0/b76384bf8716acb7115a6a032c7e3362cb0466dd93a7567bde5c17a5b9b2/ckzg-2.1.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c6b29572b2a4f678991a1edc2426f1802e9190eb763510cf1e9bafe797f004ba", size = 187908 }, - { url = "https://files.pythonhosted.org/packages/51/32/86f473ee8b6cb9f7ffdf0007ee54fc30431d9bdf79f10240d6af2b4ab0f9/ckzg-2.1.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6ce04e32c1c459afae80edd32304956340a1dc5464a9f732f115f1119e3ec51d", size = 182481 }, - { url = "https://files.pythonhosted.org/packages/3b/59/bdbd795e51402e654652693cbaa44573b7bc2b91cb9a662b7575d46bc5aa/ckzg-2.1.7-cp310-cp310-win_amd64.whl", hash = "sha256:f537529bebfc58de21a6326100ad33e7d7ee98b0d49e44ee7f53d17ef899dfd5", size = 99827 }, - { url = "https://files.pythonhosted.org/packages/78/f1/aa4fac509f986ada4718517a2d167b7ce7efae9624c0f7f71c113c4debbd/ckzg-2.1.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c9172f571ac7ec6d90207ad1903d921c38e48482bc028f723d6908720af1add6", size = 96366 }, - { url = "https://files.pythonhosted.org/packages/96/c6/30cdc5b43928221c67b3853c10c54a21c525802a10af23cbfc188f6ad2d8/ckzg-2.1.7-cp311-cp311-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:c5494f39edeffedfa085fe85614a1c05ddd895ceb9d6c1800dc5355f9132a8f9", size = 180266 }, - { url = "https://files.pythonhosted.org/packages/e5/97/86f6030cb6daff6d87b8d0c2a666f09360b5b179fdc3507bcc60ef26318e/ckzg-2.1.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb67250207b93d2df7f694bb74bd6b4a15fb2bb67d6a78977ae8ff431678c7e7", size = 165983 }, - { url = "https://files.pythonhosted.org/packages/19/85/547814b4c6a09ebd27af9f682b7066c5c4569acd4fea74841cfe8964e5ab/ckzg-2.1.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7828cb549e2e8368e966c9dab87f3a51456647f1a3e79bdac9194e17bbc4d54", size = 175698 }, - { url = "https://files.pythonhosted.org/packages/30/a0/890e33ac991222aaa919a092e0de397e59df75baa92ec17f89370062863d/ckzg-2.1.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23eacac20c6d3be2c87e592c11d02e4a1912e799d77e2559502455e85113e7b4", size = 173516 }, - { url = "https://files.pythonhosted.org/packages/a8/71/ec6f713fb1056a647d4a7fad4ced15faedcd5d7b2a6f34ece81a9d1dbdd8/ckzg-2.1.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dd2afdc41f063e57eb569034b81088ba724240d3247ca78ea6591a1e04df50d", size = 188621 }, - { url = "https://files.pythonhosted.org/packages/d8/86/04572a67546e66b809946a7234cac0e3aa67bfa4a256d8440eefb1deaf87/ckzg-2.1.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b3af91c230982d59afe6f42c9c2a4c74412424a566bd09a42ffdfb451872335a", size = 183257 }, - { url = "https://files.pythonhosted.org/packages/da/c1/3060e997955e61699e4f6a431ff3cd3f780cd8ccfab0a2e0462848680185/ckzg-2.1.7-cp311-cp311-win_amd64.whl", hash = "sha256:f959a3bbc6d7aa7a653946e67dadaa78c0c79828aaa93b125a26f171a602b8fa", size = 99823 }, - { url = "https://files.pythonhosted.org/packages/09/40/8c2d610066a2efd4048553ff12aa832c916822ec9c888ca924565e520a7b/ckzg-2.1.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:126050ffb23b504c34c4c2073c54bd8b42f4a3034798a631c9e85911e26caf47", size = 96386 }, - { url = "https://files.pythonhosted.org/packages/29/b6/092bd10eb35e9fe3d316410791d9055039c5dd29caf03c72cc86fce45624/ckzg-2.1.7-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:936b4bffc1a6fa2bf261eb5e673f4fcc59feaf70c6c07aac1b02e3e1f942fdb6", size = 180447 }, - { url = "https://files.pythonhosted.org/packages/53/7e/f1c15ec078bee7660a2cafa103c4efdf9686256a348565ef6a1cb70ff1c4/ckzg-2.1.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:902c03b689d13684cd8b61c8e1b7a65528fdd5e1ab9d76338ddb2e902b5fd1ea", size = 166242 }, - { url = "https://files.pythonhosted.org/packages/bf/de/c22535e16163a836f76d7c3606a6e579a7a02862b4797b832cd6de5f6a1d/ckzg-2.1.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e635e5e1f6ff8ffc05d2961ccfc4b3e8c95e50c87d9765b2dfe09e32474c402", size = 176015 }, - { url = "https://files.pythonhosted.org/packages/af/4f/56c303eab20d92e5d140f96881c8c7e2eaa05976d6cb887ab574d780d09d/ckzg-2.1.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cbedb5e4732d37c87fe45a2b25891d00f434d4e0f4dd612daa034fe2011e5939", size = 173682 }, - { url = "https://files.pythonhosted.org/packages/85/0a/0feb878383e9c83d6dcd760b8de2f3095546cc09b1717ae65cbb47f90b20/ckzg-2.1.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:665d0094466b576e390b4a5e1caf199f1165841e99bf7b3cc65117f12ba4ea74", size = 188873 }, - { url = "https://files.pythonhosted.org/packages/48/29/c2eb07882465c32478e575334311ad6cea21c5d76d54da6c900dd6cb8e62/ckzg-2.1.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f5d4d1fb20eda15b901fc393a4bfd39b1be661008218f9f0db47d4e143d25d62", size = 183566 }, - { url = "https://files.pythonhosted.org/packages/c8/48/4d1f5c470cc6eb73aaba30125e6fb62759ce69bbdb2a74c160f69f601236/ckzg-2.1.7-cp312-cp312-win_amd64.whl", hash = "sha256:b580f65e61f3d89a99bfeeac0e256cf68c63d29df1c1e5e788785085083a303b", size = 99811 }, - { url = "https://files.pythonhosted.org/packages/87/32/495600f43a277bcb413d08f23f594dc548ac0d7927ad1ce7db28e58afadd/ckzg-2.1.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e23e10b227209bfae11f6f1f88ff2a8b0a2232248f985321e5e844c9dd7a4c5f", size = 96394 }, - { url = "https://files.pythonhosted.org/packages/e4/fe/c3708cfdbc228298c0f5fa4d08ceee7cc01cb7f7d105bfc9ebc68c39060d/ckzg-2.1.7-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:382c015860e7159b1ec5a85642127d4b55f6b36eef5f73d664fc409d26a3b367", size = 180484 }, - { url = "https://files.pythonhosted.org/packages/28/55/d689769ea0f9b2c2c16d8390f4c3cf7cd7dea0df68542b2a435c341df0b0/ckzg-2.1.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6666801e925d2f1d7c045fe943c1265c39b90444f88288735cc1245c4fa8018a", size = 166301 }, - { url = "https://files.pythonhosted.org/packages/16/ff/e172b4ae4bef05bf88bb8f27d2b9858b56c9984ad1708eeef82ac787fe7c/ckzg-2.1.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e823de2fd4103abc4b51512d27aa3e14107e84718e11a596eefcddc6f313b25", size = 176052 }, - { url = "https://files.pythonhosted.org/packages/61/0a/dcf28e0126e5a6f8f8b7505b4b5b637ca25e1095272fbee73f8967e3a545/ckzg-2.1.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a65c7be0bb72a159c5a4b98cc3c759b868274697de11d8248f5dde32f2400776", size = 173691 }, - { url = "https://files.pythonhosted.org/packages/2a/d2/fe404ad0bd79aaeb1e75fb4981d21e37364e59517813f7f085914026a7f6/ckzg-2.1.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62523b275f74f2729fc788d02b26e447dabfd7706ffe8882ee96d776db54b920", size = 188909 }, - { url = "https://files.pythonhosted.org/packages/55/d7/ef2d30c88270ab1a0daffa8a0f8453b72035569d3295ad3dcaba9b5250a6/ckzg-2.1.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5d998cd6d0f8e37e969c96315ac8c1e87fcf581cf27ab970bd33e62dc1c43357", size = 183597 }, - { url = "https://files.pythonhosted.org/packages/93/77/1e04840c866284bec3489154caec22855829b0c2d028bd1de771655175e3/ckzg-2.1.7-cp313-cp313-win_amd64.whl", hash = "sha256:d48b75fca9e928b2ea288fc079b0522fb91af5742b5eb4f2fdea4fc33a1b7b4e", size = 99808 }, - { url = "https://files.pythonhosted.org/packages/24/ab/11eb63c520cae074195b05cd644bf45be061b910b5c97abdaae02876a50e/ckzg-2.1.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c19b98f29f4459587e1ec4cce3e2e10963a6974293cf3143d13ce43c30542806", size = 96400 }, - { url = "https://files.pythonhosted.org/packages/31/7d/3678cbb22f31a50dd354b9d3efcb9366dd5b97cdddbf270213a66b03ad41/ckzg-2.1.7-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:d31583a24cf8166d81c36f1e424de1f343c1d604dbc8c68d938a908236ae11a3", size = 180492 }, - { url = "https://files.pythonhosted.org/packages/48/a5/355f898c75e19ac6426798c28a9767bdc734bebb40c4cd15572f644745ba/ckzg-2.1.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:baf6ac696e6a40b33ddb57aa0729d5e39230bd13fa4f1e40fe9236e8920d83fe", size = 166322 }, - { url = "https://files.pythonhosted.org/packages/ff/f5/7ffc482dc628c43d9c7a1b19392e1a920ccfd1da8d2e07d7dcc79c3e3bd2/ckzg-2.1.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bbdf89f9327e442415a810beca692729c35664e154a6830296124a5c6f05470", size = 176061 }, - { url = "https://files.pythonhosted.org/packages/26/56/f79ee2a177b4522fe47709e9f7e48407cd54a63c3d7bc1ca3002c705b3a7/ckzg-2.1.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:716c2dde0a91c0095797b843f78a6425e20a3d8945ecb4f90550b5c681b6be05", size = 173746 }, - { url = "https://files.pythonhosted.org/packages/b9/a7/95b160707b22161817245de8b9e44ea143b9a2083b0c625e5e5cd4a2e20a/ckzg-2.1.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2a9f1a05ed44512b80581e47918b1f4546974e8e924ee0e8de84ab32de197326", size = 188923 }, - { url = "https://files.pythonhosted.org/packages/33/d4/ecfbecf763d42606dba8ab9d7de557d01816afad1e2f3cb1cc7efd6fc254/ckzg-2.1.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:42005c188e37c2f65d44f3a2585e89de18e0e229bc667a600d8716808ea2c33b", size = 183607 }, - { url = "https://files.pythonhosted.org/packages/4a/72/becb801d8f1224de265f299790f5b2c95e71546ab7ab24a1fd3ebb99519e/ckzg-2.1.7-cp314-cp314-win_amd64.whl", hash = "sha256:14fbc642b1e81893df76a1636fddc169173da5dcdb55fc08a030658cd186150e", size = 102517 }, - { url = "https://files.pythonhosted.org/packages/a8/6c/b310f05a6a27baaa53915b43483cc061080e3245c7facaa3c5b3a3cd7c5e/ckzg-2.1.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:da1a07e25ecaeb341ad4caf583fdec12c6af1ef3642289bb7dfcad2ca1b73dd3", size = 96609 }, - { url = "https://files.pythonhosted.org/packages/0d/96/e1ccbf3f90595d50aa98a8a9c3c1327e6be0575ddbf8292b26b0cfa69b06/ckzg-2.1.7-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:c657892f93eb70e3295b4f385e25380644c40f8bfebfcd55659f5017257c5b8c", size = 183315 }, - { url = "https://files.pythonhosted.org/packages/bc/94/2c7ff1983f82756b29011ad612bc0e1d8f4a1989073c94fd66868bc296d3/ckzg-2.1.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03af4cf053be82c22a893c8ef971d17687182dd2e75bcc2fab320bc27a62b7cb", size = 169457 }, - { url = "https://files.pythonhosted.org/packages/98/cd/8c7247181843185ff5e34ebd400594e0fbe2d81e03324f124834f377ea74/ckzg-2.1.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ecd9c44427a0035a8a9cb3dc18b4b3c72347f7be7c9f6866b8eddd6598bf0a9", size = 178841 }, - { url = "https://files.pythonhosted.org/packages/da/cb/cf2ed4cf461bd2891792317615075745053e2585d8a2cf26a8414ad01983/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:16e313e6029e88a564724217dd8eddd6226fbf0a0c07bf65a210bf3512c7b8ad", size = 176489 }, - { url = "https://files.pythonhosted.org/packages/50/65/8b7d9cf8883f0df1a15cb20ecec99dfc02fc7bf05bf53509bb270e3a1db0/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8461ec7d69ccb450d4a4d031494a86dc6c15ad54b671967d4a8bdcd8158155b2", size = 191690 }, - { url = "https://files.pythonhosted.org/packages/83/56/a1fba1b4a2f90d5fc48d3e62f59f0791c90e85b6ebb600ffeee81ea9cfa6/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:53f420a3fa55a92265e23394caa2aac5b0e1e63ee6489d414cafeb0accde9a9e", size = 186204 }, - { url = "https://files.pythonhosted.org/packages/c7/a9/a3284a64216f31a886ff216621c6b3806ca7ad7388908f68fcab9007c881/ckzg-2.1.7-cp314-cp314t-win_amd64.whl", hash = "sha256:2cdcc023d842900564d6070e397cab0d04fd393e6af07d60bdd1c97dc3ff09fd", size = 102660 }, + { url = "https://files.pythonhosted.org/packages/e4/13/543f474f03dc293828abbfc8a2efed2c3bd5bb10c78d0b6527d4cc880140/ckzg-2.1.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:21fbb7f5689413994d224046c0c06cb8385fb8de33c5171b2c057151710cffed", size = 96363, upload-time = "2026-03-11T14:10:06.585Z" }, + { url = "https://files.pythonhosted.org/packages/ca/6e/8fb39b7aa945da20652e9ca5f44a2186a3b65564b106bacaf8b9fdf317df/ckzg-2.1.7-cp310-cp310-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:83f56b03c54fd9a610aeefd9fd241bb2af960cb703f208c7806b37ccc9fb7fb8", size = 179526, upload-time = "2026-03-11T14:10:07.936Z" }, + { url = "https://files.pythonhosted.org/packages/15/4c/47e3865ffe4ae97232b67c4757b8a633f73465955d819e9d82ceb75029d7/ckzg-2.1.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8bfa41d97ee31a2053d0b2f2a53793f67745bfa694f48b6d091ae499a04c272f", size = 165238, upload-time = "2026-03-11T14:10:09.031Z" }, + { url = "https://files.pythonhosted.org/packages/33/0f/8c809f835702a1f0c519ff35d9085783155ba44f921704fd5869b499ccc6/ckzg-2.1.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:244acf422fb727dbc376a082f71d66f6f2787b570ec27d17d20c3c3b85aef6fb", size = 174946, upload-time = "2026-03-11T14:10:10.096Z" }, + { url = "https://files.pythonhosted.org/packages/77/e6/e61ba4caa703a84a9535c10c78180cec0c39279fd21361931dc147dab96a/ckzg-2.1.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8705f73a7efe0f01b8ce67677320be99c7d7c7077311d255bbf2d4e55fdc6a9b", size = 172853, upload-time = "2026-03-11T14:10:11.048Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c0/b76384bf8716acb7115a6a032c7e3362cb0466dd93a7567bde5c17a5b9b2/ckzg-2.1.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c6b29572b2a4f678991a1edc2426f1802e9190eb763510cf1e9bafe797f004ba", size = 187908, upload-time = "2026-03-11T14:10:12.018Z" }, + { url = "https://files.pythonhosted.org/packages/51/32/86f473ee8b6cb9f7ffdf0007ee54fc30431d9bdf79f10240d6af2b4ab0f9/ckzg-2.1.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6ce04e32c1c459afae80edd32304956340a1dc5464a9f732f115f1119e3ec51d", size = 182481, upload-time = "2026-03-11T14:10:13.013Z" }, + { url = "https://files.pythonhosted.org/packages/3b/59/bdbd795e51402e654652693cbaa44573b7bc2b91cb9a662b7575d46bc5aa/ckzg-2.1.7-cp310-cp310-win_amd64.whl", hash = "sha256:f537529bebfc58de21a6326100ad33e7d7ee98b0d49e44ee7f53d17ef899dfd5", size = 99827, upload-time = "2026-03-11T14:10:14.224Z" }, + { url = "https://files.pythonhosted.org/packages/78/f1/aa4fac509f986ada4718517a2d167b7ce7efae9624c0f7f71c113c4debbd/ckzg-2.1.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c9172f571ac7ec6d90207ad1903d921c38e48482bc028f723d6908720af1add6", size = 96366, upload-time = "2026-03-11T14:10:15.098Z" }, + { url = "https://files.pythonhosted.org/packages/96/c6/30cdc5b43928221c67b3853c10c54a21c525802a10af23cbfc188f6ad2d8/ckzg-2.1.7-cp311-cp311-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:c5494f39edeffedfa085fe85614a1c05ddd895ceb9d6c1800dc5355f9132a8f9", size = 180266, upload-time = "2026-03-11T14:10:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/e5/97/86f6030cb6daff6d87b8d0c2a666f09360b5b179fdc3507bcc60ef26318e/ckzg-2.1.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb67250207b93d2df7f694bb74bd6b4a15fb2bb67d6a78977ae8ff431678c7e7", size = 165983, upload-time = "2026-03-11T14:10:17.407Z" }, + { url = "https://files.pythonhosted.org/packages/19/85/547814b4c6a09ebd27af9f682b7066c5c4569acd4fea74841cfe8964e5ab/ckzg-2.1.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7828cb549e2e8368e966c9dab87f3a51456647f1a3e79bdac9194e17bbc4d54", size = 175698, upload-time = "2026-03-11T14:10:18.35Z" }, + { url = "https://files.pythonhosted.org/packages/30/a0/890e33ac991222aaa919a092e0de397e59df75baa92ec17f89370062863d/ckzg-2.1.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23eacac20c6d3be2c87e592c11d02e4a1912e799d77e2559502455e85113e7b4", size = 173516, upload-time = "2026-03-11T14:10:19.615Z" }, + { url = "https://files.pythonhosted.org/packages/a8/71/ec6f713fb1056a647d4a7fad4ced15faedcd5d7b2a6f34ece81a9d1dbdd8/ckzg-2.1.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4dd2afdc41f063e57eb569034b81088ba724240d3247ca78ea6591a1e04df50d", size = 188621, upload-time = "2026-03-11T14:10:20.865Z" }, + { url = "https://files.pythonhosted.org/packages/d8/86/04572a67546e66b809946a7234cac0e3aa67bfa4a256d8440eefb1deaf87/ckzg-2.1.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b3af91c230982d59afe6f42c9c2a4c74412424a566bd09a42ffdfb451872335a", size = 183257, upload-time = "2026-03-11T14:10:21.808Z" }, + { url = "https://files.pythonhosted.org/packages/da/c1/3060e997955e61699e4f6a431ff3cd3f780cd8ccfab0a2e0462848680185/ckzg-2.1.7-cp311-cp311-win_amd64.whl", hash = "sha256:f959a3bbc6d7aa7a653946e67dadaa78c0c79828aaa93b125a26f171a602b8fa", size = 99823, upload-time = "2026-03-11T14:10:22.674Z" }, + { url = "https://files.pythonhosted.org/packages/09/40/8c2d610066a2efd4048553ff12aa832c916822ec9c888ca924565e520a7b/ckzg-2.1.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:126050ffb23b504c34c4c2073c54bd8b42f4a3034798a631c9e85911e26caf47", size = 96386, upload-time = "2026-03-11T14:10:23.532Z" }, + { url = "https://files.pythonhosted.org/packages/29/b6/092bd10eb35e9fe3d316410791d9055039c5dd29caf03c72cc86fce45624/ckzg-2.1.7-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:936b4bffc1a6fa2bf261eb5e673f4fcc59feaf70c6c07aac1b02e3e1f942fdb6", size = 180447, upload-time = "2026-03-11T14:10:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/53/7e/f1c15ec078bee7660a2cafa103c4efdf9686256a348565ef6a1cb70ff1c4/ckzg-2.1.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:902c03b689d13684cd8b61c8e1b7a65528fdd5e1ab9d76338ddb2e902b5fd1ea", size = 166242, upload-time = "2026-03-11T14:10:25.671Z" }, + { url = "https://files.pythonhosted.org/packages/bf/de/c22535e16163a836f76d7c3606a6e579a7a02862b4797b832cd6de5f6a1d/ckzg-2.1.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e635e5e1f6ff8ffc05d2961ccfc4b3e8c95e50c87d9765b2dfe09e32474c402", size = 176015, upload-time = "2026-03-11T14:10:26.976Z" }, + { url = "https://files.pythonhosted.org/packages/af/4f/56c303eab20d92e5d140f96881c8c7e2eaa05976d6cb887ab574d780d09d/ckzg-2.1.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cbedb5e4732d37c87fe45a2b25891d00f434d4e0f4dd612daa034fe2011e5939", size = 173682, upload-time = "2026-03-11T14:10:27.857Z" }, + { url = "https://files.pythonhosted.org/packages/85/0a/0feb878383e9c83d6dcd760b8de2f3095546cc09b1717ae65cbb47f90b20/ckzg-2.1.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:665d0094466b576e390b4a5e1caf199f1165841e99bf7b3cc65117f12ba4ea74", size = 188873, upload-time = "2026-03-11T14:10:28.85Z" }, + { url = "https://files.pythonhosted.org/packages/48/29/c2eb07882465c32478e575334311ad6cea21c5d76d54da6c900dd6cb8e62/ckzg-2.1.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f5d4d1fb20eda15b901fc393a4bfd39b1be661008218f9f0db47d4e143d25d62", size = 183566, upload-time = "2026-03-11T14:10:29.777Z" }, + { url = "https://files.pythonhosted.org/packages/c8/48/4d1f5c470cc6eb73aaba30125e6fb62759ce69bbdb2a74c160f69f601236/ckzg-2.1.7-cp312-cp312-win_amd64.whl", hash = "sha256:b580f65e61f3d89a99bfeeac0e256cf68c63d29df1c1e5e788785085083a303b", size = 99811, upload-time = "2026-03-11T14:10:30.719Z" }, + { url = "https://files.pythonhosted.org/packages/87/32/495600f43a277bcb413d08f23f594dc548ac0d7927ad1ce7db28e58afadd/ckzg-2.1.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e23e10b227209bfae11f6f1f88ff2a8b0a2232248f985321e5e844c9dd7a4c5f", size = 96394, upload-time = "2026-03-11T14:10:31.535Z" }, + { url = "https://files.pythonhosted.org/packages/e4/fe/c3708cfdbc228298c0f5fa4d08ceee7cc01cb7f7d105bfc9ebc68c39060d/ckzg-2.1.7-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:382c015860e7159b1ec5a85642127d4b55f6b36eef5f73d664fc409d26a3b367", size = 180484, upload-time = "2026-03-11T14:10:32.418Z" }, + { url = "https://files.pythonhosted.org/packages/28/55/d689769ea0f9b2c2c16d8390f4c3cf7cd7dea0df68542b2a435c341df0b0/ckzg-2.1.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6666801e925d2f1d7c045fe943c1265c39b90444f88288735cc1245c4fa8018a", size = 166301, upload-time = "2026-03-11T14:10:33.363Z" }, + { url = "https://files.pythonhosted.org/packages/16/ff/e172b4ae4bef05bf88bb8f27d2b9858b56c9984ad1708eeef82ac787fe7c/ckzg-2.1.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e823de2fd4103abc4b51512d27aa3e14107e84718e11a596eefcddc6f313b25", size = 176052, upload-time = "2026-03-11T14:10:34.621Z" }, + { url = "https://files.pythonhosted.org/packages/61/0a/dcf28e0126e5a6f8f8b7505b4b5b637ca25e1095272fbee73f8967e3a545/ckzg-2.1.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a65c7be0bb72a159c5a4b98cc3c759b868274697de11d8248f5dde32f2400776", size = 173691, upload-time = "2026-03-11T14:10:35.577Z" }, + { url = "https://files.pythonhosted.org/packages/2a/d2/fe404ad0bd79aaeb1e75fb4981d21e37364e59517813f7f085914026a7f6/ckzg-2.1.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62523b275f74f2729fc788d02b26e447dabfd7706ffe8882ee96d776db54b920", size = 188909, upload-time = "2026-03-11T14:10:36.798Z" }, + { url = "https://files.pythonhosted.org/packages/55/d7/ef2d30c88270ab1a0daffa8a0f8453b72035569d3295ad3dcaba9b5250a6/ckzg-2.1.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5d998cd6d0f8e37e969c96315ac8c1e87fcf581cf27ab970bd33e62dc1c43357", size = 183597, upload-time = "2026-03-11T14:10:37.812Z" }, + { url = "https://files.pythonhosted.org/packages/93/77/1e04840c866284bec3489154caec22855829b0c2d028bd1de771655175e3/ckzg-2.1.7-cp313-cp313-win_amd64.whl", hash = "sha256:d48b75fca9e928b2ea288fc079b0522fb91af5742b5eb4f2fdea4fc33a1b7b4e", size = 99808, upload-time = "2026-03-11T14:10:38.701Z" }, + { url = "https://files.pythonhosted.org/packages/24/ab/11eb63c520cae074195b05cd644bf45be061b910b5c97abdaae02876a50e/ckzg-2.1.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c19b98f29f4459587e1ec4cce3e2e10963a6974293cf3143d13ce43c30542806", size = 96400, upload-time = "2026-03-11T14:10:39.59Z" }, + { url = "https://files.pythonhosted.org/packages/31/7d/3678cbb22f31a50dd354b9d3efcb9366dd5b97cdddbf270213a66b03ad41/ckzg-2.1.7-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:d31583a24cf8166d81c36f1e424de1f343c1d604dbc8c68d938a908236ae11a3", size = 180492, upload-time = "2026-03-11T14:10:40.766Z" }, + { url = "https://files.pythonhosted.org/packages/48/a5/355f898c75e19ac6426798c28a9767bdc734bebb40c4cd15572f644745ba/ckzg-2.1.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:baf6ac696e6a40b33ddb57aa0729d5e39230bd13fa4f1e40fe9236e8920d83fe", size = 166322, upload-time = "2026-03-11T14:10:41.752Z" }, + { url = "https://files.pythonhosted.org/packages/ff/f5/7ffc482dc628c43d9c7a1b19392e1a920ccfd1da8d2e07d7dcc79c3e3bd2/ckzg-2.1.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8bbdf89f9327e442415a810beca692729c35664e154a6830296124a5c6f05470", size = 176061, upload-time = "2026-03-11T14:10:42.649Z" }, + { url = "https://files.pythonhosted.org/packages/26/56/f79ee2a177b4522fe47709e9f7e48407cd54a63c3d7bc1ca3002c705b3a7/ckzg-2.1.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:716c2dde0a91c0095797b843f78a6425e20a3d8945ecb4f90550b5c681b6be05", size = 173746, upload-time = "2026-03-11T14:10:43.657Z" }, + { url = "https://files.pythonhosted.org/packages/b9/a7/95b160707b22161817245de8b9e44ea143b9a2083b0c625e5e5cd4a2e20a/ckzg-2.1.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2a9f1a05ed44512b80581e47918b1f4546974e8e924ee0e8de84ab32de197326", size = 188923, upload-time = "2026-03-11T14:10:44.635Z" }, + { url = "https://files.pythonhosted.org/packages/33/d4/ecfbecf763d42606dba8ab9d7de557d01816afad1e2f3cb1cc7efd6fc254/ckzg-2.1.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:42005c188e37c2f65d44f3a2585e89de18e0e229bc667a600d8716808ea2c33b", size = 183607, upload-time = "2026-03-11T14:10:45.846Z" }, + { url = "https://files.pythonhosted.org/packages/4a/72/becb801d8f1224de265f299790f5b2c95e71546ab7ab24a1fd3ebb99519e/ckzg-2.1.7-cp314-cp314-win_amd64.whl", hash = "sha256:14fbc642b1e81893df76a1636fddc169173da5dcdb55fc08a030658cd186150e", size = 102517, upload-time = "2026-03-11T14:10:47.079Z" }, + { url = "https://files.pythonhosted.org/packages/a8/6c/b310f05a6a27baaa53915b43483cc061080e3245c7facaa3c5b3a3cd7c5e/ckzg-2.1.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:da1a07e25ecaeb341ad4caf583fdec12c6af1ef3642289bb7dfcad2ca1b73dd3", size = 96609, upload-time = "2026-03-11T14:10:48.019Z" }, + { url = "https://files.pythonhosted.org/packages/0d/96/e1ccbf3f90595d50aa98a8a9c3c1327e6be0575ddbf8292b26b0cfa69b06/ckzg-2.1.7-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:c657892f93eb70e3295b4f385e25380644c40f8bfebfcd55659f5017257c5b8c", size = 183315, upload-time = "2026-03-11T14:10:49.224Z" }, + { url = "https://files.pythonhosted.org/packages/bc/94/2c7ff1983f82756b29011ad612bc0e1d8f4a1989073c94fd66868bc296d3/ckzg-2.1.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03af4cf053be82c22a893c8ef971d17687182dd2e75bcc2fab320bc27a62b7cb", size = 169457, upload-time = "2026-03-11T14:10:50.601Z" }, + { url = "https://files.pythonhosted.org/packages/98/cd/8c7247181843185ff5e34ebd400594e0fbe2d81e03324f124834f377ea74/ckzg-2.1.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ecd9c44427a0035a8a9cb3dc18b4b3c72347f7be7c9f6866b8eddd6598bf0a9", size = 178841, upload-time = "2026-03-11T14:10:51.598Z" }, + { url = "https://files.pythonhosted.org/packages/da/cb/cf2ed4cf461bd2891792317615075745053e2585d8a2cf26a8414ad01983/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:16e313e6029e88a564724217dd8eddd6226fbf0a0c07bf65a210bf3512c7b8ad", size = 176489, upload-time = "2026-03-11T14:10:52.905Z" }, + { url = "https://files.pythonhosted.org/packages/50/65/8b7d9cf8883f0df1a15cb20ecec99dfc02fc7bf05bf53509bb270e3a1db0/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8461ec7d69ccb450d4a4d031494a86dc6c15ad54b671967d4a8bdcd8158155b2", size = 191690, upload-time = "2026-03-11T14:10:53.855Z" }, + { url = "https://files.pythonhosted.org/packages/83/56/a1fba1b4a2f90d5fc48d3e62f59f0791c90e85b6ebb600ffeee81ea9cfa6/ckzg-2.1.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:53f420a3fa55a92265e23394caa2aac5b0e1e63ee6489d414cafeb0accde9a9e", size = 186204, upload-time = "2026-03-11T14:10:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a9/a3284a64216f31a886ff216621c6b3806ca7ad7388908f68fcab9007c881/ckzg-2.1.7-cp314-cp314t-win_amd64.whl", hash = "sha256:2cdcc023d842900564d6070e397cab0d04fd393e6af07d60bdd1c97dc3ff09fd", size = 102660, upload-time = "2026-03-11T14:10:55.974Z" }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] [[package]] name = "coverage" version = "7.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cc/8b/adeb62ea8951f13c4c7fef2e7a85e1a06b499c8d8237ea589d496029e53f/coverage-7.15.0.tar.gz", hash = "sha256:9ac3fe7a1435986463eaa8ee253ae2f2a268709ba4ae5c7dd1f52a05391ad78f", size = 925362 } +sdist = { url = "https://files.pythonhosted.org/packages/cc/8b/adeb62ea8951f13c4c7fef2e7a85e1a06b499c8d8237ea589d496029e53f/coverage-7.15.0.tar.gz", hash = "sha256:9ac3fe7a1435986463eaa8ee253ae2f2a268709ba4ae5c7dd1f52a05391ad78f", size = 925362, upload-time = "2026-07-02T13:10:50.535Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/97/c52dc440c390b6cfa87be9432b141a956e2d56d9b9f5fc8bd71c5f471722/coverage-7.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50913d4bf5ddafa6ca3693da5e4dd833dd1b772e0283c99ca7f7d287db67331a", size = 220539 }, - { url = "https://files.pythonhosted.org/packages/3f/26/602de8c2aec7e2e3e99ebfb8e04ba65598f746275396eea5f6794ff4673f/coverage-7.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:359e141ccd33893ce3f1ad5525f8b96083003677c82182e5907d62d4ea5799fc", size = 221058 }, - { url = "https://files.pythonhosted.org/packages/fc/13/ebab0743138891c1d646d61e247ec29639afcbb6c4e1905e6a0f0c75291a/coverage-7.15.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3200b6204935f928c64b2ca1f923ab8c1acb7c9de45ec61569711b34d25cccaf", size = 247797 }, - { url = "https://files.pythonhosted.org/packages/d3/b7/b6ffb9e042aa48dc4144a8a65529affaec8dca0685309353614a2a7386ad/coverage-7.15.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:be616bf61346883b2cfdc5178669647e03531d81ab761a7e378558b7e8bcb628", size = 249626 }, - { url = "https://files.pythonhosted.org/packages/9c/06/243ff05b652333d8e3d060c11223efc2723b19cacf6605e433fa686ab5d4/coverage-7.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7bafc3fe1059463a8fdd97ca79972d6e2bf819d775c7d54991b5b1971201d6", size = 251493 }, - { url = "https://files.pythonhosted.org/packages/d3/2b/867faa17030a806114dae388b32a3fa929d8cd4bf39226fbc11f6e6bb705/coverage-7.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b713aa7fcf325a01d4184d848acb46fd84f78fdb0978470c636b23a06a753d91", size = 253406 }, - { url = "https://files.pythonhosted.org/packages/94/c0/d789ce18f6605afc4895db75723424be2ef494282f77f61d8e5832923183/coverage-7.15.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e38e6fba2d56652fdfaf0231f8f78aeb805234a912de25dc291ee5cce5b8faa4", size = 248512 }, - { url = "https://files.pythonhosted.org/packages/c9/b6/b2673c30739f4a2e06649a0a38ad8b093c4d865462dc7bab0e9524a2c3b1/coverage-7.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:884499f42e382675be80770391983b90e0c0c774d87dbeeebf5f991cf6612b20", size = 249532 }, - { url = "https://files.pythonhosted.org/packages/3c/2e/acd79e9a41beabee92b623afe4f30b549916f48566271475f2907e752828/coverage-7.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:840481b12e083dbcbafab14794a8781a958edf327c8d3d70b4eee42f9b8253aa", size = 247537 }, - { url = "https://files.pythonhosted.org/packages/12/d4/2d301c4d1b3238d7c88b70ab9d13fd53ed9505662a7ff1b46ba1e2e4e3c3/coverage-7.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:276646e9481703d09f854f3b2f018f24e19fd7049ae670a92570043eb97203b1", size = 251348 }, - { url = "https://files.pythonhosted.org/packages/35/bb/c67708b2bc00f32e12805ec23d5fa677a0a51652f449341a89f9d6b1b715/coverage-7.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4de4b4d3f5545aa6c60dc4efd9c63b5b5dcc3bf00fe83146b2bdfffb8f6613bd", size = 247806 }, - { url = "https://files.pythonhosted.org/packages/eb/6c/57c4f653c47a6e917748f8938e389e72fbcae44e3643cd906664f0477a13/coverage-7.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5c504097b2a89b1e85bc6070d920df77daec701337e3aeef2c17775a5dd0ca90", size = 248410 }, - { url = "https://files.pythonhosted.org/packages/6c/94/bb083041aef828903668f134273f319f2bd49224962875359c52faa5497f/coverage-7.15.0-cp310-cp310-win32.whl", hash = "sha256:f6e80ed91f98316e86b9c137206b04b2bcfbffccbdff49bd2eb09dddb1cf14e0", size = 222588 }, - { url = "https://files.pythonhosted.org/packages/ef/94/a09d8ee618956f626741b0734854bac4425a00e10c0565f5abca64e7e751/coverage-7.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:b3b3e22030f3f6f5e01a5ce69936552a5c0f6992b7698777377b99041961031f", size = 223214 }, - { url = "https://files.pythonhosted.org/packages/ae/23/82e910835ef4b8391047025e1d53aa48d66029f444eb8b25373c849bf503/coverage-7.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:003fff99412ea848c0aaebcc78ed2b6ce7d8a1227ed17e68470672770b78a02a", size = 220662 }, - { url = "https://files.pythonhosted.org/packages/6d/0d/c7b213dde2f1579de5231062b386d8413f79c11667eb58c39319b25991da/coverage-7.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5cbd804bf2784ce7b45114516050f346ecd50f960c4bb630a7ee9e1d78fa2118", size = 221168 }, - { url = "https://files.pythonhosted.org/packages/33/77/d000aeedfac085088337b3c7becdad328474b1f8a9e4c9368a0c99605d68/coverage-7.15.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8773e15c23305b58882a4611fb9b2755977eae0dc2e515366a1b6c98866cc4c2", size = 251587 }, - { url = "https://files.pythonhosted.org/packages/cc/e0/86787c56b9df17afd370d5e293515dd4d9a107a561d13054873eefad8ecc/coverage-7.15.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f50e40081494c1dc4239ebb202014cbcc3306ea96fb6302a34c8cc0967fc5ae8", size = 253497 }, - { url = "https://files.pythonhosted.org/packages/3f/02/181bc917359299c07dead6270f94e411151c8b60cec905c33499da69afe6/coverage-7.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daf96f37f5fc3a7b6c6da862eb4aee61c426bd63da236ed4a73ef0e503b4bca5", size = 255607 }, - { url = "https://files.pythonhosted.org/packages/b9/35/ca5e7427699913da6788c4f910e73ab16c5f4b59ec5d3a999dce2a45112f/coverage-7.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:51aa20f6ae2788fd197747766edf4cd8234fd9423309b934257fa6b21a592723", size = 257563 }, - { url = "https://files.pythonhosted.org/packages/0b/4d/b8220bacc2fc3c4e9078e27c32e99fb411479a4718a72bdd00036a9891c8/coverage-7.15.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03d1f922757662eb7af586e77834792274cff776bc7b1d1a0b66a49ea9d84735", size = 251726 }, - { url = "https://files.pythonhosted.org/packages/c4/e4/2e145da1991d72189b9c3cf7eca05c716ee7080d099aaea6757cfc7df008/coverage-7.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a6d6acc9a7666245e6133dd15144ca038a85a9cd5026bb06d6bbae9e77440dc9", size = 253301 }, - { url = "https://files.pythonhosted.org/packages/72/28/d2c841d698bf762e481f08bd4839d370246b6d9b61dab085a7b20b201a08/coverage-7.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ac2c4c27c7df851dc9a017c2d7de00b69147e84ba3d96f37a530b0b6fb51035", size = 251361 }, - { url = "https://files.pythonhosted.org/packages/9d/ed/55d9ffde994fba3897c0c783f77a7d053b0c18787f6892ed5b0aed73f469/coverage-7.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b761a1d504fd4bd1f20f418753964dca9f5862a511fc854dac58296b3b223671", size = 255129 }, - { url = "https://files.pythonhosted.org/packages/1d/c0/ecbf33b8c460ea2718aeb813e2df8140d0370e5f67261c31524ceb0a2a8d/coverage-7.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e43b045e11c16e897895758ae90e4a90cf99e93d58549e2f90c0e2272e155695", size = 251081 }, - { url = "https://files.pythonhosted.org/packages/a9/de/fb87b4261f54448dd2b9504ef19a58be42cef0d9520595fbfe1219b15234/coverage-7.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589b54513e901739f4b4582c705ce96b80c96f57641b1464607e2367a270e540", size = 251988 }, - { url = "https://files.pythonhosted.org/packages/df/27/3494d5f291b9a4cb868f73c11221a8bd2d5bd761a8f9acea61ff57128dd1/coverage-7.15.0-cp311-cp311-win32.whl", hash = "sha256:106781b8482749162d0b47056937ba0933508e5d9447f65a5e7d5c422f0d6bb4", size = 222754 }, - { url = "https://files.pythonhosted.org/packages/2a/ee/cd4847ebc9be6a9c0123d763645a6f1f3be6b8c58c962706368b79cbac07/coverage-7.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:821e92b3631d762a339695824cadbbc73020354eba2a23a551a99ad34938fbe6", size = 223225 }, - { url = "https://files.pythonhosted.org/packages/57/37/5011581aa7f2be498b97dcc7c9902192442a42f4f9a748aeadb3d6506b42/coverage-7.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:309990eb5fb8014b9f67cb211f7fd41876ec8a88a88d3ae76de0ed1d611e3640", size = 222774 }, - { url = "https://files.pythonhosted.org/packages/2a/74/fd4c0901137c4f8d81a76ada99e43c65163b4c94a02ece107a4ec0c6b615/coverage-7.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b75ee5e8cb7575636ac598719b4307ac529ec8fcd79608a35c3cd4d4dada812d", size = 220838 }, - { url = "https://files.pythonhosted.org/packages/0f/2e/2347583467bd7f0402635101a916961915cc68fce652cd0db5f173ea04fc/coverage-7.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffb31267816b93b075302248cc1737506081b4f163df4401e9df1a6424aafabe", size = 221197 }, - { url = "https://files.pythonhosted.org/packages/f0/17/99fa688541ae1d6e84543a0e544f83de0c944815b63e9e7b1ed411d15036/coverage-7.15.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e4d0bb73455bf97ab243a8f12c37c686ccf1c13bb614b7b85f1d062f06f42b2c", size = 252705 }, - { url = "https://files.pythonhosted.org/packages/fb/02/6a95a5cd83b74839017ef9cf48d2d8c9ae60af919e17a3f336e6f9f1b7bd/coverage-7.15.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:20d9ccc4ebd0edc434d86dfd2a1dd2a8efa6b6b3073d0485a394fee86459ebb4", size = 255441 }, - { url = "https://files.pythonhosted.org/packages/67/f2/406f6c57d600f68185942422c4c00f1a3255d60aee6e5fd961425cd9987e/coverage-7.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c8a976c365c8cb12f0cbd099508772ea41fb5fa80657a8506df0e11bd278c5", size = 256556 }, - { url = "https://files.pythonhosted.org/packages/74/8e/d3fa48489c15ecdec1ba48fd61f68798555dddd2f6716f9ad42adeb1a2a9/coverage-7.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f948fd5ba1b9cbca91f0ae08b4c1ce2b139509149a435e2585d056d57d70bf01", size = 258815 }, - { url = "https://files.pythonhosted.org/packages/47/2e/2d40ddd110462c6a2769677cf7f1c119a52b45f568978fc6c98e4cc0dd0f/coverage-7.15.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f58185f06edf6ad68ec9fb155d63ef650c82f3fbd7e1770e2867751fb13158f4", size = 253117 }, - { url = "https://files.pythonhosted.org/packages/51/c0/310782f0d7c3cb2b5ac05ba8d205fe91f24a36f6bf3256098f1782181c38/coverage-7.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02adc79a920c73c647c5d117f55747df7f2de94571884758ce8bc58e04f0a796", size = 254475 }, - { url = "https://files.pythonhosted.org/packages/86/f7/702da6c275f8ae6ade423d2877243122932c9b27f5403003b9ef8c927d12/coverage-7.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6eb7c300fbed667fd6e3588eba71c1904cdb06110ca6fdf908c26bdd88b8e382", size = 252619 }, - { url = "https://files.pythonhosted.org/packages/fb/84/c5b15a7e5ecba4e56218d772d99fe80a63e63f8d11f12783723a6005ab45/coverage-7.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b5fb23fa2de9dce1f5c36c09066d8fcda16cd96e8e26686caa2d7cb9b567d65c", size = 256689 }, - { url = "https://files.pythonhosted.org/packages/95/2f/c8b07559b57701230c61b23a953858c052890c12ef568d81780c6c46e92e/coverage-7.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cec79341dbe6281484024979976d0c7f22beae08b4a254655decd25d42cbe766", size = 252189 }, - { url = "https://files.pythonhosted.org/packages/6b/80/6d2f049dd3fd3dbfd60b62ba6b2162a04009e2c002ce70b24cf3878dec7a/coverage-7.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c664c5444b1d970b1b2a450e21fb19ee5c9cfdf151ded2dda37260031cca0da", size = 254059 }, - { url = "https://files.pythonhosted.org/packages/ce/92/b0287a2c42031d25c628f815f89a3cd9f8268ee78bb1252c9356cda1c689/coverage-7.15.0-cp312-cp312-win32.whl", hash = "sha256:5f764a3fa339bde6b3aa97657f5a6a3a9451e4a5b4ea98a2892c773a43525f77", size = 222893 }, - { url = "https://files.pythonhosted.org/packages/a9/69/e34c481915fecb499b3146975061dac528752e37706edc1804f32c822469/coverage-7.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:52f9a4d2c4c56c8848bc2f524916698354b0211488b38c49ad9ae54f6cafbff6", size = 223429 }, - { url = "https://files.pythonhosted.org/packages/fe/98/6e878f0b571d32684ef3f38d7c03db241ca5b82a5da8a5391596a8f209c4/coverage-7.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:31e5c3e70c85307ea35a12964e2e40f56ca2ee4b1c8c721ccf4609d17071080b", size = 222810 }, - { url = "https://files.pythonhosted.org/packages/76/04/145a3748098bcc86b631a85408d2c3dc5c104e0bd86d605468239b25b6c4/coverage-7.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be4caf3b28836f078abe700f8944dac4a65d78f16d6c600c89cb624e5535782", size = 220863 }, - { url = "https://files.pythonhosted.org/packages/a4/5c/4ed55708fed2c64b63c9bc5715daef670872202101938869b7fe5d5fbb8f/coverage-7.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dd58ad1404704303ca8d4f4b8a1095e7cbc7040ef17a66df1e6619aa10176430", size = 221230 }, - { url = "https://files.pythonhosted.org/packages/7b/19/3a80b97d3b2a5c77a01ae359c6bed20c13738fe3d9380f08616d4fec0281/coverage-7.15.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bbcbb317c2e5ded5b21104af81c29f391be2af98d065693ffbe8d23949b948e5", size = 252227 }, - { url = "https://files.pythonhosted.org/packages/a1/fa/b70062750686bd7da454da27927622f48bbac6990ac7a4c4a4653e7b0036/coverage-7.15.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:27f31ecb458da3f859aab3f15ada871eb7a7768807d88df4a9f186bb17737970", size = 254823 }, - { url = "https://files.pythonhosted.org/packages/a9/09/dad6a75a2e561b9dc5086a8c5257a7591d584246f67e23e70d2995b89ab6/coverage-7.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fb759be317fdc62e0f56bffdf61cfcb45c7761ad6b71e3e583e71a67ae753c", size = 256059 }, - { url = "https://files.pythonhosted.org/packages/e6/e7/b5d2941fa9564573d44b693a871ff3156f0c42cbefe977a09fa7fdc59971/coverage-7.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5cf007add5ab4bb8fa9f4c77e3732127c9e6cad501d7db43355fbfafca0be84", size = 258190 }, - { url = "https://files.pythonhosted.org/packages/7c/1d/8e895bcde3c57ccd46d896dda5f2b3d5df761a1b0c6c9d450d175dedc632/coverage-7.15.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc78d9843bd576fbe2118248258d485e968dc535f95ed504a7b0867ba9b51389", size = 252456 }, - { url = "https://files.pythonhosted.org/packages/14/4c/f6997da343ddeb959be82c3b05322793f92c071ad45f7cb8a96336e2dd5f/coverage-7.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a263060f1de0b4b74b4e089c2a70b8003b3781c733329a9c8fd54995328f9950", size = 254192 }, - { url = "https://files.pythonhosted.org/packages/17/27/a0bc09d032267b9da89d95a2d874cfbef2a5aebbf0e87cf7aba221d79a99/coverage-7.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c48decf16e0dfd5b049c7d5e82200c23c08126719142998d4f172444e3d0529e", size = 252153 }, - { url = "https://files.pythonhosted.org/packages/54/c0/77fc233d9fba07b244c40948c53fe27308b8f21732fb3417f87fbd6fd992/coverage-7.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08fb028000ed0aaa0a4cbdfbb98be7cb42f370db973fbbb469733505ab20e13e", size = 256310 }, - { url = "https://files.pythonhosted.org/packages/d5/24/601cecfb5825becacb8d45219a018a3b55b9dbaec624efdb0ea249d08be2/coverage-7.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb7dc0c3b7d8a1077abea0b8546ebc5e26d6ef6ecefc2f0f5ad2b8a53bdad837", size = 251974 }, - { url = "https://files.pythonhosted.org/packages/47/1e/6f45e5a5b3d5484318d368702af6716b5ab8913b0428bec981a562fcf296/coverage-7.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cb3602054ccbe9f0d8c2dc04bbeba90d5719236e2cd06e042ddd6d3fc7b6e37", size = 253745 }, - { url = "https://files.pythonhosted.org/packages/8e/db/4df027a77bd11d0e527f44c53557c76e54ad027413d0304252ea3a78d67e/coverage-7.15.0-cp313-cp313-win32.whl", hash = "sha256:0bf781da64326b677be344df505171435b6f58716108606621d5d27d964fff8b", size = 222902 }, - { url = "https://files.pythonhosted.org/packages/a0/10/0355894d34e231f2c5449e71287e81a50793a325df2e2b027b7bcd9dfd19/coverage-7.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:2c57a275078ee3fa185f83e400f765bc764a549de66d99b47881645cbd4ea629", size = 223444 }, - { url = "https://files.pythonhosted.org/packages/06/ef/bb725f263befaaff851203ab338e68af15e195d7f7b5f323162532d9b6a8/coverage-7.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:3812c61afc6685c7999b39320779ab8f43b7a3081fdb0def39976e56fbdb9a21", size = 222839 }, - { url = "https://files.pythonhosted.org/packages/4f/9c/1e3ca54f72a3185ece06c58d871099898c48f0ed6430d17b6ab75f0d180a/coverage-7.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:41cb79af843222e11da87127ad0ecbfa878abadd0f770a4a99391a27d3887324", size = 220906 }, - { url = "https://files.pythonhosted.org/packages/09/37/f718613d83b274880382f6b67e78f3802549ae39b0b3e65ae5b5974df56e/coverage-7.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d2008989ef8fe54188d3f3bfa2e3099b025af11e90a6a1b9e7dc433d04263d8", size = 221239 }, - { url = "https://files.pythonhosted.org/packages/a7/ce/22bae91e0b75445f68d365c7643ed0aa4880bbf77450ee74ca65bdae53a7/coverage-7.15.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:769e8ece11a596315ebf5aa7ec383aeeed016c091d2bf6363ffb996d41529092", size = 252286 }, - { url = "https://files.pythonhosted.org/packages/dd/1e/bec5e32aa508615d9d7a2790effb25fb4dc28606e995816afe400b25ece3/coverage-7.15.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:65a6b6164ee5c39e2f3803f314292d6c61a607ba7fee253d1e03c42dc3903502", size = 254789 }, - { url = "https://files.pythonhosted.org/packages/17/29/0e865435b4354e4a7c03b1b7920046d31d0a273d55decefea27e011cb9bf/coverage-7.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75128817f95a5c45bb01d65fd2d8b9cb54bbe03d81608fb70e3e14b437ad56c2", size = 256135 }, - { url = "https://files.pythonhosted.org/packages/84/ff/33a870b58a13325d62fc0a6c8f01fa0ff667cef60c7498e2382a147dfa18/coverage-7.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9887bb428fe2d4cd4bee89bac1a6c9932f484afd5b36fbd4ff6ea5f825bb1f5e", size = 258449 }, - { url = "https://files.pythonhosted.org/packages/18/7b/6fffe596bf3ddba8462758d02c5dad730fd91055a6634aa2e4226229181a/coverage-7.15.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0bfc0be1f702042207a93a00523b1065ee1fe951e96edf311581c0bbc2e34888", size = 252313 }, - { url = "https://files.pythonhosted.org/packages/58/1b/11468dd6c1676ab831a70cb9a8d4e198e8607fa0b7220ab918b73fe9bfbd/coverage-7.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f64627d55def5a43282d70e08396672692f77e4da610a5bb8bb4060b432b6859", size = 254142 }, - { url = "https://files.pythonhosted.org/packages/79/41/29328e21d16b1b95092c30dd700e08cf915bd3734f836df8f3bdb0e8fa9f/coverage-7.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2c6f0fa473003905c6d5bac328ee4eba9fbea654f15bc24b8a3274b23363fa99", size = 252108 }, - { url = "https://files.pythonhosted.org/packages/9b/de/05ccfb990439655b35afbfd8e0d13fe66677565a7d4eb38c3f5ef2635e1c/coverage-7.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2bcf9afaf064172c6ec3c58a325a9957ad1178c05dd934e25f253321776e0676", size = 256385 }, - { url = "https://files.pythonhosted.org/packages/51/0e/486828a3d2695ea7a2609f17ff572f6b01905e608379440a11da4b8dffbe/coverage-7.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:baf06bc987115d6fb938d403f7eab684a057766c490367999a2b71a6883110c6", size = 251923 }, - { url = "https://files.pythonhosted.org/packages/18/c7/03582b6715f078e5e558354c87616d945b9894cda2dace8e4009b17035e4/coverage-7.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f0405f2ff97b1c4c0e782cb32e02f32369bcf2e6b618b591d67e1ea754575dfe", size = 253580 }, - { url = "https://files.pythonhosted.org/packages/db/dc/9e578bbaf2ecb4959a81b7e7601ad8cca772cba2892e8d144cb749b4a71a/coverage-7.15.0-cp314-cp314-win32.whl", hash = "sha256:ab282853ed5fbd64bbb162f19cb8fcb7087187508a6374b4f9c34ec1577c4e8f", size = 223107 }, - { url = "https://files.pythonhosted.org/packages/ae/3e/c8c3b75d8dbe0e35f7b0cc3ff5e949fc59500f70b21d0398813f66740664/coverage-7.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bb3040e9f4bbe26fcb0cd7cc85ac63e630d3f3a9c74f027abf4caa27e706663", size = 223597 }, - { url = "https://files.pythonhosted.org/packages/cd/bc/3cbc9fb036eb388519bccd521f783499c39b64256013fbc362782f196fe1/coverage-7.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:346771144d34f7fa84ec28386f78e0f31653f33cf35e19d253d5b35f9e8201da", size = 223020 }, - { url = "https://files.pythonhosted.org/packages/28/00/199c4a8d656dff63102577a056c0fce2ff6a79e40adac092fc986c49cbf1/coverage-7.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d34a010905fb6401324ba016b5da03d574967f7b21ce48ea41e66f0f1f95f641", size = 221638 }, - { url = "https://files.pythonhosted.org/packages/ba/8e/9d0092c96a3d3a26951ecc7020826aa57bcb1b119ca81acbba996884ab13/coverage-7.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bb25d825d885ca8036795dacfc3924d33091fc76d71ebc99420c6b79e77d96fa", size = 221903 }, - { url = "https://files.pythonhosted.org/packages/6d/b4/c0ca3028f42c9a08e51feb4561ef1192e5de99797cd1db5b04590c215bda/coverage-7.15.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:94c9686bfe8a9a6810297aecbd99beaa3445f9e8dc2f80b1382cca0d86b64461", size = 263267 }, - { url = "https://files.pythonhosted.org/packages/5f/aa/a375e3846e5d3c013dc600b2a3231089055c73d77f5393dd2192a8d64da6/coverage-7.15.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9bd671c25f9d85f09d7ec481d0e43d5139f486c06a37139847a7ce569788af72", size = 265390 }, - { url = "https://files.pythonhosted.org/packages/92/e1/5783cdabb797305e1c9e4809fea496d31834c51fa772514f73dc148bcfc9/coverage-7.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110cbdf8d2e216577312cf06ccf85539c0e5a5420ef747e4a4719b5e483c88cd", size = 267811 }, - { url = "https://files.pythonhosted.org/packages/85/31/96d8bbf58b8e9193bc8389574a91a0db48355ee98feb66aa6bf8d1b32eea/coverage-7.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2c5d4619214f1d9993e7b00a8600d14614b7e9d84e89507460b126aa5e6559e5", size = 268928 }, - { url = "https://files.pythonhosted.org/packages/5e/7a/5294567e811a1cb7eda93140c628fa050d66189da28da320f93d1d815c73/coverage-7.15.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:781a704516e2d8346fbbd5be6c6f3412dd824785146528b3a01816f26c081007", size = 262378 }, - { url = "https://files.pythonhosted.org/packages/69/3f/3f48538421f899f28946f90a3d272136a4686e1abf461cc9249a783ee0f3/coverage-7.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd4a1b44bcb65ee29e947ac92bbee04956df3a6bfc6143641bb6cae7ede00fc9", size = 265263 }, - { url = "https://files.pythonhosted.org/packages/ce/d3/092df15efcab8a9c1467ee960eb8019bbad3f9300d115d89ea6195f369ff/coverage-7.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0e4950c9d6d3e39c64c991814ff315e2d0b9cb8152363594212c9e55208c0a8f", size = 262866 }, - { url = "https://files.pythonhosted.org/packages/e5/ab/0254d2b88665efb2c57ad368cc77ab5de3435bd8d5add4729c1b0e79431e/coverage-7.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:fe9c87ff42e5472d80d21704972e1f96e104a0a599d77c5e35db5a3c562e2571", size = 266599 }, - { url = "https://files.pythonhosted.org/packages/a8/79/1cfa4023e489ce6fbc7be4a5d442dbc375edb4f4fda39a352cedb53263c2/coverage-7.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f00d5ae1dd2fe13fb8186e3e7d37bcbd8b25c0d764ff7d1b32cef9be058510a8", size = 261714 }, - { url = "https://files.pythonhosted.org/packages/b7/eb/fee5c8665656be63f497418d410484637c438172568688e8ac92e06574e7/coverage-7.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:363ab38cc78b615f11c9cac3cf1d7eef950c18b9fdedfb9066f59461dcf84d68", size = 264025 }, - { url = "https://files.pythonhosted.org/packages/ab/99/63005db722f91edc81abc16302f9cc2f6228c1679e46e15be9ae144b14d0/coverage-7.15.0-cp314-cp314t-win32.whl", hash = "sha256:54fd9c53a5fafff509195f1b6a3f9be615d8e8362a3629ff1de23d270c03c86b", size = 223413 }, - { url = "https://files.pythonhosted.org/packages/c1/e8/2bc6181c4fb06f1a6b981eb85330cc57bfad7e3f710fc9c9d350013ba228/coverage-7.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:87b47553097ba185ed964866078e7e63adea9f5f51b5f39691c34f30afd21080", size = 224245 }, - { url = "https://files.pythonhosted.org/packages/79/b8/4d959bf9cc45d0cfed2f4d35cafcab978cdb6ea02eb5100009cd740632a3/coverage-7.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aeefb2dd178fe7eee79f0ad25d75855cb35ee9ed472db2c5ea06f5b4fd00cec5", size = 223558 }, - { url = "https://files.pythonhosted.org/packages/52/30/21b2ad45959cd50e909e02ebac1e30b4ceb7162e91c11d4c570223a458b7/coverage-7.15.0-py3-none-any.whl", hash = "sha256:56da6a4cbe8f7e9e80bd072ca9cefe67d7106a440a7ec06519ec6507ac94ad19", size = 212632 }, + { url = "https://files.pythonhosted.org/packages/2a/97/c52dc440c390b6cfa87be9432b141a956e2d56d9b9f5fc8bd71c5f471722/coverage-7.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50913d4bf5ddafa6ca3693da5e4dd833dd1b772e0283c99ca7f7d287db67331a", size = 220539, upload-time = "2026-07-02T13:08:19.252Z" }, + { url = "https://files.pythonhosted.org/packages/3f/26/602de8c2aec7e2e3e99ebfb8e04ba65598f746275396eea5f6794ff4673f/coverage-7.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:359e141ccd33893ce3f1ad5525f8b96083003677c82182e5907d62d4ea5799fc", size = 221058, upload-time = "2026-07-02T13:08:21.013Z" }, + { url = "https://files.pythonhosted.org/packages/fc/13/ebab0743138891c1d646d61e247ec29639afcbb6c4e1905e6a0f0c75291a/coverage-7.15.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3200b6204935f928c64b2ca1f923ab8c1acb7c9de45ec61569711b34d25cccaf", size = 247797, upload-time = "2026-07-02T13:08:22.474Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b7/b6ffb9e042aa48dc4144a8a65529affaec8dca0685309353614a2a7386ad/coverage-7.15.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:be616bf61346883b2cfdc5178669647e03531d81ab761a7e378558b7e8bcb628", size = 249626, upload-time = "2026-07-02T13:08:23.803Z" }, + { url = "https://files.pythonhosted.org/packages/9c/06/243ff05b652333d8e3d060c11223efc2723b19cacf6605e433fa686ab5d4/coverage-7.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7bafc3fe1059463a8fdd97ca79972d6e2bf819d775c7d54991b5b1971201d6", size = 251493, upload-time = "2026-07-02T13:08:25.397Z" }, + { url = "https://files.pythonhosted.org/packages/d3/2b/867faa17030a806114dae388b32a3fa929d8cd4bf39226fbc11f6e6bb705/coverage-7.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b713aa7fcf325a01d4184d848acb46fd84f78fdb0978470c636b23a06a753d91", size = 253406, upload-time = "2026-07-02T13:08:26.842Z" }, + { url = "https://files.pythonhosted.org/packages/94/c0/d789ce18f6605afc4895db75723424be2ef494282f77f61d8e5832923183/coverage-7.15.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e38e6fba2d56652fdfaf0231f8f78aeb805234a912de25dc291ee5cce5b8faa4", size = 248512, upload-time = "2026-07-02T13:08:28.398Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b6/b2673c30739f4a2e06649a0a38ad8b093c4d865462dc7bab0e9524a2c3b1/coverage-7.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:884499f42e382675be80770391983b90e0c0c774d87dbeeebf5f991cf6612b20", size = 249532, upload-time = "2026-07-02T13:08:29.731Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/acd79e9a41beabee92b623afe4f30b549916f48566271475f2907e752828/coverage-7.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:840481b12e083dbcbafab14794a8781a958edf327c8d3d70b4eee42f9b8253aa", size = 247537, upload-time = "2026-07-02T13:08:31.173Z" }, + { url = "https://files.pythonhosted.org/packages/12/d4/2d301c4d1b3238d7c88b70ab9d13fd53ed9505662a7ff1b46ba1e2e4e3c3/coverage-7.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:276646e9481703d09f854f3b2f018f24e19fd7049ae670a92570043eb97203b1", size = 251348, upload-time = "2026-07-02T13:08:32.63Z" }, + { url = "https://files.pythonhosted.org/packages/35/bb/c67708b2bc00f32e12805ec23d5fa677a0a51652f449341a89f9d6b1b715/coverage-7.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4de4b4d3f5545aa6c60dc4efd9c63b5b5dcc3bf00fe83146b2bdfffb8f6613bd", size = 247806, upload-time = "2026-07-02T13:08:33.931Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6c/57c4f653c47a6e917748f8938e389e72fbcae44e3643cd906664f0477a13/coverage-7.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5c504097b2a89b1e85bc6070d920df77daec701337e3aeef2c17775a5dd0ca90", size = 248410, upload-time = "2026-07-02T13:08:35.189Z" }, + { url = "https://files.pythonhosted.org/packages/6c/94/bb083041aef828903668f134273f319f2bd49224962875359c52faa5497f/coverage-7.15.0-cp310-cp310-win32.whl", hash = "sha256:f6e80ed91f98316e86b9c137206b04b2bcfbffccbdff49bd2eb09dddb1cf14e0", size = 222588, upload-time = "2026-07-02T13:08:36.486Z" }, + { url = "https://files.pythonhosted.org/packages/ef/94/a09d8ee618956f626741b0734854bac4425a00e10c0565f5abca64e7e751/coverage-7.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:b3b3e22030f3f6f5e01a5ce69936552a5c0f6992b7698777377b99041961031f", size = 223214, upload-time = "2026-07-02T13:08:37.885Z" }, + { url = "https://files.pythonhosted.org/packages/ae/23/82e910835ef4b8391047025e1d53aa48d66029f444eb8b25373c849bf503/coverage-7.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:003fff99412ea848c0aaebcc78ed2b6ce7d8a1227ed17e68470672770b78a02a", size = 220662, upload-time = "2026-07-02T13:08:39.205Z" }, + { url = "https://files.pythonhosted.org/packages/6d/0d/c7b213dde2f1579de5231062b386d8413f79c11667eb58c39319b25991da/coverage-7.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5cbd804bf2784ce7b45114516050f346ecd50f960c4bb630a7ee9e1d78fa2118", size = 221168, upload-time = "2026-07-02T13:08:40.471Z" }, + { url = "https://files.pythonhosted.org/packages/33/77/d000aeedfac085088337b3c7becdad328474b1f8a9e4c9368a0c99605d68/coverage-7.15.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8773e15c23305b58882a4611fb9b2755977eae0dc2e515366a1b6c98866cc4c2", size = 251587, upload-time = "2026-07-02T13:08:42.033Z" }, + { url = "https://files.pythonhosted.org/packages/cc/e0/86787c56b9df17afd370d5e293515dd4d9a107a561d13054873eefad8ecc/coverage-7.15.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f50e40081494c1dc4239ebb202014cbcc3306ea96fb6302a34c8cc0967fc5ae8", size = 253497, upload-time = "2026-07-02T13:08:43.387Z" }, + { url = "https://files.pythonhosted.org/packages/3f/02/181bc917359299c07dead6270f94e411151c8b60cec905c33499da69afe6/coverage-7.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daf96f37f5fc3a7b6c6da862eb4aee61c426bd63da236ed4a73ef0e503b4bca5", size = 255607, upload-time = "2026-07-02T13:08:44.897Z" }, + { url = "https://files.pythonhosted.org/packages/b9/35/ca5e7427699913da6788c4f910e73ab16c5f4b59ec5d3a999dce2a45112f/coverage-7.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:51aa20f6ae2788fd197747766edf4cd8234fd9423309b934257fa6b21a592723", size = 257563, upload-time = "2026-07-02T13:08:46.334Z" }, + { url = "https://files.pythonhosted.org/packages/0b/4d/b8220bacc2fc3c4e9078e27c32e99fb411479a4718a72bdd00036a9891c8/coverage-7.15.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03d1f922757662eb7af586e77834792274cff776bc7b1d1a0b66a49ea9d84735", size = 251726, upload-time = "2026-07-02T13:08:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e4/2e145da1991d72189b9c3cf7eca05c716ee7080d099aaea6757cfc7df008/coverage-7.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a6d6acc9a7666245e6133dd15144ca038a85a9cd5026bb06d6bbae9e77440dc9", size = 253301, upload-time = "2026-07-02T13:08:49.5Z" }, + { url = "https://files.pythonhosted.org/packages/72/28/d2c841d698bf762e481f08bd4839d370246b6d9b61dab085a7b20b201a08/coverage-7.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ac2c4c27c7df851dc9a017c2d7de00b69147e84ba3d96f37a530b0b6fb51035", size = 251361, upload-time = "2026-07-02T13:08:51.304Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ed/55d9ffde994fba3897c0c783f77a7d053b0c18787f6892ed5b0aed73f469/coverage-7.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b761a1d504fd4bd1f20f418753964dca9f5862a511fc854dac58296b3b223671", size = 255129, upload-time = "2026-07-02T13:08:52.661Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c0/ecbf33b8c460ea2718aeb813e2df8140d0370e5f67261c31524ceb0a2a8d/coverage-7.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e43b045e11c16e897895758ae90e4a90cf99e93d58549e2f90c0e2272e155695", size = 251081, upload-time = "2026-07-02T13:08:54.188Z" }, + { url = "https://files.pythonhosted.org/packages/a9/de/fb87b4261f54448dd2b9504ef19a58be42cef0d9520595fbfe1219b15234/coverage-7.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589b54513e901739f4b4582c705ce96b80c96f57641b1464607e2367a270e540", size = 251988, upload-time = "2026-07-02T13:08:55.726Z" }, + { url = "https://files.pythonhosted.org/packages/df/27/3494d5f291b9a4cb868f73c11221a8bd2d5bd761a8f9acea61ff57128dd1/coverage-7.15.0-cp311-cp311-win32.whl", hash = "sha256:106781b8482749162d0b47056937ba0933508e5d9447f65a5e7d5c422f0d6bb4", size = 222754, upload-time = "2026-07-02T13:08:57.091Z" }, + { url = "https://files.pythonhosted.org/packages/2a/ee/cd4847ebc9be6a9c0123d763645a6f1f3be6b8c58c962706368b79cbac07/coverage-7.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:821e92b3631d762a339695824cadbbc73020354eba2a23a551a99ad34938fbe6", size = 223225, upload-time = "2026-07-02T13:08:58.594Z" }, + { url = "https://files.pythonhosted.org/packages/57/37/5011581aa7f2be498b97dcc7c9902192442a42f4f9a748aeadb3d6506b42/coverage-7.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:309990eb5fb8014b9f67cb211f7fd41876ec8a88a88d3ae76de0ed1d611e3640", size = 222774, upload-time = "2026-07-02T13:09:00.074Z" }, + { url = "https://files.pythonhosted.org/packages/2a/74/fd4c0901137c4f8d81a76ada99e43c65163b4c94a02ece107a4ec0c6b615/coverage-7.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b75ee5e8cb7575636ac598719b4307ac529ec8fcd79608a35c3cd4d4dada812d", size = 220838, upload-time = "2026-07-02T13:09:02.084Z" }, + { url = "https://files.pythonhosted.org/packages/0f/2e/2347583467bd7f0402635101a916961915cc68fce652cd0db5f173ea04fc/coverage-7.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffb31267816b93b075302248cc1737506081b4f163df4401e9df1a6424aafabe", size = 221197, upload-time = "2026-07-02T13:09:03.617Z" }, + { url = "https://files.pythonhosted.org/packages/f0/17/99fa688541ae1d6e84543a0e544f83de0c944815b63e9e7b1ed411d15036/coverage-7.15.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e4d0bb73455bf97ab243a8f12c37c686ccf1c13bb614b7b85f1d062f06f42b2c", size = 252705, upload-time = "2026-07-02T13:09:05.059Z" }, + { url = "https://files.pythonhosted.org/packages/fb/02/6a95a5cd83b74839017ef9cf48d2d8c9ae60af919e17a3f336e6f9f1b7bd/coverage-7.15.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:20d9ccc4ebd0edc434d86dfd2a1dd2a8efa6b6b3073d0485a394fee86459ebb4", size = 255441, upload-time = "2026-07-02T13:09:06.559Z" }, + { url = "https://files.pythonhosted.org/packages/67/f2/406f6c57d600f68185942422c4c00f1a3255d60aee6e5fd961425cd9987e/coverage-7.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c8a976c365c8cb12f0cbd099508772ea41fb5fa80657a8506df0e11bd278c5", size = 256556, upload-time = "2026-07-02T13:09:08.197Z" }, + { url = "https://files.pythonhosted.org/packages/74/8e/d3fa48489c15ecdec1ba48fd61f68798555dddd2f6716f9ad42adeb1a2a9/coverage-7.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f948fd5ba1b9cbca91f0ae08b4c1ce2b139509149a435e2585d056d57d70bf01", size = 258815, upload-time = "2026-07-02T13:09:09.691Z" }, + { url = "https://files.pythonhosted.org/packages/47/2e/2d40ddd110462c6a2769677cf7f1c119a52b45f568978fc6c98e4cc0dd0f/coverage-7.15.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f58185f06edf6ad68ec9fb155d63ef650c82f3fbd7e1770e2867751fb13158f4", size = 253117, upload-time = "2026-07-02T13:09:11.212Z" }, + { url = "https://files.pythonhosted.org/packages/51/c0/310782f0d7c3cb2b5ac05ba8d205fe91f24a36f6bf3256098f1782181c38/coverage-7.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02adc79a920c73c647c5d117f55747df7f2de94571884758ce8bc58e04f0a796", size = 254475, upload-time = "2026-07-02T13:09:13.029Z" }, + { url = "https://files.pythonhosted.org/packages/86/f7/702da6c275f8ae6ade423d2877243122932c9b27f5403003b9ef8c927d12/coverage-7.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6eb7c300fbed667fd6e3588eba71c1904cdb06110ca6fdf908c26bdd88b8e382", size = 252619, upload-time = "2026-07-02T13:09:14.699Z" }, + { url = "https://files.pythonhosted.org/packages/fb/84/c5b15a7e5ecba4e56218d772d99fe80a63e63f8d11f12783723a6005ab45/coverage-7.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b5fb23fa2de9dce1f5c36c09066d8fcda16cd96e8e26686caa2d7cb9b567d65c", size = 256689, upload-time = "2026-07-02T13:09:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/95/2f/c8b07559b57701230c61b23a953858c052890c12ef568d81780c6c46e92e/coverage-7.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cec79341dbe6281484024979976d0c7f22beae08b4a254655decd25d42cbe766", size = 252189, upload-time = "2026-07-02T13:09:17.828Z" }, + { url = "https://files.pythonhosted.org/packages/6b/80/6d2f049dd3fd3dbfd60b62ba6b2162a04009e2c002ce70b24cf3878dec7a/coverage-7.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c664c5444b1d970b1b2a450e21fb19ee5c9cfdf151ded2dda37260031cca0da", size = 254059, upload-time = "2026-07-02T13:09:19.304Z" }, + { url = "https://files.pythonhosted.org/packages/ce/92/b0287a2c42031d25c628f815f89a3cd9f8268ee78bb1252c9356cda1c689/coverage-7.15.0-cp312-cp312-win32.whl", hash = "sha256:5f764a3fa339bde6b3aa97657f5a6a3a9451e4a5b4ea98a2892c773a43525f77", size = 222893, upload-time = "2026-07-02T13:09:20.812Z" }, + { url = "https://files.pythonhosted.org/packages/a9/69/e34c481915fecb499b3146975061dac528752e37706edc1804f32c822469/coverage-7.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:52f9a4d2c4c56c8848bc2f524916698354b0211488b38c49ad9ae54f6cafbff6", size = 223429, upload-time = "2026-07-02T13:09:22.315Z" }, + { url = "https://files.pythonhosted.org/packages/fe/98/6e878f0b571d32684ef3f38d7c03db241ca5b82a5da8a5391596a8f209c4/coverage-7.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:31e5c3e70c85307ea35a12964e2e40f56ca2ee4b1c8c721ccf4609d17071080b", size = 222810, upload-time = "2026-07-02T13:09:23.812Z" }, + { url = "https://files.pythonhosted.org/packages/76/04/145a3748098bcc86b631a85408d2c3dc5c104e0bd86d605468239b25b6c4/coverage-7.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be4caf3b28836f078abe700f8944dac4a65d78f16d6c600c89cb624e5535782", size = 220863, upload-time = "2026-07-02T13:09:25.371Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5c/4ed55708fed2c64b63c9bc5715daef670872202101938869b7fe5d5fbb8f/coverage-7.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dd58ad1404704303ca8d4f4b8a1095e7cbc7040ef17a66df1e6619aa10176430", size = 221230, upload-time = "2026-07-02T13:09:26.897Z" }, + { url = "https://files.pythonhosted.org/packages/7b/19/3a80b97d3b2a5c77a01ae359c6bed20c13738fe3d9380f08616d4fec0281/coverage-7.15.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bbcbb317c2e5ded5b21104af81c29f391be2af98d065693ffbe8d23949b948e5", size = 252227, upload-time = "2026-07-02T13:09:28.543Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/b70062750686bd7da454da27927622f48bbac6990ac7a4c4a4653e7b0036/coverage-7.15.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:27f31ecb458da3f859aab3f15ada871eb7a7768807d88df4a9f186bb17737970", size = 254823, upload-time = "2026-07-02T13:09:30.177Z" }, + { url = "https://files.pythonhosted.org/packages/a9/09/dad6a75a2e561b9dc5086a8c5257a7591d584246f67e23e70d2995b89ab6/coverage-7.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fb759be317fdc62e0f56bffdf61cfcb45c7761ad6b71e3e583e71a67ae753c", size = 256059, upload-time = "2026-07-02T13:09:31.979Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e7/b5d2941fa9564573d44b693a871ff3156f0c42cbefe977a09fa7fdc59971/coverage-7.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5cf007add5ab4bb8fa9f4c77e3732127c9e6cad501d7db43355fbfafca0be84", size = 258190, upload-time = "2026-07-02T13:09:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/7c/1d/8e895bcde3c57ccd46d896dda5f2b3d5df761a1b0c6c9d450d175dedc632/coverage-7.15.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc78d9843bd576fbe2118248258d485e968dc535f95ed504a7b0867ba9b51389", size = 252456, upload-time = "2026-07-02T13:09:35.765Z" }, + { url = "https://files.pythonhosted.org/packages/14/4c/f6997da343ddeb959be82c3b05322793f92c071ad45f7cb8a96336e2dd5f/coverage-7.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a263060f1de0b4b74b4e089c2a70b8003b3781c733329a9c8fd54995328f9950", size = 254192, upload-time = "2026-07-02T13:09:37.445Z" }, + { url = "https://files.pythonhosted.org/packages/17/27/a0bc09d032267b9da89d95a2d874cfbef2a5aebbf0e87cf7aba221d79a99/coverage-7.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c48decf16e0dfd5b049c7d5e82200c23c08126719142998d4f172444e3d0529e", size = 252153, upload-time = "2026-07-02T13:09:39.422Z" }, + { url = "https://files.pythonhosted.org/packages/54/c0/77fc233d9fba07b244c40948c53fe27308b8f21732fb3417f87fbd6fd992/coverage-7.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08fb028000ed0aaa0a4cbdfbb98be7cb42f370db973fbbb469733505ab20e13e", size = 256310, upload-time = "2026-07-02T13:09:41.006Z" }, + { url = "https://files.pythonhosted.org/packages/d5/24/601cecfb5825becacb8d45219a018a3b55b9dbaec624efdb0ea249d08be2/coverage-7.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb7dc0c3b7d8a1077abea0b8546ebc5e26d6ef6ecefc2f0f5ad2b8a53bdad837", size = 251974, upload-time = "2026-07-02T13:09:42.733Z" }, + { url = "https://files.pythonhosted.org/packages/47/1e/6f45e5a5b3d5484318d368702af6716b5ab8913b0428bec981a562fcf296/coverage-7.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cb3602054ccbe9f0d8c2dc04bbeba90d5719236e2cd06e042ddd6d3fc7b6e37", size = 253745, upload-time = "2026-07-02T13:09:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/8e/db/4df027a77bd11d0e527f44c53557c76e54ad027413d0304252ea3a78d67e/coverage-7.15.0-cp313-cp313-win32.whl", hash = "sha256:0bf781da64326b677be344df505171435b6f58716108606621d5d27d964fff8b", size = 222902, upload-time = "2026-07-02T13:09:46.122Z" }, + { url = "https://files.pythonhosted.org/packages/a0/10/0355894d34e231f2c5449e71287e81a50793a325df2e2b027b7bcd9dfd19/coverage-7.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:2c57a275078ee3fa185f83e400f765bc764a549de66d99b47881645cbd4ea629", size = 223444, upload-time = "2026-07-02T13:09:47.687Z" }, + { url = "https://files.pythonhosted.org/packages/06/ef/bb725f263befaaff851203ab338e68af15e195d7f7b5f323162532d9b6a8/coverage-7.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:3812c61afc6685c7999b39320779ab8f43b7a3081fdb0def39976e56fbdb9a21", size = 222839, upload-time = "2026-07-02T13:09:49.717Z" }, + { url = "https://files.pythonhosted.org/packages/4f/9c/1e3ca54f72a3185ece06c58d871099898c48f0ed6430d17b6ab75f0d180a/coverage-7.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:41cb79af843222e11da87127ad0ecbfa878abadd0f770a4a99391a27d3887324", size = 220906, upload-time = "2026-07-02T13:09:51.339Z" }, + { url = "https://files.pythonhosted.org/packages/09/37/f718613d83b274880382f6b67e78f3802549ae39b0b3e65ae5b5974df56e/coverage-7.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d2008989ef8fe54188d3f3bfa2e3099b025af11e90a6a1b9e7dc433d04263d8", size = 221239, upload-time = "2026-07-02T13:09:53.138Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/22bae91e0b75445f68d365c7643ed0aa4880bbf77450ee74ca65bdae53a7/coverage-7.15.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:769e8ece11a596315ebf5aa7ec383aeeed016c091d2bf6363ffb996d41529092", size = 252286, upload-time = "2026-07-02T13:09:54.996Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1e/bec5e32aa508615d9d7a2790effb25fb4dc28606e995816afe400b25ece3/coverage-7.15.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:65a6b6164ee5c39e2f3803f314292d6c61a607ba7fee253d1e03c42dc3903502", size = 254789, upload-time = "2026-07-02T13:09:56.678Z" }, + { url = "https://files.pythonhosted.org/packages/17/29/0e865435b4354e4a7c03b1b7920046d31d0a273d55decefea27e011cb9bf/coverage-7.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75128817f95a5c45bb01d65fd2d8b9cb54bbe03d81608fb70e3e14b437ad56c2", size = 256135, upload-time = "2026-07-02T13:09:58.343Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/33a870b58a13325d62fc0a6c8f01fa0ff667cef60c7498e2382a147dfa18/coverage-7.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9887bb428fe2d4cd4bee89bac1a6c9932f484afd5b36fbd4ff6ea5f825bb1f5e", size = 258449, upload-time = "2026-07-02T13:10:00.057Z" }, + { url = "https://files.pythonhosted.org/packages/18/7b/6fffe596bf3ddba8462758d02c5dad730fd91055a6634aa2e4226229181a/coverage-7.15.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0bfc0be1f702042207a93a00523b1065ee1fe951e96edf311581c0bbc2e34888", size = 252313, upload-time = "2026-07-02T13:10:01.946Z" }, + { url = "https://files.pythonhosted.org/packages/58/1b/11468dd6c1676ab831a70cb9a8d4e198e8607fa0b7220ab918b73fe9bfbd/coverage-7.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f64627d55def5a43282d70e08396672692f77e4da610a5bb8bb4060b432b6859", size = 254142, upload-time = "2026-07-02T13:10:04.065Z" }, + { url = "https://files.pythonhosted.org/packages/79/41/29328e21d16b1b95092c30dd700e08cf915bd3734f836df8f3bdb0e8fa9f/coverage-7.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2c6f0fa473003905c6d5bac328ee4eba9fbea654f15bc24b8a3274b23363fa99", size = 252108, upload-time = "2026-07-02T13:10:06.11Z" }, + { url = "https://files.pythonhosted.org/packages/9b/de/05ccfb990439655b35afbfd8e0d13fe66677565a7d4eb38c3f5ef2635e1c/coverage-7.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2bcf9afaf064172c6ec3c58a325a9957ad1178c05dd934e25f253321776e0676", size = 256385, upload-time = "2026-07-02T13:10:08.141Z" }, + { url = "https://files.pythonhosted.org/packages/51/0e/486828a3d2695ea7a2609f17ff572f6b01905e608379440a11da4b8dffbe/coverage-7.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:baf06bc987115d6fb938d403f7eab684a057766c490367999a2b71a6883110c6", size = 251923, upload-time = "2026-07-02T13:10:10.179Z" }, + { url = "https://files.pythonhosted.org/packages/18/c7/03582b6715f078e5e558354c87616d945b9894cda2dace8e4009b17035e4/coverage-7.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f0405f2ff97b1c4c0e782cb32e02f32369bcf2e6b618b591d67e1ea754575dfe", size = 253580, upload-time = "2026-07-02T13:10:12.052Z" }, + { url = "https://files.pythonhosted.org/packages/db/dc/9e578bbaf2ecb4959a81b7e7601ad8cca772cba2892e8d144cb749b4a71a/coverage-7.15.0-cp314-cp314-win32.whl", hash = "sha256:ab282853ed5fbd64bbb162f19cb8fcb7087187508a6374b4f9c34ec1577c4e8f", size = 223107, upload-time = "2026-07-02T13:10:13.994Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3e/c8c3b75d8dbe0e35f7b0cc3ff5e949fc59500f70b21d0398813f66740664/coverage-7.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bb3040e9f4bbe26fcb0cd7cc85ac63e630d3f3a9c74f027abf4caa27e706663", size = 223597, upload-time = "2026-07-02T13:10:15.906Z" }, + { url = "https://files.pythonhosted.org/packages/cd/bc/3cbc9fb036eb388519bccd521f783499c39b64256013fbc362782f196fe1/coverage-7.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:346771144d34f7fa84ec28386f78e0f31653f33cf35e19d253d5b35f9e8201da", size = 223020, upload-time = "2026-07-02T13:10:17.844Z" }, + { url = "https://files.pythonhosted.org/packages/28/00/199c4a8d656dff63102577a056c0fce2ff6a79e40adac092fc986c49cbf1/coverage-7.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d34a010905fb6401324ba016b5da03d574967f7b21ce48ea41e66f0f1f95f641", size = 221638, upload-time = "2026-07-02T13:10:19.703Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8e/9d0092c96a3d3a26951ecc7020826aa57bcb1b119ca81acbba996884ab13/coverage-7.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bb25d825d885ca8036795dacfc3924d33091fc76d71ebc99420c6b79e77d96fa", size = 221903, upload-time = "2026-07-02T13:10:21.514Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b4/c0ca3028f42c9a08e51feb4561ef1192e5de99797cd1db5b04590c215bda/coverage-7.15.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:94c9686bfe8a9a6810297aecbd99beaa3445f9e8dc2f80b1382cca0d86b64461", size = 263267, upload-time = "2026-07-02T13:10:23.261Z" }, + { url = "https://files.pythonhosted.org/packages/5f/aa/a375e3846e5d3c013dc600b2a3231089055c73d77f5393dd2192a8d64da6/coverage-7.15.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9bd671c25f9d85f09d7ec481d0e43d5139f486c06a37139847a7ce569788af72", size = 265390, upload-time = "2026-07-02T13:10:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/92/e1/5783cdabb797305e1c9e4809fea496d31834c51fa772514f73dc148bcfc9/coverage-7.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110cbdf8d2e216577312cf06ccf85539c0e5a5420ef747e4a4719b5e483c88cd", size = 267811, upload-time = "2026-07-02T13:10:27.249Z" }, + { url = "https://files.pythonhosted.org/packages/85/31/96d8bbf58b8e9193bc8389574a91a0db48355ee98feb66aa6bf8d1b32eea/coverage-7.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2c5d4619214f1d9993e7b00a8600d14614b7e9d84e89507460b126aa5e6559e5", size = 268928, upload-time = "2026-07-02T13:10:29.242Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7a/5294567e811a1cb7eda93140c628fa050d66189da28da320f93d1d815c73/coverage-7.15.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:781a704516e2d8346fbbd5be6c6f3412dd824785146528b3a01816f26c081007", size = 262378, upload-time = "2026-07-02T13:10:31.107Z" }, + { url = "https://files.pythonhosted.org/packages/69/3f/3f48538421f899f28946f90a3d272136a4686e1abf461cc9249a783ee0f3/coverage-7.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd4a1b44bcb65ee29e947ac92bbee04956df3a6bfc6143641bb6cae7ede00fc9", size = 265263, upload-time = "2026-07-02T13:10:32.942Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d3/092df15efcab8a9c1467ee960eb8019bbad3f9300d115d89ea6195f369ff/coverage-7.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0e4950c9d6d3e39c64c991814ff315e2d0b9cb8152363594212c9e55208c0a8f", size = 262866, upload-time = "2026-07-02T13:10:35.104Z" }, + { url = "https://files.pythonhosted.org/packages/e5/ab/0254d2b88665efb2c57ad368cc77ab5de3435bd8d5add4729c1b0e79431e/coverage-7.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:fe9c87ff42e5472d80d21704972e1f96e104a0a599d77c5e35db5a3c562e2571", size = 266599, upload-time = "2026-07-02T13:10:37.05Z" }, + { url = "https://files.pythonhosted.org/packages/a8/79/1cfa4023e489ce6fbc7be4a5d442dbc375edb4f4fda39a352cedb53263c2/coverage-7.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f00d5ae1dd2fe13fb8186e3e7d37bcbd8b25c0d764ff7d1b32cef9be058510a8", size = 261714, upload-time = "2026-07-02T13:10:38.966Z" }, + { url = "https://files.pythonhosted.org/packages/b7/eb/fee5c8665656be63f497418d410484637c438172568688e8ac92e06574e7/coverage-7.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:363ab38cc78b615f11c9cac3cf1d7eef950c18b9fdedfb9066f59461dcf84d68", size = 264025, upload-time = "2026-07-02T13:10:40.789Z" }, + { url = "https://files.pythonhosted.org/packages/ab/99/63005db722f91edc81abc16302f9cc2f6228c1679e46e15be9ae144b14d0/coverage-7.15.0-cp314-cp314t-win32.whl", hash = "sha256:54fd9c53a5fafff509195f1b6a3f9be615d8e8362a3629ff1de23d270c03c86b", size = 223413, upload-time = "2026-07-02T13:10:42.597Z" }, + { url = "https://files.pythonhosted.org/packages/c1/e8/2bc6181c4fb06f1a6b981eb85330cc57bfad7e3f710fc9c9d350013ba228/coverage-7.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:87b47553097ba185ed964866078e7e63adea9f5f51b5f39691c34f30afd21080", size = 224245, upload-time = "2026-07-02T13:10:44.47Z" }, + { url = "https://files.pythonhosted.org/packages/79/b8/4d959bf9cc45d0cfed2f4d35cafcab978cdb6ea02eb5100009cd740632a3/coverage-7.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aeefb2dd178fe7eee79f0ad25d75855cb35ee9ed472db2c5ea06f5b4fd00cec5", size = 223558, upload-time = "2026-07-02T13:10:46.368Z" }, + { url = "https://files.pythonhosted.org/packages/52/30/21b2ad45959cd50e909e02ebac1e30b4ceb7162e91c11d4c570223a458b7/coverage-7.15.0-py3-none-any.whl", hash = "sha256:56da6a4cbe8f7e9e80bd072ca9cefe67d7106a440a7ec06519ec6507ac94ad19", size = 212632, upload-time = "2026-07-02T13:10:48.641Z" }, ] [package.optional-dependencies] @@ -341,160 +343,160 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "toolz" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bd/d4/16916f3dc20a3f5455b63c35dcb260b3716f59ce27a93586804e70e431d5/cytoolz-1.1.0.tar.gz", hash = "sha256:13a7bf254c3c0d28b12e2290b82aed0f0977a4c2a2bf84854fcdc7796a29f3b0", size = 642510 } +sdist = { url = "https://files.pythonhosted.org/packages/bd/d4/16916f3dc20a3f5455b63c35dcb260b3716f59ce27a93586804e70e431d5/cytoolz-1.1.0.tar.gz", hash = "sha256:13a7bf254c3c0d28b12e2290b82aed0f0977a4c2a2bf84854fcdc7796a29f3b0", size = 642510, upload-time = "2025-10-19T00:44:56.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/7a/3244e6e3587be9abfee3b1c320e43a279831b3c3a31fe5d08c1ee6193e6b/cytoolz-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:72d7043a88ea5e61ba9d17ea0d1c1eff10f645d7edfcc4e56a31ef78be287644", size = 1307813 }, - { url = "https://files.pythonhosted.org/packages/32/7e/eaf504ca59addce323ef4d4ffedc2913d83c121ec19f6419bc402f7702dc/cytoolz-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d759e9ed421bacfeb456d47af8d734c057b9912b5f2441f95b27ca35e5efab07", size = 985777 }, - { url = "https://files.pythonhosted.org/packages/d4/a1/ec95443f0cf4cd0dbc574fa26ac85a0442d35f3b601a90a0e3dda077f614/cytoolz-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fdb5be8fbcc0396141189022724155a4c1c93712ac4aef8c03829af0c2a816d7", size = 982865 }, - { url = "https://files.pythonhosted.org/packages/a7/1b/8503604b0c0534977363fb77d371019395dfa031a216f9b1d8729d1280e4/cytoolz-1.1.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c8c0a513dc89bc05cc72893609118815bced5ef201f1a317b4cc3423b3a0e750", size = 2597969 }, - { url = "https://files.pythonhosted.org/packages/4e/e5/30748da06417cb2d4bc58e380b0c11d8c6539f4e289dc1e4f4b4fc248d0e/cytoolz-1.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce94db4f8ebe842c30c0ece42ff5de977c47859088c2c363dede5a68f6906484", size = 2692230 }, - { url = "https://files.pythonhosted.org/packages/d6/84/e06580b74deb97dfd3513e4e6b660c2dedc220c7653f5bd3e4f772f4d885/cytoolz-1.1.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b622d4f54e370c853ded94a668f94fe72c6d70e06ac102f17a2746661c27ab52", size = 2565243 }, - { url = "https://files.pythonhosted.org/packages/91/5e/79c0122a34c33afcb5aaee1fec35be24fe16cecefb9bb8890f2908feae56/cytoolz-1.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:375a65baa5a5b4ff6a0c5ff17e170cf23312e4c710755771ca966144c24216b5", size = 2868602 }, - { url = "https://files.pythonhosted.org/packages/3f/84/404698ff02b32292db1e39cc4a2fbdabe15164b092cc364902984c3ce0f4/cytoolz-1.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c0d51bcdb3203a062a78f66bbe33db5e3123048e24a5f0e1402422d79df8ee2d", size = 2905121 }, - { url = "https://files.pythonhosted.org/packages/9f/33/afad6593829ba73fc87b5ae64441e380fc937f79f24a1cda60d23cb99b8c/cytoolz-1.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1010869529bb05dc9802b6d776a34ca1b6d48b9deec70ad5e2918ae175be5c2f", size = 2684382 }, - { url = "https://files.pythonhosted.org/packages/ce/86/7900013a82ca9c6cadbfb22bf50d0fbfc3b192915d2bdd9fab3f69a9afba/cytoolz-1.1.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11a8f2e83295bdb33f35454d6bafcb7845b03b5881dcaed66ecbd726c7f16772", size = 2518183 }, - { url = "https://files.pythonhosted.org/packages/c3/4b/acf9be2953fed6a6d795fb66de37c367915037a998a5b3d3b69476cf91fe/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0499c5e0a8e688ed367a2e51cc13792ae8f08226c15f7d168589fc44b9b9cada", size = 2609368 }, - { url = "https://files.pythonhosted.org/packages/fd/ec/3e30455fd526f5cc37bd3dd2a0e2aafb803ae4d271e50ce53bfc30810053/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:87d44e6033d4c5e95a7d39ba59b8e105ba1c29b1ccd1d215f26477cc1d64be39", size = 2561458 }, - { url = "https://files.pythonhosted.org/packages/49/27/e5815c85bb18cdf95780f9596dcfd76dee910a4d635a1924648cb8a636c6/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a68cef396a7de237f7b97422a6a450dfb111722296ba217ba5b34551832f1f6e", size = 2578236 }, - { url = "https://files.pythonhosted.org/packages/17/db/588e266eff397670398ea335a809152e77b02ee92e0ec42091115b42f09b/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:06ad4c95b258141f138a93ebfdc1d76ac087afc1a82f1401100a1f44b44ba656", size = 2770523 }, - { url = "https://files.pythonhosted.org/packages/ab/ad/82be0b999c7a0a0b362cedfc183eb090b872fd42937af2d6e97d58bc70f8/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ada59a4b3c59d4ac7162e0ed08667ffa78abf48e975c8a9f9d5b9bc50720f4fd", size = 2512909 }, - { url = "https://files.pythonhosted.org/packages/25/21/45f07ab0339a20c518bc9006100922babc397ab7ea5ef40a395db83b9cdd/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a8957bcaea1ba01327a9b219d2adb84144377684f51444253890dab500ca171f", size = 2755345 }, - { url = "https://files.pythonhosted.org/packages/8b/a7/e530bf2b304206f79b36d793caba1ff9448348713a41bb1ad0197714a0f2/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6d8cdc299d67eb0f3b9ecdafeeb55eb3b7b7470e2d950ac34b05ed4c7a5572b8", size = 2617790 }, - { url = "https://files.pythonhosted.org/packages/9f/77/7f53092121d7431589344c7d65c3d43c4111547aafabb21d3ca9032d126c/cytoolz-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d8e08464c5cdea4f6df31e84b11ed6bfd79cedb99fbcbfdc15eb9361a6053c5a", size = 900209 }, - { url = "https://files.pythonhosted.org/packages/84/e4/902578658303b9bc76b1704d3ed85e6d307d311bd9fa0b919581bea56e62/cytoolz-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7e49922a7ed54262d41960bf3b835a7700327bf79cff1e9bfc73d79021132ff8", size = 944802 }, - { url = "https://files.pythonhosted.org/packages/71/9f/56a7003617b4eabd8ddfb470aacc240425cbe6ddeb756adfbbaadaa175f1/cytoolz-1.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:943a662d2e72ffc4438d43ab5a1de8d852237775a423236594a3b3e381b8032c", size = 904835 }, - { url = "https://files.pythonhosted.org/packages/69/82/edf1d0c32b6222f2c22e5618d6db855d44eb59f9b6f22436ff963c5d0a5c/cytoolz-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dba8e5a8c6e3c789d27b0eb5e7ce5ed7d032a7a9aae17ca4ba5147b871f6e327", size = 1314345 }, - { url = "https://files.pythonhosted.org/packages/2d/b5/0e3c1edaa26c2bd9db90cba0ac62c85bbca84224c7ae1c2e0072c4ea64c5/cytoolz-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:44b31c05addb0889167a720123b3b497b28dd86f8a0aeaf3ae4ffa11e2c85d55", size = 989259 }, - { url = "https://files.pythonhosted.org/packages/09/aa/e2b2ee9fc684867e817640764ea5807f9d25aa1e7bdba02dd4b249aab0f7/cytoolz-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:653cb18c4fc5d8a8cfce2bce650aabcbe82957cd0536827367d10810566d5294", size = 986551 }, - { url = "https://files.pythonhosted.org/packages/39/9f/4e8ee41acf6674f10a9c2c9117b2f219429a5a0f09bba6135f34ca4f08a6/cytoolz-1.1.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:853a5b4806915020c890e1ce70cc056bbc1dd8bc44f2d74d555cccfd7aefba7d", size = 2688378 }, - { url = "https://files.pythonhosted.org/packages/78/94/ef006f3412bc22444d855a0fc9ecb81424237fb4e5c1a1f8f5fb79ac978f/cytoolz-1.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7b44e9de86bea013fe84fd8c399d6016bbb96c37c5290769e5c99460b9c53e5", size = 2798299 }, - { url = "https://files.pythonhosted.org/packages/df/aa/365953926ee8b4f2e07df7200c0d73632155908c8867af14b2d19cc9f1f7/cytoolz-1.1.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:098d628a801dc142e9740126be5624eb7aef1d732bc7a5719f60a2095547b485", size = 2639311 }, - { url = "https://files.pythonhosted.org/packages/7c/ee/62beaaee7df208f22590ad07ef8875519af49c52ca39d99460b14a00f15a/cytoolz-1.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:779ee4096ed7a82cffab89372ffc339631c285079dbf33dbe7aff1f6174985df", size = 2979532 }, - { url = "https://files.pythonhosted.org/packages/c5/04/2211251e450bed111ada1194dc42c461da9aea441de62a01e4085ea6de9f/cytoolz-1.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f2ce18dd99533d077e9712f9faa852f389f560351b1efd2f2bdb193a95eddde2", size = 3018632 }, - { url = "https://files.pythonhosted.org/packages/ed/a2/4a3400e4d07d3916172bf74fede08020d7b4df01595d8a97f1e9507af5ae/cytoolz-1.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac266a34437812cf841cecbfe19f355ab9c3dd1ef231afc60415d40ff12a76e4", size = 2788579 }, - { url = "https://files.pythonhosted.org/packages/fe/82/bb88caa53a41f600e7763c517d50e2efbbe6427ea395716a92b83f44882a/cytoolz-1.1.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1920b9b9c13d60d0bb6cd14594b3bce0870022eccb430618c37156da5f2b7a55", size = 2593024 }, - { url = "https://files.pythonhosted.org/packages/09/a8/8b25e59570da16c7a0f173b8c6ec0aa6f3abd47fd385c007485acb459896/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47caa376dafd2bdc29f8a250acf59c810ec9105cd6f7680b9a9d070aae8490ec", size = 2715304 }, - { url = "https://files.pythonhosted.org/packages/d4/56/faec7696f235521b926ffdf92c102f5b029f072d28e1020364e55b084820/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5ab2c97d8aaa522b038cca9187b1153347af22309e7c998b14750c6fdec7b1cb", size = 2654461 }, - { url = "https://files.pythonhosted.org/packages/aa/82/f790ed167c04b8d2a33bed30770a9b7066fc4f573321d797190e5f05685f/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4bce006121b120e8b359244ee140bb0b1093908efc8b739db8dbaa3f8fb42139", size = 2672077 }, - { url = "https://files.pythonhosted.org/packages/d9/b3/80b8183e7eee44f45bfa3cdd3ebdadf3dd43ffc686f96d442a6c4dded45d/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fc0f1e4e9bb384d26e73c6657bbc26abdae4ff66a95933c00f3d578be89181b", size = 2881589 }, - { url = "https://files.pythonhosted.org/packages/8f/05/ac5ba5ddb88a3ba7ecea4bf192194a838af564d22ea7a4812cbb6bd106ce/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:dd3f894ff972da1994d06ac6157d74e40dda19eb31fe5e9b7863ca4278c3a167", size = 2589924 }, - { url = "https://files.pythonhosted.org/packages/8e/cd/100483cae3849d24351c8333a815dc6adaf3f04912486e59386d86d9db9a/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0846f49cf8a4496bd42659040e68bd0484ce6af819709cae234938e039203ba0", size = 2868059 }, - { url = "https://files.pythonhosted.org/packages/34/6e/3a7c56b325772d39397fc3aafb4dc054273982097178b6c3917c6dad48de/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:16a3af394ade1973226d64bb2f9eb3336adbdea03ed5b134c1bbec5a3b20028e", size = 2721692 }, - { url = "https://files.pythonhosted.org/packages/fa/ca/9fdaee32c3bc769dfb7e7991d9499136afccea67e423d097b8fb3c5acbc1/cytoolz-1.1.0-cp311-cp311-win32.whl", hash = "sha256:b786c9c8aeab76cc2f76011e986f7321a23a56d985b77d14f155d5e5514ea781", size = 899349 }, - { url = "https://files.pythonhosted.org/packages/fd/04/2ab98edeea90311e4029e1643e43d2027b54da61453292d9ea51a103ee87/cytoolz-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:ebf06d1c5344fb22fee71bf664234733e55db72d74988f2ecb7294b05e4db30c", size = 945831 }, - { url = "https://files.pythonhosted.org/packages/b4/8d/777d86ea6bcc68b0fc926b0ef8ab51819e2176b37aadea072aac949d5231/cytoolz-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:b63f5f025fac893393b186e132e3e242de8ee7265d0cd3f5bdd4dda93f6616c9", size = 904076 }, - { url = "https://files.pythonhosted.org/packages/c6/ec/01426224f7acf60183d3921b25e1a8e71713d3d39cb464d64ac7aace6ea6/cytoolz-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:99f8e134c9be11649342853ec8c90837af4089fc8ff1e8f9a024a57d1fa08514", size = 1327800 }, - { url = "https://files.pythonhosted.org/packages/b4/07/e07e8fedd332ac9626ad58bea31416dda19bfd14310731fa38b16a97e15f/cytoolz-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0a6f44cf9319c30feb9a50aa513d777ef51efec16f31c404409e7deb8063df64", size = 997118 }, - { url = "https://files.pythonhosted.org/packages/ab/72/c0f766d63ed2f9ea8dc8e1628d385d99b41fb834ce17ac3669e3f91e115d/cytoolz-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:945580dc158c557172fca899a35a99a16fbcebf6db0c77cb6621084bc82189f9", size = 991169 }, - { url = "https://files.pythonhosted.org/packages/df/4b/1f757353d1bf33e56a7391ecc9bc49c1e529803b93a9d2f67fe5f92906fe/cytoolz-1.1.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:257905ec050d04f2f856854620d1e25556fd735064cebd81b460f54939b9f9d5", size = 2700680 }, - { url = "https://files.pythonhosted.org/packages/25/73/9b25bb7ed8d419b9d6ff2ae0b3d06694de79a3f98f5169a1293ff7ad3a3f/cytoolz-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82779049f352fb3ab5e8c993ab45edbb6e02efb1f17f0b50f4972c706cc51d76", size = 2824951 }, - { url = "https://files.pythonhosted.org/packages/0c/93/9c787f7c909e75670fff467f2504725d06d8c3f51d6dfe22c55a08c8ccd4/cytoolz-1.1.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7d3e405e435320e08c5a1633afaf285a392e2d9cef35c925d91e2a31dfd7a688", size = 2679635 }, - { url = "https://files.pythonhosted.org/packages/50/aa/9ee92c302cccf7a41a7311b325b51ebeff25d36c1f82bdc1bbe3f58dc947/cytoolz-1.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:923df8f5591e0d20543060c29909c149ab1963a7267037b39eee03a83dbc50a8", size = 2938352 }, - { url = "https://files.pythonhosted.org/packages/6a/a3/3b58c5c1692c3bacd65640d0d5c7267a7ebb76204f7507aec29de7063d2f/cytoolz-1.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:25db9e4862f22ea0ae2e56c8bec9fc9fd756b655ae13e8c7b5625d7ed1c582d4", size = 3022121 }, - { url = "https://files.pythonhosted.org/packages/e1/93/c647bc3334355088c57351a536c2d4a83dd45f7de591fab383975e45bff9/cytoolz-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7a98deb11ccd8e5d9f9441ef2ff3352aab52226a2b7d04756caaa53cd612363", size = 2857656 }, - { url = "https://files.pythonhosted.org/packages/b2/c2/43fea146bf4141deea959e19dcddf268c5ed759dec5c2ed4a6941d711933/cytoolz-1.1.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dce4ee9fc99104bc77efdea80f32ca5a650cd653bcc8a1d984a931153d3d9b58", size = 2551284 }, - { url = "https://files.pythonhosted.org/packages/6f/df/cdc7a81ce5cfcde7ef523143d545635fc37e80ccacce140ae58483a21da3/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80d6da158f7d20c15819701bbda1c041f0944ede2f564f5c739b1bc80a9ffb8b", size = 2721673 }, - { url = "https://files.pythonhosted.org/packages/45/be/f8524bb9ad8812ad375e61238dcaa3177628234d1b908ad0b74e3657cafd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3b5c5a192abda123ad45ef716ec9082b4cf7d95e9ada8291c5c2cc5558be858b", size = 2722884 }, - { url = "https://files.pythonhosted.org/packages/23/e6/6bb8e4f9c267ad42d1ff77b6d2e4984665505afae50a216290e1d7311431/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5b399ce7d967b1cb6280250818b786be652aa8ddffd3c0bb5c48c6220d945ab5", size = 2685486 }, - { url = "https://files.pythonhosted.org/packages/d7/dd/88619f9c8d2b682562c0c886bbb7c35720cb83fda2ac9a41bdd14073d9bd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e7e29a1a03f00b4322196cfe8e2c38da9a6c8d573566052c586df83aacc5663c", size = 2839661 }, - { url = "https://files.pythonhosted.org/packages/b8/8d/4478ebf471ee78dd496d254dc0f4ad729cd8e6ba8257de4f0a98a2838ef2/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5291b117d71652a817ec164e7011f18e6a51f8a352cc9a70ed5b976c51102fda", size = 2547095 }, - { url = "https://files.pythonhosted.org/packages/e6/68/f1dea33367b0b3f64e199c230a14a6b6f243c189020effafd31e970ca527/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8caef62f846a9011676c51bda9189ae394cdd6bb17f2946ecaedc23243268320", size = 2870901 }, - { url = "https://files.pythonhosted.org/packages/4a/9a/33591c09dfe799b8fb692cf2ad383e2c41ab6593cc960b00d1fc8a145655/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:de425c5a8e3be7bb3a195e19191d28d9eb3c2038046064a92edc4505033ec9cb", size = 2765422 }, - { url = "https://files.pythonhosted.org/packages/60/2b/a8aa233c9416df87f004e57ae4280bd5e1f389b4943d179f01020c6ec629/cytoolz-1.1.0-cp312-cp312-win32.whl", hash = "sha256:296440a870e8d1f2e1d1edf98f60f1532b9d3ab8dfbd4b25ec08cd76311e79e5", size = 901933 }, - { url = "https://files.pythonhosted.org/packages/ad/33/4c9bdf8390dc01d2617c7f11930697157164a52259b6818ddfa2f94f89f4/cytoolz-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:07156987f224c6dac59aa18fb8bf91e1412f5463961862716a3381bf429c8699", size = 947989 }, - { url = "https://files.pythonhosted.org/packages/35/ac/6e2708835875f5acb52318462ed296bf94ed0cb8c7cb70e62fbd03f709e3/cytoolz-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:23e616b38f5b3160c7bb45b0f84a8f3deb4bd26b29fb2dfc716f241c738e27b8", size = 903913 }, - { url = "https://files.pythonhosted.org/packages/71/4a/b3ddb3ee44fe0045e95dd973746f93f033b6f92cce1fc3cbbe24b329943c/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:76c9b58555300be6dde87a41faf1f97966d79b9a678b7a526fcff75d28ef4945", size = 976728 }, - { url = "https://files.pythonhosted.org/packages/42/21/a3681434aa425875dd828bb515924b0f12c37a55c7d2bc5c0c5de3aeb0b4/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d1d638b10d3144795655e9395566ce35807df09219fd7cacd9e6acbdef67946a", size = 986057 }, - { url = "https://files.pythonhosted.org/packages/d9/cb/efc1b29e211e0670a6953222afaac84dcbba5cb940b130c0e49858978040/cytoolz-1.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:26801c1a165e84786a99e03c9c9973356caaca002d66727b761fb1042878ef06", size = 992632 }, - { url = "https://files.pythonhosted.org/packages/be/b0/e50621d21e939338c97faab651f58ea7fa32101226a91de79ecfb89d71e1/cytoolz-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a9a464542912d3272f6dccc5142df057c71c6a5cbd30439389a732df401afb7", size = 1317534 }, - { url = "https://files.pythonhosted.org/packages/0d/6b/25aa9739b0235a5bc4c1ea293186bc6822a4c6607acfe1422423287e7400/cytoolz-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ed6104fa942aa5784bf54f339563de637557e3443b105760bc4de8f16a7fc79b", size = 992336 }, - { url = "https://files.pythonhosted.org/packages/e1/53/5f4deb0ff958805309d135d899c764364c1e8a632ce4994bd7c45fb98df2/cytoolz-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56161f0ab60dc4159ec343509abaf809dc88e85c7e420e354442c62e3e7cbb77", size = 986118 }, - { url = "https://files.pythonhosted.org/packages/1c/e3/f6255b76c8cc0debbe1c0779130777dc0434da6d9b28a90d9f76f8cb67cd/cytoolz-1.1.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:832bd36cc9123535f1945acf6921f8a2a15acc19cfe4065b1c9b985a28671886", size = 2679563 }, - { url = "https://files.pythonhosted.org/packages/59/8a/acc6e39a84e930522b965586ad3a36694f9bf247b23188ee0eb47b1c9ed1/cytoolz-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1842636b6e034f229bf084c2bcdcfd36c8437e752eefd2c74ce9e2f10415cb6e", size = 2813020 }, - { url = "https://files.pythonhosted.org/packages/db/f5/0083608286ad1716eda7c41f868e85ac549f6fd6b7646993109fa0bdfd98/cytoolz-1.1.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:823df012ab90d2f2a0f92fea453528539bf71ac1879e518524cd0c86aa6df7b9", size = 2669312 }, - { url = "https://files.pythonhosted.org/packages/47/a8/d16080b575520fe5da00cede1ece4e0a4180ec23f88dcdc6a2f5a90a7f7f/cytoolz-1.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f1fcf9e7e7b3487883ff3f815abc35b89dcc45c4cf81c72b7ee457aa72d197b", size = 2922147 }, - { url = "https://files.pythonhosted.org/packages/7e/bc/716c9c1243701e58cad511eb3937fd550e645293c5ed1907639c5d66f194/cytoolz-1.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4cdb3fa1772116827f263f25b0cdd44c663b6701346a56411960534a06c082de", size = 2981602 }, - { url = "https://files.pythonhosted.org/packages/14/bc/571b232996846b27f4ac0c957dc8bf60261e9b4d0d01c8d955e82329544e/cytoolz-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1b5c95041741b81430454db65183e133976f45ac3c03454cfa8147952568529", size = 2830103 }, - { url = "https://files.pythonhosted.org/packages/5b/55/c594afb46ecd78e4b7e1fb92c947ed041807875661ceda73baaf61baba4f/cytoolz-1.1.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b2079fd9f1a65f4c61e6278c8a6d4f85edf30c606df8d5b32f1add88cbbe2286", size = 2533802 }, - { url = "https://files.pythonhosted.org/packages/93/83/1edcf95832555a78fc43b975f3ebe8ceadcc9664dd47fd33747a14df5069/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a92a320d72bef1c7e2d4c6d875125cf57fc38be45feb3fac1bfa64ea401f54a4", size = 2706071 }, - { url = "https://files.pythonhosted.org/packages/e2/df/035a408df87f25cfe3611557818b250126cd2281b2104cd88395de205583/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06d1c79aa51e6a92a90b0e456ebce2288f03dd6a76c7f582bfaa3eda7692e8a5", size = 2707575 }, - { url = "https://files.pythonhosted.org/packages/7a/a4/ef78e13e16e93bf695a9331321d75fbc834a088d941f1c19e6b63314e257/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e1d7be25f6971e986a52b6d3a0da28e1941850985417c35528f6823aef2cfec5", size = 2660486 }, - { url = "https://files.pythonhosted.org/packages/30/7a/2c3d60682b26058d435416c4e90d4a94db854de5be944dfd069ed1be648a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:964b248edc31efc50a65e9eaa0c845718503823439d2fa5f8d2c7e974c2b5409", size = 2819605 }, - { url = "https://files.pythonhosted.org/packages/45/92/19b722a1d83cc443fbc0c16e0dc376f8a451437890d3d9ee370358cf0709/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c9ff2b3c57c79b65cb5be14a18c6fd4a06d5036fb3f33e973a9f70e9ac13ca28", size = 2533559 }, - { url = "https://files.pythonhosted.org/packages/1d/15/fa3b7891da51115204416f14192081d3dea0eaee091f123fdc1347de8dd1/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:22290b73086af600042d99f5ce52a43d4ad9872c382610413176e19fc1d4fd2d", size = 2839171 }, - { url = "https://files.pythonhosted.org/packages/46/40/d3519d5cd86eebebf1e8b7174ec32dfb6ecec67b48b0cfb92bf226659b5a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a2ade74fccd080ea793382968913ee38d7a35c921df435bbf0a6aeecf0d17574", size = 2743379 }, - { url = "https://files.pythonhosted.org/packages/93/e2/a9e7511f0a13fdbefa5bf73cf8e4763878140de9453fd3e50d6ac57b6be7/cytoolz-1.1.0-cp313-cp313-win32.whl", hash = "sha256:db5dbcfda1c00e937426cbf9bdc63c24ebbc358c3263bfcbc1ab4a88dc52aa8e", size = 900844 }, - { url = "https://files.pythonhosted.org/packages/d6/a4/fb7eb403c6a4c81e5a30363f34a71adcc8bf5292dc8ea32e2440aa5668f2/cytoolz-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9e2d3fe3b45c3eb7233746f7aca37789be3dceec3e07dcc406d3e045ea0f7bdc", size = 946461 }, - { url = "https://files.pythonhosted.org/packages/93/bb/1c8c33d353548d240bc6e8677ee8c3560ce5fa2f084e928facf7c35a6dcf/cytoolz-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:32c559f95ff44a9ebcbd934acaa1e6dc8f3e6ffce4762a79a88528064873d6d5", size = 902673 }, - { url = "https://files.pythonhosted.org/packages/c4/ba/4a53acc60f59030fcaf48c7766e3c4c81bd997379425aa45b129396557b5/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9e2cd93b28f667c5870a070ab2b8bb4397470a85c4b204f2454b0ad001cd1ca3", size = 1372336 }, - { url = "https://files.pythonhosted.org/packages/ac/90/f28fd8ad8319d8f5c8da69a2c29b8cf52a6d2c0161602d92b366d58926ab/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f494124e141a9361f31d79875fe7ea459a3be2b9dadd90480427c0c52a0943d4", size = 1011930 }, - { url = "https://files.pythonhosted.org/packages/c9/95/4561c4e0ad1c944f7673d6d916405d68080f10552cfc5d69a1cf2475a9a1/cytoolz-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53a3262bf221f19437ed544bf8c0e1980c81ac8e2a53d87a9bc075dba943d36f", size = 1020610 }, - { url = "https://files.pythonhosted.org/packages/c3/14/b2e1ffa4995ec36e1372e243411ff36325e4e6d7ffa34eb4098f5357d176/cytoolz-1.1.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:47663e57d3f3f124921f38055e86a1022d0844c444ede2e8f090d3bbf80deb65", size = 2917327 }, - { url = "https://files.pythonhosted.org/packages/4a/29/7cab6c609b4514ac84cca2f7dca6c509977a8fc16d27c3a50e97f105fa6a/cytoolz-1.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5a8755c4104ee4e3d5ba434c543b5f85fdee6a1f1df33d93f518294da793a60", size = 3108951 }, - { url = "https://files.pythonhosted.org/packages/9a/71/1d1103b819458679277206ad07d78ca6b31c4bb88d6463fd193e19bfb270/cytoolz-1.1.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4d96ff3d381423af1b105295f97de86d1db51732c9566eb37378bab6670c5010", size = 2807149 }, - { url = "https://files.pythonhosted.org/packages/1a/d4/3d83a05a21e7d2ed2b9e6daf489999c29934b005de9190272b8a2e3735d0/cytoolz-1.1.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0ec96b3d537cdf47d4e76ded199f7440715f4c71029b45445cff92c1248808c2", size = 3111608 }, - { url = "https://files.pythonhosted.org/packages/51/88/96f68354c3d4af68de41f0db4fe41a23b96a50a4a416636cea325490cfeb/cytoolz-1.1.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:208e2f2ef90a32b0acbff3303d90d89b13570a228d491d2e622a7883a3c68148", size = 3179373 }, - { url = "https://files.pythonhosted.org/packages/ce/50/ed87a5cd8e6f27ffbb64c39e9730e18ec66c37631db2888ae711909f10c9/cytoolz-1.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d416a81bb0bd517558668e49d30a7475b5445f9bbafaab7dcf066f1e9adba36", size = 3003120 }, - { url = "https://files.pythonhosted.org/packages/d3/a7/acde155b050d6eaa8e9c7845c98fc5fb28501568e78e83ebbf44f8855274/cytoolz-1.1.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f32e94c91ffe49af04835ee713ebd8e005c85ebe83e7e1fdcc00f27164c2d636", size = 2703225 }, - { url = "https://files.pythonhosted.org/packages/1b/b6/9d518597c5bdea626b61101e8d2ff94124787a42259dafd9f5fc396f346a/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15d0c6405efc040499c46df44056a5c382f551a7624a41cf3e4c84a96b988a15", size = 2956033 }, - { url = "https://files.pythonhosted.org/packages/89/7a/93e5f860926165538c85e1c5e1670ad3424f158df810f8ccd269da652138/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:bf069c5381d757debae891401b88b3a346ba3a28ca45ba9251103b282463fad8", size = 2862950 }, - { url = "https://files.pythonhosted.org/packages/76/e6/99d6af00487bedc27597b54c9fcbfd5c833a69c6b7a9b9f0fff777bfc7aa/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d5cf15892e63411ec1bd67deff0e84317d974e6ab2cdfefdd4a7cea2989df66", size = 2861757 }, - { url = "https://files.pythonhosted.org/packages/71/ca/adfa1fb7949478135a37755cb8e88c20cd6b75c22a05f1128f05f3ab2c60/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3e3872c21170f8341656f8692f8939e8800dcee6549ad2474d4c817bdefd62cd", size = 2979049 }, - { url = "https://files.pythonhosted.org/packages/70/4c/7bf47a03a4497d500bc73d4204e2d907771a017fa4457741b2a1d7c09319/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b9ddeff8e8fd65eb1fcefa61018100b2b627e759ea6ad275d2e2a93ffac147bf", size = 2699492 }, - { url = "https://files.pythonhosted.org/packages/7e/e7/3d034b0e4817314f07aa465d5864e9b8df9d25cb260a53dd84583e491558/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:02feeeda93e1fa3b33414eb57c2b0aefd1db8f558dd33fdfcce664a0f86056e4", size = 2995646 }, - { url = "https://files.pythonhosted.org/packages/c1/62/be357181c71648d9fe1d1ce91cd42c63457dcf3c158e144416fd51dced83/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d08154ad45349162b6c37f12d5d1b2e6eef338e657b85e1621e4e6a4a69d64cb", size = 2919481 }, - { url = "https://files.pythonhosted.org/packages/62/d5/bf5434fde726c4f80cb99912b2d8e0afa1587557e2a2d7e0315eb942f2de/cytoolz-1.1.0-cp313-cp313t-win32.whl", hash = "sha256:10ae4718a056948d73ca3e1bb9ab1f95f897ec1e362f829b9d37cc29ab566c60", size = 951595 }, - { url = "https://files.pythonhosted.org/packages/64/29/39c161e9204a9715321ddea698cbd0abc317e78522c7c642363c20589e71/cytoolz-1.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:1bb77bc6197e5cb19784b6a42bb0f8427e81737a630d9d7dda62ed31733f9e6c", size = 1004445 }, - { url = "https://files.pythonhosted.org/packages/e2/5a/7cbff5e9a689f558cb0bdf277f9562b2ac51acf7cd15e055b8c3efb0e1ef/cytoolz-1.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:563dda652c6ff52d215704fbe6b491879b78d7bbbb3a9524ec8e763483cb459f", size = 926207 }, - { url = "https://files.pythonhosted.org/packages/b7/e8/297a85ba700f437c01eba962428e6ab4572f6c3e68e8ff442ce5c9d3a496/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d542cee7c7882d2a914a33dec4d3600416fb336734df979473249d4c53d207a1", size = 980613 }, - { url = "https://files.pythonhosted.org/packages/e8/d7/2b02c9d18e9cc263a0e22690f78080809f1eafe72f26b29ccc115d3bf5c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31922849b701b0f24bb62e56eb2488dcd3aa6ae3057694bd6b3b7c4c2bc27c2f", size = 990476 }, - { url = "https://files.pythonhosted.org/packages/89/26/b6b159d2929310fca0eff8a4989cd4b1ecbdf7c46fdff46c7a20fcae55c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e68308d32afd31943314735c1335e4ab5696110e96b405f6bdb8f2a8dc771a16", size = 992712 }, - { url = "https://files.pythonhosted.org/packages/42/a0/f7c572aa151ed466b0fce4a327c3cc916d3ef3c82e341be59ea4b9bee9e4/cytoolz-1.1.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fc4bb48b3b866e1867f7c6411a4229e5b44be3989060663713e10efc24c9bd5f", size = 1322596 }, - { url = "https://files.pythonhosted.org/packages/72/7c/a55d035e20b77b6725e85c8f1a418b3a4c23967288b8b0c2d1a40f158cbe/cytoolz-1.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:456f77207d1445025d7ef262b8370a05492dcb1490cb428b0f3bf1bd744a89b0", size = 992825 }, - { url = "https://files.pythonhosted.org/packages/03/af/39d2d3db322136e12e9336a1f13bab51eab88b386bfb11f91d3faff8ba34/cytoolz-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:174ebc71ebb20a9baeffce6ee07ee2cd913754325c93f99d767380d8317930f7", size = 990525 }, - { url = "https://files.pythonhosted.org/packages/a6/bd/65d7a869d307f9b10ad45c2c1cbb40b81a8d0ed1138fa17fd904f5c83298/cytoolz-1.1.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8b3604fef602bcd53415055a4f68468339192fd17be39e687ae24f476d23d56e", size = 2672409 }, - { url = "https://files.pythonhosted.org/packages/2d/fb/74dfd844bfd67e810bd36e8e3903a143035447245828e7fcd7c81351d775/cytoolz-1.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3604b959a01f64c366e7d10ec7634d5f5cfe10301e27a8f090f6eb3b2a628a18", size = 2808477 }, - { url = "https://files.pythonhosted.org/packages/d6/1f/587686c43e31c19241ec317da66438d093523921ea7749bbc65558a30df9/cytoolz-1.1.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6db2127a3c1bc2f59f08010d2ae53a760771a9de2f67423ad8d400e9ba4276e8", size = 2636881 }, - { url = "https://files.pythonhosted.org/packages/bc/6d/90468cd34f77cb38a11af52c4dc6199efcc97a486395a21bef72e9b7602e/cytoolz-1.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56584745ac647993a016a21bc76399113b7595e312f8d0a1b140c9fcf9b58a27", size = 2937315 }, - { url = "https://files.pythonhosted.org/packages/d9/50/7b92cd78c613b92e3509e6291d3fb7e0d72ebda999a8df806a96c40ca9ab/cytoolz-1.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db2c4c3a7f7bd7e03bb1a236a125c8feb86c75802f4ecda6ecfaf946610b2930", size = 2959988 }, - { url = "https://files.pythonhosted.org/packages/44/d5/34b5a28a8d9bb329f984b4c2259407ca3f501d1abeb01bacea07937d85d1/cytoolz-1.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48cb8a692111a285d2b9acd16d185428176bfbffa8a7c274308525fccd01dd42", size = 2795116 }, - { url = "https://files.pythonhosted.org/packages/f5/d9/5dd829e33273ec03bdc3c812e6c3281987ae2c5c91645582f6c331544a64/cytoolz-1.1.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d2f344ba5eb17dcf38ee37fdde726f69053f54927db8f8a1bed6ac61e5b1890d", size = 2535390 }, - { url = "https://files.pythonhosted.org/packages/87/1f/7f9c58068a8eec2183110df051bc6b69dd621143f84473eeb6dc1b32905a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:abf76b1c1abd031f098f293b6d90ee08bdaa45f8b5678430e331d991b82684b1", size = 2704834 }, - { url = "https://files.pythonhosted.org/packages/d2/90/667def5665333575d01a65fe3ec0ca31b897895f6e3bc1a42d6ea3659369/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ddf9a38a5b686091265ff45b53d142e44a538cd6c2e70610d3bc6be094219032", size = 2658441 }, - { url = "https://files.pythonhosted.org/packages/23/79/6615f9a14960bd29ac98b823777b6589357833f65cf1a11b5abc1587c120/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:946786755274f07bb2be0400f28adb31d7d85a7c7001873c0a8e24a503428fb3", size = 2654766 }, - { url = "https://files.pythonhosted.org/packages/b0/99/be59c6e0ae02153ef10ae1ff0f380fb19d973c651b50cf829a731f6c9e79/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b8f78b9fed79cf185ad4ddec099abeef45951bdcb416c5835ba05f0a1242c7", size = 2827649 }, - { url = "https://files.pythonhosted.org/packages/19/b7/854ddcf9f9618844108677c20d48f4611b5c636956adea0f0e85e027608f/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fccde6efefdbc02e676ccb352a2ccc8a8e929f59a1c6d3d60bb78e923a49ca44", size = 2533456 }, - { url = "https://files.pythonhosted.org/packages/45/66/bfe6fbb2bdcf03c8377c8c2f542576e15f3340c905a09d78a6cb3badd39a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:717b7775313da5f51b0fbf50d865aa9c39cb241bd4cb605df3cf2246d6567397", size = 2826455 }, - { url = "https://files.pythonhosted.org/packages/c3/0c/cce4047bd927e95f59e73319c02c9bc86bd3d76392e0eb9e41a1147a479c/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5158744a09d0e0e4a4f82225e3a3c4ebf38f9ae74467aaa905467270e52f2794", size = 2714897 }, - { url = "https://files.pythonhosted.org/packages/ac/9a/061323bb289b565802bad14fb7ab59fcd8713105df142bcf4dd9ff64f8ac/cytoolz-1.1.0-cp314-cp314-win32.whl", hash = "sha256:1ed534bdbbf063b2bb28fca7d0f6723a3e5a72b086e7c7fe6d74ae8c3e4d00e2", size = 901490 }, - { url = "https://files.pythonhosted.org/packages/a3/20/1f3a733d710d2a25d6f10b463bef55ada52fe6392a5d233c8d770191f48a/cytoolz-1.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:472c1c9a085f5ad973ec0ad7f0b9ba0969faea6f96c9e397f6293d386f3a25ec", size = 946730 }, - { url = "https://files.pythonhosted.org/packages/f2/22/2d657db4a5d1c10a152061800f812caba9ef20d7bd2406f51a5fd800c180/cytoolz-1.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:a7ad7ca3386fa86bd301be3fa36e7f0acb024f412f665937955acfc8eb42deff", size = 905722 }, - { url = "https://files.pythonhosted.org/packages/19/97/b4a8c76796a9a8b9bc90c7992840fa1589a1af8e0426562dea4ce9b384a7/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:64b63ed4b71b1ba813300ad0f06b8aff19a12cf51116e0e4f1ed837cea4debcf", size = 1372606 }, - { url = "https://files.pythonhosted.org/packages/08/d4/a1bb1a32b454a2d650db8374ff3bf875ba0fc1c36e6446ec02a83b9140a1/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a60ba6f2ed9eb0003a737e1ee1e9fa2258e749da6477946008d4324efa25149f", size = 1012189 }, - { url = "https://files.pythonhosted.org/packages/21/4b/2f5cbbd81588918ee7dd70cffb66731608f578a9b72166aafa991071af7d/cytoolz-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1aa58e2434d732241f7f051e6f17657e969a89971025e24578b5cbc6f1346485", size = 1020624 }, - { url = "https://files.pythonhosted.org/packages/f5/99/c4954dd86cd593cd776a038b36795a259b8b5c12cbab6363edf5f6d9c909/cytoolz-1.1.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6965af3fc7214645970e312deb9bd35a213a1eaabcfef4f39115e60bf2f76867", size = 2917016 }, - { url = "https://files.pythonhosted.org/packages/b2/7c/f1f70a17e272b433232bc8a27df97e46b202d6cc07e3b0d63f7f41ba0f2d/cytoolz-1.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddd2863f321d67527d3b67a93000a378ad6f967056f68c06467fe011278a6d0e", size = 3107634 }, - { url = "https://files.pythonhosted.org/packages/8f/bd/c3226a57474b4aef1f90040510cba30d0decd3515fed48dc229b37c2f898/cytoolz-1.1.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4e6b428e9eb5126053c2ae0efa62512ff4b38ed3951f4d0888ca7005d63e56f5", size = 2806221 }, - { url = "https://files.pythonhosted.org/packages/c3/47/2f7bfe4aaa1e07dc9828bea228ed744faf73b26aee0c1bdf3b5520bf1909/cytoolz-1.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d758e5ef311d2671e0ae8c214c52e44617cf1e58bef8f022b547b9802a5a7f30", size = 3107671 }, - { url = "https://files.pythonhosted.org/packages/4d/12/6ff3b04fbd1369d0fcd5f8b5910ba6e427e33bf113754c4c35ec3f747924/cytoolz-1.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a95416eca473e6c1179b48d86adcf528b59c63ce78f4cb9934f2e413afa9b56b", size = 3176350 }, - { url = "https://files.pythonhosted.org/packages/e6/8c/6691d986b728e77b5d2872743ebcd962d37a2d0f7e9ad95a81b284fbf905/cytoolz-1.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36c8ede93525cf11e2cc787b7156e5cecd7340193ef800b816a16f1404a8dc6d", size = 3001173 }, - { url = "https://files.pythonhosted.org/packages/7a/cb/f59d83a5058e1198db5a1f04e4a124c94d60390e4fa89b6d2e38ee8288a0/cytoolz-1.1.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c949755b6d8a649c5fbc888bc30915926f1b09fe42fea9f289e297c2f6ddd3", size = 2701374 }, - { url = "https://files.pythonhosted.org/packages/b7/f0/1ae6d28df503b0bdae094879da2072b8ba13db5919cd3798918761578411/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e1b6d37545816905a76d9ed59fa4e332f929e879f062a39ea0f6f620405cdc27", size = 2953081 }, - { url = "https://files.pythonhosted.org/packages/f4/06/d86fe811c6222dc32d3e08f5d88d2be598a6055b4d0590e7c1428d55c386/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:05332112d4087904842b36954cd1d3fc0e463a2f4a7ef9477bd241427c593c3b", size = 2862228 }, - { url = "https://files.pythonhosted.org/packages/ae/32/978ef6f42623be44a0a03ae9de875ab54aa26c7e38c5c4cd505460b0927d/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:31538ca2fad2d688cbd962ccc3f1da847329e2258a52940f10a2ac0719e526be", size = 2861971 }, - { url = "https://files.pythonhosted.org/packages/ee/f7/74c69497e756b752b359925d1feef68b91df024a4124a823740f675dacd3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:747562aa70abf219ea16f07d50ac0157db856d447f7f498f592e097cbc77df0b", size = 2975304 }, - { url = "https://files.pythonhosted.org/packages/5b/2b/3ce0e6889a6491f3418ad4d84ae407b8456b02169a5a1f87990dbba7433b/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:3dc15c48b20c0f467e15e341e102896c8422dccf8efc6322def5c1b02f074629", size = 2697371 }, - { url = "https://files.pythonhosted.org/packages/15/87/c616577f0891d97860643c845f7221e95240aa589586de727e28a5eb6e52/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3c03137ee6103ba92d5d6ad6a510e86fded69cd67050bd8a1843f15283be17ac", size = 2992436 }, - { url = "https://files.pythonhosted.org/packages/e7/9f/490c81bffb3428ab1fa114051fbb5ba18aaa2e2fe4da5bf4170ca524e6b3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:be8e298d88f88bd172b59912240558be3b7a04959375646e7fd4996401452941", size = 2917612 }, - { url = "https://files.pythonhosted.org/packages/66/35/0fec2769660ca6472bbf3317ab634675827bb706d193e3240aaf20eab961/cytoolz-1.1.0-cp314-cp314t-win32.whl", hash = "sha256:3d407140f5604a89578285d4aac7b18b8eafa055cf776e781aabb89c48738fad", size = 960842 }, - { url = "https://files.pythonhosted.org/packages/46/b4/b7ce3d3cd20337becfec978ecfa6d0ef64884d0cf32d44edfed8700914b9/cytoolz-1.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:56e5afb69eb6e1b3ffc34716ee5f92ffbdb5cb003b3a5ca4d4b0fe700e217162", size = 1020835 }, - { url = "https://files.pythonhosted.org/packages/2c/1f/0498009aa563a9c5d04f520aadc6e1c0942434d089d0b2f51ea986470f55/cytoolz-1.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:27b19b4a286b3ff52040efa42dbe403730aebe5fdfd2def704eb285e2125c63e", size = 927963 }, - { url = "https://files.pythonhosted.org/packages/84/32/0522207170294cf691112a93c70a8ef942f60fa9ff8e793b63b1f09cedc0/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f32e93a55681d782fc6af939f6df36509d65122423cbc930be39b141064adff8", size = 922014 }, - { url = "https://files.pythonhosted.org/packages/4c/49/9be2d24adaa18fa307ff14e3e43f02b2ae4b69c4ce51cee6889eb2114990/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5d9bc596751cbda8073e65be02ca11706f00029768fbbbc81e11a8c290bb41aa", size = 918134 }, - { url = "https://files.pythonhosted.org/packages/5c/b3/6a76c3b94c6c87c72ea822e7e67405be6b649c2e37778eeac7c0c0c69de8/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9b16660d01c3931951fab49db422c627897c38c1a1f0393a97582004019a4887", size = 981970 }, - { url = "https://files.pythonhosted.org/packages/f6/8a/606e4c7ed14aa6a86aee6ca84a2cb804754dc6c4905b8f94e09e49f1ce60/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b7de5718e2113d4efccea3f06055758cdbc17388ecc3341ba4d1d812837d7c1a", size = 978877 }, - { url = "https://files.pythonhosted.org/packages/97/ec/ad474dcb1f6c1ebfdda3c2ad2edbb1af122a0e79c9ff2cb901ffb5f59662/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a12a2a1a6bc44099491c05a12039efa08cc33a3d0f8c7b0566185e085e139283", size = 964279 }, - { url = "https://files.pythonhosted.org/packages/68/8c/d245fd416c69d27d51f14d5ad62acc4ee5971088ee31c40ffe1cc109af68/cytoolz-1.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:047defa7f5f9a32f82373dbc3957289562e8a3fa58ae02ec8e4dca4f43a33a21", size = 916630 }, + { url = "https://files.pythonhosted.org/packages/a7/7a/3244e6e3587be9abfee3b1c320e43a279831b3c3a31fe5d08c1ee6193e6b/cytoolz-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:72d7043a88ea5e61ba9d17ea0d1c1eff10f645d7edfcc4e56a31ef78be287644", size = 1307813, upload-time = "2025-10-19T00:39:34.198Z" }, + { url = "https://files.pythonhosted.org/packages/32/7e/eaf504ca59addce323ef4d4ffedc2913d83c121ec19f6419bc402f7702dc/cytoolz-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d759e9ed421bacfeb456d47af8d734c057b9912b5f2441f95b27ca35e5efab07", size = 985777, upload-time = "2025-10-19T00:39:36.545Z" }, + { url = "https://files.pythonhosted.org/packages/d4/a1/ec95443f0cf4cd0dbc574fa26ac85a0442d35f3b601a90a0e3dda077f614/cytoolz-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fdb5be8fbcc0396141189022724155a4c1c93712ac4aef8c03829af0c2a816d7", size = 982865, upload-time = "2025-10-19T00:39:38.19Z" }, + { url = "https://files.pythonhosted.org/packages/a7/1b/8503604b0c0534977363fb77d371019395dfa031a216f9b1d8729d1280e4/cytoolz-1.1.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c8c0a513dc89bc05cc72893609118815bced5ef201f1a317b4cc3423b3a0e750", size = 2597969, upload-time = "2025-10-19T00:39:40.26Z" }, + { url = "https://files.pythonhosted.org/packages/4e/e5/30748da06417cb2d4bc58e380b0c11d8c6539f4e289dc1e4f4b4fc248d0e/cytoolz-1.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce94db4f8ebe842c30c0ece42ff5de977c47859088c2c363dede5a68f6906484", size = 2692230, upload-time = "2025-10-19T00:39:42.327Z" }, + { url = "https://files.pythonhosted.org/packages/d6/84/e06580b74deb97dfd3513e4e6b660c2dedc220c7653f5bd3e4f772f4d885/cytoolz-1.1.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b622d4f54e370c853ded94a668f94fe72c6d70e06ac102f17a2746661c27ab52", size = 2565243, upload-time = "2025-10-19T00:39:44.403Z" }, + { url = "https://files.pythonhosted.org/packages/91/5e/79c0122a34c33afcb5aaee1fec35be24fe16cecefb9bb8890f2908feae56/cytoolz-1.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:375a65baa5a5b4ff6a0c5ff17e170cf23312e4c710755771ca966144c24216b5", size = 2868602, upload-time = "2025-10-19T00:39:46.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/84/404698ff02b32292db1e39cc4a2fbdabe15164b092cc364902984c3ce0f4/cytoolz-1.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c0d51bcdb3203a062a78f66bbe33db5e3123048e24a5f0e1402422d79df8ee2d", size = 2905121, upload-time = "2025-10-19T00:39:48.078Z" }, + { url = "https://files.pythonhosted.org/packages/9f/33/afad6593829ba73fc87b5ae64441e380fc937f79f24a1cda60d23cb99b8c/cytoolz-1.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1010869529bb05dc9802b6d776a34ca1b6d48b9deec70ad5e2918ae175be5c2f", size = 2684382, upload-time = "2025-10-19T00:39:49.766Z" }, + { url = "https://files.pythonhosted.org/packages/ce/86/7900013a82ca9c6cadbfb22bf50d0fbfc3b192915d2bdd9fab3f69a9afba/cytoolz-1.1.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11a8f2e83295bdb33f35454d6bafcb7845b03b5881dcaed66ecbd726c7f16772", size = 2518183, upload-time = "2025-10-19T00:39:51.433Z" }, + { url = "https://files.pythonhosted.org/packages/c3/4b/acf9be2953fed6a6d795fb66de37c367915037a998a5b3d3b69476cf91fe/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0499c5e0a8e688ed367a2e51cc13792ae8f08226c15f7d168589fc44b9b9cada", size = 2609368, upload-time = "2025-10-19T00:39:53.458Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ec/3e30455fd526f5cc37bd3dd2a0e2aafb803ae4d271e50ce53bfc30810053/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:87d44e6033d4c5e95a7d39ba59b8e105ba1c29b1ccd1d215f26477cc1d64be39", size = 2561458, upload-time = "2025-10-19T00:39:55.493Z" }, + { url = "https://files.pythonhosted.org/packages/49/27/e5815c85bb18cdf95780f9596dcfd76dee910a4d635a1924648cb8a636c6/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a68cef396a7de237f7b97422a6a450dfb111722296ba217ba5b34551832f1f6e", size = 2578236, upload-time = "2025-10-19T00:39:57.512Z" }, + { url = "https://files.pythonhosted.org/packages/17/db/588e266eff397670398ea335a809152e77b02ee92e0ec42091115b42f09b/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:06ad4c95b258141f138a93ebfdc1d76ac087afc1a82f1401100a1f44b44ba656", size = 2770523, upload-time = "2025-10-19T00:39:59.194Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ad/82be0b999c7a0a0b362cedfc183eb090b872fd42937af2d6e97d58bc70f8/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ada59a4b3c59d4ac7162e0ed08667ffa78abf48e975c8a9f9d5b9bc50720f4fd", size = 2512909, upload-time = "2025-10-19T00:40:01.199Z" }, + { url = "https://files.pythonhosted.org/packages/25/21/45f07ab0339a20c518bc9006100922babc397ab7ea5ef40a395db83b9cdd/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a8957bcaea1ba01327a9b219d2adb84144377684f51444253890dab500ca171f", size = 2755345, upload-time = "2025-10-19T00:40:03.322Z" }, + { url = "https://files.pythonhosted.org/packages/8b/a7/e530bf2b304206f79b36d793caba1ff9448348713a41bb1ad0197714a0f2/cytoolz-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6d8cdc299d67eb0f3b9ecdafeeb55eb3b7b7470e2d950ac34b05ed4c7a5572b8", size = 2617790, upload-time = "2025-10-19T00:40:05.03Z" }, + { url = "https://files.pythonhosted.org/packages/9f/77/7f53092121d7431589344c7d65c3d43c4111547aafabb21d3ca9032d126c/cytoolz-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d8e08464c5cdea4f6df31e84b11ed6bfd79cedb99fbcbfdc15eb9361a6053c5a", size = 900209, upload-time = "2025-10-19T00:40:06.647Z" }, + { url = "https://files.pythonhosted.org/packages/84/e4/902578658303b9bc76b1704d3ed85e6d307d311bd9fa0b919581bea56e62/cytoolz-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7e49922a7ed54262d41960bf3b835a7700327bf79cff1e9bfc73d79021132ff8", size = 944802, upload-time = "2025-10-19T00:40:08.983Z" }, + { url = "https://files.pythonhosted.org/packages/71/9f/56a7003617b4eabd8ddfb470aacc240425cbe6ddeb756adfbbaadaa175f1/cytoolz-1.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:943a662d2e72ffc4438d43ab5a1de8d852237775a423236594a3b3e381b8032c", size = 904835, upload-time = "2025-10-19T00:40:11.024Z" }, + { url = "https://files.pythonhosted.org/packages/69/82/edf1d0c32b6222f2c22e5618d6db855d44eb59f9b6f22436ff963c5d0a5c/cytoolz-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dba8e5a8c6e3c789d27b0eb5e7ce5ed7d032a7a9aae17ca4ba5147b871f6e327", size = 1314345, upload-time = "2025-10-19T00:40:13.273Z" }, + { url = "https://files.pythonhosted.org/packages/2d/b5/0e3c1edaa26c2bd9db90cba0ac62c85bbca84224c7ae1c2e0072c4ea64c5/cytoolz-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:44b31c05addb0889167a720123b3b497b28dd86f8a0aeaf3ae4ffa11e2c85d55", size = 989259, upload-time = "2025-10-19T00:40:15.196Z" }, + { url = "https://files.pythonhosted.org/packages/09/aa/e2b2ee9fc684867e817640764ea5807f9d25aa1e7bdba02dd4b249aab0f7/cytoolz-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:653cb18c4fc5d8a8cfce2bce650aabcbe82957cd0536827367d10810566d5294", size = 986551, upload-time = "2025-10-19T00:40:16.831Z" }, + { url = "https://files.pythonhosted.org/packages/39/9f/4e8ee41acf6674f10a9c2c9117b2f219429a5a0f09bba6135f34ca4f08a6/cytoolz-1.1.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:853a5b4806915020c890e1ce70cc056bbc1dd8bc44f2d74d555cccfd7aefba7d", size = 2688378, upload-time = "2025-10-19T00:40:18.552Z" }, + { url = "https://files.pythonhosted.org/packages/78/94/ef006f3412bc22444d855a0fc9ecb81424237fb4e5c1a1f8f5fb79ac978f/cytoolz-1.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7b44e9de86bea013fe84fd8c399d6016bbb96c37c5290769e5c99460b9c53e5", size = 2798299, upload-time = "2025-10-19T00:40:20.191Z" }, + { url = "https://files.pythonhosted.org/packages/df/aa/365953926ee8b4f2e07df7200c0d73632155908c8867af14b2d19cc9f1f7/cytoolz-1.1.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:098d628a801dc142e9740126be5624eb7aef1d732bc7a5719f60a2095547b485", size = 2639311, upload-time = "2025-10-19T00:40:22.289Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ee/62beaaee7df208f22590ad07ef8875519af49c52ca39d99460b14a00f15a/cytoolz-1.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:779ee4096ed7a82cffab89372ffc339631c285079dbf33dbe7aff1f6174985df", size = 2979532, upload-time = "2025-10-19T00:40:24.006Z" }, + { url = "https://files.pythonhosted.org/packages/c5/04/2211251e450bed111ada1194dc42c461da9aea441de62a01e4085ea6de9f/cytoolz-1.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f2ce18dd99533d077e9712f9faa852f389f560351b1efd2f2bdb193a95eddde2", size = 3018632, upload-time = "2025-10-19T00:40:26.175Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a2/4a3400e4d07d3916172bf74fede08020d7b4df01595d8a97f1e9507af5ae/cytoolz-1.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac266a34437812cf841cecbfe19f355ab9c3dd1ef231afc60415d40ff12a76e4", size = 2788579, upload-time = "2025-10-19T00:40:27.878Z" }, + { url = "https://files.pythonhosted.org/packages/fe/82/bb88caa53a41f600e7763c517d50e2efbbe6427ea395716a92b83f44882a/cytoolz-1.1.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1920b9b9c13d60d0bb6cd14594b3bce0870022eccb430618c37156da5f2b7a55", size = 2593024, upload-time = "2025-10-19T00:40:29.601Z" }, + { url = "https://files.pythonhosted.org/packages/09/a8/8b25e59570da16c7a0f173b8c6ec0aa6f3abd47fd385c007485acb459896/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47caa376dafd2bdc29f8a250acf59c810ec9105cd6f7680b9a9d070aae8490ec", size = 2715304, upload-time = "2025-10-19T00:40:31.151Z" }, + { url = "https://files.pythonhosted.org/packages/d4/56/faec7696f235521b926ffdf92c102f5b029f072d28e1020364e55b084820/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5ab2c97d8aaa522b038cca9187b1153347af22309e7c998b14750c6fdec7b1cb", size = 2654461, upload-time = "2025-10-19T00:40:32.884Z" }, + { url = "https://files.pythonhosted.org/packages/aa/82/f790ed167c04b8d2a33bed30770a9b7066fc4f573321d797190e5f05685f/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4bce006121b120e8b359244ee140bb0b1093908efc8b739db8dbaa3f8fb42139", size = 2672077, upload-time = "2025-10-19T00:40:34.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b3/80b8183e7eee44f45bfa3cdd3ebdadf3dd43ffc686f96d442a6c4dded45d/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fc0f1e4e9bb384d26e73c6657bbc26abdae4ff66a95933c00f3d578be89181b", size = 2881589, upload-time = "2025-10-19T00:40:36.315Z" }, + { url = "https://files.pythonhosted.org/packages/8f/05/ac5ba5ddb88a3ba7ecea4bf192194a838af564d22ea7a4812cbb6bd106ce/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:dd3f894ff972da1994d06ac6157d74e40dda19eb31fe5e9b7863ca4278c3a167", size = 2589924, upload-time = "2025-10-19T00:40:38.317Z" }, + { url = "https://files.pythonhosted.org/packages/8e/cd/100483cae3849d24351c8333a815dc6adaf3f04912486e59386d86d9db9a/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0846f49cf8a4496bd42659040e68bd0484ce6af819709cae234938e039203ba0", size = 2868059, upload-time = "2025-10-19T00:40:40.025Z" }, + { url = "https://files.pythonhosted.org/packages/34/6e/3a7c56b325772d39397fc3aafb4dc054273982097178b6c3917c6dad48de/cytoolz-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:16a3af394ade1973226d64bb2f9eb3336adbdea03ed5b134c1bbec5a3b20028e", size = 2721692, upload-time = "2025-10-19T00:40:41.621Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ca/9fdaee32c3bc769dfb7e7991d9499136afccea67e423d097b8fb3c5acbc1/cytoolz-1.1.0-cp311-cp311-win32.whl", hash = "sha256:b786c9c8aeab76cc2f76011e986f7321a23a56d985b77d14f155d5e5514ea781", size = 899349, upload-time = "2025-10-19T00:40:43.183Z" }, + { url = "https://files.pythonhosted.org/packages/fd/04/2ab98edeea90311e4029e1643e43d2027b54da61453292d9ea51a103ee87/cytoolz-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:ebf06d1c5344fb22fee71bf664234733e55db72d74988f2ecb7294b05e4db30c", size = 945831, upload-time = "2025-10-19T00:40:44.693Z" }, + { url = "https://files.pythonhosted.org/packages/b4/8d/777d86ea6bcc68b0fc926b0ef8ab51819e2176b37aadea072aac949d5231/cytoolz-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:b63f5f025fac893393b186e132e3e242de8ee7265d0cd3f5bdd4dda93f6616c9", size = 904076, upload-time = "2025-10-19T00:40:46.678Z" }, + { url = "https://files.pythonhosted.org/packages/c6/ec/01426224f7acf60183d3921b25e1a8e71713d3d39cb464d64ac7aace6ea6/cytoolz-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:99f8e134c9be11649342853ec8c90837af4089fc8ff1e8f9a024a57d1fa08514", size = 1327800, upload-time = "2025-10-19T00:40:48.674Z" }, + { url = "https://files.pythonhosted.org/packages/b4/07/e07e8fedd332ac9626ad58bea31416dda19bfd14310731fa38b16a97e15f/cytoolz-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0a6f44cf9319c30feb9a50aa513d777ef51efec16f31c404409e7deb8063df64", size = 997118, upload-time = "2025-10-19T00:40:50.919Z" }, + { url = "https://files.pythonhosted.org/packages/ab/72/c0f766d63ed2f9ea8dc8e1628d385d99b41fb834ce17ac3669e3f91e115d/cytoolz-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:945580dc158c557172fca899a35a99a16fbcebf6db0c77cb6621084bc82189f9", size = 991169, upload-time = "2025-10-19T00:40:52.887Z" }, + { url = "https://files.pythonhosted.org/packages/df/4b/1f757353d1bf33e56a7391ecc9bc49c1e529803b93a9d2f67fe5f92906fe/cytoolz-1.1.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:257905ec050d04f2f856854620d1e25556fd735064cebd81b460f54939b9f9d5", size = 2700680, upload-time = "2025-10-19T00:40:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/25/73/9b25bb7ed8d419b9d6ff2ae0b3d06694de79a3f98f5169a1293ff7ad3a3f/cytoolz-1.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82779049f352fb3ab5e8c993ab45edbb6e02efb1f17f0b50f4972c706cc51d76", size = 2824951, upload-time = "2025-10-19T00:40:56.137Z" }, + { url = "https://files.pythonhosted.org/packages/0c/93/9c787f7c909e75670fff467f2504725d06d8c3f51d6dfe22c55a08c8ccd4/cytoolz-1.1.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7d3e405e435320e08c5a1633afaf285a392e2d9cef35c925d91e2a31dfd7a688", size = 2679635, upload-time = "2025-10-19T00:40:57.799Z" }, + { url = "https://files.pythonhosted.org/packages/50/aa/9ee92c302cccf7a41a7311b325b51ebeff25d36c1f82bdc1bbe3f58dc947/cytoolz-1.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:923df8f5591e0d20543060c29909c149ab1963a7267037b39eee03a83dbc50a8", size = 2938352, upload-time = "2025-10-19T00:40:59.49Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a3/3b58c5c1692c3bacd65640d0d5c7267a7ebb76204f7507aec29de7063d2f/cytoolz-1.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:25db9e4862f22ea0ae2e56c8bec9fc9fd756b655ae13e8c7b5625d7ed1c582d4", size = 3022121, upload-time = "2025-10-19T00:41:01.209Z" }, + { url = "https://files.pythonhosted.org/packages/e1/93/c647bc3334355088c57351a536c2d4a83dd45f7de591fab383975e45bff9/cytoolz-1.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7a98deb11ccd8e5d9f9441ef2ff3352aab52226a2b7d04756caaa53cd612363", size = 2857656, upload-time = "2025-10-19T00:41:03.456Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c2/43fea146bf4141deea959e19dcddf268c5ed759dec5c2ed4a6941d711933/cytoolz-1.1.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dce4ee9fc99104bc77efdea80f32ca5a650cd653bcc8a1d984a931153d3d9b58", size = 2551284, upload-time = "2025-10-19T00:41:05.347Z" }, + { url = "https://files.pythonhosted.org/packages/6f/df/cdc7a81ce5cfcde7ef523143d545635fc37e80ccacce140ae58483a21da3/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80d6da158f7d20c15819701bbda1c041f0944ede2f564f5c739b1bc80a9ffb8b", size = 2721673, upload-time = "2025-10-19T00:41:07.528Z" }, + { url = "https://files.pythonhosted.org/packages/45/be/f8524bb9ad8812ad375e61238dcaa3177628234d1b908ad0b74e3657cafd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3b5c5a192abda123ad45ef716ec9082b4cf7d95e9ada8291c5c2cc5558be858b", size = 2722884, upload-time = "2025-10-19T00:41:09.698Z" }, + { url = "https://files.pythonhosted.org/packages/23/e6/6bb8e4f9c267ad42d1ff77b6d2e4984665505afae50a216290e1d7311431/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5b399ce7d967b1cb6280250818b786be652aa8ddffd3c0bb5c48c6220d945ab5", size = 2685486, upload-time = "2025-10-19T00:41:11.349Z" }, + { url = "https://files.pythonhosted.org/packages/d7/dd/88619f9c8d2b682562c0c886bbb7c35720cb83fda2ac9a41bdd14073d9bd/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e7e29a1a03f00b4322196cfe8e2c38da9a6c8d573566052c586df83aacc5663c", size = 2839661, upload-time = "2025-10-19T00:41:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/b8/8d/4478ebf471ee78dd496d254dc0f4ad729cd8e6ba8257de4f0a98a2838ef2/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5291b117d71652a817ec164e7011f18e6a51f8a352cc9a70ed5b976c51102fda", size = 2547095, upload-time = "2025-10-19T00:41:16.054Z" }, + { url = "https://files.pythonhosted.org/packages/e6/68/f1dea33367b0b3f64e199c230a14a6b6f243c189020effafd31e970ca527/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8caef62f846a9011676c51bda9189ae394cdd6bb17f2946ecaedc23243268320", size = 2870901, upload-time = "2025-10-19T00:41:17.727Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9a/33591c09dfe799b8fb692cf2ad383e2c41ab6593cc960b00d1fc8a145655/cytoolz-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:de425c5a8e3be7bb3a195e19191d28d9eb3c2038046064a92edc4505033ec9cb", size = 2765422, upload-time = "2025-10-19T00:41:20.075Z" }, + { url = "https://files.pythonhosted.org/packages/60/2b/a8aa233c9416df87f004e57ae4280bd5e1f389b4943d179f01020c6ec629/cytoolz-1.1.0-cp312-cp312-win32.whl", hash = "sha256:296440a870e8d1f2e1d1edf98f60f1532b9d3ab8dfbd4b25ec08cd76311e79e5", size = 901933, upload-time = "2025-10-19T00:41:21.646Z" }, + { url = "https://files.pythonhosted.org/packages/ad/33/4c9bdf8390dc01d2617c7f11930697157164a52259b6818ddfa2f94f89f4/cytoolz-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:07156987f224c6dac59aa18fb8bf91e1412f5463961862716a3381bf429c8699", size = 947989, upload-time = "2025-10-19T00:41:23.288Z" }, + { url = "https://files.pythonhosted.org/packages/35/ac/6e2708835875f5acb52318462ed296bf94ed0cb8c7cb70e62fbd03f709e3/cytoolz-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:23e616b38f5b3160c7bb45b0f84a8f3deb4bd26b29fb2dfc716f241c738e27b8", size = 903913, upload-time = "2025-10-19T00:41:24.992Z" }, + { url = "https://files.pythonhosted.org/packages/71/4a/b3ddb3ee44fe0045e95dd973746f93f033b6f92cce1fc3cbbe24b329943c/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:76c9b58555300be6dde87a41faf1f97966d79b9a678b7a526fcff75d28ef4945", size = 976728, upload-time = "2025-10-19T00:41:26.5Z" }, + { url = "https://files.pythonhosted.org/packages/42/21/a3681434aa425875dd828bb515924b0f12c37a55c7d2bc5c0c5de3aeb0b4/cytoolz-1.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d1d638b10d3144795655e9395566ce35807df09219fd7cacd9e6acbdef67946a", size = 986057, upload-time = "2025-10-19T00:41:28.911Z" }, + { url = "https://files.pythonhosted.org/packages/d9/cb/efc1b29e211e0670a6953222afaac84dcbba5cb940b130c0e49858978040/cytoolz-1.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:26801c1a165e84786a99e03c9c9973356caaca002d66727b761fb1042878ef06", size = 992632, upload-time = "2025-10-19T00:41:30.612Z" }, + { url = "https://files.pythonhosted.org/packages/be/b0/e50621d21e939338c97faab651f58ea7fa32101226a91de79ecfb89d71e1/cytoolz-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a9a464542912d3272f6dccc5142df057c71c6a5cbd30439389a732df401afb7", size = 1317534, upload-time = "2025-10-19T00:41:32.625Z" }, + { url = "https://files.pythonhosted.org/packages/0d/6b/25aa9739b0235a5bc4c1ea293186bc6822a4c6607acfe1422423287e7400/cytoolz-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ed6104fa942aa5784bf54f339563de637557e3443b105760bc4de8f16a7fc79b", size = 992336, upload-time = "2025-10-19T00:41:34.073Z" }, + { url = "https://files.pythonhosted.org/packages/e1/53/5f4deb0ff958805309d135d899c764364c1e8a632ce4994bd7c45fb98df2/cytoolz-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56161f0ab60dc4159ec343509abaf809dc88e85c7e420e354442c62e3e7cbb77", size = 986118, upload-time = "2025-10-19T00:41:35.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e3/f6255b76c8cc0debbe1c0779130777dc0434da6d9b28a90d9f76f8cb67cd/cytoolz-1.1.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:832bd36cc9123535f1945acf6921f8a2a15acc19cfe4065b1c9b985a28671886", size = 2679563, upload-time = "2025-10-19T00:41:37.926Z" }, + { url = "https://files.pythonhosted.org/packages/59/8a/acc6e39a84e930522b965586ad3a36694f9bf247b23188ee0eb47b1c9ed1/cytoolz-1.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1842636b6e034f229bf084c2bcdcfd36c8437e752eefd2c74ce9e2f10415cb6e", size = 2813020, upload-time = "2025-10-19T00:41:39.935Z" }, + { url = "https://files.pythonhosted.org/packages/db/f5/0083608286ad1716eda7c41f868e85ac549f6fd6b7646993109fa0bdfd98/cytoolz-1.1.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:823df012ab90d2f2a0f92fea453528539bf71ac1879e518524cd0c86aa6df7b9", size = 2669312, upload-time = "2025-10-19T00:41:41.55Z" }, + { url = "https://files.pythonhosted.org/packages/47/a8/d16080b575520fe5da00cede1ece4e0a4180ec23f88dcdc6a2f5a90a7f7f/cytoolz-1.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f1fcf9e7e7b3487883ff3f815abc35b89dcc45c4cf81c72b7ee457aa72d197b", size = 2922147, upload-time = "2025-10-19T00:41:43.252Z" }, + { url = "https://files.pythonhosted.org/packages/7e/bc/716c9c1243701e58cad511eb3937fd550e645293c5ed1907639c5d66f194/cytoolz-1.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4cdb3fa1772116827f263f25b0cdd44c663b6701346a56411960534a06c082de", size = 2981602, upload-time = "2025-10-19T00:41:45.354Z" }, + { url = "https://files.pythonhosted.org/packages/14/bc/571b232996846b27f4ac0c957dc8bf60261e9b4d0d01c8d955e82329544e/cytoolz-1.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1b5c95041741b81430454db65183e133976f45ac3c03454cfa8147952568529", size = 2830103, upload-time = "2025-10-19T00:41:47.959Z" }, + { url = "https://files.pythonhosted.org/packages/5b/55/c594afb46ecd78e4b7e1fb92c947ed041807875661ceda73baaf61baba4f/cytoolz-1.1.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b2079fd9f1a65f4c61e6278c8a6d4f85edf30c606df8d5b32f1add88cbbe2286", size = 2533802, upload-time = "2025-10-19T00:41:49.683Z" }, + { url = "https://files.pythonhosted.org/packages/93/83/1edcf95832555a78fc43b975f3ebe8ceadcc9664dd47fd33747a14df5069/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a92a320d72bef1c7e2d4c6d875125cf57fc38be45feb3fac1bfa64ea401f54a4", size = 2706071, upload-time = "2025-10-19T00:41:51.386Z" }, + { url = "https://files.pythonhosted.org/packages/e2/df/035a408df87f25cfe3611557818b250126cd2281b2104cd88395de205583/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06d1c79aa51e6a92a90b0e456ebce2288f03dd6a76c7f582bfaa3eda7692e8a5", size = 2707575, upload-time = "2025-10-19T00:41:53.305Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a4/ef78e13e16e93bf695a9331321d75fbc834a088d941f1c19e6b63314e257/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e1d7be25f6971e986a52b6d3a0da28e1941850985417c35528f6823aef2cfec5", size = 2660486, upload-time = "2025-10-19T00:41:55.542Z" }, + { url = "https://files.pythonhosted.org/packages/30/7a/2c3d60682b26058d435416c4e90d4a94db854de5be944dfd069ed1be648a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:964b248edc31efc50a65e9eaa0c845718503823439d2fa5f8d2c7e974c2b5409", size = 2819605, upload-time = "2025-10-19T00:41:58.257Z" }, + { url = "https://files.pythonhosted.org/packages/45/92/19b722a1d83cc443fbc0c16e0dc376f8a451437890d3d9ee370358cf0709/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c9ff2b3c57c79b65cb5be14a18c6fd4a06d5036fb3f33e973a9f70e9ac13ca28", size = 2533559, upload-time = "2025-10-19T00:42:00.324Z" }, + { url = "https://files.pythonhosted.org/packages/1d/15/fa3b7891da51115204416f14192081d3dea0eaee091f123fdc1347de8dd1/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:22290b73086af600042d99f5ce52a43d4ad9872c382610413176e19fc1d4fd2d", size = 2839171, upload-time = "2025-10-19T00:42:01.881Z" }, + { url = "https://files.pythonhosted.org/packages/46/40/d3519d5cd86eebebf1e8b7174ec32dfb6ecec67b48b0cfb92bf226659b5a/cytoolz-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a2ade74fccd080ea793382968913ee38d7a35c921df435bbf0a6aeecf0d17574", size = 2743379, upload-time = "2025-10-19T00:42:03.809Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/a9e7511f0a13fdbefa5bf73cf8e4763878140de9453fd3e50d6ac57b6be7/cytoolz-1.1.0-cp313-cp313-win32.whl", hash = "sha256:db5dbcfda1c00e937426cbf9bdc63c24ebbc358c3263bfcbc1ab4a88dc52aa8e", size = 900844, upload-time = "2025-10-19T00:42:05.967Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a4/fb7eb403c6a4c81e5a30363f34a71adcc8bf5292dc8ea32e2440aa5668f2/cytoolz-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9e2d3fe3b45c3eb7233746f7aca37789be3dceec3e07dcc406d3e045ea0f7bdc", size = 946461, upload-time = "2025-10-19T00:42:07.983Z" }, + { url = "https://files.pythonhosted.org/packages/93/bb/1c8c33d353548d240bc6e8677ee8c3560ce5fa2f084e928facf7c35a6dcf/cytoolz-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:32c559f95ff44a9ebcbd934acaa1e6dc8f3e6ffce4762a79a88528064873d6d5", size = 902673, upload-time = "2025-10-19T00:42:09.982Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/4a53acc60f59030fcaf48c7766e3c4c81bd997379425aa45b129396557b5/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9e2cd93b28f667c5870a070ab2b8bb4397470a85c4b204f2454b0ad001cd1ca3", size = 1372336, upload-time = "2025-10-19T00:42:12.104Z" }, + { url = "https://files.pythonhosted.org/packages/ac/90/f28fd8ad8319d8f5c8da69a2c29b8cf52a6d2c0161602d92b366d58926ab/cytoolz-1.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f494124e141a9361f31d79875fe7ea459a3be2b9dadd90480427c0c52a0943d4", size = 1011930, upload-time = "2025-10-19T00:42:14.231Z" }, + { url = "https://files.pythonhosted.org/packages/c9/95/4561c4e0ad1c944f7673d6d916405d68080f10552cfc5d69a1cf2475a9a1/cytoolz-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:53a3262bf221f19437ed544bf8c0e1980c81ac8e2a53d87a9bc075dba943d36f", size = 1020610, upload-time = "2025-10-19T00:42:15.877Z" }, + { url = "https://files.pythonhosted.org/packages/c3/14/b2e1ffa4995ec36e1372e243411ff36325e4e6d7ffa34eb4098f5357d176/cytoolz-1.1.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:47663e57d3f3f124921f38055e86a1022d0844c444ede2e8f090d3bbf80deb65", size = 2917327, upload-time = "2025-10-19T00:42:17.706Z" }, + { url = "https://files.pythonhosted.org/packages/4a/29/7cab6c609b4514ac84cca2f7dca6c509977a8fc16d27c3a50e97f105fa6a/cytoolz-1.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5a8755c4104ee4e3d5ba434c543b5f85fdee6a1f1df33d93f518294da793a60", size = 3108951, upload-time = "2025-10-19T00:42:19.363Z" }, + { url = "https://files.pythonhosted.org/packages/9a/71/1d1103b819458679277206ad07d78ca6b31c4bb88d6463fd193e19bfb270/cytoolz-1.1.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4d96ff3d381423af1b105295f97de86d1db51732c9566eb37378bab6670c5010", size = 2807149, upload-time = "2025-10-19T00:42:20.964Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d4/3d83a05a21e7d2ed2b9e6daf489999c29934b005de9190272b8a2e3735d0/cytoolz-1.1.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0ec96b3d537cdf47d4e76ded199f7440715f4c71029b45445cff92c1248808c2", size = 3111608, upload-time = "2025-10-19T00:42:22.684Z" }, + { url = "https://files.pythonhosted.org/packages/51/88/96f68354c3d4af68de41f0db4fe41a23b96a50a4a416636cea325490cfeb/cytoolz-1.1.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:208e2f2ef90a32b0acbff3303d90d89b13570a228d491d2e622a7883a3c68148", size = 3179373, upload-time = "2025-10-19T00:42:24.395Z" }, + { url = "https://files.pythonhosted.org/packages/ce/50/ed87a5cd8e6f27ffbb64c39e9730e18ec66c37631db2888ae711909f10c9/cytoolz-1.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d416a81bb0bd517558668e49d30a7475b5445f9bbafaab7dcf066f1e9adba36", size = 3003120, upload-time = "2025-10-19T00:42:26.18Z" }, + { url = "https://files.pythonhosted.org/packages/d3/a7/acde155b050d6eaa8e9c7845c98fc5fb28501568e78e83ebbf44f8855274/cytoolz-1.1.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f32e94c91ffe49af04835ee713ebd8e005c85ebe83e7e1fdcc00f27164c2d636", size = 2703225, upload-time = "2025-10-19T00:42:27.93Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b6/9d518597c5bdea626b61101e8d2ff94124787a42259dafd9f5fc396f346a/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15d0c6405efc040499c46df44056a5c382f551a7624a41cf3e4c84a96b988a15", size = 2956033, upload-time = "2025-10-19T00:42:29.993Z" }, + { url = "https://files.pythonhosted.org/packages/89/7a/93e5f860926165538c85e1c5e1670ad3424f158df810f8ccd269da652138/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:bf069c5381d757debae891401b88b3a346ba3a28ca45ba9251103b282463fad8", size = 2862950, upload-time = "2025-10-19T00:42:31.803Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/99d6af00487bedc27597b54c9fcbfd5c833a69c6b7a9b9f0fff777bfc7aa/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d5cf15892e63411ec1bd67deff0e84317d974e6ab2cdfefdd4a7cea2989df66", size = 2861757, upload-time = "2025-10-19T00:42:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/71/ca/adfa1fb7949478135a37755cb8e88c20cd6b75c22a05f1128f05f3ab2c60/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3e3872c21170f8341656f8692f8939e8800dcee6549ad2474d4c817bdefd62cd", size = 2979049, upload-time = "2025-10-19T00:42:35.377Z" }, + { url = "https://files.pythonhosted.org/packages/70/4c/7bf47a03a4497d500bc73d4204e2d907771a017fa4457741b2a1d7c09319/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b9ddeff8e8fd65eb1fcefa61018100b2b627e759ea6ad275d2e2a93ffac147bf", size = 2699492, upload-time = "2025-10-19T00:42:37.133Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e7/3d034b0e4817314f07aa465d5864e9b8df9d25cb260a53dd84583e491558/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:02feeeda93e1fa3b33414eb57c2b0aefd1db8f558dd33fdfcce664a0f86056e4", size = 2995646, upload-time = "2025-10-19T00:42:38.912Z" }, + { url = "https://files.pythonhosted.org/packages/c1/62/be357181c71648d9fe1d1ce91cd42c63457dcf3c158e144416fd51dced83/cytoolz-1.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d08154ad45349162b6c37f12d5d1b2e6eef338e657b85e1621e4e6a4a69d64cb", size = 2919481, upload-time = "2025-10-19T00:42:40.85Z" }, + { url = "https://files.pythonhosted.org/packages/62/d5/bf5434fde726c4f80cb99912b2d8e0afa1587557e2a2d7e0315eb942f2de/cytoolz-1.1.0-cp313-cp313t-win32.whl", hash = "sha256:10ae4718a056948d73ca3e1bb9ab1f95f897ec1e362f829b9d37cc29ab566c60", size = 951595, upload-time = "2025-10-19T00:42:42.877Z" }, + { url = "https://files.pythonhosted.org/packages/64/29/39c161e9204a9715321ddea698cbd0abc317e78522c7c642363c20589e71/cytoolz-1.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:1bb77bc6197e5cb19784b6a42bb0f8427e81737a630d9d7dda62ed31733f9e6c", size = 1004445, upload-time = "2025-10-19T00:42:44.855Z" }, + { url = "https://files.pythonhosted.org/packages/e2/5a/7cbff5e9a689f558cb0bdf277f9562b2ac51acf7cd15e055b8c3efb0e1ef/cytoolz-1.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:563dda652c6ff52d215704fbe6b491879b78d7bbbb3a9524ec8e763483cb459f", size = 926207, upload-time = "2025-10-19T00:42:46.456Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e8/297a85ba700f437c01eba962428e6ab4572f6c3e68e8ff442ce5c9d3a496/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d542cee7c7882d2a914a33dec4d3600416fb336734df979473249d4c53d207a1", size = 980613, upload-time = "2025-10-19T00:42:47.988Z" }, + { url = "https://files.pythonhosted.org/packages/e8/d7/2b02c9d18e9cc263a0e22690f78080809f1eafe72f26b29ccc115d3bf5c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31922849b701b0f24bb62e56eb2488dcd3aa6ae3057694bd6b3b7c4c2bc27c2f", size = 990476, upload-time = "2025-10-19T00:42:49.653Z" }, + { url = "https://files.pythonhosted.org/packages/89/26/b6b159d2929310fca0eff8a4989cd4b1ecbdf7c46fdff46c7a20fcae55c8/cytoolz-1.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e68308d32afd31943314735c1335e4ab5696110e96b405f6bdb8f2a8dc771a16", size = 992712, upload-time = "2025-10-19T00:42:51.306Z" }, + { url = "https://files.pythonhosted.org/packages/42/a0/f7c572aa151ed466b0fce4a327c3cc916d3ef3c82e341be59ea4b9bee9e4/cytoolz-1.1.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fc4bb48b3b866e1867f7c6411a4229e5b44be3989060663713e10efc24c9bd5f", size = 1322596, upload-time = "2025-10-19T00:42:52.978Z" }, + { url = "https://files.pythonhosted.org/packages/72/7c/a55d035e20b77b6725e85c8f1a418b3a4c23967288b8b0c2d1a40f158cbe/cytoolz-1.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:456f77207d1445025d7ef262b8370a05492dcb1490cb428b0f3bf1bd744a89b0", size = 992825, upload-time = "2025-10-19T00:42:55.026Z" }, + { url = "https://files.pythonhosted.org/packages/03/af/39d2d3db322136e12e9336a1f13bab51eab88b386bfb11f91d3faff8ba34/cytoolz-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:174ebc71ebb20a9baeffce6ee07ee2cd913754325c93f99d767380d8317930f7", size = 990525, upload-time = "2025-10-19T00:42:56.666Z" }, + { url = "https://files.pythonhosted.org/packages/a6/bd/65d7a869d307f9b10ad45c2c1cbb40b81a8d0ed1138fa17fd904f5c83298/cytoolz-1.1.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8b3604fef602bcd53415055a4f68468339192fd17be39e687ae24f476d23d56e", size = 2672409, upload-time = "2025-10-19T00:42:58.81Z" }, + { url = "https://files.pythonhosted.org/packages/2d/fb/74dfd844bfd67e810bd36e8e3903a143035447245828e7fcd7c81351d775/cytoolz-1.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3604b959a01f64c366e7d10ec7634d5f5cfe10301e27a8f090f6eb3b2a628a18", size = 2808477, upload-time = "2025-10-19T00:43:00.577Z" }, + { url = "https://files.pythonhosted.org/packages/d6/1f/587686c43e31c19241ec317da66438d093523921ea7749bbc65558a30df9/cytoolz-1.1.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6db2127a3c1bc2f59f08010d2ae53a760771a9de2f67423ad8d400e9ba4276e8", size = 2636881, upload-time = "2025-10-19T00:43:02.24Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6d/90468cd34f77cb38a11af52c4dc6199efcc97a486395a21bef72e9b7602e/cytoolz-1.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56584745ac647993a016a21bc76399113b7595e312f8d0a1b140c9fcf9b58a27", size = 2937315, upload-time = "2025-10-19T00:43:03.954Z" }, + { url = "https://files.pythonhosted.org/packages/d9/50/7b92cd78c613b92e3509e6291d3fb7e0d72ebda999a8df806a96c40ca9ab/cytoolz-1.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db2c4c3a7f7bd7e03bb1a236a125c8feb86c75802f4ecda6ecfaf946610b2930", size = 2959988, upload-time = "2025-10-19T00:43:05.758Z" }, + { url = "https://files.pythonhosted.org/packages/44/d5/34b5a28a8d9bb329f984b4c2259407ca3f501d1abeb01bacea07937d85d1/cytoolz-1.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48cb8a692111a285d2b9acd16d185428176bfbffa8a7c274308525fccd01dd42", size = 2795116, upload-time = "2025-10-19T00:43:07.411Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d9/5dd829e33273ec03bdc3c812e6c3281987ae2c5c91645582f6c331544a64/cytoolz-1.1.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d2f344ba5eb17dcf38ee37fdde726f69053f54927db8f8a1bed6ac61e5b1890d", size = 2535390, upload-time = "2025-10-19T00:43:09.104Z" }, + { url = "https://files.pythonhosted.org/packages/87/1f/7f9c58068a8eec2183110df051bc6b69dd621143f84473eeb6dc1b32905a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:abf76b1c1abd031f098f293b6d90ee08bdaa45f8b5678430e331d991b82684b1", size = 2704834, upload-time = "2025-10-19T00:43:10.942Z" }, + { url = "https://files.pythonhosted.org/packages/d2/90/667def5665333575d01a65fe3ec0ca31b897895f6e3bc1a42d6ea3659369/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ddf9a38a5b686091265ff45b53d142e44a538cd6c2e70610d3bc6be094219032", size = 2658441, upload-time = "2025-10-19T00:43:12.655Z" }, + { url = "https://files.pythonhosted.org/packages/23/79/6615f9a14960bd29ac98b823777b6589357833f65cf1a11b5abc1587c120/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:946786755274f07bb2be0400f28adb31d7d85a7c7001873c0a8e24a503428fb3", size = 2654766, upload-time = "2025-10-19T00:43:14.325Z" }, + { url = "https://files.pythonhosted.org/packages/b0/99/be59c6e0ae02153ef10ae1ff0f380fb19d973c651b50cf829a731f6c9e79/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:d5b8f78b9fed79cf185ad4ddec099abeef45951bdcb416c5835ba05f0a1242c7", size = 2827649, upload-time = "2025-10-19T00:43:16.132Z" }, + { url = "https://files.pythonhosted.org/packages/19/b7/854ddcf9f9618844108677c20d48f4611b5c636956adea0f0e85e027608f/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fccde6efefdbc02e676ccb352a2ccc8a8e929f59a1c6d3d60bb78e923a49ca44", size = 2533456, upload-time = "2025-10-19T00:43:17.764Z" }, + { url = "https://files.pythonhosted.org/packages/45/66/bfe6fbb2bdcf03c8377c8c2f542576e15f3340c905a09d78a6cb3badd39a/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:717b7775313da5f51b0fbf50d865aa9c39cb241bd4cb605df3cf2246d6567397", size = 2826455, upload-time = "2025-10-19T00:43:19.561Z" }, + { url = "https://files.pythonhosted.org/packages/c3/0c/cce4047bd927e95f59e73319c02c9bc86bd3d76392e0eb9e41a1147a479c/cytoolz-1.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5158744a09d0e0e4a4f82225e3a3c4ebf38f9ae74467aaa905467270e52f2794", size = 2714897, upload-time = "2025-10-19T00:43:21.291Z" }, + { url = "https://files.pythonhosted.org/packages/ac/9a/061323bb289b565802bad14fb7ab59fcd8713105df142bcf4dd9ff64f8ac/cytoolz-1.1.0-cp314-cp314-win32.whl", hash = "sha256:1ed534bdbbf063b2bb28fca7d0f6723a3e5a72b086e7c7fe6d74ae8c3e4d00e2", size = 901490, upload-time = "2025-10-19T00:43:22.895Z" }, + { url = "https://files.pythonhosted.org/packages/a3/20/1f3a733d710d2a25d6f10b463bef55ada52fe6392a5d233c8d770191f48a/cytoolz-1.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:472c1c9a085f5ad973ec0ad7f0b9ba0969faea6f96c9e397f6293d386f3a25ec", size = 946730, upload-time = "2025-10-19T00:43:24.838Z" }, + { url = "https://files.pythonhosted.org/packages/f2/22/2d657db4a5d1c10a152061800f812caba9ef20d7bd2406f51a5fd800c180/cytoolz-1.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:a7ad7ca3386fa86bd301be3fa36e7f0acb024f412f665937955acfc8eb42deff", size = 905722, upload-time = "2025-10-19T00:43:26.439Z" }, + { url = "https://files.pythonhosted.org/packages/19/97/b4a8c76796a9a8b9bc90c7992840fa1589a1af8e0426562dea4ce9b384a7/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:64b63ed4b71b1ba813300ad0f06b8aff19a12cf51116e0e4f1ed837cea4debcf", size = 1372606, upload-time = "2025-10-19T00:43:28.491Z" }, + { url = "https://files.pythonhosted.org/packages/08/d4/a1bb1a32b454a2d650db8374ff3bf875ba0fc1c36e6446ec02a83b9140a1/cytoolz-1.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a60ba6f2ed9eb0003a737e1ee1e9fa2258e749da6477946008d4324efa25149f", size = 1012189, upload-time = "2025-10-19T00:43:30.177Z" }, + { url = "https://files.pythonhosted.org/packages/21/4b/2f5cbbd81588918ee7dd70cffb66731608f578a9b72166aafa991071af7d/cytoolz-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1aa58e2434d732241f7f051e6f17657e969a89971025e24578b5cbc6f1346485", size = 1020624, upload-time = "2025-10-19T00:43:31.712Z" }, + { url = "https://files.pythonhosted.org/packages/f5/99/c4954dd86cd593cd776a038b36795a259b8b5c12cbab6363edf5f6d9c909/cytoolz-1.1.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6965af3fc7214645970e312deb9bd35a213a1eaabcfef4f39115e60bf2f76867", size = 2917016, upload-time = "2025-10-19T00:43:33.531Z" }, + { url = "https://files.pythonhosted.org/packages/b2/7c/f1f70a17e272b433232bc8a27df97e46b202d6cc07e3b0d63f7f41ba0f2d/cytoolz-1.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddd2863f321d67527d3b67a93000a378ad6f967056f68c06467fe011278a6d0e", size = 3107634, upload-time = "2025-10-19T00:43:35.57Z" }, + { url = "https://files.pythonhosted.org/packages/8f/bd/c3226a57474b4aef1f90040510cba30d0decd3515fed48dc229b37c2f898/cytoolz-1.1.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4e6b428e9eb5126053c2ae0efa62512ff4b38ed3951f4d0888ca7005d63e56f5", size = 2806221, upload-time = "2025-10-19T00:43:37.707Z" }, + { url = "https://files.pythonhosted.org/packages/c3/47/2f7bfe4aaa1e07dc9828bea228ed744faf73b26aee0c1bdf3b5520bf1909/cytoolz-1.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d758e5ef311d2671e0ae8c214c52e44617cf1e58bef8f022b547b9802a5a7f30", size = 3107671, upload-time = "2025-10-19T00:43:39.401Z" }, + { url = "https://files.pythonhosted.org/packages/4d/12/6ff3b04fbd1369d0fcd5f8b5910ba6e427e33bf113754c4c35ec3f747924/cytoolz-1.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a95416eca473e6c1179b48d86adcf528b59c63ce78f4cb9934f2e413afa9b56b", size = 3176350, upload-time = "2025-10-19T00:43:41.148Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/6691d986b728e77b5d2872743ebcd962d37a2d0f7e9ad95a81b284fbf905/cytoolz-1.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36c8ede93525cf11e2cc787b7156e5cecd7340193ef800b816a16f1404a8dc6d", size = 3001173, upload-time = "2025-10-19T00:43:42.923Z" }, + { url = "https://files.pythonhosted.org/packages/7a/cb/f59d83a5058e1198db5a1f04e4a124c94d60390e4fa89b6d2e38ee8288a0/cytoolz-1.1.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c949755b6d8a649c5fbc888bc30915926f1b09fe42fea9f289e297c2f6ddd3", size = 2701374, upload-time = "2025-10-19T00:43:44.716Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f0/1ae6d28df503b0bdae094879da2072b8ba13db5919cd3798918761578411/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e1b6d37545816905a76d9ed59fa4e332f929e879f062a39ea0f6f620405cdc27", size = 2953081, upload-time = "2025-10-19T00:43:47.103Z" }, + { url = "https://files.pythonhosted.org/packages/f4/06/d86fe811c6222dc32d3e08f5d88d2be598a6055b4d0590e7c1428d55c386/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:05332112d4087904842b36954cd1d3fc0e463a2f4a7ef9477bd241427c593c3b", size = 2862228, upload-time = "2025-10-19T00:43:49.353Z" }, + { url = "https://files.pythonhosted.org/packages/ae/32/978ef6f42623be44a0a03ae9de875ab54aa26c7e38c5c4cd505460b0927d/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:31538ca2fad2d688cbd962ccc3f1da847329e2258a52940f10a2ac0719e526be", size = 2861971, upload-time = "2025-10-19T00:43:51.028Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f7/74c69497e756b752b359925d1feef68b91df024a4124a823740f675dacd3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:747562aa70abf219ea16f07d50ac0157db856d447f7f498f592e097cbc77df0b", size = 2975304, upload-time = "2025-10-19T00:43:52.99Z" }, + { url = "https://files.pythonhosted.org/packages/5b/2b/3ce0e6889a6491f3418ad4d84ae407b8456b02169a5a1f87990dbba7433b/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:3dc15c48b20c0f467e15e341e102896c8422dccf8efc6322def5c1b02f074629", size = 2697371, upload-time = "2025-10-19T00:43:55.312Z" }, + { url = "https://files.pythonhosted.org/packages/15/87/c616577f0891d97860643c845f7221e95240aa589586de727e28a5eb6e52/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3c03137ee6103ba92d5d6ad6a510e86fded69cd67050bd8a1843f15283be17ac", size = 2992436, upload-time = "2025-10-19T00:43:57.253Z" }, + { url = "https://files.pythonhosted.org/packages/e7/9f/490c81bffb3428ab1fa114051fbb5ba18aaa2e2fe4da5bf4170ca524e6b3/cytoolz-1.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:be8e298d88f88bd172b59912240558be3b7a04959375646e7fd4996401452941", size = 2917612, upload-time = "2025-10-19T00:43:59.423Z" }, + { url = "https://files.pythonhosted.org/packages/66/35/0fec2769660ca6472bbf3317ab634675827bb706d193e3240aaf20eab961/cytoolz-1.1.0-cp314-cp314t-win32.whl", hash = "sha256:3d407140f5604a89578285d4aac7b18b8eafa055cf776e781aabb89c48738fad", size = 960842, upload-time = "2025-10-19T00:44:01.143Z" }, + { url = "https://files.pythonhosted.org/packages/46/b4/b7ce3d3cd20337becfec978ecfa6d0ef64884d0cf32d44edfed8700914b9/cytoolz-1.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:56e5afb69eb6e1b3ffc34716ee5f92ffbdb5cb003b3a5ca4d4b0fe700e217162", size = 1020835, upload-time = "2025-10-19T00:44:03.246Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1f/0498009aa563a9c5d04f520aadc6e1c0942434d089d0b2f51ea986470f55/cytoolz-1.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:27b19b4a286b3ff52040efa42dbe403730aebe5fdfd2def704eb285e2125c63e", size = 927963, upload-time = "2025-10-19T00:44:04.85Z" }, + { url = "https://files.pythonhosted.org/packages/84/32/0522207170294cf691112a93c70a8ef942f60fa9ff8e793b63b1f09cedc0/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f32e93a55681d782fc6af939f6df36509d65122423cbc930be39b141064adff8", size = 922014, upload-time = "2025-10-19T00:44:44.911Z" }, + { url = "https://files.pythonhosted.org/packages/4c/49/9be2d24adaa18fa307ff14e3e43f02b2ae4b69c4ce51cee6889eb2114990/cytoolz-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:5d9bc596751cbda8073e65be02ca11706f00029768fbbbc81e11a8c290bb41aa", size = 918134, upload-time = "2025-10-19T00:44:47.122Z" }, + { url = "https://files.pythonhosted.org/packages/5c/b3/6a76c3b94c6c87c72ea822e7e67405be6b649c2e37778eeac7c0c0c69de8/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9b16660d01c3931951fab49db422c627897c38c1a1f0393a97582004019a4887", size = 981970, upload-time = "2025-10-19T00:44:48.906Z" }, + { url = "https://files.pythonhosted.org/packages/f6/8a/606e4c7ed14aa6a86aee6ca84a2cb804754dc6c4905b8f94e09e49f1ce60/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b7de5718e2113d4efccea3f06055758cdbc17388ecc3341ba4d1d812837d7c1a", size = 978877, upload-time = "2025-10-19T00:44:50.819Z" }, + { url = "https://files.pythonhosted.org/packages/97/ec/ad474dcb1f6c1ebfdda3c2ad2edbb1af122a0e79c9ff2cb901ffb5f59662/cytoolz-1.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a12a2a1a6bc44099491c05a12039efa08cc33a3d0f8c7b0566185e085e139283", size = 964279, upload-time = "2025-10-19T00:44:52.476Z" }, + { url = "https://files.pythonhosted.org/packages/68/8c/d245fd416c69d27d51f14d5ad62acc4ee5971088ee31c40ffe1cc109af68/cytoolz-1.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:047defa7f5f9a32f82373dbc3957289562e8a3fa58ae02ec8e4dca4f43a33a21", size = 916630, upload-time = "2025-10-19T00:44:54.059Z" }, ] [[package]] @@ -506,9 +508,9 @@ dependencies = [ { name = "eth-utils" }, { name = "parsimonious" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/71/d9e1380bd77fd22f98b534699af564f189b56d539cc2b9dab908d4e4c242/eth_abi-5.2.0.tar.gz", hash = "sha256:178703fa98c07d8eecd5ae569e7e8d159e493ebb6eeb534a8fe973fbc4e40ef0", size = 49797 } +sdist = { url = "https://files.pythonhosted.org/packages/00/71/d9e1380bd77fd22f98b534699af564f189b56d539cc2b9dab908d4e4c242/eth_abi-5.2.0.tar.gz", hash = "sha256:178703fa98c07d8eecd5ae569e7e8d159e493ebb6eeb534a8fe973fbc4e40ef0", size = 49797, upload-time = "2025-01-14T16:29:34.629Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/b4/2f3982c4cbcbf5eeb6aec62df1533c0e63c653b3021ff338d44944405676/eth_abi-5.2.0-py3-none-any.whl", hash = "sha256:17abe47560ad753f18054f5b3089fcb588f3e3a092136a416b6c1502cb7e8877", size = 28511 }, + { url = "https://files.pythonhosted.org/packages/7a/b4/2f3982c4cbcbf5eeb6aec62df1533c0e63c653b3021ff338d44944405676/eth_abi-5.2.0-py3-none-any.whl", hash = "sha256:17abe47560ad753f18054f5b3089fcb588f3e3a092136a416b6c1502cb7e8877", size = 28511, upload-time = "2025-01-14T16:29:31.862Z" }, ] [[package]] @@ -527,18 +529,18 @@ dependencies = [ { name = "pydantic" }, { name = "rlp" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/cf/20f76a29be97339c969fd765f1237154286a565a1d61be98e76bb7af946a/eth_account-0.13.7.tar.gz", hash = "sha256:5853ecbcbb22e65411176f121f5f24b8afeeaf13492359d254b16d8b18c77a46", size = 935998 } +sdist = { url = "https://files.pythonhosted.org/packages/74/cf/20f76a29be97339c969fd765f1237154286a565a1d61be98e76bb7af946a/eth_account-0.13.7.tar.gz", hash = "sha256:5853ecbcbb22e65411176f121f5f24b8afeeaf13492359d254b16d8b18c77a46", size = 935998, upload-time = "2025-04-21T21:11:21.204Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/18/088fb250018cbe665bc2111974301b2d59f294a565aff7564c4df6878da2/eth_account-0.13.7-py3-none-any.whl", hash = "sha256:39727de8c94d004ff61d10da7587509c04d2dc7eac71e04830135300bdfc6d24", size = 587452 }, + { url = "https://files.pythonhosted.org/packages/46/18/088fb250018cbe665bc2111974301b2d59f294a565aff7564c4df6878da2/eth_account-0.13.7-py3-none-any.whl", hash = "sha256:39727de8c94d004ff61d10da7587509c04d2dc7eac71e04830135300bdfc6d24", size = 587452, upload-time = "2025-04-21T21:11:18.346Z" }, ] [[package]] name = "eth-hash" version = "0.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3c/f5/c67fc24f2f676aa9b7ab29679d44f113f314c817207cd4319353356f62da/eth_hash-0.8.0.tar.gz", hash = "sha256:b009752b620da2e9c7668014849d1f5fadbe4f138603f1871cc5d4ca706896b1", size = 12225 } +sdist = { url = "https://files.pythonhosted.org/packages/3c/f5/c67fc24f2f676aa9b7ab29679d44f113f314c817207cd4319353356f62da/eth_hash-0.8.0.tar.gz", hash = "sha256:b009752b620da2e9c7668014849d1f5fadbe4f138603f1871cc5d4ca706896b1", size = 12225, upload-time = "2026-03-25T16:36:55.099Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/87/87/b36792150ca0b28e4df683a34be15a61461ca0e349e5b5cf3ec8f694edb9/eth_hash-0.8.0-py3-none-any.whl", hash = "sha256:523718a51b369ab89866b929a5c93c52978cd866ea309192ad980dd8271f9fac", size = 7965 }, + { url = "https://files.pythonhosted.org/packages/87/87/b36792150ca0b28e4df683a34be15a61461ca0e349e5b5cf3ec8f694edb9/eth_hash-0.8.0-py3-none-any.whl", hash = "sha256:523718a51b369ab89866b929a5c93c52978cd866ea309192ad980dd8271f9fac", size = 7965, upload-time = "2026-03-25T16:36:54.205Z" }, ] [[package]] @@ -550,9 +552,9 @@ dependencies = [ { name = "eth-utils" }, { name = "pycryptodome" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/35/66/dd823b1537befefbbff602e2ada88f1477c5b40ec3731e3d9bc676c5f716/eth_keyfile-0.8.1.tar.gz", hash = "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1", size = 12267 } +sdist = { url = "https://files.pythonhosted.org/packages/35/66/dd823b1537befefbbff602e2ada88f1477c5b40ec3731e3d9bc676c5f716/eth_keyfile-0.8.1.tar.gz", hash = "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1", size = 12267, upload-time = "2024-04-23T20:28:53.862Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/fc/48a586175f847dd9e05e5b8994d2fe8336098781ec2e9836a2ad94280281/eth_keyfile-0.8.1-py3-none-any.whl", hash = "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64", size = 7510 }, + { url = "https://files.pythonhosted.org/packages/88/fc/48a586175f847dd9e05e5b8994d2fe8336098781ec2e9836a2ad94280281/eth_keyfile-0.8.1-py3-none-any.whl", hash = "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64", size = 7510, upload-time = "2024-04-23T20:28:51.063Z" }, ] [[package]] @@ -563,9 +565,9 @@ dependencies = [ { name = "eth-typing" }, { name = "eth-utils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/58/11/1ed831c50bd74f57829aa06e58bd82a809c37e070ee501c953b9ac1f1552/eth_keys-0.7.0.tar.gz", hash = "sha256:79d24fd876201df67741de3e3fefb3f4dbcbb6ace66e47e6fe662851a4547814", size = 30166 } +sdist = { url = "https://files.pythonhosted.org/packages/58/11/1ed831c50bd74f57829aa06e58bd82a809c37e070ee501c953b9ac1f1552/eth_keys-0.7.0.tar.gz", hash = "sha256:79d24fd876201df67741de3e3fefb3f4dbcbb6ace66e47e6fe662851a4547814", size = 30166, upload-time = "2025-04-07T17:40:21.697Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/25/0ae00f2b0095e559d61ad3dc32171bd5a29dfd95ab04b4edd641f7c75f72/eth_keys-0.7.0-py3-none-any.whl", hash = "sha256:b0cdda8ffe8e5ba69c7c5ca33f153828edcace844f67aabd4542d7de38b159cf", size = 20656 }, + { url = "https://files.pythonhosted.org/packages/4d/25/0ae00f2b0095e559d61ad3dc32171bd5a29dfd95ab04b4edd641f7c75f72/eth_keys-0.7.0-py3-none-any.whl", hash = "sha256:b0cdda8ffe8e5ba69c7c5ca33f153828edcace844f67aabd4542d7de38b159cf", size = 20656, upload-time = "2025-04-07T17:40:20.441Z" }, ] [[package]] @@ -578,9 +580,9 @@ dependencies = [ { name = "rlp" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7f/ea/ad39d001fa9fed07fad66edb00af701e29b48be0ed44a3bcf58cb3adf130/eth_rlp-2.2.0.tar.gz", hash = "sha256:5e4b2eb1b8213e303d6a232dfe35ab8c29e2d3051b86e8d359def80cd21db83d", size = 7720 } +sdist = { url = "https://files.pythonhosted.org/packages/7f/ea/ad39d001fa9fed07fad66edb00af701e29b48be0ed44a3bcf58cb3adf130/eth_rlp-2.2.0.tar.gz", hash = "sha256:5e4b2eb1b8213e303d6a232dfe35ab8c29e2d3051b86e8d359def80cd21db83d", size = 7720, upload-time = "2025-02-04T21:51:08.134Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/3b/57efe2bc2df0980680d57c01a36516cd3171d2319ceb30e675de19fc2cc5/eth_rlp-2.2.0-py3-none-any.whl", hash = "sha256:5692d595a741fbaef1203db6a2fedffbd2506d31455a6ad378c8449ee5985c47", size = 4446 }, + { url = "https://files.pythonhosted.org/packages/99/3b/57efe2bc2df0980680d57c01a36516cd3171d2319ceb30e675de19fc2cc5/eth_rlp-2.2.0-py3-none-any.whl", hash = "sha256:5692d595a741fbaef1203db6a2fedffbd2506d31455a6ad378c8449ee5985c47", size = 4446, upload-time = "2025-02-04T21:51:05.823Z" }, ] [[package]] @@ -590,9 +592,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/37/e7/06c5af99ad40494f6d10126a9030ff4eb14c5b773f2a4076017efb0a163a/eth_typing-6.0.0.tar.gz", hash = "sha256:315dd460dc0b71c15a6cd51e3c0b70d237eec8771beb844144f3a1fb4adb2392", size = 21852 } +sdist = { url = "https://files.pythonhosted.org/packages/37/e7/06c5af99ad40494f6d10126a9030ff4eb14c5b773f2a4076017efb0a163a/eth_typing-6.0.0.tar.gz", hash = "sha256:315dd460dc0b71c15a6cd51e3c0b70d237eec8771beb844144f3a1fb4adb2392", size = 21852, upload-time = "2026-03-25T16:41:57.444Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/0d/e756622fab29f404d846d7464f929d642a7ee6eff5b38bcc79e7c64ac630/eth_typing-6.0.0-py3-none-any.whl", hash = "sha256:ee74fb641eb36dd885e1c42c2a3055314efa532b3e71480816df70a94d35cfb9", size = 19191 }, + { url = "https://files.pythonhosted.org/packages/aa/0d/e756622fab29f404d846d7464f929d642a7ee6eff5b38bcc79e7c64ac630/eth_typing-6.0.0-py3-none-any.whl", hash = "sha256:ee74fb641eb36dd885e1c42c2a3055314efa532b3e71480816df70a94d35cfb9", size = 19191, upload-time = "2026-03-25T16:41:55.544Z" }, ] [[package]] @@ -606,9 +608,9 @@ dependencies = [ { name = "pydantic" }, { name = "toolz", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e9/1b/0b8548da7b31eba87ed58bca1d0de5dcb13a6c113e02c09019ec5a6716ed/eth_utils-6.0.0.tar.gz", hash = "sha256:eb54b2f82dd300d3142c49a89da195e823f5e5284d43203593f87c67bad92a96", size = 123457 } +sdist = { url = "https://files.pythonhosted.org/packages/e9/1b/0b8548da7b31eba87ed58bca1d0de5dcb13a6c113e02c09019ec5a6716ed/eth_utils-6.0.0.tar.gz", hash = "sha256:eb54b2f82dd300d3142c49a89da195e823f5e5284d43203593f87c67bad92a96", size = 123457, upload-time = "2026-03-25T17:11:51.433Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/53/45/a20b907227b9d1aea2e36f7b12818d055629ca9bc65fc282b45738f28ca3/eth_utils-6.0.0-py3-none-any.whl", hash = "sha256:63cf48ee32c45541cb5748751909a8345c470432fb6f0fed4bd7c53fd6400469", size = 102473 }, + { url = "https://files.pythonhosted.org/packages/53/45/a20b907227b9d1aea2e36f7b12818d055629ca9bc65fc282b45738f28ca3/eth_utils-6.0.0-py3-none-any.whl", hash = "sha256:63cf48ee32c45541cb5748751909a8345c470432fb6f0fed4bd7c53fd6400469", size = 102473, upload-time = "2026-03-25T17:11:49.953Z" }, ] [[package]] @@ -616,29 +618,29 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371 } +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740 }, + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] name = "execnet" version = "2.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622 } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708 }, + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, ] [[package]] name = "hexbytes" version = "1.3.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7f/87/adf4635b4b8c050283d74e6db9a81496063229c9263e6acc1903ab79fbec/hexbytes-1.3.1.tar.gz", hash = "sha256:a657eebebdfe27254336f98d8af6e2236f3f83aed164b87466b6cf6c5f5a4765", size = 8633 } +sdist = { url = "https://files.pythonhosted.org/packages/7f/87/adf4635b4b8c050283d74e6db9a81496063229c9263e6acc1903ab79fbec/hexbytes-1.3.1.tar.gz", hash = "sha256:a657eebebdfe27254336f98d8af6e2236f3f83aed164b87466b6cf6c5f5a4765", size = 8633, upload-time = "2025-05-14T16:45:17.5Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/e0/3b31492b1c89da3c5a846680517871455b30c54738486fc57ac79a5761bd/hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7", size = 5074 }, + { url = "https://files.pythonhosted.org/packages/8d/e0/3b31492b1c89da3c5a846680517871455b30c54738486fc57ac79a5761bd/hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7", size = 5074, upload-time = "2025-05-14T16:45:16.179Z" }, ] [[package]] @@ -649,74 +651,74 @@ dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/41/96/35022710908b82d20af0c57ab8be4d4a3e4045a74d3ae9c806eb4443297c/hypothesis-6.161.0.tar.gz", hash = "sha256:c357150f826fc7492304621d535a23e8f1b7440a3b10a337c23bea52102e2e7f", size = 485855 } +sdist = { url = "https://files.pythonhosted.org/packages/41/96/35022710908b82d20af0c57ab8be4d4a3e4045a74d3ae9c806eb4443297c/hypothesis-6.161.0.tar.gz", hash = "sha256:c357150f826fc7492304621d535a23e8f1b7440a3b10a337c23bea52102e2e7f", size = 485855, upload-time = "2026-07-23T07:17:40.745Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/b9/c8b80fb7517e6f3039d0ef9a5df6aaee53667935e62c6c9d9d635436708d/hypothesis-6.161.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c9f877e288dfb46207b5c3bfcc8ab28e2613e529be8621816423960403377286", size = 766230 }, - { url = "https://files.pythonhosted.org/packages/90/16/e5c1287fee682f7c1e9afccc91c07ae36a6855a5863d0b3c15d7bfa0b322/hypothesis-6.161.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b7b6980265cb04605b2b42132dc8ef5735917fc482869298611a49d2e06dc322", size = 761883 }, - { url = "https://files.pythonhosted.org/packages/c9/b8/d9792e24e53f82bb1455935f79cf3b56ccf556fac325c8a90f7968180706/hypothesis-6.161.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f10253cac459922cad3bc09e397718188e57dffefe810e5db1d444e7113d7fb5", size = 1091083 }, - { url = "https://files.pythonhosted.org/packages/f7/15/33cba9c6bee8a80ab18f48e40669038275bf4b82e8dfb0fa9fe716925265/hypothesis-6.161.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:232ab78dd8cb0a891914d20697e0fd340ca1e6d4d8d5855df5e433d8161173e2", size = 1140530 }, - { url = "https://files.pythonhosted.org/packages/bb/f6/30c421822cd65b8edd56b2b90a5e1acf4a624d5619067957668027ab7e46/hypothesis-6.161.0-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:264336ca1e9f31edd24a8885c4020db8e18986c51a255613db28c076ac4289a8", size = 1132680 }, - { url = "https://files.pythonhosted.org/packages/e9/db/d18e45339b2ffda57a52395e03df6166bc4e428bc90e878dd3f20a7423c0/hypothesis-6.161.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:323aac4347e6ffa86929407b7f386cbf54e1c66faf923ffd6b4b86c21815d117", size = 1264892 }, - { url = "https://files.pythonhosted.org/packages/c7/7e/f4b7600272fbc9a2b28c95b96059d89cf5093ae705e52360a818df8154a5/hypothesis-6.161.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5dc83c8e83b9d133babcf9468703cece0ddb25413983561f2516927edddcc52d", size = 1307563 }, - { url = "https://files.pythonhosted.org/packages/d6/28/fa4f2d50c7434076ec7653a8372750531576e4d11cd5f3316ad83e12a553/hypothesis-6.161.0-cp310-abi3-win32.whl", hash = "sha256:75a3036121e6ae2cf55b7433f1953834cc9eca97c2e4e4be3369fe080c86b237", size = 652098 }, - { url = "https://files.pythonhosted.org/packages/93/5c/6811eee772a5cc33f9bf863326983f493977e9aee9535c8dbb6c172575d3/hypothesis-6.161.0-cp310-abi3-win_amd64.whl", hash = "sha256:e3f5b2527789a748b54d6ef46b2b042f3225164d54c24ba74a137ddb10a39407", size = 658272 }, - { url = "https://files.pythonhosted.org/packages/97/97/49216c1087962033451cc6e3093deb765b0d14eed7dda2980f6d8dfc9062/hypothesis-6.161.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:38eea270b81398c9e2c7eed028f53ba51dc7005eb97fa681c7c90007ba029423", size = 766930 }, - { url = "https://files.pythonhosted.org/packages/9a/6d/766a280bea353045ae7311ba847a50ebb939155e2a990fd08040be2b6b5b/hypothesis-6.161.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6b7183980c7729d7cf084ab26c127e4c591876536278ecb84ed2449d4d93f4e", size = 762699 }, - { url = "https://files.pythonhosted.org/packages/62/86/f28648668b5ce18bba7ae846c629c54427aa622a76280309c3bc3dca4f2d/hypothesis-6.161.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3e60bbe528d6005373146808bd0b5e618bf1a20e912c0568ae56802e8c455fc", size = 1091551 }, - { url = "https://files.pythonhosted.org/packages/52/e3/3ae24ad1056e1c992dade22e9c784c93d57ea0dc3ff9fa6a48683548489d/hypothesis-6.161.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3167e3153a9b8a8ad43284a22cbe1e3c1819d6d944f727f9810bb115a9c2ade", size = 1141106 }, - { url = "https://files.pythonhosted.org/packages/c4/37/fa3a21edcd7c4a104d6782ee98135af8ef86ae42d39ea9eb55072f84b668/hypothesis-6.161.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1489ef3b86688fc0051d0c86db238ff8f3732bd353dc4b6b28a81c3897bd756e", size = 1265529 }, - { url = "https://files.pythonhosted.org/packages/6e/2e/f377a5ea8aba231213da1b26f333a6af29c43fcdac7dda790304dd9c3ffc/hypothesis-6.161.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28a450d338067845870b03a8c61ba6d83cccf5d1ed360a6b1cfebb4f42818791", size = 1307881 }, - { url = "https://files.pythonhosted.org/packages/8f/73/276defee614d45462a1512888283d4a9bdf852e3f9d74f564bd8d6cecd09/hypothesis-6.161.0-cp310-cp310-win_amd64.whl", hash = "sha256:170fc6fe2157c8e813818a08709d78c79ffa9171b015389c50f5538eab3de1bb", size = 658159 }, - { url = "https://files.pythonhosted.org/packages/dc/1f/07054e18c7696fe5aa127952e1ff2b74c7917100e0998d77405f9aea7bbf/hypothesis-6.161.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2658a95ac7cf1943b9397725d58481373a1709e79b6867628108f695b202ff3f", size = 766737 }, - { url = "https://files.pythonhosted.org/packages/21/1b/6a04fbda729f5889b486aa3b20912ee6c7391c8db0a2926346a1b3ad0834/hypothesis-6.161.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:584906b4f8f9504d7c9d6fd3c42bf991fa42ab64c3a4490a84d6e4acf69fe7fe", size = 762514 }, - { url = "https://files.pythonhosted.org/packages/35/12/609a956b716ab20cb81263d8e0cecfe442fb46e4d54ae9b82b453f2465fe/hypothesis-6.161.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87a996d0a1c865173ed67a0b3537efbe6736bcf9f58ac28826712a48ed8d2d23", size = 1091414 }, - { url = "https://files.pythonhosted.org/packages/fc/99/093bc8aca6dddc05e88dd0baa64c5586e031737d798c66e770fbeb034510/hypothesis-6.161.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0250e209ed2401cf6c80c956c5c1906097b537d05fa748f03e9c53060a837d3f", size = 1140888 }, - { url = "https://files.pythonhosted.org/packages/65/fc/f681828dc1ca13243622eb6ddc3f7370efb1cb7931ea7505f8ade4d37ba6/hypothesis-6.161.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:210024a6e84c361803545ca055218bcae06e17fcb53d5956db7db6a1e14d7769", size = 1265245 }, - { url = "https://files.pythonhosted.org/packages/53/d4/98deace31c31369196ece4d6f32bb8c1820bf5cf5584721bda791bffa0cc/hypothesis-6.161.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c3e39be8141496a73115f1ea2c8fd7146f78d26f148e884f3d4a68dec06418a0", size = 1307841 }, - { url = "https://files.pythonhosted.org/packages/c3/5d/d9bbe1fc769e46b21d368497d4739375fcb17270eba611bac1117473e337/hypothesis-6.161.0-cp311-cp311-win_amd64.whl", hash = "sha256:e234937af9de105e28dc7ffdac5d7932265abb5881f0264aff01d3515baee732", size = 657953 }, - { url = "https://files.pythonhosted.org/packages/01/f5/b01692ea422f9995260435a5c2a425dd558ceb0b6544cf4037d312b52927/hypothesis-6.161.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8cf6149e5bcb1deaa3d029280c2c9a47fede2186ea58d8dc3e71864428b748b5", size = 767859 }, - { url = "https://files.pythonhosted.org/packages/1e/ea/147f96f352a1c62f4fa4d46ec2d8b103d39cafce236826531aba9dfbf6fc/hypothesis-6.161.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:439b9ccefc2b87b9752752d2ec6c9d40f92de2acaf07f4da94c2ebcbde4eb660", size = 759491 }, - { url = "https://files.pythonhosted.org/packages/44/05/c1ddd72ca9af054332a05bdb19b666b1dbb4ff904cac2b6e04bc483518fa/hypothesis-6.161.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35c577d4b635b914e2cdd59d144448e0de82e47f8422d8373cbb48daa5571686", size = 1089838 }, - { url = "https://files.pythonhosted.org/packages/46/79/0d9adc2ca7fe226e4f81e0e9ff88ab9a2025395a705e55e8447e8833b2e2/hypothesis-6.161.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:894af9777f2fd51bca9625fd07573456c1fa67b6bed3f6aa1659cb60255594e0", size = 1139915 }, - { url = "https://files.pythonhosted.org/packages/50/48/c557ee9899ab58e6d373712dcfe019b4eb65035f5bbffcb7624201984bd4/hypothesis-6.161.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c9f15d18d3041216d80d2a3203c1b8881efb7c20296f068651e2ad34f3852392", size = 1262692 }, - { url = "https://files.pythonhosted.org/packages/1c/37/8eede820af48d8f7a73c0741c659b4839ffe9825b020affe43d52f58acb5/hypothesis-6.161.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f5588bde17a517c943b5ef6172cacfce6ef2d542c9249cc1bd86ce3c4c07161b", size = 1306904 }, - { url = "https://files.pythonhosted.org/packages/ba/6b/16282f58b92b6698dbed7b23d7015fb9f7d5dfb78e7ba2e4b44c88116bca/hypothesis-6.161.0-cp312-cp312-win_amd64.whl", hash = "sha256:c7994d32bcca19b7cbf3c087172245fe9f4d55b21bccef81693efd5a0637d4d9", size = 655392 }, - { url = "https://files.pythonhosted.org/packages/27/13/50b3fabaa9a52f82905d6bf70b0027cbc61972f0b60dcf68506e4a85674f/hypothesis-6.161.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d5217e3df508ab71303bf1288b412548e96483eef195f6008b6472770e4fe4ed", size = 767734 }, - { url = "https://files.pythonhosted.org/packages/72/0c/0176f7722896dffef2aa677699df75cd2a53ed00d4dc6b2959c40c1c8389/hypothesis-6.161.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ad4899908abec1888d0d16eb70acd54c9d8198b58410ec26a346ba35d384fc0d", size = 759394 }, - { url = "https://files.pythonhosted.org/packages/97/1d/5ade6e0c80ce8160bbcd55c300d95a5450cdb82fa04fdcdd8a33f6198441/hypothesis-6.161.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fee553e5150af6d66ee058f3ccbc3b5b83e6df62139e8935abd0510254a2d4a7", size = 1089752 }, - { url = "https://files.pythonhosted.org/packages/99/02/14c6d54e60159ba9991a52b14ea5a9b6935d4878ffe9d0a8fabd2d166767/hypothesis-6.161.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f8110cd815f3a79e2351700654c21771eec47d98a78db56cc81879d41f08ed1", size = 1139731 }, - { url = "https://files.pythonhosted.org/packages/36/98/c099c382b0fbf6dfd209d35961e6ee9739ad1d787288a40eb364b278217a/hypothesis-6.161.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16aacb26a277d25da7466f0588c2687811334455753d513c55d8ca4dbbc5174e", size = 1262736 }, - { url = "https://files.pythonhosted.org/packages/f1/3a/6b1fbde6e2a1c9bd54acb1e5d8fa866c6fef59a829a67ca310f5d12a8fbe/hypothesis-6.161.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eb24cf5f7f301ad3db14caa4462ebc2e693fe38815d793ff6dbc116820b18dff", size = 1306628 }, - { url = "https://files.pythonhosted.org/packages/8b/c2/033da1694f956f0c566b12a1f0667138ad06a3b0a67837f17c6873cc2513/hypothesis-6.161.0-cp313-cp313-win_amd64.whl", hash = "sha256:e4f715f5598444a0d569aa8a3e74ebc14a46c67a873193db38c8542b2838e91f", size = 655355 }, - { url = "https://files.pythonhosted.org/packages/2b/26/29582b8ba467eedf270515422f41cb564d06b4eef38bdf06e236cc841546/hypothesis-6.161.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:a046954e17a1edd20b6c95e9d29f1df7bc20ccab94c01aa8b4177552896230fb", size = 767928 }, - { url = "https://files.pythonhosted.org/packages/f7/25/bb7cfd851f6b0f4b0130485785a3447621523116b89f8d82042fb9897752/hypothesis-6.161.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2d503b0fdb916371d536b33fad0c4f909846af2fc4273d3049ca6fe661aa81ff", size = 759542 }, - { url = "https://files.pythonhosted.org/packages/d9/ab/bc31d4aa5840c2438e011a615095b0e2fae5de94c3abfc18a01686825ea7/hypothesis-6.161.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df011a94870dc3e1b5fb4fb8d2c68dd641b412a3b73050288d85af1467c9a689", size = 1090304 }, - { url = "https://files.pythonhosted.org/packages/51/ee/6304f6184aee6a1b91fff746a767b4f3aab58c29e48e64cc16d56fc6dedc/hypothesis-6.161.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4678e3988503b3bd5be0ed995f84cc15ac4f99c168bade32456a08c04868f3f3", size = 1139915 }, - { url = "https://files.pythonhosted.org/packages/f5/6d/23efce26bf7f1773346732c58a23cbe33ed4f171da1bb3aa11bf349fdb4c/hypothesis-6.161.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74c6e5b5623f37eb6af8be6f861d138fac3ee3528ee30c3b48ff11c39f7be4b7", size = 1263070 }, - { url = "https://files.pythonhosted.org/packages/0b/a2/e0b4bf410630f16661eea6fdf9c3970e47c749a837de12098d63c81bb01b/hypothesis-6.161.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b841c25267ab360812a523d1861e0b0ed0f5cc4e6d7bcecc9d9eddd3f835aa0f", size = 1306929 }, - { url = "https://files.pythonhosted.org/packages/03/13/58047eb148a31ae7cce26ec0b2f0e980c46874c6673c1110c53684ba181a/hypothesis-6.161.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:a0f3830c1e816e34bd8cd940244c8c877dedc2ecfea771d2ecea252bc35eb21d", size = 599455 }, - { url = "https://files.pythonhosted.org/packages/f0/0e/a206013edd7dfd44b9a81ae1946a1ea30d878974850d60a61fa128cc170d/hypothesis-6.161.0-cp314-cp314-win_amd64.whl", hash = "sha256:d1d38f05acb9c25181157f1756f5faaa1759b4641ff6b32cb1d2ab1d55d6af2d", size = 655306 }, - { url = "https://files.pythonhosted.org/packages/e2/74/32d224a0ccf4ca9af6acc1d805047e12cd13105e0769d54ac00a86f25850/hypothesis-6.161.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:81570959521eebd0172ea9132ffab71b90050e7cd44d045da67210aa9a594376", size = 766503 }, - { url = "https://files.pythonhosted.org/packages/ce/5d/8b61c3490fd8195a25fdc37e951ccba3ae4df2c74839ffe6a6d5720fdb79/hypothesis-6.161.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:46a6039181337b85a995666e9bf87cc2390282720ba345479bb9be9c867914da", size = 758013 }, - { url = "https://files.pythonhosted.org/packages/d9/11/ac4ab15ec4586a23bb4e2acdcbed814517e341f2940eeb74fbf428dac243/hypothesis-6.161.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f2d4141c952f522d6aae0e493d170f9b0127c001319bd312ee9cfba7ed419d4", size = 1088871 }, - { url = "https://files.pythonhosted.org/packages/27/13/fd83965bcdd44dc5002c67fe8e8e2e974ed45c82dc6864e104c1c70093d5/hypothesis-6.161.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ed3e1b9c036954bfabe64899072a18e6b5113703d32a96645c6656a8cfc43e", size = 1138801 }, - { url = "https://files.pythonhosted.org/packages/2d/e7/a4ad5f3b0b805fd2e583d193e2a762cd413465b524ef07829452521dca6d/hypothesis-6.161.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:aba1508da6c317819305e875bf6c4d4dd0922193c76416d4cc907447ebe08fea", size = 1261305 }, - { url = "https://files.pythonhosted.org/packages/38/54/35e1b62ece96c24921e9a1e811179d54a6429d9611a2cd49504f5b95382e/hypothesis-6.161.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:981acb3efa88df363a0d31e0f4bacd36ef739104eee789a6b12c7f7200a457fc", size = 1305689 }, - { url = "https://files.pythonhosted.org/packages/04/87/6491e9a36d8e8df67a3b9c3eeb5a85c12c6b0d5302b5ce395b5427698b52/hypothesis-6.161.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e71e229f2dec694685245b8e55e908855b475c17ab8337bcf848768b4c32aa97", size = 655436 }, - { url = "https://files.pythonhosted.org/packages/54/e2/0782e45562fb091cd75bd12f69932c8aa55a9e3bb699599f43e5258d013c/hypothesis-6.161.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:33a19886dc05b489f0ab632c89b8ca9dc6f89a0b380b6405671cecb2b0d5b5c4", size = 767674 }, - { url = "https://files.pythonhosted.org/packages/03/46/eaccb5375ed83396be3153857f9de808b5d5ecc001fab8e30bf8e30d33d4/hypothesis-6.161.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b4fd38d0e757ae290583774b3695ab0d7f0da80e924c6473de84483449c6da8d", size = 763579 }, - { url = "https://files.pythonhosted.org/packages/99/48/31ca6b9414cf30388ba825c740b13ab74f6afcf856a194a9256f7f1ca38d/hypothesis-6.161.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59dc6871e2fbbfd2d28e7e6f33d19bd8513a3b7510bd0b224a59bbebdd5cc1b3", size = 1092394 }, - { url = "https://files.pythonhosted.org/packages/75/1d/709c03af162418c0b3e0cf624549b13ecacd8df0f2ca09d53214702cb1f8/hypothesis-6.161.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55ff16ec4b4e98bfd97e9a2a44905eaf7a3ec8f3f157d8c7eac2385a88059a29", size = 1142170 }, - { url = "https://files.pythonhosted.org/packages/3a/ae/63458a5f80db8433beb7556482e3de1a6789b6c469a5f2f99c21aaa7fdef/hypothesis-6.161.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:77ae374d9ed7046b15443053b11f5b05e185bca24b3b849c3f473a9e4cc85451", size = 659069 }, + { url = "https://files.pythonhosted.org/packages/f5/b9/c8b80fb7517e6f3039d0ef9a5df6aaee53667935e62c6c9d9d635436708d/hypothesis-6.161.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c9f877e288dfb46207b5c3bfcc8ab28e2613e529be8621816423960403377286", size = 766230, upload-time = "2026-07-23T07:16:54.313Z" }, + { url = "https://files.pythonhosted.org/packages/90/16/e5c1287fee682f7c1e9afccc91c07ae36a6855a5863d0b3c15d7bfa0b322/hypothesis-6.161.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b7b6980265cb04605b2b42132dc8ef5735917fc482869298611a49d2e06dc322", size = 761883, upload-time = "2026-07-23T07:17:05.884Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b8/d9792e24e53f82bb1455935f79cf3b56ccf556fac325c8a90f7968180706/hypothesis-6.161.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f10253cac459922cad3bc09e397718188e57dffefe810e5db1d444e7113d7fb5", size = 1091083, upload-time = "2026-07-23T07:17:10.987Z" }, + { url = "https://files.pythonhosted.org/packages/f7/15/33cba9c6bee8a80ab18f48e40669038275bf4b82e8dfb0fa9fe716925265/hypothesis-6.161.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:232ab78dd8cb0a891914d20697e0fd340ca1e6d4d8d5855df5e433d8161173e2", size = 1140530, upload-time = "2026-07-23T07:16:14.195Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f6/30c421822cd65b8edd56b2b90a5e1acf4a624d5619067957668027ab7e46/hypothesis-6.161.0-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:264336ca1e9f31edd24a8885c4020db8e18986c51a255613db28c076ac4289a8", size = 1132680, upload-time = "2026-07-23T07:16:49.73Z" }, + { url = "https://files.pythonhosted.org/packages/e9/db/d18e45339b2ffda57a52395e03df6166bc4e428bc90e878dd3f20a7423c0/hypothesis-6.161.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:323aac4347e6ffa86929407b7f386cbf54e1c66faf923ffd6b4b86c21815d117", size = 1264892, upload-time = "2026-07-23T07:16:21.657Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7e/f4b7600272fbc9a2b28c95b96059d89cf5093ae705e52360a818df8154a5/hypothesis-6.161.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5dc83c8e83b9d133babcf9468703cece0ddb25413983561f2516927edddcc52d", size = 1307563, upload-time = "2026-07-23T07:16:43.15Z" }, + { url = "https://files.pythonhosted.org/packages/d6/28/fa4f2d50c7434076ec7653a8372750531576e4d11cd5f3316ad83e12a553/hypothesis-6.161.0-cp310-abi3-win32.whl", hash = "sha256:75a3036121e6ae2cf55b7433f1953834cc9eca97c2e4e4be3369fe080c86b237", size = 652098, upload-time = "2026-07-23T07:16:24.134Z" }, + { url = "https://files.pythonhosted.org/packages/93/5c/6811eee772a5cc33f9bf863326983f493977e9aee9535c8dbb6c172575d3/hypothesis-6.161.0-cp310-abi3-win_amd64.whl", hash = "sha256:e3f5b2527789a748b54d6ef46b2b042f3225164d54c24ba74a137ddb10a39407", size = 658272, upload-time = "2026-07-23T07:16:51.173Z" }, + { url = "https://files.pythonhosted.org/packages/97/97/49216c1087962033451cc6e3093deb765b0d14eed7dda2980f6d8dfc9062/hypothesis-6.161.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:38eea270b81398c9e2c7eed028f53ba51dc7005eb97fa681c7c90007ba029423", size = 766930, upload-time = "2026-07-23T07:17:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/9a/6d/766a280bea353045ae7311ba847a50ebb939155e2a990fd08040be2b6b5b/hypothesis-6.161.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6b7183980c7729d7cf084ab26c127e4c591876536278ecb84ed2449d4d93f4e", size = 762699, upload-time = "2026-07-23T07:17:38.977Z" }, + { url = "https://files.pythonhosted.org/packages/62/86/f28648668b5ce18bba7ae846c629c54427aa622a76280309c3bc3dca4f2d/hypothesis-6.161.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3e60bbe528d6005373146808bd0b5e618bf1a20e912c0568ae56802e8c455fc", size = 1091551, upload-time = "2026-07-23T07:16:28.499Z" }, + { url = "https://files.pythonhosted.org/packages/52/e3/3ae24ad1056e1c992dade22e9c784c93d57ea0dc3ff9fa6a48683548489d/hypothesis-6.161.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3167e3153a9b8a8ad43284a22cbe1e3c1819d6d944f727f9810bb115a9c2ade", size = 1141106, upload-time = "2026-07-23T07:17:19.854Z" }, + { url = "https://files.pythonhosted.org/packages/c4/37/fa3a21edcd7c4a104d6782ee98135af8ef86ae42d39ea9eb55072f84b668/hypothesis-6.161.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1489ef3b86688fc0051d0c86db238ff8f3732bd353dc4b6b28a81c3897bd756e", size = 1265529, upload-time = "2026-07-23T07:16:44.815Z" }, + { url = "https://files.pythonhosted.org/packages/6e/2e/f377a5ea8aba231213da1b26f333a6af29c43fcdac7dda790304dd9c3ffc/hypothesis-6.161.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28a450d338067845870b03a8c61ba6d83cccf5d1ed360a6b1cfebb4f42818791", size = 1307881, upload-time = "2026-07-23T07:16:18.438Z" }, + { url = "https://files.pythonhosted.org/packages/8f/73/276defee614d45462a1512888283d4a9bdf852e3f9d74f564bd8d6cecd09/hypothesis-6.161.0-cp310-cp310-win_amd64.whl", hash = "sha256:170fc6fe2157c8e813818a08709d78c79ffa9171b015389c50f5538eab3de1bb", size = 658159, upload-time = "2026-07-23T07:16:38.473Z" }, + { url = "https://files.pythonhosted.org/packages/dc/1f/07054e18c7696fe5aa127952e1ff2b74c7917100e0998d77405f9aea7bbf/hypothesis-6.161.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2658a95ac7cf1943b9397725d58481373a1709e79b6867628108f695b202ff3f", size = 766737, upload-time = "2026-07-23T07:16:27.055Z" }, + { url = "https://files.pythonhosted.org/packages/21/1b/6a04fbda729f5889b486aa3b20912ee6c7391c8db0a2926346a1b3ad0834/hypothesis-6.161.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:584906b4f8f9504d7c9d6fd3c42bf991fa42ab64c3a4490a84d6e4acf69fe7fe", size = 762514, upload-time = "2026-07-23T07:17:25.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/12/609a956b716ab20cb81263d8e0cecfe442fb46e4d54ae9b82b453f2465fe/hypothesis-6.161.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87a996d0a1c865173ed67a0b3537efbe6736bcf9f58ac28826712a48ed8d2d23", size = 1091414, upload-time = "2026-07-23T07:16:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/fc/99/093bc8aca6dddc05e88dd0baa64c5586e031737d798c66e770fbeb034510/hypothesis-6.161.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0250e209ed2401cf6c80c956c5c1906097b537d05fa748f03e9c53060a837d3f", size = 1140888, upload-time = "2026-07-23T07:17:07.579Z" }, + { url = "https://files.pythonhosted.org/packages/65/fc/f681828dc1ca13243622eb6ddc3f7370efb1cb7931ea7505f8ade4d37ba6/hypothesis-6.161.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:210024a6e84c361803545ca055218bcae06e17fcb53d5956db7db6a1e14d7769", size = 1265245, upload-time = "2026-07-23T07:16:56.103Z" }, + { url = "https://files.pythonhosted.org/packages/53/d4/98deace31c31369196ece4d6f32bb8c1820bf5cf5584721bda791bffa0cc/hypothesis-6.161.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c3e39be8141496a73115f1ea2c8fd7146f78d26f148e884f3d4a68dec06418a0", size = 1307841, upload-time = "2026-07-23T07:16:59.457Z" }, + { url = "https://files.pythonhosted.org/packages/c3/5d/d9bbe1fc769e46b21d368497d4739375fcb17270eba611bac1117473e337/hypothesis-6.161.0-cp311-cp311-win_amd64.whl", hash = "sha256:e234937af9de105e28dc7ffdac5d7932265abb5881f0264aff01d3515baee732", size = 657953, upload-time = "2026-07-23T07:17:18.224Z" }, + { url = "https://files.pythonhosted.org/packages/01/f5/b01692ea422f9995260435a5c2a425dd558ceb0b6544cf4037d312b52927/hypothesis-6.161.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8cf6149e5bcb1deaa3d029280c2c9a47fede2186ea58d8dc3e71864428b748b5", size = 767859, upload-time = "2026-07-23T07:16:31.301Z" }, + { url = "https://files.pythonhosted.org/packages/1e/ea/147f96f352a1c62f4fa4d46ec2d8b103d39cafce236826531aba9dfbf6fc/hypothesis-6.161.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:439b9ccefc2b87b9752752d2ec6c9d40f92de2acaf07f4da94c2ebcbde4eb660", size = 759491, upload-time = "2026-07-23T07:17:37.046Z" }, + { url = "https://files.pythonhosted.org/packages/44/05/c1ddd72ca9af054332a05bdb19b666b1dbb4ff904cac2b6e04bc483518fa/hypothesis-6.161.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35c577d4b635b914e2cdd59d144448e0de82e47f8422d8373cbb48daa5571686", size = 1089838, upload-time = "2026-07-23T07:16:52.774Z" }, + { url = "https://files.pythonhosted.org/packages/46/79/0d9adc2ca7fe226e4f81e0e9ff88ab9a2025395a705e55e8447e8833b2e2/hypothesis-6.161.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:894af9777f2fd51bca9625fd07573456c1fa67b6bed3f6aa1659cb60255594e0", size = 1139915, upload-time = "2026-07-23T07:16:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/50/48/c557ee9899ab58e6d373712dcfe019b4eb65035f5bbffcb7624201984bd4/hypothesis-6.161.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c9f15d18d3041216d80d2a3203c1b8881efb7c20296f068651e2ad34f3852392", size = 1262692, upload-time = "2026-07-23T07:17:09.328Z" }, + { url = "https://files.pythonhosted.org/packages/1c/37/8eede820af48d8f7a73c0741c659b4839ffe9825b020affe43d52f58acb5/hypothesis-6.161.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f5588bde17a517c943b5ef6172cacfce6ef2d542c9249cc1bd86ce3c4c07161b", size = 1306904, upload-time = "2026-07-23T07:16:32.698Z" }, + { url = "https://files.pythonhosted.org/packages/ba/6b/16282f58b92b6698dbed7b23d7015fb9f7d5dfb78e7ba2e4b44c88116bca/hypothesis-6.161.0-cp312-cp312-win_amd64.whl", hash = "sha256:c7994d32bcca19b7cbf3c087172245fe9f4d55b21bccef81693efd5a0637d4d9", size = 655392, upload-time = "2026-07-23T07:16:16.988Z" }, + { url = "https://files.pythonhosted.org/packages/27/13/50b3fabaa9a52f82905d6bf70b0027cbc61972f0b60dcf68506e4a85674f/hypothesis-6.161.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d5217e3df508ab71303bf1288b412548e96483eef195f6008b6472770e4fe4ed", size = 767734, upload-time = "2026-07-23T07:16:35.638Z" }, + { url = "https://files.pythonhosted.org/packages/72/0c/0176f7722896dffef2aa677699df75cd2a53ed00d4dc6b2959c40c1c8389/hypothesis-6.161.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ad4899908abec1888d0d16eb70acd54c9d8198b58410ec26a346ba35d384fc0d", size = 759394, upload-time = "2026-07-23T07:16:57.551Z" }, + { url = "https://files.pythonhosted.org/packages/97/1d/5ade6e0c80ce8160bbcd55c300d95a5450cdb82fa04fdcdd8a33f6198441/hypothesis-6.161.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fee553e5150af6d66ee058f3ccbc3b5b83e6df62139e8935abd0510254a2d4a7", size = 1089752, upload-time = "2026-07-23T07:16:34.18Z" }, + { url = "https://files.pythonhosted.org/packages/99/02/14c6d54e60159ba9991a52b14ea5a9b6935d4878ffe9d0a8fabd2d166767/hypothesis-6.161.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f8110cd815f3a79e2351700654c21771eec47d98a78db56cc81879d41f08ed1", size = 1139731, upload-time = "2026-07-23T07:17:28.51Z" }, + { url = "https://files.pythonhosted.org/packages/36/98/c099c382b0fbf6dfd209d35961e6ee9739ad1d787288a40eb364b278217a/hypothesis-6.161.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16aacb26a277d25da7466f0588c2687811334455753d513c55d8ca4dbbc5174e", size = 1262736, upload-time = "2026-07-23T07:16:07.875Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3a/6b1fbde6e2a1c9bd54acb1e5d8fa866c6fef59a829a67ca310f5d12a8fbe/hypothesis-6.161.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eb24cf5f7f301ad3db14caa4462ebc2e693fe38815d793ff6dbc116820b18dff", size = 1306628, upload-time = "2026-07-23T07:16:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c2/033da1694f956f0c566b12a1f0667138ad06a3b0a67837f17c6873cc2513/hypothesis-6.161.0-cp313-cp313-win_amd64.whl", hash = "sha256:e4f715f5598444a0d569aa8a3e74ebc14a46c67a873193db38c8542b2838e91f", size = 655355, upload-time = "2026-07-23T07:16:48.054Z" }, + { url = "https://files.pythonhosted.org/packages/2b/26/29582b8ba467eedf270515422f41cb564d06b4eef38bdf06e236cc841546/hypothesis-6.161.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:a046954e17a1edd20b6c95e9d29f1df7bc20ccab94c01aa8b4177552896230fb", size = 767928, upload-time = "2026-07-23T07:17:12.935Z" }, + { url = "https://files.pythonhosted.org/packages/f7/25/bb7cfd851f6b0f4b0130485785a3447621523116b89f8d82042fb9897752/hypothesis-6.161.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2d503b0fdb916371d536b33fad0c4f909846af2fc4273d3049ca6fe661aa81ff", size = 759542, upload-time = "2026-07-23T07:16:41.736Z" }, + { url = "https://files.pythonhosted.org/packages/d9/ab/bc31d4aa5840c2438e011a615095b0e2fae5de94c3abfc18a01686825ea7/hypothesis-6.161.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df011a94870dc3e1b5fb4fb8d2c68dd641b412a3b73050288d85af1467c9a689", size = 1090304, upload-time = "2026-07-23T07:16:19.817Z" }, + { url = "https://files.pythonhosted.org/packages/51/ee/6304f6184aee6a1b91fff746a767b4f3aab58c29e48e64cc16d56fc6dedc/hypothesis-6.161.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4678e3988503b3bd5be0ed995f84cc15ac4f99c168bade32456a08c04868f3f3", size = 1139915, upload-time = "2026-07-23T07:17:14.565Z" }, + { url = "https://files.pythonhosted.org/packages/f5/6d/23efce26bf7f1773346732c58a23cbe33ed4f171da1bb3aa11bf349fdb4c/hypothesis-6.161.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74c6e5b5623f37eb6af8be6f861d138fac3ee3528ee30c3b48ff11c39f7be4b7", size = 1263070, upload-time = "2026-07-23T07:16:15.695Z" }, + { url = "https://files.pythonhosted.org/packages/0b/a2/e0b4bf410630f16661eea6fdf9c3970e47c749a837de12098d63c81bb01b/hypothesis-6.161.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b841c25267ab360812a523d1861e0b0ed0f5cc4e6d7bcecc9d9eddd3f835aa0f", size = 1306929, upload-time = "2026-07-23T07:16:37.086Z" }, + { url = "https://files.pythonhosted.org/packages/03/13/58047eb148a31ae7cce26ec0b2f0e980c46874c6673c1110c53684ba181a/hypothesis-6.161.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:a0f3830c1e816e34bd8cd940244c8c877dedc2ecfea771d2ecea252bc35eb21d", size = 599455, upload-time = "2026-07-23T07:16:25.552Z" }, + { url = "https://files.pythonhosted.org/packages/f0/0e/a206013edd7dfd44b9a81ae1946a1ea30d878974850d60a61fa128cc170d/hypothesis-6.161.0-cp314-cp314-win_amd64.whl", hash = "sha256:d1d38f05acb9c25181157f1756f5faaa1759b4641ff6b32cb1d2ab1d55d6af2d", size = 655306, upload-time = "2026-07-23T07:17:30.273Z" }, + { url = "https://files.pythonhosted.org/packages/e2/74/32d224a0ccf4ca9af6acc1d805047e12cd13105e0769d54ac00a86f25850/hypothesis-6.161.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:81570959521eebd0172ea9132ffab71b90050e7cd44d045da67210aa9a594376", size = 766503, upload-time = "2026-07-23T07:16:10.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5d/8b61c3490fd8195a25fdc37e951ccba3ae4df2c74839ffe6a6d5720fdb79/hypothesis-6.161.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:46a6039181337b85a995666e9bf87cc2390282720ba345479bb9be9c867914da", size = 758013, upload-time = "2026-07-23T07:17:26.71Z" }, + { url = "https://files.pythonhosted.org/packages/d9/11/ac4ab15ec4586a23bb4e2acdcbed814517e341f2940eeb74fbf428dac243/hypothesis-6.161.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f2d4141c952f522d6aae0e493d170f9b0127c001319bd312ee9cfba7ed419d4", size = 1088871, upload-time = "2026-07-23T07:17:02.884Z" }, + { url = "https://files.pythonhosted.org/packages/27/13/fd83965bcdd44dc5002c67fe8e8e2e974ed45c82dc6864e104c1c70093d5/hypothesis-6.161.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ed3e1b9c036954bfabe64899072a18e6b5113703d32a96645c6656a8cfc43e", size = 1138801, upload-time = "2026-07-23T07:17:35.354Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e7/a4ad5f3b0b805fd2e583d193e2a762cd413465b524ef07829452521dca6d/hypothesis-6.161.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:aba1508da6c317819305e875bf6c4d4dd0922193c76416d4cc907447ebe08fea", size = 1261305, upload-time = "2026-07-23T07:17:23.201Z" }, + { url = "https://files.pythonhosted.org/packages/38/54/35e1b62ece96c24921e9a1e811179d54a6429d9611a2cd49504f5b95382e/hypothesis-6.161.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:981acb3efa88df363a0d31e0f4bacd36ef739104eee789a6b12c7f7200a457fc", size = 1305689, upload-time = "2026-07-23T07:17:21.476Z" }, + { url = "https://files.pythonhosted.org/packages/04/87/6491e9a36d8e8df67a3b9c3eeb5a85c12c6b0d5302b5ce395b5427698b52/hypothesis-6.161.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e71e229f2dec694685245b8e55e908855b475c17ab8337bcf848768b4c32aa97", size = 655436, upload-time = "2026-07-23T07:17:04.424Z" }, + { url = "https://files.pythonhosted.org/packages/54/e2/0782e45562fb091cd75bd12f69932c8aa55a9e3bb699599f43e5258d013c/hypothesis-6.161.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:33a19886dc05b489f0ab632c89b8ca9dc6f89a0b380b6405671cecb2b0d5b5c4", size = 767674, upload-time = "2026-07-23T07:17:16.37Z" }, + { url = "https://files.pythonhosted.org/packages/03/46/eaccb5375ed83396be3153857f9de808b5d5ecc001fab8e30bf8e30d33d4/hypothesis-6.161.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b4fd38d0e757ae290583774b3695ab0d7f0da80e924c6473de84483449c6da8d", size = 763579, upload-time = "2026-07-23T07:16:46.309Z" }, + { url = "https://files.pythonhosted.org/packages/99/48/31ca6b9414cf30388ba825c740b13ab74f6afcf856a194a9256f7f1ca38d/hypothesis-6.161.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59dc6871e2fbbfd2d28e7e6f33d19bd8513a3b7510bd0b224a59bbebdd5cc1b3", size = 1092394, upload-time = "2026-07-23T07:17:01.136Z" }, + { url = "https://files.pythonhosted.org/packages/75/1d/709c03af162418c0b3e0cf624549b13ecacd8df0f2ca09d53214702cb1f8/hypothesis-6.161.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55ff16ec4b4e98bfd97e9a2a44905eaf7a3ec8f3f157d8c7eac2385a88059a29", size = 1142170, upload-time = "2026-07-23T07:17:32.044Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ae/63458a5f80db8433beb7556482e3de1a6789b6c469a5f2f99c21aaa7fdef/hypothesis-6.161.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:77ae374d9ed7046b15443053b11f5b05e185bca24b3b849c3f473a9e4cc85451", size = 659069, upload-time = "2026-07-23T07:16:12.922Z" }, ] [[package]] name = "iniconfig" version = "2.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503 } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484 }, + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] [[package]] @@ -726,27 +728,27 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454 } +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687 }, + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] [[package]] name = "packaging" version = "26.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134 } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195 }, + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, ] [[package]] @@ -756,55 +758,53 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "regex" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7b/91/abdc50c4ef06fdf8d047f60ee777ca9b2a7885e1a9cea81343fbecda52d7/parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c", size = 52172 } +sdist = { url = "https://files.pythonhosted.org/packages/7b/91/abdc50c4ef06fdf8d047f60ee777ca9b2a7885e1a9cea81343fbecda52d7/parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c", size = 52172, upload-time = "2022-09-03T17:01:17.004Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/0f/c8b64d9b54ea631fcad4e9e3c8dbe8c11bb32a623be94f22974c88e71eaf/parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f", size = 48427 }, + { url = "https://files.pythonhosted.org/packages/aa/0f/c8b64d9b54ea631fcad4e9e3c8dbe8c11bb32a623be94f22974c88e71eaf/parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f", size = 48427, upload-time = "2022-09-03T17:01:13.814Z" }, ] [[package]] name = "pluggy" version = "1.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412 } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538 }, + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] [[package]] name = "pycryptodome" version = "3.23.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152 }, - { url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348 }, - { url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033 }, - { url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142 }, - { url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384 }, - { url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237 }, - { url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898 }, - { url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197 }, - { url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600 }, - { url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740 }, - { url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685 }, - { url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627 }, - { url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362 }, - { url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625 }, - { url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954 }, - { url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534 }, - { url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853 }, - { url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465 }, - { url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414 }, - { url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484 }, - { url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636 }, - { url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675 }, - { url = "https://files.pythonhosted.org/packages/9f/7c/f5b0556590e7b4e710509105e668adb55aa9470a9f0e4dea9c40a4a11ce1/pycryptodome-3.23.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:350ebc1eba1da729b35ab7627a833a1a355ee4e852d8ba0447fafe7b14504d56", size = 1705791 }, - { url = "https://files.pythonhosted.org/packages/33/38/dcc795578d610ea1aaffef4b148b8cafcfcf4d126b1e58231ddc4e475c70/pycryptodome-3.23.0-pp27-pypy_73-win32.whl", hash = "sha256:93837e379a3e5fd2bb00302a47aee9fdf7940d83595be3915752c74033d17ca7", size = 1780265 }, - { url = "https://files.pythonhosted.org/packages/d9/12/e33935a0709c07de084d7d58d330ec3f4daf7910a18e77937affdb728452/pycryptodome-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddb95b49df036ddd264a0ad246d1be5b672000f12d6961ea2c267083a5e19379", size = 1623886 }, - { url = "https://files.pythonhosted.org/packages/22/0b/aa8f9419f25870889bebf0b26b223c6986652bdf071f000623df11212c90/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e95564beb8782abfd9e431c974e14563a794a4944c29d6d3b7b5ea042110b4", size = 1672151 }, - { url = "https://files.pythonhosted.org/packages/d4/5e/63f5cbde2342b7f70a39e591dbe75d9809d6338ce0b07c10406f1a140cdc/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e15c081e912c4b0d75632acd8382dfce45b258667aa3c67caf7a4d4c13f630", size = 1664461 }, - { url = "https://files.pythonhosted.org/packages/d6/92/608fbdad566ebe499297a86aae5f2a5263818ceeecd16733006f1600403c/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fc76bf273353dc7e5207d172b83f569540fc9a28d63171061c42e361d22353", size = 1702440 }, - { url = "https://files.pythonhosted.org/packages/d1/92/2eadd1341abd2989cce2e2740b4423608ee2014acb8110438244ee97d7ff/pycryptodome-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:45c69ad715ca1a94f778215a11e66b7ff989d792a4d63b68dc586a1da1392ff5", size = 1803005 }, + { url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" }, + { url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" }, + { url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" }, + { url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" }, + { url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" }, + { url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" }, + { url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" }, + { url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" }, + { url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" }, + { url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" }, + { url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" }, + { url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" }, + { url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" }, + { url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" }, + { url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" }, + { url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" }, + { url = "https://files.pythonhosted.org/packages/d9/12/e33935a0709c07de084d7d58d330ec3f4daf7910a18e77937affdb728452/pycryptodome-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddb95b49df036ddd264a0ad246d1be5b672000f12d6961ea2c267083a5e19379", size = 1623886, upload-time = "2025-05-17T17:21:20.614Z" }, + { url = "https://files.pythonhosted.org/packages/22/0b/aa8f9419f25870889bebf0b26b223c6986652bdf071f000623df11212c90/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e95564beb8782abfd9e431c974e14563a794a4944c29d6d3b7b5ea042110b4", size = 1672151, upload-time = "2025-05-17T17:21:22.666Z" }, + { url = "https://files.pythonhosted.org/packages/d4/5e/63f5cbde2342b7f70a39e591dbe75d9809d6338ce0b07c10406f1a140cdc/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e15c081e912c4b0d75632acd8382dfce45b258667aa3c67caf7a4d4c13f630", size = 1664461, upload-time = "2025-05-17T17:21:25.225Z" }, + { url = "https://files.pythonhosted.org/packages/d6/92/608fbdad566ebe499297a86aae5f2a5263818ceeecd16733006f1600403c/pycryptodome-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fc76bf273353dc7e5207d172b83f569540fc9a28d63171061c42e361d22353", size = 1702440, upload-time = "2025-05-17T17:21:27.991Z" }, + { url = "https://files.pythonhosted.org/packages/d1/92/2eadd1341abd2989cce2e2740b4423608ee2014acb8110438244ee97d7ff/pycryptodome-3.23.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:45c69ad715ca1a94f778215a11e66b7ff989d792a4d63b68dc586a1da1392ff5", size = 1803005, upload-time = "2025-05-17T17:21:31.37Z" }, ] [[package]] @@ -817,9 +817,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775 } +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262 }, + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, ] [[package]] @@ -829,122 +829,122 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464 } +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/08/f1ba952f1c8ae5581c70fa9c6da89f247b83e3dd8c09c035d5d7931fc23d/pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4", size = 2113146 }, - { url = "https://files.pythonhosted.org/packages/56/c6/65f646c7ff09bd257f660434adb45c4dfcbbcebcc030562fecf6f5bf887d/pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5", size = 1949769 }, - { url = "https://files.pythonhosted.org/packages/64/ba/bfb1d928fd5b49e1258935ff104ae356e9fd89384a55bf9f847e9193ad40/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba", size = 1974958 }, - { url = "https://files.pythonhosted.org/packages/4e/74/76223bfb117b64af743c9b6670d1364516f5c0604f96b48f3272f6af6cc6/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b", size = 2042118 }, - { url = "https://files.pythonhosted.org/packages/cb/7b/848732968bc8f48f3187542f08358b9d842db564147b256669426ebb1652/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c", size = 2222876 }, - { url = "https://files.pythonhosted.org/packages/b5/2f/e90b63ee2e14bd8d3db8f705a6d75d64e6ee1b7c2c8833747ce706e1e0ce/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50", size = 2286703 }, - { url = "https://files.pythonhosted.org/packages/ba/1e/acc4d70f88a0a277e4a1fa77ebb985ceabaf900430f875bf9338e11c9420/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd", size = 2092042 }, - { url = "https://files.pythonhosted.org/packages/a9/da/0a422b57bf8504102bf3c4ccea9c41bab5a5cee6a54650acf8faf67f5a24/pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01", size = 2117231 }, - { url = "https://files.pythonhosted.org/packages/bd/2a/2ac13c3af305843e23c5078c53d135656b3f05a2fd78cb7bbbb12e97b473/pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d", size = 2168388 }, - { url = "https://files.pythonhosted.org/packages/72/04/2beacf7e1607e93eefe4aed1b4709f079b905fb77530179d4f7c71745f22/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4", size = 2184769 }, - { url = "https://files.pythonhosted.org/packages/9e/29/d2b9fd9f539133548eaf622c06a4ce176cb46ac59f32d0359c4abc0de047/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f", size = 2319312 }, - { url = "https://files.pythonhosted.org/packages/7c/af/0f7a5b85fec6075bea96e3ef9187de38fccced0de92c1e7feda8d5cc7bb9/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39", size = 2361817 }, - { url = "https://files.pythonhosted.org/packages/25/a4/73363fec545fd3ec025490bdda2743c56d0dd5b6266b1a53bbe9e4265375/pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d", size = 1987085 }, - { url = "https://files.pythonhosted.org/packages/01/aa/62f082da2c91fac1c234bc9ee0066257ce83f0604abd72e4c9d5991f2d84/pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf", size = 2074311 }, - { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872 }, - { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255 }, - { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827 }, - { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051 }, - { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314 }, - { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146 }, - { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685 }, - { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420 }, - { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122 }, - { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573 }, - { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139 }, - { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433 }, - { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513 }, - { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114 }, - { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298 }, - { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158 }, - { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724 }, - { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742 }, - { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418 }, - { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274 }, - { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940 }, - { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516 }, - { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854 }, - { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306 }, - { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044 }, - { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133 }, - { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464 }, - { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823 }, - { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919 }, - { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604 }, - { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306 }, - { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906 }, - { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802 }, - { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446 }, - { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757 }, - { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275 }, - { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467 }, - { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417 }, - { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782 }, - { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782 }, - { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334 }, - { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986 }, - { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693 }, - { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819 }, - { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411 }, - { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079 }, - { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179 }, - { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926 }, - { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785 }, - { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733 }, - { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534 }, - { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732 }, - { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627 }, - { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141 }, - { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325 }, - { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990 }, - { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978 }, - { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354 }, - { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238 }, - { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251 }, - { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593 }, - { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226 }, - { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605 }, - { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777 }, - { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641 }, - { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404 }, - { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219 }, - { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594 }, - { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542 }, - { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146 }, - { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309 }, - { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736 }, - { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575 }, - { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624 }, - { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325 }, - { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589 }, - { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552 }, - { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984 }, - { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417 }, - { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527 }, - { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024 }, - { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696 }, - { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590 }, - { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782 }, - { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146 }, - { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492 }, - { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604 }, - { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828 }, - { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000 }, - { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286 }, - { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071 }, + { url = "https://files.pythonhosted.org/packages/e7/08/f1ba952f1c8ae5581c70fa9c6da89f247b83e3dd8c09c035d5d7931fc23d/pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4", size = 2113146, upload-time = "2026-05-06T13:37:36.537Z" }, + { url = "https://files.pythonhosted.org/packages/56/c6/65f646c7ff09bd257f660434adb45c4dfcbbcebcc030562fecf6f5bf887d/pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5", size = 1949769, upload-time = "2026-05-06T13:37:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/64/ba/bfb1d928fd5b49e1258935ff104ae356e9fd89384a55bf9f847e9193ad40/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba", size = 1974958, upload-time = "2026-05-06T13:37:28.611Z" }, + { url = "https://files.pythonhosted.org/packages/4e/74/76223bfb117b64af743c9b6670d1364516f5c0604f96b48f3272f6af6cc6/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b", size = 2042118, upload-time = "2026-05-06T13:36:55.216Z" }, + { url = "https://files.pythonhosted.org/packages/cb/7b/848732968bc8f48f3187542f08358b9d842db564147b256669426ebb1652/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c", size = 2222876, upload-time = "2026-05-06T13:38:25.455Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2f/e90b63ee2e14bd8d3db8f705a6d75d64e6ee1b7c2c8833747ce706e1e0ce/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50", size = 2286703, upload-time = "2026-05-06T13:37:53.304Z" }, + { url = "https://files.pythonhosted.org/packages/ba/1e/acc4d70f88a0a277e4a1fa77ebb985ceabaf900430f875bf9338e11c9420/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd", size = 2092042, upload-time = "2026-05-06T13:38:46.981Z" }, + { url = "https://files.pythonhosted.org/packages/a9/da/0a422b57bf8504102bf3c4ccea9c41bab5a5cee6a54650acf8faf67f5a24/pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01", size = 2117231, upload-time = "2026-05-06T13:39:23.146Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2a/2ac13c3af305843e23c5078c53d135656b3f05a2fd78cb7bbbb12e97b473/pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d", size = 2168388, upload-time = "2026-05-06T13:40:08.06Z" }, + { url = "https://files.pythonhosted.org/packages/72/04/2beacf7e1607e93eefe4aed1b4709f079b905fb77530179d4f7c71745f22/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4", size = 2184769, upload-time = "2026-05-06T13:38:13.901Z" }, + { url = "https://files.pythonhosted.org/packages/9e/29/d2b9fd9f539133548eaf622c06a4ce176cb46ac59f32d0359c4abc0de047/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f", size = 2319312, upload-time = "2026-05-06T13:39:08.24Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/0f7a5b85fec6075bea96e3ef9187de38fccced0de92c1e7feda8d5cc7bb9/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39", size = 2361817, upload-time = "2026-05-06T13:38:43.2Z" }, + { url = "https://files.pythonhosted.org/packages/25/a4/73363fec545fd3ec025490bdda2743c56d0dd5b6266b1a53bbe9e4265375/pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d", size = 1987085, upload-time = "2026-05-06T13:39:25.497Z" }, + { url = "https://files.pythonhosted.org/packages/01/aa/62f082da2c91fac1c234bc9ee0066257ce83f0604abd72e4c9d5991f2d84/pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf", size = 2074311, upload-time = "2026-05-06T13:39:59.922Z" }, + { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" }, + { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" }, + { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" }, + { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" }, + { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" }, + { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" }, + { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" }, + { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513, upload-time = "2026-05-06T13:38:15.669Z" }, + { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114, upload-time = "2026-05-06T13:40:35.416Z" }, + { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298, upload-time = "2026-05-06T13:38:29.754Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" }, + { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, + { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" }, + { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" }, + { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" }, + { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" }, ] [[package]] name = "pygments" version = "2.20.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991 } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151 }, + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] [[package]] @@ -960,9 +960,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369 } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536 }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] @@ -974,9 +974,9 @@ dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514 } +sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930 }, + { url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930, upload-time = "2026-05-26T09:56:02.576Z" }, ] [[package]] @@ -988,9 +988,9 @@ dependencies = [ { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592 } +sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876 }, + { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] [[package]] @@ -1001,9 +1001,9 @@ dependencies = [ { name = "execnet" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069 } +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396 }, + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, ] [[package]] @@ -1013,130 +1013,130 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8f/b2/7fc2931bfae0af02d5f53b174e9cf701adbb35f39d69c2af63d4a39f81a9/qrcode-8.2.tar.gz", hash = "sha256:35c3f2a4172b33136ab9f6b3ef1c00260dd2f66f858f24d88418a015f446506c", size = 43317 } +sdist = { url = "https://files.pythonhosted.org/packages/8f/b2/7fc2931bfae0af02d5f53b174e9cf701adbb35f39d69c2af63d4a39f81a9/qrcode-8.2.tar.gz", hash = "sha256:35c3f2a4172b33136ab9f6b3ef1c00260dd2f66f858f24d88418a015f446506c", size = 43317, upload-time = "2025-05-01T15:44:24.726Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/b8/d2d6d731733f51684bbf76bf34dab3b70a9148e8f2cef2bb544fccec681a/qrcode-8.2-py3-none-any.whl", hash = "sha256:16e64e0716c14960108e85d853062c9e8bba5ca8252c0b4d0231b9df4060ff4f", size = 45986 }, + { url = "https://files.pythonhosted.org/packages/dd/b8/d2d6d731733f51684bbf76bf34dab3b70a9148e8f2cef2bb544fccec681a/qrcode-8.2-py3-none-any.whl", hash = "sha256:16e64e0716c14960108e85d853062c9e8bba5ca8252c0b4d0231b9df4060ff4f", size = 45986, upload-time = "2025-05-01T15:44:22.781Z" }, ] [[package]] name = "regex" version = "2026.6.28" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/05/e4f219230e11e774a6c9987d2ab0d0c6b8573e13a17e143d0015bee710ef/regex-2026.6.28.tar.gz", hash = "sha256:3cb4b6c5cb3060cc31efdc1fbb27c25fb9b29044afd87e40601a1c4d9db54342", size = 416101 } +sdist = { url = "https://files.pythonhosted.org/packages/f1/05/e4f219230e11e774a6c9987d2ab0d0c6b8573e13a17e143d0015bee710ef/regex-2026.6.28.tar.gz", hash = "sha256:3cb4b6c5cb3060cc31efdc1fbb27c25fb9b29044afd87e40601a1c4d9db54342", size = 416101, upload-time = "2026-06-28T19:56:55.302Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/dc/f7a8c9cf0768f704153d358fae2bc883199bc4ea1e4aa458f1be9d0ef2ce/regex-2026.6.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b83932645630965fd860fdb70ebbf964bf3e8007f08851ea424d01f8d35454a8", size = 489471 }, - { url = "https://files.pythonhosted.org/packages/44/b3/9786a4a2133e2f1cc5897ed3d2da3da29ff54b775ffa38bc5935fc24be82/regex-2026.6.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e81f1952355042e517dc9861ce65c676e4a098f42402993c40461786d1f794d4", size = 291294 }, - { url = "https://files.pythonhosted.org/packages/dd/1f/bfe5b529257f0853aa6b94146e0f6462f4d45aa4f3c05d5a828f415dfd40/regex-2026.6.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2097591101d70bcc108af64c46f6066bb698ee067fec5f75beac0be317639311", size = 289216 }, - { url = "https://files.pythonhosted.org/packages/25/56/f615165e90ac5f3b72b249240643439520bbac0ac60a9de06868528eba4c/regex-2026.6.28-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:31d7538a614b5842bf53ce329d07b43f97754ca7e6db8d69f347e071bce1c953", size = 784787 }, - { url = "https://files.pythonhosted.org/packages/04/94/c9e3ad31b3d5fbe1228fee8319e0c02a5460296624f220d08764547fe6ae/regex-2026.6.28-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5561e47bbe2b75373b695326507743fcdd4d2cc7f5022312024ccf39fa094e0", size = 852137 }, - { url = "https://files.pythonhosted.org/packages/c0/77/d506a428e446466ee298f5425a774737d0671d070425ed794bb3314d60c6/regex-2026.6.28-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c10f2c5a55ab3dd8318d8ad5f11b530e2691c0edebebde7713066f484902c3fb", size = 899525 }, - { url = "https://files.pythonhosted.org/packages/aa/72/becc00d839f19401f10a20168b44711c7b02f7f62bba875b2d8f98417435/regex-2026.6.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23f7e0cc60c72486b42a685f1ff4eec90d50d4fb05e4f9c7d5363b03aa02600d", size = 794116 }, - { url = "https://files.pythonhosted.org/packages/fa/11/ea2ca423eeaac2e18077a18b058614e9201f130750df2126d444e39acab2/regex-2026.6.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:76493755f79a88d5ed2c9e63a41d3c05997e0a7ffbe76ed8c4ded8be35b8b14c", size = 786257 }, - { url = "https://files.pythonhosted.org/packages/6d/9e/f5bf7ecbd14ff2086f015c54dc24fd0d74ba5327fef0de479213f8128615/regex-2026.6.28-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ff0f41a00f23ea5054acb61901380c41813d813eee3f80f800995710bcc52ecd", size = 769914 }, - { url = "https://files.pythonhosted.org/packages/43/04/f9040a5360a06241ba5b7f2e6f1c6184e104a84e6f6522535700e94bf8e2/regex-2026.6.28-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3c60b297292e7e1ef5d02a4759f9e452ee4c8bb95e168d8fd0b5db01bd806f9f", size = 775013 }, - { url = "https://files.pythonhosted.org/packages/73/97/4e46f7abf2f864319d2bcac609af3c0532968c66a3364337778fd232b83c/regex-2026.6.28-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a7cf03c87f7b9cbc25a8894cf9be83818406677b6b391b003ec7c884923387b5", size = 848814 }, - { url = "https://files.pythonhosted.org/packages/f7/b8/3d1f995727799a1e2e693e397acb7358094606e5591b6b5fd3128d2d1409/regex-2026.6.28-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:418208ea0af51cfed4f46eb9b1ea7cfc990ca284f0084ecbd951460fb089421e", size = 757702 }, - { url = "https://files.pythonhosted.org/packages/20/10/fd5653b8572910a4fe9055f8959b070d7d9443c94ce986529fcdb5fb2a3c/regex-2026.6.28-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:7635fa2cddb917a6bbfac7890602573d2d8c4e470703b0640e6f86a988817ec3", size = 837140 }, - { url = "https://files.pythonhosted.org/packages/5d/31/da77e3ef7b594a2aacbd03ce3d0050f33ab3e021df50c6901467c9006511/regex-2026.6.28-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7bb96c13d6cf5880d31bbef84ca701a64d738aa491c2b79975cc33f8ad00a31e", size = 782105 }, - { url = "https://files.pythonhosted.org/packages/cd/4d/c379001448d0f58b6946f168d4af96ad60a16c1553259c27b0df8701b640/regex-2026.6.28-cp310-cp310-win32.whl", hash = "sha256:56f05194c4843957dd8b3af87eb0c52d8cf0509e7f18e172d727f5f8ff840646", size = 266728 }, - { url = "https://files.pythonhosted.org/packages/f3/8f/cb656529efa87d74cce0d69e606c745537016da3bdfae78f342af2242ee3/regex-2026.6.28-cp310-cp310-win_amd64.whl", hash = "sha256:70710927033af3b54369f17aaba1343b97a23d0b1aa994fa1512b08b1b8c136a", size = 277901 }, - { url = "https://files.pythonhosted.org/packages/7b/ac/d35ccc309c9409406445ab2ef0b56f6a341a916ccff49ff9ac5cc6bb8e9b/regex-2026.6.28-cp310-cp310-win_arm64.whl", hash = "sha256:ed7b30185ee3f8b9b053b0be567b4d226016e2afbebc17fde1c6a4580937b688", size = 276880 }, - { url = "https://files.pythonhosted.org/packages/72/db/9051b36294bdbabaa9c7db57db0fbcdfbd17f7a106c539bb423d0323faea/regex-2026.6.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a71b51dd08b9b62f055fafab3dee8af8bd2ec81b373a44caef18d6c5ca28f43a", size = 489481 }, - { url = "https://files.pythonhosted.org/packages/35/3f/24097a3c3ff30f9a639888900faaecabcf5f54a5bc9c851c297e11b349ef/regex-2026.6.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9c26a47770d30a0f85c01e261d2a3ebc342c4af6fd666dbd8c1fe4cbf3adf726", size = 291292 }, - { url = "https://files.pythonhosted.org/packages/5e/cc/e0d762a189cfb4e8926d16e691720690d139a977b38fdb80230c259332ab/regex-2026.6.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5efbc1af38f97e300d43028e5a92e752d924bcfb7f465d8669d5d5a6e78c233", size = 289232 }, - { url = "https://files.pythonhosted.org/packages/4b/c8/ca0ac7f09cc88ca61e0c61c53f7db29334f660ffba5d0b52378e7c44723c/regex-2026.6.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1758df6fdd8c800620a5638958720e8a635e1da49a2f09df2dd63e94a24ec4a", size = 792332 }, - { url = "https://files.pythonhosted.org/packages/8e/92/04ae94cbe0dd1f478b2aef6c46f995bb6946d3e338d4b28605478b66a2b7/regex-2026.6.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ad73ecf20c1ef5c975639f8bf845a9370fcf7dada7edc1e3b0bca20e2f8202f6", size = 861743 }, - { url = "https://files.pythonhosted.org/packages/4c/ec/024d7638c807679ff8a0e6081d01d66c7762339af1cac71e45911587ff9a/regex-2026.6.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d80c798b0eec6ea3d45f8816a1e8886c5664615d347d89e8c075b576a1b5a5d", size = 906481 }, - { url = "https://files.pythonhosted.org/packages/cd/fd/93bfe5af45f0be4fa8983945455c0e6924e1aeb879cde227958869c1e71c/regex-2026.6.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a361feeaf1b6ba1df060f2ff5c5947092edf537a35ce78e76387ac56d3e0f4a4", size = 799867 }, - { url = "https://files.pythonhosted.org/packages/ee/fd/e5d965d41f2398c8ce0f37a4652f03bb297fd009bb796d390134225dda12/regex-2026.6.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8b92366d9c8bba9642989534073662abdd9b41faf7603a7ae71597833f3b88f0", size = 773632 }, - { url = "https://files.pythonhosted.org/packages/eb/d9/ff39afaec92b9ee2dba0302a4783976005091681069808938c31cf8df3b6/regex-2026.6.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:11251768cc23f097dd61b18f67966e70f74da822784d17e12a444eb6b29d4288", size = 781669 }, - { url = "https://files.pythonhosted.org/packages/45/4e/e2fd4bb8228e10c24af2d7ff867182372190e498eab9fd29cbe54c403c95/regex-2026.6.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad5c67786145ec28a71a267d9f9d92bdc8d70d65541eea852c253f520a01f918", size = 854497 }, - { url = "https://files.pythonhosted.org/packages/72/7c/f0340384a973082979064156d05f3d2cc1dced7371efcd7a1b45726a1a8a/regex-2026.6.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f1da438e739765c3e85175ede05816cbede3caaacb1e0680568bda6119bfdfca", size = 763335 }, - { url = "https://files.pythonhosted.org/packages/e1/32/90ce0d0898e205506cc22b9c81cfb16b722e06ca5f50fad51c053c2a727b/regex-2026.6.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d98b639046e51c5de64d9f77351532105e99ca271cb6f7640e1f903d6ab63032", size = 844615 }, - { url = "https://files.pythonhosted.org/packages/6a/ef/55abb149599dce1ade687170557129524011eeb3d92afe02429cea7754a2/regex-2026.6.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e164ace4dbab5c6ad4a4ac7c41a2638fe226d0c770a86f2eb041f594bac6ee7", size = 789193 }, - { url = "https://files.pythonhosted.org/packages/f8/ea/cf7f6f6f152e52fdad978b913bf24c14df647eca0f81ef31f3aee0be8982/regex-2026.6.28-cp311-cp311-win32.whl", hash = "sha256:3169a3159e4d99d9ae85ff0ed90ef3b8906cc3152653b6078b842ace6c8f72c3", size = 266731 }, - { url = "https://files.pythonhosted.org/packages/c6/cf/a48d8e8d406b22481cad146f48fa0dfca3c5f402b91f26d8e5a0fe4f513d/regex-2026.6.28-cp311-cp311-win_amd64.whl", hash = "sha256:5977295b0a74e8241df8a4b3b27b12412a831f6fa32ee8b755039592cd768c3d", size = 277918 }, - { url = "https://files.pythonhosted.org/packages/89/b2/a222392207db7ed86281a732a99f7cf7f2bb35d332799e892b8510be000e/regex-2026.6.28-cp311-cp311-win_arm64.whl", hash = "sha256:f5fbaef40c3e9282ccee4b075f5600a0d858aa0c34147732f1baa69c8188a95d", size = 276876 }, - { url = "https://files.pythonhosted.org/packages/da/21/44aa415873032056c43eac21c67285deb2cf66cddb2a964c3cdc8f803efc/regex-2026.6.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:81cc5793ad33a10444445e8d29d3c73e752c8fb2e120772d70fcb6d41df40fe1", size = 490480 }, - { url = "https://files.pythonhosted.org/packages/8b/5f/30d4116093c2128099f78b6990dfc1698fdbf3ee528f1e1c647378034c79/regex-2026.6.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e18225243250a1f7d7e5e5d883f3b96465cd79031acf5c6db902b7025f2125d9", size = 292137 }, - { url = "https://files.pythonhosted.org/packages/cb/0e/ca20a0e0de49837e6337603a91ab77556aa27033ac5b975615d98698cfb3/regex-2026.6.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ecd1638b1c2db1f2d01c182a4b0d3e2e88b0e99910320a745c1727ee3638ddab", size = 289623 }, - { url = "https://files.pythonhosted.org/packages/50/11/c013422a7e2c59946df8ac93e792a4922c98287f2a2181341603c78a5d98/regex-2026.6.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4303ebe16b74eeb3fe2715745023266fea92fd44a23f3e7bb2fb48c7a7bbc195", size = 796756 }, - { url = "https://files.pythonhosted.org/packages/b0/95/1309645a0e1ee6fb91d954501da57a0b33d50ad2a9acb313702851a7054e/regex-2026.6.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56b856b70b96c381d837f609eee442a1bd320cd2159f5c294b679552fb1a7eaf", size = 865465 }, - { url = "https://files.pythonhosted.org/packages/20/06/491802db47c6f5e2904ffa2518ad3ac27fe6bbf5a66d73210a95cc080d47/regex-2026.6.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f74675ab76ab1d005ffba4dee308e53e89efc22be6e9f9fae5b539a3f81bdff2", size = 912350 }, - { url = "https://files.pythonhosted.org/packages/5e/60/3ba57840bcc7e2367090360de0c15a5ba6ad22be89314251105f2e943f43/regex-2026.6.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90581684565a93f7258af1e5d3f41ef20d7d7c61f2a428183a342bcb65485e38", size = 801261 }, - { url = "https://files.pythonhosted.org/packages/eb/27/af1eb74e9a78c782b3e450b611a595e44906da8a5107e1227f4a7fd0480b/regex-2026.6.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:28f9e6c28f9b90f6f784595a33240a57e181e61b6ee3dc259b25c61e356d1aa3", size = 777072 }, - { url = "https://files.pythonhosted.org/packages/20/18/fdd4c883a39e3ed00d669062af1135809bfd3281bf528150849fbd68825b/regex-2026.6.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:378a71d861fc7c8806b04ac5b133d53c0e774f92f5d9663a539872d3fa2b0417", size = 785119 }, - { url = "https://files.pythonhosted.org/packages/1c/79/0aabe34b8482dcadf64355f70f96e22eba5ec6c1efb33563f89654f4061c/regex-2026.6.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4cc199874ecd6267a49b111052250825bfe19b5101b23b2ba80f54efa3e0994e", size = 860118 }, - { url = "https://files.pythonhosted.org/packages/a8/2c/c973323306a27c9db7d160e9584eb7e0ece2a96224ccb0d39060558b31f9/regex-2026.6.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b916a10431494ef4b4d62c6c89cab6426af7873125b8cd6c15811bf5fc58eec8", size = 765786 }, - { url = "https://files.pythonhosted.org/packages/e3/df/9ca3e378e352242a4cb45573a5e9162c3ee791507702a23966fa559e36b5/regex-2026.6.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e27727fba075f1e4409416d2f537d4c30fc11f012ea507f7bd74d3e19ecb57a", size = 852120 }, - { url = "https://files.pythonhosted.org/packages/a2/3e/3e31e255c4971f53cbce6306b5e3c76cbd3735a54f419bb3b2f194e9f68c/regex-2026.6.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:700fc6a7844bb2c4149292ac79d1df8841a00acd4d45cd32c1ebc7bcc1fd0da8", size = 789503 }, - { url = "https://files.pythonhosted.org/packages/72/01/d36561c21c3033d7eeb31d51b491916817de7861acefccc5fc9db8a5037c/regex-2026.6.28-cp312-cp312-win32.whl", hash = "sha256:03376d60b6a11aecb88a79fa2be06b40faa01c6693bc31ef69435cd4818b9463", size = 267109 }, - { url = "https://files.pythonhosted.org/packages/a0/59/bbbb0591f38b18c65977cd65ce64749eba1c1996c99ac04e900fc30c0dcb/regex-2026.6.28-cp312-cp312-win_amd64.whl", hash = "sha256:fbd2ded482bf99e6651992bbfcde460272724d4bbc49ef3d6b46d9312867ec84", size = 277711 }, - { url = "https://files.pythonhosted.org/packages/86/06/be4f6b337d773ae5739a1bc238f97c16926e72017243735853c030f4c628/regex-2026.6.28-cp312-cp312-win_arm64.whl", hash = "sha256:37294d3d7ddb64c7e89184b2894e0f8f0a19c514bc59513d71fe692c3a8d5fc6", size = 277022 }, - { url = "https://files.pythonhosted.org/packages/b6/53/d5c1b3cc0b5a0c985563ad6fac93d73ff2b300cb84342d89f044625d6bc7/regex-2026.6.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b295a83426e0e44e9e60fde99789e181bd26788a1890ae7fe2a24c69bb6246ca", size = 490329 }, - { url = "https://files.pythonhosted.org/packages/8d/9f/0c3503e819e91ca0e7a901a8e989ebf840ac7c7aea20b1fc7f31b6759f77/regex-2026.6.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c31665c0deb5c111557a1cac8c27bd5629e2f9e7fd5058900a03576c33b601c", size = 292039 }, - { url = "https://files.pythonhosted.org/packages/bb/7f/cd004e13fcad23b3794a82307dfd222e6365eb7f598bd3caab148a830bff/regex-2026.6.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6bf295f2c59de77d1ea7de053607ae4dc9ceb3d57bbb6c7ec51ef4acc4ccff94", size = 289488 }, - { url = "https://files.pythonhosted.org/packages/73/4c/293fb34586fbcdc47eac436069e9c11f71fae5dadfd4889b475d7d2e5f7a/regex-2026.6.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17c077586770f67e05bbffeba07fbee6b2b22244f4d4caf8d94e59d574befe04", size = 796772 }, - { url = "https://files.pythonhosted.org/packages/92/fa/c0cd1a90b7d12d9dc155cfc8bdea8df9720988ea5b07e8fa1eccbd0ab2dd/regex-2026.6.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e6cb5a61486f9062397d2e189573b39d38ecfaed698fd9fb6e2756a8ebb8762", size = 865467 }, - { url = "https://files.pythonhosted.org/packages/4e/db/0b479973046d005a1eaea299d5d536aeecb9488a16d9cbb8286338102e2d/regex-2026.6.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e86e91a2664f44c3a4e363a7d78fb17c27d5046882e30ea5a877f5e89b28d2ba", size = 912345 }, - { url = "https://files.pythonhosted.org/packages/5b/5b/d65adfbd02f32212431bca1f06d1e2eb763a20b12978b454bafaf23dacb7/regex-2026.6.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4dfd1331c49233998d84fc5f1f4436cf7a435a7655f6cf0f490229bb5c7254e5", size = 801291 }, - { url = "https://files.pythonhosted.org/packages/fc/09/2103686defaf9a0a31c1663782359d5b45f42524c64cca681f5481e44a5e/regex-2026.6.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cadea12805a1bce0b091c302b814207be26fb60a9c0e7f9ad2f9e21790a429fe", size = 777106 }, - { url = "https://files.pythonhosted.org/packages/85/5a/b57593c0aa23ed269ec332fbcf07852abcb6b746e811d9464e0d09b4e25f/regex-2026.6.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5f2c1682b67ad5d2376498f2a5a2a8f782fa2e4a06d0465b5e357799806e8a20", size = 785175 }, - { url = "https://files.pythonhosted.org/packages/79/59/c36e756ad29bf14d7b6c6d7138952476b21f6160286cedb98ac13481c993/regex-2026.6.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:64e142eb55e84868087da1375d7c36ff97d55010951849f515322a91d5fef1b4", size = 860186 }, - { url = "https://files.pythonhosted.org/packages/61/66/49808aea0da9649c300139360708fb91b7144be1f962fcebf96755fde948/regex-2026.6.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:abb4daabe7be63273787a62dfd6164dadf8f7a63fbec3d2730e5e5e7126d858c", size = 765754 }, - { url = "https://files.pythonhosted.org/packages/be/c5/52bbd436cf2200decdf48825fa38363eaaeebb77011ea9928a1ef9e0b9f2/regex-2026.6.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec2b2ad00ab8c16a2798cc8db80c53c4d5b8b3a2441f6cbaef06625f5ca25854", size = 852085 }, - { url = "https://files.pythonhosted.org/packages/f9/c3/0390b66e3019497143fe768b3ba567b64d8b24f3812d09506deb86f4a0f0/regex-2026.6.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bfc9677982c914d9085b8e1c3b3ae6e88f139fb56531c2416d6c8f338093c22b", size = 789600 }, - { url = "https://files.pythonhosted.org/packages/88/fd/ab5b03653a244975069fed93d73f4f5f7484c03a84cedb238292510d7182/regex-2026.6.28-cp313-cp313-win32.whl", hash = "sha256:bf54bc693fc4e0530e666ba5ec4bcba14dbe8f66b7cfc15c27317d1a6e40b9a5", size = 267088 }, - { url = "https://files.pythonhosted.org/packages/68/55/21022f7d3143210ae8d4ff905c45306237b657375cc0b97883f49db3d423/regex-2026.6.28-cp313-cp313-win_amd64.whl", hash = "sha256:e128feaf65bf3d9eb91bec92322a8f7e4835e9c798f3e9ea4b69f4def85620e3", size = 277680 }, - { url = "https://files.pythonhosted.org/packages/b6/99/7f664804f1aef924542b0b233996b78b3e4d0a52d9951358aac99f129f51/regex-2026.6.28-cp313-cp313-win_arm64.whl", hash = "sha256:695873e0ea8d3815ea9e92e2c68faf039cc450e2c0a62a31afe2049eb11be767", size = 277017 }, - { url = "https://files.pythonhosted.org/packages/cb/e1/9eb83518e159d719fd681c4932dc2aaff855ce72451e1d05d69466f25a96/regex-2026.6.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:189dbf9fc4252d9f1352bf4bd1bef885edb6cc4b7341df202a65f821aaa3891c", size = 494195 }, - { url = "https://files.pythonhosted.org/packages/fd/e2/e259c5f2f7be269d0e2fb54275c1fa6a13fb47019f389c3f3ae457447825/regex-2026.6.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9277a4c6503390aa39cb4483b87ec0384faee0850a23b5cea33d008b5d8d83f1", size = 293976 }, - { url = "https://files.pythonhosted.org/packages/8d/4e/9bdf444014d22b045d0c82ca114fac7e07a597b5b5331b7c4ce6328426e2/regex-2026.6.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17eddca4e8ea9af0b5739314776cdf0172a49731ab61f2e1ea66e066ddd46c97", size = 292340 }, - { url = "https://files.pythonhosted.org/packages/fd/3a/f49b11e59cbfe187ace0053a460bd72a0169b8cd52e7db9421a074ce7a43/regex-2026.6.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4466b8641e00c697aab5a73150150d2b2ea96b131c595691f42031abafd9f4d", size = 811704 }, - { url = "https://files.pythonhosted.org/packages/2f/fb/ad04c39e149bf8b6cf357df5fff78341733ec366780a00c803a36735818c/regex-2026.6.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9cfcd4b0bdcf768c498415c170d1ed2a25a99bf0b65fa253bbd02f68ceba6475", size = 871157 }, - { url = "https://files.pythonhosted.org/packages/7f/64/0e5ba31c11eb8ef7aac19a690c1211fc9aa9990caf09565785ebb0081b9a/regex-2026.6.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:80c7adf1ef647f6b1e8aa2ca280e517174cd08bdf7a2e412cdfb68bd6a0917cb", size = 917287 }, - { url = "https://files.pythonhosted.org/packages/11/75/6b78df2b858c2fcbbc4858fdc3f2975cf2703be374b2842db7d2c32591a7/regex-2026.6.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a043f5770e82283a22aed4cefef1a4e0f9dd8fd7184cb6ce0ad2e579e2134a9e", size = 816333 }, - { url = "https://files.pythonhosted.org/packages/b4/01/ecfe665a3694d5eda9f3ec686c856438ada0943947b6005e90556a1e2cdf/regex-2026.6.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3bd630a8dba06b55254ea5ee862194edab52ec783100d2ef1cd15a9c512fee27", size = 785518 }, - { url = "https://files.pythonhosted.org/packages/b4/0a/88f9cd88ff1e82881605c4ffd62d77ee67d051232cfe6f8e9a64b86cf0e8/regex-2026.6.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b77207e3cee13086f1906a6a2a12b41244c577e8ad9370d4b35ae1d548d354f3", size = 801371 }, - { url = "https://files.pythonhosted.org/packages/a8/97/601483732f93275482ceb9fed57813dfed7c47d3a019db6ec4a3bb6e23e0/regex-2026.6.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:6de82c268e5d101ee9e3ffd869924aa9a371e3a21e752cf4fa17b6ce50d219f7", size = 866517 }, - { url = "https://files.pythonhosted.org/packages/81/ed/385c2a0351b994a693453c1d1a6e9af9eb35db3c9460d76b5078acd70c62/regex-2026.6.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b15859e3908544fb99cf47341dcf0bfd089147d258c4c4d8a29e5b087f8085cb", size = 772834 }, - { url = "https://files.pythonhosted.org/packages/06/bc/bbf4a5b3b29770d7f307d3c28b5b1bca0105b0cb424be0a4eb1339bc92cf/regex-2026.6.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c91487a917edd48a1ea646fdf60d7936d304f0e686fa7ea8326e47efca51d816", size = 856606 }, - { url = "https://files.pythonhosted.org/packages/28/26/51d74fff82f682819979249f8d700267108ba5dc4eb284b0e11b9c85e4b3/regex-2026.6.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4ac65f3e3a99fd8f3a4a74e7a6610acd1ce9dfe9b8a03d346a4922380d68aeb", size = 803475 }, - { url = "https://files.pythonhosted.org/packages/7c/3e/6be10cefdc813533fe604dbf5d3c77d2638e7ee658b2749ebadc113b6b2e/regex-2026.6.28-cp313-cp313t-win32.whl", hash = "sha256:3f6316f258bc7e6c9c2acbe9954947bbd397a81be3742a637a555f1855d6618d", size = 269126 }, - { url = "https://files.pythonhosted.org/packages/3c/3c/32cda905ea1a6eeeb798291c294d8ec66ee0efe0cdba28b061e248b1d396/regex-2026.6.28-cp313-cp313t-win_amd64.whl", hash = "sha256:1484bdd6fba28422df9b5ebb04055b2e1b680e8e4f08490bb21ff0f3cc50d0ab", size = 279961 }, - { url = "https://files.pythonhosted.org/packages/ea/b9/69f4e5cd6fbe0bb420cb2dbae441ca118f2495bdda522a74da75aa9829e7/regex-2026.6.28-cp313-cp313t-win_arm64.whl", hash = "sha256:3f15020f0b69cafe57baa067ff65b29acef68ff6b1670a53bef1ca11d708e02d", size = 279266 }, - { url = "https://files.pythonhosted.org/packages/3b/fb/fad3b810a5bb1e09b9e5d6913fc6ba88cab738fdf283196827a3c59a4c10/regex-2026.6.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:f7c032b0c8a73739ff8ff1aaf30c281fa19c17bf7f1543256c8507390db7807c", size = 490407 }, - { url = "https://files.pythonhosted.org/packages/d6/52/b8c79d12276d93e90e707e939b396034c04980caf1235312ef790f8e11fc/regex-2026.6.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f6710f512c57b84f127a23d0f59560a03b64136eff419ae1be5ab557577fe5e3", size = 291988 }, - { url = "https://files.pythonhosted.org/packages/23/d2/6a911f18279daa8d7bb8b20d771ddb6ef31fabd35f5921f9d3ba21640e80/regex-2026.6.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c0013958f427bd82509a186b9ff206d66cb8d60a81fc797a4c717afd18c5b0ba", size = 289704 }, - { url = "https://files.pythonhosted.org/packages/fd/22/ad1955c47c669291a05804d53d7071cc0732dfdf166857be38003cedc2d1/regex-2026.6.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f06cdcd6421f8e194ad312ea608020381250df9b8a57661c1b57e9e5273878", size = 797017 }, - { url = "https://files.pythonhosted.org/packages/e5/67/a83159ff8703ab4d0c2cf99e76ebf289b7b4a501623241d09f88f3614f80/regex-2026.6.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec9689392f7494ff4e3f8e7e8522f9158f11023f337eaaf04a64542fc45bbf26", size = 866112 }, - { url = "https://files.pythonhosted.org/packages/b9/09/7bff2d6dbbd77421b3274aa51db1c887381cbc5b6eda93598c3e882ea345/regex-2026.6.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aa084684e6d2078bf6139e374d1fc2af5ddc1ac7122759a2db716d68169f6fd0", size = 911554 }, - { url = "https://files.pythonhosted.org/packages/29/44/ae59c3826e7ba492e56795cdf74ea2a7b5b7c5ea116afb79ee4956a5dff1/regex-2026.6.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:40455e6840dc4e96a6fe50f4cedc957de2752c954d91e789812be55d49be199a", size = 800665 }, - { url = "https://files.pythonhosted.org/packages/d6/19/6fd033d2ab00f35d445aaeaf3307c1e721424dcbfd48f6f65c857cb939cf/regex-2026.6.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:530b5c223b9ca5dd8370ac502e080aee0e4ded32be987c6564b425fb5523d581", size = 777243 }, - { url = "https://files.pythonhosted.org/packages/4e/9d/99730f26df4938049ab1e652ca75e967b4c6739444e18d9707bfdb8af20c/regex-2026.6.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e0ed273ecd1a89be84466c1749bfe58609cc2a32b5d5e05006c4625ba96411b", size = 785784 }, - { url = "https://files.pythonhosted.org/packages/48/49/105cd57162f5fc5c04cc917a1388a060cf8427e5c14353cd9044660fbf4d/regex-2026.6.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0ab0d5344311fc8e8667078942056c3b9c9b4a4b1cc99f2eb8a5af54554f4acc", size = 860914 }, - { url = "https://files.pythonhosted.org/packages/a2/a5/788245a95b69018f58bff2f4fd27d007cacaea088cdb390979743f1b2571/regex-2026.6.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:eacb79625323d9f7e7925366b917f492b8356fad58f5dc4fa12ff8c21d8f4ca9", size = 765915 }, - { url = "https://files.pythonhosted.org/packages/ca/01/292065a39a004b05e67a337b18213670a7cb919d6856ac2d7df7f1a10dbb/regex-2026.6.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:20f4d87702702aa1d572721e146f301660c50eef6fd6cb596e48a22b0ace17db", size = 851404 }, - { url = "https://files.pythonhosted.org/packages/98/9e/a93d865db0e13483ae1a01d81e2ce16d4a7fe2f9b9fe4aac4cc08590b136/regex-2026.6.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e693940a3b9e6d6e4dc2a54ecaa74b74934f77af1ef95f518a74261ef7cc1bc", size = 789373 }, - { url = "https://files.pythonhosted.org/packages/82/0c/38b1685ad4017d78efbc8fa7dbbf96d8113b53750c8aa2d3609defd46605/regex-2026.6.28-cp314-cp314-win32.whl", hash = "sha256:234a51e20ebc18ab83b2c0600cf28f2e884560a0e00f743878f0b7d8e7c4cf03", size = 272496 }, - { url = "https://files.pythonhosted.org/packages/55/50/e19f261ff9ba9b50722a529e09b1743ecf65eb348be99d0fd2cd7fcede1c/regex-2026.6.28-cp314-cp314-win_amd64.whl", hash = "sha256:7b15c437bc4604f03ceb3f8d37eae2f8930e320e1bc556b259848c639d9eec1a", size = 280754 }, - { url = "https://files.pythonhosted.org/packages/36/b8/c9e68f3a9e33be73f20990b2c065b144ff2d0aa242608a950d8c4f3b56e8/regex-2026.6.28-cp314-cp314-win_arm64.whl", hash = "sha256:c6e6f790d01380a74ad564f216c533b86504afb61bf66f2b2e11e7f1a3e287a7", size = 280979 }, - { url = "https://files.pythonhosted.org/packages/03/e6/21c425a37880c650d007c4171c6a80325446d830d85f5fbf335e7205b1e7/regex-2026.6.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3527a72adcbe9e3600f1553b497d397c1a371d227580d41d96c3c5964109b65c", size = 494282 }, - { url = "https://files.pythonhosted.org/packages/07/50/6647a7ccf5ffff995ba955a0b7d766440f4e58ce1666549c8ee998f2b972/regex-2026.6.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a644f6408692812f5ead82519eed680e08d5d546fddbd9f7d9514e3c73899aa5", size = 293977 }, - { url = "https://files.pythonhosted.org/packages/8c/dc/a3e141a4eaf125e50f63105570c01fa477c06ac5259dcfa95e9b90760e84/regex-2026.6.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8e2fae6bb883648346f84db270dc9aafc29d8e895f62b88a75ccc83b09519820", size = 292432 }, - { url = "https://files.pythonhosted.org/packages/35/ee/2ac1a6b9f167f8ff69f5a789938cc103b60cff41b24a6990daced8b88e34/regex-2026.6.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:debe623e09cee97ef9404575e936c610aac9bb08358c5099aaef14644a6871f2", size = 811877 }, - { url = "https://files.pythonhosted.org/packages/df/7b/9a5505ee92180bcae300b1018b9ff3d3c19962436e66f2505f255e9fde35/regex-2026.6.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc579c91fb4605773483a8d940b136bcc5b854fff44fa14a1572a038f46563f1", size = 871212 }, - { url = "https://files.pythonhosted.org/packages/24/4d/d61a702a9f9d1bd29b22cbef1aed6d477baa961232a7eb4d91b7775b0b3e/regex-2026.6.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7c42be203d84ecf7d487ff23f8a61ef0eb0534fa0fc317a2fce8c065d20618f", size = 917507 }, - { url = "https://files.pythonhosted.org/packages/d4/60/1308066f5966b65fbb6905b99ba37e9f1cd753dd0ac08485f8257334ee92/regex-2026.6.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8184b4e2fdaf9cdfe77e38f15a4d9dc149168c9c29eb0ea17c5481d3bb80546", size = 816389 }, - { url = "https://files.pythonhosted.org/packages/bd/5c/57ce2cb8d714ee0b7f11c7ee4cfe2af66df2b90f147feadcb538609a3a02/regex-2026.6.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:697f103104f5872d64078d8eeac59979960be8ee76115a2d3f31096312e2a400", size = 785890 }, - { url = "https://files.pythonhosted.org/packages/ff/fd/1d5350d3a8a327bff0fccacb911732baf7b5b6f5529c0e3fa602a23e7dad/regex-2026.6.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:714d2b1aa29beef0ddfcdc72ad0771c05326551a8bb0680b0ddf74bfaad87387", size = 801451 }, - { url = "https://files.pythonhosted.org/packages/f3/79/3c9e4f8a0306e030ad5a43bbbc01625fb28d58a813bc52d42fd1cc63fb2e/regex-2026.6.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0f09f62e450cc2f113018cc8412aeea3a120a04e1ca7e801a0d441583f9a3b06", size = 866504 }, - { url = "https://files.pythonhosted.org/packages/65/12/f747de475b54f4709efb24dd0fbc8467c64cec91f5db0d047b079646ee78/regex-2026.6.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:731ea12d5aeb2577eaef2393d6428b995f76eb35f68a89e03e15a97719d1de19", size = 773047 }, - { url = "https://files.pythonhosted.org/packages/58/3c/f02f860e0500c1b2d61a79dec7e214b37fb9656281dcddc92397edf96678/regex-2026.6.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:51e952c8783eabd4706d0f63922f219bcfc1bef9b8cb35941c0d1a0396578858", size = 856665 }, - { url = "https://files.pythonhosted.org/packages/4d/6c/28b3fa222513484be9dee26b7222bda109056c43ea28aa2314262ca48816/regex-2026.6.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43248fe4c0ab8fbb223588a0795b11268940072c97bba30ea8f9b49d8cdfde34", size = 803573 }, - { url = "https://files.pythonhosted.org/packages/fa/f0/8f86cf1a1fd85c5ab0c503c9fe4607ad4ad48978b2d8b435d94465e134c7/regex-2026.6.28-cp314-cp314t-win32.whl", hash = "sha256:fc1eddc25ad23c0f1344ab280d961ac595ead48292d7c779497975942373f493", size = 274515 }, - { url = "https://files.pythonhosted.org/packages/0f/de/f8613c03b36786ddef2c930d28f9bcae861fcd541cc9203a870956cf1e83/regex-2026.6.28-cp314-cp314t-win_amd64.whl", hash = "sha256:ede8d8e53b6dde0a50f7eca902f0af76d87ab02a55aba7542da68ae3e5dfe83d", size = 283650 }, - { url = "https://files.pythonhosted.org/packages/4d/f3/f5ec86839bbabe33b6dee649b62ff9a445d43de6b0ad780cf6b83c56f61e/regex-2026.6.28-cp314-cp314t-win_arm64.whl", hash = "sha256:4da6f6a72f8700b97a1a765e837fb7d5750bfd9f13acea7bae498f573e3a70a8", size = 283338 }, + { url = "https://files.pythonhosted.org/packages/d8/dc/f7a8c9cf0768f704153d358fae2bc883199bc4ea1e4aa458f1be9d0ef2ce/regex-2026.6.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b83932645630965fd860fdb70ebbf964bf3e8007f08851ea424d01f8d35454a8", size = 489471, upload-time = "2026-06-28T19:53:06.385Z" }, + { url = "https://files.pythonhosted.org/packages/44/b3/9786a4a2133e2f1cc5897ed3d2da3da29ff54b775ffa38bc5935fc24be82/regex-2026.6.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e81f1952355042e517dc9861ce65c676e4a098f42402993c40461786d1f794d4", size = 291294, upload-time = "2026-06-28T19:53:09.232Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1f/bfe5b529257f0853aa6b94146e0f6462f4d45aa4f3c05d5a828f415dfd40/regex-2026.6.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2097591101d70bcc108af64c46f6066bb698ee067fec5f75beac0be317639311", size = 289216, upload-time = "2026-06-28T19:53:10.682Z" }, + { url = "https://files.pythonhosted.org/packages/25/56/f615165e90ac5f3b72b249240643439520bbac0ac60a9de06868528eba4c/regex-2026.6.28-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:31d7538a614b5842bf53ce329d07b43f97754ca7e6db8d69f347e071bce1c953", size = 784787, upload-time = "2026-06-28T19:53:12.393Z" }, + { url = "https://files.pythonhosted.org/packages/04/94/c9e3ad31b3d5fbe1228fee8319e0c02a5460296624f220d08764547fe6ae/regex-2026.6.28-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5561e47bbe2b75373b695326507743fcdd4d2cc7f5022312024ccf39fa094e0", size = 852137, upload-time = "2026-06-28T19:53:14.287Z" }, + { url = "https://files.pythonhosted.org/packages/c0/77/d506a428e446466ee298f5425a774737d0671d070425ed794bb3314d60c6/regex-2026.6.28-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c10f2c5a55ab3dd8318d8ad5f11b530e2691c0edebebde7713066f484902c3fb", size = 899525, upload-time = "2026-06-28T19:53:15.987Z" }, + { url = "https://files.pythonhosted.org/packages/aa/72/becc00d839f19401f10a20168b44711c7b02f7f62bba875b2d8f98417435/regex-2026.6.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23f7e0cc60c72486b42a685f1ff4eec90d50d4fb05e4f9c7d5363b03aa02600d", size = 794116, upload-time = "2026-06-28T19:53:17.372Z" }, + { url = "https://files.pythonhosted.org/packages/fa/11/ea2ca423eeaac2e18077a18b058614e9201f130750df2126d444e39acab2/regex-2026.6.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:76493755f79a88d5ed2c9e63a41d3c05997e0a7ffbe76ed8c4ded8be35b8b14c", size = 786257, upload-time = "2026-06-28T19:53:18.712Z" }, + { url = "https://files.pythonhosted.org/packages/6d/9e/f5bf7ecbd14ff2086f015c54dc24fd0d74ba5327fef0de479213f8128615/regex-2026.6.28-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ff0f41a00f23ea5054acb61901380c41813d813eee3f80f800995710bcc52ecd", size = 769914, upload-time = "2026-06-28T19:53:20.564Z" }, + { url = "https://files.pythonhosted.org/packages/43/04/f9040a5360a06241ba5b7f2e6f1c6184e104a84e6f6522535700e94bf8e2/regex-2026.6.28-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3c60b297292e7e1ef5d02a4759f9e452ee4c8bb95e168d8fd0b5db01bd806f9f", size = 775013, upload-time = "2026-06-28T19:53:22.067Z" }, + { url = "https://files.pythonhosted.org/packages/73/97/4e46f7abf2f864319d2bcac609af3c0532968c66a3364337778fd232b83c/regex-2026.6.28-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a7cf03c87f7b9cbc25a8894cf9be83818406677b6b391b003ec7c884923387b5", size = 848814, upload-time = "2026-06-28T19:53:24.575Z" }, + { url = "https://files.pythonhosted.org/packages/f7/b8/3d1f995727799a1e2e693e397acb7358094606e5591b6b5fd3128d2d1409/regex-2026.6.28-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:418208ea0af51cfed4f46eb9b1ea7cfc990ca284f0084ecbd951460fb089421e", size = 757702, upload-time = "2026-06-28T19:53:26.215Z" }, + { url = "https://files.pythonhosted.org/packages/20/10/fd5653b8572910a4fe9055f8959b070d7d9443c94ce986529fcdb5fb2a3c/regex-2026.6.28-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:7635fa2cddb917a6bbfac7890602573d2d8c4e470703b0640e6f86a988817ec3", size = 837140, upload-time = "2026-06-28T19:53:27.655Z" }, + { url = "https://files.pythonhosted.org/packages/5d/31/da77e3ef7b594a2aacbd03ce3d0050f33ab3e021df50c6901467c9006511/regex-2026.6.28-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7bb96c13d6cf5880d31bbef84ca701a64d738aa491c2b79975cc33f8ad00a31e", size = 782105, upload-time = "2026-06-28T19:53:29.375Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4d/c379001448d0f58b6946f168d4af96ad60a16c1553259c27b0df8701b640/regex-2026.6.28-cp310-cp310-win32.whl", hash = "sha256:56f05194c4843957dd8b3af87eb0c52d8cf0509e7f18e172d727f5f8ff840646", size = 266728, upload-time = "2026-06-28T19:53:31.813Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8f/cb656529efa87d74cce0d69e606c745537016da3bdfae78f342af2242ee3/regex-2026.6.28-cp310-cp310-win_amd64.whl", hash = "sha256:70710927033af3b54369f17aaba1343b97a23d0b1aa994fa1512b08b1b8c136a", size = 277901, upload-time = "2026-06-28T19:53:33.293Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ac/d35ccc309c9409406445ab2ef0b56f6a341a916ccff49ff9ac5cc6bb8e9b/regex-2026.6.28-cp310-cp310-win_arm64.whl", hash = "sha256:ed7b30185ee3f8b9b053b0be567b4d226016e2afbebc17fde1c6a4580937b688", size = 276880, upload-time = "2026-06-28T19:53:35.029Z" }, + { url = "https://files.pythonhosted.org/packages/72/db/9051b36294bdbabaa9c7db57db0fbcdfbd17f7a106c539bb423d0323faea/regex-2026.6.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a71b51dd08b9b62f055fafab3dee8af8bd2ec81b373a44caef18d6c5ca28f43a", size = 489481, upload-time = "2026-06-28T19:53:36.684Z" }, + { url = "https://files.pythonhosted.org/packages/35/3f/24097a3c3ff30f9a639888900faaecabcf5f54a5bc9c851c297e11b349ef/regex-2026.6.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9c26a47770d30a0f85c01e261d2a3ebc342c4af6fd666dbd8c1fe4cbf3adf726", size = 291292, upload-time = "2026-06-28T19:53:38.39Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cc/e0d762a189cfb4e8926d16e691720690d139a977b38fdb80230c259332ab/regex-2026.6.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5efbc1af38f97e300d43028e5a92e752d924bcfb7f465d8669d5d5a6e78c233", size = 289232, upload-time = "2026-06-28T19:53:40.181Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c8/ca0ac7f09cc88ca61e0c61c53f7db29334f660ffba5d0b52378e7c44723c/regex-2026.6.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1758df6fdd8c800620a5638958720e8a635e1da49a2f09df2dd63e94a24ec4a", size = 792332, upload-time = "2026-06-28T19:53:41.782Z" }, + { url = "https://files.pythonhosted.org/packages/8e/92/04ae94cbe0dd1f478b2aef6c46f995bb6946d3e338d4b28605478b66a2b7/regex-2026.6.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ad73ecf20c1ef5c975639f8bf845a9370fcf7dada7edc1e3b0bca20e2f8202f6", size = 861743, upload-time = "2026-06-28T19:53:43.261Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ec/024d7638c807679ff8a0e6081d01d66c7762339af1cac71e45911587ff9a/regex-2026.6.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d80c798b0eec6ea3d45f8816a1e8886c5664615d347d89e8c075b576a1b5a5d", size = 906481, upload-time = "2026-06-28T19:53:44.948Z" }, + { url = "https://files.pythonhosted.org/packages/cd/fd/93bfe5af45f0be4fa8983945455c0e6924e1aeb879cde227958869c1e71c/regex-2026.6.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a361feeaf1b6ba1df060f2ff5c5947092edf537a35ce78e76387ac56d3e0f4a4", size = 799867, upload-time = "2026-06-28T19:53:46.997Z" }, + { url = "https://files.pythonhosted.org/packages/ee/fd/e5d965d41f2398c8ce0f37a4652f03bb297fd009bb796d390134225dda12/regex-2026.6.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8b92366d9c8bba9642989534073662abdd9b41faf7603a7ae71597833f3b88f0", size = 773632, upload-time = "2026-06-28T19:53:48.892Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d9/ff39afaec92b9ee2dba0302a4783976005091681069808938c31cf8df3b6/regex-2026.6.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:11251768cc23f097dd61b18f67966e70f74da822784d17e12a444eb6b29d4288", size = 781669, upload-time = "2026-06-28T19:53:50.693Z" }, + { url = "https://files.pythonhosted.org/packages/45/4e/e2fd4bb8228e10c24af2d7ff867182372190e498eab9fd29cbe54c403c95/regex-2026.6.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad5c67786145ec28a71a267d9f9d92bdc8d70d65541eea852c253f520a01f918", size = 854497, upload-time = "2026-06-28T19:53:52.323Z" }, + { url = "https://files.pythonhosted.org/packages/72/7c/f0340384a973082979064156d05f3d2cc1dced7371efcd7a1b45726a1a8a/regex-2026.6.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f1da438e739765c3e85175ede05816cbede3caaacb1e0680568bda6119bfdfca", size = 763335, upload-time = "2026-06-28T19:53:54.024Z" }, + { url = "https://files.pythonhosted.org/packages/e1/32/90ce0d0898e205506cc22b9c81cfb16b722e06ca5f50fad51c053c2a727b/regex-2026.6.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d98b639046e51c5de64d9f77351532105e99ca271cb6f7640e1f903d6ab63032", size = 844615, upload-time = "2026-06-28T19:53:56.216Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ef/55abb149599dce1ade687170557129524011eeb3d92afe02429cea7754a2/regex-2026.6.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e164ace4dbab5c6ad4a4ac7c41a2638fe226d0c770a86f2eb041f594bac6ee7", size = 789193, upload-time = "2026-06-28T19:53:57.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ea/cf7f6f6f152e52fdad978b913bf24c14df647eca0f81ef31f3aee0be8982/regex-2026.6.28-cp311-cp311-win32.whl", hash = "sha256:3169a3159e4d99d9ae85ff0ed90ef3b8906cc3152653b6078b842ace6c8f72c3", size = 266731, upload-time = "2026-06-28T19:53:59.938Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cf/a48d8e8d406b22481cad146f48fa0dfca3c5f402b91f26d8e5a0fe4f513d/regex-2026.6.28-cp311-cp311-win_amd64.whl", hash = "sha256:5977295b0a74e8241df8a4b3b27b12412a831f6fa32ee8b755039592cd768c3d", size = 277918, upload-time = "2026-06-28T19:54:01.502Z" }, + { url = "https://files.pythonhosted.org/packages/89/b2/a222392207db7ed86281a732a99f7cf7f2bb35d332799e892b8510be000e/regex-2026.6.28-cp311-cp311-win_arm64.whl", hash = "sha256:f5fbaef40c3e9282ccee4b075f5600a0d858aa0c34147732f1baa69c8188a95d", size = 276876, upload-time = "2026-06-28T19:54:03.411Z" }, + { url = "https://files.pythonhosted.org/packages/da/21/44aa415873032056c43eac21c67285deb2cf66cddb2a964c3cdc8f803efc/regex-2026.6.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:81cc5793ad33a10444445e8d29d3c73e752c8fb2e120772d70fcb6d41df40fe1", size = 490480, upload-time = "2026-06-28T19:54:05.392Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5f/30d4116093c2128099f78b6990dfc1698fdbf3ee528f1e1c647378034c79/regex-2026.6.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e18225243250a1f7d7e5e5d883f3b96465cd79031acf5c6db902b7025f2125d9", size = 292137, upload-time = "2026-06-28T19:54:07.088Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/ca20a0e0de49837e6337603a91ab77556aa27033ac5b975615d98698cfb3/regex-2026.6.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ecd1638b1c2db1f2d01c182a4b0d3e2e88b0e99910320a745c1727ee3638ddab", size = 289623, upload-time = "2026-06-28T19:54:08.762Z" }, + { url = "https://files.pythonhosted.org/packages/50/11/c013422a7e2c59946df8ac93e792a4922c98287f2a2181341603c78a5d98/regex-2026.6.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4303ebe16b74eeb3fe2715745023266fea92fd44a23f3e7bb2fb48c7a7bbc195", size = 796756, upload-time = "2026-06-28T19:54:10.616Z" }, + { url = "https://files.pythonhosted.org/packages/b0/95/1309645a0e1ee6fb91d954501da57a0b33d50ad2a9acb313702851a7054e/regex-2026.6.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56b856b70b96c381d837f609eee442a1bd320cd2159f5c294b679552fb1a7eaf", size = 865465, upload-time = "2026-06-28T19:54:12.742Z" }, + { url = "https://files.pythonhosted.org/packages/20/06/491802db47c6f5e2904ffa2518ad3ac27fe6bbf5a66d73210a95cc080d47/regex-2026.6.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f74675ab76ab1d005ffba4dee308e53e89efc22be6e9f9fae5b539a3f81bdff2", size = 912350, upload-time = "2026-06-28T19:54:14.508Z" }, + { url = "https://files.pythonhosted.org/packages/5e/60/3ba57840bcc7e2367090360de0c15a5ba6ad22be89314251105f2e943f43/regex-2026.6.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90581684565a93f7258af1e5d3f41ef20d7d7c61f2a428183a342bcb65485e38", size = 801261, upload-time = "2026-06-28T19:54:16.432Z" }, + { url = "https://files.pythonhosted.org/packages/eb/27/af1eb74e9a78c782b3e450b611a595e44906da8a5107e1227f4a7fd0480b/regex-2026.6.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:28f9e6c28f9b90f6f784595a33240a57e181e61b6ee3dc259b25c61e356d1aa3", size = 777072, upload-time = "2026-06-28T19:54:18.128Z" }, + { url = "https://files.pythonhosted.org/packages/20/18/fdd4c883a39e3ed00d669062af1135809bfd3281bf528150849fbd68825b/regex-2026.6.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:378a71d861fc7c8806b04ac5b133d53c0e774f92f5d9663a539872d3fa2b0417", size = 785119, upload-time = "2026-06-28T19:54:20.314Z" }, + { url = "https://files.pythonhosted.org/packages/1c/79/0aabe34b8482dcadf64355f70f96e22eba5ec6c1efb33563f89654f4061c/regex-2026.6.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4cc199874ecd6267a49b111052250825bfe19b5101b23b2ba80f54efa3e0994e", size = 860118, upload-time = "2026-06-28T19:54:22.368Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2c/c973323306a27c9db7d160e9584eb7e0ece2a96224ccb0d39060558b31f9/regex-2026.6.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b916a10431494ef4b4d62c6c89cab6426af7873125b8cd6c15811bf5fc58eec8", size = 765786, upload-time = "2026-06-28T19:54:24.265Z" }, + { url = "https://files.pythonhosted.org/packages/e3/df/9ca3e378e352242a4cb45573a5e9162c3ee791507702a23966fa559e36b5/regex-2026.6.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e27727fba075f1e4409416d2f537d4c30fc11f012ea507f7bd74d3e19ecb57a", size = 852120, upload-time = "2026-06-28T19:54:25.972Z" }, + { url = "https://files.pythonhosted.org/packages/a2/3e/3e31e255c4971f53cbce6306b5e3c76cbd3735a54f419bb3b2f194e9f68c/regex-2026.6.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:700fc6a7844bb2c4149292ac79d1df8841a00acd4d45cd32c1ebc7bcc1fd0da8", size = 789503, upload-time = "2026-06-28T19:54:27.678Z" }, + { url = "https://files.pythonhosted.org/packages/72/01/d36561c21c3033d7eeb31d51b491916817de7861acefccc5fc9db8a5037c/regex-2026.6.28-cp312-cp312-win32.whl", hash = "sha256:03376d60b6a11aecb88a79fa2be06b40faa01c6693bc31ef69435cd4818b9463", size = 267109, upload-time = "2026-06-28T19:54:29.316Z" }, + { url = "https://files.pythonhosted.org/packages/a0/59/bbbb0591f38b18c65977cd65ce64749eba1c1996c99ac04e900fc30c0dcb/regex-2026.6.28-cp312-cp312-win_amd64.whl", hash = "sha256:fbd2ded482bf99e6651992bbfcde460272724d4bbc49ef3d6b46d9312867ec84", size = 277711, upload-time = "2026-06-28T19:54:31.143Z" }, + { url = "https://files.pythonhosted.org/packages/86/06/be4f6b337d773ae5739a1bc238f97c16926e72017243735853c030f4c628/regex-2026.6.28-cp312-cp312-win_arm64.whl", hash = "sha256:37294d3d7ddb64c7e89184b2894e0f8f0a19c514bc59513d71fe692c3a8d5fc6", size = 277022, upload-time = "2026-06-28T19:54:32.97Z" }, + { url = "https://files.pythonhosted.org/packages/b6/53/d5c1b3cc0b5a0c985563ad6fac93d73ff2b300cb84342d89f044625d6bc7/regex-2026.6.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b295a83426e0e44e9e60fde99789e181bd26788a1890ae7fe2a24c69bb6246ca", size = 490329, upload-time = "2026-06-28T19:54:35.775Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9f/0c3503e819e91ca0e7a901a8e989ebf840ac7c7aea20b1fc7f31b6759f77/regex-2026.6.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c31665c0deb5c111557a1cac8c27bd5629e2f9e7fd5058900a03576c33b601c", size = 292039, upload-time = "2026-06-28T19:54:37.977Z" }, + { url = "https://files.pythonhosted.org/packages/bb/7f/cd004e13fcad23b3794a82307dfd222e6365eb7f598bd3caab148a830bff/regex-2026.6.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6bf295f2c59de77d1ea7de053607ae4dc9ceb3d57bbb6c7ec51ef4acc4ccff94", size = 289488, upload-time = "2026-06-28T19:54:39.545Z" }, + { url = "https://files.pythonhosted.org/packages/73/4c/293fb34586fbcdc47eac436069e9c11f71fae5dadfd4889b475d7d2e5f7a/regex-2026.6.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17c077586770f67e05bbffeba07fbee6b2b22244f4d4caf8d94e59d574befe04", size = 796772, upload-time = "2026-06-28T19:54:41.347Z" }, + { url = "https://files.pythonhosted.org/packages/92/fa/c0cd1a90b7d12d9dc155cfc8bdea8df9720988ea5b07e8fa1eccbd0ab2dd/regex-2026.6.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e6cb5a61486f9062397d2e189573b39d38ecfaed698fd9fb6e2756a8ebb8762", size = 865467, upload-time = "2026-06-28T19:54:43.485Z" }, + { url = "https://files.pythonhosted.org/packages/4e/db/0b479973046d005a1eaea299d5d536aeecb9488a16d9cbb8286338102e2d/regex-2026.6.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e86e91a2664f44c3a4e363a7d78fb17c27d5046882e30ea5a877f5e89b28d2ba", size = 912345, upload-time = "2026-06-28T19:54:46.091Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5b/d65adfbd02f32212431bca1f06d1e2eb763a20b12978b454bafaf23dacb7/regex-2026.6.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4dfd1331c49233998d84fc5f1f4436cf7a435a7655f6cf0f490229bb5c7254e5", size = 801291, upload-time = "2026-06-28T19:54:48.3Z" }, + { url = "https://files.pythonhosted.org/packages/fc/09/2103686defaf9a0a31c1663782359d5b45f42524c64cca681f5481e44a5e/regex-2026.6.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cadea12805a1bce0b091c302b814207be26fb60a9c0e7f9ad2f9e21790a429fe", size = 777106, upload-time = "2026-06-28T19:54:50.326Z" }, + { url = "https://files.pythonhosted.org/packages/85/5a/b57593c0aa23ed269ec332fbcf07852abcb6b746e811d9464e0d09b4e25f/regex-2026.6.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5f2c1682b67ad5d2376498f2a5a2a8f782fa2e4a06d0465b5e357799806e8a20", size = 785175, upload-time = "2026-06-28T19:54:52.172Z" }, + { url = "https://files.pythonhosted.org/packages/79/59/c36e756ad29bf14d7b6c6d7138952476b21f6160286cedb98ac13481c993/regex-2026.6.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:64e142eb55e84868087da1375d7c36ff97d55010951849f515322a91d5fef1b4", size = 860186, upload-time = "2026-06-28T19:54:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/61/66/49808aea0da9649c300139360708fb91b7144be1f962fcebf96755fde948/regex-2026.6.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:abb4daabe7be63273787a62dfd6164dadf8f7a63fbec3d2730e5e5e7126d858c", size = 765754, upload-time = "2026-06-28T19:54:56.04Z" }, + { url = "https://files.pythonhosted.org/packages/be/c5/52bbd436cf2200decdf48825fa38363eaaeebb77011ea9928a1ef9e0b9f2/regex-2026.6.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec2b2ad00ab8c16a2798cc8db80c53c4d5b8b3a2441f6cbaef06625f5ca25854", size = 852085, upload-time = "2026-06-28T19:54:57.988Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c3/0390b66e3019497143fe768b3ba567b64d8b24f3812d09506deb86f4a0f0/regex-2026.6.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bfc9677982c914d9085b8e1c3b3ae6e88f139fb56531c2416d6c8f338093c22b", size = 789600, upload-time = "2026-06-28T19:54:59.977Z" }, + { url = "https://files.pythonhosted.org/packages/88/fd/ab5b03653a244975069fed93d73f4f5f7484c03a84cedb238292510d7182/regex-2026.6.28-cp313-cp313-win32.whl", hash = "sha256:bf54bc693fc4e0530e666ba5ec4bcba14dbe8f66b7cfc15c27317d1a6e40b9a5", size = 267088, upload-time = "2026-06-28T19:55:02.159Z" }, + { url = "https://files.pythonhosted.org/packages/68/55/21022f7d3143210ae8d4ff905c45306237b657375cc0b97883f49db3d423/regex-2026.6.28-cp313-cp313-win_amd64.whl", hash = "sha256:e128feaf65bf3d9eb91bec92322a8f7e4835e9c798f3e9ea4b69f4def85620e3", size = 277680, upload-time = "2026-06-28T19:55:04.185Z" }, + { url = "https://files.pythonhosted.org/packages/b6/99/7f664804f1aef924542b0b233996b78b3e4d0a52d9951358aac99f129f51/regex-2026.6.28-cp313-cp313-win_arm64.whl", hash = "sha256:695873e0ea8d3815ea9e92e2c68faf039cc450e2c0a62a31afe2049eb11be767", size = 277017, upload-time = "2026-06-28T19:55:06.29Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e1/9eb83518e159d719fd681c4932dc2aaff855ce72451e1d05d69466f25a96/regex-2026.6.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:189dbf9fc4252d9f1352bf4bd1bef885edb6cc4b7341df202a65f821aaa3891c", size = 494195, upload-time = "2026-06-28T19:55:08.292Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e2/e259c5f2f7be269d0e2fb54275c1fa6a13fb47019f389c3f3ae457447825/regex-2026.6.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9277a4c6503390aa39cb4483b87ec0384faee0850a23b5cea33d008b5d8d83f1", size = 293976, upload-time = "2026-06-28T19:55:10.014Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4e/9bdf444014d22b045d0c82ca114fac7e07a597b5b5331b7c4ce6328426e2/regex-2026.6.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17eddca4e8ea9af0b5739314776cdf0172a49731ab61f2e1ea66e066ddd46c97", size = 292340, upload-time = "2026-06-28T19:55:11.88Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3a/f49b11e59cbfe187ace0053a460bd72a0169b8cd52e7db9421a074ce7a43/regex-2026.6.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4466b8641e00c697aab5a73150150d2b2ea96b131c595691f42031abafd9f4d", size = 811704, upload-time = "2026-06-28T19:55:13.612Z" }, + { url = "https://files.pythonhosted.org/packages/2f/fb/ad04c39e149bf8b6cf357df5fff78341733ec366780a00c803a36735818c/regex-2026.6.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9cfcd4b0bdcf768c498415c170d1ed2a25a99bf0b65fa253bbd02f68ceba6475", size = 871157, upload-time = "2026-06-28T19:55:15.797Z" }, + { url = "https://files.pythonhosted.org/packages/7f/64/0e5ba31c11eb8ef7aac19a690c1211fc9aa9990caf09565785ebb0081b9a/regex-2026.6.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:80c7adf1ef647f6b1e8aa2ca280e517174cd08bdf7a2e412cdfb68bd6a0917cb", size = 917287, upload-time = "2026-06-28T19:55:18.692Z" }, + { url = "https://files.pythonhosted.org/packages/11/75/6b78df2b858c2fcbbc4858fdc3f2975cf2703be374b2842db7d2c32591a7/regex-2026.6.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a043f5770e82283a22aed4cefef1a4e0f9dd8fd7184cb6ce0ad2e579e2134a9e", size = 816333, upload-time = "2026-06-28T19:55:20.973Z" }, + { url = "https://files.pythonhosted.org/packages/b4/01/ecfe665a3694d5eda9f3ec686c856438ada0943947b6005e90556a1e2cdf/regex-2026.6.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3bd630a8dba06b55254ea5ee862194edab52ec783100d2ef1cd15a9c512fee27", size = 785518, upload-time = "2026-06-28T19:55:23.003Z" }, + { url = "https://files.pythonhosted.org/packages/b4/0a/88f9cd88ff1e82881605c4ffd62d77ee67d051232cfe6f8e9a64b86cf0e8/regex-2026.6.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b77207e3cee13086f1906a6a2a12b41244c577e8ad9370d4b35ae1d548d354f3", size = 801371, upload-time = "2026-06-28T19:55:24.888Z" }, + { url = "https://files.pythonhosted.org/packages/a8/97/601483732f93275482ceb9fed57813dfed7c47d3a019db6ec4a3bb6e23e0/regex-2026.6.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:6de82c268e5d101ee9e3ffd869924aa9a371e3a21e752cf4fa17b6ce50d219f7", size = 866517, upload-time = "2026-06-28T19:55:27.232Z" }, + { url = "https://files.pythonhosted.org/packages/81/ed/385c2a0351b994a693453c1d1a6e9af9eb35db3c9460d76b5078acd70c62/regex-2026.6.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b15859e3908544fb99cf47341dcf0bfd089147d258c4c4d8a29e5b087f8085cb", size = 772834, upload-time = "2026-06-28T19:55:29.154Z" }, + { url = "https://files.pythonhosted.org/packages/06/bc/bbf4a5b3b29770d7f307d3c28b5b1bca0105b0cb424be0a4eb1339bc92cf/regex-2026.6.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c91487a917edd48a1ea646fdf60d7936d304f0e686fa7ea8326e47efca51d816", size = 856606, upload-time = "2026-06-28T19:55:32.186Z" }, + { url = "https://files.pythonhosted.org/packages/28/26/51d74fff82f682819979249f8d700267108ba5dc4eb284b0e11b9c85e4b3/regex-2026.6.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4ac65f3e3a99fd8f3a4a74e7a6610acd1ce9dfe9b8a03d346a4922380d68aeb", size = 803475, upload-time = "2026-06-28T19:55:34.328Z" }, + { url = "https://files.pythonhosted.org/packages/7c/3e/6be10cefdc813533fe604dbf5d3c77d2638e7ee658b2749ebadc113b6b2e/regex-2026.6.28-cp313-cp313t-win32.whl", hash = "sha256:3f6316f258bc7e6c9c2acbe9954947bbd397a81be3742a637a555f1855d6618d", size = 269126, upload-time = "2026-06-28T19:55:36.565Z" }, + { url = "https://files.pythonhosted.org/packages/3c/3c/32cda905ea1a6eeeb798291c294d8ec66ee0efe0cdba28b061e248b1d396/regex-2026.6.28-cp313-cp313t-win_amd64.whl", hash = "sha256:1484bdd6fba28422df9b5ebb04055b2e1b680e8e4f08490bb21ff0f3cc50d0ab", size = 279961, upload-time = "2026-06-28T19:55:38.456Z" }, + { url = "https://files.pythonhosted.org/packages/ea/b9/69f4e5cd6fbe0bb420cb2dbae441ca118f2495bdda522a74da75aa9829e7/regex-2026.6.28-cp313-cp313t-win_arm64.whl", hash = "sha256:3f15020f0b69cafe57baa067ff65b29acef68ff6b1670a53bef1ca11d708e02d", size = 279266, upload-time = "2026-06-28T19:55:40.62Z" }, + { url = "https://files.pythonhosted.org/packages/3b/fb/fad3b810a5bb1e09b9e5d6913fc6ba88cab738fdf283196827a3c59a4c10/regex-2026.6.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:f7c032b0c8a73739ff8ff1aaf30c281fa19c17bf7f1543256c8507390db7807c", size = 490407, upload-time = "2026-06-28T19:55:42.724Z" }, + { url = "https://files.pythonhosted.org/packages/d6/52/b8c79d12276d93e90e707e939b396034c04980caf1235312ef790f8e11fc/regex-2026.6.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f6710f512c57b84f127a23d0f59560a03b64136eff419ae1be5ab557577fe5e3", size = 291988, upload-time = "2026-06-28T19:55:44.549Z" }, + { url = "https://files.pythonhosted.org/packages/23/d2/6a911f18279daa8d7bb8b20d771ddb6ef31fabd35f5921f9d3ba21640e80/regex-2026.6.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c0013958f427bd82509a186b9ff206d66cb8d60a81fc797a4c717afd18c5b0ba", size = 289704, upload-time = "2026-06-28T19:55:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/fd/22/ad1955c47c669291a05804d53d7071cc0732dfdf166857be38003cedc2d1/regex-2026.6.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f06cdcd6421f8e194ad312ea608020381250df9b8a57661c1b57e9e5273878", size = 797017, upload-time = "2026-06-28T19:55:48.166Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/a83159ff8703ab4d0c2cf99e76ebf289b7b4a501623241d09f88f3614f80/regex-2026.6.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec9689392f7494ff4e3f8e7e8522f9158f11023f337eaaf04a64542fc45bbf26", size = 866112, upload-time = "2026-06-28T19:55:51.047Z" }, + { url = "https://files.pythonhosted.org/packages/b9/09/7bff2d6dbbd77421b3274aa51db1c887381cbc5b6eda93598c3e882ea345/regex-2026.6.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aa084684e6d2078bf6139e374d1fc2af5ddc1ac7122759a2db716d68169f6fd0", size = 911554, upload-time = "2026-06-28T19:55:53.707Z" }, + { url = "https://files.pythonhosted.org/packages/29/44/ae59c3826e7ba492e56795cdf74ea2a7b5b7c5ea116afb79ee4956a5dff1/regex-2026.6.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:40455e6840dc4e96a6fe50f4cedc957de2752c954d91e789812be55d49be199a", size = 800665, upload-time = "2026-06-28T19:55:55.875Z" }, + { url = "https://files.pythonhosted.org/packages/d6/19/6fd033d2ab00f35d445aaeaf3307c1e721424dcbfd48f6f65c857cb939cf/regex-2026.6.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:530b5c223b9ca5dd8370ac502e080aee0e4ded32be987c6564b425fb5523d581", size = 777243, upload-time = "2026-06-28T19:55:57.909Z" }, + { url = "https://files.pythonhosted.org/packages/4e/9d/99730f26df4938049ab1e652ca75e967b4c6739444e18d9707bfdb8af20c/regex-2026.6.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e0ed273ecd1a89be84466c1749bfe58609cc2a32b5d5e05006c4625ba96411b", size = 785784, upload-time = "2026-06-28T19:56:00.072Z" }, + { url = "https://files.pythonhosted.org/packages/48/49/105cd57162f5fc5c04cc917a1388a060cf8427e5c14353cd9044660fbf4d/regex-2026.6.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0ab0d5344311fc8e8667078942056c3b9c9b4a4b1cc99f2eb8a5af54554f4acc", size = 860914, upload-time = "2026-06-28T19:56:02.017Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/788245a95b69018f58bff2f4fd27d007cacaea088cdb390979743f1b2571/regex-2026.6.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:eacb79625323d9f7e7925366b917f492b8356fad58f5dc4fa12ff8c21d8f4ca9", size = 765915, upload-time = "2026-06-28T19:56:05.021Z" }, + { url = "https://files.pythonhosted.org/packages/ca/01/292065a39a004b05e67a337b18213670a7cb919d6856ac2d7df7f1a10dbb/regex-2026.6.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:20f4d87702702aa1d572721e146f301660c50eef6fd6cb596e48a22b0ace17db", size = 851404, upload-time = "2026-06-28T19:56:07.251Z" }, + { url = "https://files.pythonhosted.org/packages/98/9e/a93d865db0e13483ae1a01d81e2ce16d4a7fe2f9b9fe4aac4cc08590b136/regex-2026.6.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e693940a3b9e6d6e4dc2a54ecaa74b74934f77af1ef95f518a74261ef7cc1bc", size = 789373, upload-time = "2026-06-28T19:56:09.894Z" }, + { url = "https://files.pythonhosted.org/packages/82/0c/38b1685ad4017d78efbc8fa7dbbf96d8113b53750c8aa2d3609defd46605/regex-2026.6.28-cp314-cp314-win32.whl", hash = "sha256:234a51e20ebc18ab83b2c0600cf28f2e884560a0e00f743878f0b7d8e7c4cf03", size = 272496, upload-time = "2026-06-28T19:56:11.83Z" }, + { url = "https://files.pythonhosted.org/packages/55/50/e19f261ff9ba9b50722a529e09b1743ecf65eb348be99d0fd2cd7fcede1c/regex-2026.6.28-cp314-cp314-win_amd64.whl", hash = "sha256:7b15c437bc4604f03ceb3f8d37eae2f8930e320e1bc556b259848c639d9eec1a", size = 280754, upload-time = "2026-06-28T19:56:13.758Z" }, + { url = "https://files.pythonhosted.org/packages/36/b8/c9e68f3a9e33be73f20990b2c065b144ff2d0aa242608a950d8c4f3b56e8/regex-2026.6.28-cp314-cp314-win_arm64.whl", hash = "sha256:c6e6f790d01380a74ad564f216c533b86504afb61bf66f2b2e11e7f1a3e287a7", size = 280979, upload-time = "2026-06-28T19:56:15.928Z" }, + { url = "https://files.pythonhosted.org/packages/03/e6/21c425a37880c650d007c4171c6a80325446d830d85f5fbf335e7205b1e7/regex-2026.6.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3527a72adcbe9e3600f1553b497d397c1a371d227580d41d96c3c5964109b65c", size = 494282, upload-time = "2026-06-28T19:56:18.049Z" }, + { url = "https://files.pythonhosted.org/packages/07/50/6647a7ccf5ffff995ba955a0b7d766440f4e58ce1666549c8ee998f2b972/regex-2026.6.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a644f6408692812f5ead82519eed680e08d5d546fddbd9f7d9514e3c73899aa5", size = 293977, upload-time = "2026-06-28T19:56:20.145Z" }, + { url = "https://files.pythonhosted.org/packages/8c/dc/a3e141a4eaf125e50f63105570c01fa477c06ac5259dcfa95e9b90760e84/regex-2026.6.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8e2fae6bb883648346f84db270dc9aafc29d8e895f62b88a75ccc83b09519820", size = 292432, upload-time = "2026-06-28T19:56:22.345Z" }, + { url = "https://files.pythonhosted.org/packages/35/ee/2ac1a6b9f167f8ff69f5a789938cc103b60cff41b24a6990daced8b88e34/regex-2026.6.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:debe623e09cee97ef9404575e936c610aac9bb08358c5099aaef14644a6871f2", size = 811877, upload-time = "2026-06-28T19:56:25.056Z" }, + { url = "https://files.pythonhosted.org/packages/df/7b/9a5505ee92180bcae300b1018b9ff3d3c19962436e66f2505f255e9fde35/regex-2026.6.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc579c91fb4605773483a8d940b136bcc5b854fff44fa14a1572a038f46563f1", size = 871212, upload-time = "2026-06-28T19:56:27.352Z" }, + { url = "https://files.pythonhosted.org/packages/24/4d/d61a702a9f9d1bd29b22cbef1aed6d477baa961232a7eb4d91b7775b0b3e/regex-2026.6.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7c42be203d84ecf7d487ff23f8a61ef0eb0534fa0fc317a2fce8c065d20618f", size = 917507, upload-time = "2026-06-28T19:56:29.762Z" }, + { url = "https://files.pythonhosted.org/packages/d4/60/1308066f5966b65fbb6905b99ba37e9f1cd753dd0ac08485f8257334ee92/regex-2026.6.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8184b4e2fdaf9cdfe77e38f15a4d9dc149168c9c29eb0ea17c5481d3bb80546", size = 816389, upload-time = "2026-06-28T19:56:32.043Z" }, + { url = "https://files.pythonhosted.org/packages/bd/5c/57ce2cb8d714ee0b7f11c7ee4cfe2af66df2b90f147feadcb538609a3a02/regex-2026.6.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:697f103104f5872d64078d8eeac59979960be8ee76115a2d3f31096312e2a400", size = 785890, upload-time = "2026-06-28T19:56:34.492Z" }, + { url = "https://files.pythonhosted.org/packages/ff/fd/1d5350d3a8a327bff0fccacb911732baf7b5b6f5529c0e3fa602a23e7dad/regex-2026.6.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:714d2b1aa29beef0ddfcdc72ad0771c05326551a8bb0680b0ddf74bfaad87387", size = 801451, upload-time = "2026-06-28T19:56:36.749Z" }, + { url = "https://files.pythonhosted.org/packages/f3/79/3c9e4f8a0306e030ad5a43bbbc01625fb28d58a813bc52d42fd1cc63fb2e/regex-2026.6.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0f09f62e450cc2f113018cc8412aeea3a120a04e1ca7e801a0d441583f9a3b06", size = 866504, upload-time = "2026-06-28T19:56:38.994Z" }, + { url = "https://files.pythonhosted.org/packages/65/12/f747de475b54f4709efb24dd0fbc8467c64cec91f5db0d047b079646ee78/regex-2026.6.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:731ea12d5aeb2577eaef2393d6428b995f76eb35f68a89e03e15a97719d1de19", size = 773047, upload-time = "2026-06-28T19:56:41.061Z" }, + { url = "https://files.pythonhosted.org/packages/58/3c/f02f860e0500c1b2d61a79dec7e214b37fb9656281dcddc92397edf96678/regex-2026.6.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:51e952c8783eabd4706d0f63922f219bcfc1bef9b8cb35941c0d1a0396578858", size = 856665, upload-time = "2026-06-28T19:56:43.466Z" }, + { url = "https://files.pythonhosted.org/packages/4d/6c/28b3fa222513484be9dee26b7222bda109056c43ea28aa2314262ca48816/regex-2026.6.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43248fe4c0ab8fbb223588a0795b11268940072c97bba30ea8f9b49d8cdfde34", size = 803573, upload-time = "2026-06-28T19:56:45.791Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/8f86cf1a1fd85c5ab0c503c9fe4607ad4ad48978b2d8b435d94465e134c7/regex-2026.6.28-cp314-cp314t-win32.whl", hash = "sha256:fc1eddc25ad23c0f1344ab280d961ac595ead48292d7c779497975942373f493", size = 274515, upload-time = "2026-06-28T19:56:47.948Z" }, + { url = "https://files.pythonhosted.org/packages/0f/de/f8613c03b36786ddef2c930d28f9bcae861fcd541cc9203a870956cf1e83/regex-2026.6.28-cp314-cp314t-win_amd64.whl", hash = "sha256:ede8d8e53b6dde0a50f7eca902f0af76d87ab02a55aba7542da68ae3e5dfe83d", size = 283650, upload-time = "2026-06-28T19:56:50.614Z" }, + { url = "https://files.pythonhosted.org/packages/4d/f3/f5ec86839bbabe33b6dee649b62ff9a445d43de6b0ad780cf6b83c56f61e/regex-2026.6.28-cp314-cp314t-win_arm64.whl", hash = "sha256:4da6f6a72f8700b97a1a765e837fb7d5750bfd9f13acea7bae498f573e3a70a8", size = 283338, upload-time = "2026-06-28T19:56:52.879Z" }, ] [[package]] @@ -1147,9 +1147,9 @@ dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680 } +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654 }, + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, ] [[package]] @@ -1159,140 +1159,140 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "eth-utils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1b/2d/439b0728a92964a04d9c88ea1ca9ebb128893fbbd5834faa31f987f2fd4c/rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9", size = 33429 } +sdist = { url = "https://files.pythonhosted.org/packages/1b/2d/439b0728a92964a04d9c88ea1ca9ebb128893fbbd5834faa31f987f2fd4c/rlp-4.1.0.tar.gz", hash = "sha256:be07564270a96f3e225e2c107db263de96b5bc1f27722d2855bd3459a08e95a9", size = 33429, upload-time = "2025-02-04T22:05:59.089Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/fb/e4c0ced9893b84ac95b7181d69a9786ce5879aeb3bbbcbba80a164f85d6a/rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f", size = 19973 }, + { url = "https://files.pythonhosted.org/packages/99/fb/e4c0ced9893b84ac95b7181d69a9786ce5879aeb3bbbcbba80a164f85d6a/rlp-4.1.0-py3-none-any.whl", hash = "sha256:8eca394c579bad34ee0b937aecb96a57052ff3716e19c7a578883e767bc5da6f", size = 19973, upload-time = "2025-02-04T22:05:57.05Z" }, ] [[package]] name = "ruff" version = "0.15.20" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489 } +sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665 }, - { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649 }, - { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638 }, - { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227 }, - { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882 }, - { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808 }, - { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094 }, - { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176 }, - { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767 }, - { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132 }, - { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828 }, - { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418 }, - { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770 }, - { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698 }, - { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322 }, - { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274 }, - { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498 }, + { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" }, + { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" }, + { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" }, + { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" }, + { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" }, ] [[package]] name = "shellingham" version = "1.5.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, ] [[package]] name = "sortedcontainers" version = "2.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, ] [[package]] name = "tomli" version = "2.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543 } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704 }, - { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454 }, - { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561 }, - { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824 }, - { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227 }, - { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859 }, - { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204 }, - { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084 }, - { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285 }, - { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924 }, - { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018 }, - { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948 }, - { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341 }, - { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159 }, - { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290 }, - { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141 }, - { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847 }, - { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088 }, - { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866 }, - { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887 }, - { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704 }, - { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628 }, - { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180 }, - { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674 }, - { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976 }, - { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755 }, - { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265 }, - { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726 }, - { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859 }, - { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713 }, - { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084 }, - { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973 }, - { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223 }, - { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973 }, - { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082 }, - { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490 }, - { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263 }, - { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736 }, - { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717 }, - { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461 }, - { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855 }, - { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144 }, - { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683 }, - { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196 }, - { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393 }, - { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583 }, + { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" }, + { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" }, + { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" }, + { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" }, + { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" }, + { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" }, + { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, ] [[package]] name = "toolz" version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613 } +sdist = { url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613, upload-time = "2025-10-17T04:03:21.661Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093 }, + { url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093, upload-time = "2025-10-17T04:03:20.435Z" }, ] [[package]] name = "ty" version = "0.0.56" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/55/07/fb29aea5235b0aa8ecfc4d1cc6ddf9fba8b863d67d96c6d345694d644c43/ty-0.0.56.tar.gz", hash = "sha256:84d114dc3796361c0fc72945016eabd74d46b9ee64f198cb0e485719704681e5", size = 6050123 } +sdist = { url = "https://files.pythonhosted.org/packages/55/07/fb29aea5235b0aa8ecfc4d1cc6ddf9fba8b863d67d96c6d345694d644c43/ty-0.0.56.tar.gz", hash = "sha256:84d114dc3796361c0fc72945016eabd74d46b9ee64f198cb0e485719704681e5", size = 6050123, upload-time = "2026-07-01T16:44:56.036Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/48/bce79e7ca5c1cc529d3e0d37ddd1121aea4b68a4f749974ad1cc77161871/ty-0.0.56-py3-none-linux_armv6l.whl", hash = "sha256:186d4a53e15747c947e1ec3d7eec8e345d8e40a1ca10e634c585db52497e87dd", size = 11643066 }, - { url = "https://files.pythonhosted.org/packages/80/d1/22555d8a1d719661f10050f3865d877bbf497da908961c75fe22217dd18a/ty-0.0.56-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aae1a980fd9535da0469b7ba2b2e1b54a907743a5e0f442dd57eee9f5bfd034c", size = 11407487 }, - { url = "https://files.pythonhosted.org/packages/cf/2d/b3b7a74ce8bc59ef48843ad80179bb0d9598bbd6cfc0d11d519bdf6b1352/ty-0.0.56-py3-none-macosx_11_0_arm64.whl", hash = "sha256:afd3058c0a6c5f241e814734f133008c93ee805f61c9cf4ce7412b8822b5d9ad", size = 10962270 }, - { url = "https://files.pythonhosted.org/packages/64/ac/6c2fd7de0304a8a7218a756af74f7e62a5e8540fdb175e0a869e51042345/ty-0.0.56-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058b52f7a823ac13aae3cae30809dd6b5145794b64d8478f9ef38c75d79b4483", size = 11471406 }, - { url = "https://files.pythonhosted.org/packages/50/b6/11d861156861c03c7726b74558f9a0e0092661aff83a4fda1279df28c425/ty-0.0.56-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c66e00c1522add1f2bbdd2e45828c953b35c306b7bef03ec9169c75a63699a0", size = 11445612 }, - { url = "https://files.pythonhosted.org/packages/fb/ba/09df108582090f3c0770ec4bc8675affed60248f6793a78d909be16211d9/ty-0.0.56-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40903d71c669a30691b5a5d5728056c7877a1bd6be4f233a38883a8b28cf34d7", size = 12093889 }, - { url = "https://files.pythonhosted.org/packages/d7/f7/dbb4b4ccb69cd64c209ae55b1ab788ace8222c2bc1f6845be9e7cbedbf25/ty-0.0.56-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63fe3947fe0c46c69a7d950e6832ee70a9ec17321fefbff3d2e3c20baf9e5bd0", size = 12666337 }, - { url = "https://files.pythonhosted.org/packages/86/e9/73f903fe4a3d9ea02f26f57c1eb07e3b1029ec92b0e8c2364718893440e3/ty-0.0.56-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71a0c1a72f9854532e710e119b6871ffe4542c8a65146f1f65dcd78fecd885b4", size = 12280247 }, - { url = "https://files.pythonhosted.org/packages/d6/90/cebd222495832f1a00dcd321ba25f3cab804221a4991b992c2178bec68ee/ty-0.0.56-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70d1665596494e24d8ebd198438872b5a56ec3cae5f2bcf6c673be797acc4e3c", size = 11991107 }, - { url = "https://files.pythonhosted.org/packages/b7/07/8f7337a07250f42d975cdb6decf47fc5b421e6c7da5e3e7be1e85f63a7e5/ty-0.0.56-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:778f99e51558afc1dbbe48ee38ab6aae7b31390ed8c1a1ef1499b295e9f1e82f", size = 12298970 }, - { url = "https://files.pythonhosted.org/packages/3c/b9/a52cd59034a48f5f18c6b155cc2cc36861d874b6d0af204b12c898024c3d/ty-0.0.56-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:867bc5708e0066bb4ff6c7db524bd5deea2676c62bfe71d3303138b3be850af0", size = 11425683 }, - { url = "https://files.pythonhosted.org/packages/1d/2e/48e42d33357d52eefb695c0c3fcfc96879b73668a7447d1d1e0ad774fedc/ty-0.0.56-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6012f4189c928edb330a37deb9930f982380bd4aa7c4b8e0428eec9651c7551", size = 11469258 }, - { url = "https://files.pythonhosted.org/packages/d5/01/ad1b4138be1e3fa97863af3925aa2134f17a593240c35dc38c3429fb5ad1/ty-0.0.56-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8ee83de1a7ff4cc32837ec06134ce391d441bc5b35ecd8d3cfe053f120f3e4c1", size = 11758736 }, - { url = "https://files.pythonhosted.org/packages/09/34/9d81967ff240eaa57e9249728ef7b7790747cf6d3c9a98ec86b2cfdcc8ee/ty-0.0.56-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:62619b3b0e2c6248ef30d3f0e2f2217ae9893040585be07f32324242f197cd6f", size = 12100242 }, - { url = "https://files.pythonhosted.org/packages/c3/36/f51d4666d2de6cf33c1f3a1fcc4bb6b70b197dd6ceaa491eef71d78fe8e8/ty-0.0.56-py3-none-win32.whl", hash = "sha256:b30687bb5cd9729d34c889a289edf32770388d9bb05243e534e723fb45e0381b", size = 11093759 }, - { url = "https://files.pythonhosted.org/packages/5e/b4/8fb5d4acfa4afb152245b20fa263069a7547bd1f8e4bfca4eda280c897d7/ty-0.0.56-py3-none-win_amd64.whl", hash = "sha256:ad4c8c47b6f4e3f9ed3fc0b1a5d650088d229e17dd8f63c1826d6bbe94cc3235", size = 12100327 }, - { url = "https://files.pythonhosted.org/packages/b8/fc/6a183e71edde90d0c35c2303f23f7a45b6891d1a2c45daf7b8f869831e19/ty-0.0.56-py3-none-win_arm64.whl", hash = "sha256:57538f273d444a5f1293fa7860e967178afe3917611fc5eff16b64e1204fe0d6", size = 11538780 }, + { url = "https://files.pythonhosted.org/packages/dc/48/bce79e7ca5c1cc529d3e0d37ddd1121aea4b68a4f749974ad1cc77161871/ty-0.0.56-py3-none-linux_armv6l.whl", hash = "sha256:186d4a53e15747c947e1ec3d7eec8e345d8e40a1ca10e634c585db52497e87dd", size = 11643066, upload-time = "2026-07-01T16:44:18.374Z" }, + { url = "https://files.pythonhosted.org/packages/80/d1/22555d8a1d719661f10050f3865d877bbf497da908961c75fe22217dd18a/ty-0.0.56-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aae1a980fd9535da0469b7ba2b2e1b54a907743a5e0f442dd57eee9f5bfd034c", size = 11407487, upload-time = "2026-07-01T16:44:20.956Z" }, + { url = "https://files.pythonhosted.org/packages/cf/2d/b3b7a74ce8bc59ef48843ad80179bb0d9598bbd6cfc0d11d519bdf6b1352/ty-0.0.56-py3-none-macosx_11_0_arm64.whl", hash = "sha256:afd3058c0a6c5f241e814734f133008c93ee805f61c9cf4ce7412b8822b5d9ad", size = 10962270, upload-time = "2026-07-01T16:44:22.959Z" }, + { url = "https://files.pythonhosted.org/packages/64/ac/6c2fd7de0304a8a7218a756af74f7e62a5e8540fdb175e0a869e51042345/ty-0.0.56-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058b52f7a823ac13aae3cae30809dd6b5145794b64d8478f9ef38c75d79b4483", size = 11471406, upload-time = "2026-07-01T16:44:25.327Z" }, + { url = "https://files.pythonhosted.org/packages/50/b6/11d861156861c03c7726b74558f9a0e0092661aff83a4fda1279df28c425/ty-0.0.56-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c66e00c1522add1f2bbdd2e45828c953b35c306b7bef03ec9169c75a63699a0", size = 11445612, upload-time = "2026-07-01T16:44:27.531Z" }, + { url = "https://files.pythonhosted.org/packages/fb/ba/09df108582090f3c0770ec4bc8675affed60248f6793a78d909be16211d9/ty-0.0.56-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40903d71c669a30691b5a5d5728056c7877a1bd6be4f233a38883a8b28cf34d7", size = 12093889, upload-time = "2026-07-01T16:44:29.548Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f7/dbb4b4ccb69cd64c209ae55b1ab788ace8222c2bc1f6845be9e7cbedbf25/ty-0.0.56-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63fe3947fe0c46c69a7d950e6832ee70a9ec17321fefbff3d2e3c20baf9e5bd0", size = 12666337, upload-time = "2026-07-01T16:44:31.586Z" }, + { url = "https://files.pythonhosted.org/packages/86/e9/73f903fe4a3d9ea02f26f57c1eb07e3b1029ec92b0e8c2364718893440e3/ty-0.0.56-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71a0c1a72f9854532e710e119b6871ffe4542c8a65146f1f65dcd78fecd885b4", size = 12280247, upload-time = "2026-07-01T16:44:33.637Z" }, + { url = "https://files.pythonhosted.org/packages/d6/90/cebd222495832f1a00dcd321ba25f3cab804221a4991b992c2178bec68ee/ty-0.0.56-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70d1665596494e24d8ebd198438872b5a56ec3cae5f2bcf6c673be797acc4e3c", size = 11991107, upload-time = "2026-07-01T16:44:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/b7/07/8f7337a07250f42d975cdb6decf47fc5b421e6c7da5e3e7be1e85f63a7e5/ty-0.0.56-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:778f99e51558afc1dbbe48ee38ab6aae7b31390ed8c1a1ef1499b295e9f1e82f", size = 12298970, upload-time = "2026-07-01T16:44:38.243Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b9/a52cd59034a48f5f18c6b155cc2cc36861d874b6d0af204b12c898024c3d/ty-0.0.56-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:867bc5708e0066bb4ff6c7db524bd5deea2676c62bfe71d3303138b3be850af0", size = 11425683, upload-time = "2026-07-01T16:44:40.473Z" }, + { url = "https://files.pythonhosted.org/packages/1d/2e/48e42d33357d52eefb695c0c3fcfc96879b73668a7447d1d1e0ad774fedc/ty-0.0.56-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6012f4189c928edb330a37deb9930f982380bd4aa7c4b8e0428eec9651c7551", size = 11469258, upload-time = "2026-07-01T16:44:42.513Z" }, + { url = "https://files.pythonhosted.org/packages/d5/01/ad1b4138be1e3fa97863af3925aa2134f17a593240c35dc38c3429fb5ad1/ty-0.0.56-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8ee83de1a7ff4cc32837ec06134ce391d441bc5b35ecd8d3cfe053f120f3e4c1", size = 11758736, upload-time = "2026-07-01T16:44:44.567Z" }, + { url = "https://files.pythonhosted.org/packages/09/34/9d81967ff240eaa57e9249728ef7b7790747cf6d3c9a98ec86b2cfdcc8ee/ty-0.0.56-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:62619b3b0e2c6248ef30d3f0e2f2217ae9893040585be07f32324242f197cd6f", size = 12100242, upload-time = "2026-07-01T16:44:46.584Z" }, + { url = "https://files.pythonhosted.org/packages/c3/36/f51d4666d2de6cf33c1f3a1fcc4bb6b70b197dd6ceaa491eef71d78fe8e8/ty-0.0.56-py3-none-win32.whl", hash = "sha256:b30687bb5cd9729d34c889a289edf32770388d9bb05243e534e723fb45e0381b", size = 11093759, upload-time = "2026-07-01T16:44:49.171Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b4/8fb5d4acfa4afb152245b20fa263069a7547bd1f8e4bfca4eda280c897d7/ty-0.0.56-py3-none-win_amd64.whl", hash = "sha256:ad4c8c47b6f4e3f9ed3fc0b1a5d650088d229e17dd8f63c1826d6bbe94cc3235", size = 12100327, upload-time = "2026-07-01T16:44:51.26Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fc/6a183e71edde90d0c35c2303f23f7a45b6891d1a2c45daf7b8f869831e19/ty-0.0.56-py3-none-win_arm64.whl", hash = "sha256:57538f273d444a5f1293fa7860e967178afe3917611fc5eff16b64e1204fe0d6", size = 11538780, upload-time = "2026-07-01T16:44:53.8Z" }, ] [[package]] @@ -1301,22 +1301,22 @@ version = "0.26.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7c/f7/68adc395201b20b872d68e975386832e8005ffeacedd43a1d837a32815be/typer-0.26.8.tar.gz", hash = "sha256:c244a6bd558886fe3f8780efb6bdd28bb9aff005a94eedebaa5cb32926fe2f7e", size = 202097 } +sdist = { url = "https://files.pythonhosted.org/packages/7c/f7/68adc395201b20b872d68e975386832e8005ffeacedd43a1d837a32815be/typer-0.26.8.tar.gz", hash = "sha256:c244a6bd558886fe3f8780efb6bdd28bb9aff005a94eedebaa5cb32926fe2f7e", size = 202097, upload-time = "2026-06-26T09:22:45.705Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/80/87/b9fd69c92c6102a066e1b86a35243f53e70bd4c709f2a26d9f4fee4f4dc0/typer-0.26.8-py3-none-any.whl", hash = "sha256:3512ca79ac5c11113414b36e80281b872884477722440691c89d1112e321a49c", size = 122564 }, + { url = "https://files.pythonhosted.org/packages/80/87/b9fd69c92c6102a066e1b86a35243f53e70bd4c709f2a26d9f4fee4f4dc0/typer-0.26.8-py3-none-any.whl", hash = "sha256:3512ca79ac5c11113414b36e80281b872884477722440691c89d1112e321a49c", size = 122564, upload-time = "2026-06-26T09:22:44.72Z" }, ] [[package]] name = "typing-extensions" version = "4.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555 } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571 }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] @@ -1326,75 +1326,75 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949 } +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611 }, + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] [[package]] name = "websockets" version = "16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346 } +sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343 }, - { url = "https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0", size = 175021 }, - { url = "https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957", size = 175320 }, - { url = "https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72", size = 183815 }, - { url = "https://files.pythonhosted.org/packages/86/26/d40eaa2a46d4302becec8d15b0fc5e45bdde05191e7628405a19cf491ccd/websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde", size = 185054 }, - { url = "https://files.pythonhosted.org/packages/b0/ba/6500a0efc94f7373ee8fefa8c271acdfd4dca8bd49a90d4be7ccabfc397e/websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3", size = 184565 }, - { url = "https://files.pythonhosted.org/packages/04/b4/96bf2cee7c8d8102389374a2616200574f5f01128d1082f44102140344cc/websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3", size = 183848 }, - { url = "https://files.pythonhosted.org/packages/02/8e/81f40fb00fd125357814e8c3025738fc4ffc3da4b6b4a4472a82ba304b41/websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9", size = 178249 }, - { url = "https://files.pythonhosted.org/packages/b4/5f/7e40efe8df57db9b91c88a43690ac66f7b7aa73a11aa6a66b927e44f26fa/websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35", size = 178685 }, - { url = "https://files.pythonhosted.org/packages/f2/db/de907251b4ff46ae804ad0409809504153b3f30984daf82a1d84a9875830/websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8", size = 177340 }, - { url = "https://files.pythonhosted.org/packages/f3/fa/abe89019d8d8815c8781e90d697dec52523fb8ebe308bf11664e8de1877e/websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad", size = 175022 }, - { url = "https://files.pythonhosted.org/packages/58/5d/88ea17ed1ded2079358b40d31d48abe90a73c9e5819dbcde1606e991e2ad/websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d", size = 175319 }, - { url = "https://files.pythonhosted.org/packages/d2/ae/0ee92b33087a33632f37a635e11e1d99d429d3d323329675a6022312aac2/websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe", size = 184631 }, - { url = "https://files.pythonhosted.org/packages/c8/c5/27178df583b6c5b31b29f526ba2da5e2f864ecc79c99dae630a85d68c304/websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b", size = 185870 }, - { url = "https://files.pythonhosted.org/packages/87/05/536652aa84ddc1c018dbb7e2c4cbcd0db884580bf8e95aece7593fde526f/websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5", size = 185361 }, - { url = "https://files.pythonhosted.org/packages/6d/e2/d5332c90da12b1e01f06fb1b85c50cfc489783076547415bf9f0a659ec19/websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64", size = 184615 }, - { url = "https://files.pythonhosted.org/packages/77/fb/d3f9576691cae9253b51555f841bc6600bf0a983a461c79500ace5a5b364/websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6", size = 178246 }, - { url = "https://files.pythonhosted.org/packages/54/67/eaff76b3dbaf18dcddabc3b8c1dba50b483761cccff67793897945b37408/websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac", size = 178684 }, - { url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365 }, - { url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038 }, - { url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328 }, - { url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915 }, - { url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152 }, - { url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583 }, - { url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880 }, - { url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261 }, - { url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693 }, - { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364 }, - { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039 }, - { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323 }, - { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975 }, - { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203 }, - { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653 }, - { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920 }, - { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255 }, - { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689 }, - { url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406 }, - { url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085 }, - { url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328 }, - { url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044 }, - { url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279 }, - { url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711 }, - { url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982 }, - { url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915 }, - { url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381 }, - { url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737 }, - { url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268 }, - { url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486 }, - { url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331 }, - { url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501 }, - { url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062 }, - { url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356 }, - { url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085 }, - { url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531 }, - { url = "https://files.pythonhosted.org/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d", size = 174947 }, - { url = "https://files.pythonhosted.org/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03", size = 175260 }, - { url = "https://files.pythonhosted.org/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da", size = 176071 }, - { url = "https://files.pythonhosted.org/packages/a5/8f/aea9c71cc92bf9b6cc0f7f70df8f0b420636b6c96ef4feee1e16f80f75dd/websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c", size = 176968 }, - { url = "https://files.pythonhosted.org/packages/9a/3f/f70e03f40ffc9a30d817eef7da1be72ee4956ba8d7255c399a01b135902a/websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767", size = 178735 }, - { url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598 }, + { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0", size = 175021, upload-time = "2026-01-10T09:22:22.696Z" }, + { url = "https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957", size = 175320, upload-time = "2026-01-10T09:22:23.94Z" }, + { url = "https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72", size = 183815, upload-time = "2026-01-10T09:22:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/26/d40eaa2a46d4302becec8d15b0fc5e45bdde05191e7628405a19cf491ccd/websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde", size = 185054, upload-time = "2026-01-10T09:22:27.101Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ba/6500a0efc94f7373ee8fefa8c271acdfd4dca8bd49a90d4be7ccabfc397e/websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3", size = 184565, upload-time = "2026-01-10T09:22:28.293Z" }, + { url = "https://files.pythonhosted.org/packages/04/b4/96bf2cee7c8d8102389374a2616200574f5f01128d1082f44102140344cc/websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3", size = 183848, upload-time = "2026-01-10T09:22:30.394Z" }, + { url = "https://files.pythonhosted.org/packages/02/8e/81f40fb00fd125357814e8c3025738fc4ffc3da4b6b4a4472a82ba304b41/websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9", size = 178249, upload-time = "2026-01-10T09:22:32.083Z" }, + { url = "https://files.pythonhosted.org/packages/b4/5f/7e40efe8df57db9b91c88a43690ac66f7b7aa73a11aa6a66b927e44f26fa/websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35", size = 178685, upload-time = "2026-01-10T09:22:33.345Z" }, + { url = "https://files.pythonhosted.org/packages/f2/db/de907251b4ff46ae804ad0409809504153b3f30984daf82a1d84a9875830/websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8", size = 177340, upload-time = "2026-01-10T09:22:34.539Z" }, + { url = "https://files.pythonhosted.org/packages/f3/fa/abe89019d8d8815c8781e90d697dec52523fb8ebe308bf11664e8de1877e/websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad", size = 175022, upload-time = "2026-01-10T09:22:36.332Z" }, + { url = "https://files.pythonhosted.org/packages/58/5d/88ea17ed1ded2079358b40d31d48abe90a73c9e5819dbcde1606e991e2ad/websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d", size = 175319, upload-time = "2026-01-10T09:22:37.602Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ae/0ee92b33087a33632f37a635e11e1d99d429d3d323329675a6022312aac2/websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe", size = 184631, upload-time = "2026-01-10T09:22:38.789Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c5/27178df583b6c5b31b29f526ba2da5e2f864ecc79c99dae630a85d68c304/websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b", size = 185870, upload-time = "2026-01-10T09:22:39.893Z" }, + { url = "https://files.pythonhosted.org/packages/87/05/536652aa84ddc1c018dbb7e2c4cbcd0db884580bf8e95aece7593fde526f/websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5", size = 185361, upload-time = "2026-01-10T09:22:41.016Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e2/d5332c90da12b1e01f06fb1b85c50cfc489783076547415bf9f0a659ec19/websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64", size = 184615, upload-time = "2026-01-10T09:22:42.442Z" }, + { url = "https://files.pythonhosted.org/packages/77/fb/d3f9576691cae9253b51555f841bc6600bf0a983a461c79500ace5a5b364/websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6", size = 178246, upload-time = "2026-01-10T09:22:43.654Z" }, + { url = "https://files.pythonhosted.org/packages/54/67/eaff76b3dbaf18dcddabc3b8c1dba50b483761cccff67793897945b37408/websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac", size = 178684, upload-time = "2026-01-10T09:22:44.941Z" }, + { url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365, upload-time = "2026-01-10T09:22:46.787Z" }, + { url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038, upload-time = "2026-01-10T09:22:47.999Z" }, + { url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328, upload-time = "2026-01-10T09:22:49.809Z" }, + { url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915, upload-time = "2026-01-10T09:22:51.071Z" }, + { url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152, upload-time = "2026-01-10T09:22:52.224Z" }, + { url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583, upload-time = "2026-01-10T09:22:53.443Z" }, + { url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" }, + { url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" }, + { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" }, + { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" }, + { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" }, + { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" }, + { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" }, + { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" }, + { url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" }, + { url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" }, + { url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044, upload-time = "2026-01-10T09:23:15.939Z" }, + { url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279, upload-time = "2026-01-10T09:23:17.148Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711, upload-time = "2026-01-10T09:23:18.372Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982, upload-time = "2026-01-10T09:23:19.652Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915, upload-time = "2026-01-10T09:23:21.458Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381, upload-time = "2026-01-10T09:23:22.715Z" }, + { url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737, upload-time = "2026-01-10T09:23:24.523Z" }, + { url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268, upload-time = "2026-01-10T09:23:25.781Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486, upload-time = "2026-01-10T09:23:27.033Z" }, + { url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331, upload-time = "2026-01-10T09:23:28.259Z" }, + { url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501, upload-time = "2026-01-10T09:23:29.449Z" }, + { url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062, upload-time = "2026-01-10T09:23:31.368Z" }, + { url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356, upload-time = "2026-01-10T09:23:32.627Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085, upload-time = "2026-01-10T09:23:33.816Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531, upload-time = "2026-01-10T09:23:35.016Z" }, + { url = "https://files.pythonhosted.org/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d", size = 174947, upload-time = "2026-01-10T09:23:36.166Z" }, + { url = "https://files.pythonhosted.org/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03", size = 175260, upload-time = "2026-01-10T09:23:37.409Z" }, + { url = "https://files.pythonhosted.org/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da", size = 176071, upload-time = "2026-01-10T09:23:39.158Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8f/aea9c71cc92bf9b6cc0f7f70df8f0b420636b6c96ef4feee1e16f80f75dd/websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c", size = 176968, upload-time = "2026-01-10T09:23:41.031Z" }, + { url = "https://files.pythonhosted.org/packages/9a/3f/f70e03f40ffc9a30d817eef7da1be72ee4956ba8d7255c399a01b135902a/websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767", size = 178735, upload-time = "2026-01-10T09:23:42.259Z" }, + { url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" }, ] From 86ad1e110c228cf9f2d256ad7692d80858221700 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Tue, 4 Aug 2026 14:40:48 +0200 Subject: [PATCH 36/58] fix(cli): align root output shapes Keep root position rows aligned with their human table columns in both single-wallet and all-wallet modes. Emit one consolidated JSON document for explicit validator details and cover the affected human and JSON paths. (cherry picked from commit 3e56c87536d2669638e9af04dc0bc97f4eb0de30) --- sdk/python/bittensor/cli/commands/root.py | 2 +- sdk/python/bittensor/cli/root_helpers.py | 12 ++- sdk/python/tests/unit/test_cli.py | 111 ++++++++++++++++++++++ 3 files changed, 119 insertions(+), 6 deletions(-) diff --git a/sdk/python/bittensor/cli/commands/root.py b/sdk/python/bittensor/cli/commands/root.py index 54798bab50..d2bc6e2920 100644 --- a/sdk/python/bittensor/cli/commands/root.py +++ b/sdk/python/bittensor/cli/commands/root.py @@ -107,7 +107,7 @@ def root_list( app_ctx.output.table( title, position_columns(all_wallets), - position_rows(shown), + position_rows(shown, all_wallets), shown_records, ) app_ctx.output.message( diff --git a/sdk/python/bittensor/cli/root_helpers.py b/sdk/python/bittensor/cli/root_helpers.py index a88920a604..73ecb08c4e 100644 --- a/sdk/python/bittensor/cli/root_helpers.py +++ b/sdk/python/bittensor/cli/root_helpers.py @@ -474,6 +474,10 @@ def print_command_hint(console: Console, argv_prefix: list[str]) -> None: def render_validator_detail( app_ctx: AppContext, summary: dict, yours: Optional[RootPosition] ) -> None: + if app_ctx.output.json_mode: + app_ctx.output.value(summary) + return + hotkey = summary["hotkey"] weights = summary.get("weights") or [] holdings = summary.get("holdings") or [] @@ -491,7 +495,6 @@ def render_validator_detail( f"weights of {hotkey}", ["netuid", "share", "weight (u16)"], weight_rows, - weights, ) else: app_ctx.output.message( @@ -513,7 +516,6 @@ def render_validator_detail( f"fund holdings of {hotkey}", ["netuid", "holding", "realizable", "spot"], table_rows, - summary, ) lifetime = summary.get("lifetime_return") @@ -524,10 +526,10 @@ def render_validator_detail( ) -def position_rows(positions: list[RootPosition]) -> list[list[str]]: +def position_rows(positions: list[RootPosition], all_wallets: bool) -> list[list[str]]: return [ - [ - pos.wallet or "—", + ([pos.wallet or "—"] if all_wallets else []) + + [ pos.hotkey, str(pos.staked), str(pos.accrued), diff --git a/sdk/python/tests/unit/test_cli.py b/sdk/python/tests/unit/test_cli.py index b11dcfaa9b..43391c22d1 100644 --- a/sdk/python/tests/unit/test_cli.py +++ b/sdk/python/tests/unit/test_cli.py @@ -14,9 +14,12 @@ import pytest from typer.testing import CliRunner +import bittensor.cli.commands.root as root_commands import bittensor.cli.context as cli_context from bittensor import RpcConnectionError, RpcPolicyError, __version__, wallets +from bittensor.balance import Balance from bittensor.cli.main import app +from bittensor.cli.root_helpers import RootPosition, position_columns, position_rows from bittensor.client import Client from bittensor.intents import REGISTRY from tests.harness.fake_substrate import FakeSubstrate @@ -65,6 +68,29 @@ def invoke(*args: str): return runner.invoke(app, list(args)) +def seed_root_validator_summary(fake: FakeSubstrate) -> None: + fake.seed_runtime( + "BetaBasketRuntimeApi", + "get_validator_basket_summary", + { + "hotkey": BOB, + "nav_tao": 1_250_000_000, + "spot_nav_tao": 1_500_000_000, + "deposited_tao": 1_000_000_000, + "redeemed_tao": 0, + "weights": [(1, 65535)], + "holdings": [ + { + "netuid": 1, + "alpha": 2_000_000_000, + "spot_tao": 1_500_000_000, + "realizable_tao": 1_250_000_000, + } + ], + }, + ) + + class TestOffline: """Commands that never open a connection.""" @@ -219,6 +245,91 @@ def test_wallet_balance_by_address(self, fake: FakeSubstrate): assert payload["free_tao"] == pytest.approx(2.5) +class TestRoot: + @pytest.mark.parametrize("all_wallets", [False, True]) + def test_position_rows_match_columns(self, all_wallets): + position = RootPosition( + hotkey=BOB, + staked=Balance.from_tao(1), + accrued=Balance.from_tao("0.25"), + wallet=_WALLET_NAME if all_wallets else None, + ) + + rows = position_rows([position], all_wallets) + + assert all(len(row) == len(position_columns(all_wallets)) for row in rows) + + def test_list_single_coldkey_renders_human_table(self, fake: FakeSubstrate, monkeypatch): + async def root_positions(_client, _coldkey_ss58): + return [ + RootPosition( + hotkey=BOB, + staked=Balance.from_tao(1), + accrued=Balance.from_tao("0.25"), + ) + ] + + monkeypatch.setattr(root_commands, "fetch_root_positions", root_positions) + + result = invoke("root", "list", "--coldkey", BOB) + + assert result.exit_code == 0, result.exception + assert "root positions of" in result.output + assert "staked (τ)" in result.output + assert "τ1.250000000" in result.output + + def test_list_all_wallets_renders_wallet_column(self, fake: FakeSubstrate, monkeypatch): + async def all_root_positions(_client, _coldkeys): + return [ + RootPosition( + hotkey=BOB, + staked=Balance.from_tao(1), + accrued=Balance.from_tao("0.25"), + wallet=_WALLET_NAME, + coldkey=BOB, + ) + ] + + monkeypatch.setattr(root_commands, "list_coldkeys", lambda _path: [(_WALLET_NAME, BOB)]) + monkeypatch.setattr(root_commands, "fetch_all_root_positions", all_root_positions) + + result = invoke("root", "list", "--all") + + assert result.exit_code == 0, result.exception + assert "wallet" in result.output + assert _WALLET_NAME in result.output + assert "τ1.250000000" in result.output + + def test_show_explicit_hotkey_renders_human_detail(self, fake: FakeSubstrate, monkeypatch): + async def root_positions(_client, _coldkey_ss58): + return [] + + monkeypatch.setattr(root_commands, "fetch_root_positions", root_positions) + seed_root_validator_summary(fake) + + result = invoke("root", "show", "--hotkey", BOB, "--coldkey", BOB) + + assert result.exit_code == 0, result.exception + assert "weights of" in result.output + assert "fund holdings of" in result.output + assert "fund nav: τ1.250000000" in result.output + + def test_show_explicit_hotkey_json_emits_one_document(self, fake: FakeSubstrate, monkeypatch): + async def root_positions(_client, _coldkey_ss58): + return [] + + monkeypatch.setattr(root_commands, "fetch_root_positions", root_positions) + seed_root_validator_summary(fake) + + result = invoke("--json", "root", "show", "--hotkey", BOB, "--coldkey", BOB) + + assert result.exit_code == 0, result.exception + payload = json.loads(result.output) + assert payload["hotkey"] == BOB + assert payload["nav_tao"] == "τ1.250000000" + assert payload["weights"] == [{"netuid": 1, "weight": 65535, "share": 1.0}] + + class TestTransactions: def test_dry_run_renders_plan_without_submitting(self, fake: FakeSubstrate): result = invoke( From b1e6b83fc6ed987b49b29fabc38c3618ff4a6ff3 Mon Sep 17 00:00:00 2001 From: unarbos Date: Thu, 6 Aug 2026 09:17:58 -0300 Subject: [PATCH 37/58] fix: no-std imports in precompiles; regenerate docs pages for drift gate Co-authored-by: Cursor --- .../AnnouncementDepositInvariantViolated.mdx | 2 +- docs/errors/chain/Duplicate.mdx | 2 +- docs/errors/chain/InvalidDerivedAccountId.mdx | 2 +- docs/errors/chain/NoPermission.mdx | 2 +- docs/errors/chain/NoSelfProxy.mdx | 2 +- docs/errors/chain/NotFound.mdx | 2 +- docs/errors/chain/NotProxy.mdx | 2 +- docs/errors/chain/TooMany.mdx | 2 +- docs/errors/chain/Unannounced.mdx | 2 +- docs/errors/chain/Unproxyable.mdx | 2 +- docs/hyperparameters/index.mdx | 12 +- docs/query/associated-evm-key.mdx | 2 +- docs/query/blocks-since-last-update.mdx | 2 +- docs/query/blocks-until-next-epoch.mdx | 2 +- docs/query/bonds.mdx | 2 +- docs/query/epoch-status.mdx | 2 +- docs/query/hotkey-identities.mdx | 2 +- docs/query/identity.mdx | 2 +- docs/query/lease.mdx | 2 +- docs/query/leases.mdx | 2 +- docs/query/mechanism-count.mdx | 2 +- docs/query/mechanism-emission-split.mdx | 2 +- docs/query/next-epoch-start-block.mdx | 2 +- docs/query/proxies.mdx | 2 +- docs/query/reveal-period.mdx | 2 +- docs/query/subnet-collateral.mdx | 2 +- docs/query/subnet-identity.mdx | 2 +- docs/query/subnet-names.mdx | 2 +- docs/query/timelocked-weight-commits.mdx | 2 +- docs/query/uid.mdx | 2 +- docs/query/validator-basket.mdx | 2 +- docs/query/weights.mdx | 2 +- docs/tx/add-proxy.mdx | 6 +- docs/tx/create-pure-proxy.mdx | 6 +- docs/tx/execute-proxy-announced.mdx | 6 +- docs/tx/kill-pure-proxy.mdx | 6 +- docs/tx/remove-proxies.mdx | 6 +- docs/tx/remove-proxy.mdx | 6 +- docs/tx/set-hyperparameter.mdx | 64 ++--- docs/tx/set-mechanism-count.mdx | 4 +- docs/tx/set-subnet-emission-enabled.mdx | 4 +- docs/tx/trim-subnet.mdx | 4 +- precompiles/src/balance.rs | 1 + precompiles/src/registry.rs | 1 + .../public/catalog/errors.json | 40 +-- .../public/catalog/intents.json | 240 +++++++++--------- .../public/catalog/reads.json | 92 +++---- 47 files changed, 281 insertions(+), 279 deletions(-) diff --git a/docs/errors/chain/AnnouncementDepositInvariantViolated.mdx b/docs/errors/chain/AnnouncementDepositInvariantViolated.mdx index 4a783688c7..f1c2e16fef 100644 --- a/docs/errors/chain/AnnouncementDepositInvariantViolated.mdx +++ b/docs/errors/chain/AnnouncementDepositInvariantViolated.mdx @@ -9,7 +9,7 @@ Internal invariant failure in `announce`: recomputing the announcement deposit r Declared by the `Proxy` pallet; it classifies to the semantic code [`internal`](/docs/errors/internal). -Declared at [`pallets/proxy/src/lib.rs#L795`](/code/pallets/proxy/src/lib.rs#L795). +Declared at [`pallets/proxy/src/lib.rs#L809`](/code/pallets/proxy/src/lib.rs#L809). ## Remediation diff --git a/docs/errors/chain/Duplicate.mdx b/docs/errors/chain/Duplicate.mdx index fa560ffca3..60c1159ac7 100644 --- a/docs/errors/chain/Duplicate.mdx +++ b/docs/errors/chain/Duplicate.mdx @@ -9,7 +9,7 @@ This delegate is already registered as a proxy for the delegator with the same p Declared by the `Proxy` pallet; it classifies to the semantic code [`already_exists`](/docs/errors/already-exists). -Declared at [`pallets/proxy/src/lib.rs#L787`](/code/pallets/proxy/src/lib.rs#L787). +Declared at [`pallets/proxy/src/lib.rs#L801`](/code/pallets/proxy/src/lib.rs#L801). ## Remediation diff --git a/docs/errors/chain/InvalidDerivedAccountId.mdx b/docs/errors/chain/InvalidDerivedAccountId.mdx index dd62a44411..252eb41644 100644 --- a/docs/errors/chain/InvalidDerivedAccountId.mdx +++ b/docs/errors/chain/InvalidDerivedAccountId.mdx @@ -9,7 +9,7 @@ Deriving the pure proxy account id from the provided entropy failed to decode in Declared by the `Proxy` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/proxy/src/lib.rs#L797`](/code/pallets/proxy/src/lib.rs#L797). +Declared at [`pallets/proxy/src/lib.rs#L811`](/code/pallets/proxy/src/lib.rs#L811). ## Remediation diff --git a/docs/errors/chain/NoPermission.mdx b/docs/errors/chain/NoPermission.mdx index 9e53857f24..2795c82ba1 100644 --- a/docs/errors/chain/NoPermission.mdx +++ b/docs/errors/chain/NoPermission.mdx @@ -9,7 +9,7 @@ The proxy pallet refused the action: the proxied call could escalate privileges, Declared by the `Proxy` pallet; it classifies to the semantic code [`not_authorized`](/docs/errors/not-authorized). -Declared at [`pallets/proxy/src/lib.rs#L789`](/code/pallets/proxy/src/lib.rs#L789). +Declared at [`pallets/proxy/src/lib.rs#L803`](/code/pallets/proxy/src/lib.rs#L803). ## Remediation diff --git a/docs/errors/chain/NoSelfProxy.mdx b/docs/errors/chain/NoSelfProxy.mdx index 4ebcbb8969..ab9af577d5 100644 --- a/docs/errors/chain/NoSelfProxy.mdx +++ b/docs/errors/chain/NoSelfProxy.mdx @@ -9,7 +9,7 @@ An account attempted to register itself as its own proxy, which is not allowed. Declared by the `Proxy` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/proxy/src/lib.rs#L793`](/code/pallets/proxy/src/lib.rs#L793). +Declared at [`pallets/proxy/src/lib.rs#L807`](/code/pallets/proxy/src/lib.rs#L807). ## Remediation diff --git a/docs/errors/chain/NotFound.mdx b/docs/errors/chain/NotFound.mdx index d6682c660b..acda02ac76 100644 --- a/docs/errors/chain/NotFound.mdx +++ b/docs/errors/chain/NotFound.mdx @@ -9,7 +9,7 @@ The referenced item does not exist in storage: no multisig operation for that ca Declared by the `Multisig`, `Scheduler`, `Proxy` pallets; it classifies to the semantic code [`not_found`](/docs/errors/not-found). -Declared at [`pallets/proxy/src/lib.rs#L781`](/code/pallets/proxy/src/lib.rs#L781). +Declared at [`pallets/proxy/src/lib.rs#L795`](/code/pallets/proxy/src/lib.rs#L795). ## Remediation diff --git a/docs/errors/chain/NotProxy.mdx b/docs/errors/chain/NotProxy.mdx index 4f9fe3745d..d59d0b988a 100644 --- a/docs/errors/chain/NotProxy.mdx +++ b/docs/errors/chain/NotProxy.mdx @@ -9,7 +9,7 @@ The sender is not registered as a proxy for the account it tried to act for. Che Declared by the `Proxy` pallet; it classifies to the semantic code [`not_authorized`](/docs/errors/not-authorized). -Declared at [`pallets/proxy/src/lib.rs#L783`](/code/pallets/proxy/src/lib.rs#L783). +Declared at [`pallets/proxy/src/lib.rs#L797`](/code/pallets/proxy/src/lib.rs#L797). ## Remediation diff --git a/docs/errors/chain/TooMany.mdx b/docs/errors/chain/TooMany.mdx index 1a6589e888..f7d51e6e47 100644 --- a/docs/errors/chain/TooMany.mdx +++ b/docs/errors/chain/TooMany.mdx @@ -9,7 +9,7 @@ A limit was exceeded: more preimage hashes than `MAX_HASH_UPGRADE_BULK_COUNT` we Declared by the `Preimage`, `Proxy` pallets; it classifies to the semantic code [`limit_exceeded`](/docs/errors/limit-exceeded). -Declared at [`pallets/proxy/src/lib.rs#L779`](/code/pallets/proxy/src/lib.rs#L779). +Declared at [`pallets/proxy/src/lib.rs#L793`](/code/pallets/proxy/src/lib.rs#L793). ## Remediation diff --git a/docs/errors/chain/Unannounced.mdx b/docs/errors/chain/Unannounced.mdx index 1e7aa11bc3..24fb61e38b 100644 --- a/docs/errors/chain/Unannounced.mdx +++ b/docs/errors/chain/Unannounced.mdx @@ -9,7 +9,7 @@ The proxied call was executed before its announcement matured, or no matching an Declared by the `Proxy` pallet; it classifies to the semantic code [`too_early`](/docs/errors/too-early). -Declared at [`pallets/proxy/src/lib.rs#L791`](/code/pallets/proxy/src/lib.rs#L791). +Declared at [`pallets/proxy/src/lib.rs#L805`](/code/pallets/proxy/src/lib.rs#L805). ## Remediation diff --git a/docs/errors/chain/Unproxyable.mdx b/docs/errors/chain/Unproxyable.mdx index 0ebfd4f77b..b0de284617 100644 --- a/docs/errors/chain/Unproxyable.mdx +++ b/docs/errors/chain/Unproxyable.mdx @@ -9,7 +9,7 @@ The attempted call is not permitted by the registered proxy type's call filter. Declared by the `Proxy` pallet; it classifies to the semantic code [`not_authorized`](/docs/errors/not-authorized). -Declared at [`pallets/proxy/src/lib.rs#L785`](/code/pallets/proxy/src/lib.rs#L785). +Declared at [`pallets/proxy/src/lib.rs#L799`](/code/pallets/proxy/src/lib.rs#L799). ## Remediation diff --git a/docs/hyperparameters/index.mdx b/docs/hyperparameters/index.mdx index d910de7733..17b9a87cd5 100644 --- a/docs/hyperparameters/index.mdx +++ b/docs/hyperparameters/index.mdx @@ -33,7 +33,7 @@ Read them with `btcli sudo get --netuid N` (the [`subnet_hyperparameters`](/docs | [`serving_rate_limit`](/docs/hyperparameters/serving-rate-limit) | blocks (12s) | yes | cooldown between axon serve calls | [`ServingRateLimit`](/code/pallets/subtensor/src/lib.rs#L2189) | | [`max_validators`](/docs/hyperparameters/max-validators) | integer | root only | top-stake validator permit cap | [`MaxAllowedValidators`](/code/pallets/subtensor/src/lib.rs#L2263) | | [`adjustment_alpha`](/docs/hyperparameters/adjustment-alpha) | fraction (u64, u64::MAX = 1.0) | yes | difficulty/burn adjust smoothing | [`AdjustmentAlpha`](/code/pallets/subtensor/src/lib.rs#L2308) | -| [`commit_reveal_period`](/docs/hyperparameters/commit-reveal-period) | epochs (tempos) | yes | weight commit-to-reveal delay | [`RevealPeriodEpochs`](/code/pallets/subtensor/src/lib.rs#L2750) | +| [`commit_reveal_period`](/docs/hyperparameters/commit-reveal-period) | epochs (tempos) | yes | weight commit-to-reveal delay | [`RevealPeriodEpochs`](/code/pallets/subtensor/src/lib.rs#L2756) | | [`commit_reveal_weights_enabled`](/docs/hyperparameters/commit-reveal-weights-enabled) | flag | yes | commit-reveal weights toggle | [`CommitRevealWeightsEnabled`](/code/pallets/subtensor/src/lib.rs#L2313) | | [`alpha_high`](/docs/hyperparameters/alpha-high) | fraction (u16, 65535 = 1.0) | yes | liquid-alpha smoothing upper bound | — | | [`alpha_low`](/docs/hyperparameters/alpha-low) | fraction (u16, 65535 = 1.0) | yes | liquid-alpha smoothing lower bound | — | @@ -41,12 +41,12 @@ Read them with `btcli sudo get --netuid N` (the [`subnet_hyperparameters`](/docs | [`bonds_penalty`](/docs/hyperparameters/bonds-penalty) | fraction (u16, 65535 = 1.0) | yes | penalty on out-of-consensus bonds | [`BondsPenalty`](/code/pallets/subtensor/src/lib.rs#L2278) | | [`alpha_sigmoid_steepness`](/docs/hyperparameters/alpha-sigmoid-steepness) | integer | yes | liquid-alpha sigmoid steepness | [`AlphaSigmoidSteepness`](/code/pallets/subtensor/src/lib.rs#L2198) | | [`min_childkey_take`](/docs/hyperparameters/min-childkey-take) | fraction (u16, 65535 = 1.0) | yes | floor for childkey take | [`MinChildkeyTakePerSubnet`](/code/pallets/subtensor/src/lib.rs#L1320) | -| [`owner_immune_neuron_limit`](/docs/hyperparameters/owner-immune-neuron-limit) | integer | yes | owner-designated prune-immune UIDs | [`ImmuneOwnerUidsLimit`](/code/pallets/subtensor/src/lib.rs#L2489) | +| [`owner_immune_neuron_limit`](/docs/hyperparameters/owner-immune-neuron-limit) | integer | yes | owner-designated prune-immune UIDs | [`ImmuneOwnerUidsLimit`](/code/pallets/subtensor/src/lib.rs#L2495) | | [`max_allowed_uids`](/docs/hyperparameters/max-allowed-uids) | integer | yes | neuron slot capacity before pruning | [`MaxAllowedUids`](/code/pallets/subtensor/src/lib.rs#L2227) | -| [`burn_increase_mult`](/docs/hyperparameters/burn-increase-mult) | multiplier (U64F64 bits / 2^64) | yes | burn cost bump per registration | [`BurnIncreaseMult`](/code/pallets/subtensor/src/lib.rs#L3011) | -| [`burn_half_life`](/docs/hyperparameters/burn-half-life) | blocks (12s) | yes | burn cost decay half-life | [`BurnHalfLife`](/code/pallets/subtensor/src/lib.rs#L3006) | -| [`collateral_lock_share`](/docs/hyperparameters/collateral-lock-share) | fraction (u16, 65535 = 1.0) | yes | registration price share locked | [`CollateralLockShare`](/code/pallets/subtensor/src/lib.rs#L3020) | -| [`collateral_drain_ratio`](/docs/hyperparameters/collateral-drain-ratio) | multiplier (U64F64 bits / 2^64) | yes | collateral released per α earned | [`CollateralDrainRatio`](/code/pallets/subtensor/src/lib.rs#L3029) | +| [`burn_increase_mult`](/docs/hyperparameters/burn-increase-mult) | multiplier (U64F64 bits / 2^64) | yes | burn cost bump per registration | [`BurnIncreaseMult`](/code/pallets/subtensor/src/lib.rs#L3017) | +| [`burn_half_life`](/docs/hyperparameters/burn-half-life) | blocks (12s) | yes | burn cost decay half-life | [`BurnHalfLife`](/code/pallets/subtensor/src/lib.rs#L3012) | +| [`collateral_lock_share`](/docs/hyperparameters/collateral-lock-share) | fraction (u16, 65535 = 1.0) | yes | registration price share locked | [`CollateralLockShare`](/code/pallets/subtensor/src/lib.rs#L3026) | +| [`collateral_drain_ratio`](/docs/hyperparameters/collateral-drain-ratio) | multiplier (U64F64 bits / 2^64) | yes | collateral released per α earned | [`CollateralDrainRatio`](/code/pallets/subtensor/src/lib.rs#L3035) | | [`yuma3_enabled`](/docs/hyperparameters/yuma3-enabled) | flag | yes | yuma3 consensus variant toggle | [`Yuma3On`](/code/pallets/subtensor/src/lib.rs#L2395) | | [`yuma_version`](/docs/hyperparameters/yuma-version) | integer | root only | epoch consensus variant (2 or 3) | — | | [`subnet_is_active`](/docs/hyperparameters/subnet-is-active) | flag | root only | subnet started (staking + emissions) | — | diff --git a/docs/query/associated-evm-key.mdx b/docs/query/associated-evm-key.mdx index e3270abef9..f8fc58274d 100644 --- a/docs/query/associated-evm-key.mdx +++ b/docs/query/associated-evm-key.mdx @@ -43,6 +43,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.AssociatedEvmAddress`](/code/pallets/subtensor/src/lib.rs#L2904) +- Storage [`SubtensorModule.AssociatedEvmAddress`](/code/pallets/subtensor/src/lib.rs#L2910) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/blocks-since-last-update.mdx b/docs/query/blocks-since-last-update.mdx index 2654e7fc4c..479ec5feab 100644 --- a/docs/query/blocks-since-last-update.mdx +++ b/docs/query/blocks-since-last-update.mdx @@ -48,6 +48,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.LastUpdate`](/code/pallets/subtensor/src/lib.rs#L2547) +- Storage [`SubtensorModule.LastUpdate`](/code/pallets/subtensor/src/lib.rs#L2553) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/blocks-until-next-epoch.mdx b/docs/query/blocks-until-next-epoch.mdx index 52d88739ab..32a5fdcb53 100644 --- a/docs/query/blocks-until-next-epoch.mdx +++ b/docs/query/blocks-until-next-epoch.mdx @@ -45,6 +45,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1257-L1271) +- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/bonds.mdx b/docs/query/bonds.mdx index 253580652d..aeb5fd0d84 100644 --- a/docs/query/bonds.mdx +++ b/docs/query/bonds.mdx @@ -46,6 +46,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.Bonds`](/code/pallets/subtensor/src/lib.rs#L2575) +- Storage [`SubtensorModule.Bonds`](/code/pallets/subtensor/src/lib.rs#L2581) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/epoch-status.mdx b/docs/query/epoch-status.mdx index ae371e38ab..cdd6c9c5bf 100644 --- a/docs/query/epoch-status.mdx +++ b/docs/query/epoch-status.mdx @@ -50,6 +50,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. - Storage [`SubtensorModule.BlocksSinceLastStep`](/code/pallets/subtensor/src/lib.rs#L2164) - Storage [`SubtensorModule.PendingEpochAt`](/code/pallets/subtensor/src/lib.rs#L2053) - Storage [`SubtensorModule.SubnetEpochIndex`](/code/pallets/subtensor/src/lib.rs#L2059) -- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1257-L1271) +- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/hotkey-identities.mdx b/docs/query/hotkey-identities.mdx index 3cd5ab5745..1a4af51f60 100644 --- a/docs/query/hotkey-identities.mdx +++ b/docs/query/hotkey-identities.mdx @@ -43,6 +43,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation - Storage [`SubtensorModule.Owner`](/code/pallets/subtensor/src/lib.rs#L1325) -- Storage [`SubtensorModule.IdentitiesV2`](/code/pallets/subtensor/src/lib.rs#L2637) +- Storage [`SubtensorModule.IdentitiesV2`](/code/pallets/subtensor/src/lib.rs#L2643) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/identity.mdx b/docs/query/identity.mdx index 3ad5b3a63a..fd4a849faf 100644 --- a/docs/query/identity.mdx +++ b/docs/query/identity.mdx @@ -42,6 +42,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.IdentitiesV2`](/code/pallets/subtensor/src/lib.rs#L2637) +- Storage [`SubtensorModule.IdentitiesV2`](/code/pallets/subtensor/src/lib.rs#L2643) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/lease.mdx b/docs/query/lease.mdx index cf64b87dbb..a15ecee8ba 100644 --- a/docs/query/lease.mdx +++ b/docs/query/lease.mdx @@ -43,6 +43,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.SubnetLeases`](/code/pallets/subtensor/src/lib.rs#L2922) +- Storage [`SubtensorModule.SubnetLeases`](/code/pallets/subtensor/src/lib.rs#L2928) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/leases.mdx b/docs/query/leases.mdx index dbd0d93e13..893e505cc6 100644 --- a/docs/query/leases.mdx +++ b/docs/query/leases.mdx @@ -40,6 +40,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.SubnetLeases`](/code/pallets/subtensor/src/lib.rs#L2922) +- Storage [`SubtensorModule.SubnetLeases`](/code/pallets/subtensor/src/lib.rs#L2928) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/mechanism-count.mdx b/docs/query/mechanism-count.mdx index 8dd9a71f1c..babe67ea75 100644 --- a/docs/query/mechanism-count.mdx +++ b/docs/query/mechanism-count.mdx @@ -42,6 +42,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.MechanismCountCurrent`](/code/pallets/subtensor/src/lib.rs#L2996) +- Storage [`SubtensorModule.MechanismCountCurrent`](/code/pallets/subtensor/src/lib.rs#L3002) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/mechanism-emission-split.mdx b/docs/query/mechanism-emission-split.mdx index 49cea75d7e..cc7ed2d917 100644 --- a/docs/query/mechanism-emission-split.mdx +++ b/docs/query/mechanism-emission-split.mdx @@ -43,6 +43,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.MechanismEmissionSplit`](/code/pallets/subtensor/src/lib.rs#L3001) +- Storage [`SubtensorModule.MechanismEmissionSplit`](/code/pallets/subtensor/src/lib.rs#L3007) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/next-epoch-start-block.mdx b/docs/query/next-epoch-start-block.mdx index b84e52f170..d5b6ab7b6d 100644 --- a/docs/query/next-epoch-start-block.mdx +++ b/docs/query/next-epoch-start-block.mdx @@ -45,6 +45,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1257-L1271) +- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/proxies.mdx b/docs/query/proxies.mdx index 5e5028503a..a1def3f998 100644 --- a/docs/query/proxies.mdx +++ b/docs/query/proxies.mdx @@ -42,6 +42,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`Proxy.Proxies`](/code/pallets/proxy/src/lib.rs#L811) +- Storage [`Proxy.Proxies`](/code/pallets/proxy/src/lib.rs#L825) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/reveal-period.mdx b/docs/query/reveal-period.mdx index b1d5e2c165..d0d35227d0 100644 --- a/docs/query/reveal-period.mdx +++ b/docs/query/reveal-period.mdx @@ -42,6 +42,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.RevealPeriodEpochs`](/code/pallets/subtensor/src/lib.rs#L2750) +- Storage [`SubtensorModule.RevealPeriodEpochs`](/code/pallets/subtensor/src/lib.rs#L2756) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/subnet-collateral.mdx b/docs/query/subnet-collateral.mdx index de7b9f786d..e0ce378cd4 100644 --- a/docs/query/subnet-collateral.mdx +++ b/docs/query/subnet-collateral.mdx @@ -46,6 +46,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.Uids`](/code/pallets/subtensor/src/lib.rs#L2500) +- Storage [`SubtensorModule.Uids`](/code/pallets/subtensor/src/lib.rs#L2506) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/subnet-identity.mdx b/docs/query/subnet-identity.mdx index 2421bcc0a3..2c9cd69d8b 100644 --- a/docs/query/subnet-identity.mdx +++ b/docs/query/subnet-identity.mdx @@ -42,6 +42,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.SubnetIdentitiesV3`](/code/pallets/subtensor/src/lib.rs#L2642) +- Storage [`SubtensorModule.SubnetIdentitiesV3`](/code/pallets/subtensor/src/lib.rs#L2648) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/subnet-names.mdx b/docs/query/subnet-names.mdx index ba372be994..02843245e0 100644 --- a/docs/query/subnet-names.mdx +++ b/docs/query/subnet-names.mdx @@ -40,6 +40,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.SubnetIdentitiesV3`](/code/pallets/subtensor/src/lib.rs#L2642) +- Storage [`SubtensorModule.SubnetIdentitiesV3`](/code/pallets/subtensor/src/lib.rs#L2648) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/timelocked-weight-commits.mdx b/docs/query/timelocked-weight-commits.mdx index ba28640a94..bdbd19f999 100644 --- a/docs/query/timelocked-weight-commits.mdx +++ b/docs/query/timelocked-weight-commits.mdx @@ -47,6 +47,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.TimelockedWeightCommits`](/code/pallets/subtensor/src/lib.rs#L2698) +- Storage [`SubtensorModule.TimelockedWeightCommits`](/code/pallets/subtensor/src/lib.rs#L2704) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/uid.mdx b/docs/query/uid.mdx index 6d5d745d55..db316987c3 100644 --- a/docs/query/uid.mdx +++ b/docs/query/uid.mdx @@ -43,6 +43,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.Uids`](/code/pallets/subtensor/src/lib.rs#L2500) +- Storage [`SubtensorModule.Uids`](/code/pallets/subtensor/src/lib.rs#L2506) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/validator-basket.mdx b/docs/query/validator-basket.mdx index 010445bdd6..83abd46f6a 100644 --- a/docs/query/validator-basket.mdx +++ b/docs/query/validator-basket.mdx @@ -44,6 +44,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`BetaBasketRuntimeApi.get_validator_basket`](/code/pallets/subtensor/src/staking/basket_views.rs#L77-L85) +- Runtime API [`BetaBasketRuntimeApi.get_validator_basket`](/code/pallets/subtensor/src/staking/basket_views.rs#L102-L110) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/weights.mdx b/docs/query/weights.mdx index 4865bcfeee..93675f1bc8 100644 --- a/docs/query/weights.mdx +++ b/docs/query/weights.mdx @@ -47,6 +47,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`SubtensorModule.Weights`](/code/pallets/subtensor/src/lib.rs#L2562) +- Storage [`SubtensorModule.Weights`](/code/pallets/subtensor/src/lib.rs#L2568) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/tx/add-proxy.mdx b/docs/tx/add-proxy.mdx index 571fb0f031..d629342f52 100644 --- a/docs/tx/add-proxy.mdx +++ b/docs/tx/add-proxy.mdx @@ -14,7 +14,7 @@ only to keys you control or fully trust. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.add_proxy`](/code/pallets/proxy/src/lib.rs#L265-L276) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.add_proxy`](/code/pallets/proxy/src/lib.rs#L279-L290) | ## Parameters @@ -65,7 +65,7 @@ result = sub.execute_tool("add_proxy", {...}, wallet) ## On-chain implementation -`Proxy.add_proxy` — [`pallets/proxy/src/lib.rs#L267`](/code/pallets/proxy/src/lib.rs#L265-L276): +`Proxy.add_proxy` — [`pallets/proxy/src/lib.rs#L281`](/code/pallets/proxy/src/lib.rs#L279-L290): ```rust #[pallet::call_index(1)] @@ -82,6 +82,6 @@ pub fn add_proxy( } ``` -Delegates to [`add_proxy_delegate`](/code/pallets/proxy/src/lib.rs#L941). +Delegates to [`add_proxy_delegate`](/code/pallets/proxy/src/lib.rs#L955). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/create-pure-proxy.mdx b/docs/tx/create-pure-proxy.mdx index e603cd6c91..8d6385c4f9 100644 --- a/docs/tx/create-pure-proxy.mdx +++ b/docs/tx/create-pure-proxy.mdx @@ -15,7 +15,7 @@ the pure proxy and anything it holds. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.create_pure`](/code/pallets/proxy/src/lib.rs#L330-L364) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.create_pure`](/code/pallets/proxy/src/lib.rs#L344-L378) | ## Parameters @@ -64,7 +64,7 @@ result = sub.execute_tool("create_pure_proxy", {...}, wallet) ## On-chain implementation -`Proxy.create_pure` — [`pallets/proxy/src/lib.rs#L332`](/code/pallets/proxy/src/lib.rs#L330-L364): +`Proxy.create_pure` — [`pallets/proxy/src/lib.rs#L346`](/code/pallets/proxy/src/lib.rs#L344-L378): ```rust #[pallet::call_index(4)] @@ -104,6 +104,6 @@ pub fn create_pure( } ``` -Delegates to [`pure_account`](/code/pallets/proxy/src/lib.rs#L907). +Delegates to [`pure_account`](/code/pallets/proxy/src/lib.rs#L921). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/execute-proxy-announced.mdx b/docs/tx/execute-proxy-announced.mdx index f86f605cd7..7e577e08b1 100644 --- a/docs/tx/execute-proxy-announced.mdx +++ b/docs/tx/execute-proxy-announced.mdx @@ -14,7 +14,7 @@ matching announcement exists. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.proxy_announced`](/code/pallets/proxy/src/lib.rs#L540-L573) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.proxy_announced`](/code/pallets/proxy/src/lib.rs#L554-L587) | ## Parameters @@ -73,7 +73,7 @@ result = sub.execute_tool("execute_proxy_announced", {...}, wallet) ## On-chain implementation -`Proxy.proxy_announced` — [`pallets/proxy/src/lib.rs#L549`](/code/pallets/proxy/src/lib.rs#L540-L573): +`Proxy.proxy_announced` — [`pallets/proxy/src/lib.rs#L563`](/code/pallets/proxy/src/lib.rs#L554-L587): ```rust #[pallet::call_index(9)] @@ -112,6 +112,6 @@ result = sub.execute_tool("execute_proxy_announced", {...}, wallet) } ``` -Delegates to [`find_proxy`](/code/pallets/proxy/src/lib.rs#L1085). +Delegates to [`find_proxy`](/code/pallets/proxy/src/lib.rs#L1099). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/kill-pure-proxy.mdx b/docs/tx/kill-pure-proxy.mdx index 95db441902..a4ddf1bf68 100644 --- a/docs/tx/kill-pure-proxy.mdx +++ b/docs/tx/kill-pure-proxy.mdx @@ -13,7 +13,7 @@ account become permanently inaccessible, so empty it first. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.kill_pure`](/code/pallets/proxy/src/lib.rs#L382-L410) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.kill_pure`](/code/pallets/proxy/src/lib.rs#L396-L424) | ## Parameters @@ -66,7 +66,7 @@ result = sub.execute_tool("kill_pure_proxy", {...}, wallet) ## On-chain implementation -`Proxy.kill_pure` — [`pallets/proxy/src/lib.rs#L384`](/code/pallets/proxy/src/lib.rs#L382-L410): +`Proxy.kill_pure` — [`pallets/proxy/src/lib.rs#L398`](/code/pallets/proxy/src/lib.rs#L396-L424): ```rust #[pallet::call_index(5)] @@ -100,6 +100,6 @@ pub fn kill_pure( } ``` -Delegates to [`pure_account`](/code/pallets/proxy/src/lib.rs#L907). +Delegates to [`pure_account`](/code/pallets/proxy/src/lib.rs#L921). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/remove-proxies.mdx b/docs/tx/remove-proxies.mdx index 29da4e12a6..2d9f905179 100644 --- a/docs/tx/remove-proxies.mdx +++ b/docs/tx/remove-proxies.mdx @@ -12,7 +12,7 @@ permanently (there is no key to recover a pure proxy with). | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.remove_proxies`](/code/pallets/proxy/src/lib.rs#L304-L310) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.remove_proxies`](/code/pallets/proxy/src/lib.rs#L318-L324) | ## Parameters @@ -57,7 +57,7 @@ result = sub.execute_tool("remove_proxies", {...}, wallet) ## On-chain implementation -`Proxy.remove_proxies` — [`pallets/proxy/src/lib.rs#L306`](/code/pallets/proxy/src/lib.rs#L304-L310): +`Proxy.remove_proxies` — [`pallets/proxy/src/lib.rs#L320`](/code/pallets/proxy/src/lib.rs#L318-L324): ```rust #[pallet::call_index(3)] @@ -69,6 +69,6 @@ pub fn remove_proxies(origin: OriginFor) -> DispatchResult { } ``` -Delegates to [`remove_all_proxy_delegates`](/code/pallets/proxy/src/lib.rs#L1143). +Delegates to [`remove_all_proxy_delegates`](/code/pallets/proxy/src/lib.rs#L1157). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/remove-proxy.mdx b/docs/tx/remove-proxy.mdx index f09c4229a9..6b245cff5b 100644 --- a/docs/tx/remove-proxy.mdx +++ b/docs/tx/remove-proxy.mdx @@ -12,7 +12,7 @@ to the signer. Check current delegations with `btcli query proxies`. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.remove_proxy`](/code/pallets/proxy/src/lib.rs#L285-L296) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.remove_proxy`](/code/pallets/proxy/src/lib.rs#L299-L310) | ## Parameters @@ -63,7 +63,7 @@ result = sub.execute_tool("remove_proxy", {...}, wallet) ## On-chain implementation -`Proxy.remove_proxy` — [`pallets/proxy/src/lib.rs#L287`](/code/pallets/proxy/src/lib.rs#L285-L296): +`Proxy.remove_proxy` — [`pallets/proxy/src/lib.rs#L301`](/code/pallets/proxy/src/lib.rs#L299-L310): ```rust #[pallet::call_index(2)] @@ -80,6 +80,6 @@ pub fn remove_proxy( } ``` -Delegates to [`remove_proxy_delegate`](/code/pallets/proxy/src/lib.rs#L986). +Delegates to [`remove_proxy_delegate`](/code/pallets/proxy/src/lib.rs#L1000). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/set-hyperparameter.mdx b/docs/tx/set-hyperparameter.mdx index a20533c6c6..adaee02484 100644 --- a/docs/tx/set-hyperparameter.mdx +++ b/docs/tx/set-hyperparameter.mdx @@ -19,7 +19,7 @@ fail. Read current values back with the `subnet_hyperparameters` read. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | subnet owner | AdminUtils | [`AdminUtils.sudo_set_tempo`](/code/pallets/admin-utils/src/lib.rs#L1028-L1043), [`AdminUtils.sudo_set_immunity_period`](/code/pallets/admin-utils/src/lib.rs#L481-L509), [`AdminUtils.sudo_set_min_allowed_weights`](/code/pallets/admin-utils/src/lib.rs#L514-L542), [`AdminUtils.sudo_set_weights_version_key`](/code/pallets/admin-utils/src/lib.rs#L366-L396), [`AdminUtils.sudo_set_activity_cutoff_factor`](/code/pallets/admin-utils/src/lib.rs#L686-L702), [`AdminUtils.sudo_set_min_burn`](/code/pallets/admin-utils/src/lib.rs#L768-L802), [`AdminUtils.sudo_set_max_burn`](/code/pallets/admin-utils/src/lib.rs#L807-L841), [`AdminUtils.sudo_set_bonds_moving_average`](/code/pallets/admin-utils/src/lib.rs#L899-L933), [`AdminUtils.sudo_set_bonds_penalty`](/code/pallets/admin-utils/src/lib.rs#L938-L964), [`AdminUtils.sudo_set_serving_rate_limit`](/code/pallets/admin-utils/src/lib.rs#L283-L304), [`AdminUtils.sudo_set_commit_reveal_weights_interval`](/code/pallets/admin-utils/src/lib.rs#L1381-L1410), [`AdminUtils.sudo_set_max_allowed_uids`](/code/pallets/admin-utils/src/lib.rs#L547-L592), [`AdminUtils.sudo_set_burn_increase_mult`](/code/pallets/admin-utils/src/lib.rs#L2216-L2256), [`AdminUtils.sudo_set_burn_half_life`](/code/pallets/admin-utils/src/lib.rs#L2174-L2212), [`AdminUtils.sudo_set_collateral_lock_share`](/code/pallets/admin-utils/src/lib.rs#L2340-L2375), [`AdminUtils.sudo_set_collateral_drain_ratio`](/code/pallets/admin-utils/src/lib.rs#L2383-L2424), [`AdminUtils.sudo_set_adjustment_alpha`](/code/pallets/admin-utils/src/lib.rs#L450-L476), [`AdminUtils.sudo_set_rho`](/code/pallets/admin-utils/src/lib.rs#L613-L635), [`AdminUtils.sudo_set_max_difficulty`](/code/pallets/admin-utils/src/lib.rs#L333-L361), [`AdminUtils.sudo_set_alpha_sigmoid_steepness`](/code/pallets/admin-utils/src/lib.rs#L1632-L1666), [`AdminUtils.sudo_set_min_childkey_take_per_subnet`](/code/pallets/admin-utils/src/lib.rs#L1205-L1239), [`AdminUtils.sudo_set_owner_immune_neuron_limit`](/code/pallets/admin-utils/src/lib.rs#L1818-L1838), [`AdminUtils.sudo_set_alpha_values`](/code/pallets/admin-utils/src/lib.rs#L1306-L1331), [`AdminUtils.sudo_set_commit_reveal_weights_enabled`](/code/pallets/admin-utils/src/lib.rs#L1244-L1271), [`AdminUtils.sudo_set_liquid_alpha_enabled`](/code/pallets/admin-utils/src/lib.rs#L1282-L1303), [`AdminUtils.sudo_set_network_pow_registration_allowed`](/code/pallets/admin-utils/src/lib.rs#L728-L736), [`AdminUtils.sudo_set_yuma3_enabled`](/code/pallets/admin-utils/src/lib.rs#L1677-L1700), [`AdminUtils.sudo_set_bonds_reset_enabled`](/code/pallets/admin-utils/src/lib.rs#L1711-L1734), [`AdminUtils.sudo_set_toggle_transfer`](/code/pallets/admin-utils/src/lib.rs#L1470-L1492), [`AdminUtils.sudo_set_owner_cut_enabled`](/code/pallets/admin-utils/src/lib.rs#L2260-L2280), [`AdminUtils.sudo_set_owner_cut_auto_lock_enabled`](/code/pallets/admin-utils/src/lib.rs#L2284-L2304) | +| `coldkey` | subnet owner | AdminUtils | [`AdminUtils.sudo_set_tempo`](/code/pallets/admin-utils/src/lib.rs#L1038-L1053), [`AdminUtils.sudo_set_immunity_period`](/code/pallets/admin-utils/src/lib.rs#L491-L519), [`AdminUtils.sudo_set_min_allowed_weights`](/code/pallets/admin-utils/src/lib.rs#L524-L552), [`AdminUtils.sudo_set_weights_version_key`](/code/pallets/admin-utils/src/lib.rs#L376-L406), [`AdminUtils.sudo_set_activity_cutoff_factor`](/code/pallets/admin-utils/src/lib.rs#L696-L712), [`AdminUtils.sudo_set_min_burn`](/code/pallets/admin-utils/src/lib.rs#L778-L812), [`AdminUtils.sudo_set_max_burn`](/code/pallets/admin-utils/src/lib.rs#L817-L851), [`AdminUtils.sudo_set_bonds_moving_average`](/code/pallets/admin-utils/src/lib.rs#L909-L943), [`AdminUtils.sudo_set_bonds_penalty`](/code/pallets/admin-utils/src/lib.rs#L948-L974), [`AdminUtils.sudo_set_serving_rate_limit`](/code/pallets/admin-utils/src/lib.rs#L293-L314), [`AdminUtils.sudo_set_commit_reveal_weights_interval`](/code/pallets/admin-utils/src/lib.rs#L1391-L1420), [`AdminUtils.sudo_set_max_allowed_uids`](/code/pallets/admin-utils/src/lib.rs#L557-L602), [`AdminUtils.sudo_set_burn_increase_mult`](/code/pallets/admin-utils/src/lib.rs#L2226-L2266), [`AdminUtils.sudo_set_burn_half_life`](/code/pallets/admin-utils/src/lib.rs#L2184-L2222), [`AdminUtils.sudo_set_collateral_lock_share`](/code/pallets/admin-utils/src/lib.rs#L2350-L2385), [`AdminUtils.sudo_set_collateral_drain_ratio`](/code/pallets/admin-utils/src/lib.rs#L2393-L2434), [`AdminUtils.sudo_set_adjustment_alpha`](/code/pallets/admin-utils/src/lib.rs#L460-L486), [`AdminUtils.sudo_set_rho`](/code/pallets/admin-utils/src/lib.rs#L623-L645), [`AdminUtils.sudo_set_max_difficulty`](/code/pallets/admin-utils/src/lib.rs#L343-L371), [`AdminUtils.sudo_set_alpha_sigmoid_steepness`](/code/pallets/admin-utils/src/lib.rs#L1642-L1676), [`AdminUtils.sudo_set_min_childkey_take_per_subnet`](/code/pallets/admin-utils/src/lib.rs#L1215-L1249), [`AdminUtils.sudo_set_owner_immune_neuron_limit`](/code/pallets/admin-utils/src/lib.rs#L1828-L1848), [`AdminUtils.sudo_set_alpha_values`](/code/pallets/admin-utils/src/lib.rs#L1316-L1341), [`AdminUtils.sudo_set_commit_reveal_weights_enabled`](/code/pallets/admin-utils/src/lib.rs#L1254-L1281), [`AdminUtils.sudo_set_liquid_alpha_enabled`](/code/pallets/admin-utils/src/lib.rs#L1292-L1313), [`AdminUtils.sudo_set_network_pow_registration_allowed`](/code/pallets/admin-utils/src/lib.rs#L738-L746), [`AdminUtils.sudo_set_yuma3_enabled`](/code/pallets/admin-utils/src/lib.rs#L1687-L1710), [`AdminUtils.sudo_set_bonds_reset_enabled`](/code/pallets/admin-utils/src/lib.rs#L1721-L1744), [`AdminUtils.sudo_set_toggle_transfer`](/code/pallets/admin-utils/src/lib.rs#L1480-L1502), [`AdminUtils.sudo_set_owner_cut_enabled`](/code/pallets/admin-utils/src/lib.rs#L2270-L2290), [`AdminUtils.sudo_set_owner_cut_auto_lock_enabled`](/code/pallets/admin-utils/src/lib.rs#L2294-L2314) | ## Parameters @@ -76,36 +76,36 @@ result = sub.execute_tool("set_hyperparameter", {...}, wallet) | Chain call | Source | | --- | --- | -| `AdminUtils.sudo_set_tempo` | [`pallets/admin-utils/src/lib.rs#L1039`](/code/pallets/admin-utils/src/lib.rs#L1028-L1043) | -| `AdminUtils.sudo_set_immunity_period` | [`pallets/admin-utils/src/lib.rs#L483`](/code/pallets/admin-utils/src/lib.rs#L481-L509) | -| `AdminUtils.sudo_set_min_allowed_weights` | [`pallets/admin-utils/src/lib.rs#L516`](/code/pallets/admin-utils/src/lib.rs#L514-L542) | -| `AdminUtils.sudo_set_weights_version_key` | [`pallets/admin-utils/src/lib.rs#L368`](/code/pallets/admin-utils/src/lib.rs#L366-L396) | -| `AdminUtils.sudo_set_activity_cutoff_factor` | [`pallets/admin-utils/src/lib.rs#L688`](/code/pallets/admin-utils/src/lib.rs#L686-L702) | -| `AdminUtils.sudo_set_min_burn` | [`pallets/admin-utils/src/lib.rs#L770`](/code/pallets/admin-utils/src/lib.rs#L768-L802) | -| `AdminUtils.sudo_set_max_burn` | [`pallets/admin-utils/src/lib.rs#L809`](/code/pallets/admin-utils/src/lib.rs#L807-L841) | -| `AdminUtils.sudo_set_bonds_moving_average` | [`pallets/admin-utils/src/lib.rs#L901`](/code/pallets/admin-utils/src/lib.rs#L899-L933) | -| `AdminUtils.sudo_set_bonds_penalty` | [`pallets/admin-utils/src/lib.rs#L940`](/code/pallets/admin-utils/src/lib.rs#L938-L964) | -| `AdminUtils.sudo_set_serving_rate_limit` | [`pallets/admin-utils/src/lib.rs#L285`](/code/pallets/admin-utils/src/lib.rs#L283-L304) | -| `AdminUtils.sudo_set_commit_reveal_weights_interval` | [`pallets/admin-utils/src/lib.rs#L1383`](/code/pallets/admin-utils/src/lib.rs#L1381-L1410) | -| `AdminUtils.sudo_set_max_allowed_uids` | [`pallets/admin-utils/src/lib.rs#L549`](/code/pallets/admin-utils/src/lib.rs#L547-L592) | -| `AdminUtils.sudo_set_burn_increase_mult` | [`pallets/admin-utils/src/lib.rs#L2218`](/code/pallets/admin-utils/src/lib.rs#L2216-L2256) | -| `AdminUtils.sudo_set_burn_half_life` | [`pallets/admin-utils/src/lib.rs#L2176`](/code/pallets/admin-utils/src/lib.rs#L2174-L2212) | -| `AdminUtils.sudo_set_collateral_lock_share` | [`pallets/admin-utils/src/lib.rs#L2342`](/code/pallets/admin-utils/src/lib.rs#L2340-L2375) | -| `AdminUtils.sudo_set_collateral_drain_ratio` | [`pallets/admin-utils/src/lib.rs#L2385`](/code/pallets/admin-utils/src/lib.rs#L2383-L2424) | -| `AdminUtils.sudo_set_adjustment_alpha` | [`pallets/admin-utils/src/lib.rs#L452`](/code/pallets/admin-utils/src/lib.rs#L450-L476) | -| `AdminUtils.sudo_set_rho` | [`pallets/admin-utils/src/lib.rs#L615`](/code/pallets/admin-utils/src/lib.rs#L613-L635) | -| `AdminUtils.sudo_set_max_difficulty` | [`pallets/admin-utils/src/lib.rs#L335`](/code/pallets/admin-utils/src/lib.rs#L333-L361) | -| `AdminUtils.sudo_set_alpha_sigmoid_steepness` | [`pallets/admin-utils/src/lib.rs#L1634`](/code/pallets/admin-utils/src/lib.rs#L1632-L1666) | -| `AdminUtils.sudo_set_min_childkey_take_per_subnet` | [`pallets/admin-utils/src/lib.rs#L1207`](/code/pallets/admin-utils/src/lib.rs#L1205-L1239) | -| `AdminUtils.sudo_set_owner_immune_neuron_limit` | [`pallets/admin-utils/src/lib.rs#L1820`](/code/pallets/admin-utils/src/lib.rs#L1818-L1838) | -| `AdminUtils.sudo_set_alpha_values` | [`pallets/admin-utils/src/lib.rs#L1308`](/code/pallets/admin-utils/src/lib.rs#L1306-L1331) | -| `AdminUtils.sudo_set_commit_reveal_weights_enabled` | [`pallets/admin-utils/src/lib.rs#L1246`](/code/pallets/admin-utils/src/lib.rs#L1244-L1271) | -| `AdminUtils.sudo_set_liquid_alpha_enabled` | [`pallets/admin-utils/src/lib.rs#L1284`](/code/pallets/admin-utils/src/lib.rs#L1282-L1303) | -| `AdminUtils.sudo_set_network_pow_registration_allowed` | [`pallets/admin-utils/src/lib.rs#L730`](/code/pallets/admin-utils/src/lib.rs#L728-L736) | -| `AdminUtils.sudo_set_yuma3_enabled` | [`pallets/admin-utils/src/lib.rs#L1679`](/code/pallets/admin-utils/src/lib.rs#L1677-L1700) | -| `AdminUtils.sudo_set_bonds_reset_enabled` | [`pallets/admin-utils/src/lib.rs#L1713`](/code/pallets/admin-utils/src/lib.rs#L1711-L1734) | -| `AdminUtils.sudo_set_toggle_transfer` | [`pallets/admin-utils/src/lib.rs#L1472`](/code/pallets/admin-utils/src/lib.rs#L1470-L1492) | -| `AdminUtils.sudo_set_owner_cut_enabled` | [`pallets/admin-utils/src/lib.rs#L2262`](/code/pallets/admin-utils/src/lib.rs#L2260-L2280) | -| `AdminUtils.sudo_set_owner_cut_auto_lock_enabled` | [`pallets/admin-utils/src/lib.rs#L2286`](/code/pallets/admin-utils/src/lib.rs#L2284-L2304) | +| `AdminUtils.sudo_set_tempo` | [`pallets/admin-utils/src/lib.rs#L1049`](/code/pallets/admin-utils/src/lib.rs#L1038-L1053) | +| `AdminUtils.sudo_set_immunity_period` | [`pallets/admin-utils/src/lib.rs#L493`](/code/pallets/admin-utils/src/lib.rs#L491-L519) | +| `AdminUtils.sudo_set_min_allowed_weights` | [`pallets/admin-utils/src/lib.rs#L526`](/code/pallets/admin-utils/src/lib.rs#L524-L552) | +| `AdminUtils.sudo_set_weights_version_key` | [`pallets/admin-utils/src/lib.rs#L378`](/code/pallets/admin-utils/src/lib.rs#L376-L406) | +| `AdminUtils.sudo_set_activity_cutoff_factor` | [`pallets/admin-utils/src/lib.rs#L698`](/code/pallets/admin-utils/src/lib.rs#L696-L712) | +| `AdminUtils.sudo_set_min_burn` | [`pallets/admin-utils/src/lib.rs#L780`](/code/pallets/admin-utils/src/lib.rs#L778-L812) | +| `AdminUtils.sudo_set_max_burn` | [`pallets/admin-utils/src/lib.rs#L819`](/code/pallets/admin-utils/src/lib.rs#L817-L851) | +| `AdminUtils.sudo_set_bonds_moving_average` | [`pallets/admin-utils/src/lib.rs#L911`](/code/pallets/admin-utils/src/lib.rs#L909-L943) | +| `AdminUtils.sudo_set_bonds_penalty` | [`pallets/admin-utils/src/lib.rs#L950`](/code/pallets/admin-utils/src/lib.rs#L948-L974) | +| `AdminUtils.sudo_set_serving_rate_limit` | [`pallets/admin-utils/src/lib.rs#L295`](/code/pallets/admin-utils/src/lib.rs#L293-L314) | +| `AdminUtils.sudo_set_commit_reveal_weights_interval` | [`pallets/admin-utils/src/lib.rs#L1393`](/code/pallets/admin-utils/src/lib.rs#L1391-L1420) | +| `AdminUtils.sudo_set_max_allowed_uids` | [`pallets/admin-utils/src/lib.rs#L559`](/code/pallets/admin-utils/src/lib.rs#L557-L602) | +| `AdminUtils.sudo_set_burn_increase_mult` | [`pallets/admin-utils/src/lib.rs#L2228`](/code/pallets/admin-utils/src/lib.rs#L2226-L2266) | +| `AdminUtils.sudo_set_burn_half_life` | [`pallets/admin-utils/src/lib.rs#L2186`](/code/pallets/admin-utils/src/lib.rs#L2184-L2222) | +| `AdminUtils.sudo_set_collateral_lock_share` | [`pallets/admin-utils/src/lib.rs#L2352`](/code/pallets/admin-utils/src/lib.rs#L2350-L2385) | +| `AdminUtils.sudo_set_collateral_drain_ratio` | [`pallets/admin-utils/src/lib.rs#L2395`](/code/pallets/admin-utils/src/lib.rs#L2393-L2434) | +| `AdminUtils.sudo_set_adjustment_alpha` | [`pallets/admin-utils/src/lib.rs#L462`](/code/pallets/admin-utils/src/lib.rs#L460-L486) | +| `AdminUtils.sudo_set_rho` | [`pallets/admin-utils/src/lib.rs#L625`](/code/pallets/admin-utils/src/lib.rs#L623-L645) | +| `AdminUtils.sudo_set_max_difficulty` | [`pallets/admin-utils/src/lib.rs#L345`](/code/pallets/admin-utils/src/lib.rs#L343-L371) | +| `AdminUtils.sudo_set_alpha_sigmoid_steepness` | [`pallets/admin-utils/src/lib.rs#L1644`](/code/pallets/admin-utils/src/lib.rs#L1642-L1676) | +| `AdminUtils.sudo_set_min_childkey_take_per_subnet` | [`pallets/admin-utils/src/lib.rs#L1217`](/code/pallets/admin-utils/src/lib.rs#L1215-L1249) | +| `AdminUtils.sudo_set_owner_immune_neuron_limit` | [`pallets/admin-utils/src/lib.rs#L1830`](/code/pallets/admin-utils/src/lib.rs#L1828-L1848) | +| `AdminUtils.sudo_set_alpha_values` | [`pallets/admin-utils/src/lib.rs#L1318`](/code/pallets/admin-utils/src/lib.rs#L1316-L1341) | +| `AdminUtils.sudo_set_commit_reveal_weights_enabled` | [`pallets/admin-utils/src/lib.rs#L1256`](/code/pallets/admin-utils/src/lib.rs#L1254-L1281) | +| `AdminUtils.sudo_set_liquid_alpha_enabled` | [`pallets/admin-utils/src/lib.rs#L1294`](/code/pallets/admin-utils/src/lib.rs#L1292-L1313) | +| `AdminUtils.sudo_set_network_pow_registration_allowed` | [`pallets/admin-utils/src/lib.rs#L740`](/code/pallets/admin-utils/src/lib.rs#L738-L746) | +| `AdminUtils.sudo_set_yuma3_enabled` | [`pallets/admin-utils/src/lib.rs#L1689`](/code/pallets/admin-utils/src/lib.rs#L1687-L1710) | +| `AdminUtils.sudo_set_bonds_reset_enabled` | [`pallets/admin-utils/src/lib.rs#L1723`](/code/pallets/admin-utils/src/lib.rs#L1721-L1744) | +| `AdminUtils.sudo_set_toggle_transfer` | [`pallets/admin-utils/src/lib.rs#L1482`](/code/pallets/admin-utils/src/lib.rs#L1480-L1502) | +| `AdminUtils.sudo_set_owner_cut_enabled` | [`pallets/admin-utils/src/lib.rs#L2272`](/code/pallets/admin-utils/src/lib.rs#L2270-L2290) | +| `AdminUtils.sudo_set_owner_cut_auto_lock_enabled` | [`pallets/admin-utils/src/lib.rs#L2296`](/code/pallets/admin-utils/src/lib.rs#L2294-L2314) | Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/set-mechanism-count.mdx b/docs/tx/set-mechanism-count.mdx index ac7cc32e8d..64b3022378 100644 --- a/docs/tx/set-mechanism-count.mdx +++ b/docs/tx/set-mechanism-count.mdx @@ -16,7 +16,7 @@ end-of-epoch admin freeze window. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | subnet owner | AdminUtils | [`AdminUtils.sudo_set_mechanism_count`](/code/pallets/admin-utils/src/lib.rs#L1878-L1900) | +| `coldkey` | subnet owner | AdminUtils | [`AdminUtils.sudo_set_mechanism_count`](/code/pallets/admin-utils/src/lib.rs#L1888-L1910) | ## Parameters @@ -68,7 +68,7 @@ result = sub.execute_tool("set_mechanism_count", {...}, wallet) ## On-chain implementation -`AdminUtils.sudo_set_mechanism_count` — [`pallets/admin-utils/src/lib.rs#L1880`](/code/pallets/admin-utils/src/lib.rs#L1878-L1900): +`AdminUtils.sudo_set_mechanism_count` — [`pallets/admin-utils/src/lib.rs#L1890`](/code/pallets/admin-utils/src/lib.rs#L1888-L1910): ```rust #[pallet::call_index(76)] diff --git a/docs/tx/set-subnet-emission-enabled.mdx b/docs/tx/set-subnet-emission-enabled.mdx index e7b75d4cad..b01d30ee5d 100644 --- a/docs/tx/set-subnet-emission-enabled.mdx +++ b/docs/tx/set-subnet-emission-enabled.mdx @@ -24,7 +24,7 @@ read. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | root (chain sudo) | AdminUtils | [`AdminUtils.sudo_set_subnet_emission_enabled`](/code/pallets/admin-utils/src/lib.rs#L2312-L2332), `Sudo.sudo` | +| `coldkey` | root (chain sudo) | AdminUtils | [`AdminUtils.sudo_set_subnet_emission_enabled`](/code/pallets/admin-utils/src/lib.rs#L2322-L2342), `Sudo.sudo` | ## Verify @@ -85,7 +85,7 @@ result = sub.execute_tool("set_subnet_emission_enabled", {...}, wallet) ## On-chain implementation -`AdminUtils.sudo_set_subnet_emission_enabled` — [`pallets/admin-utils/src/lib.rs#L2314`](/code/pallets/admin-utils/src/lib.rs#L2312-L2332): +`AdminUtils.sudo_set_subnet_emission_enabled` — [`pallets/admin-utils/src/lib.rs#L2324`](/code/pallets/admin-utils/src/lib.rs#L2322-L2342): ```rust #[pallet::call_index(94)] diff --git a/docs/tx/trim-subnet.mdx b/docs/tx/trim-subnet.mdx index dfd13d30e1..9bb457ef29 100644 --- a/docs/tx/trim-subnet.mdx +++ b/docs/tx/trim-subnet.mdx @@ -21,7 +21,7 @@ at or above the current UID count instead. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | subnet owner | AdminUtils | [`AdminUtils.sudo_trim_to_max_allowed_uids`](/code/pallets/admin-utils/src/lib.rs#L1932-L1954) | +| `coldkey` | subnet owner | AdminUtils | [`AdminUtils.sudo_trim_to_max_allowed_uids`](/code/pallets/admin-utils/src/lib.rs#L1942-L1964) | ## Parameters @@ -73,7 +73,7 @@ result = sub.execute_tool("trim_subnet", {...}, wallet) ## On-chain implementation -`AdminUtils.sudo_trim_to_max_allowed_uids` — [`pallets/admin-utils/src/lib.rs#L1934`](/code/pallets/admin-utils/src/lib.rs#L1932-L1954): +`AdminUtils.sudo_trim_to_max_allowed_uids` — [`pallets/admin-utils/src/lib.rs#L1944`](/code/pallets/admin-utils/src/lib.rs#L1942-L1964): ```rust #[pallet::call_index(78)] diff --git a/precompiles/src/balance.rs b/precompiles/src/balance.rs index af990b40ad..76f094ee92 100644 --- a/precompiles/src/balance.rs +++ b/precompiles/src/balance.rs @@ -1,5 +1,6 @@ use core::marker::PhantomData; +use alloc::vec::Vec; use frame_support::{ dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}, traits::{ConstU32, IsSubType}, diff --git a/precompiles/src/registry.rs b/precompiles/src/registry.rs index 8efd170e30..87681bfb58 100644 --- a/precompiles/src/registry.rs +++ b/precompiles/src/registry.rs @@ -1,5 +1,6 @@ use core::marker::PhantomData; +use alloc::string::String; use pallet_admin_utils::{PrecompileEnable, PrecompileEnum}; use pallet_evm::PrecompileHandle; use precompile_utils::{ diff --git a/website/apps/bittensor-website/public/catalog/errors.json b/website/apps/bittensor-website/public/catalog/errors.json index c7f211c80d..4ae02ca5ba 100644 --- a/website/apps/bittensor-website/public/catalog/errors.json +++ b/website/apps/bittensor-website/public/catalog/errors.json @@ -393,8 +393,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 795, - "url": "/code/pallets/proxy/src/lib.rs#L795", + "line": 809, + "url": "/code/pallets/proxy/src/lib.rs#L809", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1471,8 +1471,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 787, - "url": "/code/pallets/proxy/src/lib.rs#L787", + "line": 801, + "url": "/code/pallets/proxy/src/lib.rs#L801", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -2253,8 +2253,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 797, - "url": "/code/pallets/proxy/src/lib.rs#L797", + "line": 811, + "url": "/code/pallets/proxy/src/lib.rs#L811", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -3423,8 +3423,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 789, - "url": "/code/pallets/proxy/src/lib.rs#L789", + "line": 803, + "url": "/code/pallets/proxy/src/lib.rs#L803", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -3441,8 +3441,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 793, - "url": "/code/pallets/proxy/src/lib.rs#L793", + "line": 807, + "url": "/code/pallets/proxy/src/lib.rs#L807", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -3713,8 +3713,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 781, - "url": "/code/pallets/proxy/src/lib.rs#L781", + "line": 795, + "url": "/code/pallets/proxy/src/lib.rs#L795", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -3767,8 +3767,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 783, - "url": "/code/pallets/proxy/src/lib.rs#L783", + "line": 797, + "url": "/code/pallets/proxy/src/lib.rs#L797", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -4954,8 +4954,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 779, - "url": "/code/pallets/proxy/src/lib.rs#L779", + "line": 793, + "url": "/code/pallets/proxy/src/lib.rs#L793", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -5350,8 +5350,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 791, - "url": "/code/pallets/proxy/src/lib.rs#L791", + "line": 805, + "url": "/code/pallets/proxy/src/lib.rs#L805", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -5459,8 +5459,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 785, - "url": "/code/pallets/proxy/src/lib.rs#L785", + "line": 799, + "url": "/code/pallets/proxy/src/lib.rs#L799", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] diff --git a/website/apps/bittensor-website/public/catalog/intents.json b/website/apps/bittensor-website/public/catalog/intents.json index fa8bcb427a..e15ed75506 100644 --- a/website/apps/bittensor-website/public/catalog/intents.json +++ b/website/apps/bittensor-website/public/catalog/intents.json @@ -106,9 +106,9 @@ "pallet": "Proxy", "call": "add_proxy", "path": "pallets/proxy/src/lib.rs", - "line": 267, - "end_line": 276, - "url": "/code/pallets/proxy/src/lib.rs#L265-L276", + "line": 281, + "end_line": 290, + "url": "/code/pallets/proxy/src/lib.rs#L279-L290", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -875,9 +875,9 @@ "pallet": "Proxy", "call": "create_pure", "path": "pallets/proxy/src/lib.rs", - "line": 332, - "end_line": 364, - "url": "/code/pallets/proxy/src/lib.rs#L330-L364", + "line": 346, + "end_line": 378, + "url": "/code/pallets/proxy/src/lib.rs#L344-L378", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1103,9 +1103,9 @@ "pallet": "Proxy", "call": "proxy_announced", "path": "pallets/proxy/src/lib.rs", - "line": 549, - "end_line": 573, - "url": "/code/pallets/proxy/src/lib.rs#L540-L573", + "line": 563, + "end_line": 587, + "url": "/code/pallets/proxy/src/lib.rs#L554-L587", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1304,9 +1304,9 @@ "pallet": "Proxy", "call": "kill_pure", "path": "pallets/proxy/src/lib.rs", - "line": 384, - "end_line": 410, - "url": "/code/pallets/proxy/src/lib.rs#L382-L410", + "line": 398, + "end_line": 424, + "url": "/code/pallets/proxy/src/lib.rs#L396-L424", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1821,9 +1821,9 @@ "pallet": "Proxy", "call": "remove_proxies", "path": "pallets/proxy/src/lib.rs", - "line": 306, - "end_line": 310, - "url": "/code/pallets/proxy/src/lib.rs#L304-L310", + "line": 320, + "end_line": 324, + "url": "/code/pallets/proxy/src/lib.rs#L318-L324", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1871,9 +1871,9 @@ "pallet": "Proxy", "call": "remove_proxy", "path": "pallets/proxy/src/lib.rs", - "line": 287, - "end_line": 296, - "url": "/code/pallets/proxy/src/lib.rs#L285-L296", + "line": 301, + "end_line": 310, + "url": "/code/pallets/proxy/src/lib.rs#L299-L310", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -2751,279 +2751,279 @@ "pallet": "AdminUtils", "call": "sudo_set_tempo", "path": "pallets/admin-utils/src/lib.rs", - "line": 1039, - "end_line": 1043, - "url": "/code/pallets/admin-utils/src/lib.rs#L1028-L1043", + "line": 1049, + "end_line": 1053, + "url": "/code/pallets/admin-utils/src/lib.rs#L1038-L1053", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_immunity_period", "path": "pallets/admin-utils/src/lib.rs", - "line": 483, - "end_line": 509, - "url": "/code/pallets/admin-utils/src/lib.rs#L481-L509", + "line": 493, + "end_line": 519, + "url": "/code/pallets/admin-utils/src/lib.rs#L491-L519", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_min_allowed_weights", "path": "pallets/admin-utils/src/lib.rs", - "line": 516, - "end_line": 542, - "url": "/code/pallets/admin-utils/src/lib.rs#L514-L542", + "line": 526, + "end_line": 552, + "url": "/code/pallets/admin-utils/src/lib.rs#L524-L552", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_weights_version_key", "path": "pallets/admin-utils/src/lib.rs", - "line": 368, - "end_line": 396, - "url": "/code/pallets/admin-utils/src/lib.rs#L366-L396", + "line": 378, + "end_line": 406, + "url": "/code/pallets/admin-utils/src/lib.rs#L376-L406", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_activity_cutoff_factor", "path": "pallets/admin-utils/src/lib.rs", - "line": 688, - "end_line": 702, - "url": "/code/pallets/admin-utils/src/lib.rs#L686-L702", + "line": 698, + "end_line": 712, + "url": "/code/pallets/admin-utils/src/lib.rs#L696-L712", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_min_burn", "path": "pallets/admin-utils/src/lib.rs", - "line": 770, - "end_line": 802, - "url": "/code/pallets/admin-utils/src/lib.rs#L768-L802", + "line": 780, + "end_line": 812, + "url": "/code/pallets/admin-utils/src/lib.rs#L778-L812", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_max_burn", "path": "pallets/admin-utils/src/lib.rs", - "line": 809, - "end_line": 841, - "url": "/code/pallets/admin-utils/src/lib.rs#L807-L841", + "line": 819, + "end_line": 851, + "url": "/code/pallets/admin-utils/src/lib.rs#L817-L851", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_bonds_moving_average", "path": "pallets/admin-utils/src/lib.rs", - "line": 901, - "end_line": 933, - "url": "/code/pallets/admin-utils/src/lib.rs#L899-L933", + "line": 911, + "end_line": 943, + "url": "/code/pallets/admin-utils/src/lib.rs#L909-L943", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_bonds_penalty", "path": "pallets/admin-utils/src/lib.rs", - "line": 940, - "end_line": 964, - "url": "/code/pallets/admin-utils/src/lib.rs#L938-L964", + "line": 950, + "end_line": 974, + "url": "/code/pallets/admin-utils/src/lib.rs#L948-L974", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_serving_rate_limit", "path": "pallets/admin-utils/src/lib.rs", - "line": 285, - "end_line": 304, - "url": "/code/pallets/admin-utils/src/lib.rs#L283-L304", + "line": 295, + "end_line": 314, + "url": "/code/pallets/admin-utils/src/lib.rs#L293-L314", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_commit_reveal_weights_interval", "path": "pallets/admin-utils/src/lib.rs", - "line": 1383, - "end_line": 1410, - "url": "/code/pallets/admin-utils/src/lib.rs#L1381-L1410", + "line": 1393, + "end_line": 1420, + "url": "/code/pallets/admin-utils/src/lib.rs#L1391-L1420", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_max_allowed_uids", "path": "pallets/admin-utils/src/lib.rs", - "line": 549, - "end_line": 592, - "url": "/code/pallets/admin-utils/src/lib.rs#L547-L592", + "line": 559, + "end_line": 602, + "url": "/code/pallets/admin-utils/src/lib.rs#L557-L602", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_burn_increase_mult", "path": "pallets/admin-utils/src/lib.rs", - "line": 2218, - "end_line": 2256, - "url": "/code/pallets/admin-utils/src/lib.rs#L2216-L2256", + "line": 2228, + "end_line": 2266, + "url": "/code/pallets/admin-utils/src/lib.rs#L2226-L2266", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_burn_half_life", "path": "pallets/admin-utils/src/lib.rs", - "line": 2176, - "end_line": 2212, - "url": "/code/pallets/admin-utils/src/lib.rs#L2174-L2212", + "line": 2186, + "end_line": 2222, + "url": "/code/pallets/admin-utils/src/lib.rs#L2184-L2222", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_collateral_lock_share", "path": "pallets/admin-utils/src/lib.rs", - "line": 2342, - "end_line": 2375, - "url": "/code/pallets/admin-utils/src/lib.rs#L2340-L2375", + "line": 2352, + "end_line": 2385, + "url": "/code/pallets/admin-utils/src/lib.rs#L2350-L2385", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_collateral_drain_ratio", "path": "pallets/admin-utils/src/lib.rs", - "line": 2385, - "end_line": 2424, - "url": "/code/pallets/admin-utils/src/lib.rs#L2383-L2424", + "line": 2395, + "end_line": 2434, + "url": "/code/pallets/admin-utils/src/lib.rs#L2393-L2434", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_adjustment_alpha", "path": "pallets/admin-utils/src/lib.rs", - "line": 452, - "end_line": 476, - "url": "/code/pallets/admin-utils/src/lib.rs#L450-L476", + "line": 462, + "end_line": 486, + "url": "/code/pallets/admin-utils/src/lib.rs#L460-L486", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_rho", "path": "pallets/admin-utils/src/lib.rs", - "line": 615, - "end_line": 635, - "url": "/code/pallets/admin-utils/src/lib.rs#L613-L635", + "line": 625, + "end_line": 645, + "url": "/code/pallets/admin-utils/src/lib.rs#L623-L645", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_max_difficulty", "path": "pallets/admin-utils/src/lib.rs", - "line": 335, - "end_line": 361, - "url": "/code/pallets/admin-utils/src/lib.rs#L333-L361", + "line": 345, + "end_line": 371, + "url": "/code/pallets/admin-utils/src/lib.rs#L343-L371", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_alpha_sigmoid_steepness", "path": "pallets/admin-utils/src/lib.rs", - "line": 1634, - "end_line": 1666, - "url": "/code/pallets/admin-utils/src/lib.rs#L1632-L1666", + "line": 1644, + "end_line": 1676, + "url": "/code/pallets/admin-utils/src/lib.rs#L1642-L1676", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_min_childkey_take_per_subnet", "path": "pallets/admin-utils/src/lib.rs", - "line": 1207, - "end_line": 1239, - "url": "/code/pallets/admin-utils/src/lib.rs#L1205-L1239", + "line": 1217, + "end_line": 1249, + "url": "/code/pallets/admin-utils/src/lib.rs#L1215-L1249", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_owner_immune_neuron_limit", "path": "pallets/admin-utils/src/lib.rs", - "line": 1820, - "end_line": 1838, - "url": "/code/pallets/admin-utils/src/lib.rs#L1818-L1838", + "line": 1830, + "end_line": 1848, + "url": "/code/pallets/admin-utils/src/lib.rs#L1828-L1848", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_alpha_values", "path": "pallets/admin-utils/src/lib.rs", - "line": 1308, - "end_line": 1331, - "url": "/code/pallets/admin-utils/src/lib.rs#L1306-L1331", + "line": 1318, + "end_line": 1341, + "url": "/code/pallets/admin-utils/src/lib.rs#L1316-L1341", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_commit_reveal_weights_enabled", "path": "pallets/admin-utils/src/lib.rs", - "line": 1246, - "end_line": 1271, - "url": "/code/pallets/admin-utils/src/lib.rs#L1244-L1271", + "line": 1256, + "end_line": 1281, + "url": "/code/pallets/admin-utils/src/lib.rs#L1254-L1281", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_liquid_alpha_enabled", "path": "pallets/admin-utils/src/lib.rs", - "line": 1284, - "end_line": 1303, - "url": "/code/pallets/admin-utils/src/lib.rs#L1282-L1303", + "line": 1294, + "end_line": 1313, + "url": "/code/pallets/admin-utils/src/lib.rs#L1292-L1313", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_network_pow_registration_allowed", "path": "pallets/admin-utils/src/lib.rs", - "line": 730, - "end_line": 736, - "url": "/code/pallets/admin-utils/src/lib.rs#L728-L736", + "line": 740, + "end_line": 746, + "url": "/code/pallets/admin-utils/src/lib.rs#L738-L746", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_yuma3_enabled", "path": "pallets/admin-utils/src/lib.rs", - "line": 1679, - "end_line": 1700, - "url": "/code/pallets/admin-utils/src/lib.rs#L1677-L1700", + "line": 1689, + "end_line": 1710, + "url": "/code/pallets/admin-utils/src/lib.rs#L1687-L1710", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_bonds_reset_enabled", "path": "pallets/admin-utils/src/lib.rs", - "line": 1713, - "end_line": 1734, - "url": "/code/pallets/admin-utils/src/lib.rs#L1711-L1734", + "line": 1723, + "end_line": 1744, + "url": "/code/pallets/admin-utils/src/lib.rs#L1721-L1744", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_toggle_transfer", "path": "pallets/admin-utils/src/lib.rs", - "line": 1472, - "end_line": 1492, - "url": "/code/pallets/admin-utils/src/lib.rs#L1470-L1492", + "line": 1482, + "end_line": 1502, + "url": "/code/pallets/admin-utils/src/lib.rs#L1480-L1502", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_owner_cut_enabled", "path": "pallets/admin-utils/src/lib.rs", - "line": 2262, - "end_line": 2280, - "url": "/code/pallets/admin-utils/src/lib.rs#L2260-L2280", + "line": 2272, + "end_line": 2290, + "url": "/code/pallets/admin-utils/src/lib.rs#L2270-L2290", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" }, { "pallet": "AdminUtils", "call": "sudo_set_owner_cut_auto_lock_enabled", "path": "pallets/admin-utils/src/lib.rs", - "line": 2286, - "end_line": 2304, - "url": "/code/pallets/admin-utils/src/lib.rs#L2284-L2304", + "line": 2296, + "end_line": 2314, + "url": "/code/pallets/admin-utils/src/lib.rs#L2294-L2314", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" } ] @@ -3134,9 +3134,9 @@ "pallet": "AdminUtils", "call": "sudo_set_mechanism_count", "path": "pallets/admin-utils/src/lib.rs", - "line": 1880, - "end_line": 1900, - "url": "/code/pallets/admin-utils/src/lib.rs#L1878-L1900", + "line": 1890, + "end_line": 1910, + "url": "/code/pallets/admin-utils/src/lib.rs#L1888-L1910", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" } ] @@ -3400,9 +3400,9 @@ "pallet": "AdminUtils", "call": "sudo_set_subnet_emission_enabled", "path": "pallets/admin-utils/src/lib.rs", - "line": 2314, - "end_line": 2332, - "url": "/code/pallets/admin-utils/src/lib.rs#L2312-L2332", + "line": 2324, + "end_line": 2342, + "url": "/code/pallets/admin-utils/src/lib.rs#L2322-L2342", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" } ] @@ -4183,9 +4183,9 @@ "pallet": "AdminUtils", "call": "sudo_trim_to_max_allowed_uids", "path": "pallets/admin-utils/src/lib.rs", - "line": 1934, - "end_line": 1954, - "url": "/code/pallets/admin-utils/src/lib.rs#L1932-L1954", + "line": 1944, + "end_line": 1964, + "url": "/code/pallets/admin-utils/src/lib.rs#L1942-L1964", "raw_url": "/code/raw/pallets/admin-utils/src/lib.rs" } ] diff --git a/website/apps/bittensor-website/public/catalog/reads.json b/website/apps/bittensor-website/public/catalog/reads.json index 7fca8b997c..74a5682bea 100644 --- a/website/apps/bittensor-website/public/catalog/reads.json +++ b/website/apps/bittensor-website/public/catalog/reads.json @@ -71,8 +71,8 @@ "container": "SubtensorModule", "name": "AssociatedEvmAddress", "path": "pallets/subtensor/src/lib.rs", - "line": 2904, - "url": "/code/pallets/subtensor/src/lib.rs#L2904", + "line": 2910, + "url": "/code/pallets/subtensor/src/lib.rs#L2910", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -249,8 +249,8 @@ "container": "SubtensorModule", "name": "LastUpdate", "path": "pallets/subtensor/src/lib.rs", - "line": 2547, - "url": "/code/pallets/subtensor/src/lib.rs#L2547", + "line": 2553, + "url": "/code/pallets/subtensor/src/lib.rs#L2553", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -275,9 +275,9 @@ "container": "SubnetInfoRuntimeApi", "name": "get_next_epoch_start_block", "path": "pallets/subtensor/src/coinbase/run_coinbase.rs", - "line": 1257, - "end_line": 1271, - "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1257-L1271", + "line": 1258, + "end_line": 1272, + "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272", "raw_url": "/code/raw/pallets/subtensor/src/coinbase/run_coinbase.rs" } ] @@ -304,8 +304,8 @@ "container": "SubtensorModule", "name": "Bonds", "path": "pallets/subtensor/src/lib.rs", - "line": 2575, - "url": "/code/pallets/subtensor/src/lib.rs#L2575", + "line": 2581, + "url": "/code/pallets/subtensor/src/lib.rs#L2581", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -797,9 +797,9 @@ "container": "SubnetInfoRuntimeApi", "name": "get_next_epoch_start_block", "path": "pallets/subtensor/src/coinbase/run_coinbase.rs", - "line": 1257, - "end_line": 1271, - "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1257-L1271", + "line": 1258, + "end_line": 1272, + "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272", "raw_url": "/code/raw/pallets/subtensor/src/coinbase/run_coinbase.rs" } ] @@ -884,8 +884,8 @@ "container": "SubtensorModule", "name": "IdentitiesV2", "path": "pallets/subtensor/src/lib.rs", - "line": 2637, - "url": "/code/pallets/subtensor/src/lib.rs#L2637", + "line": 2643, + "url": "/code/pallets/subtensor/src/lib.rs#L2643", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -936,8 +936,8 @@ "container": "SubtensorModule", "name": "IdentitiesV2", "path": "pallets/subtensor/src/lib.rs", - "line": 2637, - "url": "/code/pallets/subtensor/src/lib.rs#L2637", + "line": 2643, + "url": "/code/pallets/subtensor/src/lib.rs#L2643", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -1026,8 +1026,8 @@ "container": "SubtensorModule", "name": "SubnetLeases", "path": "pallets/subtensor/src/lib.rs", - "line": 2922, - "url": "/code/pallets/subtensor/src/lib.rs#L2922", + "line": 2928, + "url": "/code/pallets/subtensor/src/lib.rs#L2928", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -1048,8 +1048,8 @@ "container": "SubtensorModule", "name": "SubnetLeases", "path": "pallets/subtensor/src/lib.rs", - "line": 2922, - "url": "/code/pallets/subtensor/src/lib.rs#L2922", + "line": 2928, + "url": "/code/pallets/subtensor/src/lib.rs#L2928", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -1126,8 +1126,8 @@ "container": "SubtensorModule", "name": "MechanismCountCurrent", "path": "pallets/subtensor/src/lib.rs", - "line": 2996, - "url": "/code/pallets/subtensor/src/lib.rs#L2996", + "line": 3002, + "url": "/code/pallets/subtensor/src/lib.rs#L3002", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -1152,8 +1152,8 @@ "container": "SubtensorModule", "name": "MechanismEmissionSplit", "path": "pallets/subtensor/src/lib.rs", - "line": 3001, - "url": "/code/pallets/subtensor/src/lib.rs#L3001", + "line": 3007, + "url": "/code/pallets/subtensor/src/lib.rs#L3007", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -1398,9 +1398,9 @@ "container": "SubnetInfoRuntimeApi", "name": "get_next_epoch_start_block", "path": "pallets/subtensor/src/coinbase/run_coinbase.rs", - "line": 1257, - "end_line": 1271, - "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1257-L1271", + "line": 1258, + "end_line": 1272, + "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272", "raw_url": "/code/raw/pallets/subtensor/src/coinbase/run_coinbase.rs" } ] @@ -1507,8 +1507,8 @@ "container": "Proxy", "name": "Proxies", "path": "pallets/proxy/src/lib.rs", - "line": 811, - "url": "/code/pallets/proxy/src/lib.rs#L811", + "line": 825, + "url": "/code/pallets/proxy/src/lib.rs#L825", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1591,8 +1591,8 @@ "container": "SubtensorModule", "name": "RevealPeriodEpochs", "path": "pallets/subtensor/src/lib.rs", - "line": 2750, - "url": "/code/pallets/subtensor/src/lib.rs#L2750", + "line": 2756, + "url": "/code/pallets/subtensor/src/lib.rs#L2756", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -2023,8 +2023,8 @@ "container": "SubtensorModule", "name": "Uids", "path": "pallets/subtensor/src/lib.rs", - "line": 2500, - "url": "/code/pallets/subtensor/src/lib.rs#L2500", + "line": 2506, + "url": "/code/pallets/subtensor/src/lib.rs#L2506", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -2200,8 +2200,8 @@ "container": "SubtensorModule", "name": "SubnetIdentitiesV3", "path": "pallets/subtensor/src/lib.rs", - "line": 2642, - "url": "/code/pallets/subtensor/src/lib.rs#L2642", + "line": 2648, + "url": "/code/pallets/subtensor/src/lib.rs#L2648", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -2222,8 +2222,8 @@ "container": "SubtensorModule", "name": "SubnetIdentitiesV3", "path": "pallets/subtensor/src/lib.rs", - "line": 2642, - "url": "/code/pallets/subtensor/src/lib.rs#L2642", + "line": 2648, + "url": "/code/pallets/subtensor/src/lib.rs#L2648", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -2357,8 +2357,8 @@ "container": "SubtensorModule", "name": "TimelockedWeightCommits", "path": "pallets/subtensor/src/lib.rs", - "line": 2698, - "url": "/code/pallets/subtensor/src/lib.rs#L2698", + "line": 2704, + "url": "/code/pallets/subtensor/src/lib.rs#L2704", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -2440,8 +2440,8 @@ "container": "SubtensorModule", "name": "Uids", "path": "pallets/subtensor/src/lib.rs", - "line": 2500, - "url": "/code/pallets/subtensor/src/lib.rs#L2500", + "line": 2506, + "url": "/code/pallets/subtensor/src/lib.rs#L2506", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] @@ -2466,9 +2466,9 @@ "container": "BetaBasketRuntimeApi", "name": "get_validator_basket", "path": "pallets/subtensor/src/staking/basket_views.rs", - "line": 77, - "end_line": 85, - "url": "/code/pallets/subtensor/src/staking/basket_views.rs#L77-L85", + "line": 102, + "end_line": 110, + "url": "/code/pallets/subtensor/src/staking/basket_views.rs#L102-L110", "raw_url": "/code/raw/pallets/subtensor/src/staking/basket_views.rs" } ] @@ -2576,8 +2576,8 @@ "container": "SubtensorModule", "name": "Weights", "path": "pallets/subtensor/src/lib.rs", - "line": 2562, - "url": "/code/pallets/subtensor/src/lib.rs#L2562", + "line": 2568, + "url": "/code/pallets/subtensor/src/lib.rs#L2568", "raw_url": "/code/raw/pallets/subtensor/src/lib.rs" } ] From fb0843b113fbfed2eafb57dd62e3f313c23a7b0e Mon Sep 17 00:00:00 2001 From: unarbos Date: Thu, 6 Aug 2026 09:24:03 -0300 Subject: [PATCH 38/58] test: get_shares regression coverage for MinerBurned independence Co-authored-by: Cursor --- .../subtensor/src/tests/subnet_emissions.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/pallets/subtensor/src/tests/subnet_emissions.rs b/pallets/subtensor/src/tests/subnet_emissions.rs index acd038c29f..756bfbe8c0 100644 --- a/pallets/subtensor/src/tests/subnet_emissions.rs +++ b/pallets/subtensor/src/tests/subnet_emissions.rs @@ -192,6 +192,38 @@ fn get_shares_ignores_root_prop_storage_when_prices_and_burns_match() { }); } +/// Regression: `get_shares` must be independent of `MinerBurned`. The removed +/// formula weighted each price share by (1 - miner_burned) and renormalized, +/// so under it a burn split of 0 : 1 yields shares 1 : 0 and a split of +/// 0.25 : 0.75 yields 0.75 : 0.25. This test fails if that weighting is +/// reintroduced. +#[test] +fn get_shares_independent_of_miner_burned() { + // (burn_n1, burn_n2): boundary values and a non-boundary split. + for (burn_n1, burn_n2) in [(0.0, 1.0), (1.0, 0.0), (0.25, 0.75)] { + new_test_ext(1).execute_with(|| { + let owner_hotkey = U256::from(90); + let owner_coldkey = U256::from(91); + let n1 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + let n2 = add_dynamic_network(&owner_hotkey, &owner_coldkey); + + // Equal prices; only the miner-burn values differ. + SubnetMovingPrice::::insert(n1, i96f32(1.0)); + SubnetMovingPrice::::insert(n2, i96f32(1.0)); + MinerBurned::::insert(n1, U96F32::saturating_from_num(burn_n1)); + MinerBurned::::insert(n2, U96F32::saturating_from_num(burn_n2)); + + let shares = SubtensorModule::get_shares(&[n1, n2]); + let s1 = shares.get(&n1).copied().unwrap().to_num::(); + let s2 = shares.get(&n2).copied().unwrap().to_num::(); + + assert_abs_diff_eq!(s1, 0.5_f64, epsilon = 1e-9); + assert_abs_diff_eq!(s2, 0.5_f64, epsilon = 1e-9); + assert_abs_diff_eq!(s1 + s2, 1.0_f64, epsilon = 1e-9); + }); + } +} + /// Empty candidate set: no panic, empty map, bar stays unset. #[test] fn emission_gate_empty_set_no_panic() { From e5aada8a6f22ba1845c86a99bb3b3f4f5907e9ac Mon Sep 17 00:00:00 2001 From: unarbos Date: Thu, 6 Aug 2026 09:43:36 -0300 Subject: [PATCH 39/58] chore: add TotalVotingPower to generated SDK metadata; regen namespaces stub Co-authored-by: Cursor --- sdk/python/bittensor/_generated/storage.py | 1 + sdk/python/bittensor/namespaces.pyi | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/sdk/python/bittensor/_generated/storage.py b/sdk/python/bittensor/_generated/storage.py index 06be5cec81..a38f662944 100644 --- a/sdk/python/bittensor/_generated/storage.py +++ b/sdk/python/bittensor/_generated/storage.py @@ -252,6 +252,7 @@ class SubtensorModule: NetworkRegistrationQueue = Item('SubtensorModule', 'NetworkRegistrationQueue', 'Vec') NetworkRegistrationLockId = Item('SubtensorModule', 'NetworkRegistrationLockId', 'u32') VotingPower = Item('SubtensorModule', 'VotingPower', 'u64') + TotalVotingPower = Item('SubtensorModule', 'TotalVotingPower', 'u64') VotingPowerTrackingEnabled = Item('SubtensorModule', 'VotingPowerTrackingEnabled', 'bool') VotingPowerDisableAtBlock = Item('SubtensorModule', 'VotingPowerDisableAtBlock', 'u64') VotingPowerEmaAlpha = Item('SubtensorModule', 'VotingPowerEmaAlpha', 'u64') diff --git a/sdk/python/bittensor/namespaces.pyi b/sdk/python/bittensor/namespaces.pyi index e3d1c291f2..dde7d8d1d0 100644 --- a/sdk/python/bittensor/namespaces.pyi +++ b/sdk/python/bittensor/namespaces.pyi @@ -435,6 +435,18 @@ class Staking(_ReadNamespace): async def stake(self, coldkey_ss58: str, hotkey_ss58: str, netuid: int, *, block: Optional[int] = None) -> Balance: """Alpha staked by a coldkey to a hotkey on a subnet (TAO when netuid is 0).""" + async def stake_availability(self, coldkey_ss58: str, netuid: int, *, block: Optional[int] = None) -> dict: + """Free vs locked stake for a coldkey on one subnet. + + `locked` is conviction-locked mass (plus any miner collateral reserved + against the coldkey on that subnet). `available` is what can still be + unstaked or transferred without moving lock mass. Both are denominated in + the subnet's own currency (TAO on netuid 0). + """ + + async def stake_availability_for_coldkey(self, coldkey_ss58: str, netuids: list[int], *, block: Optional[int] = None) -> list[dict]: + """Free vs locked stake for a coldkey across many subnets (one runtime call).""" + async def stake_for_coldkey(self, coldkey_ss58: str, *, block: Optional[int] = None) -> list[StakePosition]: """Every stake position held by a coldkey, across all hotkeys and subnets. @@ -490,8 +502,9 @@ class Staking(_ReadNamespace): The `(netuid, weight)` pairs its root dividends are deployed into each epoch, exactly as stored (u16, max-upscaled), plus each destination's normalized `share` of the total. Netuid 0 means "hold as TAO / root - stake". An empty list means no custom weights are set; dividends accrue - 100% into the fund's root (TAO cash) slot. + stake". An empty list means no custom weights are set; the fund is + uncurated and each subnet's dividend accumulates in place on that + subnet, trade-free (no sell, no redeploy). """ class Subnets(_ReadNamespace): From 8c5174fb4474dfbc18457b9d7529e663cb69478a Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Fri, 7 Aug 2026 11:12:45 -0700 Subject: [PATCH 40/58] add migration --- clones/js-tests/package.json | 3 +- .../tests/test-storage-bloat-migration.ts | 339 ++++++++++++++++++ .../subtensor/src/coinbase/run_coinbase.rs | 6 +- pallets/subtensor/src/macros/hooks.rs | 16 +- .../migrations/migrate_storage_bloat_v2.rs | 228 ++++++++++++ pallets/subtensor/src/migrations/mod.rs | 1 + pallets/subtensor/src/swap/swap_hotkey.rs | 11 +- pallets/subtensor/src/tests/migration.rs | 145 ++++++++ pallets/swap/src/pallet/hooks.rs | 7 +- pallets/swap/src/pallet/impls.rs | 8 +- .../migrations/migrate_storage_cleanup_v2.rs | 70 ++++ pallets/swap/src/pallet/migrations/mod.rs | 1 + pallets/swap/src/pallet/mod.rs | 3 +- pallets/swap/src/pallet/tests.rs | 62 ++++ runtime/src/lib.rs | 2 +- 15 files changed, 885 insertions(+), 17 deletions(-) create mode 100644 clones/js-tests/tests/test-storage-bloat-migration.ts create mode 100644 pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs create mode 100644 pallets/swap/src/pallet/migrations/migrate_storage_cleanup_v2.rs diff --git a/clones/js-tests/package.json b/clones/js-tests/package.json index a554fe8372..ed889dc1ea 100644 --- a/clones/js-tests/package.json +++ b/clones/js-tests/package.json @@ -26,7 +26,8 @@ "test:testnet-unlock-rate": "tsx tests/testnet-unlock-rate-read.ts", "test:testnet-maturity-rate": "tsx tests/testnet-maturity-rate-read.ts", "test:hotkey-swap-and-proxy-stake": "tsx tests/test-hotkey-swap-and-proxy-stake.ts", - "test:proxy-filter-security-regressions": "tsx tests/test-proxy-filter-security-regressions.ts" + "test:proxy-filter-security-regressions": "tsx tests/test-proxy-filter-security-regressions.ts", + "test:storage-bloat-migration": "tsx tests/test-storage-bloat-migration.ts" }, "dependencies": { "@polkadot/api": "^16.4.9", diff --git a/clones/js-tests/tests/test-storage-bloat-migration.ts b/clones/js-tests/tests/test-storage-bloat-migration.ts new file mode 100644 index 0000000000..5212d998d8 --- /dev/null +++ b/clones/js-tests/tests/test-storage-bloat-migration.ts @@ -0,0 +1,339 @@ +import assert from "node:assert/strict"; + +import { xxhashAsHex } from "@polkadot/util-crypto"; + +import { connectApi } from "../lib/api.js"; +import { createTempLogger } from "../lib/file-log.js"; + +const WS_ENDPOINT = process.env.WS_ENDPOINT ?? "ws://127.0.0.1:9944"; +const TARGET_SPEC_VERSION = BigInt(process.env.TARGET_SPEC_VERSION ?? 444); +const PAGE_SIZE = Number(process.env.STORAGE_MIGRATION_PAGE_SIZE ?? 1000); +const MAX_HEAD_GAP_MS = Number(process.env.MAX_HEAD_GAP_MS ?? 30_000); +const MIGRATION_TIMEOUT_MS = Number(process.env.MIGRATION_TIMEOUT_MS ?? 60 * 60 * 1000); +const MIGRATION_NAME = "migrate_storage_bloat_v2"; +const logger = createTempLogger("storage-bloat-migration.log"); + +const SUBTENSOR_CLEAR = [ + "TotalHotkeyStake", + "PendingdHotkeyEmission", + "PendingdHotkeyEmissionUntouchable", + "LastHotkeyEmissionDrain", + "StakeDeltaSinceLastEmissionDrain", + "TotalColdkeyStake", + "LastAddStakeIncrease", + "ColdkeyArbitrationBlock", +] as const; + +const SUBTENSOR_ZERO = [ + "Alpha", + "TotalHotkeyShares", + "TotalHotkeyAlpha", + "TotalHotkeyAlphaLastEpoch", + "StakingHotkeys", +] as const; + +const SUBTENSOR_ROOT_AGE = "LastColdkeyHotkeyStakeBlock"; + +const SWAP_CLEAR = [ + "AlphaSqrtPrice", + "CurrentTick", + "EnabledUserLiquidity", + "FeeGlobalTao", + "FeeGlobalAlpha", + "LastPositionId", + "ScrapReservoirTao", + "ScrapReservoirAlpha", + "Ticks", + "TickIndexBitmapWords", + "SwapV3Initialized", + "CurrentLiquidity", + "Positions", +] as const; + +const SWAP_ZERO = ["BalancerTaoReservoir", "BalancerAlphaReservoir"] as const; + +type PrefixStats = { + count: number; + zero: number; + nonzero: number; +}; + +type HeadSample = { + number: bigint; + arrivalMs: number; +}; + +function prefix(pallet: string, storage: string): string { + return `${xxhashAsHex(pallet, 128)}${xxhashAsHex(storage, 128).slice(2)}`; +} + +function isAllZero(valueHex: string): boolean { + return valueHex.length > 2 && /^0x0+$/.test(valueHex); +} + +function percentile(values: number[], fraction: number): number { + assert.ok(values.length > 0, "cannot calculate a percentile without samples"); + const sorted = [...values].sort((left, right) => left - right); + return sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * fraction))]; +} + +function gaps(samples: HeadSample[]): number[] { + return samples.slice(1).map((sample, index) => sample.arrivalMs - samples[index].arrivalMs); +} + +async function scanPrefix( + api: any, + pallet: string, + storage: string, + atHash: any, + checkHalt: () => void, +): Promise { + const storagePrefix = prefix(pallet, storage); + let startKey: any = undefined; + let count = 0; + let zero = 0; + let pages = 0; + + for (;;) { + checkHalt(); + const keys: any[] = await api.rpc.state.getKeysPaged( + storagePrefix, + PAGE_SIZE, + startKey, + atHash, + ); + if (keys.length === 0) break; + + const changeSets: any = await api.rpc.state.queryStorageAt(keys, atHash); + const values = new Map(); + if ( + Array.isArray(changeSets) && + changeSets.length === keys.length && + changeSets.every((value) => typeof value?.isSome === "boolean") + ) { + for (let index = 0; index < keys.length; index += 1) { + const maybeValue = changeSets[index]; + values.set( + keys[index].toHex().toLowerCase(), + maybeValue.isSome ? maybeValue.unwrap().toHex() : "0x", + ); + } + } else { + const decodedSets = changeSets.changes ? [changeSets] : Array.from(changeSets); + for (const changeSet of decodedSets as any[]) { + const changes = + typeof changeSet.changes === "function" ? changeSet.changes() : changeSet.changes; + for (const [key, maybeValue] of changes) { + values.set( + key.toHex().toLowerCase(), + maybeValue.isSome ? maybeValue.unwrap().toHex() : "0x", + ); + } + } + } + + for (const key of keys) { + if (isAllZero(values.get(key.toHex().toLowerCase()) ?? "0x")) zero += 1; + } + count += keys.length; + pages += 1; + startKey = keys.at(-1); + if (pages === 1 || pages % 200 === 0) { + await logger.info( + `scan pallet=${pallet} storage=${storage} pages=${pages} keys=${count} zero=${zero}`, + ); + } + } + + const result = { count, zero, nonzero: count - zero }; + await logger.info(`PREFIX ${pallet}.${storage} ${JSON.stringify(result)}`); + return result; +} + +async function snapshot( + api: any, + atHash: any, + checkHalt: () => void, +): Promise> { + const result = new Map(); + for (const name of SUBTENSOR_CLEAR) { + result.set( + `SubtensorModule.${name}`, + await scanPrefix(api, "SubtensorModule", name, atHash, checkHalt), + ); + } + for (const name of SUBTENSOR_ZERO) { + result.set( + `SubtensorModule.${name}`, + await scanPrefix(api, "SubtensorModule", name, atHash, checkHalt), + ); + } + result.set( + `SubtensorModule.${SUBTENSOR_ROOT_AGE}`, + await scanPrefix(api, "SubtensorModule", SUBTENSOR_ROOT_AGE, atHash, checkHalt), + ); + for (const name of SWAP_CLEAR) { + result.set(`Swap.${name}`, await scanPrefix(api, "Swap", name, atHash, checkHalt)); + } + for (const name of SWAP_ZERO) { + result.set(`Swap.${name}`, await scanPrefix(api, "Swap", name, atHash, checkHalt)); + } + return result; +} + +function assertCleanup(before: Map, after: Map): void { + for (const name of SUBTENSOR_CLEAR) { + const key = `SubtensorModule.${name}`; + assert.ok((before.get(key)?.count ?? 0) > 0, `${key} had no mainnet rows before migration`); + assert.equal(after.get(key)?.count, 0, `${key} was not fully removed`); + } + + for (const name of SUBTENSOR_ZERO) { + const key = `SubtensorModule.${name}`; + const pre = before.get(key)!; + const post = after.get(key)!; + assert.ok(pre.zero > 0, `${key} had no zero rows to exercise the migration`); + assert.ok(pre.nonzero > 0, `${key} had no nonzero rows to preserve`); + assert.equal(post.zero, 0, `${key} retained explicit zero rows`); + assert.ok(post.nonzero > 0, `${key} lost all nonzero rows`); + } + + const rootAgeKey = `SubtensorModule.${SUBTENSOR_ROOT_AGE}`; + assert.ok((before.get(rootAgeKey)?.count ?? 0) > 0, `${rootAgeKey} had no rows before migration`); + assert.deepEqual(after.get(rootAgeKey), before.get(rootAgeKey), `${rootAgeKey} changed`); + + for (const name of SWAP_CLEAR) { + const key = `Swap.${name}`; + assert.ok((before.get(key)?.count ?? 0) > 0, `${key} had no mainnet rows before migration`); + assert.equal(after.get(key)?.count, 0, `${key} was not fully removed`); + } + + for (const name of SWAP_ZERO) { + const key = `Swap.${name}`; + assert.ok((before.get(key)?.zero ?? 0) > 0, `${key} had no zero rows before migration`); + assert.equal(after.get(key)?.zero, 0, `${key} retained explicit zero rows`); + } +} + +async function main(): Promise { + await logger.start(); + const api = await connectApi(WS_ENDPOINT, { log: (...args) => logger.info(...args) }); + const samples: HeadSample[] = []; + let lastHeadAt = Date.now(); + let lastLoggedHead = -1n; + + const unsubscribe = await api.rpc.chain.subscribeNewHeads((header: any) => { + const arrivalMs = Date.now(); + const number = BigInt(header.number.toString()); + samples.push({ number, arrivalMs }); + lastHeadAt = arrivalMs; + }); + + const checkHalt = (): void => { + const gap = Date.now() - lastHeadAt; + assert.ok(gap <= MAX_HEAD_GAP_MS, `block production halted for ${gap}ms`); + }; + + try { + const initialRuntime = await api.rpc.state.getRuntimeVersion(); + assert.ok( + BigInt(initialRuntime.specVersion.toString()) < TARGET_SPEC_VERSION, + `expected a pre-upgrade runtime, got spec ${initialRuntime.specVersion.toString()}`, + ); + const beforeHeader = await api.rpc.chain.getHeader(); + const beforeHash = beforeHeader.hash; + const rootUnlockInterval = BigInt( + (await (api.query.subtensorModule as any).rootStakeUnlockInterval.at(beforeHash)).toString(), + ); + assert.equal(rootUnlockInterval, 0n, "root stake hold is enabled; root-age cleanup is unsafe"); + + await logger.info( + `baseline block=${beforeHeader.number.toString()} hash=${beforeHash.toString()} spec=${initialRuntime.specVersion.toString()}`, + ); + const before = await snapshot(api, beforeHash, checkHalt); + await logger.info("READY_FOR_RUNTIME_UPGRADE"); + + const startedAt = Date.now(); + let upgradeDetectedAt = 0; + let upgradeBlock = 0n; + let completionBlock = 0n; + for (;;) { + checkHalt(); + assert.ok(Date.now() - startedAt <= MIGRATION_TIMEOUT_MS, "migration timed out"); + + const header = await api.rpc.chain.getHeader(); + const block = BigInt(header.number.toString()); + const runtime = await api.rpc.state.getRuntimeVersion(); + const spec = BigInt(runtime.specVersion.toString()); + if (spec >= TARGET_SPEC_VERSION && upgradeDetectedAt === 0) { + upgradeDetectedAt = Date.now(); + upgradeBlock = block; + await logger.info(`UPGRADE_DETECTED block=${block} spec=${spec}`); + } + + if (upgradeDetectedAt !== 0) { + const marker = await (api.query.subtensorModule as any).hasMigrationRun(MIGRATION_NAME); + const progress: any = await api.rpc.state.getStorage( + prefix("SubtensorModule", "StorageBloatCleanupMigration"), + ); + if (block >= lastLoggedHead + 10n || marker.isTrue) { + await logger.info( + `progress block=${block} marker=${marker.toString()} cursor_present=${progress.isSome}`, + ); + lastLoggedHead = block; + } + if (marker.isTrue && progress.isNone) { + completionBlock = block; + break; + } + } + + await new Promise((resolve) => setTimeout(resolve, 2_000)); + } + + while ((samples.at(-1)?.number ?? 0n) < completionBlock + 10n) { + checkHalt(); + await new Promise((resolve) => setTimeout(resolve, 1_000)); + } + + const afterHeader = await api.rpc.chain.getHeader(); + const afterHash = afterHeader.hash; + const after = await snapshot(api, afterHash, checkHalt); + assertCleanup(before, after); + + const baselineSamples = samples.filter((sample) => sample.arrivalMs < upgradeDetectedAt); + const migrationSamples = samples.filter( + (sample) => sample.number >= upgradeBlock && sample.number <= completionBlock + 10n, + ); + const baselineGaps = gaps(baselineSamples); + const migrationGaps = gaps(migrationSamples); + assert.ok(baselineGaps.length >= 5, "not enough baseline block-time samples"); + assert.ok(migrationGaps.length >= 10, "not enough migration block-time samples"); + const baselineMedian = percentile(baselineGaps, 0.5); + const migrationMedian = percentile(migrationGaps, 0.5); + const migrationP95 = percentile(migrationGaps, 0.95); + const migrationMax = Math.max(...migrationGaps); + assert.ok(migrationMax <= MAX_HEAD_GAP_MS, `maximum migration head gap was ${migrationMax}ms`); + assert.ok( + migrationMedian <= Math.max(6_000, baselineMedian * 3), + `median head gap regressed from ${baselineMedian}ms to ${migrationMedian}ms`, + ); + + await logger.info( + `TIMING baseline_median_ms=${baselineMedian} migration_median_ms=${migrationMedian} migration_p95_ms=${migrationP95} migration_max_ms=${migrationMax}`, + ); + await logger.info( + `PASS upgrade_block=${upgradeBlock} completion_block=${completionBlock} migration_blocks=${completionBlock - upgradeBlock + 1n} final_block=${afterHeader.number.toString()}`, + ); + } finally { + unsubscribe(); + await api.disconnect(); + await logger.flush(); + } +} + +main().catch(async (error) => { + await logger.error(error); + await logger.flush(); + process.exit(1); +}); diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index d8fa2af0eb..49df8ed27c 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -833,7 +833,11 @@ impl Pallet { }); } let total_hotkey_alpha = TotalHotkeyAlpha::::get(&hotkey, netuid); - TotalHotkeyAlphaLastEpoch::::insert(hotkey, netuid, total_hotkey_alpha); + if total_hotkey_alpha == AlphaBalance::ZERO { + TotalHotkeyAlphaLastEpoch::::remove(hotkey, netuid); + } else { + TotalHotkeyAlphaLastEpoch::::insert(hotkey, netuid, total_hotkey_alpha); + } } // Distribute root alpha divs. Same ownership rule: full root emission diff --git a/pallets/subtensor/src/macros/hooks.rs b/pallets/subtensor/src/macros/hooks.rs index ba828ef298..4bbedb0e92 100644 --- a/pallets/subtensor/src/macros/hooks.rs +++ b/pallets/subtensor/src/macros/hooks.rs @@ -197,7 +197,10 @@ mod hooks { // Kill the stale quantile-derived emission gate bar so the // rank-32 bar (DefaultEmissionBarRank) applies from the first // recompute after the upgrade instead of the next cadence boundary. - .saturating_add(migrations::migrate_reset_emission_gate_bar::migrate_reset_emission_gate_bar::()); + .saturating_add(migrations::migrate_reset_emission_gate_bar::migrate_reset_emission_gate_bar::()) + // Schedule the large storage-GC sweep. Actual work is bounded by the remaining + // on_idle weight over subsequent blocks. + .saturating_add(migrations::migrate_storage_bloat_v2::kickoff_storage_bloat_cleanup::()); weight } @@ -237,6 +240,17 @@ mod hooks { ); } + // Storage GC is independent from beta-basket conversion, but both are large. Let the + // state-sensitive seed finish first and then consume only otherwise-unused block + // weight, so normal extrinsics and dissolution work retain priority. + if !seed_in_progress && weight.all_lt(limit) { + weight.saturating_accrue( + migrations::migrate_storage_bloat_v2::continue_storage_bloat_cleanup::( + limit.saturating_sub(weight), + ), + ); + } + weight } } diff --git a/pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs b/pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs new file mode 100644 index 0000000000..6921d35383 --- /dev/null +++ b/pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs @@ -0,0 +1,228 @@ +use super::*; +use codec::{Decode, DecodeWithMemTracking, Encode}; +use frame_support::{storage_alias, traits::Get, weights::Weight}; +use scale_info::TypeInfo; +use scale_info::prelude::string::String; +use sp_io::{hashing::twox_128, storage}; +use sp_std::vec::Vec; + +const MIGRATION_NAME: &[u8] = b"migrate_storage_bloat_v2"; + +#[derive(Clone, Copy, PartialEq, Eq)] +enum CleanupMode { + Clear, + ClearIfZero, +} + +#[derive(Clone, Copy)] +struct CleanupTarget { + pallet: &'static str, + storage: &'static str, + mode: CleanupMode, +} + +// The undeclared prefixes are dead pre-dTAO state. The remaining targets use ValueQuery (or an +// OptionQuery whose consumer treats a missing value as zero), so deleting a zero/default row does +// not change the value observed by runtime callers. +const TARGETS: &[CleanupTarget] = &[ + CleanupTarget { + pallet: "SubtensorModule", + storage: "TotalHotkeyStake", + mode: CleanupMode::Clear, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "PendingdHotkeyEmission", + mode: CleanupMode::Clear, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "PendingdHotkeyEmissionUntouchable", + mode: CleanupMode::Clear, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "LastHotkeyEmissionDrain", + mode: CleanupMode::Clear, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "StakeDeltaSinceLastEmissionDrain", + mode: CleanupMode::Clear, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "TotalColdkeyStake", + mode: CleanupMode::Clear, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "LastAddStakeIncrease", + mode: CleanupMode::Clear, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "ColdkeyArbitrationBlock", + mode: CleanupMode::Clear, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "Alpha", + mode: CleanupMode::ClearIfZero, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "TotalHotkeyShares", + mode: CleanupMode::ClearIfZero, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "TotalHotkeyAlpha", + mode: CleanupMode::ClearIfZero, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "TotalHotkeyAlphaLastEpoch", + mode: CleanupMode::ClearIfZero, + }, + CleanupTarget { + pallet: "SubtensorModule", + storage: "StakingHotkeys", + mode: CleanupMode::ClearIfZero, + }, +]; + +/// Persistent progress for the bounded storage cleanup. +#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug, TypeInfo)] +pub struct StorageBloatCleanupProgress { + /// Index into [`TARGETS`]. + pub target: u16, + /// Last raw key visited in the current prefix. An empty cursor starts at the prefix. + pub cursor: Vec, + /// Rows inspected across all passes. + pub scanned: u64, + /// Rows removed across all passes. + pub removed: u64, +} + +#[storage_alias] +pub type StorageBloatCleanupMigration = + StorageValue, StorageBloatCleanupProgress, OptionQuery>; + +fn storage_prefix(pallet: &str, item: &str) -> Vec { + [twox_128(pallet.as_bytes()), twox_128(item.as_bytes())].concat() +} + +fn is_zero_value(value: &[u8]) -> bool { + !value.is_empty() && value.iter().all(|byte| *byte == 0) +} + +fn scan_item_weight(mode: CleanupMode) -> Weight { + match mode { + // next_key + clear + CleanupMode::Clear => T::DbWeight::get().reads_writes(1, 1), + // next_key + get + a conservatively charged clear + CleanupMode::ClearIfZero => T::DbWeight::get().reads_writes(2, 1), + } +} + +/// Starts the cleanup without doing any unbounded work in the runtime-upgrade block. +pub fn kickoff_storage_bloat_cleanup() -> Weight { + let mut weight = T::DbWeight::get().reads(2); + if HasMigrationRun::::get(MIGRATION_NAME) || StorageBloatCleanupMigration::::exists() { + return weight; + } + + StorageBloatCleanupMigration::::put(StorageBloatCleanupProgress { + target: 0, + cursor: Vec::new(), + scanned: 0, + removed: 0, + }); + weight.saturating_accrue(T::DbWeight::get().writes(1)); + log::info!( + "Migration '{}' scheduled for bounded on_idle execution", + String::from_utf8_lossy(MIGRATION_NAME) + ); + weight +} +/// Continues the cleanup using no more than the supplied remaining block weight. +pub fn continue_storage_bloat_cleanup(limit: Weight) -> Weight { + // Cursor read plus either a cursor write, or the completion marker and cursor removal. + let pass_overhead = T::DbWeight::get().reads_writes(1, 2); + if !pass_overhead.all_lte(limit) { + return Weight::zero(); + } + + let Some(mut progress) = StorageBloatCleanupMigration::::get() else { + return T::DbWeight::get().reads(1); + }; + let work_limit = limit.saturating_sub(pass_overhead); + let mut work_weight = Weight::zero(); + + while usize::from(progress.target) < TARGETS.len() { + let target = TARGETS[usize::from(progress.target)]; + + let item_weight = scan_item_weight::(target.mode); + if !work_weight.saturating_add(item_weight).all_lte(work_limit) { + break; + } + + let prefix = storage_prefix(target.pallet, target.storage); + let start = if progress.cursor.is_empty() { + &prefix + } else { + &progress.cursor + }; + let Some(next_key) = storage::next_key(start) else { + work_weight.saturating_accrue(T::DbWeight::get().reads(1)); + progress.target = progress.target.saturating_add(1); + progress.cursor.clear(); + continue; + }; + + if !next_key.starts_with(&prefix) { + work_weight.saturating_accrue(T::DbWeight::get().reads(1)); + log::info!( + "Migration '{}' finished {}::{} (scanned {}, removed {} total)", + String::from_utf8_lossy(MIGRATION_NAME), + target.pallet, + target.storage, + progress.scanned, + progress.removed, + ); + progress.target = progress.target.saturating_add(1); + progress.cursor.clear(); + continue; + } + + let should_clear = match target.mode { + CleanupMode::Clear => true, + CleanupMode::ClearIfZero => storage::get(&next_key) + .as_deref() + .is_some_and(is_zero_value), + }; + if should_clear { + storage::clear(&next_key); + progress.removed = progress.removed.saturating_add(1); + } + progress.cursor = next_key; + progress.scanned = progress.scanned.saturating_add(1); + work_weight.saturating_accrue(item_weight); + } + + if usize::from(progress.target) == TARGETS.len() { + HasMigrationRun::::insert(MIGRATION_NAME, true); + StorageBloatCleanupMigration::::kill(); + log::info!( + "Migration '{}' completed: scanned {}, removed {} rows", + String::from_utf8_lossy(MIGRATION_NAME), + progress.scanned, + progress.removed, + ); + } else { + StorageBloatCleanupMigration::::put(progress); + } + + pass_overhead.saturating_add(work_weight) +} diff --git a/pallets/subtensor/src/migrations/mod.rs b/pallets/subtensor/src/migrations/mod.rs index bee75ce474..f75cfca2a6 100644 --- a/pallets/subtensor/src/migrations/mod.rs +++ b/pallets/subtensor/src/migrations/mod.rs @@ -69,6 +69,7 @@ pub mod migrate_set_registration_enable; pub mod migrate_set_root_min_allowed_weights; pub mod migrate_set_subtoken_enabled; pub mod migrate_stake_threshold; +pub mod migrate_storage_bloat_v2; pub mod migrate_subnet_balances; pub mod migrate_subnet_limit_to_default; pub mod migrate_subnet_locked; diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index 8e559400c6..a611a00ac0 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -820,11 +820,12 @@ impl Pallet { // 8.1 Swap TotalHotkeyAlphaLastEpoch let old_alpha = TotalHotkeyAlphaLastEpoch::::take(old_hotkey, netuid); let new_total_hotkey_alpha = TotalHotkeyAlphaLastEpoch::::get(new_hotkey, netuid); - TotalHotkeyAlphaLastEpoch::::insert( - new_hotkey, - netuid, - old_alpha.saturating_add(new_total_hotkey_alpha), - ); + let merged_alpha = old_alpha.saturating_add(new_total_hotkey_alpha); + if merged_alpha == AlphaBalance::ZERO { + TotalHotkeyAlphaLastEpoch::::remove(new_hotkey, netuid); + } else { + TotalHotkeyAlphaLastEpoch::::insert(new_hotkey, netuid, merged_alpha); + } weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); // 8.2 Swap AlphaDividendsPerSubnet diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index cdcab61428..010ffc6f6e 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -6609,3 +6609,148 @@ fn test_migrate_reset_emission_gate_bar() { assert_eq!(EmissionGateBar::::get(), U64F64::from_num(0.003)); }); } + +#[test] +fn test_storage_bloat_cleanup_is_bounded_and_preserves_nonzero_state() { + use crate::migrations::migrate_storage_bloat_v2::{ + StorageBloatCleanupMigration, continue_storage_bloat_cleanup, kickoff_storage_bloat_cleanup, + }; + + new_test_ext(1).execute_with(|| { + const MIGRATION_NAME: &[u8] = b"migrate_storage_bloat_v2"; + let netuid = NetUid::from(1); + let hot_zero = U256::from(10); + let hot_nonzero = U256::from(11); + let coldkey = U256::from(12); + + let raw_key = |pallet: &str, item: &str, suffix: u8| { + let mut key = [twox_128(pallet.as_bytes()), twox_128(item.as_bytes())].concat(); + key.push(suffix); + key + }; + let dead_items = [ + "TotalHotkeyStake", + "PendingdHotkeyEmission", + "PendingdHotkeyEmissionUntouchable", + "LastHotkeyEmissionDrain", + "StakeDeltaSinceLastEmissionDrain", + "TotalColdkeyStake", + "LastAddStakeIncrease", + "ColdkeyArbitrationBlock", + ]; + let dead_keys: Vec<_> = dead_items + .iter() + .enumerate() + .map(|(index, item)| { + let key = raw_key("SubtensorModule", item, index as u8); + sp_io::storage::set(&key, &[1]); + key + }) + .collect(); + + Alpha::::insert((hot_zero, coldkey, netuid), U64F64::from_num(0)); + Alpha::::insert((hot_nonzero, coldkey, netuid), U64F64::from_num(7)); + TotalHotkeyShares::::insert(hot_zero, netuid, U64F64::from_num(0)); + TotalHotkeyShares::::insert(hot_nonzero, netuid, U64F64::from_num(9)); + TotalHotkeyAlpha::::insert(hot_zero, netuid, AlphaBalance::ZERO); + TotalHotkeyAlpha::::insert(hot_nonzero, netuid, AlphaBalance::from(13)); + TotalHotkeyAlphaLastEpoch::::insert(hot_zero, netuid, AlphaBalance::ZERO); + TotalHotkeyAlphaLastEpoch::::insert(hot_nonzero, netuid, AlphaBalance::from(15)); + StakingHotkeys::::insert(hot_zero, Vec::::new()); + StakingHotkeys::::insert(hot_nonzero, vec![coldkey]); + let used_work = vec![1, 2, 3, 4]; + UsedWork::::insert(&used_work, 41); + LastColdkeyHotkeyStakeBlock::::insert(coldkey, hot_zero, 42); + assert_eq!(RootStakeUnlockInterval::::get(), 0); + + let kickoff_weight = kickoff_storage_bloat_cleanup::(); + assert!(!kickoff_weight.is_zero()); + assert!(StorageBloatCleanupMigration::::exists()); + + let limit = ::DbWeight::get().reads_writes(8, 5); + let mut passes = 0; + while StorageBloatCleanupMigration::::exists() { + let used = continue_storage_bloat_cleanup::(limit); + assert!(used.all_lte(limit)); + passes += 1; + assert!(passes < 100, "bounded cleanup did not converge"); + } + assert!(passes > 1, "test must exercise resumable progress"); + assert!(HasMigrationRun::::get(MIGRATION_NAME)); + + for key in dead_keys { + assert!(sp_io::storage::get(&key).is_none()); + } + assert!(!Alpha::::contains_key((hot_zero, coldkey, netuid))); + assert_eq!( + Alpha::::get((hot_nonzero, coldkey, netuid)), + U64F64::from_num(7) + ); + assert!(!TotalHotkeyShares::::contains_key(hot_zero, netuid)); + assert_eq!( + TotalHotkeyShares::::get(hot_nonzero, netuid), + U64F64::from_num(9) + ); + assert!(!TotalHotkeyAlpha::::contains_key(hot_zero, netuid)); + assert_eq!( + TotalHotkeyAlpha::::get(hot_nonzero, netuid), + AlphaBalance::from(13) + ); + assert!(!TotalHotkeyAlphaLastEpoch::::contains_key( + hot_zero, netuid + )); + assert_eq!( + TotalHotkeyAlphaLastEpoch::::get(hot_nonzero, netuid), + AlphaBalance::from(15) + ); + assert!(!StakingHotkeys::::contains_key(hot_zero)); + assert_eq!(StakingHotkeys::::get(hot_nonzero), vec![coldkey]); + assert_eq!(UsedWork::::get(&used_work), 41); + assert_eq!( + LastColdkeyHotkeyStakeBlock::::get(coldkey, hot_zero), + Some(42) + ); + + // Once marked complete, an upgrade cannot restart the sweep. + kickoff_storage_bloat_cleanup::(); + assert!(!StorageBloatCleanupMigration::::exists()); + }); +} + +#[test] +fn test_storage_bloat_cleanup_preserves_root_age_when_hold_is_enabled() { + use crate::migrations::migrate_storage_bloat_v2::{ + continue_storage_bloat_cleanup, kickoff_storage_bloat_cleanup, + }; + + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(20); + let hotkey = U256::from(21); + RootStakeUnlockInterval::::put(100); + LastColdkeyHotkeyStakeBlock::::insert(coldkey, hotkey, 42); + + kickoff_storage_bloat_cleanup::(); + continue_storage_bloat_cleanup::(Weight::MAX); + + assert_eq!( + LastColdkeyHotkeyStakeBlock::::get(coldkey, hotkey), + Some(42) + ); + }); +} + +#[test] +fn test_touch_root_stake_age_writes_while_hold_is_disabled() { + new_test_ext(1).execute_with(|| { + let coldkey = U256::from(30); + let hotkey = U256::from(31); + assert_eq!(RootStakeUnlockInterval::::get(), 0); + + SubtensorModule::touch_root_stake_age(&coldkey, &hotkey); + + assert_eq!( + LastColdkeyHotkeyStakeBlock::::get(coldkey, hotkey), + Some(SubtensorModule::get_current_block_as_u64()) + ); + }); +} diff --git a/pallets/swap/src/pallet/hooks.rs b/pallets/swap/src/pallet/hooks.rs index 90989d5f52..988cedea4b 100644 --- a/pallets/swap/src/pallet/hooks.rs +++ b/pallets/swap/src/pallet/hooks.rs @@ -4,7 +4,7 @@ use frame_support::pallet_macros::pallet_section; mod hooks { #[pallet::hooks] impl Hooks> for Pallet { - fn on_initialize(block_number: BlockNumberFor) -> Weight { + fn on_initialize(_block_number: BlockNumberFor) -> Weight { Weight::from_parts(0, 0) } @@ -15,9 +15,10 @@ mod hooks { let mut weight = Weight::from_parts(0, 0); weight = weight - // Cleanup uniswap v3 and migrate to balancer + // Cleanup the abandoned V3 prefixes without replaying the obsolete balancer + // initialization against an already-live PalSwap. .saturating_add( - migrations::migrate_swapv3_to_balancer::migrate_swapv3_to_balancer::(), + migrations::migrate_storage_cleanup_v2::migrate_swap_storage_cleanup_v2::(), ); weight } diff --git a/pallets/swap/src/pallet/impls.rs b/pallets/swap/src/pallet/impls.rs index 689f2a753c..2d17fe6153 100644 --- a/pallets/swap/src/pallet/impls.rs +++ b/pallets/swap/src/pallet/impls.rs @@ -116,8 +116,8 @@ impl Pallet { pending_tao, pending_alpha, ) { - BalancerTaoReservoir::::insert(netuid, TaoBalance::ZERO); - BalancerAlphaReservoir::::insert(netuid, AlphaBalance::ZERO); + BalancerTaoReservoir::::remove(netuid); + BalancerAlphaReservoir::::remove(netuid); SwapBalancer::::insert(netuid, new_balancer); return (pending_tao, pending_alpha); } @@ -130,7 +130,7 @@ impl Pallet { pending_alpha, ) { BalancerTaoReservoir::::insert(netuid, pending_tao); - BalancerAlphaReservoir::::insert(netuid, AlphaBalance::ZERO); + BalancerAlphaReservoir::::remove(netuid); SwapBalancer::::insert(netuid, new_balancer); return (TaoBalance::ZERO, pending_alpha); } @@ -142,7 +142,7 @@ impl Pallet { pending_tao, AlphaBalance::ZERO, ) { - BalancerTaoReservoir::::insert(netuid, TaoBalance::ZERO); + BalancerTaoReservoir::::remove(netuid); BalancerAlphaReservoir::::insert(netuid, pending_alpha); SwapBalancer::::insert(netuid, new_balancer); return (pending_tao, AlphaBalance::ZERO); diff --git a/pallets/swap/src/pallet/migrations/migrate_storage_cleanup_v2.rs b/pallets/swap/src/pallet/migrations/migrate_storage_cleanup_v2.rs new file mode 100644 index 0000000000..e9ac9f5908 --- /dev/null +++ b/pallets/swap/src/pallet/migrations/migrate_storage_cleanup_v2.rs @@ -0,0 +1,70 @@ +use super::*; +use crate::{BalancerAlphaReservoir, BalancerTaoReservoir, HasMigrationRun}; +use frame_support::{traits::Get, weights::Weight}; +use scale_info::prelude::string::String; + +const MIGRATION_NAME: &[u8] = b"migrate_swap_storage_cleanup_v2"; + +/// Removes the abandoned Swap V3 prefixes without replaying the obsolete initialization logic. +/// +/// Mainnet has 2,661 legacy rows across these prefixes, so this small cleanup is intentionally +/// completed in the runtime-upgrade block. The much larger Subtensor cleanup is separately +/// bounded across `on_idle` blocks. +pub fn migrate_swap_storage_cleanup_v2() -> Weight { + let migration_name = BoundedVec::truncate_from(MIGRATION_NAME.to_vec()); + let mut weight = T::DbWeight::get().reads(1); + if HasMigrationRun::::get(&migration_name) { + return weight; + } + + for storage_name in [ + "AlphaSqrtPrice", + "CurrentTick", + "EnabledUserLiquidity", + "FeeGlobalTao", + "FeeGlobalAlpha", + "LastPositionId", + "ScrapReservoirTao", + "ScrapReservoirAlpha", + "Ticks", + "TickIndexBitmapWords", + "SwapV3Initialized", + "CurrentLiquidity", + "Positions", + ] { + remove_prefix::("Swap", storage_name, &mut weight); + } + + // ValueQuery returns zero for an absent row. Avoid retaining the explicit zero reservoirs + // created by the old update path while preserving any genuinely pending balance. + let mut reservoir_reads = 0_u64; + let zero_tao: sp_std::vec::Vec<_> = BalancerTaoReservoir::::iter() + .filter_map(|(netuid, value)| { + reservoir_reads = reservoir_reads.saturating_add(1); + value.is_zero().then_some(netuid) + }) + .collect(); + let zero_alpha: sp_std::vec::Vec<_> = BalancerAlphaReservoir::::iter() + .filter_map(|(netuid, value)| { + reservoir_reads = reservoir_reads.saturating_add(1); + value.is_zero().then_some(netuid) + }) + .collect(); + weight.saturating_accrue(T::DbWeight::get().reads(reservoir_reads)); + for netuid in zero_tao { + BalancerTaoReservoir::::remove(netuid); + weight.saturating_accrue(T::DbWeight::get().writes(1)); + } + for netuid in zero_alpha { + BalancerAlphaReservoir::::remove(netuid); + weight.saturating_accrue(T::DbWeight::get().writes(1)); + } + + HasMigrationRun::::insert(&migration_name, true); + weight.saturating_accrue(T::DbWeight::get().writes(1)); + log::info!( + "Migration '{}' completed", + String::from_utf8_lossy(MIGRATION_NAME) + ); + weight +} diff --git a/pallets/swap/src/pallet/migrations/mod.rs b/pallets/swap/src/pallet/migrations/mod.rs index d34626f05e..9fe5fd9754 100644 --- a/pallets/swap/src/pallet/migrations/mod.rs +++ b/pallets/swap/src/pallet/migrations/mod.rs @@ -5,6 +5,7 @@ use sp_io::hashing::twox_128; use sp_io::storage::clear_prefix; use sp_std::vec::Vec; +pub mod migrate_storage_cleanup_v2; pub mod migrate_swapv3_to_balancer; pub(crate) fn remove_prefix(module: &str, old_map: &str, weight: &mut Weight) { diff --git a/pallets/swap/src/pallet/mod.rs b/pallets/swap/src/pallet/mod.rs index f23fc97c73..3389fae022 100644 --- a/pallets/swap/src/pallet/mod.rs +++ b/pallets/swap/src/pallet/mod.rs @@ -1,6 +1,6 @@ use core::num::NonZeroU64; -use frame_support::{PalletId, pallet_prelude::*, traits::Get}; +use frame_support::{PalletId, pallet_macros::import_section, pallet_prelude::*, traits::Get}; use frame_system::pallet_prelude::*; use subtensor_runtime_common::{ AlphaBalance, BalanceOps, NetUid, SubnetInfo, TaoBalance, TokenReserve, @@ -22,6 +22,7 @@ mod tests; type MigrationKeyMaxLen = ConstU32<128>; #[allow(clippy::module_inception)] +#[import_section(hooks::hooks)] #[frame_support::pallet] #[allow(clippy::expect_used)] mod pallet { diff --git a/pallets/swap/src/pallet/tests.rs b/pallets/swap/src/pallet/tests.rs index dd41c84269..e5de33c33f 100644 --- a/pallets/swap/src/pallet/tests.rs +++ b/pallets/swap/src/pallet/tests.rs @@ -1069,3 +1069,65 @@ fn test_migrate_swapv3_to_balancer_falls_back_to_default_when_price_init_fails() assert!(HasMigrationRun::::get(&migration_name)); }); } + +#[test] +fn test_swap_storage_cleanup_is_wired_and_cleanup_only() { + use frame_support::traits::Hooks; + use sp_io::hashing::twox_128; + + new_test_ext().execute_with(|| { + let legacy_items = [ + "AlphaSqrtPrice", + "CurrentTick", + "EnabledUserLiquidity", + "FeeGlobalTao", + "FeeGlobalAlpha", + "LastPositionId", + "ScrapReservoirTao", + "ScrapReservoirAlpha", + "Ticks", + "TickIndexBitmapWords", + "SwapV3Initialized", + "CurrentLiquidity", + "Positions", + ]; + let legacy_keys: sp_std::vec::Vec<_> = legacy_items + .iter() + .enumerate() + .map(|(index, item)| { + let mut key = [twox_128(b"Swap"), twox_128(item.as_bytes())].concat(); + key.push(index as u8); + sp_io::storage::set(&key, &[1]); + key + }) + .collect(); + + let zero_netuid = NetUid::from(1); + let pending_netuid = NetUid::from(2); + BalancerTaoReservoir::::insert(zero_netuid, TaoBalance::ZERO); + BalancerAlphaReservoir::::insert(zero_netuid, AlphaBalance::ZERO); + BalancerTaoReservoir::::insert(pending_netuid, TaoBalance::from(10)); + BalancerAlphaReservoir::::insert(pending_netuid, AlphaBalance::from(20)); + + as Hooks>::on_runtime_upgrade(); + for (item, key) in legacy_items.iter().zip(legacy_keys) { + assert!( + sp_io::storage::get(&key).is_none(), + "legacy prefix {item} was not cleared" + ); + } + assert!(!BalancerTaoReservoir::::contains_key(zero_netuid)); + assert!(!BalancerAlphaReservoir::::contains_key(zero_netuid)); + assert_eq!( + BalancerTaoReservoir::::get(pending_netuid), + TaoBalance::from(10) + ); + assert_eq!( + BalancerAlphaReservoir::::get(pending_netuid), + AlphaBalance::from(20) + ); + + let migration_name = BoundedVec::truncate_from(b"migrate_swap_storage_cleanup_v2".to_vec()); + assert!(HasMigrationRun::::get(migration_name)); + }); +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 27fe5f0c2c..36bb308c5e 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -235,7 +235,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 443, + spec_version: 444, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 8ecc0069594f3f46d88b7ecfe9b171732ec5cd2a Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Fri, 7 Aug 2026 11:15:00 -0700 Subject: [PATCH 41/58] chore: remove mainnet clone migration test --- clones/js-tests/package.json | 3 +- .../tests/test-storage-bloat-migration.ts | 339 ------------------ 2 files changed, 1 insertion(+), 341 deletions(-) delete mode 100644 clones/js-tests/tests/test-storage-bloat-migration.ts diff --git a/clones/js-tests/package.json b/clones/js-tests/package.json index ed889dc1ea..a554fe8372 100644 --- a/clones/js-tests/package.json +++ b/clones/js-tests/package.json @@ -26,8 +26,7 @@ "test:testnet-unlock-rate": "tsx tests/testnet-unlock-rate-read.ts", "test:testnet-maturity-rate": "tsx tests/testnet-maturity-rate-read.ts", "test:hotkey-swap-and-proxy-stake": "tsx tests/test-hotkey-swap-and-proxy-stake.ts", - "test:proxy-filter-security-regressions": "tsx tests/test-proxy-filter-security-regressions.ts", - "test:storage-bloat-migration": "tsx tests/test-storage-bloat-migration.ts" + "test:proxy-filter-security-regressions": "tsx tests/test-proxy-filter-security-regressions.ts" }, "dependencies": { "@polkadot/api": "^16.4.9", diff --git a/clones/js-tests/tests/test-storage-bloat-migration.ts b/clones/js-tests/tests/test-storage-bloat-migration.ts deleted file mode 100644 index 5212d998d8..0000000000 --- a/clones/js-tests/tests/test-storage-bloat-migration.ts +++ /dev/null @@ -1,339 +0,0 @@ -import assert from "node:assert/strict"; - -import { xxhashAsHex } from "@polkadot/util-crypto"; - -import { connectApi } from "../lib/api.js"; -import { createTempLogger } from "../lib/file-log.js"; - -const WS_ENDPOINT = process.env.WS_ENDPOINT ?? "ws://127.0.0.1:9944"; -const TARGET_SPEC_VERSION = BigInt(process.env.TARGET_SPEC_VERSION ?? 444); -const PAGE_SIZE = Number(process.env.STORAGE_MIGRATION_PAGE_SIZE ?? 1000); -const MAX_HEAD_GAP_MS = Number(process.env.MAX_HEAD_GAP_MS ?? 30_000); -const MIGRATION_TIMEOUT_MS = Number(process.env.MIGRATION_TIMEOUT_MS ?? 60 * 60 * 1000); -const MIGRATION_NAME = "migrate_storage_bloat_v2"; -const logger = createTempLogger("storage-bloat-migration.log"); - -const SUBTENSOR_CLEAR = [ - "TotalHotkeyStake", - "PendingdHotkeyEmission", - "PendingdHotkeyEmissionUntouchable", - "LastHotkeyEmissionDrain", - "StakeDeltaSinceLastEmissionDrain", - "TotalColdkeyStake", - "LastAddStakeIncrease", - "ColdkeyArbitrationBlock", -] as const; - -const SUBTENSOR_ZERO = [ - "Alpha", - "TotalHotkeyShares", - "TotalHotkeyAlpha", - "TotalHotkeyAlphaLastEpoch", - "StakingHotkeys", -] as const; - -const SUBTENSOR_ROOT_AGE = "LastColdkeyHotkeyStakeBlock"; - -const SWAP_CLEAR = [ - "AlphaSqrtPrice", - "CurrentTick", - "EnabledUserLiquidity", - "FeeGlobalTao", - "FeeGlobalAlpha", - "LastPositionId", - "ScrapReservoirTao", - "ScrapReservoirAlpha", - "Ticks", - "TickIndexBitmapWords", - "SwapV3Initialized", - "CurrentLiquidity", - "Positions", -] as const; - -const SWAP_ZERO = ["BalancerTaoReservoir", "BalancerAlphaReservoir"] as const; - -type PrefixStats = { - count: number; - zero: number; - nonzero: number; -}; - -type HeadSample = { - number: bigint; - arrivalMs: number; -}; - -function prefix(pallet: string, storage: string): string { - return `${xxhashAsHex(pallet, 128)}${xxhashAsHex(storage, 128).slice(2)}`; -} - -function isAllZero(valueHex: string): boolean { - return valueHex.length > 2 && /^0x0+$/.test(valueHex); -} - -function percentile(values: number[], fraction: number): number { - assert.ok(values.length > 0, "cannot calculate a percentile without samples"); - const sorted = [...values].sort((left, right) => left - right); - return sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * fraction))]; -} - -function gaps(samples: HeadSample[]): number[] { - return samples.slice(1).map((sample, index) => sample.arrivalMs - samples[index].arrivalMs); -} - -async function scanPrefix( - api: any, - pallet: string, - storage: string, - atHash: any, - checkHalt: () => void, -): Promise { - const storagePrefix = prefix(pallet, storage); - let startKey: any = undefined; - let count = 0; - let zero = 0; - let pages = 0; - - for (;;) { - checkHalt(); - const keys: any[] = await api.rpc.state.getKeysPaged( - storagePrefix, - PAGE_SIZE, - startKey, - atHash, - ); - if (keys.length === 0) break; - - const changeSets: any = await api.rpc.state.queryStorageAt(keys, atHash); - const values = new Map(); - if ( - Array.isArray(changeSets) && - changeSets.length === keys.length && - changeSets.every((value) => typeof value?.isSome === "boolean") - ) { - for (let index = 0; index < keys.length; index += 1) { - const maybeValue = changeSets[index]; - values.set( - keys[index].toHex().toLowerCase(), - maybeValue.isSome ? maybeValue.unwrap().toHex() : "0x", - ); - } - } else { - const decodedSets = changeSets.changes ? [changeSets] : Array.from(changeSets); - for (const changeSet of decodedSets as any[]) { - const changes = - typeof changeSet.changes === "function" ? changeSet.changes() : changeSet.changes; - for (const [key, maybeValue] of changes) { - values.set( - key.toHex().toLowerCase(), - maybeValue.isSome ? maybeValue.unwrap().toHex() : "0x", - ); - } - } - } - - for (const key of keys) { - if (isAllZero(values.get(key.toHex().toLowerCase()) ?? "0x")) zero += 1; - } - count += keys.length; - pages += 1; - startKey = keys.at(-1); - if (pages === 1 || pages % 200 === 0) { - await logger.info( - `scan pallet=${pallet} storage=${storage} pages=${pages} keys=${count} zero=${zero}`, - ); - } - } - - const result = { count, zero, nonzero: count - zero }; - await logger.info(`PREFIX ${pallet}.${storage} ${JSON.stringify(result)}`); - return result; -} - -async function snapshot( - api: any, - atHash: any, - checkHalt: () => void, -): Promise> { - const result = new Map(); - for (const name of SUBTENSOR_CLEAR) { - result.set( - `SubtensorModule.${name}`, - await scanPrefix(api, "SubtensorModule", name, atHash, checkHalt), - ); - } - for (const name of SUBTENSOR_ZERO) { - result.set( - `SubtensorModule.${name}`, - await scanPrefix(api, "SubtensorModule", name, atHash, checkHalt), - ); - } - result.set( - `SubtensorModule.${SUBTENSOR_ROOT_AGE}`, - await scanPrefix(api, "SubtensorModule", SUBTENSOR_ROOT_AGE, atHash, checkHalt), - ); - for (const name of SWAP_CLEAR) { - result.set(`Swap.${name}`, await scanPrefix(api, "Swap", name, atHash, checkHalt)); - } - for (const name of SWAP_ZERO) { - result.set(`Swap.${name}`, await scanPrefix(api, "Swap", name, atHash, checkHalt)); - } - return result; -} - -function assertCleanup(before: Map, after: Map): void { - for (const name of SUBTENSOR_CLEAR) { - const key = `SubtensorModule.${name}`; - assert.ok((before.get(key)?.count ?? 0) > 0, `${key} had no mainnet rows before migration`); - assert.equal(after.get(key)?.count, 0, `${key} was not fully removed`); - } - - for (const name of SUBTENSOR_ZERO) { - const key = `SubtensorModule.${name}`; - const pre = before.get(key)!; - const post = after.get(key)!; - assert.ok(pre.zero > 0, `${key} had no zero rows to exercise the migration`); - assert.ok(pre.nonzero > 0, `${key} had no nonzero rows to preserve`); - assert.equal(post.zero, 0, `${key} retained explicit zero rows`); - assert.ok(post.nonzero > 0, `${key} lost all nonzero rows`); - } - - const rootAgeKey = `SubtensorModule.${SUBTENSOR_ROOT_AGE}`; - assert.ok((before.get(rootAgeKey)?.count ?? 0) > 0, `${rootAgeKey} had no rows before migration`); - assert.deepEqual(after.get(rootAgeKey), before.get(rootAgeKey), `${rootAgeKey} changed`); - - for (const name of SWAP_CLEAR) { - const key = `Swap.${name}`; - assert.ok((before.get(key)?.count ?? 0) > 0, `${key} had no mainnet rows before migration`); - assert.equal(after.get(key)?.count, 0, `${key} was not fully removed`); - } - - for (const name of SWAP_ZERO) { - const key = `Swap.${name}`; - assert.ok((before.get(key)?.zero ?? 0) > 0, `${key} had no zero rows before migration`); - assert.equal(after.get(key)?.zero, 0, `${key} retained explicit zero rows`); - } -} - -async function main(): Promise { - await logger.start(); - const api = await connectApi(WS_ENDPOINT, { log: (...args) => logger.info(...args) }); - const samples: HeadSample[] = []; - let lastHeadAt = Date.now(); - let lastLoggedHead = -1n; - - const unsubscribe = await api.rpc.chain.subscribeNewHeads((header: any) => { - const arrivalMs = Date.now(); - const number = BigInt(header.number.toString()); - samples.push({ number, arrivalMs }); - lastHeadAt = arrivalMs; - }); - - const checkHalt = (): void => { - const gap = Date.now() - lastHeadAt; - assert.ok(gap <= MAX_HEAD_GAP_MS, `block production halted for ${gap}ms`); - }; - - try { - const initialRuntime = await api.rpc.state.getRuntimeVersion(); - assert.ok( - BigInt(initialRuntime.specVersion.toString()) < TARGET_SPEC_VERSION, - `expected a pre-upgrade runtime, got spec ${initialRuntime.specVersion.toString()}`, - ); - const beforeHeader = await api.rpc.chain.getHeader(); - const beforeHash = beforeHeader.hash; - const rootUnlockInterval = BigInt( - (await (api.query.subtensorModule as any).rootStakeUnlockInterval.at(beforeHash)).toString(), - ); - assert.equal(rootUnlockInterval, 0n, "root stake hold is enabled; root-age cleanup is unsafe"); - - await logger.info( - `baseline block=${beforeHeader.number.toString()} hash=${beforeHash.toString()} spec=${initialRuntime.specVersion.toString()}`, - ); - const before = await snapshot(api, beforeHash, checkHalt); - await logger.info("READY_FOR_RUNTIME_UPGRADE"); - - const startedAt = Date.now(); - let upgradeDetectedAt = 0; - let upgradeBlock = 0n; - let completionBlock = 0n; - for (;;) { - checkHalt(); - assert.ok(Date.now() - startedAt <= MIGRATION_TIMEOUT_MS, "migration timed out"); - - const header = await api.rpc.chain.getHeader(); - const block = BigInt(header.number.toString()); - const runtime = await api.rpc.state.getRuntimeVersion(); - const spec = BigInt(runtime.specVersion.toString()); - if (spec >= TARGET_SPEC_VERSION && upgradeDetectedAt === 0) { - upgradeDetectedAt = Date.now(); - upgradeBlock = block; - await logger.info(`UPGRADE_DETECTED block=${block} spec=${spec}`); - } - - if (upgradeDetectedAt !== 0) { - const marker = await (api.query.subtensorModule as any).hasMigrationRun(MIGRATION_NAME); - const progress: any = await api.rpc.state.getStorage( - prefix("SubtensorModule", "StorageBloatCleanupMigration"), - ); - if (block >= lastLoggedHead + 10n || marker.isTrue) { - await logger.info( - `progress block=${block} marker=${marker.toString()} cursor_present=${progress.isSome}`, - ); - lastLoggedHead = block; - } - if (marker.isTrue && progress.isNone) { - completionBlock = block; - break; - } - } - - await new Promise((resolve) => setTimeout(resolve, 2_000)); - } - - while ((samples.at(-1)?.number ?? 0n) < completionBlock + 10n) { - checkHalt(); - await new Promise((resolve) => setTimeout(resolve, 1_000)); - } - - const afterHeader = await api.rpc.chain.getHeader(); - const afterHash = afterHeader.hash; - const after = await snapshot(api, afterHash, checkHalt); - assertCleanup(before, after); - - const baselineSamples = samples.filter((sample) => sample.arrivalMs < upgradeDetectedAt); - const migrationSamples = samples.filter( - (sample) => sample.number >= upgradeBlock && sample.number <= completionBlock + 10n, - ); - const baselineGaps = gaps(baselineSamples); - const migrationGaps = gaps(migrationSamples); - assert.ok(baselineGaps.length >= 5, "not enough baseline block-time samples"); - assert.ok(migrationGaps.length >= 10, "not enough migration block-time samples"); - const baselineMedian = percentile(baselineGaps, 0.5); - const migrationMedian = percentile(migrationGaps, 0.5); - const migrationP95 = percentile(migrationGaps, 0.95); - const migrationMax = Math.max(...migrationGaps); - assert.ok(migrationMax <= MAX_HEAD_GAP_MS, `maximum migration head gap was ${migrationMax}ms`); - assert.ok( - migrationMedian <= Math.max(6_000, baselineMedian * 3), - `median head gap regressed from ${baselineMedian}ms to ${migrationMedian}ms`, - ); - - await logger.info( - `TIMING baseline_median_ms=${baselineMedian} migration_median_ms=${migrationMedian} migration_p95_ms=${migrationP95} migration_max_ms=${migrationMax}`, - ); - await logger.info( - `PASS upgrade_block=${upgradeBlock} completion_block=${completionBlock} migration_blocks=${completionBlock - upgradeBlock + 1n} final_block=${afterHeader.number.toString()}`, - ); - } finally { - unsubscribe(); - await api.disconnect(); - await logger.flush(); - } -} - -main().catch(async (error) => { - await logger.error(error); - await logger.flush(); - process.exit(1); -}); From d316a6c01d99fa7e85e8a83d86ecb580acb956a4 Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Fri, 7 Aug 2026 11:21:46 -0700 Subject: [PATCH 42/58] revert extra --- pallets/subtensor/src/coinbase/run_coinbase.rs | 6 +----- pallets/subtensor/src/swap/swap_hotkey.rs | 11 +++++------ pallets/subtensor/src/tests/migration.rs | 16 ---------------- pallets/swap/src/pallet/impls.rs | 8 ++++---- 4 files changed, 10 insertions(+), 31 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index 49df8ed27c..d8fa2af0eb 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -833,11 +833,7 @@ impl Pallet { }); } let total_hotkey_alpha = TotalHotkeyAlpha::::get(&hotkey, netuid); - if total_hotkey_alpha == AlphaBalance::ZERO { - TotalHotkeyAlphaLastEpoch::::remove(hotkey, netuid); - } else { - TotalHotkeyAlphaLastEpoch::::insert(hotkey, netuid, total_hotkey_alpha); - } + TotalHotkeyAlphaLastEpoch::::insert(hotkey, netuid, total_hotkey_alpha); } // Distribute root alpha divs. Same ownership rule: full root emission diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index a611a00ac0..8e559400c6 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -820,12 +820,11 @@ impl Pallet { // 8.1 Swap TotalHotkeyAlphaLastEpoch let old_alpha = TotalHotkeyAlphaLastEpoch::::take(old_hotkey, netuid); let new_total_hotkey_alpha = TotalHotkeyAlphaLastEpoch::::get(new_hotkey, netuid); - let merged_alpha = old_alpha.saturating_add(new_total_hotkey_alpha); - if merged_alpha == AlphaBalance::ZERO { - TotalHotkeyAlphaLastEpoch::::remove(new_hotkey, netuid); - } else { - TotalHotkeyAlphaLastEpoch::::insert(new_hotkey, netuid, merged_alpha); - } + TotalHotkeyAlphaLastEpoch::::insert( + new_hotkey, + netuid, + old_alpha.saturating_add(new_total_hotkey_alpha), + ); weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); // 8.2 Swap AlphaDividendsPerSubnet diff --git a/pallets/subtensor/src/tests/migration.rs b/pallets/subtensor/src/tests/migration.rs index 010ffc6f6e..ac15ffb07c 100644 --- a/pallets/subtensor/src/tests/migration.rs +++ b/pallets/subtensor/src/tests/migration.rs @@ -6738,19 +6738,3 @@ fn test_storage_bloat_cleanup_preserves_root_age_when_hold_is_enabled() { ); }); } - -#[test] -fn test_touch_root_stake_age_writes_while_hold_is_disabled() { - new_test_ext(1).execute_with(|| { - let coldkey = U256::from(30); - let hotkey = U256::from(31); - assert_eq!(RootStakeUnlockInterval::::get(), 0); - - SubtensorModule::touch_root_stake_age(&coldkey, &hotkey); - - assert_eq!( - LastColdkeyHotkeyStakeBlock::::get(coldkey, hotkey), - Some(SubtensorModule::get_current_block_as_u64()) - ); - }); -} diff --git a/pallets/swap/src/pallet/impls.rs b/pallets/swap/src/pallet/impls.rs index 2d17fe6153..689f2a753c 100644 --- a/pallets/swap/src/pallet/impls.rs +++ b/pallets/swap/src/pallet/impls.rs @@ -116,8 +116,8 @@ impl Pallet { pending_tao, pending_alpha, ) { - BalancerTaoReservoir::::remove(netuid); - BalancerAlphaReservoir::::remove(netuid); + BalancerTaoReservoir::::insert(netuid, TaoBalance::ZERO); + BalancerAlphaReservoir::::insert(netuid, AlphaBalance::ZERO); SwapBalancer::::insert(netuid, new_balancer); return (pending_tao, pending_alpha); } @@ -130,7 +130,7 @@ impl Pallet { pending_alpha, ) { BalancerTaoReservoir::::insert(netuid, pending_tao); - BalancerAlphaReservoir::::remove(netuid); + BalancerAlphaReservoir::::insert(netuid, AlphaBalance::ZERO); SwapBalancer::::insert(netuid, new_balancer); return (TaoBalance::ZERO, pending_alpha); } @@ -142,7 +142,7 @@ impl Pallet { pending_tao, AlphaBalance::ZERO, ) { - BalancerTaoReservoir::::remove(netuid); + BalancerTaoReservoir::::insert(netuid, TaoBalance::ZERO); BalancerAlphaReservoir::::insert(netuid, pending_alpha); SwapBalancer::::insert(netuid, new_balancer); return (pending_tao, AlphaBalance::ZERO); From 63369449a9335455e84b0f8446a2b3772e8ba6e6 Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Fri, 7 Aug 2026 12:04:54 -0700 Subject: [PATCH 43/58] prevent zero values from being created --- .../subtensor/src/coinbase/run_coinbase.rs | 6 +++- pallets/subtensor/src/swap/swap_coldkey.rs | 6 +++- pallets/subtensor/src/swap/swap_hotkey.rs | 11 ++++---- pallets/subtensor/src/tests/coinbase.rs | 22 +++++++++++++++ pallets/subtensor/src/tests/swap_coldkey.rs | 1 + pallets/subtensor/src/tests/swap_hotkey.rs | 28 +++++++++++++++++++ pallets/swap/src/pallet/impls.rs | 20 +++++++++---- pallets/swap/src/pallet/tests.rs | 6 ++++ 8 files changed, 87 insertions(+), 13 deletions(-) diff --git a/pallets/subtensor/src/coinbase/run_coinbase.rs b/pallets/subtensor/src/coinbase/run_coinbase.rs index d8fa2af0eb..644c36a489 100644 --- a/pallets/subtensor/src/coinbase/run_coinbase.rs +++ b/pallets/subtensor/src/coinbase/run_coinbase.rs @@ -833,7 +833,11 @@ impl Pallet { }); } let total_hotkey_alpha = TotalHotkeyAlpha::::get(&hotkey, netuid); - TotalHotkeyAlphaLastEpoch::::insert(hotkey, netuid, total_hotkey_alpha); + if total_hotkey_alpha.is_zero() { + TotalHotkeyAlphaLastEpoch::::remove(hotkey, netuid); + } else { + TotalHotkeyAlphaLastEpoch::::insert(hotkey, netuid, total_hotkey_alpha); + } } // Distribute root alpha divs. Same ownership rule: full root emission diff --git a/pallets/subtensor/src/swap/swap_coldkey.rs b/pallets/subtensor/src/swap/swap_coldkey.rs index 0e3a68d48a..54d32755a1 100644 --- a/pallets/subtensor/src/swap/swap_coldkey.rs +++ b/pallets/subtensor/src/swap/swap_coldkey.rs @@ -167,7 +167,11 @@ impl Pallet { } StakingHotkeys::::remove(old_coldkey); - StakingHotkeys::::insert(new_coldkey, new_staking_hotkeys); + if new_staking_hotkeys.is_empty() { + StakingHotkeys::::remove(new_coldkey); + } else { + StakingHotkeys::::insert(new_coldkey, new_staking_hotkeys); + } } /// Transfer the ownership of the hotkeys owned by the old coldkey to the new coldkey. diff --git a/pallets/subtensor/src/swap/swap_hotkey.rs b/pallets/subtensor/src/swap/swap_hotkey.rs index 8e559400c6..a557ac3cdd 100644 --- a/pallets/subtensor/src/swap/swap_hotkey.rs +++ b/pallets/subtensor/src/swap/swap_hotkey.rs @@ -820,11 +820,12 @@ impl Pallet { // 8.1 Swap TotalHotkeyAlphaLastEpoch let old_alpha = TotalHotkeyAlphaLastEpoch::::take(old_hotkey, netuid); let new_total_hotkey_alpha = TotalHotkeyAlphaLastEpoch::::get(new_hotkey, netuid); - TotalHotkeyAlphaLastEpoch::::insert( - new_hotkey, - netuid, - old_alpha.saturating_add(new_total_hotkey_alpha), - ); + let merged_alpha = old_alpha.saturating_add(new_total_hotkey_alpha); + if merged_alpha.is_zero() { + TotalHotkeyAlphaLastEpoch::::remove(new_hotkey, netuid); + } else { + TotalHotkeyAlphaLastEpoch::::insert(new_hotkey, netuid, merged_alpha); + } weight.saturating_accrue(T::DbWeight::get().reads_writes(2, 2)); // 8.2 Swap AlphaDividendsPerSubnet diff --git a/pallets/subtensor/src/tests/coinbase.rs b/pallets/subtensor/src/tests/coinbase.rs index 96afae33e1..ecf3a627bb 100644 --- a/pallets/subtensor/src/tests/coinbase.rs +++ b/pallets/subtensor/src/tests/coinbase.rs @@ -69,6 +69,28 @@ fn test_coinbase_basecase() { }); } +#[test] +fn test_dividend_distribution_does_not_store_zero_last_epoch_alpha() { + new_test_ext(1).execute_with(|| { + let netuid = NetUid::from(1); + let hotkey = U256::from(1); + let mut alpha_dividends = BTreeMap::new(); + alpha_dividends.insert(hotkey, U96F32::from_num(0)); + + SubtensorModule::distribute_dividends_and_incentives( + netuid, + AlphaBalance::ZERO, + BTreeMap::new(), + alpha_dividends, + BTreeMap::new(), + ); + + assert!(!TotalHotkeyAlphaLastEpoch::::contains_key( + hotkey, netuid + )); + }); +} + // Test the emission distribution for a single subnet. // This test verifies that: // - Single subnet gets cutoff by lower flow limit, so nothing is distributed diff --git a/pallets/subtensor/src/tests/swap_coldkey.rs b/pallets/subtensor/src/tests/swap_coldkey.rs index 8bd6ad45c4..2773a98cf2 100644 --- a/pallets/subtensor/src/tests/swap_coldkey.rs +++ b/pallets/subtensor/src/tests/swap_coldkey.rs @@ -802,6 +802,7 @@ fn test_do_swap_coldkey_with_no_stake() { SubtensorModule::get_total_stake_for_coldkey(&new_coldkey), TaoBalance::ZERO ); + assert!(!StakingHotkeys::::contains_key(new_coldkey)); }); } diff --git a/pallets/subtensor/src/tests/swap_hotkey.rs b/pallets/subtensor/src/tests/swap_hotkey.rs index decc12ac91..28c30a4da9 100644 --- a/pallets/subtensor/src/tests/swap_hotkey.rs +++ b/pallets/subtensor/src/tests/swap_hotkey.rs @@ -1023,6 +1023,34 @@ fn test_swap_stake_v2_success() { }); } +#[test] +fn test_swap_does_not_create_zero_last_epoch_alpha() { + new_test_ext(1).execute_with(|| { + let old_hotkey = U256::from(1); + let new_hotkey = U256::from(2); + let coldkey = U256::from(3); + let subnet_owner_coldkey = U256::from(1001); + let subnet_owner_hotkey = U256::from(1002); + add_dynamic_network(&subnet_owner_hotkey, &subnet_owner_coldkey); + let mut weight = Weight::zero(); + + SubtensorModule::perform_hotkey_swap_on_all_subnets( + &old_hotkey, + &new_hotkey, + &coldkey, + &mut weight, + false, + ) + .unwrap(); + + for netuid in SubtensorModule::get_all_subnet_netuids() { + assert!(!TotalHotkeyAlphaLastEpoch::::contains_key( + new_hotkey, netuid + )); + } + }); +} + // SKIP_WASM_BUILD=1 RUST_LOG=debug cargo test --package pallet-subtensor --lib -- tests::swap_hotkey::test_swap_stake_old_hotkey_not_exist --exact --nocapture #[test] fn test_swap_stake_old_hotkey_not_exist() { diff --git a/pallets/swap/src/pallet/impls.rs b/pallets/swap/src/pallet/impls.rs index 689f2a753c..a2a254b1c1 100644 --- a/pallets/swap/src/pallet/impls.rs +++ b/pallets/swap/src/pallet/impls.rs @@ -116,8 +116,8 @@ impl Pallet { pending_tao, pending_alpha, ) { - BalancerTaoReservoir::::insert(netuid, TaoBalance::ZERO); - BalancerAlphaReservoir::::insert(netuid, AlphaBalance::ZERO); + BalancerTaoReservoir::::remove(netuid); + BalancerAlphaReservoir::::remove(netuid); SwapBalancer::::insert(netuid, new_balancer); return (pending_tao, pending_alpha); } @@ -130,7 +130,7 @@ impl Pallet { pending_alpha, ) { BalancerTaoReservoir::::insert(netuid, pending_tao); - BalancerAlphaReservoir::::insert(netuid, AlphaBalance::ZERO); + BalancerAlphaReservoir::::remove(netuid); SwapBalancer::::insert(netuid, new_balancer); return (TaoBalance::ZERO, pending_alpha); } @@ -142,14 +142,22 @@ impl Pallet { pending_tao, AlphaBalance::ZERO, ) { - BalancerTaoReservoir::::insert(netuid, TaoBalance::ZERO); + BalancerTaoReservoir::::remove(netuid); BalancerAlphaReservoir::::insert(netuid, pending_alpha); SwapBalancer::::insert(netuid, new_balancer); return (pending_tao, AlphaBalance::ZERO); } - BalancerTaoReservoir::::insert(netuid, pending_tao); - BalancerAlphaReservoir::::insert(netuid, pending_alpha); + if pending_tao.is_zero() { + BalancerTaoReservoir::::remove(netuid); + } else { + BalancerTaoReservoir::::insert(netuid, pending_tao); + } + if pending_alpha.is_zero() { + BalancerAlphaReservoir::::remove(netuid); + } else { + BalancerAlphaReservoir::::insert(netuid, pending_alpha); + } if pending_tao > TaoBalance::ZERO || pending_alpha > AlphaBalance::ZERO { log::warn!( "Reserves are out of range for emission: netuid = {}, tao = {}, alpha = {}, tao_delta = {}, alpha_delta = {}, tao_reservoir = {}, alpha_reservoir = {}", diff --git a/pallets/swap/src/pallet/tests.rs b/pallets/swap/src/pallet/tests.rs index e5de33c33f..1d112d0b88 100644 --- a/pallets/swap/src/pallet/tests.rs +++ b/pallets/swap/src/pallet/tests.rs @@ -182,6 +182,7 @@ mod dispatchables { BalancerAlphaReservoir::::get(netuid), AlphaBalance::ZERO ); + assert!(!BalancerAlphaReservoir::::contains_key(netuid)); }); } @@ -204,6 +205,7 @@ mod dispatchables { assert_eq!(price_active_tao, TaoBalance::from(1_000_u64)); assert_eq!(price_active_alpha, AlphaBalance::ZERO); assert_eq!(BalancerTaoReservoir::::get(netuid), TaoBalance::ZERO); + assert!(!BalancerTaoReservoir::::contains_key(netuid)); assert_eq!( BalancerAlphaReservoir::::get(netuid), AlphaBalance::from(200_000_u64) @@ -246,6 +248,8 @@ mod dispatchables { BalancerAlphaReservoir::::get(netuid), AlphaBalance::ZERO ); + assert!(!BalancerTaoReservoir::::contains_key(netuid)); + assert!(!BalancerAlphaReservoir::::contains_key(netuid)); }); } @@ -271,6 +275,8 @@ mod dispatchables { BalancerAlphaReservoir::::get(netuid), AlphaBalance::ZERO ); + assert!(!BalancerTaoReservoir::::contains_key(netuid)); + assert!(!BalancerAlphaReservoir::::contains_key(netuid)); }); } From 62edbef63f0f067d47dffbf029750237cdebd984 Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Fri, 7 Aug 2026 12:28:12 -0700 Subject: [PATCH 44/58] urge neuron commitments when trimming uids --- chain-extensions/src/mock.rs | 4 +- eco-tests/src/mock.rs | 4 +- pallets/admin-utils/src/tests/mock.rs | 4 +- pallets/commitments/src/lib.rs | 16 +++++++- pallets/subtensor/src/lib.rs | 6 ++- pallets/subtensor/src/macros/config.rs | 4 +- pallets/subtensor/src/subnets/uids.rs | 2 + pallets/subtensor/src/tests/mock.rs | 6 ++- pallets/subtensor/src/tests/mock_high_ed.rs | 4 +- pallets/subtensor/src/tests/uids.rs | 43 ++++++++++++++++++++- pallets/transaction-fee/src/tests/mock.rs | 4 +- precompiles/src/mock.rs | 4 +- runtime/src/lib.rs | 6 ++- 13 files changed, 93 insertions(+), 14 deletions(-) diff --git a/chain-extensions/src/mock.rs b/chain-extensions/src/mock.rs index 6887dc5822..bffaeec707 100644 --- a/chain-extensions/src/mock.rs +++ b/chain-extensions/src/mock.rs @@ -477,13 +477,15 @@ impl PrivilegeCmp for OriginPrivilegeCmp { } pub struct CommitmentsI; -impl CommitmentsInterface for CommitmentsI { +impl CommitmentsInterface for CommitmentsI { fn purge_netuid( _netuid: NetUid, _weight_meter: &mut frame_support::weights::WeightMeter, ) -> bool { true } + + fn purge_neuron(_netuid: NetUid, _account: &AccountId) {} } parameter_types! { diff --git a/eco-tests/src/mock.rs b/eco-tests/src/mock.rs index a4929a2cb7..9c913295e5 100644 --- a/eco-tests/src/mock.rs +++ b/eco-tests/src/mock.rs @@ -370,13 +370,15 @@ impl PrivilegeCmp for OriginPrivilegeCmp { } pub struct CommitmentsI; -impl CommitmentsInterface for CommitmentsI { +impl CommitmentsInterface for CommitmentsI { fn purge_netuid( _netuid: NetUid, _weight_meter: &mut frame_support::weights::WeightMeter, ) -> bool { true } + + fn purge_neuron(_netuid: NetUid, _account: &AccountId) {} } parameter_types! { diff --git a/pallets/admin-utils/src/tests/mock.rs b/pallets/admin-utils/src/tests/mock.rs index ad8152b8e2..effe293ce7 100644 --- a/pallets/admin-utils/src/tests/mock.rs +++ b/pallets/admin-utils/src/tests/mock.rs @@ -382,13 +382,15 @@ impl PrivilegeCmp for OriginPrivilegeCmp { } pub struct CommitmentsI; -impl pallet_subtensor::CommitmentsInterface for CommitmentsI { +impl pallet_subtensor::CommitmentsInterface for CommitmentsI { fn purge_netuid( _netuid: NetUid, _weight_meter: &mut frame_support::weights::WeightMeter, ) -> bool { true } + + fn purge_neuron(_netuid: NetUid, _account: &AccountId) {} } pub struct GrandpaInterfaceImpl; diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index 5ed05744ed..baa28199ff 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -16,7 +16,7 @@ use frame_support::IterableStorageDoubleMap; use frame_support::weights::WeightMeter; use frame_support::{ BoundedVec, - traits::{Currency, Get}, + traits::{Currency, Get, ReservableCurrency}, }; use frame_system::pallet_prelude::BlockNumberFor; pub use pallet::*; @@ -586,6 +586,20 @@ impl Pallet { commitments } + /// Purges all commitment state for one neuron on a subnet. + pub fn purge_neuron(netuid: NetUid, account: &T::AccountId) { + if let Some(registration) = CommitmentOf::::take(netuid, account) { + T::Currency::unreserve(account, registration.deposit); + } + LastCommitment::::remove(netuid, account); + LastBondsReset::::remove(netuid, account); + RevealedCommitments::::remove(netuid, account); + UsedSpaceOf::::remove(netuid, account); + TimelockedIndex::::mutate(|index| { + index.remove(&(netuid, account.clone())); + }); + } + pub fn purge_netuid(netuid: NetUid, weight_meter: &mut WeightMeter) -> bool { let write_weight = T::DbWeight::get().writes(1); diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 36ae44371a..a612517200 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -3376,7 +3376,9 @@ impl ProxyInterface for () { } } -/// Pallets that hold per-subnet commitments implement this to purge all state for `netuid`. -pub trait CommitmentsInterface { +/// Interface for purging commitment state when subnets or neurons are removed. +pub trait CommitmentsInterface { fn purge_netuid(netuid: NetUid, weight_meter: &mut WeightMeter) -> bool; + + fn purge_neuron(netuid: NetUid, account: &AccountId); } diff --git a/pallets/subtensor/src/macros/config.rs b/pallets/subtensor/src/macros/config.rs index 6f6718a15c..c95298ba8d 100644 --- a/pallets/subtensor/src/macros/config.rs +++ b/pallets/subtensor/src/macros/config.rs @@ -61,8 +61,8 @@ mod config { /// Interface to get commitments. type GetCommitments: GetCommitments; - /// Interface to clean commitments on network dissolution. - type CommitmentsInterface: CommitmentsInterface; + /// Interface to clean commitments when a network or neuron is removed. + type CommitmentsInterface: CommitmentsInterface; /// Interface to mint, burn, and recycle subnet alpha. type AlphaAssets: AlphaAssetsInterface; diff --git a/pallets/subtensor/src/subnets/uids.rs b/pallets/subtensor/src/subnets/uids.rs index 9720be0765..e8a76119a4 100644 --- a/pallets/subtensor/src/subnets/uids.rs +++ b/pallets/subtensor/src/subnets/uids.rs @@ -224,6 +224,8 @@ impl Pallet { // Remove hotkey related storage items if hotkey exists if let Ok(hotkey) = Keys::::try_get(netuid, neuron_uid) { + T::CommitmentsInterface::purge_neuron(netuid, &hotkey); + // Same root-churn finalization as `replace_neuron`: deposit while // still on root, then recycle leftover dust after membership drops. if netuid.is_root() { diff --git a/pallets/subtensor/src/tests/mock.rs b/pallets/subtensor/src/tests/mock.rs index 0452471018..81e66a505b 100644 --- a/pallets/subtensor/src/tests/mock.rs +++ b/pallets/subtensor/src/tests/mock.rs @@ -439,13 +439,17 @@ impl PrivilegeCmp for OriginPrivilegeCmp { } pub struct CommitmentsI; -impl CommitmentsInterface for CommitmentsI { +impl CommitmentsInterface for CommitmentsI { fn purge_netuid( netuid: NetUid, weight_meter: &mut frame_support::weights::WeightMeter, ) -> bool { CommitmentsPallet::::purge_netuid(netuid, weight_meter) } + + fn purge_neuron(netuid: NetUid, account: &AccountId) { + CommitmentsPallet::::purge_neuron(netuid, account); + } } parameter_types! { diff --git a/pallets/subtensor/src/tests/mock_high_ed.rs b/pallets/subtensor/src/tests/mock_high_ed.rs index f991cab592..09c730a7ee 100644 --- a/pallets/subtensor/src/tests/mock_high_ed.rs +++ b/pallets/subtensor/src/tests/mock_high_ed.rs @@ -345,13 +345,15 @@ impl PrivilegeCmp for OriginPrivilegeCmp { } pub struct CommitmentsI; -impl CommitmentsInterface for CommitmentsI { +impl CommitmentsInterface for CommitmentsI { fn purge_netuid( _netuid: NetUid, _weight_meter: &mut frame_support::weights::WeightMeter, ) -> bool { true } + + fn purge_neuron(_netuid: NetUid, _account: &AccountId) {} } parameter_types! { diff --git a/pallets/subtensor/src/tests/uids.rs b/pallets/subtensor/src/tests/uids.rs index edf41ebb01..40a09c3a90 100644 --- a/pallets/subtensor/src/tests/uids.rs +++ b/pallets/subtensor/src/tests/uids.rs @@ -2,7 +2,8 @@ use super::mock::*; use crate::*; -use frame_support::{assert_err, assert_ok}; +use frame_support::{BoundedVec, assert_err, assert_ok}; +use pallet_commitments::{CommitmentInfo, Data}; use sp_core::{H160, U256}; use sp_runtime::PerU16; use subtensor_runtime_common::{AlphaBalance, NetUidStorageIndex}; @@ -11,6 +12,46 @@ use subtensor_runtime_common::{AlphaBalance, NetUidStorageIndex}; tests for uids.rs file *********************************************/ +#[test] +fn test_trim_to_max_allowed_uids_purges_removed_neuron_commitment() { + new_test_ext(1).execute_with(|| { + let netuid = NetUid::from(1); + let removed_hotkey = U256::from(1); + let retained_hotkey = U256::from(2); + + add_network(netuid, 13, 0); + MinAllowedUids::::insert(netuid, 2); + SubtensorModule::set_immunity_period(netuid, 0); + + for hotkey in [removed_hotkey, retained_hotkey, U256::from(3)] { + SubtensorModule::append_neuron(netuid, &hotkey, 0); + } + let emissions: Vec = vec![0.into(), 2.into(), 1.into()]; + Emission::::insert(netuid, emissions); + + let commitment = || { + Box::new(CommitmentInfo { + fields: BoundedVec::try_from(vec![Data::None]).unwrap(), + }) + }; + assert_ok!(Commitments::set_commitment( + RuntimeOrigin::signed(removed_hotkey), + netuid, + commitment(), + )); + assert_ok!(Commitments::set_commitment( + RuntimeOrigin::signed(retained_hotkey), + netuid, + commitment(), + )); + + assert_ok!(SubtensorModule::trim_to_max_allowed_uids(netuid, 2)); + + assert!(Commitments::commitment_of(netuid, removed_hotkey).is_none()); + assert!(Commitments::commitment_of(netuid, retained_hotkey).is_some()); + }); +} + /******************************************** tests uids::replace_neuron() *********************************************/ diff --git a/pallets/transaction-fee/src/tests/mock.rs b/pallets/transaction-fee/src/tests/mock.rs index a539e389fe..7b9aab0b69 100644 --- a/pallets/transaction-fee/src/tests/mock.rs +++ b/pallets/transaction-fee/src/tests/mock.rs @@ -452,13 +452,15 @@ impl PrivilegeCmp for OriginPrivilegeCmp { } pub struct CommitmentsI; -impl pallet_subtensor::CommitmentsInterface for CommitmentsI { +impl pallet_subtensor::CommitmentsInterface for CommitmentsI { fn purge_netuid( _netuid: NetUid, _weight_meter: &mut frame_support::weights::WeightMeter, ) -> bool { true } + + fn purge_neuron(_netuid: NetUid, _account: &AccountId) {} } parameter_types! { diff --git a/precompiles/src/mock.rs b/precompiles/src/mock.rs index d42fb253eb..ad207d2484 100644 --- a/precompiles/src/mock.rs +++ b/precompiles/src/mock.rs @@ -432,13 +432,15 @@ impl AuthorshipInfo for MockAuthorshipProvider { } pub struct CommitmentsI; -impl pallet_subtensor::CommitmentsInterface for CommitmentsI { +impl pallet_subtensor::CommitmentsInterface for CommitmentsI { fn purge_netuid( _netuid: NetUid, _weight_meter: &mut frame_support::weights::WeightMeter, ) -> bool { true } + + fn purge_neuron(_netuid: NetUid, _account: &AccountId) {} } impl pallet_subtensor::Config for Runtime { diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 27fe5f0c2c..d265fe241b 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -625,13 +625,17 @@ impl ProxyInterface for Proxier { } pub struct CommitmentsI; -impl CommitmentsInterface for CommitmentsI { +impl CommitmentsInterface for CommitmentsI { fn purge_netuid( netuid: NetUid, weight_meter: &mut frame_support::weights::WeightMeter, ) -> bool { pallet_commitments::Pallet::::purge_netuid(netuid, weight_meter) } + + fn purge_neuron(netuid: NetUid, account: &AccountId) { + pallet_commitments::Pallet::::purge_neuron(netuid, account); + } } parameter_types! { From 2904c51236ffd4cc1e6261ef10374d1409cb5b9c Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Fri, 7 Aug 2026 12:53:21 -0700 Subject: [PATCH 45/58] propagate inner post-dispatch weight --- pallets/proxy/src/lib.rs | 25 ++++++++++------ pallets/proxy/src/tests.rs | 58 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/pallets/proxy/src/lib.rs b/pallets/proxy/src/lib.rs index 1fca855327..488889e7ec 100644 --- a/pallets/proxy/src/lib.rs +++ b/pallets/proxy/src/lib.rs @@ -39,6 +39,7 @@ use frame::{ prelude::*, traits::{Currency, InstanceFilter, ReservableCurrency}, }; +use frame_support::dispatch::extract_actual_weight; use frame_system::pallet_prelude::BlockNumberFor as SystemBlockNumberFor; pub use pallet::*; use subtensor_macros::freeze_struct; @@ -126,7 +127,7 @@ pub mod pallet { pub trait Config: frame_system::Config { /// The overarching call type. type RuntimeCall: Parameter - + Dispatchable + + Dispatchable + GetDispatchInfo + From> + IsSubType> @@ -242,15 +243,17 @@ pub mod pallet { real: AccountIdLookupOf, force_proxy_type: Option, call: Box<::RuntimeCall>, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let real = T::Lookup::lookup(real)?; let def = Self::find_proxy(&real, &who, force_proxy_type)?; ensure!(def.delay.is_zero(), Error::::Unannounced); - Self::do_proxy(def, real, *call); + let weight = T::WeightInfo::proxy(T::MaxProxies::get()) + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) + .saturating_add(Self::do_proxy(def, real, *call)); - Ok(()) + Ok(Some(weight).into()) } /// Register a proxy account for the sender that is able to make calls on its behalf. @@ -552,7 +555,7 @@ pub mod pallet { real: AccountIdLookupOf, force_proxy_type: Option, call: Box<::RuntimeCall>, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { ensure_signed(origin)?; let delegate = T::Lookup::lookup(delegate)?; let real = T::Lookup::lookup(real)?; @@ -567,9 +570,11 @@ pub mod pallet { }) .map_err(|_| Error::::Unannounced)?; - Self::do_proxy(def, real, *call); + let weight = T::WeightInfo::proxy_announced(T::MaxPending::get(), T::MaxProxies::get()) + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) + .saturating_add(Self::do_proxy(def, real, *call)); - Ok(()) + Ok(Some(weight).into()) } /// Poke / Adjust deposits made for proxies and announcements based on current values. @@ -1101,7 +1106,7 @@ impl Pallet { def: ProxyDefinition>, real: T::AccountId, call: ::RuntimeCall, - ) { + ) -> Weight { use frame::traits::{InstanceFilter as _, OriginTrait as _}; // This is a freshly authenticated new account, the origin restrictions doesn't apply. let mut origin: T::RuntimeOrigin = frame_system::RawOrigin::Signed(real.clone()).into(); @@ -1127,13 +1132,17 @@ impl Pallet { _ => def.proxy_type.filter(c), } }); + let info = call.get_dispatch_info(); let e = call.dispatch(origin); + let actual_weight = extract_actual_weight(&e, &info); LastCallResult::::insert(real, e.map(|_| ()).map_err(|e| e.error)); Self::deposit_event(Event::ProxyExecuted { result: e.map(|_| ()).map_err(|e| e.error), }); + + actual_weight } /// Removes all proxy delegates for a given delegator. diff --git a/pallets/proxy/src/tests.rs b/pallets/proxy/src/tests.rs index 5bc5be2415..d3ce6f82cf 100644 --- a/pallets/proxy/src/tests.rs +++ b/pallets/proxy/src/tests.rs @@ -175,6 +175,12 @@ fn call_transfer(dest: u64, value: u64) -> RuntimeCall { RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) } +fn call_batch_with_refund() -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch { + calls: vec![call_transfer(6, 20), call_transfer(6, 1)], + }) +} + #[test] fn announcement_works() { new_test_ext().execute_with(|| { @@ -363,6 +369,58 @@ fn calling_proxy_doesnt_remove_announcement() { }); } +#[test] +fn proxy_propagates_inner_actual_weight() { + new_test_ext().execute_with(|| { + assert_ok!(Proxy::add_proxy( + RuntimeOrigin::signed(1), + 2, + ProxyType::Any, + 0 + )); + + let call = RuntimeCall::Proxy(ProxyCall::new_call_variant_proxy( + 1, + None, + Box::new(call_batch_with_refund()), + )); + let info = call.get_dispatch_info(); + let result = call.dispatch(RuntimeOrigin::signed(2)); + + assert_ok!(result); + assert_ne!(extract_actual_weight(&result, &info), info.call_weight); + }); +} + +#[test] +fn proxy_announced_propagates_inner_actual_weight() { + new_test_ext().execute_with(|| { + assert_ok!(Proxy::add_proxy( + RuntimeOrigin::signed(1), + 2, + ProxyType::Any, + 1 + )); + + let call = Box::new(call_batch_with_refund()); + assert_ok!(Proxy::announce( + RuntimeOrigin::signed(2), + 1, + BlakeTwo256::hash_of(&call) + )); + System::set_block_number(2); + + let call = RuntimeCall::Proxy(ProxyCall::new_call_variant_proxy_announced( + 2, 1, None, call, + )); + let info = call.get_dispatch_info(); + let result = call.dispatch(RuntimeOrigin::signed(0)); + + assert_ok!(result); + assert_ne!(extract_actual_weight(&result, &info), info.call_weight); + }); +} + #[test] fn delayed_requires_pre_announcement() { new_test_ext().execute_with(|| { From bf69eeac5b063e3b2b403203e977777f09c305e4 Mon Sep 17 00:00:00 2001 From: UnarbosFour Date: Fri, 7 Aug 2026 18:11:15 -0400 Subject: [PATCH 46/58] clippy --- pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs b/pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs index 6921d35383..4e61dfeda9 100644 --- a/pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs +++ b/pallets/subtensor/src/migrations/migrate_storage_bloat_v2.rs @@ -160,9 +160,7 @@ pub fn continue_storage_bloat_cleanup(limit: Weight) -> Weight { let work_limit = limit.saturating_sub(pass_overhead); let mut work_weight = Weight::zero(); - while usize::from(progress.target) < TARGETS.len() { - let target = TARGETS[usize::from(progress.target)]; - + while let Some(target) = TARGETS.get(usize::from(progress.target)).copied() { let item_weight = scan_item_weight::(target.mode); if !work_weight.saturating_add(item_weight).all_lte(work_limit) { break; From d251f45b0c92b43112a1c4727d3b93bcc1537e33 Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Mon, 10 Aug 2026 07:13:43 -0700 Subject: [PATCH 47/58] purge on neuron dereg --- pallets/subtensor/src/subnets/uids.rs | 2 ++ pallets/subtensor/src/tests/uids.rs | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/pallets/subtensor/src/subnets/uids.rs b/pallets/subtensor/src/subnets/uids.rs index e8a76119a4..ee08f78a61 100644 --- a/pallets/subtensor/src/subnets/uids.rs +++ b/pallets/subtensor/src/subnets/uids.rs @@ -91,6 +91,8 @@ impl Pallet { let _ = Self::flush_basket_deposits_for_hotkey(&old_hotkey); } + T::CommitmentsInterface::purge_neuron(netuid, &old_hotkey); + // 2. Remove previous set memberships. Uids::::remove(netuid, old_hotkey.clone()); Self::remove_associated_evm_address(netuid, uid_to_replace); diff --git a/pallets/subtensor/src/tests/uids.rs b/pallets/subtensor/src/tests/uids.rs index 40a09c3a90..1b714c95f0 100644 --- a/pallets/subtensor/src/tests/uids.rs +++ b/pallets/subtensor/src/tests/uids.rs @@ -105,6 +105,13 @@ fn test_replace_neuron() { ); Prometheus::::insert(netuid, hotkey_account_id, PrometheusInfoOf::default()); SubtensorModule::set_associated_evm_address(netuid, neuron_uid, evm_address, 1); + assert_ok!(Commitments::set_commitment( + RuntimeOrigin::signed(hotkey_account_id), + netuid, + Box::new(CommitmentInfo { + fields: BoundedVec::try_from(vec![Data::None]).unwrap(), + }), + )); // Replace the neuron. SubtensorModule::replace_neuron(netuid, neuron_uid, &new_hotkey_account_id, block_number); @@ -169,6 +176,10 @@ fn test_replace_neuron() { ); assert_eq!(AssociatedEvmAddress::::get(netuid, neuron_uid), None); assert!(AssociatedUidsByEvmAddress::::get(netuid, evm_address).is_empty()); + assert!( + Commitments::commitment_of(netuid, hotkey_account_id).is_none(), + "deregistered neuron's commitment should be purged" + ); }); } From 3d74b6ee770a5f903f344eb136e59199faab6588 Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Mon, 10 Aug 2026 09:01:13 -0700 Subject: [PATCH 48/58] fix: clear voting power state on subnet dissolutio --- pallets/subtensor/src/subnets/dissolution.rs | 8 +++++- pallets/subtensor/src/tests/networks.rs | 30 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/src/subnets/dissolution.rs b/pallets/subtensor/src/subnets/dissolution.rs index 0410325e6a..a90ecc49b2 100644 --- a/pallets/subtensor/src/subnets/dissolution.rs +++ b/pallets/subtensor/src/subnets/dissolution.rs @@ -165,6 +165,8 @@ impl Pallet { Keys::::clear_prefix(netuid, limit, None) }) && clear_prefix_with_meter(weight_meter, write_weight, |limit| { Uids::::clear_prefix(netuid, limit, None) + }) && clear_prefix_with_meter(weight_meter, write_weight, |limit| { + VotingPower::::clear_prefix(netuid, limit, None) }) && clear_prefix_with_meter(weight_meter, write_weight, |limit| { BlockAtRegistration::::clear_prefix(netuid, limit, None) }) && clear_prefix_with_meter(weight_meter, write_weight, |limit| { @@ -281,7 +283,7 @@ impl Pallet { pub fn remove_network_parameters(netuid: NetUid, weight_meter: &mut WeightMeter) -> bool { // Flat write charge for the `::remove(netuid)` list below. Bump this when // adding or removing entries from that list so the weight stays in step. - let removal_weight = T::DbWeight::get().writes(82); + let removal_weight = T::DbWeight::get().writes(86); if !weight_meter.can_consume(removal_weight) { return false; } @@ -373,6 +375,10 @@ impl Pallet { LastEpochBlock::::remove(netuid); PendingEpochAt::::remove(netuid); SubnetEpochIndex::::remove(netuid); + TotalVotingPower::::remove(netuid); + VotingPowerTrackingEnabled::::remove(netuid); + VotingPowerDisableAtBlock::::remove(netuid); + VotingPowerEmaAlpha::::remove(netuid); if SubnetIdentitiesV3::::contains_key(netuid) { SubnetIdentitiesV3::::remove(netuid); diff --git a/pallets/subtensor/src/tests/networks.rs b/pallets/subtensor/src/tests/networks.rs index a1af973eb6..2aafcaf9fc 100644 --- a/pallets/subtensor/src/tests/networks.rs +++ b/pallets/subtensor/src/tests/networks.rs @@ -3286,6 +3286,36 @@ fn registered_subnet_counter_survives_dissolve_and_bumps_on_reregistration() { }); } +#[test] +fn dissolve_clears_voting_power_state_before_netuid_reuse() { + new_test_ext(1).execute_with(|| { + SubtensorModule::set_max_subnets(2); + + let owner_cold = U256::from(100); + let owner_hot = U256::from(101); + let voter = U256::from(102); + let netuid = add_dynamic_network(&owner_hot, &owner_cold); + + VotingPower::::insert(netuid, voter, 42); + TotalVotingPower::::insert(netuid, 42); + VotingPowerTrackingEnabled::::insert(netuid, true); + VotingPowerDisableAtBlock::::insert(netuid, 123); + VotingPowerEmaAlpha::::insert(netuid, 456); + + assert_ok!(SubtensorModule::do_dissolve_network(netuid)); + run_block_idle(); + + let reused_netuid = add_dynamic_network(&owner_hot, &owner_cold); + assert_eq!(reused_netuid, netuid); + assert_eq!(SubtensorModule::get_total_voting_power(netuid), 0); + assert!(!VotingPower::::contains_key(netuid, voter)); + assert!(!TotalVotingPower::::contains_key(netuid)); + assert!(!VotingPowerTrackingEnabled::::contains_key(netuid)); + assert!(!VotingPowerDisableAtBlock::::contains_key(netuid)); + assert!(!VotingPowerEmaAlpha::::contains_key(netuid)); + }); +} + #[test] fn dissolve_async_cleanup_leaves_phase_unset_until_idle_finishes() { new_test_ext(0).execute_with(|| { From 78443705609d5fb0c07ca4fcf0983f36337e7e36 Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Mon, 10 Aug 2026 09:21:07 -0700 Subject: [PATCH 49/58] preserve wrapper order for saved multisig dispatch --- sdk/python/bittensor/cli/context.py | 4 +- sdk/python/bittensor/cli/multisig_helpers.py | 18 +---- sdk/python/bittensor/executor.py | 78 ++++++++++++------- sdk/python/bittensor/intents/base.py | 9 +++ sdk/python/bittensor/intents/multisig.py | 54 +++++++++++-- sdk/python/tests/unit/test_multisig_safety.py | 44 +++++++++++ 6 files changed, 155 insertions(+), 52 deletions(-) diff --git a/sdk/python/bittensor/cli/context.py b/sdk/python/bittensor/cli/context.py index a1a70e3b0a..4803ebce33 100644 --- a/sdk/python/bittensor/cli/context.py +++ b/sdk/python/bittensor/cli/context.py @@ -677,9 +677,9 @@ async def _registration_preview(client): # Privileged intents say up front which key the chain will accept, so # nobody signs (or approves a multisig) before learning the call needs # a different origin. - if intent.origin == "root": + if semantic_intent.origin == "root": self.output.message("[dim]requires: chain sudo key (call wrapped in Sudo.sudo)[/dim]") - elif intent.origin == "subnet_owner": + elif semantic_intent.origin == "subnet_owner": self.output.message("[dim]requires: subnet owner coldkey[/dim]") if self.uses_extension_signer(): diff --git a/sdk/python/bittensor/cli/multisig_helpers.py b/sdk/python/bittensor/cli/multisig_helpers.py index 48bd6456ef..8aec45145e 100644 --- a/sdk/python/bittensor/cli/multisig_helpers.py +++ b/sdk/python/bittensor/cli/multisig_helpers.py @@ -393,7 +393,6 @@ def wrap_intent_for_multisig_wallet(app_ctx, intent): MultisigIntentAdapter, MultisigThreshold1, MultisigThreshold1IntentAdapter, - _compose_inner, ) if getattr(intent, "signer", None) != "coldkey": @@ -423,28 +422,15 @@ def wrap_intent_for_multisig_wallet(app_ctx, intent): dispatch = MultisigThreshold1(other_signatories=others, call=call_dict) return MultisigThreshold1IntentAdapter(dispatch=dispatch, semantic=intent) - async def _timepoint(client): - wallet = wallets.open_wallet(member_name, path=app_ctx.wallet_path) - inner = await _compose_inner(client._substrate, wallet, call_dict) - return await pending_timepoint_for_call( - client, - signatories=signatories, - threshold=threshold, - call_hash=inner.call_hash, - signer_ss58=signer_ss58, - ) - - timepoint = app_ctx.run(_timepoint) - action = "approving" if timepoint else "opening" app_ctx.output.message( - f"[dim]{action} via {threshold}-of-{len(signatories)} multisig {preset} " + f"[dim]dispatching via {threshold}-of-{len(signatories)} multisig {preset} " f"as {format_signatory_display(signer_ss58, member_name)}[/dim]" ) dispatch = MultisigExecute( threshold=threshold, other_signatories=others, call=call_dict, - timepoint=timepoint, + timepoint=None, ) return MultisigIntentAdapter(dispatch=dispatch, semantic=intent) diff --git a/sdk/python/bittensor/executor.py b/sdk/python/bittensor/executor.py index 1309794eca..25341dbbb8 100644 --- a/sdk/python/bittensor/executor.py +++ b/sdk/python/bittensor/executor.py @@ -91,6 +91,37 @@ def _coerce_addresses(intent: Intent) -> Intent: return replace(intent, **changes) if changes else intent +async def _compose_intent_call( + substrate: Substrate, + intent: Intent, + wallet: WalletLike, + *, + proxy_for: Optional[str] = None, + proxy_type: Optional[str] = None, +) -> tuple[Any, dict]: + """Compose semantic call -> sudo -> proxy -> execution adapter.""" + semantic = _coerce_addresses(intent.semantic_intent()) + built = await semantic.build(substrate, wallet) + if isinstance(built, BuiltCall): + call, extras = built.call, built.extras + else: + call, extras = built, {} + + call = await _wrap_root_call(substrate, semantic, call) + if proxy_for is not None: + if proxy_type is not None: + check_proxy_type(proxy_type) + call = await substrate.compose( + generated_calls.Proxy.proxy(real=proxy_for, force_proxy_type=proxy_type, call=call) + ) + extras = {**extras, "proxy_for": proxy_for} + + wrapped = await intent.wrap_call(substrate, wallet, call) + if isinstance(wrapped, BuiltCall): + return wrapped.call, {**extras, **wrapped.extras} + return wrapped, extras + + def _find_event(events: list, module_id: str, event_id: str) -> Optional[Any]: """The attributes of the first matching triggered event, or None.""" for entry in events: @@ -470,34 +501,24 @@ async def plan( ``proxy_for`` switches to proxy signing: the call is wrapped in ``Proxy.proxy(real=proxy_for)`` so it dispatches with that account's - origin, while the *local* wallet key (which must be a registered proxy of - ``proxy_for``) signs. ``proxy_type`` optionally forces the exact proxy - type to match (``force_proxy_type``). + origin. The effective dispatch account (the direct signer or saved + multisig) must be a registered proxy of ``proxy_for``. ``proxy_type`` + optionally forces the exact proxy type to match (``force_proxy_type``). """ wallet = as_wallet(wallet) intent = _coerce_addresses(intent) - built = await intent.build(self.substrate, wallet) - if isinstance(built, BuiltCall): - call, extras = built.call, built.extras - else: - call, extras = built, {} - # Root intents declare privilege via ``origin``; wrap here so metadata - # and execution cannot drift (an intent that forgets Sudo.sudo still - # dispatches as root, and docs stay authoritative). - call = await _wrap_root_call(self.substrate, intent, call) + call, extras = await _compose_intent_call( + self.substrate, + intent, + wallet, + proxy_for=proxy_for, + proxy_type=proxy_type, + ) pub = self._public_keypair(wallet, intent.signer) signer_address = pub.ss58_address # The account whose state the call actually touches. origin = proxy_for or signer_address - if proxy_for is not None: - if proxy_type is not None: - check_proxy_type(proxy_type) - call = await self.substrate.compose( - generated_calls.Proxy.proxy(real=proxy_for, force_proxy_type=proxy_type, call=call) - ) - extras = {**extras, "proxy_for": proxy_for} - warnings: list[str] = list(await intent.warnings(self.substrate, origin)) if intent.signer == "hotkey" and proxy_for is None and charges_coldkey_fee(call): warnings.append(COLDKEY_FEE_WARNING) @@ -546,8 +567,8 @@ async def execute( """Plan, then sign and submit. Raises ``PolicyError`` if the plan violates policy. (To preview without submitting, call ``plan`` instead.) - With ``proxy_for``, the local wallet key signs a ``Proxy.proxy`` wrapper - and the call dispatches as ``proxy_for`` — the real account's key never + With ``proxy_for``, the direct signer or saved multisig dispatches a + ``Proxy.proxy`` wrapper as ``proxy_for`` — the real account's key never touches this machine (see ``plan``). ``retries`` resubmits (up to that many extra times, one block apart) when @@ -673,11 +694,7 @@ async def submit_shielded( """ wallet = as_wallet(wallet) intent = _coerce_addresses(intent) - built = await intent.build(self.substrate, wallet) - call = built.call if isinstance(built, BuiltCall) else built - # Same root wrapping as ``plan``/``execute``: the decrypted inner - # extrinsic must dispatch ``Sudo.sudo``, not the bare AdminUtils call. - call = await _wrap_root_call(self.substrate, intent, call) + call, extras = await _compose_intent_call(self.substrate, intent, wallet) fee = None active = self._active_policy(policy) if active is not None and active.max_fee_tao is not None: @@ -727,7 +744,12 @@ async def submit_shielded( if result.success: result = replace( result, - data={**result.data, "shielded": True, "inner_extrinsic_hash": inner_hash}, + data={ + **result.data, + **extras, + "shielded": True, + "inner_extrinsic_hash": inner_hash, + }, ) if result.success and (wait_for_inclusion or wait_for_finalization): # The carrier's success only proves the ciphertext was accepted; diff --git a/sdk/python/bittensor/intents/base.py b/sdk/python/bittensor/intents/base.py index 5f7eda0b78..1f68ee020a 100644 --- a/sdk/python/bittensor/intents/base.py +++ b/sdk/python/bittensor/intents/base.py @@ -168,6 +168,15 @@ async def warnings(self, substrate: "Substrate", signer_address: str) -> list[st """Non-fatal cautions surfaced by ``plan`` (e.g. dust amounts).""" return [] + async def wrap_call(self, substrate: "Substrate", wallet: "Any", call: Any): + """Apply an execution wrapper around an already composed semantic call. + + The executor calls this after root and proxy composition. Ordinary + intents leave the call unchanged; execution adapters such as saved + multisigs add their transport wrapper here. + """ + return call + # Key views ---------------------------------------------------------------- # # Intents never touch private keys, but some need the *addresses* of the diff --git a/sdk/python/bittensor/intents/multisig.py b/sdk/python/bittensor/intents/multisig.py index 5b281e1d35..2cee2e8a7e 100644 --- a/sdk/python/bittensor/intents/multisig.py +++ b/sdk/python/bittensor/intents/multisig.py @@ -18,7 +18,7 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass, field, replace from typing import Any, Optional from .._generated import calls @@ -94,6 +94,31 @@ def _inner_call_extras(inner) -> dict: } +async def _pending_timepoint(substrate, dispatch, wallet: Any, inner): + """Resolve a saved multisig's timepoint from the final inner call hash.""" + if dispatch.timepoint is not None: + return dispatch.timepoint + + signer = public_view(wallet, "coldkey").ss58_address + signatories = [signer, *dispatch.other_signatories] + account = substrate.multisig_account(signatories, dispatch.threshold) + call_hash = bytes(inner.call_hash) + pending = await substrate.query("Multisig", "Multisigs", [account.ss58_address, call_hash]) + if pending is None: + pending = await substrate.query( + "Multisig", "Multisigs", [account.ss58_address, "0x" + call_hash.hex()] + ) + if pending is None: + return None + if signer in {str(approval) for approval in pending.get("approvals") or []}: + raise ValueError( + f"this signatory already approved pending call 0x{call_hash.hex()}; " + "wait for another member, or cancel the operation" + ) + when = pending.get("when") or {} + return {"height": int(when.get("height", 0)), "index": int(when.get("index", 0))} + + THRESHOLD_HELP = ( "Number of approvals required to execute, counting the signer. Together with " "the full signatory set it identifies the multisig account, so it must match " @@ -142,6 +167,9 @@ class MultisigThreshold1(Intent): async def build(self, substrate, wallet: Any): inner = await _compose_inner(substrate, wallet, self.call) + return await self._build_with_inner(substrate, wallet, inner) + + async def _build_with_inner(self, substrate, wallet: Any, inner): return await substrate.compose( calls.Multisig.as_multi_threshold_1( other_signatories=_sorted_signatories(self.other_signatories), call=inner @@ -179,8 +207,11 @@ class MultisigExecute(Intent): timepoint: Optional[dict] = field(default=None, metadata={"help": TIMEPOINT_HELP}) async def build(self, substrate, wallet: Any): - _validate_multisig(self.threshold, self.other_signatories, self.coldkey_address(wallet)) inner = await _compose_inner(substrate, wallet, self.call) + return await self._build_with_inner(substrate, wallet, inner) + + async def _build_with_inner(self, substrate, wallet: Any, inner): + _validate_multisig(self.threshold, self.other_signatories, self.coldkey_address(wallet)) view = public_view(wallet, "coldkey") max_weight = await substrate.estimate_weight(inner, view) composed = await substrate.compose( @@ -226,10 +257,11 @@ class MultisigIntentAdapter(Intent): """Keep an inner intent's safety contract while dispatching it by multisig. Saved-multisig CLI wallets turn a regular coldkey intent into one of the - concrete multisig intents above. The concrete intent owns call composition, - while ``semantic`` remains authoritative for policy scope and MEV handling. - This adapter is internal and deliberately unregistered: it is execution - state, not a separate operation exposed by the SDK. + concrete multisig intents above. The executor composes the semantic call's + sudo and proxy layers first; this adapter adds only the outer multisig layer. + ``semantic`` remains authoritative for policy and execution semantics. This + adapter is internal and deliberately unregistered: it is execution state, + not a separate operation exposed by the SDK. """ op = "multisig_execute" @@ -249,6 +281,16 @@ def other_signatories(self) -> list: async def build(self, substrate, wallet: Any): return await self.dispatch.build(substrate, wallet) + async def wrap_call(self, substrate, wallet: Any, call): + dispatch = self.dispatch + if isinstance(dispatch, MultisigExecute): + dispatch = replace( + dispatch, + timepoint=await _pending_timepoint(substrate, dispatch, wallet, call), + ) + self.dispatch = dispatch + return await dispatch._build_with_inner(substrate, wallet, call) + def summary(self) -> str: return self.dispatch.summary() diff --git a/sdk/python/tests/unit/test_multisig_safety.py b/sdk/python/tests/unit/test_multisig_safety.py index 720593e699..25954368e2 100644 --- a/sdk/python/tests/unit/test_multisig_safety.py +++ b/sdk/python/tests/unit/test_multisig_safety.py @@ -6,15 +6,19 @@ import pytest from bittensor import Policy +from bittensor._generated import calls from bittensor.cli import multisig_helpers from bittensor.client import Client from bittensor.executor import Executor from bittensor.intents._money import UNBOUNDED from bittensor.intents.multisig import ( + MultisigExecute, + MultisigIntentAdapter, MultisigThreshold1, MultisigThreshold1IntentAdapter, ) from bittensor.intents.registration import BurnedRegister +from bittensor.intents.root import SetSubnetEmissionEnabled from tests.harness.fake_substrate import FakeSubstrate from tests.harness.samples import ALICE, ALICE_HOT, BOB, dev_wallet @@ -92,3 +96,43 @@ async def test_required_mev_shield_survives_multisig_dispatch(): wait_for_inclusion=True, wait_for_finalization=True, ) + + +@pytest.mark.asyncio +async def test_saved_multisig_composes_sudo_and_proxy_inside_multisig(): + substrate = FakeSubstrate() + wallet = dev_wallet() + semantic = SetSubnetEmissionEnabled(netuids=[7], enabled=True) + semantic_call = await semantic.build(substrate, wallet) + sudo = await substrate.compose(calls.Sudo.sudo(call=semantic_call)) + proxy = await substrate.compose(calls.Proxy.proxy(real=BOB, force_proxy_type=None, call=sudo)) + multisig_account = substrate.multisig_account([ALICE, BOB], 2) + substrate.seed( + "Multisig", + "Multisigs", + [multisig_account.ss58_address, proxy.call_hash], + {"when": {"height": 12, "index": 3}, "approvals": [BOB]}, + ) + substrate.seed("System", "Account", [ALICE], {"data": {"free": 10**9}}) + + dispatch = MultisigExecute( + threshold=2, + other_signatories=[BOB], + call=semantic.to_dict(), + ) + wrapped = MultisigIntentAdapter(dispatch=dispatch, semantic=semantic) + + plan = await Client("local", substrate=substrate).plan(wrapped, wallet, proxy_for=BOB) + + multisig = plan.call + assert (multisig.module, multisig.function) == ("Multisig", "as_multi") + assert multisig.params["maybe_timepoint"] == {"height": 12, "index": 3} + proxy = multisig.params["call"] + assert (proxy.module, proxy.function) == ("Proxy", "proxy") + sudo = proxy.params["call"] + assert (sudo.module, sudo.function) == ("Sudo", "sudo") + semantic_call = sudo.params["call"] + assert (semantic_call.module, semantic_call.function) == ( + "AdminUtils", + "sudo_set_subnet_emission_enabled", + ) From 49724bf6b361bb220e1b494b71e9138a724d2e6b Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Mon, 10 Aug 2026 10:08:34 -0700 Subject: [PATCH 50/58] add release page --- .../(pages-without-footer)/releases/page.tsx | 10 + .../releases/v444-upgrade/page.tsx | 392 ++++++++++++++++++ 2 files changed, 402 insertions(+) create mode 100644 website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx diff --git a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/page.tsx b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/page.tsx index c40d898607..019c139935 100644 --- a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/page.tsx +++ b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/page.tsx @@ -22,6 +22,16 @@ type Release = { // Newest first. Add new releases to the top. const releases: Release[] = [ + { + tag: 'v444', + date: 'August 2026', + title: 'Pure Price Emissions', + summary: + 'Subnet emission returns to pure price EMA through the gate. The release also completes ' + + 'the typed EVM surface, makes multisigs first-class btcli wallets, adds human-readable ' + + 'Ledger orders, and lands a broad reliability pass.', + href: '/releases/v444-upgrade', + }, { tag: 'v441', date: 'July 2026', diff --git a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx new file mode 100644 index 0000000000..54880f0bb4 --- /dev/null +++ b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx @@ -0,0 +1,392 @@ +import FadeInWrapper from '@/app/components/FadeInWrapper'; +import {Code} from '@/app/components/Code/Code'; +import {Link} from '@raofoundation/ui'; +import type {Metadata} from 'next'; +import {Suspense} from 'react'; +import styles from '../v436-upgrade/page.module.css'; + +export const metadata: Metadata = { + title: 'The V444 Upgrade — Pure Price Emissions', + description: + 'Subnet emission returns to pure price EMA through the emission gate, while v444 ' + + 'completes the EVM surface, makes btcli safer for multisigs and automation, adds ' + + 'human-readable Ledger orders, and lands a broad reliability pass.', + alternates: {canonical: '/releases/v444-upgrade'}, +}; + +const DocLink = ({href, children}: {href: string; children: React.ReactNode}) => ( + + {children} + +); + +const page = () => { + return ( + }> + +
+

The V444 Upgrade

+

+ Pure Price Emissions · August 2026 +

+
+ +
+

Introduction

+

+ Spec 444 makes the market signal simple again: a subnet's share of + network emission is determined by its moving price, passed through the emission gate. + The share is no longer reduced when a subnet directs miner incentive to an owner or burn + hotkey. Recycling and burning still do exactly what the subnet chose locally; they no + longer change its standing against every other subnet. +

+

+ The release also makes the chain substantially easier to use from every external + surface. Solidity contracts gain five new Bittensor precompiles and 69 functions on + existing interfaces. A saved multisig now behaves like a wallet throughout + btcli. Automated dry runs carry enough information to approve and replay a + transaction safely. Ledger users can read the actual fields of a limit order before + signing it. Underneath those interfaces, v444 corrects transaction-pool validation, + proxy charging, commitment cleanup, storage growth, and GRANDPA finality. +

+
+ +
+

Price is the signal

+

+ The emission gate introduced in v440{' '} + starts with each subnet's share of price EMA, then suppresses emission below the + market-set bar. A second factor had been applied before that gate:{' '} + 1 − MinerBurned. That meant two subnets with the same demand could receive + different cross-network emission solely because one withheld miner incentive for + recycling or burning. +

+ +

+ V444 removes that extra multiplier. MinerBurned remains on-chain as an + informational measure, and the miner-incentive path still recycles or burns according to + the subnet's configuration. What changes is the boundary between local token policy + and network allocation: demand determines how much emission a subnet earns; the subnet + determines what it does with the miner portion after that. +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Miner incentive policyEffect on subnet's network share in v444Local effect
Paid to minersPrice EMA through the gateMiner alpha is distributed
Withheld and recycledPrice EMA through the gateValue returns through the recycle path
Withheld and burnedPrice EMA through the gateValue is removed by the burn path
+

+ Subnet teams do not need to change a setting. Forecasting software should remove the + miner-burn factor from cross-subnet share calculations and retain it only where it + describes the subnet's own incentive accounting. +

+
+ +
+

The runtime, typed for Solidity

+

+ The Bittensor precompile suite now covers the deterministic, typed runtime surface that + an EVM caller is authorized to use. Five new domain addresses expose system state that + previously required a Substrate client or duplicated constants: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AddressPrecompileWhat contracts can inspect
+ 0x…080f + SchedulerScheduled calls, retry state, task addresses, and incomplete work
+ 0x…0810 + DrandBeacon configuration, pulses, stored rounds, and unsigned timing
+ 0x…0811 + TimestampRuntime timestamp and whether it was updated in the current block
+ 0x…0812 + Runtime configuration + Chain ID and grouped economic, consensus, registration, and pallet constants +
+ 0x…0813 + Precompile registryWhether a selector is deprecated, disabled, or replaced
+

+ Existing precompiles gain another 69 functions across staking V2, neurons, subnets, + alpha, balances, proxies, leasing, crowdloans, UID lookup, voting power, and transfer + surfaces. The additions include typed registration and identity operations, weight and + commitment calls, stake and collateral management, subnet configuration, global and + per-subnet state, and a maintained total-voting-power view. The{' '} + coverage audit{' '} + inventories the deliberate exclusions: Root-only, unsigned, inherent, disabled, and + compatibility-only calls are not made reachable by pretending an EVM caller has a + stronger origin. +

+

+ Every state-changing method dispatches the highest-level runtime call as the mapped EVM + signer. The pallet still enforces ownership, role, rate limits, freeze windows, and + every other authorization rule. Released addresses and selectors remain stable; the new + registry gives contracts a typed way to discover lifecycle and operational status before + calling. +

+ +

+ Canonical Solidity interfaces, JSON ABIs, generated Python ABI copies, documentation, + gas accounting, and tests ship together. Integrators should use the v444 copies rather + than reconstructing selectors from release notes. The new maintainer documentation also + fixes the rules for ABI versioning, state exposure, lifecycle metadata, coverage, and + backwards compatibility so later runtime releases can extend this surface without + breaking deployed contracts. +

+
+ +
+

A multisig is now a wallet

+

+ The v11 CLI no longer makes operators translate a multisig workflow into low-level + approvals by hand. Save a signer set once, then pass its name wherever a coldkey wallet + is accepted. Reads resolve the derived account. Writes select a local member, wrap the + intended call, find an existing approval round, and supply its timepoint. A co-signer + completes the round by running the same command. +

+ +

+ Before signing, --dry-run --json now returns the parsed arguments, exact + spend or an explicit unbounded-spend marker, estimated fee, warnings, policy verdict, + and a replay command that submits the same invocation without the dry-run flags. That + makes a plan reviewable by a human, an agent, or a policy engine without asking any of + them to infer intent from prose. +

+ +

+ The same release improves everyday staking: stake add shows free balance, + accepts all, offers local hotkeys without requiring the target to live on + disk, and accepts pasted or address-book targets. stake burn joins the + normal command tree with a price-aware default. Names resolve inside raw-call JSON, + multisig approvals fail early when the signer cannot cover the deposit and fee, and + wrapper order is preserved so intent safety survives multisig dispatch. Root position + rows now stay aligned with their human table columns, and explicit validator details + produce one consolidated JSON document. +

+

+ Secret-bearing flags now warn that values are visible in shell history and the process + list; omitting them uses a hidden prompt. EVM private-key export prefers the clipboard + on a terminal, and wallet regeneration accepts 64-byte sr25519 private keys. Keyfiles + once again include the legacy fields expected by older subnet tooling, while the reader + tolerates older encodings and gives specific guidance for browser and mobile exports. + The complete operational flow is in the{' '} + multisig guide. +

+
+ +
+

Read the order before signing it

+

+ V438 let Ledger and compatible signers + authorize limit orders by signing a wrapped order hash. V444 adds an alternative + clear-signing form: one canonical printable message containing the order type, amount, + subnet, limit or trigger price, expiry, hotkey, relayer policy, fee, slippage, chain ID, + partial-fill policy, and signer. The hardware wallet displays those fields before + approval, and the runtime deterministically rebuilds the same message before accepting + the signature. +

+ on subnet , +limit price , expiry , hotkey , fee to , +relayer , max slippage , chain , +partial fills , signer `} + /> +

+ This format is additive. Existing raw SCALE signatures and wrapped-hash signatures + remain valid, and every format resolves to the same canonical order ID for replay + protection, cancellation, relayer restrictions, and partial fills. Sr25519 and ed25519 + remain supported; ECDSA remains rejected. Rust and TypeScript parity tests plus + device-derived Ledger vectors lock the exact bytes so a frontend cannot show one order + and submit another. +

+
+ +
+

Failures get cheaper, state stays smaller

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AreaChange in v444
Commit transactions + Deterministic failures are rejected during transaction validation; competing + commits in the same signer and rate-limit lane conflict in the pool. +
Neuron trimming + Deregistration purges active and revealed commitments, metadata, usage and + timelock indexes, and releases the associated commitment deposit. +
Proxy fees + proxy and proxy_announced propagate the inner + call's actual post-dispatch weight, refunding unused worst-case weight. +
Storage + A bounded, resumable on_idle migration removes obsolete pre-dTAO + prefixes and explicit zero rows; abandoned Swap V3 state is cleared separately. +
Voting power + A maintained subnet total avoids repeated aggregation, and neuron removal or + subnet dissolution now clears the corresponding voting-power state. +
GRANDPA + The Polkadot SDK is pinned to fork revision cacb4310, including + warp-finality and concluded-round cleanup fixes; testnet's warp checkpoint + now carries the correct authority set and set ID. +
+

+ These changes do not introduce new operator workflows. They move predictable failures + out of blocks, stop deleted identities from leaving chargeable state behind, return + overestimated proxy weight, and keep historical defaults from accumulating forever. +

+
+ +
+

What to do

+
    +
  • + Node operators: wait for the on-chain spec_version to + move to 444, then update to the matching release. Testnet operators should update + promptly for the corrected GRANDPA warp checkpoint. +
  • +
  • + Subnet teams and analysts: remove 1 − MinerBurned from + cross-subnet emission forecasts. The emission gate remains active and miner recycling + or burning remains a local policy. +
  • +
  • + EVM integrators: refresh the complete canonical ABI set before using + v444 selectors. Add 0x…080f through 0x…0813 only from the + published interfaces, and use the registry to inspect selector status. +
  • +
  • + SDK and CLI users: install the matching bittensor 11.1.0 + release and bittensor-core 0.1.3. Existing wallet files remain usable; + saved multisigs can now be passed directly as -w. +
  • +
  • + Limit-order applications: add the human-readable signing format for + hardware-wallet users. Do not remove raw or wrapped-hash support; all three formats + remain valid. +
  • +
+

+ Signers: after the release train proposes, use{' '} + btcli upgrade sign --url <v444 release URL> -w <wallet>. +

+
+ + + Read the complete precompile reference + +
+
+ ); +}; + +export default page; From a91ade05e4331f981e686b5933f4f799e68a04ca Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Mon, 10 Aug 2026 10:28:54 -0700 Subject: [PATCH 51/58] remove unsynchronized burnBalance function --- .../evm/precompiles/account-balance.mdx | 9 +++-- .../evm/precompiles/extrinsic-coverage.mdx | 7 ++-- precompiles/src/balance.rs | 34 +++++++------------ precompiles/src/lib.rs | 12 +++---- precompiles/src/solidity/balance.abi | 20 +---------- precompiles/src/solidity/balance.sol | 1 - sdk/python/bittensor/evm/abi/balance.json | 20 +---------- .../releases/v444-upgrade/page.tsx | 4 +-- 8 files changed, 29 insertions(+), 78 deletions(-) diff --git a/docs/guides/evm/precompiles/account-balance.mdx b/docs/guides/evm/precompiles/account-balance.mdx index 478cbcf9f9..cd39133728 100644 --- a/docs/guides/evm/precompiles/account-balance.mdx +++ b/docs/guides/evm/precompiles/account-balance.mdx @@ -21,13 +21,12 @@ description: Reference for the deployed BalancePrecompile. | Function | Source extrinsic | |---|---| -| `burnBalance` | `Balances.burn` | | `upgradeAccounts` | `Balances.upgrade_accounts` | -`upgradeAccounts` has an explicit input bound of 64 accounts. Both operations -dispatch the highest-level Balances call as the mapped signer and preserve all -runtime authorization and issuance invariants. Force operations require Root -and are not exposed. +`upgradeAccounts` has an explicit input bound of 64 accounts and dispatches the +highest-level Balances call as the mapped signer. `Balances.burn` is not exposed: +the native call updates FRAME Balances issuance without updating Subtensor's +separate issuance ledger. Force operations require Root and are not exposed. Source: [`balance.sol`](https://github.com/RaoFoundation/subtensor/blob/main/precompiles/src/solidity/balance.sol) diff --git a/docs/guides/evm/precompiles/extrinsic-coverage.mdx b/docs/guides/evm/precompiles/extrinsic-coverage.mdx index ce41488e86..f0f0c5bddc 100644 --- a/docs/guides/evm/precompiles/extrinsic-coverage.mdx +++ b/docs/guides/evm/precompiles/extrinsic-coverage.mdx @@ -18,14 +18,14 @@ interface or an explicit proposed typed replacement. |---|---:|---:|---:|---:| | `SubtensorModule` | 82 | 68 | 0 | 14 | | `AdminUtils` | 86 | 40 | 0 | 46 | -| `Balances` | 9 | 5 | 0 | 4 | +| `Balances` | 9 | 4 | 0 | 5 | | `Proxy` | 12 | 11 | 1 | 0 | | `Scheduler` | 10 | 0 | 0 | 10 | | `Drand` | 3 | 0 | 0 | 3 | | `Crowdloan` | 10 | 10 | 0 | 0 | | `Timestamp` | 1 | 0 | 0 | 1 | | `Swap` | 6 | 0 | 0 | 6 | -| **Total** | **219** | **134** | **1** | **84** | +| **Total** | **219** | **133** | **1** | **85** | `Typed today` counts semantic coverage, not only direct dispatch to the same Rust call. For example, `registerNetwork(bytes32)` covers basic subnet @@ -47,7 +47,7 @@ Each implemented operation is listed on the page of its target precompile: | [Staking V2](/docs/guides/evm/precompiles/staking-v2) | 20 | | [Neuron](/docs/guides/evm/precompiles/neuron) | 21 | | [Alpha](/docs/guides/evm/precompiles/alpha) | 3 | -| [Account balance](/docs/guides/evm/precompiles/account-balance) | 2 | +| [Account balance](/docs/guides/evm/precompiles/account-balance) | 1 | | [Proxy](/docs/guides/evm/precompiles/proxy) | 4 | | [Balance transfer](/docs/guides/evm/precompiles/balance-transfer) | 2 | | [Voting power](/docs/guides/evm/precompiles/voting-power) | 2 | @@ -69,6 +69,7 @@ must not add another SCALE-encoded `RuntimeCall` interface. | `SubtensorModule.set_activity_cutoff_factor` | Retained call-index compatibility entry point that succeeds without changing state. The active AdminUtils operation is already covered by `SubnetPrecompile.setActivityCutoffFactor`. | | Root-only `AdminUtils` extrinsics | Root-only administration is not delegated to EVM callers. For calls that also accept a signed subnet owner, the domain precompile dispatches the highest-level call as the mapped EVM signer and preserves its authorization checks. | | `AdminUtils.sudo_set_total_issuance` | Deprecated call that always returns `Deprecated`. | +| `Balances.burn` | The native call reduces FRAME Balances issuance without updating Subtensor's separate issuance ledger, which drives block emission. It is not exposed until the runtime provides a synchronized signed burn operation. | | Root-only `Balances` extrinsics | `force_unreserve`, `force_transfer`, `force_set_balance`, and `force_adjust_total_issuance` require Root. | | All `Scheduler` extrinsics | `Scheduler.ScheduleOrigin` is configured as Root in the runtime. | | `Drand.write_pulse` | Unsigned offchain-worker submission requiring `None` origin. An EVM caller cannot satisfy that origin without changing its security model. | diff --git a/precompiles/src/balance.rs b/precompiles/src/balance.rs index 76f094ee92..91f0987261 100644 --- a/precompiles/src/balance.rs +++ b/precompiles/src/balance.rs @@ -36,7 +36,7 @@ where + IsSubType> + IsSubType> + IsSubType>, - ::Balance: Into + TryFrom, + ::Balance: Into, ::AddressMapping: AddressMapping, { const INDEX: u64 = 2062; @@ -63,7 +63,7 @@ where + IsSubType> + IsSubType> + IsSubType>, - ::Balance: Into + TryFrom, + ::Balance: Into, ::AddressMapping: AddressMapping, { #[precompile::public("getFreeBalance(bytes32)")] @@ -81,26 +81,6 @@ where Ok(pallet_balances::Pallet::::total_issuance().into()) } - #[precompile::public("burnBalance(uint256,bool)")] - fn burn_balance( - handle: &mut impl PrecompileHandle, - amount: U256, - keep_alive: bool, - ) -> EvmResult<()> { - let caller = handle.caller_account_id::(); - let call = pallet_balances::Call::::burn { - value: amount - .try_into() - .map_err(|_| fp_evm::PrecompileFailure::Error { - exit_status: fp_evm::ExitError::Other( - "balance amount does not fit runtime".into(), - ), - })?, - keep_alive, - }; - handle.try_dispatch_runtime_call::(call, RawOrigin::Signed(caller)) - } - #[precompile::public("upgradeAccounts(bytes32[])")] fn upgrade_accounts( handle: &mut impl PrecompileHandle, @@ -152,6 +132,16 @@ mod tests { ) } + #[test] + fn balance_precompile_does_not_expose_unsynchronized_native_burn() { + assert!( + !BalancePrecompileCall::::supports_selector(selector_u32( + "burnBalance(uint256,bool)" + )), + "Balances.burn does not update Subtensor TotalIssuance" + ); + } + #[test] fn balance_precompile_returns_free_balance_for_coldkey() { new_test_ext().execute_with(|| { diff --git a/precompiles/src/lib.rs b/precompiles/src/lib.rs index 174bffc391..0bdcd7902e 100644 --- a/precompiles/src/lib.rs +++ b/precompiles/src/lib.rs @@ -516,13 +516,11 @@ mod address_and_selector_tests { ) ); } - for signature in ["burnBalance(uint256,bool)", "upgradeAccounts(bytes32[])"] { - assert!( - balance::BalancePrecompileCall::::supports_selector(selector_u32( - signature - )) - ); - } + assert!( + balance::BalancePrecompileCall::::supports_selector(selector_u32( + "upgradeAccounts(bytes32[])" + )) + ); for signature in [ "enableVotingPowerTracking(uint16)", "disableVotingPowerTracking(uint16)", diff --git a/precompiles/src/solidity/balance.abi b/precompiles/src/solidity/balance.abi index 52c19b6eb6..6f070e9bf3 100644 --- a/precompiles/src/solidity/balance.abi +++ b/precompiles/src/solidity/balance.abi @@ -18,24 +18,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "keepAlive", - "type": "bool" - } - ], - "name": "burnBalance", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -62,4 +44,4 @@ "stateMutability": "view", "type": "function" } -] \ No newline at end of file +] diff --git a/precompiles/src/solidity/balance.sol b/precompiles/src/solidity/balance.sol index a20075c5ea..9f83e34a32 100644 --- a/precompiles/src/solidity/balance.sol +++ b/precompiles/src/solidity/balance.sol @@ -9,6 +9,5 @@ interface IBalance { /// @return The free balance in rao (1 TAO = 1e9 rao). function getFreeBalance(bytes32 coldkey) external view returns (uint256); function getTotalIssuance() external view returns (uint256); - function burnBalance(uint256 amount, bool keepAlive) external; function upgradeAccounts(bytes32[] calldata accounts) external; } diff --git a/sdk/python/bittensor/evm/abi/balance.json b/sdk/python/bittensor/evm/abi/balance.json index 52c19b6eb6..6f070e9bf3 100644 --- a/sdk/python/bittensor/evm/abi/balance.json +++ b/sdk/python/bittensor/evm/abi/balance.json @@ -18,24 +18,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "keepAlive", - "type": "bool" - } - ], - "name": "burnBalance", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -62,4 +44,4 @@ "stateMutability": "view", "type": "function" } -] \ No newline at end of file +] diff --git a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx index 54880f0bb4..897232817f 100644 --- a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx +++ b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx @@ -42,7 +42,7 @@ const page = () => {

The release also makes the chain substantially easier to use from every external - surface. Solidity contracts gain five new Bittensor precompiles and 69 functions on + surface. Solidity contracts gain five new Bittensor precompiles and 68 functions on existing interfaces. A saved multisig now behaves like a wallet throughout btcli. Automated dry runs carry enough information to approve and replay a transaction safely. Ledger users can read the actual fields of a limit order before @@ -165,7 +165,7 @@ v444: s_i = normalize(price_ema_i)

- Existing precompiles gain another 69 functions across staking V2, neurons, subnets, + Existing precompiles gain another 68 functions across staking V2, neurons, subnets, alpha, balances, proxies, leasing, crowdloans, UID lookup, voting power, and transfer surfaces. The additions include typed registration and identity operations, weight and commitment calls, stake and collateral management, subnet configuration, global and From 73f8092c0316b8e9eb03209417c839394e992a12 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Mon, 10 Aug 2026 19:39:48 +0200 Subject: [PATCH 52/58] fix: restore release CI checks --- .github/docs-preview-vercel/package-lock.json | 6 +- .github/docs-preview-vercel/package.json | 2 +- .../AnnouncementDepositInvariantViolated.mdx | 2 +- docs/errors/chain/ArithmeticOverflow.mdx | 2 +- docs/errors/chain/ChainIdMismatch.mdx | 2 +- docs/errors/chain/Deprecated.mdx | 2 +- docs/errors/chain/Duplicate.mdx | 2 +- docs/errors/chain/DuplicateOrderInBatch.mdx | 2 +- docs/errors/chain/FeeRateTooHigh.mdx | 2 +- .../chain/IncorrectPartialFillAmount.mdx | 2 +- docs/errors/chain/InsufficientBalance.mdx | 2 +- docs/errors/chain/InsufficientInputAmount.mdx | 2 +- docs/errors/chain/InsufficientLiquidity.mdx | 2 +- docs/errors/chain/InvalidDerivedAccountId.mdx | 2 +- docs/errors/chain/InvalidLiquidityValue.mdx | 2 +- docs/errors/chain/InvalidSignature.mdx | 2 +- docs/errors/chain/InvalidTickRange.mdx | 2 +- docs/errors/chain/LimitOrdersDisabled.mdx | 2 +- docs/errors/chain/MechanismDoesNotExist.mdx | 2 +- docs/errors/chain/NoPermission.mdx | 2 +- docs/errors/chain/NoSelfProxy.mdx | 2 +- docs/errors/chain/NotFound.mdx | 2 +- docs/errors/chain/NotProxy.mdx | 2 +- docs/errors/chain/OrderAlreadyProcessed.mdx | 2 +- docs/errors/chain/OrderCancelled.mdx | 2 +- docs/errors/chain/OrderExpired.mdx | 2 +- docs/errors/chain/OrderNetUidMismatch.mdx | 2 +- .../chain/PalletHotkeyNotRegistered.mdx | 2 +- docs/errors/chain/PartialFillsNotEnabled.mdx | 2 +- docs/errors/chain/PriceConditionNotMet.mdx | 2 +- docs/errors/chain/PriceLimitExceeded.mdx | 2 +- docs/errors/chain/RelayerMissMatch.mdx | 2 +- .../chain/RelayerRequiredForPartialFill.mdx | 2 +- docs/errors/chain/ReservesOutOfBalance.mdx | 2 +- docs/errors/chain/ReservesTooLow.mdx | 2 +- docs/errors/chain/RootNetUidNotAllowed.mdx | 2 +- docs/errors/chain/SubtokenDisabled.mdx | 2 +- docs/errors/chain/SwapInputTooLarge.mdx | 2 +- docs/errors/chain/SwapReturnedZero.mdx | 2 +- docs/errors/chain/TooMany.mdx | 2 +- docs/errors/chain/Unannounced.mdx | 2 +- docs/errors/chain/Unauthorized.mdx | 2 +- docs/errors/chain/Unproxyable.mdx | 2 +- docs/errors/chain/ZeroShareInBatch.mdx | 2 +- docs/query/alpha-prices.mdx | 2 +- docs/query/blocks-until-next-epoch.mdx | 2 +- docs/query/epoch-status.mdx | 2 +- docs/query/hotkey-conviction.mdx | 2 +- docs/query/most-convicted-hotkey.mdx | 2 +- docs/query/next-epoch-start-block.mdx | 2 +- docs/query/proxies.mdx | 2 +- docs/query/quote-stake.mdx | 2 +- docs/query/quote-unstake.mdx | 2 +- docs/query/root-basket-owed.mdx | 2 +- docs/query/root-basket-total-nav.mdx | 2 +- docs/query/subnet-registration-cost.mdx | 2 +- docs/query/subnet-start-schedule.mdx | 2 +- docs/query/validator-basket-nav.mdx | 2 +- docs/query/validator-root-weights.mdx | 2 +- docs/tx/add-proxy.mdx | 6 +- docs/tx/create-pure-proxy.mdx | 6 +- docs/tx/execute-proxy-announced.mdx | 14 +- docs/tx/kill-pure-proxy.mdx | 6 +- docs/tx/remove-proxies.mdx | 6 +- docs/tx/remove-proxy.mdx | 6 +- pallets/limit-orders/src/benchmarking.rs | 9 +- pallets/limit-orders/src/lib.rs | 4 +- .../limit-orders/src/tests/ledger_vector.rs | 10 +- pallets/limit-orders/src/tests/readable.rs | 182 ++++++++++-------- runtime/tests/limit_orders.rs | 8 +- .../test-ledger-raw-sign-vector.ts | 8 +- .../public/catalog/errors.json | 168 ++++++++-------- .../public/catalog/intents.json | 36 ++-- .../public/catalog/reads.json | 86 ++++----- 74 files changed, 342 insertions(+), 335 deletions(-) diff --git a/.github/docs-preview-vercel/package-lock.json b/.github/docs-preview-vercel/package-lock.json index a0a5a9a25c..9361fc37e7 100644 --- a/.github/docs-preview-vercel/package-lock.json +++ b/.github/docs-preview-vercel/package-lock.json @@ -2919,9 +2919,9 @@ } }, "node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "funding": [ { "type": "github", diff --git a/.github/docs-preview-vercel/package.json b/.github/docs-preview-vercel/package.json index bda15888ed..521cb4968c 100644 --- a/.github/docs-preview-vercel/package.json +++ b/.github/docs-preview-vercel/package.json @@ -22,7 +22,7 @@ }, "ajv": "8.18.0", "brace-expansion": "5.0.9", - "js-yaml": "4.3.0", + "js-yaml": "4.3.1", "minimatch": "10.2.5", "path-to-regexp": "8.4.2", "smol-toml": "1.7.0", diff --git a/docs/errors/chain/AnnouncementDepositInvariantViolated.mdx b/docs/errors/chain/AnnouncementDepositInvariantViolated.mdx index f1c2e16fef..da721e5e09 100644 --- a/docs/errors/chain/AnnouncementDepositInvariantViolated.mdx +++ b/docs/errors/chain/AnnouncementDepositInvariantViolated.mdx @@ -9,7 +9,7 @@ Internal invariant failure in `announce`: recomputing the announcement deposit r Declared by the `Proxy` pallet; it classifies to the semantic code [`internal`](/docs/errors/internal). -Declared at [`pallets/proxy/src/lib.rs#L809`](/code/pallets/proxy/src/lib.rs#L809). +Declared at [`pallets/proxy/src/lib.rs#L814`](/code/pallets/proxy/src/lib.rs#L814). ## Remediation diff --git a/docs/errors/chain/ArithmeticOverflow.mdx b/docs/errors/chain/ArithmeticOverflow.mdx index fa0e69d052..21654a0dba 100644 --- a/docs/errors/chain/ArithmeticOverflow.mdx +++ b/docs/errors/chain/ArithmeticOverflow.mdx @@ -9,7 +9,7 @@ Converting a TAO amount to alpha during batched order execution overflowed the f Declared by the `LimitOrders` pallet; it classifies to the semantic code [`internal`](/docs/errors/internal). -Declared at [`pallets/limit-orders/src/lib.rs#L352`](/code/pallets/limit-orders/src/lib.rs#L352). +Declared at [`pallets/limit-orders/src/lib.rs#L373`](/code/pallets/limit-orders/src/lib.rs#L373). ## Remediation diff --git a/docs/errors/chain/ChainIdMismatch.mdx b/docs/errors/chain/ChainIdMismatch.mdx index 1da0ae87be..b0725d4664 100644 --- a/docs/errors/chain/ChainIdMismatch.mdx +++ b/docs/errors/chain/ChainIdMismatch.mdx @@ -9,7 +9,7 @@ The order payload's `chain_id` field differs from this chain's configured EVM ch Declared by the `LimitOrders` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L346`](/code/pallets/limit-orders/src/lib.rs#L346). +Declared at [`pallets/limit-orders/src/lib.rs#L367`](/code/pallets/limit-orders/src/lib.rs#L367). ## Remediation diff --git a/docs/errors/chain/Deprecated.mdx b/docs/errors/chain/Deprecated.mdx index 270ee2ff4e..bb03a90f09 100644 --- a/docs/errors/chain/Deprecated.mdx +++ b/docs/errors/chain/Deprecated.mdx @@ -9,7 +9,7 @@ The extrinsic has been removed and always fails, e.g. `schedule_swap_coldkey`, t Declared by the `SubtensorModule`, `AdminUtils`, `Swap` pallets; it classifies to the semantic code [`disabled`](/docs/errors/disabled). -Declared at [`pallets/subtensor/src/macros/errors.rs#L284`](/code/pallets/subtensor/src/macros/errors.rs#L284), [`pallets/admin-utils/src/lib.rs#L176`](/code/pallets/admin-utils/src/lib.rs#L176), [`pallets/swap/src/pallet/mod.rs#L181`](/code/pallets/swap/src/pallet/mod.rs#L181). +Declared at [`pallets/subtensor/src/macros/errors.rs#L284`](/code/pallets/subtensor/src/macros/errors.rs#L284), [`pallets/admin-utils/src/lib.rs#L176`](/code/pallets/admin-utils/src/lib.rs#L176), [`pallets/swap/src/pallet/mod.rs#L182`](/code/pallets/swap/src/pallet/mod.rs#L182). ## Remediation diff --git a/docs/errors/chain/Duplicate.mdx b/docs/errors/chain/Duplicate.mdx index 60c1159ac7..7ef5717637 100644 --- a/docs/errors/chain/Duplicate.mdx +++ b/docs/errors/chain/Duplicate.mdx @@ -9,7 +9,7 @@ This delegate is already registered as a proxy for the delegator with the same p Declared by the `Proxy` pallet; it classifies to the semantic code [`already_exists`](/docs/errors/already-exists). -Declared at [`pallets/proxy/src/lib.rs#L801`](/code/pallets/proxy/src/lib.rs#L801). +Declared at [`pallets/proxy/src/lib.rs#L806`](/code/pallets/proxy/src/lib.rs#L806). ## Remediation diff --git a/docs/errors/chain/DuplicateOrderInBatch.mdx b/docs/errors/chain/DuplicateOrderInBatch.mdx index 7e223d9adf..504e5c3e0b 100644 --- a/docs/errors/chain/DuplicateOrderInBatch.mdx +++ b/docs/errors/chain/DuplicateOrderInBatch.mdx @@ -9,7 +9,7 @@ Two entries in one `execute_batched_orders` call hash to the same order id, mean Declared by the `LimitOrders` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L354`](/code/pallets/limit-orders/src/lib.rs#L354). +Declared at [`pallets/limit-orders/src/lib.rs#L375`](/code/pallets/limit-orders/src/lib.rs#L375). ## Remediation diff --git a/docs/errors/chain/FeeRateTooHigh.mdx b/docs/errors/chain/FeeRateTooHigh.mdx index 2171309620..160b2ace05 100644 --- a/docs/errors/chain/FeeRateTooHigh.mdx +++ b/docs/errors/chain/FeeRateTooHigh.mdx @@ -9,7 +9,7 @@ description: "Check the argument values against the operation schema" Declared by the `Swap` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/swap/src/pallet/mod.rs#L145`](/code/pallets/swap/src/pallet/mod.rs#L145). +Declared at [`pallets/swap/src/pallet/mod.rs#L146`](/code/pallets/swap/src/pallet/mod.rs#L146). ## Remediation diff --git a/docs/errors/chain/IncorrectPartialFillAmount.mdx b/docs/errors/chain/IncorrectPartialFillAmount.mdx index 386970e23e..c485a03ee3 100644 --- a/docs/errors/chain/IncorrectPartialFillAmount.mdx +++ b/docs/errors/chain/IncorrectPartialFillAmount.mdx @@ -9,7 +9,7 @@ The `partial_fill` amount is zero or exceeds the order's remaining unfilled amou Declared by the `LimitOrders` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L342`](/code/pallets/limit-orders/src/lib.rs#L342). +Declared at [`pallets/limit-orders/src/lib.rs#L363`](/code/pallets/limit-orders/src/lib.rs#L363). ## Remediation diff --git a/docs/errors/chain/InsufficientBalance.mdx b/docs/errors/chain/InsufficientBalance.mdx index da25e42e8d..e0c43787a5 100644 --- a/docs/errors/chain/InsufficientBalance.mdx +++ b/docs/errors/chain/InsufficientBalance.mdx @@ -9,7 +9,7 @@ The caller's spendable balance is below what the operation needs, whether a plai Declared by the `Balances`, `Crowdloan`, `Swap` pallets; it classifies to the semantic code [`insufficient_balance`](/docs/errors/insufficient-balance). -Declared at [`pallets/crowdloan/src/lib.rs#L253`](/code/pallets/crowdloan/src/lib.rs#L253), [`pallets/swap/src/pallet/mod.rs#L157`](/code/pallets/swap/src/pallet/mod.rs#L157). +Declared at [`pallets/crowdloan/src/lib.rs#L253`](/code/pallets/crowdloan/src/lib.rs#L253), [`pallets/swap/src/pallet/mod.rs#L158`](/code/pallets/swap/src/pallet/mod.rs#L158). ## Remediation diff --git a/docs/errors/chain/InsufficientInputAmount.mdx b/docs/errors/chain/InsufficientInputAmount.mdx index ab355918aa..4902a63054 100644 --- a/docs/errors/chain/InsufficientInputAmount.mdx +++ b/docs/errors/chain/InsufficientInputAmount.mdx @@ -9,7 +9,7 @@ Declared for swap inputs too small to execute, but no current code path raises i Declared by the `Swap` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/swap/src/pallet/mod.rs#L148`](/code/pallets/swap/src/pallet/mod.rs#L148). +Declared at [`pallets/swap/src/pallet/mod.rs#L149`](/code/pallets/swap/src/pallet/mod.rs#L149). ## Remediation diff --git a/docs/errors/chain/InsufficientLiquidity.mdx b/docs/errors/chain/InsufficientLiquidity.mdx index 3f4a891a88..2f399866b8 100644 --- a/docs/errors/chain/InsufficientLiquidity.mdx +++ b/docs/errors/chain/InsufficientLiquidity.mdx @@ -9,7 +9,7 @@ The pool cannot absorb the operation: the swap simulation failed, reserves are s Declared by the `SubtensorModule`, `Swap` pallets; it classifies to the semantic code [`insufficient_liquidity`](/docs/errors/insufficient-liquidity). -Declared at [`pallets/subtensor/src/macros/errors.rs#L191`](/code/pallets/subtensor/src/macros/errors.rs#L191), [`pallets/swap/src/pallet/mod.rs#L151`](/code/pallets/swap/src/pallet/mod.rs#L151). +Declared at [`pallets/subtensor/src/macros/errors.rs#L191`](/code/pallets/subtensor/src/macros/errors.rs#L191), [`pallets/swap/src/pallet/mod.rs#L152`](/code/pallets/swap/src/pallet/mod.rs#L152). ## Remediation diff --git a/docs/errors/chain/InvalidDerivedAccountId.mdx b/docs/errors/chain/InvalidDerivedAccountId.mdx index 252eb41644..37867345e7 100644 --- a/docs/errors/chain/InvalidDerivedAccountId.mdx +++ b/docs/errors/chain/InvalidDerivedAccountId.mdx @@ -9,7 +9,7 @@ Deriving the pure proxy account id from the provided entropy failed to decode in Declared by the `Proxy` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/proxy/src/lib.rs#L811`](/code/pallets/proxy/src/lib.rs#L811). +Declared at [`pallets/proxy/src/lib.rs#L816`](/code/pallets/proxy/src/lib.rs#L816). ## Remediation diff --git a/docs/errors/chain/InvalidLiquidityValue.mdx b/docs/errors/chain/InvalidLiquidityValue.mdx index 1db976967b..ba1e9e71c7 100644 --- a/docs/errors/chain/InvalidLiquidityValue.mdx +++ b/docs/errors/chain/InvalidLiquidityValue.mdx @@ -9,7 +9,7 @@ Legacy error from the removed V3 user-liquidity code, raised when an added or re Declared by the `Swap` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/swap/src/pallet/mod.rs#L163`](/code/pallets/swap/src/pallet/mod.rs#L163). +Declared at [`pallets/swap/src/pallet/mod.rs#L164`](/code/pallets/swap/src/pallet/mod.rs#L164). ## Remediation diff --git a/docs/errors/chain/InvalidSignature.mdx b/docs/errors/chain/InvalidSignature.mdx index 3260b0a704..3026243bba 100644 --- a/docs/errors/chain/InvalidSignature.mdx +++ b/docs/errors/chain/InvalidSignature.mdx @@ -9,7 +9,7 @@ Signature verification failed: the sender of an Ethereum or EVM transaction coul Declared by the `Ethereum`, `EVM`, `LimitOrders` pallets; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L318`](/code/pallets/limit-orders/src/lib.rs#L318). +Declared at [`pallets/limit-orders/src/lib.rs#L339`](/code/pallets/limit-orders/src/lib.rs#L339). ## Remediation diff --git a/docs/errors/chain/InvalidTickRange.mdx b/docs/errors/chain/InvalidTickRange.mdx index a705019a3c..b9b554deae 100644 --- a/docs/errors/chain/InvalidTickRange.mdx +++ b/docs/errors/chain/InvalidTickRange.mdx @@ -9,7 +9,7 @@ Legacy error from the removed V3 user-liquidity code, raised when `tick_low` was Declared by the `Swap` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/swap/src/pallet/mod.rs#L160`](/code/pallets/swap/src/pallet/mod.rs#L160). +Declared at [`pallets/swap/src/pallet/mod.rs#L161`](/code/pallets/swap/src/pallet/mod.rs#L161). ## Remediation diff --git a/docs/errors/chain/LimitOrdersDisabled.mdx b/docs/errors/chain/LimitOrdersDisabled.mdx index 52cea88067..f5d6f4d52f 100644 --- a/docs/errors/chain/LimitOrdersDisabled.mdx +++ b/docs/errors/chain/LimitOrdersDisabled.mdx @@ -9,7 +9,7 @@ Order execution was attempted while the pallet's global switch is off. Check the Declared by the `LimitOrders` pallet; it classifies to the semantic code [`disabled`](/docs/errors/disabled). -Declared at [`pallets/limit-orders/src/lib.rs#L336`](/code/pallets/limit-orders/src/lib.rs#L336). +Declared at [`pallets/limit-orders/src/lib.rs#L357`](/code/pallets/limit-orders/src/lib.rs#L357). ## Remediation diff --git a/docs/errors/chain/MechanismDoesNotExist.mdx b/docs/errors/chain/MechanismDoesNotExist.mdx index ebc1defbb2..40e0a87e8a 100644 --- a/docs/errors/chain/MechanismDoesNotExist.mdx +++ b/docs/errors/chain/MechanismDoesNotExist.mdx @@ -9,7 +9,7 @@ The target subnet or its sub-mechanism does not exist: the netuid is unknown, th Declared by the `SubtensorModule`, `Swap` pallets; it classifies to the semantic code [`subnet_not_exists`](/docs/errors/subnet-not-exists). -Declared at [`pallets/subtensor/src/macros/errors.rs#L173`](/code/pallets/subtensor/src/macros/errors.rs#L173), [`pallets/swap/src/pallet/mod.rs#L169`](/code/pallets/swap/src/pallet/mod.rs#L169). +Declared at [`pallets/subtensor/src/macros/errors.rs#L173`](/code/pallets/subtensor/src/macros/errors.rs#L173), [`pallets/swap/src/pallet/mod.rs#L170`](/code/pallets/swap/src/pallet/mod.rs#L170). ## Remediation diff --git a/docs/errors/chain/NoPermission.mdx b/docs/errors/chain/NoPermission.mdx index 2795c82ba1..3bedba35da 100644 --- a/docs/errors/chain/NoPermission.mdx +++ b/docs/errors/chain/NoPermission.mdx @@ -9,7 +9,7 @@ The proxy pallet refused the action: the proxied call could escalate privileges, Declared by the `Proxy` pallet; it classifies to the semantic code [`not_authorized`](/docs/errors/not-authorized). -Declared at [`pallets/proxy/src/lib.rs#L803`](/code/pallets/proxy/src/lib.rs#L803). +Declared at [`pallets/proxy/src/lib.rs#L808`](/code/pallets/proxy/src/lib.rs#L808). ## Remediation diff --git a/docs/errors/chain/NoSelfProxy.mdx b/docs/errors/chain/NoSelfProxy.mdx index ab9af577d5..c4d9f543b5 100644 --- a/docs/errors/chain/NoSelfProxy.mdx +++ b/docs/errors/chain/NoSelfProxy.mdx @@ -9,7 +9,7 @@ An account attempted to register itself as its own proxy, which is not allowed. Declared by the `Proxy` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/proxy/src/lib.rs#L807`](/code/pallets/proxy/src/lib.rs#L807). +Declared at [`pallets/proxy/src/lib.rs#L812`](/code/pallets/proxy/src/lib.rs#L812). ## Remediation diff --git a/docs/errors/chain/NotFound.mdx b/docs/errors/chain/NotFound.mdx index acda02ac76..be68f30df6 100644 --- a/docs/errors/chain/NotFound.mdx +++ b/docs/errors/chain/NotFound.mdx @@ -9,7 +9,7 @@ The referenced item does not exist in storage: no multisig operation for that ca Declared by the `Multisig`, `Scheduler`, `Proxy` pallets; it classifies to the semantic code [`not_found`](/docs/errors/not-found). -Declared at [`pallets/proxy/src/lib.rs#L795`](/code/pallets/proxy/src/lib.rs#L795). +Declared at [`pallets/proxy/src/lib.rs#L800`](/code/pallets/proxy/src/lib.rs#L800). ## Remediation diff --git a/docs/errors/chain/NotProxy.mdx b/docs/errors/chain/NotProxy.mdx index d59d0b988a..8d7bbeb706 100644 --- a/docs/errors/chain/NotProxy.mdx +++ b/docs/errors/chain/NotProxy.mdx @@ -9,7 +9,7 @@ The sender is not registered as a proxy for the account it tried to act for. Che Declared by the `Proxy` pallet; it classifies to the semantic code [`not_authorized`](/docs/errors/not-authorized). -Declared at [`pallets/proxy/src/lib.rs#L797`](/code/pallets/proxy/src/lib.rs#L797). +Declared at [`pallets/proxy/src/lib.rs#L802`](/code/pallets/proxy/src/lib.rs#L802). ## Remediation diff --git a/docs/errors/chain/OrderAlreadyProcessed.mdx b/docs/errors/chain/OrderAlreadyProcessed.mdx index 08074d06f0..ba5faf2608 100644 --- a/docs/errors/chain/OrderAlreadyProcessed.mdx +++ b/docs/errors/chain/OrderAlreadyProcessed.mdx @@ -9,7 +9,7 @@ The order id already has a terminal status: execution found it fulfilled, or `ca Declared by the `LimitOrders` pallet; it classifies to the semantic code [`already_exists`](/docs/errors/already-exists). -Declared at [`pallets/limit-orders/src/lib.rs#L320`](/code/pallets/limit-orders/src/lib.rs#L320). +Declared at [`pallets/limit-orders/src/lib.rs#L341`](/code/pallets/limit-orders/src/lib.rs#L341). ## Remediation diff --git a/docs/errors/chain/OrderCancelled.mdx b/docs/errors/chain/OrderCancelled.mdx index 038fe0ea2f..f87caab46c 100644 --- a/docs/errors/chain/OrderCancelled.mdx +++ b/docs/errors/chain/OrderCancelled.mdx @@ -9,7 +9,7 @@ The order was previously cancelled via `cancel_order` and can never be executed. Declared by the `LimitOrders` pallet; it classifies to the semantic code [`expired`](/docs/errors/expired). -Declared at [`pallets/limit-orders/src/lib.rs#L322`](/code/pallets/limit-orders/src/lib.rs#L322). +Declared at [`pallets/limit-orders/src/lib.rs#L343`](/code/pallets/limit-orders/src/lib.rs#L343). ## Remediation diff --git a/docs/errors/chain/OrderExpired.mdx b/docs/errors/chain/OrderExpired.mdx index 1069ff6611..84d4247911 100644 --- a/docs/errors/chain/OrderExpired.mdx +++ b/docs/errors/chain/OrderExpired.mdx @@ -9,7 +9,7 @@ The current chain time is past the order's `expiry` field, which is a unix times Declared by the `LimitOrders` pallet; it classifies to the semantic code [`expired`](/docs/errors/expired). -Declared at [`pallets/limit-orders/src/lib.rs#L324`](/code/pallets/limit-orders/src/lib.rs#L324). +Declared at [`pallets/limit-orders/src/lib.rs#L345`](/code/pallets/limit-orders/src/lib.rs#L345). ## Remediation diff --git a/docs/errors/chain/OrderNetUidMismatch.mdx b/docs/errors/chain/OrderNetUidMismatch.mdx index d7231b72da..c7d4a9084c 100644 --- a/docs/errors/chain/OrderNetUidMismatch.mdx +++ b/docs/errors/chain/OrderNetUidMismatch.mdx @@ -9,7 +9,7 @@ An order inside an `execute_batched_orders` call has a `netuid` field different Declared by the `LimitOrders` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L334`](/code/pallets/limit-orders/src/lib.rs#L334). +Declared at [`pallets/limit-orders/src/lib.rs#L355`](/code/pallets/limit-orders/src/lib.rs#L355). ## Remediation diff --git a/docs/errors/chain/PalletHotkeyNotRegistered.mdx b/docs/errors/chain/PalletHotkeyNotRegistered.mdx index eae4f55fda..23573ec535 100644 --- a/docs/errors/chain/PalletHotkeyNotRegistered.mdx +++ b/docs/errors/chain/PalletHotkeyNotRegistered.mdx @@ -9,7 +9,7 @@ Root tried to enable the pallet via `set_pallet_status` before its hotkey was re Declared by the `LimitOrders` pallet; it classifies to the semantic code [`not_registered`](/docs/errors/not-registered). -Declared at [`pallets/limit-orders/src/lib.rs#L350`](/code/pallets/limit-orders/src/lib.rs#L350). +Declared at [`pallets/limit-orders/src/lib.rs#L371`](/code/pallets/limit-orders/src/lib.rs#L371). ## Remediation diff --git a/docs/errors/chain/PartialFillsNotEnabled.mdx b/docs/errors/chain/PartialFillsNotEnabled.mdx index 8745c2f5a2..ee34e91faf 100644 --- a/docs/errors/chain/PartialFillsNotEnabled.mdx +++ b/docs/errors/chain/PartialFillsNotEnabled.mdx @@ -9,7 +9,7 @@ A `partial_fill` amount was supplied for an order whose signed payload has `part Declared by the `LimitOrders` pallet; it classifies to the semantic code [`disabled`](/docs/errors/disabled). -Declared at [`pallets/limit-orders/src/lib.rs#L340`](/code/pallets/limit-orders/src/lib.rs#L340). +Declared at [`pallets/limit-orders/src/lib.rs#L361`](/code/pallets/limit-orders/src/lib.rs#L361). ## Remediation diff --git a/docs/errors/chain/PriceConditionNotMet.mdx b/docs/errors/chain/PriceConditionNotMet.mdx index 10ba7d4daa..63dcb9b954 100644 --- a/docs/errors/chain/PriceConditionNotMet.mdx +++ b/docs/errors/chain/PriceConditionNotMet.mdx @@ -9,7 +9,7 @@ The subnet's current alpha price does not satisfy the order's trigger: buys and Declared by the `LimitOrders` pallet; it classifies to the semantic code [`too_early`](/docs/errors/too-early). -Declared at [`pallets/limit-orders/src/lib.rs#L326`](/code/pallets/limit-orders/src/lib.rs#L326). +Declared at [`pallets/limit-orders/src/lib.rs#L347`](/code/pallets/limit-orders/src/lib.rs#L347). ## Remediation diff --git a/docs/errors/chain/PriceLimitExceeded.mdx b/docs/errors/chain/PriceLimitExceeded.mdx index 5f4ae893ef..cc15016f7c 100644 --- a/docs/errors/chain/PriceLimitExceeded.mdx +++ b/docs/errors/chain/PriceLimitExceeded.mdx @@ -9,7 +9,7 @@ The `limit_price` given to a swap is not beyond the current pool price in the tr Declared by the `Swap` pallet; it classifies to the semantic code [`insufficient_liquidity`](/docs/errors/insufficient-liquidity). -Declared at [`pallets/swap/src/pallet/mod.rs#L154`](/code/pallets/swap/src/pallet/mod.rs#L154). +Declared at [`pallets/swap/src/pallet/mod.rs#L155`](/code/pallets/swap/src/pallet/mod.rs#L155). ## Remediation diff --git a/docs/errors/chain/RelayerMissMatch.mdx b/docs/errors/chain/RelayerMissMatch.mdx index d05224dcf4..b6f8be87c0 100644 --- a/docs/errors/chain/RelayerMissMatch.mdx +++ b/docs/errors/chain/RelayerMissMatch.mdx @@ -9,7 +9,7 @@ The order's `relayer` allowlist is set but the account that submitted the execut Declared by the `LimitOrders` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L338`](/code/pallets/limit-orders/src/lib.rs#L338). +Declared at [`pallets/limit-orders/src/lib.rs#L359`](/code/pallets/limit-orders/src/lib.rs#L359). ## Remediation diff --git a/docs/errors/chain/RelayerRequiredForPartialFill.mdx b/docs/errors/chain/RelayerRequiredForPartialFill.mdx index 0d099c6866..ef6c488739 100644 --- a/docs/errors/chain/RelayerRequiredForPartialFill.mdx +++ b/docs/errors/chain/RelayerRequiredForPartialFill.mdx @@ -9,7 +9,7 @@ A `partial_fill` was requested for an order whose `relayer` field is empty; part Declared by the `LimitOrders` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L344`](/code/pallets/limit-orders/src/lib.rs#L344). +Declared at [`pallets/limit-orders/src/lib.rs#L365`](/code/pallets/limit-orders/src/lib.rs#L365). ## Remediation diff --git a/docs/errors/chain/ReservesOutOfBalance.mdx b/docs/errors/chain/ReservesOutOfBalance.mdx index c2fbd9c320..2eee6ee9fc 100644 --- a/docs/errors/chain/ReservesOutOfBalance.mdx +++ b/docs/errors/chain/ReservesOutOfBalance.mdx @@ -9,7 +9,7 @@ Swap balancer initialization failed because the subnet's TAO and alpha reserves Declared by the `Swap` pallet; it classifies to the semantic code [`insufficient_liquidity`](/docs/errors/insufficient-liquidity). -Declared at [`pallets/swap/src/pallet/mod.rs#L175`](/code/pallets/swap/src/pallet/mod.rs#L175). +Declared at [`pallets/swap/src/pallet/mod.rs#L176`](/code/pallets/swap/src/pallet/mod.rs#L176). ## Remediation diff --git a/docs/errors/chain/ReservesTooLow.mdx b/docs/errors/chain/ReservesTooLow.mdx index c95033fb3c..47e2a7f2a5 100644 --- a/docs/errors/chain/ReservesTooLow.mdx +++ b/docs/errors/chain/ReservesTooLow.mdx @@ -9,7 +9,7 @@ The output-side reserve is below the swap pallet's `MinimumReserve`, or a swap s Declared by the `Swap` pallet; it classifies to the semantic code [`insufficient_liquidity`](/docs/errors/insufficient-liquidity). -Declared at [`pallets/swap/src/pallet/mod.rs#L166`](/code/pallets/swap/src/pallet/mod.rs#L166). +Declared at [`pallets/swap/src/pallet/mod.rs#L167`](/code/pallets/swap/src/pallet/mod.rs#L167). ## Remediation diff --git a/docs/errors/chain/RootNetUidNotAllowed.mdx b/docs/errors/chain/RootNetUidNotAllowed.mdx index 136d017011..e25e869ec6 100644 --- a/docs/errors/chain/RootNetUidNotAllowed.mdx +++ b/docs/errors/chain/RootNetUidNotAllowed.mdx @@ -9,7 +9,7 @@ The order or batch targets the root subnet, netuid 0, which the limit orders pal Declared by the `LimitOrders` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L332`](/code/pallets/limit-orders/src/lib.rs#L332). +Declared at [`pallets/limit-orders/src/lib.rs#L353`](/code/pallets/limit-orders/src/lib.rs#L353). ## Remediation diff --git a/docs/errors/chain/SubtokenDisabled.mdx b/docs/errors/chain/SubtokenDisabled.mdx index 551ed351a8..e4791978b7 100644 --- a/docs/errors/chain/SubtokenDisabled.mdx +++ b/docs/errors/chain/SubtokenDisabled.mdx @@ -9,7 +9,7 @@ The subnet's alpha token is not yet enabled, so staking, swapping, and trading o Declared by the `SubtensorModule`, `Swap` pallets; it classifies to the semantic code [`subtoken_disabled`](/docs/errors/subtoken-disabled). -Declared at [`pallets/subtensor/src/macros/errors.rs#L213`](/code/pallets/subtensor/src/macros/errors.rs#L213), [`pallets/swap/src/pallet/mod.rs#L172`](/code/pallets/swap/src/pallet/mod.rs#L172). +Declared at [`pallets/subtensor/src/macros/errors.rs#L213`](/code/pallets/subtensor/src/macros/errors.rs#L213), [`pallets/swap/src/pallet/mod.rs#L173`](/code/pallets/swap/src/pallet/mod.rs#L173). ## Remediation diff --git a/docs/errors/chain/SwapInputTooLarge.mdx b/docs/errors/chain/SwapInputTooLarge.mdx index 95f4874988..345d4712f4 100644 --- a/docs/errors/chain/SwapInputTooLarge.mdx +++ b/docs/errors/chain/SwapInputTooLarge.mdx @@ -9,7 +9,7 @@ The swap's net input after fees exceeds 1000 times the input-side reserve, the p Declared by the `Swap` pallet; it classifies to the semantic code [`insufficient_liquidity`](/docs/errors/insufficient-liquidity). -Declared at [`pallets/swap/src/pallet/mod.rs#L178`](/code/pallets/swap/src/pallet/mod.rs#L178). +Declared at [`pallets/swap/src/pallet/mod.rs#L179`](/code/pallets/swap/src/pallet/mod.rs#L179). ## Remediation diff --git a/docs/errors/chain/SwapReturnedZero.mdx b/docs/errors/chain/SwapReturnedZero.mdx index 13ef5d7db1..2ce02f95c5 100644 --- a/docs/errors/chain/SwapReturnedZero.mdx +++ b/docs/errors/chain/SwapReturnedZero.mdx @@ -9,7 +9,7 @@ The netted pool swap in `execute_batched_orders` produced zero output for a non- Declared by the `LimitOrders` pallet; it classifies to the semantic code [`insufficient_liquidity`](/docs/errors/insufficient-liquidity). -Declared at [`pallets/limit-orders/src/lib.rs#L330`](/code/pallets/limit-orders/src/lib.rs#L330). +Declared at [`pallets/limit-orders/src/lib.rs#L351`](/code/pallets/limit-orders/src/lib.rs#L351). ## Remediation diff --git a/docs/errors/chain/TooMany.mdx b/docs/errors/chain/TooMany.mdx index f7d51e6e47..90b6bd9985 100644 --- a/docs/errors/chain/TooMany.mdx +++ b/docs/errors/chain/TooMany.mdx @@ -9,7 +9,7 @@ A limit was exceeded: more preimage hashes than `MAX_HASH_UPGRADE_BULK_COUNT` we Declared by the `Preimage`, `Proxy` pallets; it classifies to the semantic code [`limit_exceeded`](/docs/errors/limit-exceeded). -Declared at [`pallets/proxy/src/lib.rs#L793`](/code/pallets/proxy/src/lib.rs#L793). +Declared at [`pallets/proxy/src/lib.rs#L798`](/code/pallets/proxy/src/lib.rs#L798). ## Remediation diff --git a/docs/errors/chain/Unannounced.mdx b/docs/errors/chain/Unannounced.mdx index 24fb61e38b..420ac60007 100644 --- a/docs/errors/chain/Unannounced.mdx +++ b/docs/errors/chain/Unannounced.mdx @@ -9,7 +9,7 @@ The proxied call was executed before its announcement matured, or no matching an Declared by the `Proxy` pallet; it classifies to the semantic code [`too_early`](/docs/errors/too-early). -Declared at [`pallets/proxy/src/lib.rs#L805`](/code/pallets/proxy/src/lib.rs#L805). +Declared at [`pallets/proxy/src/lib.rs#L810`](/code/pallets/proxy/src/lib.rs#L810). ## Remediation diff --git a/docs/errors/chain/Unauthorized.mdx b/docs/errors/chain/Unauthorized.mdx index 6042c9dd0d..7e7e8d6dcc 100644 --- a/docs/errors/chain/Unauthorized.mdx +++ b/docs/errors/chain/Unauthorized.mdx @@ -9,7 +9,7 @@ In System, the code passed to `apply_authorized_upgrade` does not hash to the va Declared by the `System`, `LimitOrders` pallets; it classifies to the semantic code [`not_authorized`](/docs/errors/not-authorized). -Declared at [`pallets/limit-orders/src/lib.rs#L328`](/code/pallets/limit-orders/src/lib.rs#L328). +Declared at [`pallets/limit-orders/src/lib.rs#L349`](/code/pallets/limit-orders/src/lib.rs#L349). ## Remediation diff --git a/docs/errors/chain/Unproxyable.mdx b/docs/errors/chain/Unproxyable.mdx index b0de284617..0bb48d217c 100644 --- a/docs/errors/chain/Unproxyable.mdx +++ b/docs/errors/chain/Unproxyable.mdx @@ -9,7 +9,7 @@ The attempted call is not permitted by the registered proxy type's call filter. Declared by the `Proxy` pallet; it classifies to the semantic code [`not_authorized`](/docs/errors/not-authorized). -Declared at [`pallets/proxy/src/lib.rs#L799`](/code/pallets/proxy/src/lib.rs#L799). +Declared at [`pallets/proxy/src/lib.rs#L804`](/code/pallets/proxy/src/lib.rs#L804). ## Remediation diff --git a/docs/errors/chain/ZeroShareInBatch.mdx b/docs/errors/chain/ZeroShareInBatch.mdx index 482b245a61..49e1567ace 100644 --- a/docs/errors/chain/ZeroShareInBatch.mdx +++ b/docs/errors/chain/ZeroShareInBatch.mdx @@ -9,7 +9,7 @@ An order's pro-rata share of the batch output floored to zero, so the whole batc Declared by the `LimitOrders` pallet; it classifies to the semantic code [`invalid_argument`](/docs/errors/invalid-argument). -Declared at [`pallets/limit-orders/src/lib.rs#L359`](/code/pallets/limit-orders/src/lib.rs#L359). +Declared at [`pallets/limit-orders/src/lib.rs#L380`](/code/pallets/limit-orders/src/lib.rs#L380). ## Remediation diff --git a/docs/query/alpha-prices.mdx b/docs/query/alpha-prices.mdx index 3b44cb5085..af313d5732 100644 --- a/docs/query/alpha-prices.mdx +++ b/docs/query/alpha-prices.mdx @@ -40,6 +40,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`SwapRuntimeApi.current_alpha_price_all`](/code/runtime/src/lib.rs#L2455-L2465) +- Runtime API [`SwapRuntimeApi.current_alpha_price_all`](/code/runtime/src/lib.rs#L2478-L2488) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/blocks-until-next-epoch.mdx b/docs/query/blocks-until-next-epoch.mdx index 32a5fdcb53..54a46e4772 100644 --- a/docs/query/blocks-until-next-epoch.mdx +++ b/docs/query/blocks-until-next-epoch.mdx @@ -45,6 +45,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272) +- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1262-L1276) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/epoch-status.mdx b/docs/query/epoch-status.mdx index cdd6c9c5bf..7ae9a42c8d 100644 --- a/docs/query/epoch-status.mdx +++ b/docs/query/epoch-status.mdx @@ -50,6 +50,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. - Storage [`SubtensorModule.BlocksSinceLastStep`](/code/pallets/subtensor/src/lib.rs#L2164) - Storage [`SubtensorModule.PendingEpochAt`](/code/pallets/subtensor/src/lib.rs#L2053) - Storage [`SubtensorModule.SubnetEpochIndex`](/code/pallets/subtensor/src/lib.rs#L2059) -- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272) +- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1262-L1276) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/hotkey-conviction.mdx b/docs/query/hotkey-conviction.mdx index 320082eee5..4bcea21e61 100644 --- a/docs/query/hotkey-conviction.mdx +++ b/docs/query/hotkey-conviction.mdx @@ -44,6 +44,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`StakeInfoRuntimeApi.get_hotkey_conviction`](/code/runtime/src/lib.rs#L2338-L2340) +- Runtime API [`StakeInfoRuntimeApi.get_hotkey_conviction`](/code/runtime/src/lib.rs#L2361-L2363) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/most-convicted-hotkey.mdx b/docs/query/most-convicted-hotkey.mdx index 8674684e65..2c24025c84 100644 --- a/docs/query/most-convicted-hotkey.mdx +++ b/docs/query/most-convicted-hotkey.mdx @@ -42,6 +42,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`StakeInfoRuntimeApi.get_most_convicted_hotkey_on_subnet`](/code/runtime/src/lib.rs#L2342-L2344) +- Runtime API [`StakeInfoRuntimeApi.get_most_convicted_hotkey_on_subnet`](/code/runtime/src/lib.rs#L2365-L2367) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/next-epoch-start-block.mdx b/docs/query/next-epoch-start-block.mdx index d5b6ab7b6d..01055cacf2 100644 --- a/docs/query/next-epoch-start-block.mdx +++ b/docs/query/next-epoch-start-block.mdx @@ -45,6 +45,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272) +- Runtime API [`SubnetInfoRuntimeApi.get_next_epoch_start_block`](/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1262-L1276) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/proxies.mdx b/docs/query/proxies.mdx index a1def3f998..6106113f62 100644 --- a/docs/query/proxies.mdx +++ b/docs/query/proxies.mdx @@ -42,6 +42,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Storage [`Proxy.Proxies`](/code/pallets/proxy/src/lib.rs#L825) +- Storage [`Proxy.Proxies`](/code/pallets/proxy/src/lib.rs#L830) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/quote-stake.mdx b/docs/query/quote-stake.mdx index 05b0eb394f..6891dc7441 100644 --- a/docs/query/quote-stake.mdx +++ b/docs/query/quote-stake.mdx @@ -43,6 +43,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`SwapRuntimeApi.sim_swap_tao_for_alpha`](/code/runtime/src/lib.rs#L2467-L2495) +- Runtime API [`SwapRuntimeApi.sim_swap_tao_for_alpha`](/code/runtime/src/lib.rs#L2490-L2518) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/quote-unstake.mdx b/docs/query/quote-unstake.mdx index 3a21838838..183686ba8d 100644 --- a/docs/query/quote-unstake.mdx +++ b/docs/query/quote-unstake.mdx @@ -43,6 +43,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`SwapRuntimeApi.sim_swap_alpha_for_tao`](/code/runtime/src/lib.rs#L2497-L2525) +- Runtime API [`SwapRuntimeApi.sim_swap_alpha_for_tao`](/code/runtime/src/lib.rs#L2520-L2548) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/root-basket-owed.mdx b/docs/query/root-basket-owed.mdx index 1a634718d6..28157f55fc 100644 --- a/docs/query/root-basket-owed.mdx +++ b/docs/query/root-basket-owed.mdx @@ -48,6 +48,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`BetaBasketRuntimeApi.get_root_basket_owed`](/code/runtime/src/lib.rs#L2354-L2356) +- Runtime API [`BetaBasketRuntimeApi.get_root_basket_owed`](/code/runtime/src/lib.rs#L2377-L2379) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/root-basket-total-nav.mdx b/docs/query/root-basket-total-nav.mdx index 893c4ecc89..fb160ab084 100644 --- a/docs/query/root-basket-total-nav.mdx +++ b/docs/query/root-basket-total-nav.mdx @@ -40,6 +40,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`BetaBasketRuntimeApi.get_root_basket_total_nav`](/code/runtime/src/lib.rs#L2366-L2368) +- Runtime API [`BetaBasketRuntimeApi.get_root_basket_total_nav`](/code/runtime/src/lib.rs#L2389-L2391) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/subnet-registration-cost.mdx b/docs/query/subnet-registration-cost.mdx index 08d6bf4c75..a9b96219ec 100644 --- a/docs/query/subnet-registration-cost.mdx +++ b/docs/query/subnet-registration-cost.mdx @@ -41,6 +41,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`SubnetRegistrationRuntimeApi.get_network_registration_cost`](/code/runtime/src/lib.rs#L2348-L2350) +- Runtime API [`SubnetRegistrationRuntimeApi.get_network_registration_cost`](/code/runtime/src/lib.rs#L2371-L2373) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/subnet-start-schedule.mdx b/docs/query/subnet-start-schedule.mdx index 303b91ef29..44b2c8e348 100644 --- a/docs/query/subnet-start-schedule.mdx +++ b/docs/query/subnet-start-schedule.mdx @@ -44,6 +44,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation - Storage [`SubtensorModule.NetworkRegisteredAt`](/code/pallets/subtensor/src/lib.rs#L2113) -- Constant [`SubtensorModule.InitialStartCallDelay`](/code/runtime/src/lib.rs#L851) +- Constant [`SubtensorModule.InitialStartCallDelay`](/code/runtime/src/lib.rs#L874) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/validator-basket-nav.mdx b/docs/query/validator-basket-nav.mdx index ec57bedffd..32859bec7a 100644 --- a/docs/query/validator-basket-nav.mdx +++ b/docs/query/validator-basket-nav.mdx @@ -42,6 +42,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`BetaBasketRuntimeApi.get_validator_basket_nav`](/code/runtime/src/lib.rs#L2360-L2362) +- Runtime API [`BetaBasketRuntimeApi.get_validator_basket_nav`](/code/runtime/src/lib.rs#L2383-L2385) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/query/validator-root-weights.mdx b/docs/query/validator-root-weights.mdx index 44cef6c5ef..bbf7901ce5 100644 --- a/docs/query/validator-root-weights.mdx +++ b/docs/query/validator-root-weights.mdx @@ -47,6 +47,6 @@ Async is the same surface awaited: `async with bt.Subtensor() as client:`. ## On-chain implementation -- Runtime API [`BetaBasketRuntimeApi.get_validator_weights`](/code/runtime/src/lib.rs#L2369-L2371) +- Runtime API [`BetaBasketRuntimeApi.get_validator_weights`](/code/runtime/src/lib.rs#L2392-L2394) Every file is browsable under [/code](/code) exactly as built into the runtime. diff --git a/docs/tx/add-proxy.mdx b/docs/tx/add-proxy.mdx index d629342f52..93aa891ede 100644 --- a/docs/tx/add-proxy.mdx +++ b/docs/tx/add-proxy.mdx @@ -14,7 +14,7 @@ only to keys you control or fully trust. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.add_proxy`](/code/pallets/proxy/src/lib.rs#L279-L290) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.add_proxy`](/code/pallets/proxy/src/lib.rs#L282-L293) | ## Parameters @@ -65,7 +65,7 @@ result = sub.execute_tool("add_proxy", {...}, wallet) ## On-chain implementation -`Proxy.add_proxy` — [`pallets/proxy/src/lib.rs#L281`](/code/pallets/proxy/src/lib.rs#L279-L290): +`Proxy.add_proxy` — [`pallets/proxy/src/lib.rs#L284`](/code/pallets/proxy/src/lib.rs#L282-L293): ```rust #[pallet::call_index(1)] @@ -82,6 +82,6 @@ pub fn add_proxy( } ``` -Delegates to [`add_proxy_delegate`](/code/pallets/proxy/src/lib.rs#L955). +Delegates to [`add_proxy_delegate`](/code/pallets/proxy/src/lib.rs#L960). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/create-pure-proxy.mdx b/docs/tx/create-pure-proxy.mdx index 8d6385c4f9..c6fd5d12c2 100644 --- a/docs/tx/create-pure-proxy.mdx +++ b/docs/tx/create-pure-proxy.mdx @@ -15,7 +15,7 @@ the pure proxy and anything it holds. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.create_pure`](/code/pallets/proxy/src/lib.rs#L344-L378) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.create_pure`](/code/pallets/proxy/src/lib.rs#L347-L381) | ## Parameters @@ -64,7 +64,7 @@ result = sub.execute_tool("create_pure_proxy", {...}, wallet) ## On-chain implementation -`Proxy.create_pure` — [`pallets/proxy/src/lib.rs#L346`](/code/pallets/proxy/src/lib.rs#L344-L378): +`Proxy.create_pure` — [`pallets/proxy/src/lib.rs#L349`](/code/pallets/proxy/src/lib.rs#L347-L381): ```rust #[pallet::call_index(4)] @@ -104,6 +104,6 @@ pub fn create_pure( } ``` -Delegates to [`pure_account`](/code/pallets/proxy/src/lib.rs#L921). +Delegates to [`pure_account`](/code/pallets/proxy/src/lib.rs#L926). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/execute-proxy-announced.mdx b/docs/tx/execute-proxy-announced.mdx index 7e577e08b1..1c99d88243 100644 --- a/docs/tx/execute-proxy-announced.mdx +++ b/docs/tx/execute-proxy-announced.mdx @@ -14,7 +14,7 @@ matching announcement exists. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.proxy_announced`](/code/pallets/proxy/src/lib.rs#L554-L587) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.proxy_announced`](/code/pallets/proxy/src/lib.rs#L557-L592) | ## Parameters @@ -73,7 +73,7 @@ result = sub.execute_tool("execute_proxy_announced", {...}, wallet) ## On-chain implementation -`Proxy.proxy_announced` — [`pallets/proxy/src/lib.rs#L563`](/code/pallets/proxy/src/lib.rs#L554-L587): +`Proxy.proxy_announced` — [`pallets/proxy/src/lib.rs#L566`](/code/pallets/proxy/src/lib.rs#L557-L592): ```rust #[pallet::call_index(9)] @@ -91,7 +91,7 @@ result = sub.execute_tool("execute_proxy_announced", {...}, wallet) real: AccountIdLookupOf, force_proxy_type: Option, call: Box<::RuntimeCall>, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { ensure_signed(origin)?; let delegate = T::Lookup::lookup(delegate)?; let real = T::Lookup::lookup(real)?; @@ -106,12 +106,14 @@ result = sub.execute_tool("execute_proxy_announced", {...}, wallet) }) .map_err(|_| Error::::Unannounced)?; - Self::do_proxy(def, real, *call); + let weight = T::WeightInfo::proxy_announced(T::MaxPending::get(), T::MaxProxies::get()) + .saturating_add(T::DbWeight::get().reads_writes(1, 1)) + .saturating_add(Self::do_proxy(def, real, *call)); - Ok(()) + Ok(Some(weight).into()) } ``` -Delegates to [`find_proxy`](/code/pallets/proxy/src/lib.rs#L1099). +Delegates to [`find_proxy`](/code/pallets/proxy/src/lib.rs#L1104). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/kill-pure-proxy.mdx b/docs/tx/kill-pure-proxy.mdx index a4ddf1bf68..89b27abb81 100644 --- a/docs/tx/kill-pure-proxy.mdx +++ b/docs/tx/kill-pure-proxy.mdx @@ -13,7 +13,7 @@ account become permanently inaccessible, so empty it first. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.kill_pure`](/code/pallets/proxy/src/lib.rs#L396-L424) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.kill_pure`](/code/pallets/proxy/src/lib.rs#L399-L427) | ## Parameters @@ -66,7 +66,7 @@ result = sub.execute_tool("kill_pure_proxy", {...}, wallet) ## On-chain implementation -`Proxy.kill_pure` — [`pallets/proxy/src/lib.rs#L398`](/code/pallets/proxy/src/lib.rs#L396-L424): +`Proxy.kill_pure` — [`pallets/proxy/src/lib.rs#L401`](/code/pallets/proxy/src/lib.rs#L399-L427): ```rust #[pallet::call_index(5)] @@ -100,6 +100,6 @@ pub fn kill_pure( } ``` -Delegates to [`pure_account`](/code/pallets/proxy/src/lib.rs#L921). +Delegates to [`pure_account`](/code/pallets/proxy/src/lib.rs#L926). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/remove-proxies.mdx b/docs/tx/remove-proxies.mdx index 2d9f905179..f18d7295b8 100644 --- a/docs/tx/remove-proxies.mdx +++ b/docs/tx/remove-proxies.mdx @@ -12,7 +12,7 @@ permanently (there is no key to recover a pure proxy with). | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.remove_proxies`](/code/pallets/proxy/src/lib.rs#L318-L324) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.remove_proxies`](/code/pallets/proxy/src/lib.rs#L321-L327) | ## Parameters @@ -57,7 +57,7 @@ result = sub.execute_tool("remove_proxies", {...}, wallet) ## On-chain implementation -`Proxy.remove_proxies` — [`pallets/proxy/src/lib.rs#L320`](/code/pallets/proxy/src/lib.rs#L318-L324): +`Proxy.remove_proxies` — [`pallets/proxy/src/lib.rs#L323`](/code/pallets/proxy/src/lib.rs#L321-L327): ```rust #[pallet::call_index(3)] @@ -69,6 +69,6 @@ pub fn remove_proxies(origin: OriginFor) -> DispatchResult { } ``` -Delegates to [`remove_all_proxy_delegates`](/code/pallets/proxy/src/lib.rs#L1157). +Delegates to [`remove_all_proxy_delegates`](/code/pallets/proxy/src/lib.rs#L1166). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/docs/tx/remove-proxy.mdx b/docs/tx/remove-proxy.mdx index 6b245cff5b..27293afb26 100644 --- a/docs/tx/remove-proxy.mdx +++ b/docs/tx/remove-proxy.mdx @@ -12,7 +12,7 @@ to the signer. Check current delegations with `btcli query proxies`. | Signer | Origin | Pallet | Wraps | | --- | --- | --- | --- | -| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.remove_proxy`](/code/pallets/proxy/src/lib.rs#L299-L310) | +| `coldkey` | signed account (pallet role may apply) | Proxy | [`Proxy.remove_proxy`](/code/pallets/proxy/src/lib.rs#L302-L313) | ## Parameters @@ -63,7 +63,7 @@ result = sub.execute_tool("remove_proxy", {...}, wallet) ## On-chain implementation -`Proxy.remove_proxy` — [`pallets/proxy/src/lib.rs#L301`](/code/pallets/proxy/src/lib.rs#L299-L310): +`Proxy.remove_proxy` — [`pallets/proxy/src/lib.rs#L304`](/code/pallets/proxy/src/lib.rs#L302-L313): ```rust #[pallet::call_index(2)] @@ -80,6 +80,6 @@ pub fn remove_proxy( } ``` -Delegates to [`remove_proxy_delegate`](/code/pallets/proxy/src/lib.rs#L1000). +Delegates to [`remove_proxy_delegate`](/code/pallets/proxy/src/lib.rs#L1005). Every file is browsable under [/code](/code) exactly as built into the runtime, or as plain text under `/code/raw/` (index: [`/code/index.json`](/code/index.json)). diff --git a/pallets/limit-orders/src/benchmarking.rs b/pallets/limit-orders/src/benchmarking.rs index 6f33c65010..e17f9b51d2 100644 --- a/pallets/limit-orders/src/benchmarking.rs +++ b/pallets/limit-orders/src/benchmarking.rs @@ -37,12 +37,9 @@ fn sign_order( } else { payload }; - let sig = sp_io::crypto::sr25519_sign( - sp_core::crypto::key_types::ACCOUNT, - &public, - &signed_bytes, - ) - .unwrap(); + let sig = + sp_io::crypto::sr25519_sign(sp_core::crypto::key_types::ACCOUNT, &public, &signed_bytes) + .unwrap(); crate::SignedOrder { order: order.clone(), signature: MultiSignature::Sr25519(sig), diff --git a/pallets/limit-orders/src/lib.rs b/pallets/limit-orders/src/lib.rs index 8917ff29a1..fedfa8281a 100644 --- a/pallets/limit-orders/src/lib.rs +++ b/pallets/limit-orders/src/lib.rs @@ -213,6 +213,8 @@ pub(crate) struct OrderEntry { pub mod pallet { use super::*; use crate::weights::WeightInfo as _; + use alloc::format; + use alloc::string::String; use frame_support::{ PalletId, pallet_prelude::*, @@ -220,8 +222,6 @@ pub mod pallet { transactional, }; use frame_system::pallet_prelude::*; - use alloc::format; - use alloc::string::String; use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; use sp_runtime::traits::AccountIdConversion; use sp_std::collections::btree_set::BTreeSet; diff --git a/pallets/limit-orders/src/tests/ledger_vector.rs b/pallets/limit-orders/src/tests/ledger_vector.rs index 31c43e8113..8bf356aa4a 100644 --- a/pallets/limit-orders/src/tests/ledger_vector.rs +++ b/pallets/limit-orders/src/tests/ledger_vector.rs @@ -364,9 +364,8 @@ fn executable_vector_order() -> Order { #[test] fn executable_vector_is_the_seeds_signature_over_the_rendered_message() { new_test_ext().execute_with(|| { - let rendered = LimitOrders::::render_order(&VersionedOrder::V1( - executable_vector_order(), - )); + let rendered = + LimitOrders::::render_order(&VersionedOrder::V1(executable_vector_order())); assert_eq!( String::from_utf8(rendered.clone()).unwrap(), EXECUTABLE_MESSAGE, @@ -374,7 +373,10 @@ fn executable_vector_is_the_seeds_signature_over_the_rendered_message() { ); let payload = [b"".as_slice(), &rendered, b"".as_slice()].concat(); - assert!(payload.len() > LEDGER_MAX_SIGN_SIZE, "must be hashed, not signed bare"); + assert!( + payload.len() > LEDGER_MAX_SIGN_SIZE, + "must be hashed, not signed bare" + ); assert_eq!( sp_core::hashing::blake2_256(&payload), EXECUTABLE_VECTOR_DIGEST diff --git a/pallets/limit-orders/src/tests/readable.rs b/pallets/limit-orders/src/tests/readable.rs index bd7d724351..47217c743c 100644 --- a/pallets/limit-orders/src/tests/readable.rs +++ b/pallets/limit-orders/src/tests/readable.rs @@ -13,8 +13,8 @@ use frame_support::{ BoundedVec, assert_noop, assert_ok, traits::{ConstU32, Get}, }; -use sp_core::{H256, Pair}; use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; +use sp_core::{H256, Pair}; use sp_keyring::Sr25519Keyring as AccountKeyring; use sp_runtime::{MultiSignature, Perbill}; use subtensor_runtime_common::NetUid; @@ -131,24 +131,42 @@ fn render_account_uses_chain_ss58_prefix() { // B. render_order golden vectors // ───────────────────────────────────────────────────────────────────────────── -/// Independently reconstruct the canonical message from the order's fields using -/// the SS58 oracle. Deliberately NOT a copy of production `format!`. -fn expected_message( - label: &str, - price_word: &str, +struct ExpectedMessage<'a> { + label: &'a str, + price_word: &'a str, amount: u64, netuid_val: u16, limit_price: u64, expiry: u64, - hotkey: &AccountId, + hotkey: &'a AccountId, fee_rate_ppb: u32, - fee_recipient: &AccountId, - relayer_str: &str, - max_slippage_str: &str, + fee_recipient: &'a AccountId, + relayer_str: &'a str, + max_slippage_str: &'a str, chain_id: u64, partial: bool, - signer: &AccountId, -) -> String { + signer: &'a AccountId, +} + +/// Independently reconstruct the canonical message from expected values using +/// the SS58 oracle. Deliberately NOT a copy of production `format!`. +fn expected_message(expected: ExpectedMessage<'_>) -> String { + let ExpectedMessage { + label, + price_word, + amount, + netuid_val, + limit_price, + expiry, + hotkey, + fee_rate_ppb, + fee_recipient, + relayer_str, + max_slippage_str, + chain_id, + partial, + signer, + } = expected; format!( "TAO.com order v1: {label} {amount} on subnet {netuid_val}, \ {price_word} {limit_price}, expiry {expiry}, hotkey {hotkey}, \ @@ -188,24 +206,23 @@ fn render_order_golden_limit_buy_relayer_none() { chain_id: 945, partial_fills_enabled: false, }; - let versioned = VersionedOrder::V1(order); - let rendered = LimitOrders::::render_order(&versioned); - let expected = expected_message( - "Limit buy", - "limit price", - 1_234_567, - 7, - 2_000_000_000, - 9_999_999, - &bob(), - 5_000_000, - &fee_recipient(), - "none", - "none", - 945, - false, - &alice(), - ); + let expected = expected_message(ExpectedMessage { + label: "Limit buy", + price_word: "limit price", + amount: 1_234_567, + netuid_val: 7, + limit_price: 2_000_000_000, + expiry: 9_999_999, + hotkey: &bob(), + fee_rate_ppb: 5_000_000, + fee_recipient: &fee_recipient(), + relayer_str: "none", + max_slippage_str: "none", + chain_id: 945, + partial: false, + signer: &alice(), + }); + let rendered = LimitOrders::::render_order(&VersionedOrder::V1(order)); assert_eq!(String::from_utf8(rendered.clone()).unwrap(), expected); assert_all_printable_ascii(&rendered); }); @@ -231,24 +248,23 @@ fn render_order_golden_stop_loss_trigger_price_and_slippage() { chain_id: 945, partial_fills_enabled: true, }; - let versioned = VersionedOrder::V1(order); - let rendered = LimitOrders::::render_order(&versioned); - let expected = expected_message( - "Stop-loss", - "trigger price", - 500, - 2, - 750_000_000, - 42, - &dave(), - 0, - &alice(), - "none", - &Perbill::from_percent(1).deconstruct().to_string(), - 945, - true, - &charlie(), - ); + let expected = expected_message(ExpectedMessage { + label: "Stop-loss", + price_word: "trigger price", + amount: 500, + netuid_val: 2, + limit_price: 750_000_000, + expiry: 42, + hotkey: &dave(), + fee_rate_ppb: 0, + fee_recipient: &alice(), + relayer_str: "none", + max_slippage_str: &Perbill::from_percent(1).deconstruct().to_string(), + chain_id: 945, + partial: true, + signer: &charlie(), + }); + let rendered = LimitOrders::::render_order(&VersionedOrder::V1(order)); assert_eq!(String::from_utf8(rendered.clone()).unwrap(), expected); assert_all_printable_ascii(&rendered); }); @@ -276,25 +292,24 @@ fn render_order_golden_take_profit_two_relayers() { chain_id: 945, partial_fills_enabled: false, }; - let versioned = VersionedOrder::V1(order); - let rendered = LimitOrders::::render_order(&versioned); let relayer_str = format!("{}+{}", canonical_ss58(&bob()), canonical_ss58(&charlie())); - let expected = expected_message( - "Take-profit", - "trigger price", - 88, - 1, - 1_000_000_000, - 100_000, - &dave(), - 1, - &fee_recipient(), - &relayer_str, - "none", - 945, - false, - &alice(), - ); + let expected = expected_message(ExpectedMessage { + label: "Take-profit", + price_word: "trigger price", + amount: 88, + netuid_val: 1, + limit_price: 1_000_000_000, + expiry: 100_000, + hotkey: &dave(), + fee_rate_ppb: 1, + fee_recipient: &fee_recipient(), + relayer_str: &relayer_str, + max_slippage_str: "none", + chain_id: 945, + partial: false, + signer: &alice(), + }); + let rendered = LimitOrders::::render_order(&VersionedOrder::V1(order)); assert_eq!(String::from_utf8(rendered.clone()).unwrap(), expected); assert_all_printable_ascii(&rendered); }); @@ -309,24 +324,23 @@ fn render_order_golden_relayer_empty_list() { relayer: Some(empty), ..base_buy_order() }; - let versioned = VersionedOrder::V1(order); - let rendered = LimitOrders::::render_order(&versioned); - let expected = expected_message( - "Limit buy", - "limit price", - 1_000, - u16::from(netuid()), - u64::MAX, - u64::MAX, - &bob(), - 0, - &fee_recipient(), - "[]", - "none", - 945, - false, - &alice(), - ); + let expected = expected_message(ExpectedMessage { + label: "Limit buy", + price_word: "limit price", + amount: 1_000, + netuid_val: u16::from(netuid()), + limit_price: u64::MAX, + expiry: u64::MAX, + hotkey: &bob(), + fee_rate_ppb: 0, + fee_recipient: &fee_recipient(), + relayer_str: "[]", + max_slippage_str: "none", + chain_id: 945, + partial: false, + signer: &alice(), + }); + let rendered = LimitOrders::::render_order(&VersionedOrder::V1(order)); assert_eq!(String::from_utf8(rendered.clone()).unwrap(), expected); assert_all_printable_ascii(&rendered); }); diff --git a/runtime/tests/limit_orders.rs b/runtime/tests/limit_orders.rs index 1f62b4f4f9..76de6ac8a7 100644 --- a/runtime/tests/limit_orders.rs +++ b/runtime/tests/limit_orders.rs @@ -18,8 +18,8 @@ use pallet_limit_orders::{ VersionedOrder, }; use pallet_subtensor::{SubnetAlphaIn, SubnetMechanism, SubnetTAO}; -use sp_core::{Get, H256, Pair}; use sp_core::crypto::{Ss58AddressFormat, Ss58Codec}; +use sp_core::{Get, H256, Pair}; use sp_keyring::Sr25519Keyring; use sp_runtime::traits::{AccountIdConversion, IdentifyAccount, Verify}; use sp_runtime::{MultiSignature, MultiSigner, Perbill}; @@ -2815,11 +2815,7 @@ fn render_order_readable(order: &Order) -> Vec { let relayer = match &order.relayer { None => "none".to_string(), Some(list) if list.is_empty() => "[]".to_string(), - Some(list) => list - .iter() - .map(ss58) - .collect::>() - .join("+"), + Some(list) => list.iter().map(ss58).collect::>().join("+"), }; let netuid: u16 = u16::from(order.netuid); format!( diff --git a/ts-tests/suites/dev/subtensor/limit-orders/test-ledger-raw-sign-vector.ts b/ts-tests/suites/dev/subtensor/limit-orders/test-ledger-raw-sign-vector.ts index a4fee1ecb2..7953104365 100644 --- a/ts-tests/suites/dev/subtensor/limit-orders/test-ledger-raw-sign-vector.ts +++ b/ts-tests/suites/dev/subtensor/limit-orders/test-ledger-raw-sign-vector.ts @@ -233,9 +233,7 @@ describeSuite({ ["the ASCII hex of the digest", bytes(u8aToHex(digest()).slice(2))], ]; for (const [form, message] of rejected) { - expect(ed25519Verify(message, signature, publicKey), `must not verify over ${form}`).toBe( - false - ); + expect(ed25519Verify(message, signature, publicKey), `must not verify over ${form}`).toBe(false); } }, }); @@ -244,9 +242,7 @@ describeSuite({ id: "T06", title: "buildReadableSignedOrder emits the device shape for the executable vector", test: () => { - const signer = new Keyring({ type: "ed25519" }).addFromSeed( - hexToU8a(SOFTWARE_VECTOR.seedHex) - ); + const signer = new Keyring({ type: "ed25519" }).addFromSeed(hexToU8a(SOFTWARE_VECTOR.seedHex)); expect(signer.address).toBe(SOFTWARE_ADDRESS); // `api` is unused by the readable builder (the payload is rendered from diff --git a/website/apps/bittensor-website/public/catalog/errors.json b/website/apps/bittensor-website/public/catalog/errors.json index 4ae02ca5ba..e2a6ee525c 100644 --- a/website/apps/bittensor-website/public/catalog/errors.json +++ b/website/apps/bittensor-website/public/catalog/errors.json @@ -393,8 +393,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 809, - "url": "/code/pallets/proxy/src/lib.rs#L809", + "line": 814, + "url": "/code/pallets/proxy/src/lib.rs#L814", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -411,8 +411,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 352, - "url": "/code/pallets/limit-orders/src/lib.rs#L352", + "line": 373, + "url": "/code/pallets/limit-orders/src/lib.rs#L373", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -807,8 +807,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 346, - "url": "/code/pallets/limit-orders/src/lib.rs#L346", + "line": 367, + "url": "/code/pallets/limit-orders/src/lib.rs#L367", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -1417,8 +1417,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 181, - "url": "/code/pallets/swap/src/pallet/mod.rs#L181", + "line": 182, + "url": "/code/pallets/swap/src/pallet/mod.rs#L182", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -1471,8 +1471,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 801, - "url": "/code/pallets/proxy/src/lib.rs#L801", + "line": 806, + "url": "/code/pallets/proxy/src/lib.rs#L806", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1525,8 +1525,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 354, - "url": "/code/pallets/limit-orders/src/lib.rs#L354", + "line": 375, + "url": "/code/pallets/limit-orders/src/lib.rs#L375", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -1759,8 +1759,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 145, - "url": "/code/pallets/swap/src/pallet/mod.rs#L145", + "line": 146, + "url": "/code/pallets/swap/src/pallet/mod.rs#L146", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -1966,8 +1966,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 342, - "url": "/code/pallets/limit-orders/src/lib.rs#L342", + "line": 363, + "url": "/code/pallets/limit-orders/src/lib.rs#L363", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -2065,8 +2065,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 157, - "url": "/code/pallets/swap/src/pallet/mod.rs#L157", + "line": 158, + "url": "/code/pallets/swap/src/pallet/mod.rs#L158", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -2083,8 +2083,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 148, - "url": "/code/pallets/swap/src/pallet/mod.rs#L148", + "line": 149, + "url": "/code/pallets/swap/src/pallet/mod.rs#L149", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -2109,8 +2109,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 151, - "url": "/code/pallets/swap/src/pallet/mod.rs#L151", + "line": 152, + "url": "/code/pallets/swap/src/pallet/mod.rs#L152", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -2253,8 +2253,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 811, - "url": "/code/pallets/proxy/src/lib.rs#L811", + "line": 816, + "url": "/code/pallets/proxy/src/lib.rs#L816", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -2397,8 +2397,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 163, - "url": "/code/pallets/swap/src/pallet/mod.rs#L163", + "line": 164, + "url": "/code/pallets/swap/src/pallet/mod.rs#L164", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -2579,8 +2579,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 318, - "url": "/code/pallets/limit-orders/src/lib.rs#L318", + "line": 339, + "url": "/code/pallets/limit-orders/src/lib.rs#L339", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -2606,8 +2606,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 160, - "url": "/code/pallets/swap/src/pallet/mod.rs#L160", + "line": 161, + "url": "/code/pallets/swap/src/pallet/mod.rs#L161", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -2803,8 +2803,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 336, - "url": "/code/pallets/limit-orders/src/lib.rs#L336", + "line": 357, + "url": "/code/pallets/limit-orders/src/lib.rs#L357", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -3063,8 +3063,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 169, - "url": "/code/pallets/swap/src/pallet/mod.rs#L169", + "line": 170, + "url": "/code/pallets/swap/src/pallet/mod.rs#L170", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -3423,8 +3423,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 803, - "url": "/code/pallets/proxy/src/lib.rs#L803", + "line": 808, + "url": "/code/pallets/proxy/src/lib.rs#L808", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -3441,8 +3441,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 807, - "url": "/code/pallets/proxy/src/lib.rs#L807", + "line": 812, + "url": "/code/pallets/proxy/src/lib.rs#L812", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -3713,8 +3713,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 795, - "url": "/code/pallets/proxy/src/lib.rs#L795", + "line": 800, + "url": "/code/pallets/proxy/src/lib.rs#L800", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -3767,8 +3767,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 797, - "url": "/code/pallets/proxy/src/lib.rs#L797", + "line": 802, + "url": "/code/pallets/proxy/src/lib.rs#L802", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -3857,8 +3857,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 320, - "url": "/code/pallets/limit-orders/src/lib.rs#L320", + "line": 341, + "url": "/code/pallets/limit-orders/src/lib.rs#L341", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -3875,8 +3875,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 322, - "url": "/code/pallets/limit-orders/src/lib.rs#L322", + "line": 343, + "url": "/code/pallets/limit-orders/src/lib.rs#L343", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -3893,8 +3893,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 324, - "url": "/code/pallets/limit-orders/src/lib.rs#L324", + "line": 345, + "url": "/code/pallets/limit-orders/src/lib.rs#L345", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -3911,8 +3911,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 334, - "url": "/code/pallets/limit-orders/src/lib.rs#L334", + "line": 355, + "url": "/code/pallets/limit-orders/src/lib.rs#L355", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -4009,8 +4009,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 350, - "url": "/code/pallets/limit-orders/src/lib.rs#L350", + "line": 371, + "url": "/code/pallets/limit-orders/src/lib.rs#L371", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -4027,8 +4027,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 340, - "url": "/code/pallets/limit-orders/src/lib.rs#L340", + "line": 361, + "url": "/code/pallets/limit-orders/src/lib.rs#L361", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -4072,8 +4072,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 326, - "url": "/code/pallets/limit-orders/src/lib.rs#L326", + "line": 347, + "url": "/code/pallets/limit-orders/src/lib.rs#L347", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -4090,8 +4090,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 154, - "url": "/code/pallets/swap/src/pallet/mod.rs#L154", + "line": 155, + "url": "/code/pallets/swap/src/pallet/mod.rs#L155", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -4207,8 +4207,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 338, - "url": "/code/pallets/limit-orders/src/lib.rs#L338", + "line": 359, + "url": "/code/pallets/limit-orders/src/lib.rs#L359", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -4225,8 +4225,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 344, - "url": "/code/pallets/limit-orders/src/lib.rs#L344", + "line": 365, + "url": "/code/pallets/limit-orders/src/lib.rs#L365", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -4270,8 +4270,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 175, - "url": "/code/pallets/swap/src/pallet/mod.rs#L175", + "line": 176, + "url": "/code/pallets/swap/src/pallet/mod.rs#L176", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -4288,8 +4288,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 166, - "url": "/code/pallets/swap/src/pallet/mod.rs#L166", + "line": 167, + "url": "/code/pallets/swap/src/pallet/mod.rs#L167", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -4369,8 +4369,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 332, - "url": "/code/pallets/limit-orders/src/lib.rs#L332", + "line": 353, + "url": "/code/pallets/limit-orders/src/lib.rs#L353", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -4791,8 +4791,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 172, - "url": "/code/pallets/swap/src/pallet/mod.rs#L172", + "line": 173, + "url": "/code/pallets/swap/src/pallet/mod.rs#L173", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -4809,8 +4809,8 @@ { "pallet": "Swap", "path": "pallets/swap/src/pallet/mod.rs", - "line": 178, - "url": "/code/pallets/swap/src/pallet/mod.rs#L178", + "line": 179, + "url": "/code/pallets/swap/src/pallet/mod.rs#L179", "raw_url": "/code/raw/pallets/swap/src/pallet/mod.rs" } ] @@ -4827,8 +4827,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 330, - "url": "/code/pallets/limit-orders/src/lib.rs#L330", + "line": 351, + "url": "/code/pallets/limit-orders/src/lib.rs#L351", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -4954,8 +4954,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 793, - "url": "/code/pallets/proxy/src/lib.rs#L793", + "line": 798, + "url": "/code/pallets/proxy/src/lib.rs#L798", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -5350,8 +5350,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 805, - "url": "/code/pallets/proxy/src/lib.rs#L805", + "line": 810, + "url": "/code/pallets/proxy/src/lib.rs#L810", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -5369,8 +5369,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 328, - "url": "/code/pallets/limit-orders/src/lib.rs#L328", + "line": 349, + "url": "/code/pallets/limit-orders/src/lib.rs#L349", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] @@ -5459,8 +5459,8 @@ { "pallet": "Proxy", "path": "pallets/proxy/src/lib.rs", - "line": 799, - "url": "/code/pallets/proxy/src/lib.rs#L799", + "line": 804, + "url": "/code/pallets/proxy/src/lib.rs#L804", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -5684,8 +5684,8 @@ { "pallet": "LimitOrders", "path": "pallets/limit-orders/src/lib.rs", - "line": 359, - "url": "/code/pallets/limit-orders/src/lib.rs#L359", + "line": 380, + "url": "/code/pallets/limit-orders/src/lib.rs#L380", "raw_url": "/code/raw/pallets/limit-orders/src/lib.rs" } ] diff --git a/website/apps/bittensor-website/public/catalog/intents.json b/website/apps/bittensor-website/public/catalog/intents.json index e15ed75506..b6c93a3941 100644 --- a/website/apps/bittensor-website/public/catalog/intents.json +++ b/website/apps/bittensor-website/public/catalog/intents.json @@ -106,9 +106,9 @@ "pallet": "Proxy", "call": "add_proxy", "path": "pallets/proxy/src/lib.rs", - "line": 281, - "end_line": 290, - "url": "/code/pallets/proxy/src/lib.rs#L279-L290", + "line": 284, + "end_line": 293, + "url": "/code/pallets/proxy/src/lib.rs#L282-L293", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -875,9 +875,9 @@ "pallet": "Proxy", "call": "create_pure", "path": "pallets/proxy/src/lib.rs", - "line": 346, - "end_line": 378, - "url": "/code/pallets/proxy/src/lib.rs#L344-L378", + "line": 349, + "end_line": 381, + "url": "/code/pallets/proxy/src/lib.rs#L347-L381", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1103,9 +1103,9 @@ "pallet": "Proxy", "call": "proxy_announced", "path": "pallets/proxy/src/lib.rs", - "line": 563, - "end_line": 587, - "url": "/code/pallets/proxy/src/lib.rs#L554-L587", + "line": 566, + "end_line": 592, + "url": "/code/pallets/proxy/src/lib.rs#L557-L592", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1304,9 +1304,9 @@ "pallet": "Proxy", "call": "kill_pure", "path": "pallets/proxy/src/lib.rs", - "line": 398, - "end_line": 424, - "url": "/code/pallets/proxy/src/lib.rs#L396-L424", + "line": 401, + "end_line": 427, + "url": "/code/pallets/proxy/src/lib.rs#L399-L427", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1821,9 +1821,9 @@ "pallet": "Proxy", "call": "remove_proxies", "path": "pallets/proxy/src/lib.rs", - "line": 320, - "end_line": 324, - "url": "/code/pallets/proxy/src/lib.rs#L318-L324", + "line": 323, + "end_line": 327, + "url": "/code/pallets/proxy/src/lib.rs#L321-L327", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1871,9 +1871,9 @@ "pallet": "Proxy", "call": "remove_proxy", "path": "pallets/proxy/src/lib.rs", - "line": 301, - "end_line": 310, - "url": "/code/pallets/proxy/src/lib.rs#L299-L310", + "line": 304, + "end_line": 313, + "url": "/code/pallets/proxy/src/lib.rs#L302-L313", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] diff --git a/website/apps/bittensor-website/public/catalog/reads.json b/website/apps/bittensor-website/public/catalog/reads.json index 74a5682bea..2af3ebf83b 100644 --- a/website/apps/bittensor-website/public/catalog/reads.json +++ b/website/apps/bittensor-website/public/catalog/reads.json @@ -42,9 +42,9 @@ "container": "SwapRuntimeApi", "name": "current_alpha_price_all", "path": "runtime/src/lib.rs", - "line": 2455, - "end_line": 2465, - "url": "/code/runtime/src/lib.rs#L2455-L2465", + "line": 2478, + "end_line": 2488, + "url": "/code/runtime/src/lib.rs#L2478-L2488", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -275,9 +275,9 @@ "container": "SubnetInfoRuntimeApi", "name": "get_next_epoch_start_block", "path": "pallets/subtensor/src/coinbase/run_coinbase.rs", - "line": 1258, - "end_line": 1272, - "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272", + "line": 1262, + "end_line": 1276, + "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1262-L1276", "raw_url": "/code/raw/pallets/subtensor/src/coinbase/run_coinbase.rs" } ] @@ -797,9 +797,9 @@ "container": "SubnetInfoRuntimeApi", "name": "get_next_epoch_start_block", "path": "pallets/subtensor/src/coinbase/run_coinbase.rs", - "line": 1258, - "end_line": 1272, - "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272", + "line": 1262, + "end_line": 1276, + "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1262-L1276", "raw_url": "/code/raw/pallets/subtensor/src/coinbase/run_coinbase.rs" } ] @@ -848,9 +848,9 @@ "container": "StakeInfoRuntimeApi", "name": "get_hotkey_conviction", "path": "runtime/src/lib.rs", - "line": 2338, - "end_line": 2340, - "url": "/code/runtime/src/lib.rs#L2338-L2340", + "line": 2361, + "end_line": 2363, + "url": "/code/runtime/src/lib.rs#L2361-L2363", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -1282,9 +1282,9 @@ "container": "StakeInfoRuntimeApi", "name": "get_most_convicted_hotkey_on_subnet", "path": "runtime/src/lib.rs", - "line": 2342, - "end_line": 2344, - "url": "/code/runtime/src/lib.rs#L2342-L2344", + "line": 2365, + "end_line": 2367, + "url": "/code/runtime/src/lib.rs#L2365-L2367", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -1398,9 +1398,9 @@ "container": "SubnetInfoRuntimeApi", "name": "get_next_epoch_start_block", "path": "pallets/subtensor/src/coinbase/run_coinbase.rs", - "line": 1258, - "end_line": 1272, - "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1258-L1272", + "line": 1262, + "end_line": 1276, + "url": "/code/pallets/subtensor/src/coinbase/run_coinbase.rs#L1262-L1276", "raw_url": "/code/raw/pallets/subtensor/src/coinbase/run_coinbase.rs" } ] @@ -1507,8 +1507,8 @@ "container": "Proxy", "name": "Proxies", "path": "pallets/proxy/src/lib.rs", - "line": 825, - "url": "/code/pallets/proxy/src/lib.rs#L825", + "line": 830, + "url": "/code/pallets/proxy/src/lib.rs#L830", "raw_url": "/code/raw/pallets/proxy/src/lib.rs" } ] @@ -1535,9 +1535,9 @@ "container": "SwapRuntimeApi", "name": "sim_swap_tao_for_alpha", "path": "runtime/src/lib.rs", - "line": 2467, - "end_line": 2495, - "url": "/code/runtime/src/lib.rs#L2467-L2495", + "line": 2490, + "end_line": 2518, + "url": "/code/runtime/src/lib.rs#L2490-L2518", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -1564,9 +1564,9 @@ "container": "SwapRuntimeApi", "name": "sim_swap_alpha_for_tao", "path": "runtime/src/lib.rs", - "line": 2497, - "end_line": 2525, - "url": "/code/runtime/src/lib.rs#L2497-L2525", + "line": 2520, + "end_line": 2548, + "url": "/code/runtime/src/lib.rs#L2520-L2548", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -1645,9 +1645,9 @@ "container": "BetaBasketRuntimeApi", "name": "get_root_basket_owed", "path": "runtime/src/lib.rs", - "line": 2354, - "end_line": 2356, - "url": "/code/runtime/src/lib.rs#L2354-L2356", + "line": 2377, + "end_line": 2379, + "url": "/code/runtime/src/lib.rs#L2377-L2379", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -1695,9 +1695,9 @@ "container": "BetaBasketRuntimeApi", "name": "get_root_basket_total_nav", "path": "runtime/src/lib.rs", - "line": 2366, - "end_line": 2368, - "url": "/code/runtime/src/lib.rs#L2366-L2368", + "line": 2389, + "end_line": 2391, + "url": "/code/runtime/src/lib.rs#L2389-L2391", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -2244,9 +2244,9 @@ "container": "SubnetRegistrationRuntimeApi", "name": "get_network_registration_cost", "path": "runtime/src/lib.rs", - "line": 2348, - "end_line": 2350, - "url": "/code/runtime/src/lib.rs#L2348-L2350", + "line": 2371, + "end_line": 2373, + "url": "/code/runtime/src/lib.rs#L2371-L2373", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -2280,8 +2280,8 @@ "container": "SubtensorModule", "name": "InitialStartCallDelay", "path": "runtime/src/lib.rs", - "line": 851, - "url": "/code/runtime/src/lib.rs#L851", + "line": 874, + "url": "/code/runtime/src/lib.rs#L874", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -2493,9 +2493,9 @@ "container": "BetaBasketRuntimeApi", "name": "get_validator_basket_nav", "path": "runtime/src/lib.rs", - "line": 2360, - "end_line": 2362, - "url": "/code/runtime/src/lib.rs#L2360-L2362", + "line": 2383, + "end_line": 2385, + "url": "/code/runtime/src/lib.rs#L2383-L2385", "raw_url": "/code/raw/runtime/src/lib.rs" } ] @@ -2547,9 +2547,9 @@ "container": "BetaBasketRuntimeApi", "name": "get_validator_weights", "path": "runtime/src/lib.rs", - "line": 2369, - "end_line": 2371, - "url": "/code/runtime/src/lib.rs#L2369-L2371", + "line": 2392, + "end_line": 2394, + "url": "/code/runtime/src/lib.rs#L2392-L2394", "raw_url": "/code/raw/runtime/src/lib.rs" } ] From 28e3c5fcdfb76180bf31041e7bf068f258265662 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Mon, 10 Aug 2026 20:17:13 +0200 Subject: [PATCH 53/58] docs: correct documentation details --- docs/concepts/emissions.mdx | 7 ++--- docs/concepts/money.mdx | 5 ++-- docs/concepts/transactions.mdx | 27 +++++++++++-------- .../releases/v444-upgrade/page.tsx | 2 +- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/docs/concepts/emissions.mdx b/docs/concepts/emissions.mdx index 1a313056d4..85a8bfd639 100644 --- a/docs/concepts/emissions.mdx +++ b/docs/concepts/emissions.mdx @@ -22,9 +22,10 @@ Halvings are triggered by **total-issuance thresholds**, not block counts: emission halves each time issuance crosses the midpoint of the remaining supply (10.5M, 15.75M, ...) ([`get_block_emission_for_issuance`](/code/pallets/subtensor/src/coinbase/block_emission.rs#L38-L81)). -Because recycled TAO (registration burns) is subtracted from total issuance -and can be re-emitted, recycling pushes halvings out. Transaction fees are -not recycled — they are paid to the block author (see +Because recycled TAO is subtracted from total issuance and can be re-emitted, +recycling pushes halvings out. This includes registration burns and transaction +fees: native TAO fees and EVM fees reduce issuance directly, while eligible +alpha-paid fees are sold for TAO and recycled atomically (see [fees](/docs/concepts/transactions#fees)). The first halving occurred in December 2025: current emission is 0.5 TAO per diff --git a/docs/concepts/money.mdx b/docs/concepts/money.mdx index 98a207eddf..5eb14b989d 100644 --- a/docs/concepts/money.mdx +++ b/docs/concepts/money.mdx @@ -118,6 +118,7 @@ schedule can re-issue them later — neuron registration costs are recycled this way. **Burned** tokens stay counted in total issuance and are simply gone forever; nothing re-emits them. The distinction matters when reasoning about supply: recycling slows emission's approach to the cap, burning -permanently retires supply. Transaction fees are neither — they are paid to -the block author, not destroyed +permanently retires supply. Transaction fees are recycled rather than paid to +the block author: native TAO and EVM fees reduce issuance directly, while +eligible alpha-paid fees are sold for TAO and recycled atomically ([fees](/docs/concepts/transactions#fees)). diff --git a/docs/concepts/transactions.mdx b/docs/concepts/transactions.mdx index b36f3058b3..4e74a96a29 100644 --- a/docs/concepts/transactions.mdx +++ b/docs/concepts/transactions.mdx @@ -142,22 +142,27 @@ serving has its own code 12. ## Fees -A fee-bearing extrinsic pays two components in TAO from the signer's free -balance: a **weight fee**, linear in the call's dispatch weight, and a -**length fee** of 1 rao per byte of the encoded extrinsic. Both are withdrawn -up front, before the call runs — insufficient balance rejects the transaction -outright, and a failed call does not refund them. The fee is paid to the -block author, not recycled or burned (dropped in the edge case of a block -with no author). `plan.fee` (and the `--dry-run` output) is this number, -estimated from the chain before anything is signed. +A fee-bearing extrinsic normally pays two components in TAO from the signer's +free balance: a **weight fee**, linear in the call's dispatch weight, and a +**length fee** of 1 rao per byte of the encoded extrinsic. The estimated fee is +withdrawn before the call runs — insufficient balance rejects the transaction +outright. After execution, TAO fees are corrected for actual dispatch weight +where the call reports it; a failed call still pays its resulting fee. The +final fee and any tip are **recycled** by reducing total issuance instead of +being paid to the block author. `plan.fee` (and the `--dry-run` output) is the +chain's estimate before anything is signed. + +EVM base and priority fees follow the same recycling path. For a small set of +unstake-side calls (`remove_stake` and friends), a signer with no TAO can have +the fee taken in alpha instead. The alpha is sold for TAO and the resulting TAO +is recycled atomically; alpha-paid transaction fees are final rather than +post-dispatch adjusted. The validator hot path is free: [`set-weights`](/docs/tx/set-weights), [`commit-weights`](/docs/tx/commit-weights), [`reveal-weights`](/docs/tx/reveal-weights) and their batch and timelocked variants pay no transaction fee, as do [`serve-axon`](/docs/tx/serve-axon) -and take changes. For a small set of unstake-side calls (`remove_stake` and -friends), a signer with no TAO can have the fee taken in alpha instead, -converted at pool price; every other call simply requires TAO. +and take changes. Calls outside the alpha-fee fallback set require TAO. Staking, unstaking, and stake moves additionally pay a pool swap fee on the amount transacted — a property of the swap, not the extrinsic; see diff --git a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx index 897232817f..b11bdd7113 100644 --- a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx +++ b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx @@ -270,7 +270,7 @@ btcli wallet transfer --dest 5F... --amount-tao 10 -w team-treasury`} on subnet , -limit price , expiry , hotkey , fee to , +limit price , expiry , hotkey , fee to , relayer , max slippage , chain , partial fills , signer `} /> From f699950f4a89e3e20e8a3742e5fabafc478fc983 Mon Sep 17 00:00:00 2001 From: UnArbosSix Date: Mon, 10 Aug 2026 11:30:55 -0700 Subject: [PATCH 54/58] fix pre-compile conversions --- docs/guides/evm/precompiles/alpha.mdx | 4 +- docs/guides/evm/precompiles/timestamp.mdx | 4 +- precompiles/src/alpha.rs | 54 +++++++++++++++++++++-- precompiles/src/timestamp.rs | 10 +++-- 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/docs/guides/evm/precompiles/alpha.mdx b/docs/guides/evm/precompiles/alpha.mdx index ae4cf01904..f56aca7c6e 100644 --- a/docs/guides/evm/precompiles/alpha.mdx +++ b/docs/guides/evm/precompiles/alpha.mdx @@ -45,7 +45,9 @@ hasSwapMigrationRun(bytes) Flow values use signed Solidity integers. Fixed-point economic values are returned as their raw runtime bits. `getSwapState` includes the fee, initialization status, balancer quote weight, and both protocol reservoirs; -the initialization flag is the generic swap-initialization view. +the initialization flag is the generic swap-initialization view. The +`blockEmission` field returned by `getEmissionGateConfig` is the current value +calculated from total issuance, matching runtime minting. ## Added operations diff --git a/docs/guides/evm/precompiles/timestamp.mdx b/docs/guides/evm/precompiles/timestamp.mdx index 5c78dfffee..1ff113ed92 100644 --- a/docs/guides/evm/precompiles/timestamp.mdx +++ b/docs/guides/evm/precompiles/timestamp.mdx @@ -17,8 +17,8 @@ description: Typed EVM interface for Timestamp pallet state. | `getTimestamp()` | `Timestamp.Now` | | `wasUpdatedThisBlock()` | `Timestamp.DidUpdate` | -`getTimestamp()` returns the same underlying time as the EVM -`block.timestamp` value. It exists here so every storage item authorized through +`getTimestamp()` converts the pallet's millisecond timestamp to Unix seconds, +matching the EVM `block.timestamp` value. It exists here so every storage item authorized through `StorageQueryPrecompile` has an explicit typed replacement. `wasUpdatedThisBlock` provides the Timestamp pallet's update state without requiring contracts to construct a storage key or decode SCALE. diff --git a/precompiles/src/alpha.rs b/precompiles/src/alpha.rs index 62b70272d4..0f7b8c21b5 100644 --- a/precompiles/src/alpha.rs +++ b/precompiles/src/alpha.rs @@ -413,9 +413,13 @@ where handle: &mut impl PrecompileHandle, ) -> EvmResult<(u64, U256, bool, U256, u128, u128, u128, u128, u64)> { handle.record_db_reads::(9)?; + let block_emission = pallet_subtensor::Pallet::::calculate_block_emission() + .map_err(|error| PrecompileFailure::Error { + exit_status: ExitError::Other(error.into()), + })? + .to_u64(); Ok(( - #[allow(deprecated)] - pallet_subtensor::BlockEmission::::get(), + block_emission, signed_i128_word(pallet_subtensor::SubnetMovingAlpha::::get().to_bits()), pallet_subtensor::NetTaoFlowEnabled::::get(), signed_i128_word(pallet_subtensor::TaoFlowCutoff::::get().to_bits()), @@ -888,9 +892,10 @@ mod tests { ), ); - #[allow(deprecated)] let emission_gate = ( - pallet_subtensor::BlockEmission::::get(), + pallet_subtensor::Pallet::::calculate_block_emission() + .expect("block emission calculation should succeed") + .to_u64(), signed_i128_word(pallet_subtensor::SubnetMovingAlpha::::get().to_bits()), pallet_subtensor::NetTaoFlowEnabled::::get(), signed_i128_word(pallet_subtensor::TaoFlowCutoff::::get().to_bits()), @@ -941,6 +946,47 @@ mod tests { }); } + #[test] + fn emission_gate_block_emission_matches_runtime_at_halving_boundary() { + new_test_ext().execute_with(|| { + const FIRST_HALVING_ISSUANCE: u64 = 10_500_000_000_000_000; + + pallet_subtensor::TotalIssuance::::put(TaoBalance::from( + FIRST_HALVING_ISSUANCE, + )); + #[allow(deprecated)] + pallet_subtensor::BlockEmission::::put(123_u64); + + let expected_block_emission = + pallet_subtensor::Pallet::::calculate_block_emission() + .expect("halving-boundary emission calculation should succeed") + .to_u64(); + assert_eq!(expected_block_emission, 500_000_000); + + let precompiles = precompiles::>(); + assert_view( + &precompiles, + addr_from_index(1), + addr_from_index(AlphaPrecompile::::INDEX), + "getEmissionGateConfig()", + (), + ( + expected_block_emission, + signed_i128_word( + pallet_subtensor::SubnetMovingAlpha::::get().to_bits(), + ), + pallet_subtensor::NetTaoFlowEnabled::::get(), + signed_i128_word(pallet_subtensor::TaoFlowCutoff::::get().to_bits()), + pallet_subtensor::FlowNormExponent::::get().to_bits(), + pallet_subtensor::EmissionBarQuantile::::get().to_bits(), + pallet_subtensor::EmissionGateExponent::::get().to_bits(), + pallet_subtensor::EmissionGateBar::::get().to_bits(), + pallet_subtensor::FlowEmaSmoothingFactor::::get(), + ), + ); + }); + } + fn assert_view( precompiles: &impl pallet_evm::PrecompileSet, caller: sp_core::H160, diff --git a/precompiles/src/timestamp.rs b/precompiles/src/timestamp.rs index 7878200ddc..f7500a8070 100644 --- a/precompiles/src/timestamp.rs +++ b/precompiles/src/timestamp.rs @@ -42,9 +42,10 @@ where #[precompile::view] fn get_timestamp(handle: &mut impl PrecompileHandle) -> EvmResult { handle.record_db_reads::(1)?; - pallet_timestamp::Pallet::::get() + let timestamp_millis: u64 = pallet_timestamp::Pallet::::get() .try_into() - .map_err(|_| conversion_error("timestamp moment")) + .map_err(|_| conversion_error("timestamp moment"))?; + Ok(timestamp_millis / 1_000) } #[precompile::public("wasUpdatedThisBlock()")] @@ -74,10 +75,10 @@ mod tests { }; #[test] - fn address_selectors_and_values_are_stable() { + fn views_match_evm_timestamp_and_update_state() { new_test_ext().execute_with(|| { assert_eq!(TimestampPrecompile::::INDEX, 2065); - Timestamp::set_timestamp(1_234); + Timestamp::set_timestamp(1_234_567); let precompiles = precompiles::>(); let caller = addr_from_index(1); @@ -92,6 +93,7 @@ mod tests { ) .with_static_call(true) .expect_cost(read_cost) + // Frontier exposes pallet timestamp milliseconds as EVM seconds. .execute_returns_raw(encode_return_value(1_234u64)); precompiles .prepare_test( From 16a6b86815c11c4577bf80caf5da851340730922 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Mon, 10 Aug 2026 20:37:10 +0200 Subject: [PATCH 55/58] docs: synchronize EVM interface artifacts --- docs/guides/evm/precompile-design.mdx | 50 ++++++++++--------- docs/guides/evm/precompiles/registry.mdx | 15 ++++-- precompiles/src/solidity/registry.sol | 3 ++ precompiles/src/solidity/stakingV2.abi | 32 ++++++++++-- precompiles/src/solidity/stakingV2.sol | 12 +++++ sdk/python/bittensor/evm/abi/stakingV2.json | 32 ++++++++++-- sdk/python/tests/unit/test_evm.py | 15 ++++++ .../releases/v444-upgrade/page.tsx | 13 +++-- 8 files changed, 131 insertions(+), 41 deletions(-) diff --git a/docs/guides/evm/precompile-design.mdx b/docs/guides/evm/precompile-design.mdx index a2a233c57f..570b57244e 100644 --- a/docs/guides/evm/precompile-design.mdx +++ b/docs/guides/evm/precompile-design.mdx @@ -9,8 +9,9 @@ and durable chain values without requiring contracts to understand Substrate storage. This page defines the compatibility model that new and existing precompiles -should follow. It also describes the target lifecycle registry. The registry -interface shown below is a design contract; it is not yet available on chain. +should follow. The deployed registry currently reports whole-precompile +availability. Function-level lifecycle metadata remains a future extension of +that interface. A deployed contract may be immutable. Treat every released precompile address, @@ -27,8 +28,9 @@ The precompile layer is designed around five goals: richer behavior is introduced through new function versions. 3. **Deprecation is normally soft.** An old function continues to preserve its original behavior whenever that behavior can still be represented safely. -4. **Status is discoverable.** Solidity interfaces and a registry should tell - developers when a function is deprecated, replaced, or temporarily disabled. +4. **Status is discoverable.** The registry reports whether a precompile is + disabled. Solidity interfaces document the supported selectors; typed + function-level lifecycle metadata is a future extension. 5. **The signed, deterministic Substrate API has typed parity.** Storage and runtime API results have bounded typed views, and extrinsics that accept a non-Root signed origin have typed operations. @@ -178,8 +180,8 @@ without receiving any authority to change it: contract logic that depends on the runtime's randomness state. - Timestamp views replace raw reads of timestamp storage; `getTimestamp` corresponds to the same underlying time represented by `block.timestamp`. -- Lifecycle views let contracts and tooling discover whether a selector is - deprecated, replaced, or currently unavailable. +- The registry lets contracts and tooling discover whether a whole precompile + is currently disabled. Canonical interfaces and ABIs define its selectors. These views replace raw storage decoding or off-chain RPC composition. They do not execute privileged extrinsics and do not provide a path to Root. @@ -314,11 +316,8 @@ behavior. ## Discovering status -The standalone registry precompile gives tooling and contracts one -place to inspect both API lifecycle and operational availability. - -Because the result covers both lifecycle and operational availability, it is -called `PrecompileStatus`: +The standalone registry precompile gives tooling and contracts one place to +inspect whether a whole precompile is operationally disabled: ```solidity interface IPrecompileRegistry { @@ -337,22 +336,24 @@ interface IPrecompileRegistry { } ``` -The fields have the following meaning: +In v444, the fields have the following behavior: | Field | Meaning | |---|---| -| `isDeprecated` | The function is soft- or hard-deprecated. | +| `isDeprecated` | Reserved; always `false`. | | `isDisabled` | The containing precompile is currently disabled by Root; Root can re-enable it. | -| `newPrecompile` | Address of the recommended replacement, often the same address. | -| `newSelector` | Selector of the recommended replacement function. | -| `message` | Human-readable status or migration guidance. | +| `newPrecompile` | Reserved; always the zero address. | +| `newSelector` | Reserved; always `0x00000000`. | +| `message` | Reserved; always empty. | -Zero replacement fields mean that no replacement is available. Tooling should -not infer that `isDisabled` implies deprecation, or that re-enabling a -precompile clears `isDeprecated`. +The `selector` parameter is also reserved and is not interpreted in v444. A +response therefore does not prove that a selector exists or describe its +lifecycle. Tooling must use the canonical Solidity interfaces and JSON ABIs to +discover supported selectors. -The registry avoids adding overhead to every deprecated call. Deployment tools, -frontends, and upgradeable contracts can query it when evaluating dependencies. +Function-level deprecation and replacement metadata may populate the reserved +fields in a future runtime. Until then, use NatSpec annotations and release +documentation for migration guidance. Solidity interfaces should also carry NatSpec annotations: @@ -429,7 +430,7 @@ Every precompile change should verify: - new behavior uses a new versioned selector when necessary; - Solidity interfaces, generated ABIs, SDK copies, and runtime implementations agree; -- lifecycle registry metadata and NatSpec annotations agree; +- any implemented lifecycle registry metadata and NatSpec annotations agree; - disable and re-enable behavior is covered for the affected precompile; - state-changing functions dispatch the highest-level extrinsic as the mapped signed caller and do not bypass its authorization checks; @@ -454,5 +455,6 @@ Precompiles are a long-lived contract between Subtensor and deployed EVM code. Keep addresses and released selectors stable, version functions additively, preserve old semantics whenever possible, and replace raw storage access with typed views that insulate callers from storage layouts. Use deprecation to guide -migration and reversible disablement to handle operational risk; report both -through a common status model without treating them as the same condition. +migration and reversible disablement to handle operational risk. The v444 +registry reports whole-precompile disablement; function-level lifecycle status +remains a future extension. diff --git a/docs/guides/evm/precompiles/registry.mdx b/docs/guides/evm/precompiles/registry.mdx index 5a0ca38ef0..68b9fb0513 100644 --- a/docs/guides/evm/precompiles/registry.mdx +++ b/docs/guides/evm/precompiles/registry.mdx @@ -1,6 +1,6 @@ --- title: Precompile registry -description: Registry for precompile lifecycle and availability. +description: Registry for precompile availability. --- | Property | Value | @@ -10,10 +10,9 @@ description: Registry for precompile lifecycle and availability. | Address | `0x0000000000000000000000000000000000000813` | | Status | Deployed | -The registry provides function-level lifecycle metadata and the current -operational availability of the containing precompile. Contracts, deployment -tools, and frontends can inspect whether a selector is deprecated, has a -replacement, or is currently unavailable without attempting the affected call. +In v444, the registry reports the current operational availability of a whole +precompile through `isDisabled`. It does not report whether an individual +selector exists, is deprecated, or has a replacement. ## Interface @@ -34,6 +33,12 @@ interface IPrecompileRegistry { } ``` +The `selector` parameter and the `isDeprecated`, `newPrecompile`, `newSelector`, +and `message` result fields are reserved for future selector-lifecycle support. +In v444 those fields are not populated, and the selector is not interpreted. +Do not use this call to test whether a selector is supported; use the canonical +Solidity interfaces and JSON ABIs for selector discovery. + `AdminUtils.sudo_toggle_evm_precompile` is Root-only and is not exposed by this precompile. The registry reports availability but does not grant callers permission to change it. diff --git a/precompiles/src/solidity/registry.sol b/precompiles/src/solidity/registry.sol index ba67235154..291b054ae6 100644 --- a/precompiles/src/solidity/registry.sol +++ b/precompiles/src/solidity/registry.sol @@ -12,6 +12,9 @@ interface IPrecompileRegistry { string message; } + /// @notice Reports whether the containing precompile is disabled. + /// @dev In v444, `selector` and the selector-lifecycle result fields are + /// reserved for future use and do not establish whether a selector exists. function getPrecompileStatus( address precompile, bytes4 selector diff --git a/precompiles/src/solidity/stakingV2.abi b/precompiles/src/solidity/stakingV2.abi index 1418a5b50c..dd1f1a1f90 100644 --- a/precompiles/src/solidity/stakingV2.abi +++ b/precompiles/src/solidity/stakingV2.abi @@ -205,6 +205,30 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "netuid", + "type": "uint256" + } + ], + "name": "getTotalColdkeyStakeOnSubnet", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -469,7 +493,7 @@ ], "name": "approve", "outputs": [], - "stateMutability": "", + "stateMutability": "nonpayable", "type": "function" }, { @@ -521,7 +545,7 @@ ], "name": "increaseAllowance", "outputs": [], - "stateMutability": "", + "stateMutability": "nonpayable", "type": "function" }, { @@ -544,7 +568,7 @@ ], "name": "decreaseAllowance", "outputs": [], - "stateMutability": "", + "stateMutability": "nonpayable", "type": "function" }, { @@ -582,7 +606,7 @@ ], "name": "transferStakeFrom", "outputs": [], - "stateMutability": "", + "stateMutability": "nonpayable", "type": "function" }, { diff --git a/precompiles/src/solidity/stakingV2.sol b/precompiles/src/solidity/stakingV2.sol index e14f78a9db..b30cbc7946 100644 --- a/precompiles/src/solidity/stakingV2.sol +++ b/precompiles/src/solidity/stakingV2.sol @@ -142,6 +142,18 @@ interface IStaking { bytes32 coldkey ) external view returns (uint256); + /** + * @dev Returns the coldkey's total alpha stake on one subnet. + * + * @param coldkey The coldkey public key (32 bytes). + * @param netuid The subnet containing the stake position (uint256). + * @return The coldkey's total alpha stake on the subnet. + */ + function getTotalColdkeyStakeOnSubnet( + bytes32 coldkey, + uint256 netuid + ) external view returns (uint256); + /** * @dev Returns the total amount of stake under a hotkey (delegative or otherwise) * diff --git a/sdk/python/bittensor/evm/abi/stakingV2.json b/sdk/python/bittensor/evm/abi/stakingV2.json index 1418a5b50c..dd1f1a1f90 100644 --- a/sdk/python/bittensor/evm/abi/stakingV2.json +++ b/sdk/python/bittensor/evm/abi/stakingV2.json @@ -205,6 +205,30 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "coldkey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "netuid", + "type": "uint256" + } + ], + "name": "getTotalColdkeyStakeOnSubnet", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -469,7 +493,7 @@ ], "name": "approve", "outputs": [], - "stateMutability": "", + "stateMutability": "nonpayable", "type": "function" }, { @@ -521,7 +545,7 @@ ], "name": "increaseAllowance", "outputs": [], - "stateMutability": "", + "stateMutability": "nonpayable", "type": "function" }, { @@ -544,7 +568,7 @@ ], "name": "decreaseAllowance", "outputs": [], - "stateMutability": "", + "stateMutability": "nonpayable", "type": "function" }, { @@ -582,7 +606,7 @@ ], "name": "transferStakeFrom", "outputs": [], - "stateMutability": "", + "stateMutability": "nonpayable", "type": "function" }, { diff --git a/sdk/python/tests/unit/test_evm.py b/sdk/python/tests/unit/test_evm.py index b3a85d0145..53685191e6 100644 --- a/sdk/python/tests/unit/test_evm.py +++ b/sdk/python/tests/unit/test_evm.py @@ -86,6 +86,21 @@ def test_balance_transfer_encode(self): data = precompiles.encode_call(fn_abi, [addresses.ss58_to_pubkey(ALICE)]) assert data.startswith("0x") + def test_total_coldkey_stake_on_subnet_encode(self): + fn_abi = precompiles.get_precompile("staking-v2").function( + "getTotalColdkeyStakeOnSubnet" + ) + data = precompiles.encode_call(fn_abi, [BOB_HOT, 1]) + assert data.startswith("0x") + + @pytest.mark.parametrize( + "function_name", + ["approve", "increaseAllowance", "decreaseAllowance", "transferStakeFrom"], + ) + def test_staking_v2_state_changers_are_nonpayable(self, function_name: str): + fn_abi = precompiles.get_precompile("staking-v2").function(function_name) + assert fn_abi["stateMutability"] == "nonpayable" + def test_new_bounded_array_calls_encode(self): claim_root = precompiles.get_precompile("staking-v2").function("claimRoot") assert precompiles.encode_call(claim_root, ["[1, 2]"]).startswith("0x") diff --git a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx index b11bdd7113..1de98b6251 100644 --- a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx +++ b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx @@ -160,7 +160,7 @@ v444: s_i = normalize(price_ema_i) 0x…0813 Precompile registry - Whether a selector is deprecated, disabled, or replaced + Whether a precompile is currently disabled @@ -179,8 +179,8 @@ v444: s_i = normalize(price_ema_i) Every state-changing method dispatches the highest-level runtime call as the mapped EVM signer. The pallet still enforces ownership, role, rate limits, freeze windows, and every other authorization rule. Released addresses and selectors remain stable; the new - registry gives contracts a typed way to discover lifecycle and operational status before - calling. + registry gives contracts a typed way to discover whether a whole precompile is currently + disabled. Supported selectors remain defined by the published interfaces and ABIs.

+

+ In v444, only the registry's isDisabled field is populated. Its + selector parameter and selector-lifecycle fields are reserved for a future extension and + must not be used to infer whether a selector exists. +

Canonical Solidity interfaces, JSON ABIs, generated Python ABI copies, documentation, gas accounting, and tests ship together. Integrators should use the v444 copies rather @@ -362,7 +367,7 @@ partial fills , signer `}

  • EVM integrators: refresh the complete canonical ABI set before using v444 selectors. Add 0x…080f through 0x…0813 only from the - published interfaces, and use the registry to inspect selector status. + published interfaces, and use the registry to inspect whole-precompile availability.
  • SDK and CLI users: install the matching bittensor 11.1.0 From a3aa5ba5742c06bbfd88976c1a955e1a307b16ad Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Mon, 10 Aug 2026 21:53:21 +0200 Subject: [PATCH 56/58] docs: prepare v444 release guidance --- docs/concepts/emissions.mdx | 52 +- docs/migration.mdx | 14 +- sdk/python/tests/unit/test_evm.py | 4 +- .../public/catalog/emission-snapshot.json | 924 +++++++++++++++--- .../scripts/fetch-emission-snapshot.py | 255 +++-- .../releases/v436-upgrade/page.module.css | 4 +- .../releases/v444-upgrade/page.tsx | 103 +- .../docs/emission-network-snapshot.tsx | 49 +- .../docs/subnet-emission-share-chart.tsx | 132 +-- .../src/lib/emission-math.ts | 88 +- .../src/lib/emission-snapshot.ts | 22 +- 11 files changed, 1303 insertions(+), 344 deletions(-) diff --git a/docs/concepts/emissions.mdx b/docs/concepts/emissions.mdx index 85a8bfd639..3eef1b5fc4 100644 --- a/docs/concepts/emissions.mdx +++ b/docs/concepts/emissions.mdx @@ -71,24 +71,39 @@ protocol-owned alpha. ## Subnet emission shares -Each block's TAO emission is divided across subnets in proportion to their -**EMA price**, weighted by a miner-burn penalty -([`get_shares`](/code/pallets/subtensor/src/coinbase/subnet_emissions.rs#L354-L389); -this price-based formula shipped in June 2026): +V444 divides each block's TAO emission in two clear steps. First, it turns +each eligible subnet's **EMA price** into a share of total demand: ``` -share_i = p_i × (1 − b_i) / Σ_j p_j × (1 − b_j) +demand_share_i = price_ema_i / Σ price_ema ``` -where `p_i` is the subnet's moving price (`SubnetMovingPrice`) and `b_i` is -the proportion of the last tempo's miner incentive that was withheld because -it was directed to subnet-owner hotkeys (counted whether the withheld alpha -was recycled or burned). If the combined weight is zero across all subnets, -the chain falls back to unweighted price shares so emission is never -stranded. Emission-disabled subnets get zero share, redistributed -proportionally to enabled ones — and with `tao_in` zeroed, `alpha_in` -(`tao_in / price`) is zero too, so pool injection stops entirely while -`alpha_out` keeps accruing for participants. +`MinerBurned` does not change this cross-subnet share in v444. It still records +what happened to miner incentive inside the subnet, but one subnet's local burn +or recycle choice no longer changes another subnet's emission. + +Second, the **emission gate** reduces weak demand before the final shares are +normalized. The gate has a midpoint called `theta`. By default, `theta` is the +32nd-highest positive demand share. It is normally recalculated every 360 +blocks and stays fixed between updates. A subnet at the midpoint passes half +of its demand weight. Subnets well above it pass almost all; subnets well below +it pass much less: + +``` +gate_i = 1 / (1 + (theta / demand_share_i)^h) +final_share_i = demand_share_i × gate_i / Σ(demand_share × gate) +``` + +The default exponent `h` is 3. This makes the gate gradual rather than a hard +cutoff. A very small share can still round down to zero. If every gated value +rounds to zero, the runtime restores the ungated price shares so emission is +not stranded. See +[`get_shares`](/code/pallets/subtensor/src/coinbase/subnet_emissions.rs#L354-L476). + +An emission-disabled subnet receives no TAO-side share; its share is +redistributed among enabled subnets. That also stops its `tao_in` and +`alpha_in` pool injection, while its participant-side `alpha_out` continues +to accrue. The EMA uses an age-dependent smoothing factor: @@ -99,8 +114,7 @@ ema_alpha = base_alpha × blocks_since_start / (blocks_since_start + halving_blo with `halving_blocks` defaulting to 201,600 (~4 weeks). New subnets start near zero — their moving price adapts extremely slowly, which blunts launch pumps, coordinated buys, and flash attacks on emission shares. The spot -price feeding the EMA is capped at 1.0. There is no zero-emission floor: a -subnet with a low EMA price still receives a small non-zero share. +price feeding the EMA is capped at 1.0. @@ -127,10 +141,10 @@ Per-block `alpha_out` is divided as it accrues - **41%** to miners — 50% of the remainder. - **41%** to validators and their stakers — the other 50%. -A [`root_proportion`](/code/pallets/subtensor/src/coinbase/block_step.rs#L69-L79) share of the validator half (same formula as the +A [`root_proportion`](/code/pallets/subtensor/src/coinbase/block_step.rs#L74-L84) share of the validator half (same formula as the injection cap) is reserved for **root TAO stakers** and accumulated as -claimable root dividends — but only in blocks where the sum of all subnets' -EMA prices exceeds 1.0; otherwise that alpha is recycled. +claimable root dividends — but only in blocks where the sum of eligible +non-root subnets' EMA prices exceeds 1.0; otherwise that alpha is recycled. If an epoch ends with zero total miner incentive, the miner half of that tempo's pending alpha is paid to validators instead of being withheld. diff --git a/docs/migration.mdx b/docs/migration.mdx index ca38712480..7600537c53 100644 --- a/docs/migration.mdx +++ b/docs/migration.mdx @@ -512,8 +512,8 @@ if not result.success: The v11 package ships against a runtime that also changed behavior. These are not rename mappings — scripts that still "work" can fail or mis-account after -the upgrade. Full narrative: -[The V431 Upgrade](/releases/v431-upgrade). +the upgrade. See the release notes for +[V431](/releases/v431-upgrade) and [V444](/releases/v444-upgrade). ### Ownership and emissions @@ -521,10 +521,12 @@ the upgrade. Full narrative: to the highest-conviction hotkey when total conviction reaches 10% of `SubnetAlphaOut`. Existing conviction counts toward this threshold. See [Conviction](/docs/guides/conviction). -- **Cross-subnet emissions.** Allocation uses EMA price adjusted by miner burn; - [`root_proportion`](/code/pallets/subtensor/src/coinbase/block_step.rs#L69-L79) is no longer included in the inter-subnet split (it still - applies inside each subnet for injection caps and root dividends). Update - emission calculations and forecasts. See [Emissions](/docs/concepts/emissions). +- **Cross-subnet emissions.** V444 allocation uses each subnet's EMA price, + followed by the emission gate. `MinerBurned` no longer changes a subnet's + cross-network share. [`root_proportion`](/code/pallets/subtensor/src/coinbase/block_step.rs#L74-L84) + is also not part of the inter-subnet split; it still applies inside each + subnet for injection caps and root dividends. Update emission calculations + and forecasts. See [Emissions](/docs/concepts/emissions). ### Proxies and coldkeys diff --git a/sdk/python/tests/unit/test_evm.py b/sdk/python/tests/unit/test_evm.py index 53685191e6..503a7ef44e 100644 --- a/sdk/python/tests/unit/test_evm.py +++ b/sdk/python/tests/unit/test_evm.py @@ -87,9 +87,7 @@ def test_balance_transfer_encode(self): assert data.startswith("0x") def test_total_coldkey_stake_on_subnet_encode(self): - fn_abi = precompiles.get_precompile("staking-v2").function( - "getTotalColdkeyStakeOnSubnet" - ) + fn_abi = precompiles.get_precompile("staking-v2").function("getTotalColdkeyStakeOnSubnet") data = precompiles.encode_call(fn_abi, [BOB_HOT, 1]) assert data.startswith("0x") diff --git a/website/apps/bittensor-website/public/catalog/emission-snapshot.json b/website/apps/bittensor-website/public/catalog/emission-snapshot.json index 4f1d64016e..680c5a28cd 100644 --- a/website/apps/bittensor-website/public/catalog/emission-snapshot.json +++ b/website/apps/bittensor-website/public/catalog/emission-snapshot.json @@ -1,176 +1,844 @@ { - "fetchedAt": "2026-07-08T14:39:25.714962Z", + "fetchedAt": "2026-08-10T19:50:58.619291Z", "network": "finney", - "emissionMode": "price_ema", + "chainSpecVersion": 443, + "emissionMode": "v444_price_ema_hill_gate", + "emissionGateSource": "v444_defaults_recomputed", "dataSource": { "subnets": "taomarketcap.com", "chain": "finney", "tmcEndpoint": "https://api.taomarketcap.com/public/v1/subnets/" }, - "blockEmissionTao": 1.0, - "blockEmissionCalculatedTao": 0.5, - "totalIssuanceTao": 11100766.878, - "totalIssuanceRao": 11100766877818994, - "rootTao": 5374581.7, - "emaPriceSum": 1.4037, + "blockEmissionTao": 0.5, + "totalIssuanceTao": 11219409.114, + "totalIssuanceRao": 11219409114200811, + "rootTao": 5413546.52, + "emaPriceSum": 1.3084, "rootDividendGateOpen": true, "taoWeight": 0.18, - "featuredSubnet": { - "netuid": 4, - "name": "Targon", - "spotPrice": 0.054146, - "emaPrice": 0.05436, - "minerBurned": 0.5057, - "taoIn": 131662.34, - "alphaIn": 2431632.87, - "alphaOut": 3201815.16, - "taoShare": 0.067811, - "taoPerBlock": 0.067811 - }, - "topSubnets": [ + "emissionGateRank": 32, + "emissionGateQuantile": 0.61, + "emissionGateExponent": 3.0, + "emissionGateBar": 0.00733118, + "emissionInputs": [ { - "netuid": 64, - "name": "Chutes", - "spotPrice": 0.072102, - "emaPrice": 0.072286, - "minerBurned": 0.0, - "taoIn": 198988.71, - "alphaIn": 2759827.89, - "alphaOut": 2856519.66, - "taoShare": 0.182424, - "taoPerBlock": 0.182424 + "netuid": 1, + "emaPrice": 0.008054, + "emissionEnabled": true }, { - "netuid": 120, - "name": "Affine", - "spotPrice": 0.056117, - "emaPrice": 0.055983, - "minerBurned": 0.0, - "taoIn": 78441.44, - "alphaIn": 1397809.15, - "alphaOut": 2270005.06, - "taoShare": 0.141281, - "taoPerBlock": 0.141281 + "netuid": 2, + "emaPrice": 0.004216, + "emissionEnabled": true + }, + { + "netuid": 3, + "emaPrice": 0.02563, + "emissionEnabled": true }, { "netuid": 4, - "name": "Targon", - "spotPrice": 0.054146, - "emaPrice": 0.05436, - "minerBurned": 0.5057, - "taoIn": 131662.34, - "alphaIn": 2431632.87, - "alphaOut": 3201815.16, - "taoShare": 0.067811, - "taoPerBlock": 0.067811 + "emaPrice": 0.057038, + "emissionEnabled": true + }, + { + "netuid": 5, + "emaPrice": 0.013702, + "emissionEnabled": true + }, + { + "netuid": 6, + "emaPrice": 0.002964, + "emissionEnabled": true + }, + { + "netuid": 7, + "emaPrice": 0.003321, + "emissionEnabled": true + }, + { + "netuid": 8, + "emaPrice": 0.029832, + "emissionEnabled": true + }, + { + "netuid": 9, + "emaPrice": 0.033401, + "emissionEnabled": true + }, + { + "netuid": 10, + "emaPrice": 0.006398, + "emissionEnabled": false + }, + { + "netuid": 11, + "emaPrice": 0.007657, + "emissionEnabled": true + }, + { + "netuid": 12, + "emaPrice": 0.004999, + "emissionEnabled": false + }, + { + "netuid": 13, + "emaPrice": 0.006294, + "emissionEnabled": true + }, + { + "netuid": 14, + "emaPrice": 0.010195, + "emissionEnabled": false + }, + { + "netuid": 15, + "emaPrice": 0.021038, + "emissionEnabled": true + }, + { + "netuid": 16, + "emaPrice": 0.003094, + "emissionEnabled": false + }, + { + "netuid": 17, + "emaPrice": 0.009592, + "emissionEnabled": true + }, + { + "netuid": 18, + "emaPrice": 0.00515, + "emissionEnabled": true + }, + { + "netuid": 19, + "emaPrice": 0.010228, + "emissionEnabled": true + }, + { + "netuid": 20, + "emaPrice": 0.002892, + "emissionEnabled": false + }, + { + "netuid": 21, + "emaPrice": 0.003186, + "emissionEnabled": true + }, + { + "netuid": 22, + "emaPrice": 0.003353, + "emissionEnabled": true + }, + { + "netuid": 23, + "emaPrice": 0.004562, + "emissionEnabled": true + }, + { + "netuid": 24, + "emaPrice": 0.004405, + "emissionEnabled": true + }, + { + "netuid": 25, + "emaPrice": 0.010332, + "emissionEnabled": false + }, + { + "netuid": 26, + "emaPrice": 0.004317, + "emissionEnabled": false + }, + { + "netuid": 27, + "emaPrice": 0.002477, + "emissionEnabled": false + }, + { + "netuid": 28, + "emaPrice": 0.016706, + "emissionEnabled": true + }, + { + "netuid": 29, + "emaPrice": 0.003131, + "emissionEnabled": false + }, + { + "netuid": 30, + "emaPrice": 0.004021, + "emissionEnabled": false + }, + { + "netuid": 31, + "emaPrice": 0.005064, + "emissionEnabled": false + }, + { + "netuid": 32, + "emaPrice": 0.003187, + "emissionEnabled": true + }, + { + "netuid": 33, + "emaPrice": 0.005635, + "emissionEnabled": true + }, + { + "netuid": 34, + "emaPrice": 0.012238, + "emissionEnabled": true + }, + { + "netuid": 35, + "emaPrice": 0.002785, + "emissionEnabled": true + }, + { + "netuid": 36, + "emaPrice": 0.00167, + "emissionEnabled": true + }, + { + "netuid": 37, + "emaPrice": 0.003596, + "emissionEnabled": false + }, + { + "netuid": 38, + "emaPrice": 0.011619, + "emissionEnabled": true + }, + { + "netuid": 39, + "emaPrice": 0.006459, + "emissionEnabled": true + }, + { + "netuid": 40, + "emaPrice": 0.006692, + "emissionEnabled": true + }, + { + "netuid": 41, + "emaPrice": 0.005026, + "emissionEnabled": true + }, + { + "netuid": 42, + "emaPrice": 0.002774, + "emissionEnabled": false + }, + { + "netuid": 43, + "emaPrice": 0.005369, + "emissionEnabled": false + }, + { + "netuid": 44, + "emaPrice": 0.042633, + "emissionEnabled": true + }, + { + "netuid": 45, + "emaPrice": 0.002634, + "emissionEnabled": false + }, + { + "netuid": 46, + "emaPrice": 0.004547, + "emissionEnabled": true + }, + { + "netuid": 47, + "emaPrice": 0.002858, + "emissionEnabled": false + }, + { + "netuid": 48, + "emaPrice": 0.004478, + "emissionEnabled": true + }, + { + "netuid": 49, + "emaPrice": 0.007034, + "emissionEnabled": true + }, + { + "netuid": 50, + "emaPrice": 0.004823, + "emissionEnabled": true }, { "netuid": 51, - "name": "lium.io", - "spotPrice": 0.052853, - "emaPrice": 0.052677, - "minerBurned": 0.2646, - "taoIn": 117433.52, - "alphaIn": 2221903.93, - "alphaOut": 3088579.47, - "taoShare": 0.097762, - "taoPerBlock": 0.097762 + "emaPrice": 0.073255, + "emissionEnabled": true + }, + { + "netuid": 52, + "emaPrice": 0.00678, + "emissionEnabled": false + }, + { + "netuid": 53, + "emaPrice": 0.03318, + "emissionEnabled": true + }, + { + "netuid": 54, + "emaPrice": 0.004743, + "emissionEnabled": true + }, + { + "netuid": 55, + "emaPrice": 0.002857, + "emissionEnabled": true + }, + { + "netuid": 56, + "emaPrice": 0.016981, + "emissionEnabled": true + }, + { + "netuid": 57, + "emaPrice": 0.005359, + "emissionEnabled": false + }, + { + "netuid": 58, + "emaPrice": 0.008788, + "emissionEnabled": false + }, + { + "netuid": 59, + "emaPrice": 0.002019, + "emissionEnabled": true + }, + { + "netuid": 60, + "emaPrice": 0.004075, + "emissionEnabled": true + }, + { + "netuid": 61, + "emaPrice": 0.008461, + "emissionEnabled": true + }, + { + "netuid": 62, + "emaPrice": 0.012264, + "emissionEnabled": true + }, + { + "netuid": 63, + "emaPrice": 0.008203, + "emissionEnabled": true + }, + { + "netuid": 64, + "emaPrice": 0.086481, + "emissionEnabled": true + }, + { + "netuid": 65, + "emaPrice": 0.002534, + "emissionEnabled": true + }, + { + "netuid": 66, + "emaPrice": 0.003033, + "emissionEnabled": true + }, + { + "netuid": 67, + "emaPrice": 0.006518, + "emissionEnabled": true + }, + { + "netuid": 68, + "emaPrice": 0.024419, + "emissionEnabled": true + }, + { + "netuid": 69, + "emaPrice": 0.009912, + "emissionEnabled": false + }, + { + "netuid": 70, + "emaPrice": 0.001371, + "emissionEnabled": false + }, + { + "netuid": 71, + "emaPrice": 0.003849, + "emissionEnabled": true + }, + { + "netuid": 72, + "emaPrice": 0.002701, + "emissionEnabled": false + }, + { + "netuid": 73, + "emaPrice": 0.003274, + "emissionEnabled": false + }, + { + "netuid": 74, + "emaPrice": 0.003809, + "emissionEnabled": true + }, + { + "netuid": 75, + "emaPrice": 0.019342, + "emissionEnabled": true + }, + { + "netuid": 76, + "emaPrice": 0.002632, + "emissionEnabled": true + }, + { + "netuid": 77, + "emaPrice": 0.006135, + "emissionEnabled": false + }, + { + "netuid": 78, + "emaPrice": 0.002605, + "emissionEnabled": true + }, + { + "netuid": 79, + "emaPrice": 0.007527, + "emissionEnabled": true + }, + { + "netuid": 80, + "emaPrice": 0.014918, + "emissionEnabled": true + }, + { + "netuid": 81, + "emaPrice": 0.007893, + "emissionEnabled": true + }, + { + "netuid": 82, + "emaPrice": 0.004499, + "emissionEnabled": true + }, + { + "netuid": 83, + "emaPrice": 0.010613, + "emissionEnabled": false + }, + { + "netuid": 84, + "emaPrice": 0.002521, + "emissionEnabled": false + }, + { + "netuid": 85, + "emaPrice": 0.005342, + "emissionEnabled": true + }, + { + "netuid": 87, + "emaPrice": 0.003704, + "emissionEnabled": false + }, + { + "netuid": 88, + "emaPrice": 0.004539, + "emissionEnabled": true + }, + { + "netuid": 89, + "emaPrice": 0.003664, + "emissionEnabled": true + }, + { + "netuid": 90, + "emaPrice": 0.025303, + "emissionEnabled": false + }, + { + "netuid": 91, + "emaPrice": 0.009309, + "emissionEnabled": true + }, + { + "netuid": 92, + "emaPrice": 0.003914, + "emissionEnabled": false + }, + { + "netuid": 93, + "emaPrice": 0.00976, + "emissionEnabled": true + }, + { + "netuid": 94, + "emaPrice": 0.00375, + "emissionEnabled": true + }, + { + "netuid": 95, + "emaPrice": 0.057053, + "emissionEnabled": false + }, + { + "netuid": 96, + "emaPrice": 0.008541, + "emissionEnabled": true + }, + { + "netuid": 97, + "emaPrice": 0.025306, + "emissionEnabled": true + }, + { + "netuid": 98, + "emaPrice": 0.002965, + "emissionEnabled": true + }, + { + "netuid": 99, + "emaPrice": 0.004781, + "emissionEnabled": true + }, + { + "netuid": 100, + "emaPrice": 0.005732, + "emissionEnabled": true + }, + { + "netuid": 101, + "emaPrice": 0.004636, + "emissionEnabled": true + }, + { + "netuid": 102, + "emaPrice": 0.008691, + "emissionEnabled": true + }, + { + "netuid": 103, + "emaPrice": 0.009532, + "emissionEnabled": false + }, + { + "netuid": 104, + "emaPrice": 0.004384, + "emissionEnabled": false + }, + { + "netuid": 105, + "emaPrice": 0.007274, + "emissionEnabled": true + }, + { + "netuid": 106, + "emaPrice": 0.003108, + "emissionEnabled": true + }, + { + "netuid": 107, + "emaPrice": 0.06158, + "emissionEnabled": true + }, + { + "netuid": 108, + "emaPrice": 0.004023, + "emissionEnabled": false + }, + { + "netuid": 109, + "emaPrice": 0.003304, + "emissionEnabled": false + }, + { + "netuid": 110, + "emaPrice": 0.00737, + "emissionEnabled": true + }, + { + "netuid": 111, + "emaPrice": 0.004958, + "emissionEnabled": false + }, + { + "netuid": 112, + "emaPrice": 0.002535, + "emissionEnabled": true + }, + { + "netuid": 113, + "emaPrice": 0.00273, + "emissionEnabled": false + }, + { + "netuid": 114, + "emaPrice": 0.011642, + "emissionEnabled": true + }, + { + "netuid": 115, + "emaPrice": 0.003533, + "emissionEnabled": false }, { "netuid": 116, - "name": "Memo", - "spotPrice": 0.050456, - "emaPrice": 0.054405, - "minerBurned": 0.0, - "taoIn": 4169.0, - "alphaIn": 82626.23, - "alphaOut": 397234.66, - "taoShare": 0.137298, - "taoPerBlock": 0.137298 + "emaPrice": 0.007126, + "emissionEnabled": false + }, + { + "netuid": 117, + "emaPrice": 0.002574, + "emissionEnabled": true + }, + { + "netuid": 118, + "emaPrice": 0.009272, + "emissionEnabled": true + }, + { + "netuid": 119, + "emaPrice": 0.003091, + "emissionEnabled": false + }, + { + "netuid": 120, + "emaPrice": 0.059987, + "emissionEnabled": true + }, + { + "netuid": 121, + "emaPrice": 0.004739, + "emissionEnabled": true + }, + { + "netuid": 122, + "emaPrice": 0.004685, + "emissionEnabled": false + }, + { + "netuid": 123, + "emaPrice": 0.002703, + "emissionEnabled": true + }, + { + "netuid": 124, + "emaPrice": 0.010121, + "emissionEnabled": true + }, + { + "netuid": 125, + "emaPrice": 0.00328, + "emissionEnabled": false + }, + { + "netuid": 126, + "emaPrice": 0.005165, + "emissionEnabled": true + }, + { + "netuid": 127, + "emaPrice": 0.002883, + "emissionEnabled": true + }, + { + "netuid": 128, + "emaPrice": 0.002938, + "emissionEnabled": false + } + ], + "featuredSubnet": { + "netuid": 4, + "name": "Targon", + "spotPrice": 0.056784, + "emaPrice": 0.057038, + "emissionEnabled": true, + "taoIn": 136777.6, + "alphaIn": 2408742.63, + "alphaOut": 3498348.62, + "demandShare": 0.04359424, + "gateFactor": 0.99526659, + "taoShare": 0.07641434, + "taoPerBlock": 0.03820717 + }, + "topSubnets": [ + { + "netuid": 64, + "name": "Chutes", + "spotPrice": 0.085869, + "emaPrice": 0.086481, + "emissionEnabled": true, + "taoIn": 220039.08, + "alphaIn": 2562495.19, + "alphaOut": 3327621.07, + "demandShare": 0.06609757, + "gateFactor": 0.99863738, + "taoShare": 0.11625179, + "taoPerBlock": 0.0581259 + }, + { + "netuid": 51, + "name": "lium.io", + "spotPrice": 0.073558, + "emaPrice": 0.073255, + "emissionEnabled": true, + "taoIn": 140987.41, + "alphaIn": 1916689.46, + "alphaOut": 3668935.54, + "demandShare": 0.05598891, + "gateFactor": 0.99776003, + "taoShare": 0.09838627, + "taoPerBlock": 0.04919314 }, { "netuid": 107, "name": "Minos", - "spotPrice": 0.049685, - "emaPrice": 0.050977, - "minerBurned": 0.0, - "taoIn": 12570.91, - "alphaIn": 253009.78, - "alphaOut": 1138810.42, - "taoShare": 0.128647, - "taoPerBlock": 0.128647 + "spotPrice": 0.061349, + "emaPrice": 0.06158, + "emissionEnabled": true, + "taoIn": 19184.4, + "alphaIn": 312709.51, + "alphaOut": 1406061.78, + "demandShare": 0.04706569, + "gateFactor": 0.99623495, + "taoShare": 0.08257957, + "taoPerBlock": 0.04128978 }, { - "netuid": 95, - "name": "Actual", - "spotPrice": 0.047114, - "emaPrice": 0.047571, - "minerBurned": 1.0, - "taoIn": 28836.85, - "alphaIn": 612063.81, - "alphaOut": 2506271.86, - "taoShare": 0.0, - "taoPerBlock": 0.0 + "netuid": 120, + "name": "Affine", + "spotPrice": 0.060743, + "emaPrice": 0.059987, + "emissionEnabled": true, + "taoIn": 84377.64, + "alphaIn": 1389096.16, + "alphaOut": 2556991.84, + "demandShare": 0.04584816, + "gateFactor": 0.99592822, + "taoShare": 0.08041856, + "taoPerBlock": 0.04020928 + }, + { + "netuid": 4, + "name": "Targon", + "spotPrice": 0.056784, + "emaPrice": 0.057038, + "emissionEnabled": true, + "taoIn": 136777.6, + "alphaIn": 2408742.63, + "alphaOut": 3498348.62, + "demandShare": 0.04359424, + "gateFactor": 0.99526659, + "taoShare": 0.07641434, + "taoPerBlock": 0.03820717 }, { "netuid": 44, "name": "Score", - "spotPrice": 0.038289, - "emaPrice": 0.038547, - "minerBurned": 0.2424, - "taoIn": 64995.55, - "alphaIn": 1697501.73, - "alphaOut": 3677515.8, - "taoShare": 0.073698, - "taoPerBlock": 0.073698 + "spotPrice": 0.042135, + "emaPrice": 0.042633, + "emissionEnabled": true, + "taoIn": 69596.55, + "alphaIn": 1651741.69, + "alphaOut": 3998290.27, + "demandShare": 0.03258447, + "gateFactor": 0.98873914, + "taoShare": 0.05674123, + "taoPerBlock": 0.02837062 }, { "netuid": 9, "name": "iota", - "spotPrice": 0.033581, - "emaPrice": 0.033636, - "minerBurned": 0.88, - "taoIn": 60387.91, - "alphaIn": 1798289.0, - "alphaOut": 3715764.4, - "taoShare": 0.010186, - "taoPerBlock": 0.010186 + "spotPrice": 0.03345, + "emaPrice": 0.033401, + "emissionEnabled": true, + "taoIn": 60926.17, + "alphaIn": 1821422.27, + "alphaOut": 3951121.46, + "demandShare": 0.02552844, + "gateFactor": 0.97686426, + "taoShare": 0.04392025, + "taoPerBlock": 0.02196013 }, { - "netuid": 15, - "name": "ORO", - "spotPrice": 0.032336, - "emaPrice": 0.032448, - "minerBurned": 0.0, - "taoIn": 10285.4, - "alphaIn": 318079.98, - "alphaOut": 1126057.23, - "taoShare": 0.081887, - "taoPerBlock": 0.081887 + "netuid": 53, + "name": "engy", + "spotPrice": 0.032, + "emaPrice": 0.03318, + "emissionEnabled": true, + "taoIn": 35107.27, + "alphaIn": 1097096.66, + "alphaOut": 4580364.57, + "demandShare": 0.02535953, + "gateFactor": 0.97640986, + "taoShare": 0.04360936, + "taoPerBlock": 0.02180468 }, { "netuid": 8, "name": "Vanta", - "spotPrice": 0.030126, - "emaPrice": 0.030149, - "minerBurned": 0.9657, - "taoIn": 80876.76, - "alphaIn": 2684601.87, - "alphaOut": 2792927.62, - "taoShare": 0.00261, - "taoPerBlock": 0.00261 + "spotPrice": 0.029842, + "emaPrice": 0.029832, + "emissionEnabled": true, + "taoIn": 81218.94, + "alphaIn": 2721615.73, + "alphaOut": 3019607.15, + "demandShare": 0.02280065, + "gateFactor": 0.96782796, + "taoShare": 0.03886437, + "taoPerBlock": 0.01943219 + }, + { + "netuid": 3, + "name": "deprecated", + "spotPrice": 0.025426, + "emaPrice": 0.02563, + "emissionEnabled": true, + "taoIn": 74149.25, + "alphaIn": 2916243.4, + "alphaOut": 2819141.61, + "demandShare": 0.01958905, + "gateFactor": 0.95019266, + "taoShare": 0.0327817, + "taoPerBlock": 0.01639085 }, { "netuid": 97, "name": "Albedo", - "spotPrice": 0.027816, - "emaPrice": 0.030272, - "minerBurned": 0.0, - "taoIn": 8712.92, - "alphaIn": 313234.21, - "alphaOut": 731120.65, - "taoShare": 0.076396, - "taoPerBlock": 0.076396 + "spotPrice": 0.024872, + "emaPrice": 0.025306, + "emissionEnabled": true, + "taoIn": 11057.13, + "alphaIn": 444567.2, + "alphaOut": 932144.63, + "demandShare": 0.01934142, + "gateFactor": 0.94835504, + "taoShare": 0.03230469, + "taoPerBlock": 0.01615235 + }, + { + "netuid": 68, + "name": "NOVA", + "spotPrice": 0.02442, + "emaPrice": 0.024419, + "emissionEnabled": true, + "taoIn": 46153.92, + "alphaIn": 1890019.99, + "alphaOut": 3609349.49, + "demandShare": 0.01866348, + "gateFactor": 0.94285369, + "taoShare": 0.03099155, + "taoPerBlock": 0.01549578 } ] } diff --git a/website/apps/bittensor-website/scripts/fetch-emission-snapshot.py b/website/apps/bittensor-website/scripts/fetch-emission-snapshot.py index 9ddf3271fe..502703e4ca 100644 --- a/website/apps/bittensor-website/scripts/fetch-emission-snapshot.py +++ b/website/apps/bittensor-website/scripts/fetch-emission-snapshot.py @@ -1,8 +1,12 @@ -"""Refresh public/catalog/emission-snapshot.json from TaoMarketCap + finney. +"""Refresh public/catalog/emission-snapshot.json from TaoMarketCap + Finney. -Subnet prices, EMA sums, and the root dividend gate use TMC's public API -(`subnet_moving_price` summed across all subnets). Miner-burn penalties, -total issuance, block emission, and root pool TAO come from finney storage. +Subnet prices and EMA sums use TMC's public API. Eligibility, emission-enabled +flags, total issuance, and root pool TAO come from Finney storage. The output +models the v444 pure-price EMA allocation and Hill gate. On spec 444 or later, +the gate settings and cadence-held midpoint come from chain storage. Before the +upgrade, the output previews the first v444 calculation with the upgrade +defaults. It does not use the deprecated ``BlockEmission`` or ``MinerBurned`` +storage items. Usage (from bittensor-website/, with the bittensor SDK venv active): @@ -24,25 +28,23 @@ import bittensor as bt from bittensor._generated import storage as st -I96 = 2**32 RAO = 1_000_000_000 TMC_SUBNETS_URL = "https://api.taomarketcap.com/public/v1/subnets/" TOP_N = 12 +DEFAULT_EMISSION_BAR_RANK = 32 +DEFAULT_EMISSION_BAR_QUANTILE = 0.61 +DEFAULT_EMISSION_GATE_EXPONENT = 3.0 WEBSITE_DIR = Path(__file__).resolve().parent.parent OUTPUT = WEBSITE_DIR / "public" / "catalog" / "emission-snapshot.json" -def fixed_to_float(val) -> float: - if val is None: - return 0.0 - if isinstance(val, (int, float)): - return float(val) - if isinstance(val, dict) and "bits" in val: - return int(val["bits"]) / I96 - bits = getattr(val, "bits", None) - if bits is not None: - return int(bits) / I96 - return float(val) +def fixed_u64f64_num(value) -> float: + """Convert the SDK's U64F64/FixedU128 representation to a float.""" + if isinstance(value, dict) and "bits" in value: + return int(value["bits"]) / 2**64 + if isinstance(value, int): + return value / 2**64 + return float(value) def tmc_num(val) -> float: @@ -56,7 +58,7 @@ def tmc_num(val) -> float: except ValueError: return 0.0 if isinstance(val, dict) and "bits" in val: - return int(val["bits"]) / I96 + return int(val["bits"]) / 2**32 return 0.0 @@ -69,15 +71,20 @@ def fetch_tmc_subnets(retries: int = 5) -> list[dict]: try: req = urllib.request.Request( url, - headers={"User-Agent": "bittensor-website/1.0", "Accept": "application/json"}, + headers={ + "User-Agent": "bittensor-website/1.0", + "Accept": "application/json", + }, ) with urllib.request.urlopen(req, timeout=90) as response: page = json.loads(response.read()) break except (urllib.error.HTTPError, TimeoutError, urllib.error.URLError) as exc: if attempt + 1 == retries: - raise RuntimeError(f"TMC fetch failed at offset {offset}: {exc}") from exc - time.sleep(2 ** attempt) + raise RuntimeError( + f"TMC fetch failed at offset {offset}: {exc}" + ) from exc + time.sleep(2**attempt) rows.extend(page["results"]) if not page.get("next"): break @@ -92,7 +99,7 @@ def subnet_name(row: dict) -> str: return identities.get("subnetName") or f"SN{row['netuid']}" -def row_from_tmc(row: dict, miner_burned: float) -> dict: +def row_from_tmc(row: dict, emission_enabled: bool) -> dict: snap = row.get("latest_snapshot") or {} netuid = int(row["netuid"]) spot = tmc_num(snap.get("price")) @@ -105,7 +112,7 @@ def row_from_tmc(row: dict, miner_burned: float) -> dict: "name": subnet_name(row), "spotPrice": round(spot, 6), "emaPrice": round(ema, 6), - "minerBurned": round(min(max(miner_burned, 0.0), 1.0), 4), + "emissionEnabled": emission_enabled, "taoIn": round(tao_in, 2), "alphaIn": round(alpha_in, 2), "alphaOut": round(alpha_out, 2), @@ -128,88 +135,219 @@ def block_emission_calculated(issuance_tao: float) -> float: async def chain_fields(client: bt.Client, netuids: list[int]) -> dict: view = await client.at() + spec_version = await client.spec_version() total_issuance = int(await view.query(st.SubtensorModule.TotalIssuance)) - block_emission = int(await view.query(st.SubtensorModule.BlockEmission)) root_tao = int(await view.query(st.SubtensorModule.SubnetTAO, [0])) tao_weight_raw = int(await view.query(st.SubtensorModule.TaoWeight)) - miner_burned: dict[int, float] = {} - for netuid in netuids: - burned = await view.query(st.SubtensorModule.MinerBurned, [netuid]) - miner_burned[netuid] = fixed_to_float(burned) + async def subnet_flags(netuid: int) -> tuple[int, dict[str, bool]]: + ( + first_emission, + subtoken_enabled, + registration_allowed, + emission_enabled, + ) = await asyncio.gather( + view.query(st.SubtensorModule.FirstEmissionBlockNumber, [netuid]), + view.query(st.SubtensorModule.SubtokenEnabled, [netuid]), + view.query(st.SubtensorModule.NetworkRegistrationAllowed, [netuid]), + view.query(st.SubtensorModule.SubnetEmissionEnabled, [netuid]), + ) + return netuid, { + "eligible": ( + first_emission is not None + and bool(subtoken_enabled) + and bool(registration_allowed) + ), + "emissionEnabled": bool(emission_enabled), + } + + flags = dict(await asyncio.gather(*(subnet_flags(netuid) for netuid in netuids))) + + gate = None + if spec_version >= 444: + rank, quantile, exponent, bar = await asyncio.gather( + view.query(st.SubtensorModule.EmissionBarRank), + view.query(st.SubtensorModule.EmissionBarQuantile), + view.query(st.SubtensorModule.EmissionGateExponent), + view.query(st.SubtensorModule.EmissionGateBar), + ) + gate = { + "rank": int(rank), + "quantile": fixed_u64f64_num(quantile), + "exponent": fixed_u64f64_num(exponent), + "bar": fixed_u64f64_num(bar), + "source": "chain_storage", + } issuance_tao = total_issuance / RAO return { + "specVersion": spec_version, "totalIssuanceRao": total_issuance, "totalIssuanceTao": round(issuance_tao, 3), - "blockEmissionTao": round(block_emission / RAO, 6), - "blockEmissionCalculatedTao": round(block_emission_calculated(issuance_tao), 6), + "blockEmissionTao": round(block_emission_calculated(issuance_tao), 6), "rootTao": round(root_tao / RAO, 2), "taoWeight": round(tao_weight_raw / (2**64 - 1), 6), - "minerBurned": miner_burned, + "subnetFlags": flags, + "emissionGate": gate, } -def apply_shares(subnets: list[dict], block_emission: float) -> None: - weights = [s["emaPrice"] * (1 - s["minerBurned"]) for s in subnets] - weight_sum = sum(weights) or 1.0 - for subnet, weight in zip(subnets, weights): - share = weight / weight_sum - subnet["taoShare"] = round(share, 6) - subnet["taoPerBlock"] = round(block_emission * share, 6) +def select_emission_gate_bar( + demand_shares: list[float], + rank: int = DEFAULT_EMISSION_BAR_RANK, + quantile: float = DEFAULT_EMISSION_BAR_QUANTILE, +) -> float: + """Mirror ``maybe_update_emission_gate_bar`` for the v444 snapshot.""" + positive = sorted((share for share in demand_shares if share > 0), reverse=True) + if not positive: + return 0.0 + if rank > 0: + return positive[min(rank, len(positive)) - 1] + + cumulative = 0.0 + for share in positive: + cumulative += share + if cumulative >= quantile: + return share + return positive[-1] + + +def apply_shares( + subnets: list[dict], + block_emission: float, + *, + gate_bar: float | None = None, + gate_exponent: float = DEFAULT_EMISSION_GATE_EXPONENT, +) -> float: + """Apply v444 pure-price demand shares, the Hill gate, and enable flags.""" + price_sum = sum(max(subnet["emaPrice"], 0.0) for subnet in subnets) + demand_shares = [ + max(subnet["emaPrice"], 0.0) / price_sum if price_sum > 0 else 0.0 + for subnet in subnets + ] + if gate_bar is None: + gate_bar = select_emission_gate_bar(demand_shares) + + gate_factors = [] + gated_weights = [] + for share in demand_shares: + gate = ( + 1.0 / (1.0 + (gate_bar / share) ** gate_exponent) + if share > 0 and gate_bar > 0 + else (1.0 if share > 0 else 0.0) + ) + gate_factors.append(gate) + gated_weights.append(share * gate) + + if sum(gated_weights) == 0: + gated_weights = demand_shares + + enabled_total = sum( + weight + for subnet, weight in zip(subnets, gated_weights) + if subnet["emissionEnabled"] + ) + for subnet, demand_share, gate, weight in zip( + subnets, demand_shares, gate_factors, gated_weights + ): + share = ( + weight / enabled_total + if subnet["emissionEnabled"] and enabled_total > 0 + else 0.0 + ) + subnet["demandShare"] = round(demand_share, 8) + subnet["gateFactor"] = round(gate, 8) + subnet["taoShare"] = round(share, 8) + subnet["taoPerBlock"] = round(block_emission * share, 8) + + return gate_bar async def build_snapshot() -> dict: tmc_rows = fetch_tmc_subnets() non_root = [r for r in tmc_rows if int(r["netuid"]) != 0] - ema_price_sum = sum( - tmc_num((r.get("latest_snapshot") or {}).get("subnet_moving_price")) for r in non_root - ) + async with bt.Subtensor() as client: + chain = await chain_fields(client, [int(row["netuid"]) for row in non_root]) - top_rows = sorted( - non_root, - key=lambda r: tmc_num((r.get("latest_snapshot") or {}).get("price")), - reverse=True, - )[:TOP_N] - top_netuids = [int(r["netuid"]) for r in top_rows] - featured_netuid = 4 if 4 in top_netuids else top_netuids[0] + eligible_rows = [ + row for row in non_root if chain["subnetFlags"][int(row["netuid"])]["eligible"] + ] - async with bt.Subtensor() as client: - chain = await chain_fields(client, top_netuids + [featured_netuid]) + ema_price_sum = sum( + tmc_num((r.get("latest_snapshot") or {}).get("subnet_moving_price")) + for r in eligible_rows + ) subnets = [ - row_from_tmc(row, chain["minerBurned"].get(int(row["netuid"]), 0.0)) for row in top_rows + row_from_tmc( + row, + chain["subnetFlags"][int(row["netuid"])]["emissionEnabled"], + ) + for row in eligible_rows ] - apply_shares(subnets, chain["blockEmissionTao"]) + gate = chain["emissionGate"] or { + "rank": DEFAULT_EMISSION_BAR_RANK, + "quantile": DEFAULT_EMISSION_BAR_QUANTILE, + "exponent": DEFAULT_EMISSION_GATE_EXPONENT, + "bar": None, + "source": "v444_defaults_recomputed", + } + gate_bar = apply_shares( + subnets, + chain["blockEmissionTao"], + gate_bar=gate["bar"], + gate_exponent=gate["exponent"], + ) - featured = next(s for s in subnets if s["netuid"] == featured_netuid) + subnets_by_netuid = {subnet["netuid"]: subnet for subnet in subnets} + top_subnets = sorted(subnets, key=lambda subnet: subnet["taoShare"], reverse=True)[ + :TOP_N + ] + featured_netuid = 4 if 4 in subnets_by_netuid else top_subnets[0]["netuid"] + + featured = subnets_by_netuid[featured_netuid] return { "fetchedAt": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"), "network": "finney", - "emissionMode": "price_ema", + "chainSpecVersion": chain["specVersion"], + "emissionMode": "v444_price_ema_hill_gate", + "emissionGateSource": gate["source"], "dataSource": { "subnets": "taomarketcap.com", "chain": "finney", "tmcEndpoint": TMC_SUBNETS_URL, }, "blockEmissionTao": chain["blockEmissionTao"], - "blockEmissionCalculatedTao": chain["blockEmissionCalculatedTao"], "totalIssuanceTao": chain["totalIssuanceTao"], "totalIssuanceRao": chain["totalIssuanceRao"], "rootTao": chain["rootTao"], "emaPriceSum": round(ema_price_sum, 4), "rootDividendGateOpen": ema_price_sum > 1.0, "taoWeight": chain["taoWeight"], + "emissionGateRank": gate["rank"], + "emissionGateQuantile": round(gate["quantile"], 8), + "emissionGateExponent": round(gate["exponent"], 8), + "emissionGateBar": round(gate_bar, 8), + "emissionInputs": [ + { + "netuid": subnet["netuid"], + "emaPrice": subnet["emaPrice"], + "emissionEnabled": subnet["emissionEnabled"], + } + for subnet in subnets + ], "featuredSubnet": featured, - "topSubnets": subnets, + "topSubnets": top_subnets, } def main() -> int: parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--check", action="store_true", help="exit 1 if output would change") + parser.add_argument( + "--check", action="store_true", help="exit 1 if output would change" + ) args = parser.parse_args() snapshot = asyncio.run(build_snapshot()) @@ -217,7 +355,10 @@ def main() -> int: if args.check: if not OUTPUT.exists() or OUTPUT.read_text() != rendered: - print(f"{OUTPUT} is stale; run scripts/fetch-emission-snapshot.py", file=sys.stderr) + print( + f"{OUTPUT} is stale; run scripts/fetch-emission-snapshot.py", + file=sys.stderr, + ) return 1 print(f"{OUTPUT} is up to date.") return 0 diff --git a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v436-upgrade/page.module.css b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v436-upgrade/page.module.css index f5ea37976f..3a6f7c1367 100644 --- a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v436-upgrade/page.module.css +++ b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v436-upgrade/page.module.css @@ -11,13 +11,15 @@ .paper_title { font-size: 20px; + font-weight: 400; + margin: 0; } .subtitle { font-family: 'FiraCode'; font-size: 12px; font-weight: 200; - margin-bottom: -8px; + margin: 0 0 -8px; text-transform: uppercase; text-align: center; } diff --git a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx index 1de98b6251..887358d632 100644 --- a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx +++ b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx @@ -25,34 +25,34 @@ const page = () => { }>
    -

    The V444 Upgrade

    +

    The V444 Upgrade

    Pure Price Emissions · August 2026

    -

    Introduction

    +

    Introduction

    - Spec 444 makes the market signal simple again: a subnet's share of - network emission is determined by its moving price, passed through the emission gate. - The share is no longer reduced when a subnet directs miner incentive to an owner or burn - hotkey. Recycling and burning still do exactly what the subnet chose locally; they no - longer change its standing against every other subnet. + The market signal becomes simple again in spec 444: a subnet's + share of network emission is determined by its moving price, passed through the emission + gate. The share is no longer reduced when a subnet directs miner incentive to an owner + or burn hotkey. Recycling and burning still do exactly what the subnet chose locally; + they no longer change its standing against every other subnet.

    The release also makes the chain substantially easier to use from every external - surface. Solidity contracts gain five new Bittensor precompiles and 68 functions on - existing interfaces. A saved multisig now behaves like a wallet throughout - btcli. Automated dry runs carry enough information to approve and replay a - transaction safely. Ledger users can read the actual fields of a limit order before - signing it. Underneath those interfaces, v444 corrects transaction-pool validation, - proxy charging, commitment cleanup, storage growth, and GRANDPA finality. + surface. Solidity contracts gain 31 functions across five new Bittensor precompiles, + plus 135 additions to existing interfaces. A saved multisig now behaves like a wallet + throughout btcli. Automated dry runs carry enough information to approve + and replay a transaction safely. Ledger users can read the actual fields of a limit + order before signing it. Underneath those interfaces, v444 corrects transaction-pool + validation, proxy charging, commitment cleanup, storage growth, and GRANDPA finality.

    -

    Price is the signal

    +

    Price is the signal

    The emission gate introduced in v440{' '} starts with each subnet's share of price EMA, then suppresses emission below the @@ -70,11 +70,11 @@ v444: s_i = normalize(price_ema_i) e_i ∝ s_i × gate(s_i)`} />

    - V444 removes that extra multiplier. MinerBurned remains on-chain as an - informational measure, and the miner-incentive path still recycles or burns according to - the subnet's configuration. What changes is the boundary between local token policy - and network allocation: demand determines how much emission a subnet earns; the subnet - determines what it does with the miner portion after that. + V444 removes that extra multiplier. The on-chain value remains as an informational + measure called MinerBurned. The miner-incentive path still recycles or + burns according to the subnet's configuration. What changes is the boundary between + local token policy and network allocation: demand determines how much emission a subnet + earns; the subnet determines what it does with the miner portion after that.

    @@ -110,7 +110,7 @@ v444: s_i = normalize(price_ema_i)
    -

    The runtime, typed for Solidity

    +

    The runtime, typed for Solidity

    The Bittensor precompile suite now covers the deterministic, typed runtime surface that an EVM caller is authorized to use. Five new domain addresses expose system state that @@ -165,11 +165,12 @@ v444: s_i = normalize(price_ema_i)

    - Existing precompiles gain another 68 functions across staking V2, neurons, subnets, - alpha, balances, proxies, leasing, crowdloans, UID lookup, voting power, and transfer - surfaces. The additions include typed registration and identity operations, weight and - commitment calls, stake and collateral management, subnet configuration, global and - per-subnet state, and a maintained total-voting-power view. The{' '} + Existing precompiles gain 68 state-changing methods and 67 typed views across staking + V2, neurons, subnets, alpha, balances, proxies, leasing, crowdloans, UID lookup, voting + power, and transfer surfaces. The additions include typed registration and identity + operations, weight and commitment calls, stake and collateral management, subnet + configuration, global and per-subnet state, and a maintained total-voting-power view. + The{' '} coverage audit{' '} inventories the deliberate exclusions: Root-only, unsigned, inherent, disabled, and compatibility-only calls are not made reachable by pretending an EVM caller has a @@ -208,10 +209,17 @@ uint256 chainId = config.getEvmChainId();`} backwards compatibility so later runtime releases can extend this surface without breaking deployed contracts.

    +

    + Some existing staking reads now scan more stake records, so their gas estimate is + higher. The affected methods are getTotalHotkeyStake,{' '} + getTotalColdkeyStake, and getTotalColdkeyStakeOnSubnet. + Contracts and services should estimate these calls again after the upgrade and avoid + hard-coded gas limits. The selectors and return values have not changed. +

    -

    A multisig is now a wallet

    +

    A multisig is now a wallet

    The v11 CLI no longer makes operators translate a multisig workflow into low-level approvals by hand. Save a signer set once, then pass its name wherever a coldkey wallet @@ -262,7 +270,7 @@ btcli wallet transfer --dest 5F... --amount-tao 10 -w team-treasury`}

    -

    Read the order before signing it

    +

    Read the order before signing it

    V438 let Ledger and compatible signers authorize limit orders by signing a wrapped order hash. V444 adds an alternative @@ -279,6 +287,13 @@ limit price , expiry , hotkey , fee to , max slippage , chain , partial fills , signer `} /> +

    + The signed message uses raw integer units: amount is rao for a buy and raw + alpha units for a sell; price uses a ×109 scale; fee and + slippage use parts per billion; and expiry is a Unix timestamp in + milliseconds. Frontends may show friendlier values alongside the message, but must sign + these exact integers. +

    This format is additive. Existing raw SCALE signatures and wrapped-hash signatures remain valid, and every format resolves to the same canonical order ID for replay @@ -290,7 +305,7 @@ partial fills , signer `}

    -

    Failures get cheaper, state stays smaller

    +

    Failures get cheaper, state stays smaller

    @@ -299,6 +314,13 @@ partial fills , signer `} + + + + @@ -345,14 +368,16 @@ partial fills , signer `}
    Transaction fees + Native TAO fees and EVM fees are recycled instead of paid to the block author. + Eligible alpha-paid fees are sold for TAO and recycled in the same transaction. +
    Commit transactions @@ -316,8 +338,9 @@ partial fills , signer `}
    Proxy fees - proxy and proxy_announced propagate the inner - call's actual post-dispatch weight, refunding unused worst-case weight. + Proxy calls propagate the inner call's actual post-dispatch weight, refunding + unused worst-case weight. This applies to proxy and{' '} + proxy_announced.

    - These changes do not introduce new operator workflows. They move predictable failures - out of blocks, stop deleted identities from leaving chargeable state behind, return - overestimated proxy weight, and keep historical defaults from accumulating forever. + Transaction fees are separate from swap fees; swap fees still go to the block author. + The other changes do not introduce new operator workflows. They move predictable + failures out of blocks, stop deleted identities from leaving chargeable state behind, + return overestimated proxy weight, and keep historical defaults from accumulating + forever.

    -

    What to do

    +

    What to do

    • Node operators: wait for the on-chain spec_version to @@ -368,11 +393,15 @@ partial fills , signer `} EVM integrators: refresh the complete canonical ABI set before using v444 selectors. Add 0x…080f through 0x…0813 only from the published interfaces, and use the registry to inspect whole-precompile availability. + Re-estimate aggregate staking reads and do not rely on fixed gas stipends.
    • - SDK and CLI users: install the matching bittensor 11.1.0 - release and bittensor-core 0.1.3. Existing wallet files remain usable; - saved multisigs can now be passed directly as -w. + SDK and CLI users: older clients that read current chain metadata can + keep using existing commands. Install bittensor 11.1.0 when it is + published, plus bittensor-core 0.1.3, to use the new v444 features. + Existing wallet files remain usable, and saved multisigs can now be passed directly as{' '} + -w. Rebuild any offline signing payload prepared before the runtime + upgrade.
    • Limit-order applications: add the human-readable signing format for diff --git a/website/apps/bittensor-website/src/components/docs/emission-network-snapshot.tsx b/website/apps/bittensor-website/src/components/docs/emission-network-snapshot.tsx index 8bbb862d96..909e46ee4d 100644 --- a/website/apps/bittensor-website/src/components/docs/emission-network-snapshot.tsx +++ b/website/apps/bittensor-website/src/components/docs/emission-network-snapshot.tsx @@ -1,51 +1,58 @@ 'use client'; -import { ExplainerPanel, ExplainerStat } from './explainer-panel'; -import { useEmissionSnapshot } from '@/hooks/use-emission-snapshot'; -import { formatSnapshotAge } from '@/lib/emission-snapshot'; -import { formatPct, formatTao } from '@/lib/emission-math'; +import {ExplainerPanel, ExplainerStat} from './explainer-panel'; +import {useEmissionSnapshot} from '@/hooks/use-emission-snapshot'; +import {formatSnapshotAge} from '@/lib/emission-snapshot'; +import {formatPct, formatTao} from '@/lib/emission-math'; export function EmissionNetworkSnapshot() { const {snapshot, loading} = useEmissionSnapshot(); + const gateCaption = + snapshot.emissionGateSource === 'chain_storage' + ? 'The gate settings and midpoint come from current chain storage.' + : 'Because this snapshot predates spec 444, it previews the upgrade with the v444 default gate settings.'; return ( -
      +
      1.0, TMC)' - : 'Root gate closed (Σ EMA ≤ 1.0, TMC)' + ? 'Root dividends active (eligible Σ EMA > 1.0)' + : 'Root gate closed (eligible Σ EMA ≤ 1.0)' } accent={!loading && !snapshot.rootDividendGateOpen} />
      -

      - TAO splits across subnets by SubnetMovingPrice{' '} - (EMA of spot alpha price, capped at 1.0), minus last-tempo{' '} - MinerBurned penalties. Top recipient right - now: SN{snapshot.topSubnets[0]?.netuid} {snapshot.topSubnets[0]?.name}{' '} +

      + This preview starts with each eligible subnet's{' '} + SubnetMovingPrice (EMA of spot alpha price, + capped at 1.0), turns it into a share of the total, then applies the emission gate.{' '} + MinerBurned is not part of this cross-subnet allocation. Top modeled recipient:{' '} + + SN{snapshot.topSubnets[0]?.netuid} {snapshot.topSubnets[0]?.name} + {' '} at {loading ? '…' : formatPct(snapshot.topSubnets[0]?.taoShare ?? 0)} ( {loading ? '…' : formatTao(snapshot.topSubnets[0]?.taoPerBlock ?? 0, 4)}/block).

      diff --git a/website/apps/bittensor-website/src/components/docs/subnet-emission-share-chart.tsx b/website/apps/bittensor-website/src/components/docs/subnet-emission-share-chart.tsx index f6c3cab7ce..7788ac9aa5 100644 --- a/website/apps/bittensor-website/src/components/docs/subnet-emission-share-chart.tsx +++ b/website/apps/bittensor-website/src/components/docs/subnet-emission-share-chart.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useMemo, useRef, useState } from 'react'; +import {useMemo, useRef, useState} from 'react'; import { Chart as ChartJS, CategoryScale, @@ -10,11 +10,19 @@ import { Legend, type Plugin, } from 'chart.js'; -import { Bar } from 'react-chartjs-2'; -import { ExplainerPanel, ExplainerSlider, ExplainerStat } from './explainer-panel'; -import { useEmissionSnapshot } from '@/hooks/use-emission-snapshot'; -import { formatPct, formatTao, subnetEmissionShares } from '@/lib/emission-math'; -import { ACCENT, AXIS_BORDER, GRAPH_FONT, GRID, INK_FAINT, axisTitle, baseTicks } from './chart-theme'; +import {Bar} from 'react-chartjs-2'; +import {ExplainerPanel, ExplainerSlider, ExplainerStat} from './explainer-panel'; +import {useEmissionSnapshot} from '@/hooks/use-emission-snapshot'; +import {formatPct, formatTao, subnetEmissionShares} from '@/lib/emission-math'; +import { + ACCENT, + AXIS_BORDER, + GRAPH_FONT, + GRID, + INK_FAINT, + axisTitle, + baseTicks, +} from './chart-theme'; ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip, Legend); @@ -26,27 +34,44 @@ export function SubnetEmissionShareChart() { const {snapshot, loading} = useEmissionSnapshot(); const [selectedIdx, setSelectedIdx] = useState(2); const [whatIfEma, setWhatIfEma] = useState(null); - const [whatIfBurn, setWhatIfBurn] = useState(null); - const rows = snapshot.topSubnets.slice(0, 8); + const rows = useMemo(() => snapshot.topSubnets.slice(0, 8), [snapshot.topSubnets]); const selected = rows[selectedIdx] ?? rows[0]; - const prices = useMemo( - () => rows.map((r, i) => (i === selectedIdx && whatIfEma !== null ? whatIfEma : r.emaPrice)), - [rows, selectedIdx, whatIfEma], - ); - const burns = useMemo( - () => rows.map((r, i) => (i === selectedIdx && whatIfBurn !== null ? whatIfBurn : r.minerBurned)), - [rows, selectedIdx, whatIfBurn], + const calculation = useMemo(() => { + const inputs = snapshot.emissionInputs.map((input) => ({ + ...input, + emaPrice: + input.netuid === selected?.netuid && whatIfEma !== null ? whatIfEma : input.emaPrice, + })); + const result = subnetEmissionShares( + inputs.map((input) => input.emaPrice), + { + emissionEnabled: inputs.map((input) => input.emissionEnabled), + rank: snapshot.emissionGateRank, + quantile: snapshot.emissionGateQuantile, + exponent: snapshot.emissionGateExponent, + gateBar: snapshot.emissionGateBar, + }, + ); + const indexByNetuid = new Map(inputs.map((input, index) => [input.netuid, index])); + const priceByNetuid = new Map(inputs.map((input) => [input.netuid, input.emaPrice])); + return {indexByNetuid, priceByNetuid, ...result}; + }, [selected?.netuid, snapshot, whatIfEma]); + const shares = useMemo( + () => + rows.map((row) => { + const index = calculation.indexByNetuid.get(row.netuid); + return index === undefined ? 0 : calculation.shares[index]; + }), + [calculation, rows], ); - - const shares = useMemo(() => subnetEmissionShares(prices, burns), [prices, burns]); const blockEmission = snapshot.blockEmissionTao; // The plugin is registered once at chart creation, so it reads live values // through a ref instead of closing over state that would go stale. - const drawState = useRef({ shares, selectedIdx }); - drawState.current = { shares, selectedIdx }; + const drawState = useRef({shares, selectedIdx}); + drawState.current = {shares, selectedIdx}; // Direct value labels at each bar end instead of a legend; the selected // (highlighted) bar carries the accent. @@ -54,9 +79,9 @@ export function SubnetEmissionShareChart() { () => ({ id: 'barValueLabels', afterDatasetsDraw(chart) { - const { shares, selectedIdx } = drawState.current; + const {shares, selectedIdx} = drawState.current; const meta = chart.getDatasetMeta(0); - const { ctx } = chart; + const {ctx} = chart; ctx.save(); ctx.font = GRAPH_FONT; @@ -106,7 +131,7 @@ export function SubnetEmissionShareChart() { return [ `${ctx.parsed.x.toFixed(1)}% of ${formatTao(blockEmission)}/block`, `${formatTao(tao, 4)}/block`, - `EMA ${row.emaPrice.toFixed(4)} · burn ${formatPct(row.minerBurned, 0)}`, + `Price EMA ${calculation.priceByNetuid.get(row.netuid)?.toFixed(4) ?? '0.0000'}`, ]; }, }, @@ -115,7 +140,7 @@ export function SubnetEmissionShareChart() { scales: { x: { // Headroom for the in-plot value labels beside the longest bar. - max: Math.max(...shares.map((s) => s * 100)) * 1.35, + max: Math.max(1, ...shares.map((s) => s * 100)) * 1.35, grid: {color: GRID}, border: {color: AXIS_BORDER}, ticks: baseTicks({ @@ -133,24 +158,29 @@ export function SubnetEmissionShareChart() { if (elements[0]) { setSelectedIdx(elements[0].index); setWhatIfEma(null); - setWhatIfBurn(null); } }, }), - [rows, shares, blockEmission], + [rows, shares, blockEmission, calculation], ); const displayEma = whatIfEma ?? selected?.emaPrice ?? 0; - const displayBurn = whatIfBurn ?? selected?.minerBurned ?? 0; + const selectedInputIdx = selected ? calculation.indexByNetuid.get(selected.netuid) : undefined; + const selectedDemandShare = + selectedInputIdx === undefined ? 0 : calculation.demandShares[selectedInputIdx]; + const selectedGateFactor = + selectedInputIdx === undefined ? 0 : calculation.gateFactors[selectedInputIdx]; return ( -
      +
      {loading ? ( -
      Loading snapshot…
      +
      + Loading snapshot… +
      ) : ( )} @@ -158,49 +188,41 @@ export function SubnetEmissionShareChart() { {selected && ( <> -
      +
      - - + +
      -
      +
      setWhatIfEma(v)} /> - setWhatIfBurn(v)} - />
      - - {selected.minerBurned > 0.1 && ( -

      - SN{selected.netuid} carries a {formatPct(selected.minerBurned, 0)} burn penalty — roughly half - its unpenalized EMA share is redistributed to subnets like Chutes and Affine with b=0. -

      - )} )} diff --git a/website/apps/bittensor-website/src/lib/emission-math.ts b/website/apps/bittensor-website/src/lib/emission-math.ts index cb08297440..baea8d5e4f 100644 --- a/website/apps/bittensor-website/src/lib/emission-math.ts +++ b/website/apps/bittensor-website/src/lib/emission-math.ts @@ -1,4 +1,4 @@ -/** Chain-accurate emission helpers mirroring subtensor coinbase/epoch math. */ +/** Runtime-aligned emission helpers for the documentation models. */ export const RAO_PER_TAO = 1_000_000_000; export const TOTAL_SUPPLY_TAO = 21_000_000; @@ -20,6 +20,9 @@ export const ONE_YEAR_BLOCKS = 2_629_800; export const CONVICTION_OWNERSHIP_THRESHOLD = 0.1; export const EMA_HALVING_BLOCKS = 201_600; export const SUBNET_MOVING_ALPHA = 0.000003; +export const DEFAULT_EMISSION_BAR_RANK = 32; +export const DEFAULT_EMISSION_BAR_QUANTILE = 0.61; +export const DEFAULT_EMISSION_GATE_EXPONENT = 3; /** `get_block_emission_for_issuance` in block_emission.rs */ export function blockEmissionTao(issuanceTao: number): number { @@ -42,25 +45,85 @@ export function halvingThresholdsTao(count = 8): number[] { return thresholds; } -/** `get_shares_price_ema` + miner burn penalty in subnet_emissions.rs */ -export function subnetEmissionShares(prices: number[], minerBurned: number[]): number[] { - const priceSum = prices.reduce((a, b) => a + b, 0); - const priceShares = priceSum > 0 ? prices.map((p) => p / priceSum) : prices.map(() => 0); +export type SubnetEmissionResult = { + demandShares: number[]; + gateFactors: number[]; + shares: number[]; + gateBar: number; +}; + +/** `maybe_update_emission_gate_bar` in subnet_emissions.rs */ +export function selectEmissionGateBar( + demandShares: number[], + rank = DEFAULT_EMISSION_BAR_RANK, + quantile = DEFAULT_EMISSION_BAR_QUANTILE, +): number { + const positive = demandShares.filter((share) => share > 0).sort((a, b) => b - a); + if (positive.length === 0) return 0; + if (rank > 0) return positive[Math.min(rank, positive.length) - 1]; - const weights = prices.map((p, i) => p * (1 - Math.min(Math.max(minerBurned[i], 0), 1))); - const weightSum = weights.reduce((a, b) => a + b, 0); + let cumulative = 0; + for (const share of positive) { + cumulative += share; + if (cumulative >= quantile) return share; + } + return positive[positive.length - 1]; +} - if (weightSum === 0) return priceShares; - return weights.map((w) => w / weightSum); +/** v444 `get_shares` plus emission-enabled redistribution in subnet_emissions.rs */ +export function subnetEmissionShares( + prices: number[], + options: { + emissionEnabled?: boolean[]; + rank?: number; + quantile?: number; + exponent?: number; + gateBar?: number; + } = {}, +): SubnetEmissionResult { + const safePrices = prices.map((price) => Math.max(price, 0)); + const priceSum = safePrices.reduce((sum, price) => sum + price, 0); + const demandShares = safePrices.map((price) => (priceSum > 0 ? price / priceSum : 0)); + const gateBar = + options.gateBar ?? selectEmissionGateBar(demandShares, options.rank, options.quantile); + const exponent = options.exponent ?? DEFAULT_EMISSION_GATE_EXPONENT; + const gateFactors = demandShares.map((share) => { + if (share <= 0) return 0; + if (gateBar <= 0) return 1; + return 1 / (1 + (gateBar / share) ** exponent); + }); + + let gatedWeights = demandShares.map((share, index) => share * gateFactors[index]); + if (gatedWeights.reduce((sum, weight) => sum + weight, 0) === 0) { + gatedWeights = demandShares; + } + + const emissionEnabled = options.emissionEnabled ?? prices.map(() => true); + const enabledTotal = gatedWeights.reduce( + (sum, weight, index) => sum + (emissionEnabled[index] === false ? 0 : weight), + 0, + ); + const shares = gatedWeights.map((weight, index) => + emissionEnabled[index] !== false && enabledTotal > 0 ? weight / enabledTotal : 0, + ); + + return {demandShares, gateFactors, shares, gateBar}; } /** `update_moving_price` smoothing factor in stake_utils.rs */ -export function emaSmoothingAlpha(blocksSinceStart: number, halvingBlocks = EMA_HALVING_BLOCKS): number { +export function emaSmoothingAlpha( + blocksSinceStart: number, + halvingBlocks = EMA_HALVING_BLOCKS, +): number { return (SUBNET_MOVING_ALPHA * blocksSinceStart) / (blocksSinceStart + halvingBlocks); } /** `root_proportion` in block_step.rs (taoWeight is normalized fraction) */ -export function rootProportion(rootTao: number, alphaIssuance: number, taoWeight = DEFAULT_TAO_WEIGHT): number { +export function rootProportion( + rootTao: number, + alphaIssuance: number, + taoWeight = DEFAULT_TAO_WEIGHT, +): number { const scaled = rootTao * taoWeight; const denom = scaled + alphaIssuance; return denom > 0 ? scaled / denom : 0; @@ -199,8 +262,7 @@ export function rollForwardLock( } else if (unlockRate === maturityRate) { convictionFromMass = lockedMass * (deltaBlocks / maturityRate) * maturityDecay; } else if (unlockRate > 0 && maturityRate > 0) { - const gamma = - (unlockRate * (unlockDecay - maturityDecay)) / (unlockRate - maturityRate); + const gamma = (unlockRate * (unlockDecay - maturityDecay)) / (unlockRate - maturityRate); convictionFromMass = lockedMass * Math.max(0, gamma); } diff --git a/website/apps/bittensor-website/src/lib/emission-snapshot.ts b/website/apps/bittensor-website/src/lib/emission-snapshot.ts index 2d51119fed..53abdb2b74 100644 --- a/website/apps/bittensor-website/src/lib/emission-snapshot.ts +++ b/website/apps/bittensor-website/src/lib/emission-snapshot.ts @@ -1,31 +1,45 @@ import snapshotData from '../../public/catalog/emission-snapshot.json'; -import { blockEmissionTao } from './emission-math'; +import {blockEmissionTao} from './emission-math'; export type SubnetEmissionRow = { netuid: number; name: string; spotPrice: number; emaPrice: number; - minerBurned: number; + emissionEnabled: boolean; taoIn: number; alphaIn: number; alphaOut: number; + demandShare: number; + gateFactor: number; taoShare: number; taoPerBlock: number; }; +export type EmissionInput = { + netuid: number; + emaPrice: number; + emissionEnabled: boolean; +}; + export type EmissionSnapshot = { fetchedAt: string; network: string; - emissionMode: 'price_ema' | string; + chainSpecVersion: number; + emissionMode: 'v444_price_ema_hill_gate' | string; + emissionGateSource: 'chain_storage' | 'v444_defaults_recomputed'; blockEmissionTao: number; - blockEmissionCalculatedTao?: number; totalIssuanceTao: number; totalIssuanceRao?: number; rootTao: number; emaPriceSum: number; rootDividendGateOpen: boolean; taoWeight: number; + emissionGateRank: number; + emissionGateQuantile: number; + emissionGateExponent: number; + emissionGateBar: number; + emissionInputs: EmissionInput[]; dataSource?: { subnets: string; chain: string; From f22b50e570f3762b3345cec6e3187ffa16dae13b Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Mon, 10 Aug 2026 22:12:37 +0200 Subject: [PATCH 57/58] docs: refine v444 release actions --- .../releases/v444-upgrade/page.tsx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx index 887358d632..089af21603 100644 --- a/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx +++ b/website/apps/bittensor-website/src/app/(pages-without-footer)/releases/v444-upgrade/page.tsx @@ -361,8 +361,7 @@ partial fills , signer `} GRANDPA The Polkadot SDK is pinned to fork revision cacb4310, including - warp-finality and concluded-round cleanup fixes; testnet's warp checkpoint - now carries the correct authority set and set ID. + warp-finality and concluded-round cleanup fixes. @@ -379,11 +378,6 @@ partial fills , signer `}

      What to do

        -
      • - Node operators: wait for the on-chain spec_version to - move to 444, then update to the matching release. Testnet operators should update - promptly for the corrected GRANDPA warp checkpoint. -
      • Subnet teams and analysts: remove 1 − MinerBurned from cross-subnet emission forecasts. The emission gate remains active and miner recycling @@ -397,11 +391,11 @@ partial fills , signer `}
      • SDK and CLI users: older clients that read current chain metadata can - keep using existing commands. Install bittensor 11.1.0 when it is - published, plus bittensor-core 0.1.3, to use the new v444 features. - Existing wallet files remain usable, and saved multisigs can now be passed directly as{' '} - -w. Rebuild any offline signing payload prepared before the runtime - upgrade. + keep using existing commands. To use the new v444 features, upgrade to{' '} + bittensor 11.1.0 and bittensor-core 0.1.3 alongside the + runtime upgrade. Existing wallet files remain usable, and saved multisigs can now be + passed directly as -w. Rebuild any offline signing payload prepared + before the runtime upgrade.
      • Limit-order applications: add the human-readable signing format for From 3aa4ae77ea3e21cbf38bd5079d4729efaf31f980 Mon Sep 17 00:00:00 2001 From: UnArbosFive Date: Mon, 10 Aug 2026 22:16:24 +0200 Subject: [PATCH 58/58] docs: make emissions guidance timeless --- docs/concepts/emissions.mdx | 8 ++++---- .../src/components/docs/emission-network-snapshot.tsx | 2 +- .../src/components/docs/subnet-emission-share-chart.tsx | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/concepts/emissions.mdx b/docs/concepts/emissions.mdx index 3eef1b5fc4..2c3e6ef9ce 100644 --- a/docs/concepts/emissions.mdx +++ b/docs/concepts/emissions.mdx @@ -71,16 +71,16 @@ protocol-owned alpha. ## Subnet emission shares -V444 divides each block's TAO emission in two clear steps. First, it turns +Each block's TAO emission is divided in two clear steps. First, the chain turns each eligible subnet's **EMA price** into a share of total demand: ``` demand_share_i = price_ema_i / Σ price_ema ``` -`MinerBurned` does not change this cross-subnet share in v444. It still records -what happened to miner incentive inside the subnet, but one subnet's local burn -or recycle choice no longer changes another subnet's emission. +`MinerBurned` does not change this cross-subnet share. It still records what +happened to miner incentive inside the subnet, but one subnet's local burn or +recycle choice does not change another subnet's emission. Second, the **emission gate** reduces weak demand before the final shares are normalized. The gate has a midpoint called `theta`. By default, `theta` is the diff --git a/website/apps/bittensor-website/src/components/docs/emission-network-snapshot.tsx b/website/apps/bittensor-website/src/components/docs/emission-network-snapshot.tsx index 909e46ee4d..55fb849a0a 100644 --- a/website/apps/bittensor-website/src/components/docs/emission-network-snapshot.tsx +++ b/website/apps/bittensor-website/src/components/docs/emission-network-snapshot.tsx @@ -10,7 +10,7 @@ export function EmissionNetworkSnapshot() { const gateCaption = snapshot.emissionGateSource === 'chain_storage' ? 'The gate settings and midpoint come from current chain storage.' - : 'Because this snapshot predates spec 444, it previews the upgrade with the v444 default gate settings.'; + : 'This snapshot was captured before these emission rules became active, so it uses the default gate settings.'; return (