Skip to content
Open
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
5 changes: 5 additions & 0 deletions .github/workflows/run-benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ jobs:

- name: Run & validate benchmarks
timeout-minutes: 180
env:
# PRs use fewer regression points; nightly/manual runs retain the
# full-resolution benchmark configuration.
STEPS: ${{ github.event_name == 'pull_request' && '15' || '50' }}
REPEAT: "20"
run: |
mkdir -p .bench_patch
chmod +x scripts/benchmark_action.sh
Expand Down
211 changes: 115 additions & 96 deletions chain-extensions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ pub mod types;

use crate::types::{ColdkeyLock, FunctionId, Output, StakeAvailability, SubnetRegistrationState};
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{DebugNoBound, traits::Get};
use frame_support::{
DebugNoBound,
dispatch::{DispatchResult, DispatchResultWithPostInfo},
traits::Get,
};
use frame_system::RawOrigin;
use pallet_contracts::chain_extension::{
BufInBufOutState, ChainExtension, Environment, Ext, InitState, RetVal, SysConfig,
BufInBufOutState, ChainExtension, ChargedAmount, Environment, Ext, InitState, RetVal, SysConfig,
};
use pallet_subtensor::weights::WeightInfo as SubtensorWeightInfo;
use pallet_subtensor_proxy as pallet_proxy;
Expand All @@ -32,6 +36,43 @@ impl<T> Default for SubtensorChainExtension<T> {
}
}

fn finish_subtensor_call<T, Env>(
env: &mut Env,
charged: Env::ChargedAmount,
declared_weight: Weight,
call_result: DispatchResultWithPostInfo,
) -> Result<RetVal, DispatchError>
where
T: pallet_contracts::Config,
Env: SubtensorExtensionEnv<T>,
{
match call_result {
Ok(post_info) => {
env.adjust_weight(charged, post_info.actual_weight.unwrap_or(declared_weight));
Ok(RetVal::Converging(Output::Success as u32))
}
Err(error_with_post_info) => {
env.adjust_weight(
charged,
error_with_post_info
.post_info
.actual_weight
.unwrap_or(declared_weight),
);
Ok(RetVal::Converging(
Output::from(error_with_post_info.error) as u32
))
}
}
}

fn finish_fixed_subtensor_call(call_result: DispatchResult) -> Result<RetVal, DispatchError> {
match call_result {
Ok(()) => Ok(RetVal::Converging(Output::Success as u32)),
Err(error) => Ok(RetVal::Converging(Output::from(error) as u32)),
}
}

impl<T> ChainExtension<T> for SubtensorChainExtension<T>
where
T: pallet_subtensor::Config
Expand Down Expand Up @@ -82,13 +123,7 @@ where
let call_result =
pallet_subtensor::Pallet::<T>::add_stake(origin.into(), hotkey, netuid, amount_staked);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_remove_stake_v1<Env>(
Expand Down Expand Up @@ -116,13 +151,7 @@ where
amount_unstaked,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_unstake_all_v1<Env>(
Expand All @@ -137,20 +166,18 @@ where
.read_as()
.map_err(|_| DispatchError::Other("Failed to decode input parameters"))?;

let subnet_count = u32::from(pallet_subtensor::TotalNetworks::<T>::get());
let weight =
<<T as pallet_subtensor::Config>::WeightInfo as SubtensorWeightInfo>::unstake_all();
<<T as pallet_subtensor::Config>::WeightInfo as SubtensorWeightInfo>::unstake_all(
subnet_count,
)
.saturating_add(T::DbWeight::get().reads(1));

env.charge_weight(weight)?;

let call_result = pallet_subtensor::Pallet::<T>::unstake_all(origin.into(), hotkey);
let call_result = pallet_subtensor::Pallet::<T>::do_unstake_all(origin.into(), hotkey);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_unstake_all_alpha_v1<Env>(
Expand All @@ -165,21 +192,19 @@ where
.read_as()
.map_err(|_| DispatchError::Other("Failed to decode input parameters"))?;

let subnet_count = u32::from(pallet_subtensor::TotalNetworks::<T>::get());
let weight =
<<T as pallet_subtensor::Config>::WeightInfo as SubtensorWeightInfo>::unstake_all_alpha(
);
subnet_count,
)
.saturating_add(T::DbWeight::get().reads(1));

env.charge_weight(weight)?;

let call_result = pallet_subtensor::Pallet::<T>::unstake_all_alpha(origin.into(), hotkey);
let call_result =
pallet_subtensor::Pallet::<T>::do_unstake_all_alpha(origin.into(), hotkey);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_move_stake_v1<Env>(
Expand Down Expand Up @@ -214,13 +239,7 @@ where
alpha_amount,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_transfer_stake_v1<Env>(
Expand Down Expand Up @@ -255,13 +274,7 @@ where
alpha_amount,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_swap_stake_v1<Env>(
Expand Down Expand Up @@ -294,13 +307,7 @@ where
alpha_amount,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_add_stake_limit_v1<Env>(
Expand Down Expand Up @@ -335,13 +342,7 @@ where
allow_partial,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_remove_stake_limit_v1<Env>(
Expand Down Expand Up @@ -376,13 +377,7 @@ where
allow_partial,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_swap_stake_limit_v1<Env>(
Expand Down Expand Up @@ -420,13 +415,7 @@ where
allow_partial,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_remove_stake_full_limit_v1<Env>(
Expand All @@ -452,13 +441,7 @@ where
limit_price,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_fixed_subtensor_call(call_result)
}

fn dispatch_set_coldkey_auto_stake_hotkey_v1<Env>(
Expand All @@ -473,23 +456,50 @@ where
.read_as()
.map_err(|_| DispatchError::Other("Failed to decode input parameters"))?;

let weight = <<T as pallet_subtensor::Config>::WeightInfo as SubtensorWeightInfo>::set_coldkey_auto_stake_hotkey();

env.charge_weight(weight)?;
// Charge the state reads used to derive this nested call's conservative
// benchmark bound separately. The top-level extrinsic ceiling cannot be
// reserved inside a contract whose enclosing gas limit is smaller.
let metering_reserve = T::DbWeight::get().reads(3);
let metering_charged = env.charge_weight(metering_reserve)?;
let (weight, metering_reads) = match &origin {
RawOrigin::Signed(coldkey) => {
let current_hotkey =
pallet_subtensor::AutoStakeDestination::<T>::get(coldkey, netuid);
let old_coldkeys = current_hotkey
.as_ref()
.and_then(|old_hotkey| {
pallet_subtensor::AutoStakeDestinationColdkeys::<T>::decode_len(
old_hotkey, netuid,
)
})
.unwrap_or_default() as u32;
let new_coldkeys =
pallet_subtensor::AutoStakeDestinationColdkeys::<T>::decode_len(&hotkey, netuid)
.unwrap_or_default() as u32;
(
<<T as pallet_subtensor::Config>::WeightInfo as SubtensorWeightInfo>::set_coldkey_auto_stake_hotkey(
old_coldkeys,
new_coldkeys,
),
if current_hotkey.is_some() { 3 } else { 2 },
)
}
_ => (
<<T as pallet_subtensor::Config>::WeightInfo as SubtensorWeightInfo>::set_coldkey_auto_stake_hotkey(0, 0),
0,
),
};
env.adjust_weight(metering_charged, T::DbWeight::get().reads(metering_reads));

let charged = env.charge_weight(weight)?;

let call_result = pallet_subtensor::Pallet::<T>::set_coldkey_auto_stake_hotkey(
origin.into(),
netuid,
hotkey,
);

match call_result {
Ok(_) => Ok(RetVal::Converging(Output::Success as u32)),
Err(e) => {
let error_code = Output::from(e) as u32;
Ok(RetVal::Converging(error_code))
}
}
finish_subtensor_call::<T, Env>(env, charged, weight, call_result)
}

fn dispatch_add_proxy_v1<Env>(
Expand Down Expand Up @@ -925,8 +935,11 @@ trait SubtensorExtensionEnv<T>
where
T: pallet_contracts::Config,
{
type ChargedAmount;

fn func_id(&self) -> u16;
fn charge_weight(&mut self, weight: Weight) -> Result<(), DispatchError>;
fn charge_weight(&mut self, weight: Weight) -> Result<Self::ChargedAmount, DispatchError>;
fn adjust_weight(&mut self, charged: Self::ChargedAmount, actual_weight: Weight);
fn read_as<U: Decode + MaxEncodedLen>(&mut self) -> Result<U, DispatchError>;
fn write_output(&mut self, data: &[u8]) -> Result<(), DispatchError>;
fn caller(&mut self) -> T::AccountId;
Expand Down Expand Up @@ -963,12 +976,18 @@ where
T::AccountId: Clone,
E: Ext<T = T>,
{
type ChargedAmount = ChargedAmount;

fn func_id(&self) -> u16 {
self.env.func_id()
}

fn charge_weight(&mut self, weight: Weight) -> Result<(), DispatchError> {
self.env.charge_weight(weight).map(|_| ())
fn charge_weight(&mut self, weight: Weight) -> Result<Self::ChargedAmount, DispatchError> {
self.env.charge_weight(weight)
}

fn adjust_weight(&mut self, charged: Self::ChargedAmount, actual_weight: Weight) {
self.env.adjust_weight(charged, actual_weight);
}

fn read_as<U: Decode + MaxEncodedLen>(&mut self) -> Result<U, DispatchError> {
Expand Down
1 change: 1 addition & 0 deletions chain-extensions/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ impl pallet_subtensor::Config for Test {
type BurnAccountId = BurnAccountId;
type InitialMaxEpochsPerBlock = MaxEpochsPerBlock;
type WeightInfo = ();
type MaxTransactionExtensionWeight = ();
}

// Swap-related parameter types
Expand Down
Loading
Loading