6

I developed a pallet with one extrinsic:

#[pallet::weight(0)]
pub fn sum(_: OriginFor<T>, values: Vec<u64>) {
    // Sum up `values`
}

The Extrinsic accepts a vector and uses it. Currently it has weight(0).
Can I still call my extrinsic or is it going to crash the node?
How do I get a real weight?

1 Answer 1

8

Weight

Weight is an absolute unit of execution time. The longer your extrinsic runs, the more Weight it has.
Substrate uses this to know in advance how many transactions fit in a block.
This is important to keep the block production at a constant pace.

An extrinsic in Substrate will not revert or error when it uses more Weight than specified.
For development you are safe to use 0 as your node is not doing anything else.
Later on for a real deployment you should properly benchmark it.

The Idea Of Benchmarking

The idea is to call your extrinsic with different arguments and measure how they influence the execution time.
In your example this boils down to different lengths of the argument vector.
More generally speaking you must ensure that the worst-case execution time is covered.

A Minimal Example

A benchmark for your extrinsic could look like this:

sum {
    // Define a complexity component.
    // This will be used as length for the vector.  
    // The 256 is arbitrary and a hard limit should be added to your extrinsic,
    // otherwise its weight is unbounded.
    let l in 0 .. 256;
    
    // Create a vector with value `123` repeated `l` times.
    let values = vec![123; l];

    // The account that will sign the call.
    let acc: T::AccountId = whitelisted_caller();
}: _(RawOrigin::Signed(acc), values)    // Call the extrinsic.

Substrate will try to figure out how the l component influences the execution time of your extrinsic.
If you just loop over the vector and sum up the values, a linear growth is expected.
In fact; Substrate currently only supports linear growth.

Substrate then generates a rust file which makes it possible to use weight annotations in your pallet with:
#[pallet::weight(T::WeightInfo::sum(values.len()))].

The whole setup for this is rather involved and requires a node.
You are best of looking at the pallet-template benchmark for a complete example and the benchmarking tutorial for a walk-through.

... or ask here obviously 😀

2
  • Nice answer! I have a question related to the An extrinsic in Substrate will not revert or error when it uses more Weight than specified. What if I have some extrinsic with hardcode weight values lower than the truly benchmarked weight values in the production chains, what will happened? Jun 20, 2022 at 8:44
  • The benchmarking generally aims at slightly over-estimating the weight. This ensures that the chain never runs out of resources when validating a block. If you annotate a lower weight for your extrinsic than what the benchmarking reports, you risk running out of resources when validating a block. This could potentially even stall the chain, depending on the discrepancy. Jul 13, 2022 at 7:28

Your Answer

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

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