Fix generation of well-known keys (#3452)

* Fix generation of well-known keys

* CHANGELOG

* Linting, unfiy decorate params

* Adjust
This commit is contained in:
Jaco
2021-04-27 14:05:59 +02:00
committed by GitHub
parent debecde50f
commit 30c98ef857
14 changed files with 53 additions and 28 deletions
+2 -1
View File
@@ -4,7 +4,8 @@
Changes: Changes:
- De-alias XCmOutcome (used in multiple pallettes) - De-alias xcm `Outcome` (used in multiple pallettes)
- Fix generate of well-known storage keys (e.g. `:code`)
## 4.7.2 Apr 26, 2021 ## 4.7.2 Apr 26, 2021
@@ -17,7 +17,7 @@ function init (meta: string): [Constants, TypeRegistry] {
registry.setMetadata(metadata); registry.setMetadata(metadata);
return [decorateConstants(registry, metadata.asLatest), registry]; return [decorateConstants(registry, metadata.asLatest, 12), registry];
} }
describe('decorateConstants', (): void => { describe('decorateConstants', (): void => {
@@ -8,7 +8,8 @@ import type { ConstantCodec, Constants, ModuleConstants } from '../types';
import { hexToU8a, stringCamelCase } from '@polkadot/util'; import { hexToU8a, stringCamelCase } from '@polkadot/util';
/** @internal */ /** @internal */
export function decorateConstants (registry: Registry, { modules }: MetadataLatest): Constants { // eslint-disable-next-line @typescript-eslint/no-unused-vars
export function decorateConstants (registry: Registry, { modules }: MetadataLatest, _metaVersion: number): Constants {
return modules.reduce((result: Constants, { constants, name }): Constants => { return modules.reduce((result: Constants, { constants, name }): Constants => {
if (constants.isEmpty) { if (constants.isEmpty) {
return result; return result;
+1 -1
View File
@@ -46,7 +46,7 @@ describe('Decorated', () => {
}); });
it('should return constants with the correct type and value', (): void => { it('should return constants with the correct type and value', (): void => {
const consts = decorateConstants(registry, metadata.asLatest); const consts = decorateConstants(registry, metadata.asLatest, metadata.version);
expect(consts.democracy.cooloffPeriod).toBeInstanceOf(registry.createClass('BlockNumber')); expect(consts.democracy.cooloffPeriod).toBeInstanceOf(registry.createClass('BlockNumber'));
expect(consts.democracy.cooloffPeriod.toHex()).toEqual('0x000c4e00'); expect(consts.democracy.cooloffPeriod.toHex()).toEqual('0x000c4e00');
+6 -5
View File
@@ -20,13 +20,14 @@ export function expandMetadata (registry: Registry, metadata: Metadata): Decorat
assert(metadata instanceof Metadata, 'You need to pass a valid Metadata instance to Decorated'); assert(metadata instanceof Metadata, 'You need to pass a valid Metadata instance to Decorated');
const latest = metadata.asLatest; const latest = metadata.asLatest;
const version = metadata.version;
return { return {
consts: decorateConstants(registry, latest), consts: decorateConstants(registry, latest, version),
errors: decorateErrors(registry, latest, metadata.version), errors: decorateErrors(registry, latest, version),
events: decorateEvents(registry, latest, metadata.version), events: decorateEvents(registry, latest, version),
query: decorateStorage(registry, latest, metadata.version), query: decorateStorage(registry, latest, version),
tx: decorateExtrinsics(registry, latest, metadata.version) tx: decorateExtrinsics(registry, latest, version)
}; };
} }
@@ -28,7 +28,7 @@ describe('createFunction', (): void => {
method: 'NextKeys', method: 'NextKeys',
prefix: 'Session', prefix: 'Session',
section: 'session' section: 'session'
}, { metaVersion: 9 }); }, {});
expect( expect(
u8aToHex( u8aToHex(
@@ -9,15 +9,14 @@ import BN from 'bn.js';
import { Raw } from '@polkadot/types/codec'; import { Raw } from '@polkadot/types/codec';
import { StorageKey } from '@polkadot/types/primitive'; import { StorageKey } from '@polkadot/types/primitive';
import { assert, compactAddLength, compactStripLength, isNull, isUndefined, stringLowerFirst, u8aConcat } from '@polkadot/util'; import { assert, compactAddLength, compactStripLength, isNull, isUndefined, stringLowerFirst, u8aConcat, u8aToU8a } from '@polkadot/util';
import { xxhashAsU8a } from '@polkadot/util-crypto'; import { xxhashAsU8a } from '@polkadot/util-crypto';
import { getHasher, HasherFunction } from './getHasher'; import { getHasher, HasherFunction } from './getHasher';
export interface CreateItemOptions { export interface CreateItemOptions {
key?: string; key?: string;
metaVersion: number; skipHashing?: boolean;
skipHashing?: boolean; // We don't hash the keys defined in ./substrate.ts
} }
export interface CreateItemFn { export interface CreateItemFn {
@@ -35,7 +34,6 @@ interface IterFn {
type CreateArgType = boolean | string | number | null | BN | BigInt | Uint8Array | Codec; type CreateArgType = boolean | string | number | null | BN | BigInt | Uint8Array | Codec;
const EMPTY_U8A = new Uint8Array([]); const EMPTY_U8A = new Uint8Array([]);
const NULL_HASHER = (value: Uint8Array): Uint8Array => value;
// get the hashers, the base (and in the case of DoubleMap), the second key // get the hashers, the base (and in the case of DoubleMap), the second key
/** @internal */ /** @internal */
@@ -186,7 +184,9 @@ export function createFunction (registry: Registry, itemFn: CreateItemFn, option
const storageFn = expandWithMeta(itemFn, (arg?: CreateArgType | [CreateArgType?, CreateArgType?]): Uint8Array => const storageFn = expandWithMeta(itemFn, (arg?: CreateArgType | [CreateArgType?, CreateArgType?]): Uint8Array =>
type.isDoubleMap type.isDoubleMap
? createKeyDoubleMap(registry, itemFn, arg as [CreateArgType, CreateArgType], [hasher, key2Hasher]) ? createKeyDoubleMap(registry, itemFn, arg as [CreateArgType, CreateArgType], [hasher, key2Hasher])
: createKey(registry, itemFn, arg as CreateArgType, options.skipHashing ? NULL_HASHER : hasher) : options.skipHashing
? compactAddLength(u8aToU8a(options.key))
: createKey(registry, itemFn, arg as CreateArgType, hasher)
); );
if (type.isMap || type.isDoubleMap) { if (type.isMap || type.isDoubleMap) {
@@ -2,19 +2,21 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { TypeRegistry } from '@polkadot/types/create'; import { TypeRegistry } from '@polkadot/types/create';
import { compactAddLength, u8aToU8a } from '@polkadot/util';
import { getStorage } from './getStorage'; import { getStorage } from './getStorage';
describe('getSorage', (): void => { describe('getSorage', (): void => {
const registry = new TypeRegistry(); const registry = new TypeRegistry();
const storage = getStorage(registry, 8); const storage = getStorage(registry);
it('should return well known keys', (): void => { it('should return well known keys', (): void => {
expect(typeof storage.substrate).toBe('object'); expect(typeof storage.substrate).toBe('object');
expect(storage.substrate.code()).toEqual(compactAddLength(u8aToU8a(':code')));
expect(storage.substrate.changesTrieConfig).toBeTruthy(); expect(storage.substrate.changesTrieConfig).toBeTruthy();
expect(storage.substrate.childStorageKeyPrefix).toBeTruthy(); expect(storage.substrate.childStorageKeyPrefix).toBeTruthy();
expect(storage.substrate.code).toBeTruthy();
expect(storage.substrate.extrinsicIndex).toBeTruthy(); expect(storage.substrate.extrinsicIndex).toBeTruthy();
expect(storage.substrate.heapPages).toBeTruthy(); expect(storage.substrate.heapPages).toBeTruthy();
}); });
@@ -8,12 +8,12 @@ import type { Storage } from '../types';
import { substrate } from './substrate'; import { substrate } from './substrate';
/** @internal */ /** @internal */
export function getStorage (registry: Registry, metaVersion: number): Storage { export function getStorage (registry: Registry): Storage {
return { return {
substrate: Object substrate: Object
.entries(substrate) .entries(substrate)
.reduce((storage: Record<string, StorageEntry>, [key, fn]): Record<string, StorageEntry> => { .reduce((storage: Record<string, StorageEntry>, [key, fn]): Record<string, StorageEntry> => {
(storage as Record<string, unknown>)[key] = fn(registry, metaVersion); (storage as Record<string, unknown>)[key] = fn(registry);
return storage; return storage;
}, {}) }, {})
@@ -11,7 +11,8 @@ import { createFunction } from './createFunction';
import { getStorage } from './getStorage'; import { getStorage } from './getStorage';
/** @internal */ /** @internal */
export function decorateStorage (registry: Registry, { modules }: MetadataLatest, metaVersion: number): Storage { // eslint-disable-next-line @typescript-eslint/no-unused-vars
export function decorateStorage (registry: Registry, { modules }: MetadataLatest, _metaVersion: number): Storage {
return modules.reduce((result: Storage, moduleMetadata): Storage => { return modules.reduce((result: Storage, moduleMetadata): Storage => {
if (moduleMetadata.storage.isNone) { if (moduleMetadata.storage.isNone) {
return result; return result;
@@ -31,11 +32,11 @@ export function decorateStorage (registry: Registry, { modules }: MetadataLatest
method, method,
prefix, prefix,
section section
}, { metaVersion }); }, {});
return newModule; return newModule;
}, {} as ModuleStorage); }, {} as ModuleStorage);
return result; return result;
}, { ...getStorage(registry, metaVersion) }); }, { ...getStorage(registry) });
} }
@@ -0,0 +1,19 @@
// Copyright 2017-2021 @polkadot/metadata authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { TypeRegistry } from '@polkadot/types/create';
import { compactAddLength, u8aToU8a } from '@polkadot/util';
import { substrate } from './substrate';
const registry = new TypeRegistry();
describe('substrate', (): void => {
it('creates a well-known :code key', (): void => {
expect(
substrate.code(registry)()
).toEqual(
compactAddLength(u8aToU8a(':code'))
);
});
});
@@ -12,12 +12,12 @@ interface SubstrateMetadata {
type: string; type: string;
} }
type Creator = (registry: Registry, metaVersion: number) => StorageEntry; type Creator = (registry: Registry) => StorageEntry;
// Small helper function to factorize code on this page. // Small helper function to factorize code on this page.
/** @internal */ /** @internal */
function createRuntimeFunction (method: string, key: string, { documentation, type }: SubstrateMetadata): (registry: Registry, metaVersion: number) => StorageEntry { function createRuntimeFunction (method: string, key: string, { documentation, type }: SubstrateMetadata): (registry: Registry) => StorageEntry {
return (registry: Registry, metaVersion: number): StorageEntry => return (registry: Registry): StorageEntry =>
createFunction(registry, { createFunction(registry, {
meta: { meta: {
documentation: registry.createType('Vec<Text>', [documentation]), documentation: registry.createType('Vec<Text>', [documentation]),
@@ -28,7 +28,7 @@ function createRuntimeFunction (method: string, key: string, { documentation, ty
method, method,
prefix: 'Substrate', prefix: 'Substrate',
section: 'substrate' section: 'substrate'
}, { key, metaVersion, skipHashing: true }); }, { key, skipHashing: true });
} }
export const substrate: Record<string, Creator> = { export const substrate: Record<string, Creator> = {
+1 -1
View File
@@ -195,7 +195,7 @@ function addConstants (metadata: MetadataLatest): string {
/** @internal */ /** @internal */
function addStorage (metadata: MetadataLatest): string { function addStorage (metadata: MetadataLatest): string {
const { substrate } = getSubstrateStorage(metadata.registry, 12); const { substrate } = getSubstrateStorage(metadata.registry);
const moduleSections = metadata.modules const moduleSections = metadata.modules
.sort(sortByName) .sort(sortByName)
.filter((moduleMetadata) => !moduleMetadata.storage.isNone) .filter((moduleMetadata) => !moduleMetadata.storage.isNone)
+1 -1
View File
@@ -97,7 +97,7 @@ function injectExtrinsics (registry: Registry, metadata: Metadata, metadataCalls
// extract additional properties from the metadata // extract additional properties from the metadata
function extractProperties (registry: Registry, metadata: Metadata): ChainProperties | undefined { function extractProperties (registry: Registry, metadata: Metadata): ChainProperties | undefined {
const original = registry.getChainProperties(); const original = registry.getChainProperties();
const constants = decorateConstants(registry, metadata.asLatest); const constants = decorateConstants(registry, metadata.asLatest, metadata.version);
const ss58Format = constants.system?.ss58Prefix; const ss58Format = constants.system?.ss58Prefix;
if (!ss58Format) { if (!ss58Format) {