Skip to content

Commit

Permalink
fix: Update fee calc to use `system::constants::BlockWeights.per_clas…
Browse files Browse the repository at this point in the history
…s.normal.base_extrinsic` (#388)

* fix: Update fee calc to use system::blockWeight

* WIP

* Use blockweights constant in metadata

* Add comment

* Bump deps

* New metadata WIP

* Add tests to show how constants are used

* Pre-merge

* Ensure correct constants based on runtime version

* Grammar

* Update specs
  • Loading branch information
emostov committed Jan 18, 2021
1 parent bcd6b40 commit 5ec24e6
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 11 deletions.
46 changes: 43 additions & 3 deletions src/services/blocks/BlocksService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { ApiPromise } from '@polkadot/api';
import { expandMetadata } from '@polkadot/metadata/decorate';
import { GenericCall, Struct } from '@polkadot/types';
import { AbstractInt } from '@polkadot/types/codec/AbstractInt';
import {
AccountId,
Block,
BlockHash,
BlockWeights,
Digest,
DispatchInfo,
EventRecord,
Expand All @@ -14,6 +16,7 @@ import { AnyJson, Codec, Registry } from '@polkadot/types/types';
import { u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
import { CalcFee } from '@substrate/calc';
import { InternalServerError } from 'http-errors';

import {
IBlock,
Expand Down Expand Up @@ -338,13 +341,14 @@ export class BlocksService extends AbstractService {
block: Block
) {
const perByte = api.consts.transactionPayment?.transactionByteFee;
const extrinsicBaseWeight = api.consts.system
?.extrinsicBaseWeight as AbstractInt;
const extrinsicBaseWeightExists =
api.consts.system.extrinsicBaseWeight ||
api.consts.system.blockWeights.perClass.normal.baseExtrinsic;

let calcFee, specName, specVersion;
if (
perByte === undefined ||
extrinsicBaseWeight === undefined ||
extrinsicBaseWeightExists === undefined ||
typeof api.query.transactionPayment?.nextFeeMultiplier?.at !==
'function'
) {
Expand Down Expand Up @@ -393,6 +397,42 @@ export class BlocksService extends AbstractService {
version.specVersion.toNumber(),
];

// This `extrinsicBaseWeight` changed from using system.extrinsicBaseWeight => system.blockWeights.perClass.normal.baseExtrinsic
// in polkadot v0.8.27 due to this pr: https://github.com/paritytech/substrate/pull/6629 .
// TODO https://github.com/paritytech/substrate-api-sidecar/issues/393 .
// TODO once https://github.com/polkadot-js/api/issues/2365 is resolved we can use that instead.
let extrinsicBaseWeight;
if (
specName !== api.runtimeVersion.specName.toString() ||
specVersion !== api.runtimeVersion.specVersion.toNumber()
) {
// We are in a runtime that does **not** match the decorated metadata in the api,
// so we must fetch the correct metadata, decorate it and pull out the constant
const metadata = await api.rpc.state.getMetadata(
parentParentHash
);
const decorated = expandMetadata(api.registry, metadata);

extrinsicBaseWeight =
((decorated.consts.system
?.extrinsicBaseWeight as unknown) as AbstractInt) ||
((decorated.consts.system
?.blockWeights as unknown) as BlockWeights).perClass
?.normal?.baseExtrinsic;
} else {
// We are querying a runtime that matches the decorated metadata in the api
extrinsicBaseWeight =
(api.consts.system?.extrinsicBaseWeight as AbstractInt) ||
api.consts.system.blockWeights.perClass?.normal
?.baseExtrinsic;
}

if (!extrinsicBaseWeight) {
throw new InternalServerError(
'`extrinsicBaseWeight` is not defined when it was expected to be defined. File an issue at https://github.com/paritytech/substrate-api-sidecar/issues'
);
}

calcFee = CalcFee.from_params(
coefficients,
extrinsicBaseWeight.toBigInt(),
Expand Down
19 changes: 11 additions & 8 deletions src/services/test-helpers/mock/mockApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,18 @@ export const deriveGetBlock = (
const getHeader = (_hash: Hash) =>
Promise.resolve().then(() => mockBlock789629.header);

const runtimeVersion = {
specName: polkadotRegistry.createType('Text', 'polkadot'),
specVersion: polkadotRegistry.createType('u32', 16),
transactionVersion: polkadotRegistry.createType('u32', 2),
implVersion: polkadotRegistry.createType('u32', 0),
implName: polkadotRegistry.createType('Text', 'parity-polkadot'),
authoringVersion: polkadotRegistry.createType('u32', 0),
};

const getRuntimeVersion = () =>
Promise.resolve().then(() => {
return {
specName: polkadotRegistry.createType('Text', 'polkadot'),
specVersion: polkadotRegistry.createType('u32', 16),
transactionVersion: polkadotRegistry.createType('u32', 2),
implVersion: polkadotRegistry.createType('u32', 0),
implName: polkadotRegistry.createType('Text', 'parity-polkadot'),
authoringVersion: polkadotRegistry.createType('u32', 0),
};
return runtimeVersion;
});

const getMetadata = () => Promise.resolve().then(() => polkadotMetadata);
Expand Down Expand Up @@ -279,6 +281,7 @@ const referendumInfoOfAt = () =>
* #789629, which is what most Service unit tests are based on.
*/
export const mockApi = ({
runtimeVersion,
createType: polkadotRegistry.createType.bind(polkadotRegistry),
registry: polkadotRegistry,
tx,
Expand Down

0 comments on commit 5ec24e6

Please sign in to comment.