Derive operation on keypair (#487)

* Derive operation on keypair

* nobody -> derive

* Derivation tests
This commit is contained in:
Jaco Greeff
2019-11-06 15:22:12 +01:00
committed by GitHub
parent 71f26aac8d
commit a5f59ca926
5 changed files with 51 additions and 19 deletions
+17 -1
View File
@@ -2,14 +2,19 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { setSS58Format } from '@polkadot/util-crypto';
import { cryptoWaitReady, setSS58Format } from '@polkadot/util-crypto';
import { PAIRS } from '../testing';
import testingPairs from '../testingPairs';
import createPair from '.';
const keyring = testingPairs({ type: 'ed25519' }, false);
describe('pair', (): void => {
beforeEach(async (): Promise<void> => {
await cryptoWaitReady();
});
const SIGNATURE = new Uint8Array([80, 191, 198, 147, 225, 207, 75, 88, 126, 39, 129, 109, 191, 38, 72, 181, 75, 254, 81, 143, 244, 79, 237, 38, 236, 141, 28, 252, 134, 26, 169, 234, 79, 33, 153, 158, 151, 34, 175, 188, 235, 20, 35, 135, 83, 120, 139, 211, 233, 130, 1, 208, 201, 215, 73, 80, 56, 98, 185, 196, 11, 8, 193, 14]);
it('has a publicKey', (): void => {
@@ -66,6 +71,8 @@ describe('pair', (): void => {
expect(keyring.alice.address).toEqual(
'7sGUeMak588SPY2YMmmuKUuLz7u2WQpf74F9dCFtSLB2td9d'
);
setSS58Format(42);
});
it('allows getting public key after decoding', (): void => {
@@ -77,4 +84,13 @@ describe('pair', (): void => {
expect(pair.isLocked).toEqual(false);
});
it('allows derivation on the pair', (): void => {
const alice = createPair('sr25519', { publicKey: PAIRS[0].publicKey, secretKey: PAIRS[0].secretKey }, {});
const stash = alice.derive('//stash');
const soft = alice.derive('//funding/0');
expect(stash.publicKey).toEqual(PAIRS[1].publicKey);
expect(soft.address).toEqual('5ECQNn7UueWHPFda5qUi4fTmTtyCnPvGnuoyVVSj5CboJh9J');
});
});
+22 -12
View File
@@ -6,8 +6,8 @@ import { Keypair, KeypairType } from '@polkadot/util-crypto/types';
import { KeyringPair, KeyringPair$Json, KeyringPair$Meta, SignOptions } from '../types';
import { PairInfo } from './types';
import { u8aConcat } from '@polkadot/util';
import { encodeAddress, naclKeypairFromSeed as naclFromSeed, naclSign, naclVerify, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, schnorrkelVerify } from '@polkadot/util-crypto';
import { u8aConcat, assert } from '@polkadot/util';
import { encodeAddress, keyExtractPath, keyFromPath, naclKeypairFromSeed as naclFromSeed, naclSign, naclVerify, schnorrkelKeypairFromSeed as schnorrkelFromSeed, schnorrkelSign, schnorrkelVerify } from '@polkadot/util-crypto';
import decode from './decode';
import encode from './encode';
@@ -87,10 +87,21 @@ const verify = (type: KeypairType, message: Uint8Array, signature: Uint8Array, p
*/
export default function createPair (type: KeypairType, { publicKey, secretKey }: PairInfo, meta: KeyringPair$Meta = {}, encoded: Uint8Array | null = null): KeyringPair {
return {
type,
get address (): string {
return encodeAddress(publicKey);
},
get meta (): KeyringPair$Meta {
return meta;
},
get isLocked (): boolean {
return !secretKey || secretKey.length === 0 || isEmpty(secretKey);
},
get publicKey (): Uint8Array {
return publicKey;
},
get type (): KeypairType {
return type;
},
decodePkcs8: (passphrase?: string, _encoded?: Uint8Array | null): void => {
const decoded = decode(passphrase, _encoded || encoded);
@@ -104,20 +115,19 @@ export default function createPair (type: KeypairType, { publicKey, secretKey }:
secretKey = pair.secretKey;
}
},
derive: (suri: string, meta?: KeyringPair$Meta): KeyringPair => {
assert(secretKey, 'Cannot derive on a locked keypair');
const { path } = keyExtractPath(suri);
const derived = keyFromPath({ publicKey, secretKey: secretKey as Uint8Array }, path, type);
return createPair(type, derived, meta, null);
},
encodePkcs8: (passphrase?: string): Uint8Array =>
encode({ publicKey, secretKey }, passphrase),
get meta (): KeyringPair$Meta {
return meta;
},
get isLocked (): boolean {
return !secretKey || secretKey.length === 0 || isEmpty(secretKey);
},
lock: (): void => {
secretKey = new Uint8Array(0);
},
get publicKey (): Uint8Array {
return publicKey;
},
setMeta: (additional: KeyringPair$Meta): void => {
meta = { ...meta, ...additional };
},
+6 -1
View File
@@ -24,13 +24,16 @@ const json: KeyringPair$Json = {
};
export default function everybody (): KeyringPair {
return {
const pair: KeyringPair = {
type: 'ed25519',
address,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
decodePkcs8: (passphrase?: string, encoded?: Uint8Array): void =>
undefined,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
derive: (suri: string, meta?: KeyringPair$Meta): KeyringPair =>
pair,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
encodePkcs8: (passphrase?: string): Uint8Array =>
new Uint8Array(0),
meta,
@@ -52,4 +55,6 @@ export default function everybody (): KeyringPair {
verify: (message: Uint8Array, signature: Uint8Array): boolean =>
false
};
return pair;
}
+1 -1
View File
@@ -21,7 +21,7 @@ interface PairDef {
// keyring is for testing - what happens is that in most cases the keyring is initialises
// before anything else. Since the sr25519 crypto is async, this creates problems with
// adding the keys when only the keyring is used.
const PAIRS: PairDef[] = [
export const PAIRS: PairDef[] = [
{
seed: 'Alice',
secretKey: hexToU8a('0x98319d4ff8a9508c4bb0cf0b5a78d760a0b2082c02775e6e82370816fedfff48925a225d97aa00682d6a59b95b18780c10d7032336e88f3442b42361f4a66011'),
+5 -4
View File
@@ -38,15 +38,16 @@ export interface SignOptions {
}
export interface KeyringPair {
readonly address: string;
readonly meta: KeyringPair$Meta;
readonly isLocked: boolean;
readonly publicKey: Uint8Array;
readonly type: KeypairType;
address: string;
decodePkcs8: (passphrase?: string, encoded?: Uint8Array) => void;
derive: (suri: string, meta?: KeyringPair$Meta) => KeyringPair;
encodePkcs8: (passphrase?: string) => Uint8Array;
meta: KeyringPair$Meta;
isLocked: boolean;
lock: () => void;
publicKey: Uint8Array;
setMeta: (meta: KeyringPair$Meta) => void;
sign (message: Uint8Array, options?: SignOptions): Uint8Array;
toJson (passphrase?: string): KeyringPair$Json;