Move address helpers to util-crypto (#416)
* Move address helpers to util * Move address helpers to @polkadot/util-crypto
This commit is contained in:
@@ -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/);
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
@@ -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))
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,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()
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user