Skip to content

Commit

Permalink
fix: Use correct registry when parsing extrinsic call arguments (#323)
Browse files Browse the repository at this point in the history
* fix: Use correct registry when parsing extrinsic `call` arguments

* Use registry directly; fix regressions in v0
  • Loading branch information
emostov committed Oct 21, 2020
1 parent d1f01ea commit b4678e1
Show file tree
Hide file tree
Showing 5 changed files with 738 additions and 732 deletions.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
"test": "jest --silent"
},
"dependencies": {
"@polkadot/api": "^2.0.1",
"@polkadot/util-crypto": "^3.5.1",
"@polkadot/api": "^2.3.1",
"@polkadot/util-crypto": "^3.6.1",
"@substrate/calc": "^0.1.2",
"confmgr": "^1.0.6",
"express": "^4.17.1",
Expand All @@ -49,16 +49,16 @@
"@types/express": "^4.17.8",
"@types/express-serve-static-core": "^4.17.13",
"@types/http-errors": "^1.6.3",
"@types/jest": "^26.0.13",
"@types/jest": "^26.0.15",
"@types/morgan": "^1.9.1",
"@types/triple-beam": "^1.3.2",
"@typescript-eslint/eslint-plugin": "^4.3.0",
"@typescript-eslint/parser": "^4.3.0",
"eslint": "^7.10.0",
"eslint-config-prettier": "^6.12.0",
"@typescript-eslint/eslint-plugin": "^4.5.0",
"@typescript-eslint/parser": "^4.5.0",
"eslint": "^7.11.0",
"eslint-config-prettier": "^6.13.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-simple-import-sort": "^5.0.3",
"jest": "^26.4.2",
"jest": "^26.6.0",
"prettier": "^2.1.2",
"rimraf": "^3.0.2",
"standard-version": "^9.0.0",
Expand Down
24 changes: 20 additions & 4 deletions src/services/blocks/BlocksService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,19 @@ describe('BlocksService', () => {
it('does not handle an empty object', () =>
expect(() =>
blocksService['parseGenericCall'](
({} as unknown) as GenericCall
({} as unknown) as GenericCall,
mockBlock789629.registry
)
).toThrow());

it('parses a simple balances.transfer', () => {
expect(
JSON.stringify(blocksService['parseGenericCall'](transfer))
JSON.stringify(
blocksService['parseGenericCall'](
transfer,
mockBlock789629.registry
)
)
).toBe(JSON.stringify(transferOutput));
});

Expand Down Expand Up @@ -159,7 +165,12 @@ describe('BlocksService', () => {
};

expect(
JSON.stringify(blocksService['parseGenericCall'](batch4))
JSON.stringify(
blocksService['parseGenericCall'](
batch4,
mockBlock789629.registry
)
)
).toBe(
JSON.stringify({
...baseBatch,
Expand Down Expand Up @@ -232,7 +243,12 @@ describe('BlocksService', () => {
};

expect(
JSON.stringify(blocksService['parseGenericCall'](batch))
JSON.stringify(
blocksService['parseGenericCall'](
batch,
mockBlock789629.registry
)
)
).toEqual(
JSON.stringify({
method: {
Expand Down
33 changes: 22 additions & 11 deletions src/services/blocks/BlocksService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApiPromise } from '@polkadot/api';
import { Struct } from '@polkadot/types';
import { GenericCall } from '@polkadot/types';
import { GenericCall, Struct } from '@polkadot/types';
import {
AccountId,
Block,
Expand All @@ -10,7 +9,7 @@ import {
EventRecord,
Hash,
} from '@polkadot/types/interfaces';
import { AnyJson, Codec } from '@polkadot/types/types';
import { AnyJson, Codec, Registry } from '@polkadot/types/types';
import { u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
import { CalcFee } from '@substrate/calc';
Expand Down Expand Up @@ -221,7 +220,7 @@ export class BlocksService extends AbstractService {
},
signature: isSigned ? { signature, signer } : null,
nonce: isSigned ? nonce : null,
args: this.parseGenericCall(method).args,
args: this.parseGenericCall(method, block.registry).args,
tip: isSigned ? tip : null,
hash,
info: {},
Expand Down Expand Up @@ -394,13 +393,15 @@ export class BlocksService extends AbstractService {
* Helper function for `parseGenericCall`.
*
* @param argsArray array of `Codec` values
* @param registry type registry of the block the call belongs to
*/
private parseArrayGenericCalls(
argsArray: Codec[]
argsArray: Codec[],
registry: Registry
): (Codec | ISanitizedCall)[] {
return argsArray.map((argument) => {
if (argument instanceof GenericCall) {
return this.parseGenericCall(argument);
return this.parseGenericCall(argument, registry);
}

return argument;
Expand All @@ -413,8 +414,12 @@ export class BlocksService extends AbstractService {
* call index). Parses `GenericCall`s that are nested as arguments.
*
* @param genericCall `GenericCall`
* @param registry type registry of the block the call belongs to
*/
private parseGenericCall(genericCall: GenericCall): ISanitizedCall {
private parseGenericCall(
genericCall: GenericCall,
registry: Registry
): ISanitizedCall {
const { sectionName, methodName } = genericCall;
const newArgs = {};

Expand All @@ -428,17 +433,23 @@ export class BlocksService extends AbstractService {
const argument = callArgs.get(paramName);

if (Array.isArray(argument)) {
newArgs[paramName] = this.parseArrayGenericCalls(argument);
newArgs[paramName] = this.parseArrayGenericCalls(
argument,
registry
);
} else if (argument instanceof GenericCall) {
newArgs[paramName] = this.parseGenericCall(argument);
newArgs[paramName] = this.parseGenericCall(
argument,
registry
);
} else if (
paramName === 'call' &&
argument?.toRawType() === 'Bytes'
) {
// multiSig.asMulti.args.call is an OpaqueCall (Vec<u8>) that we
// serialize to a polkadot-js Call and parse so it is not a hex blob.
const call = this.api.createType('Call', argument.toHex());
newArgs[paramName] = this.parseGenericCall(call);
const call = registry.createType('Call', argument.toHex());
newArgs[paramName] = this.parseGenericCall(call, registry);
} else {
newArgs[paramName] = argument;
}
Expand Down
33 changes: 22 additions & 11 deletions src/services/v0/v0blocks/BlocksService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApiPromise } from '@polkadot/api';
import { Struct } from '@polkadot/types';
import { GenericCall } from '@polkadot/types';
import { GenericCall, Struct } from '@polkadot/types';
import {
AccountId,
Block,
Expand All @@ -10,7 +9,7 @@ import {
EventRecord,
Hash,
} from '@polkadot/types/interfaces';
import { AnyJson, Codec } from '@polkadot/types/types';
import { AnyJson, Codec, Registry } from '@polkadot/types/types';
import { u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
import { CalcFee } from '@substrate/calc';
Expand Down Expand Up @@ -201,7 +200,7 @@ export class BlocksService extends AbstractService {
method: `${method.sectionName}.${method.methodName}`,
signature: isSigned ? { signature, signer } : null,
nonce,
args: this.parseGenericCall(method).args,
args: this.parseGenericCall(method, block.registry).args,
tip,
hash,
info: {},
Expand Down Expand Up @@ -361,13 +360,15 @@ export class BlocksService extends AbstractService {
* Helper function for `parseGenericCall`.
*
* @param argsArray array of `Codec` values
* @param registry type registry of the block the call belongs to
*/
private parseArrayGenericCalls(
argsArray: Codec[]
argsArray: Codec[],
registry: Registry
): (Codec | ISanitizedCall)[] {
return argsArray.map((argument) => {
if (argument instanceof GenericCall) {
return this.parseGenericCall(argument);
return this.parseGenericCall(argument, registry);
}

return argument;
Expand All @@ -380,8 +381,12 @@ export class BlocksService extends AbstractService {
* call index). Parses `GenericCall`s that are nested as arguments.
*
* @param genericCall `GenericCall`
* @param registry type registry of the block the call belongs to
*/
private parseGenericCall(genericCall: GenericCall): ISanitizedCall {
private parseGenericCall(
genericCall: GenericCall,
registry: Registry
): ISanitizedCall {
const { sectionName, methodName, callIndex } = genericCall;
const newArgs = {};

Expand All @@ -395,17 +400,23 @@ export class BlocksService extends AbstractService {
const argument = callArgs.get(paramName);

if (Array.isArray(argument)) {
newArgs[paramName] = this.parseArrayGenericCalls(argument);
newArgs[paramName] = this.parseArrayGenericCalls(
argument,
registry
);
} else if (argument instanceof GenericCall) {
newArgs[paramName] = this.parseGenericCall(argument);
newArgs[paramName] = this.parseGenericCall(
argument,
registry
);
} else if (
paramName === 'call' &&
argument?.toRawType() === 'Bytes'
) {
// multiSig.asMulti.args.call is an OpaqueCall (Vec<u8>) that we
// serialize to a polkadot-js Call and parse so it is not a hex blob.
const call = this.api.createType('Call', argument.toHex());
newArgs[paramName] = this.parseGenericCall(call);
const call = registry.createType('Call', argument.toHex());
newArgs[paramName] = this.parseGenericCall(call, registry);
} else {
newArgs[paramName] = argument;
}
Expand Down

0 comments on commit b4678e1

Please sign in to comment.