From 83d0121a282cec70af2f6d78f76ae8d1109c9062 Mon Sep 17 00:00:00 2001 From: Jaco Date: Fri, 13 May 2022 10:19:20 +0200 Subject: [PATCH] Additional deprecations (#1488) * Additional deprecations * Unsigned shift * Adjust * offset calc --- packages/util/src/bi/toU8a.ts | 10 ++---- packages/util/src/bn/toBn.ts | 10 +++--- packages/util/src/bn/toHex.spec.ts | 2 +- packages/util/src/bn/toHex.ts | 2 ++ packages/util/src/bn/toU8a.ts | 40 ++++++++++------------- packages/util/src/compact/fromU8a.spec.ts | 14 ++++++++ packages/util/src/compact/fromU8a.ts | 18 +++++----- packages/util/src/compact/toU8a.ts | 6 ++-- packages/util/src/u8a/toU8a.ts | 8 ++--- 9 files changed, 59 insertions(+), 51 deletions(-) diff --git a/packages/util/src/bi/toU8a.ts b/packages/util/src/bi/toU8a.ts index 3fcfad2c6..76b85bc45 100644 --- a/packages/util/src/bi/toU8a.ts +++ b/packages/util/src/bi/toU8a.ts @@ -13,12 +13,6 @@ import { nToBigInt } from './toBigInt'; const DIV = BigInt(256); const NEG_MASK = BigInt(0xff); -function createEmpty ({ bitLength = 0 }: NumberOptions): Uint8Array { - return bitLength === -1 - ? new Uint8Array() - : new Uint8Array(Math.ceil(bitLength / 8)); -} - function toU8a (value: bigint, { isLe, isNegative }: NumberOptions): Uint8Array { const arr: number[] = []; @@ -59,7 +53,9 @@ export function nToU8a (value?: ExtToBn | BN | const valueBi = nToBigInt(value); if (valueBi === _0n) { - return createEmpty(opts); + return opts.bitLength === -1 + ? new Uint8Array() + : new Uint8Array(Math.ceil((opts.bitLength || 0) / 8)); } const u8a = toU8a(valueBi, opts); diff --git a/packages/util/src/bn/toBn.ts b/packages/util/src/bn/toBn.ts index 9a34983fe..14995adcd 100644 --- a/packages/util/src/bn/toBn.ts +++ b/packages/util/src/bn/toBn.ts @@ -27,10 +27,9 @@ import { BN } from './bn'; * ``` */ export function bnToBn (value?: HexString | ExtToBn | BN | bigint | string | number | null): BN { - return BN.isBN(value) - ? value - : !value - ? new BN(0) + return value + ? BN.isBN(value) + ? value : isHex(value) ? hexToBn(value.toString()) : isBigInt(value) @@ -39,5 +38,6 @@ export function bnToBn (value?: HexString | Ex ? value.toBn() : isToBigInt(value) ? new BN(value.toBigInt().toString()) - : new BN(value); + : new BN(value) + : new BN(0); } diff --git a/packages/util/src/bn/toHex.spec.ts b/packages/util/src/bn/toHex.spec.ts index 7a50c66fb..54c20f4f4 100644 --- a/packages/util/src/bn/toHex.spec.ts +++ b/packages/util/src/bn/toHex.spec.ts @@ -46,7 +46,7 @@ describe('bnToHex', (): void => { ).toBe('0xfffffb2e'); }); - it('handles backwards compatibility', (): void => { + it('handles legacy compatibility', (): void => { expect( bnToHex(new BN(1234), 32) ).toBe( diff --git a/packages/util/src/bn/toHex.ts b/packages/util/src/bn/toHex.ts index b191818f9..cc3dc81dc 100644 --- a/packages/util/src/bn/toHex.ts +++ b/packages/util/src/bn/toHex.ts @@ -28,7 +28,9 @@ const DEFAULT_OPTS: NumberOptions = { bitLength: -1, isLe: false, isNegative: fa * ``` */ function bnToHex (value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions): HexString; +/** @deprecated Use bnToHex (value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */ function bnToHex (value?: ExtToBn | BN | bigint | number | null, bitLength?: number, isLe?: boolean): HexString; +/** @deprecated Use bnToHex (value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */ function bnToHex (value?: ExtToBn | BN | bigint | number | null, arg1: number | NumberOptions = DEFAULT_OPTS, arg2?: boolean): HexString { return !value ? ZERO_STR diff --git a/packages/util/src/bn/toU8a.ts b/packages/util/src/bn/toU8a.ts index c3288e6d8..a1c597014 100644 --- a/packages/util/src/bn/toU8a.ts +++ b/packages/util/src/bn/toU8a.ts @@ -10,23 +10,6 @@ import { bnToBn } from './toBn'; const DEFAULT_OPTS: NumberOptions = { bitLength: -1, isLe: true, isNegative: false }; -function createEmpty (byteLength: number, options: NumberOptions): Uint8Array { - return options.bitLength === -1 - ? new Uint8Array() - : new Uint8Array(byteLength); -} - -function createValue (valueBn: BN, byteLength: number, { isLe, isNegative }: NumberOptions): Uint8Array { - const output = new Uint8Array(byteLength); - const bn = isNegative - ? valueBn.toTwos(byteLength * 8) - : valueBn; - - output.set(bn.toArray(isLe ? 'le' : 'be', byteLength), 0); - - return output; -} - /** * @name bnToU8a * @summary Creates a Uint8Array object from a BN. @@ -46,7 +29,7 @@ function bnToU8a (value?: ExtToBn | BN | bigint | number function bnToU8a (value?: ExtToBn | BN | bigint | number | null, bitLength?: number, isLe?: boolean): Uint8Array; /** @deprecated Use bnToU8a(value?: ExtToBn | BN | bigint | number | null, options?: NumberOptions) */ function bnToU8a (value?: ExtToBn | BN | bigint | number | null, arg1: number | NumberOptions = DEFAULT_OPTS, arg2?: boolean): Uint8Array { - const options: NumberOptions = objectSpread( + const { bitLength, isLe, isNegative }: NumberOptions = objectSpread( { bitLength: -1, isLe: true, isNegative: false }, isNumber(arg1) ? { bitLength: arg1, isLe: arg2 } @@ -54,13 +37,24 @@ function bnToU8a (value?: ExtToBn | BN | bigint | number ); const valueBn = bnToBn(value); - const byteLength = options.bitLength === -1 + const byteLength = bitLength === -1 ? Math.ceil(valueBn.bitLength() / 8) - : Math.ceil((options.bitLength || 0) / 8); + : Math.ceil((bitLength || 0) / 8); - return value - ? createValue(valueBn, byteLength, options) - : createEmpty(byteLength, options); + if (!value) { + return bitLength === -1 + ? new Uint8Array() + : new Uint8Array(byteLength); + } + + const output = new Uint8Array(byteLength); + const bn = isNegative + ? valueBn.toTwos(byteLength * 8) + : valueBn; + + output.set(bn.toArray(isLe ? 'le' : 'be', byteLength), 0); + + return output; } export { bnToU8a }; diff --git a/packages/util/src/compact/fromU8a.spec.ts b/packages/util/src/compact/fromU8a.spec.ts index 4be95136f..1eda48384 100644 --- a/packages/util/src/compact/fromU8a.spec.ts +++ b/packages/util/src/compact/fromU8a.spec.ts @@ -3,6 +3,7 @@ import { BN } from '../bn/bn'; import { hexToU8a } from '../hex/toU8a'; +import { performance } from '../test/performance'; import { compactFromU8a } from '.'; describe('compactFromU8a', (): void => { @@ -28,6 +29,14 @@ describe('compactFromU8a', (): void => { ); }); + it('decodes from same u32 encoded value (short)', (): void => { + expect( + compactFromU8a(new Uint8Array([254, 255, 255, 255])).toString() + ).toEqual( + [4, new BN(1073741823)].toString() + ); + }); + it('decodes from same u32 encoded value (full)', (): void => { expect( compactFromU8a(new Uint8Array([3, 249, 255, 255, 255])) @@ -55,4 +64,9 @@ describe('compactFromU8a', (): void => { )[1].toString() ).toEqual('100000000'); }); + + performance('compactFromU8a (u8)', 500_000, [[new Uint8Array([63 << 2])]], compactFromU8a); + performance('compactFromU8a (u16)', 500_000, [[new Uint8Array([0b11111101, 0b00000111])]], compactFromU8a); + performance('compactFromU8a (u32)', 500_000, [[new Uint8Array([254, 255, 3, 0])]], compactFromU8a); + performance('compactFromU8a (u64)', 500_000, [[hexToU8a('0x0b00407a10f35a')]], compactFromU8a); }); diff --git a/packages/util/src/compact/fromU8a.ts b/packages/util/src/compact/fromU8a.ts index 4ad99fbcf..2244b0899 100644 --- a/packages/util/src/compact/fromU8a.ts +++ b/packages/util/src/compact/fromU8a.ts @@ -3,7 +3,7 @@ import type { U8aLike } from '../types'; -import { BN, BN_FIVE } from '../bn'; +import { BN } from '../bn'; import { u8aToBn, u8aToU8a } from '../u8a'; /** @@ -24,18 +24,18 @@ export function compactFromU8a (input: U8aLike): [number, BN] { const u8a = u8aToU8a(input); const flag = u8a[0] & 0b11; + // The u8a is manually converted here, it is 2x faster that doing an + // additional call to u8aToBn if (flag === 0b00) { - return [1, new BN(u8a[0]).ishrn(2)]; + return [1, new BN(u8a[0] >>> 2)]; } else if (flag === 0b01) { - return [2, u8aToBn(u8a.subarray(0, 2), true).ishrn(2)]; + return [2, new BN((u8a[0] + (u8a[1] * 0x1_00)) >>> 2)]; } else if (flag === 0b10) { - return [4, u8aToBn(u8a.subarray(0, 4), true).ishrn(2)]; + return [4, new BN((u8a[0] + (u8a[1] * 0x1_00) + (u8a[2] * 0x1_00_00) + (u8a[3] * 0x1_00_00_00)) >>> 2)]; } - const offset = new BN(u8a[0]) - .ishrn(2) // clear flag - .iadd(BN_FIVE) // add 4 for base length, 1 for this byte - .toNumber(); + // add 5 to shifted (4 for base length, 1 for this byte) + const offset = (u8a[0] >>> 2) + 5; - return [offset, u8aToBn(u8a.subarray(1, offset), true)]; + return [offset, u8aToBn(u8a.subarray(1, offset))]; } diff --git a/packages/util/src/compact/toU8a.ts b/packages/util/src/compact/toU8a.ts index a08bc3815..eac8b8617 100644 --- a/packages/util/src/compact/toU8a.ts +++ b/packages/util/src/compact/toU8a.ts @@ -8,6 +8,8 @@ import { u8aConcat } from '../u8a'; const MAX_U8 = BN_TWO.pow(new BN(8 - 2)).isub(BN_ONE); const MAX_U16 = BN_TWO.pow(new BN(16 - 2)).isub(BN_ONE); const MAX_U32 = BN_TWO.pow(new BN(32 - 2)).isub(BN_ONE); +const BL_16 = { bitLength: 16 }; +const BL_32 = { bitLength: 32 }; /** * @name compactToU8a @@ -27,9 +29,9 @@ export function compactToU8a (value: BN | bigint | number): Uint8Array { if (bn.lte(MAX_U8)) { return new Uint8Array([bn.toNumber() << 2]); } else if (bn.lte(MAX_U16)) { - return bnToU8a(bn.shln(2).iadd(BN_ONE), 16, true); + return bnToU8a(bn.shln(2).iadd(BN_ONE), BL_16); } else if (bn.lte(MAX_U32)) { - return bnToU8a(bn.shln(2).iadd(BN_TWO), 32, true); + return bnToU8a(bn.shln(2).iadd(BN_TWO), BL_32); } const u8a = bnToU8a(bn); diff --git a/packages/util/src/u8a/toU8a.ts b/packages/util/src/u8a/toU8a.ts index 470a86f2a..06a376e5a 100644 --- a/packages/util/src/u8a/toU8a.ts +++ b/packages/util/src/u8a/toU8a.ts @@ -25,13 +25,13 @@ import { stringToU8a } from '../string/toU8a'; * ``` */ export function u8aToU8a (value?: U8aLike | null): Uint8Array { - return !value - ? new Uint8Array() - : Array.isArray(value) || isBuffer(value) + return value + ? Array.isArray(value) || isBuffer(value) ? new Uint8Array(value) : isU8a(value) ? value : isHex(value) ? hexToU8a(value) - : stringToU8a(value); + : stringToU8a(value) + : new Uint8Array(); }