Adjust base library usage of for vs reduce/map (#1151)

* Adjust base library usage of `for` vs `reduce/map`

* Additional

* Adjust
This commit is contained in:
Jaco
2021-10-31 08:27:14 +02:00
committed by GitHub
parent 7ef169585f
commit a4cefa4bfc
20 changed files with 130 additions and 87 deletions
+1
View File
@@ -10,6 +10,7 @@ Changes:
- Add `arrayZip` to combine a key + value array into entries-like
- Assert `chainCode` inputs to `derive*`, protecting against misuse
- Adjust base library usage of `for` vs `reduce/map`
- Adjust testnet detection in `@polkadot/networks`
- Bump Ledger libraries to latest versions
+1 -5
View File
@@ -262,11 +262,7 @@ export class Keyring implements KeyringInstance {
* @description Returns an array list of all the public keys associated with each of the keyring pair values that are stored in the keyring pair dictionary.
*/
public getPublicKeys (): Uint8Array[] {
return this.#pairs
.all()
.map(({ publicKey }): Uint8Array =>
publicKey
);
return this.#pairs.all().map(({ publicKey }) => publicKey);
}
/**
+2 -2
View File
@@ -121,7 +121,7 @@ export function createTestKeyring (options: KeyringOptions = {}, isDerived = tru
const keyring = new Keyring(options);
const pairs: PairDef[] = (options.type && options.type === 'ethereum') ? PAIRSETHEREUM : PAIRSSR25519;
pairs.forEach(({ name, publicKey, secretKey, seed, type }): void => {
for (const { name, publicKey, secretKey, seed, type } of pairs) {
if (!name && !seed) {
throw new Error('Testing pair should have either a name or a seed');
}
@@ -139,7 +139,7 @@ export function createTestKeyring (options: KeyringOptions = {}, isDerived = tru
pair.lock = (): void => {
// we don't have lock/unlock functionality here
};
});
}
return keyring;
}
+4 -6
View File
@@ -15,11 +15,9 @@ export function createTestPairs (options?: KeyringOptions, isDerived = true): Te
const pairs = keyring.getPairs();
const map: TestKeyringMap = { nobody: nobody() };
return pairs.reduce((result, pair): TestKeyringMap => {
const { name } = pair.meta;
for (const p of pairs) {
map[p.meta.name as string] = p;
}
result[name as string] = pair;
return result;
}, map);
return map;
}
+8 -5
View File
@@ -7,7 +7,6 @@ import type { Prefix } from './types';
import { assert } from '@polkadot/util';
import { keyExtractPath } from '../key';
import { DeriveJunction } from '../key/DeriveJunction';
import { schnorrkelDerivePublic } from '../schnorrkel';
import { decodeAddress } from './decode';
import { encodeAddress } from './encode';
@@ -21,9 +20,13 @@ import { encodeAddress } from './encode';
export function deriveAddress (who: HexString | Uint8Array | string, suri: string, ss58Format?: Prefix): string {
const { path } = keyExtractPath(suri);
assert(path.length && !path.some((path) => path.isHard), 'Expected suri to contain a combination of non-hard paths');
assert(path.length && !path.some((p) => p.isHard), 'Expected suri to contain a combination of non-hard paths');
return encodeAddress(path.reduce((publicKey: Uint8Array, path: DeriveJunction): Uint8Array => {
return schnorrkelDerivePublic(publicKey, path.chainCode);
}, decodeAddress(who)), ss58Format);
let publicKey = decodeAddress(who);
for (const { chainCode } of path) {
publicKey = schnorrkelDerivePublic(publicKey, chainCode);
}
return encodeAddress(publicKey, ss58Format);
}
+12 -13
View File
@@ -44,7 +44,7 @@ function deriveChild (hd: CodedKeypair, index: number): CodedKeypair {
export function hdEthereum (seed: Uint8Array, path = ''): Keypair {
const I = hmacSha512(MASTER_SECRET, seed);
const hd = createCoded(I.slice(0, 32), I.slice(32));
let hd = createCoded(I.slice(0, 32), I.slice(32));
if (!path || path === 'm' || path === 'M' || path === "m'" || path === "M'") {
return hd;
@@ -52,16 +52,15 @@ export function hdEthereum (seed: Uint8Array, path = ''): Keypair {
assert(hdValidatePath(path), 'Invalid derivation path');
return path
.split('/')
.slice(1)
.reduce((hd: CodedKeypair, c): CodedKeypair =>
deriveChild(
hd, parseInt(c, 10) + (
(c.length > 1) && c.endsWith("'")
? HARDENED
: 0
)
), hd
);
const parts = path.split('/').slice(1);
for (const p of parts) {
hd = deriveChild(hd, parseInt(p, 10) + (
(p.length > 1) && p.endsWith("'")
? HARDENED
: 0
));
}
return hd;
}
+15 -14
View File
@@ -12,27 +12,28 @@ import { ledgerDerivePrivate } from './derivePrivate';
import { ledgerMaster } from './master';
export function hdLedger (_mnemonic: string, path: string): Keypair {
const parts = _mnemonic
const words = _mnemonic
.split(' ')
.map((s) => s.trim())
.filter((s) => s);
assert([12, 24, 25].includes(parts.length), 'Expected a mnemonic with 24 words (or 25 including a password)');
assert([12, 24, 25].includes(words.length), 'Expected a mnemonic with 24 words (or 25 including a password)');
const [mnemonic, password] = parts.length === 25
? [parts.slice(0, 24).join(' '), parts[24]]
: [parts.join(' '), ''];
const [mnemonic, password] = words.length === 25
? [words.slice(0, 24).join(' '), words[24]]
: [words.join(' '), ''];
assert(mnemonicValidate(mnemonic), 'Invalid mnemonic passed to ledger derivation');
assert(hdValidatePath(path), 'Invalid derivation path');
return naclKeypairFromSeed(
path
.split('/')
.slice(1)
.map((n) => parseInt(n.replace(/'$/, ''), 10))
.map((n) => (n < HARDENED) ? (n + HARDENED) : n)
.reduce((x, n) => ledgerDerivePrivate(x, n), ledgerMaster(mnemonic, password))
.slice(0, 32)
);
const parts = path.split('/').slice(1);
let seed = ledgerMaster(mnemonic, password);
for (const p of parts) {
const n = parseInt(p.replace(/'$/, ''), 10);
seed = ledgerDerivePrivate(seed, (n < HARDENED) ? (n + HARDENED) : n);
}
return naclKeypairFromSeed(seed.slice(0, 32));
}
+11 -5
View File
@@ -10,9 +10,15 @@ export function hdValidatePath (path: string): boolean {
const parts = path.split('/').slice(1);
return parts.every((n) => /^\d+'?$/.test(n)) && (
!parts
.map((n) => parseInt(n.replace(/'$/, ''), 10))
.some((n) => isNaN(n) || (n >= HARDENED) || (n < 0))
);
for (const p of parts) {
const n = /^\d+'?$/.test(p)
? parseInt(p.replace(/'$/, ''), 10)
: Number.NaN;
if (isNaN(n) || (n >= HARDENED) || (n < 0)) {
return false;
}
}
return true;
}
+3 -3
View File
@@ -23,9 +23,9 @@ export function keyExtractPath (derivePath: string): ExtractResult {
if (parts) {
constructed = parts.join('');
parts.forEach((value: string): void => {
path.push(DeriveJunction.from(value.substr(1)));
});
for (const p of parts) {
path.push(DeriveJunction.from(p.substr(1)));
}
}
assert(constructed === derivePath, () => `Re-constructed path "${constructed}" does not match input`);
+6 -3
View File
@@ -18,8 +18,11 @@ const generators = {
export function keyFromPath (pair: Keypair, path: DeriveJunction[], type: KeypairType): Keypair {
const keyHdkd = generators[type];
let result = pair;
return path.reduce((pair, junction): Keypair => {
return keyHdkd(pair, junction);
}, pair);
for (const junction of path) {
result = keyHdkd(result, junction);
}
return result;
}
+10 -6
View File
@@ -20,15 +20,19 @@
*/
export function arrayFlatten <T> (arrays: T[][]): T[] {
// pre-allocate based on the combined size
const output = new Array<T>(arrays.reduce((length, array) => length + array.length, 0));
let size = 0;
for (const a of arrays) {
size += a.length;
}
const output = new Array<T>(size);
let index = -1;
for (let a = 0; a < arrays.length; a++) {
const array = arrays[a];
for (const a of arrays) {
// instead of pushing, we just set the entries
for (let e = 0; e < array.length; e++) {
output[++index] = array[e];
for (let e = 0; e < a.length; e++) {
output[++index] = a[e];
}
}
+7 -1
View File
@@ -21,5 +21,11 @@ import { assert } from '../assert';
export function arrayRange (size: number, startAt = 0): number[] {
assert(size > 0, 'Expected non-zero, positive number as a range size');
return new Array(size).fill(0).map((_, i) => i + startAt);
const result = new Array<number>(size).fill(0);
for (let i = 0; i < result.length; i++) {
result[i] = i + startAt;
}
return result;
}
+6
View File
@@ -9,4 +9,10 @@ describe('bnMax', (): void => {
bnMax(new BN(1), new BN(2), new BN(3))
).toEqual(new BN(3));
});
it('finds BN maximum', (): void => {
expect(
bnMax(new BN(2), new BN(3), new BN(1))
).toEqual(new BN(3));
});
});
+1 -1
View File
@@ -6,7 +6,7 @@ import { BN, bnMin } from '.';
describe('bnMin', (): void => {
it('finds BN minimum', (): void => {
expect(
bnMin(new BN(1), new BN(2), new BN(3))
bnMin(new BN(2), new BN(1), new BN(3))
).toEqual(new BN(1));
});
});
+7 -1
View File
@@ -7,5 +7,11 @@ import { BN } from './bn';
export function checkMaxMin (type: 'max' | 'min', items: BN[]): BN {
assert(items.length >= 1, 'Must provide one or more BN arguments');
return items.reduce<BN>((a, v) => BN[type](a, v), items[0]);
let result = items[0];
for (const v of items) {
result = BN[type](result, v);
}
return result;
}
+6 -4
View File
@@ -24,11 +24,13 @@ const logTo = {
function formatOther (value: unknown): unknown {
if (value && isObject(value) && value.constructor === Object) {
return Object.keys(value).reduce((result: Record<string, unknown>, key): Record<string, unknown> => {
result[key] = loggerFormat(value[key]);
const result: Record<string, unknown> = {};
return result;
}, {});
for (const k of Object.keys(value)) {
result[k] = loggerFormat(value[k]);
}
return result;
}
return value;
+7 -1
View File
@@ -44,7 +44,13 @@ function getEntry (name: string): VersionPath[] {
}
function getVersionLength (all: { version: string }[]): number {
return all.reduce((max, { version }) => Math.max(max, version.length), 0);
let length = 0;
for (const { version } of all) {
length = Math.max(length, version.length);
}
return length;
}
/** @internal */
+7 -5
View File
@@ -5,10 +5,12 @@ import crypto from 'crypto';
export { packageInfo } from './packageInfo';
export function getRandomValues <T extends Uint8Array> (arr: T): T {
return crypto.randomBytes(arr.length).reduce((arr, value, index) => {
arr[index] = value;
export function getRandomValues <T extends Uint8Array> (output: T): T {
const bytes = crypto.randomBytes(output.length);
return arr;
}, arr);
for (let i = 0; i < bytes.length; i++) {
output[i] = bytes[i];
}
return output;
}
+9 -9
View File
@@ -19,18 +19,18 @@ interface RNExt {
}
}
function getRandomValuesNative <T extends Uint8Array> (arr: T): T {
return Buffer
.from((NativeModules as RNExt).RNGetRandomValues.getRandomBase64(arr.length), 'base64')
.reduce((arr, byte, index): T => {
arr[index] = byte;
function getRandomValuesNative <T extends Uint8Array> (output: T): T {
const bytes = Buffer.from((NativeModules as RNExt).RNGetRandomValues.getRandomBase64(output.length), 'base64');
return arr;
}, arr);
for (let i = 0; i < bytes.length; i++) {
output[i] = bytes[i];
}
return output;
}
function getRandomValuesGlobal <T extends Uint8Array> (arr: T): T {
return crypto.getRandomValues(arr);
function getRandomValuesGlobal <T extends Uint8Array> (output: T): T {
return crypto.getRandomValues(output);
}
export const getRandomValues = (
+7 -3
View File
@@ -9,8 +9,12 @@ export class TextDecoder {
}
decode (value: Uint8Array): string {
return value.reduce((str, code): string => {
return str + String.fromCharCode(code);
}, '');
let result = '';
for (const c of value) {
result += String.fromCharCode(c);
}
return result;
}
}