Adjust contracts to pass either V1 or V2 weights (#5254)

* Adjust contracts to pass either V1 or V2 weights

* Adjust

* Formatting

* Adjust

* Fix build
This commit is contained in:
Jaco
2022-10-03 12:31:00 +03:00
committed by GitHub
parent 71ddc66515
commit 6983f8c883
7 changed files with 96 additions and 71 deletions
+10 -8
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
import type { Registry } from '@polkadot/types/types';
import type { INumber, Registry } from '@polkadot/types/types';
import { ApiBase } from '@polkadot/api/base';
import { isFunction } from '@polkadot/util';
@@ -16,14 +16,9 @@ export abstract class Base<ApiType extends ApiTypes> {
protected readonly _decorateMethod: DecorateMethod<ApiType>;
protected readonly _isOldWeight: boolean;
constructor (api: ApiBase<ApiType>, abi: string | Record<string, unknown> | Abi, decorateMethod: DecorateMethod<ApiType>) {
this.abi = abi instanceof Abi
? abi
: new Abi(abi, api.registry.getChainProperties());
this.api = api;
this._decorateMethod = decorateMethod;
if (!api || !api.isConnected || !api.tx) {
throw new Error('Your API has not been initialized correctly and is not connected to a chain');
} else if (!api.tx.contracts || !isFunction(api.tx.contracts.instantiateWithCode) || api.tx.contracts.instantiateWithCode.meta.args.length !== 6) {
@@ -31,6 +26,13 @@ export abstract class Base<ApiType extends ApiTypes> {
} else if (!api.call.contractsApi || !isFunction(api.call.contractsApi.call)) {
throw new Error('Your runtime does not expose the api.call.contractsApi.call runtime interfaces');
}
this.abi = abi instanceof Abi
? abi
: new Abi(abi, api.registry.getChainProperties());
this.api = api;
this._decorateMethod = decorateMethod;
this._isOldWeight = isFunction(api.registry.createType<INumber>('Weight').toBn);
}
public get registry (): Registry {
+7 -8
View File
@@ -5,7 +5,7 @@ import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
import type { AccountId, EventRecord, Hash } from '@polkadot/types/interfaces';
import type { ISubmittableResult } from '@polkadot/types/types';
import type { AbiConstructor, BlueprintOptions } from '../types';
import type { AbiConstructor, BlueprintOptions, WeightAll } from '../types';
import type { MapConstructorExec } from './types';
import { SubmittableResult } from '@polkadot/api';
@@ -16,7 +16,7 @@ import { Abi } from '../Abi';
import { applyOnEvent } from '../util';
import { Base } from './Base';
import { Contract } from './Contract';
import { createBluePrintTx, encodeSalt } from './util';
import { convertWeight, createBluePrintTx, encodeSalt } from './util';
export interface BlueprintConstructor<ApiType extends ApiTypes> {
new(api: ApiBase<ApiType>, abi: string | Record<string, unknown> | Abi, codeHash: string | Hash | Uint8Array): Blueprint<ApiType>;
@@ -57,13 +57,12 @@ export class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
}
#deploy = (constructorOrId: AbiConstructor | string | number, { gasLimit = BN_ZERO, salt, storageDepositLimit = null, value = BN_ZERO }: BlueprintOptions, params: unknown[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> => {
// TODO Cater for new call structure (with old fallback)
return (
this.api.tx.contracts.instantiateOldWeight ||
this.api.tx.contracts.instantiate
)(
return this.api.tx.contracts.instantiate(
value,
gasLimit,
this._isOldWeight
// jiggle v1 weights, metadata points to latest
? convertWeight(gasLimit).v1Weight as unknown as WeightAll['v2Weight']
: convertWeight(gasLimit).v2Weight,
storageDepositLimit,
this.codeHash,
this.abi.findConstructor(constructorOrId).toU8a(params),
+7 -8
View File
@@ -6,7 +6,7 @@ import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
import type { AccountId, EventRecord } from '@polkadot/types/interfaces';
import type { ISubmittableResult } from '@polkadot/types/types';
import type { Codec } from '@polkadot/types-codec/types';
import type { AbiConstructor, BlueprintOptions } from '../types';
import type { AbiConstructor, BlueprintOptions, WeightAll } from '../types';
import type { MapConstructorExec } from './types';
import { SubmittableResult } from '@polkadot/api';
@@ -18,7 +18,7 @@ import { applyOnEvent } from '../util';
import { Base } from './Base';
import { Blueprint } from './Blueprint';
import { Contract } from './Contract';
import { createBluePrintTx, encodeSalt } from './util';
import { convertWeight, createBluePrintTx, encodeSalt } from './util';
export interface CodeConstructor<ApiType extends ApiTypes> {
new(api: ApiBase<ApiType>, abi: string | Record<string, unknown> | Abi, wasm: Uint8Array | string | Buffer | null | undefined): Code<ApiType>;
@@ -64,13 +64,12 @@ export class Code<ApiType extends ApiTypes> extends Base<ApiType> {
}
#instantiate = (constructorOrId: AbiConstructor | string | number, { gasLimit = BN_ZERO, salt, storageDepositLimit = null, value = BN_ZERO }: BlueprintOptions, params: unknown[]): SubmittableExtrinsic<ApiType, CodeSubmittableResult<ApiType>> => {
// TODO Cater for new call structure (with old fallback)
return (
this.api.tx.contracts.instantiateWithCodeOldWeight ||
this.api.tx.contracts.instantiateWithCode
)(
return this.api.tx.contracts.instantiateWithCode(
value,
gasLimit,
this._isOldWeight
// jiggle v1 weights, metadata points to latest
? convertWeight(gasLimit).v1Weight as unknown as WeightAll['v2Weight']
: convertWeight(gasLimit).v2Weight,
storageDepositLimit,
compactAddLength(this.code),
this.abi.findConstructor(constructorOrId).toU8a(params),
+43 -42
View File
@@ -3,22 +3,22 @@
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import type { ApiTypes, DecorateMethod } from '@polkadot/api/types';
import type { Bytes, Compact } from '@polkadot/types';
import type { Bytes } from '@polkadot/types';
import type { AccountId, ContractExecResult, EventRecord, Weight } from '@polkadot/types/interfaces';
import type { ISubmittableResult } from '@polkadot/types/types';
import type { AbiMessage, ContractCallOutcome, ContractOptions, DecodedEvent } from '../types';
import type { AbiMessage, ContractCallOutcome, ContractOptions, DecodedEvent, WeightAll, WeightV2 } from '../types';
import type { ContractCallResult, ContractCallSend, ContractQuery, ContractTx, MapMessageQuery, MapMessageTx } from './types';
import { map } from 'rxjs';
import { SubmittableResult } from '@polkadot/api';
import { ApiBase } from '@polkadot/api/base';
import { BN, BN_HUNDRED, BN_ONE, BN_ZERO, bnToBn, isUndefined, logger } from '@polkadot/util';
import { BN, BN_HUNDRED, BN_ONE, BN_ZERO, isUndefined, logger } from '@polkadot/util';
import { Abi } from '../Abi';
import { applyOnEvent } from '../util';
import { Base } from './Base';
import { withMeta } from './util';
import { convertWeight, withMeta } from './util';
export interface ContractConstructor<ApiType extends ApiTypes> {
new(api: ApiBase<ApiType>, abi: string | Record<string, unknown> | Abi, address: string | AccountId): Contract<ApiType>;
@@ -85,37 +85,32 @@ export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
return this.#tx;
}
#getMaxGas = (): BN => {
if (this.api.consts.system.blockWeights) {
const maxBlock = (this.api.consts.system.blockWeights as unknown as { maxBlock: { proofSize: Compact<Weight>, refTime: Compact<Weight> } }).maxBlock;
#getGas = (_gasLimit: bigint | BN | string | number | WeightV2, isCall = false): WeightAll => {
const weight = convertWeight(_gasLimit);
return maxBlock.proofSize
? maxBlock.refTime.unwrap()
: maxBlock as unknown as Weight;
if (weight.v1Weight.gt(BN_ZERO)) {
return weight;
}
return this.api.consts.system.maximumBlockWeight as Weight;
};
#getGas = (_gasLimit: bigint | BN | string | number, isCall = false): BN => {
const gasLimit = bnToBn(_gasLimit);
return gasLimit.lte(BN_ZERO)
? isCall
return convertWeight(
isCall
? MAX_CALL_GAS
: this.#getMaxGas().muln(64).div(BN_HUNDRED)
: gasLimit;
: convertWeight(
this.api.consts.system.blockWeights
? (this.api.consts.system.blockWeights as unknown as { maxBlock: WeightV2 }).maxBlock
: this.api.consts.system.maximumBlockWeight as Weight
).v1Weight.muln(64).div(BN_HUNDRED)
);
};
#exec = (messageOrId: AbiMessage | string | number, { gasLimit = BN_ZERO, storageDepositLimit = null, value = BN_ZERO }: ContractOptions, params: unknown[]): SubmittableExtrinsic<ApiType> => {
// TODO Cater for new call structure (with old fallback)
return (
this.api.tx.contracts.callOldWeight ||
this.api.tx.contracts.call
)(
return this.api.tx.contracts.call(
this.address,
value,
this.#getGas(gasLimit),
this._isOldWeight
// jiggle v1 weights, metadata points to latest
? convertWeight(gasLimit).v1Weight as unknown as WeightAll['v2Weight']
: convertWeight(gasLimit).v2Weight,
storageDepositLimit,
this.abi.findMessage(messageOrId).toU8a(params)
).withResultTransform((result: ISubmittableResult) =>
@@ -142,22 +137,28 @@ export class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
send: this._decorateMethod((origin: string | AccountId | Uint8Array) =>
this.api.rx.call.contractsApi
.call<ContractExecResult>(origin, this.address, value, this.#getGas(gasLimit, true), storageDepositLimit, message.toU8a(params))
.pipe(
map(({ debugMessage, gasConsumed, gasRequired, result, storageDeposit }): ContractCallOutcome => ({
debugMessage,
gasConsumed,
gasRequired: gasRequired && !gasRequired.isZero()
? gasRequired
: gasConsumed,
output: result.isOk && message.returnType
? this.abi.registry.createTypeUnsafe(message.returnType.lookupName || message.returnType.type, [result.asOk.data.toU8a(true)], { isPedantic: true })
: null,
result,
storageDeposit
}))
)
this.api.rx.call.contractsApi.call<ContractExecResult>(
origin,
this.address,
value,
// the runtime interface still used u64 inputs
this.#getGas(gasLimit, true).v1Weight,
storageDepositLimit,
message.toU8a(params)
).pipe(
map(({ debugMessage, gasConsumed, gasRequired, result, storageDeposit }): ContractCallOutcome => ({
debugMessage,
gasConsumed,
gasRequired: gasRequired && !gasRequired.isZero()
? gasRequired
: gasConsumed,
output: result.isOk && message.returnType
? this.abi.registry.createTypeUnsafe(message.returnType.lookupName || message.returnType.type, [result.asOk.data.toU8a(true)], { isPedantic: true })
: null,
result,
storageDeposit
}))
)
)
};
};
+14 -2
View File
@@ -4,11 +4,12 @@
import type { SubmittableResult } from '@polkadot/api';
import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import type { ApiTypes } from '@polkadot/api/types';
import type { AbiConstructor, AbiMessage, BlueprintOptions } from '../types';
import type { BN } from '@polkadot/util';
import type { AbiConstructor, AbiMessage, BlueprintOptions, WeightAll, WeightV2 } from '../types';
import type { BlueprintDeploy, ContractGeneric } from './types';
import { Bytes } from '@polkadot/types';
import { compactAddLength, u8aToU8a } from '@polkadot/util';
import { bnToBn, compactAddLength, u8aToU8a } from '@polkadot/util';
import { randomAsU8a } from '@polkadot/util-crypto';
export const EMPTY_SALT = new Uint8Array();
@@ -37,3 +38,14 @@ export function encodeSalt (salt: Uint8Array | string | null = randomAsU8a()): U
? compactAddLength(u8aToU8a(salt))
: EMPTY_SALT;
}
export function convertWeight (orig: WeightV2 | bigint | string | number | BN): WeightAll {
const refTime = (orig as WeightV2).proofSize
? (orig as WeightV2).refTime.toBn()
: bnToBn(orig as BN);
return {
v1Weight: refTime,
v2Weight: { refTime }
};
}
+14 -2
View File
@@ -5,7 +5,7 @@ import type { ApiBase } from '@polkadot/api/base';
import type { ApiTypes } from '@polkadot/api/types';
import type { Text, u64 } from '@polkadot/types';
import type { ContractExecResultResult, ContractSelector, StorageDeposit } from '@polkadot/types/interfaces';
import type { Codec, TypeDef } from '@polkadot/types/types';
import type { Codec, ICompact, INumber, TypeDef } from '@polkadot/types/types';
import type { BN } from '@polkadot/util';
import type { Abi } from '.';
@@ -73,7 +73,7 @@ export interface DecodedMessage {
}
export interface ContractOptions {
gasLimit?: bigint | string | number | BN;
gasLimit?: bigint | string | number | BN | WeightV2;
storageDepositLimit?: bigint | string | number | BN | null;
value?: bigint | BN | string | number;
}
@@ -81,3 +81,15 @@ export interface ContractOptions {
export interface BlueprintOptions extends ContractOptions {
salt?: Uint8Array | string | null;
}
export interface WeightV2 {
refTime: ICompact<INumber>;
proofSize: ICompact<INumber>;
}
export interface WeightAll {
v1Weight: BN;
v2Weight: {
refTime: BN;
};
}