Move address helpers to util-crypto (#416)

* Move address helpers to util

* Move address helpers to @polkadot/util-crypto
This commit is contained in:
Jaco Greeff
2019-06-12 15:01:54 +02:00
committed by GitHub
parent cbce516006
commit 6907add8ff
20 changed files with 29 additions and 32 deletions
@@ -1,90 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// @flow
import testingPairs from '../testingPairs';
import decode from './decode';
describe('decode', () => {
let keyring: any;
beforeAll(async () => {
keyring = testingPairs({ type: 'sr25519' });
});
it('decodes an address', () => {
expect(
decode('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')
).toEqual(
keyring.alice.publicKey()
);
});
it('converts a publicKey (u8a) as-is', () => {
expect(
decode(new Uint8Array([1, 2, 3]))
).toEqual(
new Uint8Array([1, 2, 3])
);
});
it('converts a publicKey (hex) as-is', () => {
expect(
decode('0x01020304')
).toEqual(
new Uint8Array([1, 2, 3, 4])
);
});
it('decodes a short address', () => {
expect(
decode('F7NZ')
).toEqual(new Uint8Array([1]));
});
it('decodes a 1-byte accountId (with prefix)', () => {
expect(
decode('PqtB', false, 68)
).toEqual(new Uint8Array([1]));
});
it('decodes a 2-byte accountId', () => {
expect(
decode('2jpAFn', false, 68)
).toEqual(new Uint8Array([0, 1]));
});
it('encodes a 4-byte address', () => {
expect(
decode('as7QnGMf', false, 68)
).toEqual(new Uint8Array([1, 2, 3, 4]));
});
it('decodes a 8-byte address', () => {
expect(
decode('4q7qY5RBG7Z4wv', false, 68)
).toEqual(new Uint8Array([42, 44, 10, 0, 0, 0, 0, 0]));
});
it.skip('allows invalid prefix (in list)', () => {
expect(
() => decode('6GfvWUvHvU8otbZ7sFhXH4eYeMcKdUkL61P3nFy52efEPVUx')
).toThrow(/address prefix/);
});
it('fails when length is invalid', () => {
expect(
() => decode('y9EMHt34JJo4rWLSaxoLGdYXvjgSXEd4zHUnQgfNzwES8b')
).toThrow(/address length/);
});
it('fails when the checksum does not match', () => {
expect(
() => decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMa9cj')
).toThrow(/address checksum/);
expect(
() => decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDwU')
).toThrow(/address checksum/);
});
});
-46
View File
@@ -1,46 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Prefix } from './types';
// Original implementation: https://github.com/paritytech/polka-ui/blob/4858c094684769080f5811f32b081dd7780b0880/src/polkadot.js#L6
import bs58 from 'bs58';
import { assert, bufferToU8a, isHex, isU8a, u8aToU8a } from '@polkadot/util';
import defaults from './defaults';
import sshash from './sshash';
export default function decode (encoded: string | Uint8Array, ignoreChecksum?: boolean, prefix: Prefix = defaults.prefix): Uint8Array {
if (isU8a(encoded) || isHex(encoded)) {
return u8aToU8a(encoded);
}
const decoded = bufferToU8a(bs58.decode(encoded));
const error = (message: string) =>
`Decoding ${encoded}: ${message}`;
// assert(defaults.allowedPrefix.includes(decoded[0] as Prefix), error('Invalid decoded address prefix'));
assert(defaults.allowedEncodedLengths.includes(decoded.length), error('Invalid decoded address length'));
// TODO Unless it is an "use everywhere" prefix, throw an error
// if (decoded[0] !== prefix) {
// console.log(`WARN: Expected ${prefix}, found ${decoded[0]}`);
// }
const isPublicKey = decoded.length === 35;
// non-publicKeys has 1 byte checksums, else default to 2
const endPos = decoded.length - (isPublicKey ? 2 : 1);
// calculate the hash and do the checksum byte checks
const hash = sshash(decoded.subarray(0, endPos));
const checks = isPublicKey
? decoded[decoded.length - 2] === hash[0] && decoded[decoded.length - 1] === hash[1]
: decoded[decoded.length - 1] === hash[0];
assert(ignoreChecksum || checks, error('Invalid decoded address checksum'));
return decoded.slice(1, endPos);
}
-15
View File
@@ -1,15 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Prefix } from './types';
const defaults = {
allowedDecodedLengths: [1, 2, 4, 8, 32],
// publicKey has prefix + 2 checksum bytes, short only prefix + 1 checksum byte
allowedEncodedLengths: [3, 4, 6, 10, 35],
allowedPrefix: [0, 1, 3, 42, 43, 68, 69] as Array<Prefix>,
prefix: 42 as Prefix
};
export default defaults;
@@ -1,65 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// @flow
import testingPairs from '../testingPairs';
import encode from './encode';
const keyring = testingPairs({ type: 'ed25519' }, false);
describe('encode', () => {
it('encodes an address to a valid value', () => {
expect(
keyring.alice.address()
).toEqual('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua');
});
it('fails when non-valid publicKey provided', () => {
expect(
() => encode(
keyring.alice.publicKey().slice(0, 30)
)
).toThrow(/Expected a valid key/);
});
it('encodes a 1-byte address', () => {
expect(
encode(
new Uint8Array([1])
)
).toEqual('F7NZ');
});
it('encodes a 1-byte address (with prefix)', () => {
expect(
encode(
new Uint8Array([1]), 68
)
).toEqual('PqtB');
});
it('encodes a 2-byte address', () => {
expect(
encode(
new Uint8Array([0, 1]), 68
)
).toEqual('2jpAFn');
});
it('encodes a 4-byte address', () => {
expect(
encode(
new Uint8Array([1, 2, 3, 4]), 68
)
).toEqual('as7QnGMf');
});
it('enodes a 8-byte address', () => {
expect(
encode(
new Uint8Array([42, 44, 10, 0, 0, 0, 0, 0]), 68
)
).toEqual('4q7qY5RBG7Z4wv');
});
});
-30
View File
@@ -1,30 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Prefix } from './types';
// Original implementation: https://github.com/paritytech/polka-ui/blob/4858c094684769080f5811f32b081dd7780b0880/src/polkadot.js#L34
import bs58 from 'bs58';
import { assert, u8aConcat, u8aToBuffer, u8aToU8a } from '@polkadot/util';
import defaults from './defaults';
import sshash from './sshash';
export default function encode (_key: Uint8Array | string, prefix: Prefix = defaults.prefix): string {
const key = u8aToU8a(_key);
assert(defaults.allowedDecodedLengths.includes(key.length), `Expected a valid key to convert, with length ${defaults.allowedDecodedLengths}`);
const isPublicKey = key.length === 32;
const input = u8aConcat(new Uint8Array([prefix]), key);
const hash = sshash(input);
return bs58.encode(
u8aToBuffer(
u8aConcat(input, hash.subarray(0, isPublicKey ? 2 : 1))
)
);
}
-13
View File
@@ -1,13 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import decodeAddress from './decode';
import encodeAddress from './encode';
import setAddressPrefix from './setPrefix';
export {
decodeAddress,
encodeAddress,
setAddressPrefix
};
@@ -1,20 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import encode from './encode';
import setPrefix from './setPrefix';
describe('setPrefix', () => {
beforeEach(() => {
setPrefix(68);
});
it('sets and allows encoding using', () => {
expect(
encode(
new Uint8Array([1])
)
).toEqual('PqtB');
});
});
-11
View File
@@ -1,11 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Prefix } from './types';
import defaults from './defaults';
export default function setPrefix (prefix: Prefix): void {
defaults.prefix = prefix;
}
-12
View File
@@ -1,12 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { stringToU8a, u8aConcat } from '@polkadot/util';
import { blake2AsU8a } from '@polkadot/util-crypto';
const SS58_PREFIX = stringToU8a('SS58PRE');
export default function hash (key: Uint8Array): Uint8Array {
return blake2AsU8a(u8aConcat(SS58_PREFIX, key), 512);
}
-5
View File
@@ -1,5 +0,0 @@
// Copyright 2017-2019 @polkadot/keyring authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export type Prefix = 0 | 1 | 3 | 42 | 43 | 68 | 69;
+3 -4
View File
@@ -3,10 +3,9 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { hexToU8a, stringToU8a } from '@polkadot/util';
import { cryptoWaitReady } from '@polkadot/util-crypto';
import { cryptoWaitReady, setAddressPrefix } from '@polkadot/util-crypto';
import Keyring from '.';
import setPrefix from './address/setPrefix';
describe('keypair', () => {
beforeEach(async () => {
@@ -41,7 +40,7 @@ describe('keypair', () => {
});
it('adds from a mnemonic', () => {
setPrefix(68);
setAddressPrefix(68);
expect(
keypair.addFromMnemonic('moral movie very draw assault whisper awful rebuild speed purity repeat card', {}).address()
@@ -107,7 +106,7 @@ describe('keypair', () => {
});
it('adds from a mnemonic', () => {
setPrefix(68);
setAddressPrefix(68);
expect(
keypair.addFromMnemonic('moral movie very draw assault whisper awful rebuild speed purity repeat card', {}).address()
+1 -1
View File
@@ -3,8 +3,8 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { assertSingletonPackage } from '@polkadot/util';
import { decodeAddress, encodeAddress, setAddressPrefix } from '@polkadot/util-crypto';
import { decodeAddress, encodeAddress, setAddressPrefix } from './address';
import { default as Keyring } from './keyring';
assertSingletonPackage('@polkadot/keyring');
+1 -2
View File
@@ -6,9 +6,8 @@ import { KeypairType } from '@polkadot/util-crypto/types';
import { KeyringInstance, KeyringPair, KeyringPair$Json, KeyringPair$Meta, KeyringOptions } from './types';
import { assert, hexToU8a, isNumber, isHex, stringToU8a } from '@polkadot/util';
import { keyExtractSuri, naclKeypairFromSeed as naclFromSeed, schnorrkelKeypairFromSeed as schnorrkelFromSeed, mnemonicToMiniSecret, keyFromPath } from '@polkadot/util-crypto';
import { decodeAddress, encodeAddress, keyExtractSuri, keyFromPath, naclKeypairFromSeed as naclFromSeed, schnorrkelKeypairFromSeed as schnorrkelFromSeed, mnemonicToMiniSecret, setAddressPrefix } from '@polkadot/util-crypto';
import { decodeAddress, encodeAddress, setAddressPrefix } from './address';
import { DEV_PHRASE } from './defaults';
import createPair from './pair';
import Pairs from './pairs';
+1 -2
View File
@@ -6,9 +6,8 @@ import { Keypair, KeypairType } from '@polkadot/util-crypto/types';
import { KeyringPair, KeyringPair$Json, KeyringPair$Meta } from '../types';
import { PairInfo } from './types';
import { naclKeypairFromSeed as naclFromSeed, naclSign, naclVerify, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, schnorrkelVerify } from '@polkadot/util-crypto';
import { encodeAddress, naclKeypairFromSeed as naclFromSeed, naclSign, naclVerify, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, schnorrkelVerify } from '@polkadot/util-crypto';
import { encodeAddress } from '../address';
import decode from './decode';
import encode from './encode';
import toJson from './toJson';
+2 -2
View File
@@ -4,10 +4,10 @@
import { KeyringPair, KeyringPair$Json, KeyringPair$Meta } from '../types';
import addressEncode from '../address/encode';
import { encodeAddress } from '@polkadot/util-crypto';
const publicKey = new Uint8Array(32);
const address = addressEncode(publicKey);
const address = encodeAddress(publicKey);
const meta = {
isTesting: true,
name: 'nobody'
+1 -2
View File
@@ -6,8 +6,7 @@ import { KeypairType } from '@polkadot/util-crypto/types';
import { KeyringPair$Json, KeyringPair$Meta } from '../types';
import { u8aToHex } from '@polkadot/util';
import { encodeAddress } from '../address';
import { encodeAddress } from '@polkadot/util-crypto';
type PairStateJson = KeyringPair$Meta & {
publicKey: Uint8Array
+3 -4
View File
@@ -5,8 +5,7 @@
import { KeyringPairs, KeyringPair } from './types';
import { assert, isHex, isU8a, u8aToHex, u8aToU8a } from '@polkadot/util';
import addressDecode from './address/decode';
import { decodeAddress } from '@polkadot/util-crypto';
type KeyringPairMap = {
// @ts-ignore we use coercion :(
@@ -33,7 +32,7 @@ export default class Pairs implements KeyringPairs {
get (address: string | Uint8Array): KeyringPair {
// @ts-ignore we use coercion :(
const pair = this._map[addressDecode(address)];
const pair = this._map[decodeAddress(address)];
assert(pair, () => {
const formatted: string = isU8a(address) || isHex(address)
@@ -48,6 +47,6 @@ export default class Pairs implements KeyringPairs {
remove (address: string | Uint8Array): void {
// @ts-ignore we use coercion :(
delete this._map[addressDecode(address)];
delete this._map[decodeAddress(address)];
}
}
+1 -1
View File
@@ -2,8 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Prefix } from '@polkadot/util-crypto/address/types';
import { KeypairType } from '@polkadot/util-crypto/types';
import { Prefix } from './address/types';
export type KeyringOptions = {
addressPrefix?: Prefix,