3

We have an extrinsic where the complexity is dictated by the number of items held in storage. Is it appropriate to read from storage in the weight annotation? See for example:

pub trait Tree<RootKey> {
    fn num_leaves(root_key: RootKey) -> u32;
}

#[pallet::config]
pub trait Config: other_pallet::Config {
    type Tree: Tree<Self::RootKey>
}

#[pallet::weight(T::WeightInfo::update(T::Tree::num_leaves(root_key)))]
pub fn update(origin: Origin, root_key: RootKey) -> DispatchResult {
    for i in T::Tree::num_leaves(root_key) {
        ...
    }

    Ok(())
}

#[frame_support::pallet]
pub mod other_pallet {
    #[pallet::storage]
    pub type Branch<T: Config> =
        StorageMap<_, Blake2_128Concat, T::RootKey, BTreeSet<T::Item>, ValueQuery>;

    #[pallet::pallet]
    pub struct OtherPallet<T>(_);

    impl<T: Config> Tree<T::RootKey> for OtherPallet<T> {
        fn num_leaves(root_key: T::RootKey) -> u32 {
            Branch::get(root_key).len() as u32
        }
    }
}

1 Answer 1

1

No this is not possible. The weight calculation has to be stateless and very fast - since it is itself not benchmarked.

A solution that is often possible is to use a length witness as argument.
This provides as worst-case upper bound to make the weight calculation stateless.
One example would be in the Alliance pallet.

The pattern is as follows:

// `length_witness` provides an upper bound for the worst-case weight. This needs
// to be provided by the user.
fn call(origin…, length_witness: u32) {
    // Now you do the state-access to figure out how much effort it will actually take.
    let actual_length = State<…>::get().len();
    // ... and reject if it would be more than expected.
    ensure!(length_witness >= actual_length, Error::<T>::BadWitness);
}

The weight for figuring out how much work needs to be done should be constant. In this example it is just one state read.
You can also do a weight refund to mitigate over-estimations a bit.

3
  • Fwiw I see Polkadot reads from storage here: github.com/paritytech/polkadot/blob/… Apr 20, 2023 at 13:35
  • Why must the weight calculation be very fast? Do slow computations (or DB accesses) introduce security issues (maybe some possible DoS attacks)? Can't find any info about it :(
    – bragov4ik
    Nov 21, 2023 at 9:09
  • Yea a slow benchmarking formula with DB accesses can be a DoS vector, since the user does not pay for it in case that the Transaction is invalid. Nov 21, 2023 at 18:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.