Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for configurable hashers #2503

Merged
merged 1 commit into from
Aug 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Add types for the new `proposeParachain` module (as per Rococo)
- Adjust `Address` <-> `LookupSource` definitions (no external impact, both in existence)
- Add Ethereum-compatible `Ethereum{AccountId, LookupSource}` types, underlying `H160`
- Allow for configurable hashers via `registry.setHasher(...)` (defaults to `blake2AsU8a`)

## 1.29.1 Aug 17, 2020

Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/AbstractArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { H256 } from '../interfaces/runtime';
import { AnyJson, Codec, Registry } from '../types';

import { u8aConcat, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Compact from './Compact';
import Raw from './Raw';
Expand Down Expand Up @@ -41,7 +40,7 @@ export default abstract class AbstractArray<T extends Codec> extends Array<T> im
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/AbstractInt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { AnyNumber, Codec, Registry } from '../types';

import BN from 'bn.js';
import { BN_ZERO, assert, bnToBn, bnToHex, bnToU8a, formatBalance, formatNumber, hexToBn, isHex, isString, isU8a, u8aToBn } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Raw from './Raw';

Expand Down Expand Up @@ -92,7 +91,7 @@ export default abstract class AbstractInt extends BN implements Codec {
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/BTreeSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { H256 } from '../interfaces/runtime';
import { AnyJson, Constructor, Codec, InterfaceTypes, Registry } from '../types';

import { isHex, hexToU8a, isU8a, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Compact from './Compact';
import Raw from './Raw';
Expand Down Expand Up @@ -117,7 +116,7 @@ export default class BTreeSet<V extends Codec = Codec> extends Set<V> implements
* @description Returns a hash of the value
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
4 changes: 1 addition & 3 deletions packages/types/src/codec/Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import { H256 } from '../interfaces/runtime';
import { AnyJson, BareOpts, Codec, Registry } from '../types';

import { blake2AsU8a } from '@polkadot/util-crypto';

import Raw from './Raw';

/**
Expand Down Expand Up @@ -34,7 +32,7 @@ export default abstract class Base<T extends Codec> implements Codec {
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/Compact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { AnyJson, AnyNumber, Codec, Constructor, ICompact, InterfaceTypes, Regis
import BN from 'bn.js';
import { compactAddLength, compactFromU8a, compactStripLength, compactToU8a, isBigInt, isBn, isNumber, isString } from '@polkadot/util';
import { DEFAULT_BITLENGTH } from '@polkadot/util/compact/defaults';
import { blake2AsU8a } from '@polkadot/util-crypto';

import typeToConstructor from './utils/typeToConstructor';
import { UIntBitLength } from './AbstractInt';
Expand Down Expand Up @@ -90,7 +89,7 @@ export default class Compact<T extends CompactEncodable> implements ICompact<T>
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/Date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { AnyNumber, Codec, Registry } from '../types';

import BN from 'bn.js';
import { bnToBn, bnToHex, bnToU8a, isString, isU8a, u8aToBn } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import { UIntBitLength } from './AbstractInt';

Expand Down Expand Up @@ -58,7 +57,7 @@ export default class CodecDate extends Date implements Codec {
* @description returns a hash of the contents
*/
public get hash (): H256 {
return this.registry.createType('H256', blake2AsU8a(this.toU8a(), 256));
return this.registry.createType('H256', this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/Enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { H256 } from '@polkadot/types/interfaces';
import { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';

import { assert, hexToU8a, isHex, isNumber, isObject, isString, isU8a, isUndefined, stringCamelCase, stringUpperFirst, u8aConcat, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Null from '../primitive/Null';
import { mapToTypeMap } from './utils';
Expand Down Expand Up @@ -188,7 +187,7 @@ export default class Enum implements Codec {
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/Map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { H256 } from '../interfaces/runtime';
import { AnyJson, Constructor, Codec, InterfaceTypes, Registry } from '../types';

import { isHex, hexToU8a, isObject, isU8a, u8aConcat, u8aToHex, u8aToU8a } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Compact from './Compact';
import Raw from './Raw';
Expand Down Expand Up @@ -126,7 +125,7 @@ export default class CodecMap<K extends Codec = Codec, V extends Codec = Codec>
* @description Returns a hash of the value
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/Option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { H256 } from '@polkadot/types/interfaces';
import { AnyJson, Codec, Constructor, InterfaceTypes, Registry } from '../types';

import { isNull, isU8a, isUndefined, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Null from '../primitive/Null';
import { typeToConstructor } from './utils';
Expand Down Expand Up @@ -83,7 +82,7 @@ export default class Option<T extends Codec> implements Codec {
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/Raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { H256 } from '../interfaces/runtime';
import { AnyJson, AnyU8a, IU8a, Registry } from '../types';

import { assert, isAscii, isU8a, isUndefined, isUtf8, u8aToHex, u8aToString, u8aToU8a } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

/** @internal */
function decodeU8a (value?: any): Uint8Array {
Expand Down Expand Up @@ -46,7 +45,7 @@ export default class Raw extends Uint8Array implements IU8a {
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/Set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Codec, Constructor, Registry } from '../types';

import BN from 'bn.js';
import { assert, bnToBn, bnToU8a, isBn, isU8a, isNumber, isString, isUndefined, stringCamelCase, stringUpperFirst, u8aToHex, u8aToBn, u8aToU8a } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Raw from './Raw';
import { compareArray } from './utils';
Expand Down Expand Up @@ -127,7 +126,7 @@ export default class CodecSet extends Set<string> implements Codec {
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/Struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { H256 } from '../interfaces/runtime';
import { AnyJson, BareOpts, Codec, Constructor, ConstructorDef, InterfaceTypes, Registry } from '../types';

import { hexToU8a, isBoolean, isFunction, isHex, isObject, isU8a, isUndefined, u8aConcat, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Raw from './Raw';
import { compareMap, decodeU8a, mapToTypeMap } from './utils';
Expand Down Expand Up @@ -198,7 +197,7 @@ export default class Struct<
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/types/src/codec/StructAny.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { H256 } from '../interfaces/runtime';
import { AnyJson, Codec, Registry } from '../types';

import { isUndefined } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Raw from './Raw';

Expand Down Expand Up @@ -61,7 +60,7 @@ export default class StructAny extends Map<string, any> implements Codec {
* @description returns a hash of the contents
*/
public get hash (): H256 {
return new Raw(this.registry, blake2AsU8a(this.toU8a(), 256));
return new Raw(this.registry, this.registry.hash(this.toU8a()));
}

/**
Expand Down
29 changes: 28 additions & 1 deletion packages/types/src/create/registry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

import { Codec, Constructor } from '../types';

import { isChildClass } from '@polkadot/util';
import { isChildClass, u8aToU8a } from '@polkadot/util';
import { keccakAsU8a } from '@polkadot/util-crypto';

import Struct from '../codec/Struct';
import DoNotConstruct from '../primitive/DoNotConstruct';
Expand Down Expand Up @@ -159,4 +160,30 @@ describe('TypeRegistry', (): void => {
expect(struct.bar.toString()).toEqual('testing');
});
});

it('hashes via blake2 by default', (): void => {
expect(
registry.hash(u8aToU8a('abc'))
).toEqual(
new Uint8Array([189, 221, 129, 60, 99, 66, 57, 114, 49, 113, 239, 63, 238, 152, 87, 155, 148, 150, 78, 59, 177, 203, 62, 66, 114, 98, 200, 192, 104, 213, 35, 25])
);
});

it('hashes via override hasher', (): void => {
registry.setHasher(keccakAsU8a);

expect(
registry.hash(u8aToU8a('test value'))
).toEqual(
u8aToU8a('0x2d07364b5c231c56ce63d49430e085ea3033c750688ba532b24029124c26ca5e')
);

registry.setHasher();

expect(
registry.hash(u8aToU8a('abc'))
).toEqual(
new Uint8Array([189, 221, 129, 60, 99, 66, 57, 114, 49, 113, 239, 63, 238, 152, 87, 155, 148, 150, 78, 59, 177, 203, 62, 66, 114, 98, 200, 192, 104, 213, 35, 25])
);
});
});
11 changes: 11 additions & 0 deletions packages/types/src/create/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CallFunction, Codec, Constructor, InterfaceTypes, RegistryError, Regist

import extrinsicsFromMeta from '@polkadot/metadata/Decorated/extrinsics/fromMetadata';
import { assert, formatBalance, isFunction, isString, isU8a, isUndefined, stringCamelCase, u8aToHex } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';

import Raw from '../codec/Raw';
import { defaultExtensions, expandExtensionTypes, findUnknownExtensions } from '../extrinsic/signedExtensions';
Expand Down Expand Up @@ -94,6 +95,8 @@ export class TypeRegistry implements Registry {

#chainProperties?: ChainProperties;

#hasher: (data: Uint8Array) => Uint8Array = blake2AsU8a;

#knownTypes: RegisteredTypes = {};

#signedExtensions: string[] = defaultExtensions;
Expand Down Expand Up @@ -271,6 +274,10 @@ export class TypeRegistry implements Registry {
return !this.#unknownTypes.get(name) && (this.hasClass(name) || this.hasDef(name));
}

public hash (data: Uint8Array): Uint8Array {
return this.#hasher(data);
}

public register (type: Constructor | RegistryTypes): void;

// eslint-disable-next-line no-dupe-class-members
Expand Down Expand Up @@ -317,6 +324,10 @@ export class TypeRegistry implements Registry {
}
}

setHasher (hasher: (data: Uint8Array) => Uint8Array = blake2AsU8a): void {
this.#hasher = hasher;
}

setKnownTypes (knownTypes: RegisteredTypes): void {
this.#knownTypes = knownTypes;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/types/src/extrinsic/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
// of the Apache-2.0 license. See the LICENSE file for details.

import { SignOptions } from '@polkadot/keyring/types';
import { IKeyringPair } from '../types';
import { IKeyringPair, Registry } from '../types';

import { blake2AsU8a } from '@polkadot/util-crypto';

// a helper function for both types of payloads, Raw and metadata-known
export function sign (signerPair: IKeyringPair, u8a: Uint8Array, options?: SignOptions): Uint8Array {
export function sign (registry: Registry, signerPair: IKeyringPair, u8a: Uint8Array, options?: SignOptions): Uint8Array {
const encoded = u8a.length > 256
? blake2AsU8a(u8a)
: u8a;
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/extrinsic/v1/ExtrinsicPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,6 @@ export default class ExtrinsicPayloadV1 extends Struct {
* @description Sign the payload with the keypair
*/
public sign (signerPair: IKeyringPair): Uint8Array {
return sign(signerPair, this.toU8a({ method: true }));
return sign(this.registry, signerPair, this.toU8a({ method: true }));
}
}
4 changes: 1 addition & 3 deletions packages/types/src/extrinsic/v1/ExtrinsicSignature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { Address, Balance, Call, Index } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../types';
import { ExtrinsicSignatureOptions } from '../types';

import { blake2AsU8a } from '@polkadot/util-crypto';

import Compact from '../../codec/Compact';
import Struct from '../../codec/Struct';
import { EMPTY_U8A, IMMORTAL_ERA } from '../constants';
Expand Down Expand Up @@ -143,7 +141,7 @@ export default class ExtrinsicSignatureV1 extends Struct implements IExtrinsicSi
*/
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
const address = account.publicKey.length > 32
? blake2AsU8a(account.publicKey, 256)
? this.registry.hash(account.publicKey)
: account.publicKey;
const signer = this.registry.createType('Address', address);
const payload = this.createPayload(method, options);
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/extrinsic/v2/ExtrinsicPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ export default class ExtrinsicPayloadV2 extends Struct {
* @description Sign the payload with the keypair
*/
public sign (signerPair: IKeyringPair): Uint8Array {
return sign(signerPair, this.toU8a({ method: true }));
return sign(this.registry, signerPair, this.toU8a({ method: true }));
}
}
4 changes: 1 addition & 3 deletions packages/types/src/extrinsic/v2/ExtrinsicSignature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { Address, Balance, Call, Index } from '../../interfaces/runtime';
import { ExtrinsicPayloadValue, IExtrinsicSignature, IKeyringPair, Registry, SignatureOptions } from '../../types';
import { ExtrinsicSignatureOptions } from '../types';

import { blake2AsU8a } from '@polkadot/util-crypto';

import Compact from '../../codec/Compact';
import Struct from '../../codec/Struct';
import { EMPTY_U8A, IMMORTAL_ERA } from '../constants';
Expand Down Expand Up @@ -139,7 +137,7 @@ export default class ExtrinsicSignatureV2 extends Struct implements IExtrinsicSi
*/
public sign (method: Call, account: IKeyringPair, options: SignatureOptions): IExtrinsicSignature {
const address = account.publicKey.length > 32
? blake2AsU8a(account.publicKey, 256)
? this.registry.hash(account.publicKey)
: account.publicKey;
const signer = this.registry.createType('Address', address);
const payload = this.createPayload(method, options);
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/extrinsic/v3/ExtrinsicPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@ export default class ExtrinsicPayloadV3 extends Struct {
* @description Sign the payload with the keypair
*/
public sign (signerPair: IKeyringPair): Uint8Array {
return sign(signerPair, this.toU8a({ method: true }));
return sign(this.registry, signerPair, this.toU8a({ method: true }));
}
}
Loading