Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions common/src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub enum ProxyType {
Registration,
Transfer,
SmallTransfer,
RootWeights, // Deprecated
RootWeights,
ChildKeys,
SudoUncheckedSetCode,
SwapHotkey,
Expand Down Expand Up @@ -99,10 +99,7 @@ impl From<ProxyType> for u8 {

impl ProxyType {
pub fn is_deprecated(&self) -> bool {
matches!(
self,
Self::Triumvirate | Self::Senate | Self::Governance | Self::RootWeights
)
matches!(self, Self::Triumvirate | Self::Senate | Self::Governance)
}
}

Expand Down
2 changes: 1 addition & 1 deletion docs/tx/add-proxy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ only to keys you control or fully trust.
| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `delegate_ss58` | string | yes | Key that will be allowed to sign for this account. |
| `proxy_type` | string | no | Scope of calls the delegation covers. One of: Any, Owner, NonCritical, NonTransfer, Senate, NonFungible, Triumvirate, Governance, Staking, Registration, Transfer, SmallTransfer, RootWeights, ChildKeys, SudoUncheckedSetCode, SwapHotkey, SubnetLeaseBeneficiary, RootClaim. Triumvirate, Senate, Governance, and RootWeights are deprecated on the current runtime: they deny all calls, so a proxy of those types can dispatch nothing. Prefer the narrowest type that covers your use; Any can do everything the account can, including transfers. |
| `proxy_type` | string | no | Scope of calls the delegation covers. One of: Any, Owner, NonCritical, NonTransfer, Senate, NonFungible, Triumvirate, Governance, Staking, Registration, Transfer, SmallTransfer, RootWeights, ChildKeys, SudoUncheckedSetCode, SwapHotkey, SubnetLeaseBeneficiary, RootClaim. Triumvirate, Senate, and Governance are deprecated on the current runtime: they deny all calls, so a proxy of those types can dispatch nothing. RootWeights covers exactly SubtensorModule.set_root_weights. Prefer the narrowest type that covers your use; Any can do everything the account can, including transfers. |
| `delay` | integer | no | Announcement delay in blocks: the delegate must announce each call and wait this long before executing it, giving you time to veto. 0 executes immediately. |

Address parameters (`--hotkey`, `--coldkey`, `--dest`, ...) accept a raw ss58
Expand Down
2 changes: 1 addition & 1 deletion docs/tx/create-pure-proxy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ the pure proxy and anything it holds.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `proxy_type` | string | no | Scope of calls the delegation covers. One of: Any, Owner, NonCritical, NonTransfer, Senate, NonFungible, Triumvirate, Governance, Staking, Registration, Transfer, SmallTransfer, RootWeights, ChildKeys, SudoUncheckedSetCode, SwapHotkey, SubnetLeaseBeneficiary, RootClaim. Triumvirate, Senate, Governance, and RootWeights are deprecated on the current runtime: they deny all calls, so a proxy of those types can dispatch nothing. Prefer the narrowest type that covers your use; Any can do everything the account can, including transfers. |
| `proxy_type` | string | no | Scope of calls the delegation covers. One of: Any, Owner, NonCritical, NonTransfer, Senate, NonFungible, Triumvirate, Governance, Staking, Registration, Transfer, SmallTransfer, RootWeights, ChildKeys, SudoUncheckedSetCode, SwapHotkey, SubnetLeaseBeneficiary, RootClaim. Triumvirate, Senate, and Governance are deprecated on the current runtime: they deny all calls, so a proxy of those types can dispatch nothing. RootWeights covers exactly SubtensorModule.set_root_weights. Prefer the narrowest type that covers your use; Any can do everything the account can, including transfers. |
| `delay` | integer | no | Announcement delay in blocks: the delegate must announce each call and wait this long before executing it, giving you time to veto. 0 executes immediately. |
| `index` | integer | no | Disambiguator so one signer can create several pure proxies in one block; also part of the derived address. Keep 0 unless batching. |

Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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: 441,
spec_version: 442,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
11 changes: 11 additions & 0 deletions runtime/src/proxy_filters/call_groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,17 @@ call_filter_group!(SudoSetCodeCalls, [
where nested(call) == RuntimeCall::System(SystemCall::set_code),
]);

// `RootWeights`: exactly the root-weight vector call. Deliberately not the
// whole `SubtensorCommonCalls` group it overlaps: the delegator hands out the
// right to publish their root weights, not the validator's consensus-weight
// surface (`set_weights`, batch/commit/reveal) that lives alongside it.
call_filter_group!(
RootWeightCalls,
[RuntimeCall::SubtensorModule(
SubtensorCall::set_root_weights
),]
);

// Full inventory of every runtime call, used only by the coverage test that
// checks it against `RuntimeCall` metadata. Nested in three blocks so the
// flattened tuple stays within the `CallFilterMetadata` tuple-impl arity;
Expand Down
95 changes: 86 additions & 9 deletions runtime/src/proxy_filters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,9 @@ pub(crate) fn proxy_type_filter(proxy_type: &ProxyType, call: &RuntimeCall) -> b
ProxyType::SwapHotkey => HotkeySwapCalls::contains(call),
ProxyType::SubnetLeaseBeneficiary => SubnetLeaseAllowed::contains(call),
ProxyType::RootClaim => RootClaimCalls::contains(call),
ProxyType::RootWeights => RootWeightCalls::contains(call),
ProxyType::SudoUncheckedSetCode => SudoSetCodeCalls::contains(call),
ProxyType::Triumvirate
| ProxyType::Senate
| ProxyType::Governance
| ProxyType::RootWeights => false,
ProxyType::Triumvirate | ProxyType::Senate | ProxyType::Governance => false,
}
}

Expand Down Expand Up @@ -154,6 +152,10 @@ impl InstanceFilter<RuntimeCall> for ProxyType {
| ProxyType::SubnetLeaseBeneficiary
| ProxyType::RootClaim,
) => true,
// `NonFungible` already allows `set_root_weights` (via
// `SubtensorCommonCalls`), so it may also manage the
// strictly-narrower `RootWeights` delegation.
(ProxyType::NonFungible, ProxyType::RootWeights) => true,
(ProxyType::Transfer, ProxyType::SmallTransfer) => true,
_ => false,
}
Expand Down Expand Up @@ -183,11 +185,11 @@ fn proxy_filter_mode(proxy_type: ProxyType) -> FilterMode {
ProxyType::SwapHotkey => FilterMode::Allow(HotkeySwapCalls::call_infos()),
ProxyType::SubnetLeaseBeneficiary => FilterMode::Allow(SubnetLeaseAllowed::call_infos()),
ProxyType::RootClaim => FilterMode::Allow(RootClaimCalls::call_infos()),
ProxyType::RootWeights => FilterMode::Allow(RootWeightCalls::call_infos()),
ProxyType::SudoUncheckedSetCode => FilterMode::Allow(SudoSetCodeCalls::call_infos()),
ProxyType::Triumvirate
| ProxyType::Senate
| ProxyType::Governance
| ProxyType::RootWeights => FilterMode::Allow(Vec::new()),
ProxyType::Triumvirate | ProxyType::Senate | ProxyType::Governance => {
FilterMode::Allow(Vec::new())
}
}
}

Expand Down Expand Up @@ -291,12 +293,70 @@ mod tests {
ProxyType::Triumvirate,
ProxyType::Senate,
ProxyType::Governance,
ProxyType::RootWeights,
] {
assert!(allowed_calls(deprecated).is_empty());
}
}

// Re-enabled `RootWeights` is the narrowest weight grant: the root-weight
// vector call and nothing else — not consensus weights, stake movement,
// key rotation, or child keys.
#[test]
fn root_weights_grants_exactly_set_root_weights() {
use pallet_subtensor::Call as SubtensorCall;
use subtensor_runtime_common::{AccountId, AlphaBalance, NetUid, TaoBalance};

let hotkey = AccountId::new([1u8; 32]);

let set_root_weights = RuntimeCall::SubtensorModule(SubtensorCall::set_root_weights {
dests: vec![0],
weights: vec![0],
});
assert!(proxy_type_filter(
&ProxyType::RootWeights,
&set_root_weights
));

let denied = [
RuntimeCall::SubtensorModule(SubtensorCall::set_weights {
netuid: NetUid::from(1),
dests: vec![0],
weights: vec![0],
version_key: 0,
}),
RuntimeCall::SubtensorModule(SubtensorCall::add_stake {
hotkey: hotkey.clone(),
netuid: NetUid::from(1),
amount_staked: TaoBalance::from(1),
}),
RuntimeCall::SubtensorModule(SubtensorCall::remove_stake {
hotkey: hotkey.clone(),
netuid: NetUid::from(1),
amount_unstaked: AlphaBalance::from(1),
}),
RuntimeCall::SubtensorModule(SubtensorCall::swap_hotkey {
hotkey: hotkey.clone(),
new_hotkey: AccountId::new([2u8; 32]),
netuid: None,
}),
RuntimeCall::SubtensorModule(SubtensorCall::set_children {
hotkey,
netuid: NetUid::from(1),
children: vec![],
}),
];
for call in &denied {
assert!(
!proxy_type_filter(&ProxyType::RootWeights, call),
"RootWeights must not allow {:?}",
call
);
}

// The metadata view agrees: exactly one allowed call.
assert_eq!(allowed_calls(ProxyType::RootWeights).len(), 1);
}

// Broad proxies are specified subtractively here (all calls minus a few
// denied groups) and checked against the additive composition in the filter.
// Because the inventory groups partition every runtime call, the two must
Expand Down Expand Up @@ -405,6 +465,19 @@ mod tests {
assert_eq!(actual, expected);
}

#[test]
fn non_fungible_superset_is_explicit_allowlist() {
let actual = all_proxy_types()
.into_iter()
.filter(|proxy_type| ProxyType::NonFungible.is_superset(proxy_type))
.collect::<BTreeSet<_>>();
let expected = [ProxyType::NonFungible, ProxyType::RootWeights]
.into_iter()
.collect::<BTreeSet<_>>();

assert_eq!(actual, expected);
}

#[test]
fn owner_allows_only_owner_settable_config() {
let owner = allowed_calls(ProxyType::Owner);
Expand Down Expand Up @@ -513,6 +586,10 @@ mod tests {
"SubtensorModule::claim_root_with_hotkey",
])
);
assert_eq!(
allowed_calls(ProxyType::RootWeights),
expected(&["SubtensorModule::set_root_weights"])
);
assert_eq!(
allowed_calls(ProxyType::SudoUncheckedSetCode),
expected(&["Sudo::sudo_unchecked_weight"])
Expand Down
9 changes: 5 additions & 4 deletions sdk/python/bittensor/intents/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ def check_proxy_type(proxy_type: str) -> str:
PROXY_TYPE_HELP = (
"Scope of calls the delegation covers. One of: "
+ ", ".join(PROXY_TYPES)
+ ". Triumvirate, Senate, Governance, and RootWeights are deprecated on "
"the current runtime: they deny all calls, so a proxy of those types can "
"dispatch nothing. Prefer the narrowest type that covers your use; Any "
"can do everything the account can, including transfers."
+ ". Triumvirate, Senate, and Governance are deprecated on the current "
"runtime: they deny all calls, so a proxy of those types can dispatch "
"nothing. RootWeights covers exactly SubtensorModule.set_root_weights. "
"Prefer the narrowest type that covers your use; Any can do everything "
"the account can, including transfers."
)

DELAY_HELP = (
Expand Down
4 changes: 2 additions & 2 deletions website/apps/bittensor-website/public/catalog/intents.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
},
"proxy_type": {
"type": "string",
"description": "Scope of calls the delegation covers. One of: Any, Owner, NonCritical, NonTransfer, Senate, NonFungible, Triumvirate, Governance, Staking, Registration, Transfer, SmallTransfer, RootWeights, ChildKeys, SudoUncheckedSetCode, SwapHotkey, SubnetLeaseBeneficiary, RootClaim. Triumvirate, Senate, Governance, and RootWeights are deprecated on the current runtime: they deny all calls, so a proxy of those types can dispatch nothing. Prefer the narrowest type that covers your use; Any can do everything the account can, including transfers."
"description": "Scope of calls the delegation covers. One of: Any, Owner, NonCritical, NonTransfer, Senate, NonFungible, Triumvirate, Governance, Staking, Registration, Transfer, SmallTransfer, RootWeights, ChildKeys, SudoUncheckedSetCode, SwapHotkey, SubnetLeaseBeneficiary, RootClaim. Triumvirate, Senate, and Governance are deprecated on the current runtime: they deny all calls, so a proxy of those types can dispatch nothing. RootWeights covers exactly SubtensorModule.set_root_weights. Prefer the narrowest type that covers your use; Any can do everything the account can, including transfers."
},
"delay": {
"type": "integer",
Expand Down Expand Up @@ -847,7 +847,7 @@
"properties": {
"proxy_type": {
"type": "string",
"description": "Scope of calls the delegation covers. One of: Any, Owner, NonCritical, NonTransfer, Senate, NonFungible, Triumvirate, Governance, Staking, Registration, Transfer, SmallTransfer, RootWeights, ChildKeys, SudoUncheckedSetCode, SwapHotkey, SubnetLeaseBeneficiary, RootClaim. Triumvirate, Senate, Governance, and RootWeights are deprecated on the current runtime: they deny all calls, so a proxy of those types can dispatch nothing. Prefer the narrowest type that covers your use; Any can do everything the account can, including transfers."
"description": "Scope of calls the delegation covers. One of: Any, Owner, NonCritical, NonTransfer, Senate, NonFungible, Triumvirate, Governance, Staking, Registration, Transfer, SmallTransfer, RootWeights, ChildKeys, SudoUncheckedSetCode, SwapHotkey, SubnetLeaseBeneficiary, RootClaim. Triumvirate, Senate, and Governance are deprecated on the current runtime: they deny all calls, so a proxy of those types can dispatch nothing. RootWeights covers exactly SubtensorModule.set_root_weights. Prefer the narrowest type that covers your use; Any can do everything the account can, including transfers."
},
"delay": {
"type": "integer",
Expand Down