Skip to content

Commit

Permalink
fix: alternating address derivation
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranjamie committed Jul 16, 2020
1 parent e838926 commit edc7b30
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 13 deletions.
2 changes: 1 addition & 1 deletion packages/keychain/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@blockstack/keychain",
"version": "0.7.5",
"version": "0.8.5",
"description": "A package for managing Blockstack keychains",
"main": "./dist/index.js",
"umd:main": "./dist/keychain.umd.production.js",
Expand Down
16 changes: 12 additions & 4 deletions packages/keychain/src/address-derivation/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { ChainID, getAddressFromPrivateKey } from '@blockstack/stacks-transactions';
import {
ChainID,
getAddressFromPrivateKey,
TransactionVersion,
} from '@blockstack/stacks-transactions';
import { BIP32Interface, ECPair } from 'bitcoinjs-lib';
import { ecPairToHexString } from 'blockstack';

const networkDerivationPath = `m/44'/5757'/0'/0/0`;

export const derivationPaths = {
[ChainID.Mainnet]: `m/44'/5757'/0'/0/0`,
[ChainID.Testnet]: `m/44'/1'/0'/0/0`,
[ChainID.Mainnet]: networkDerivationPath,
[ChainID.Testnet]: networkDerivationPath,
};

export function getDerivationPath(chain: ChainID) {
Expand All @@ -19,9 +25,11 @@ export function deriveStxAddressChain(chain: ChainID) {
}
const ecPair = ECPair.fromPrivateKey(childKey.privateKey);
const privateKey = ecPairToHexString(ecPair);
const txVersion =
chain === ChainID.Mainnet ? TransactionVersion.Mainnet : TransactionVersion.Testnet;
return {
childKey,
address: getAddressFromPrivateKey(privateKey),
address: getAddressFromPrivateKey(privateKey, txVersion),
privateKey,
};
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ChainID } from '@blockstack/stacks-transactions';
import { BIP32Interface } from 'bitcoinjs-lib';

import { deriveStxAddressChain } from '../../src/address-derivation';
import { deriveRootKeychainFromMnemonic } from '../../src/mnemonic';

const phrase =
'humble ramp winner eagle stumble follow gravity roast receive quote buddy start demise issue egg jewel return hurdle ball blind pulse physical uncle room';

describe('deriveStxAddressChain()', () => {
test('it returns mainnet derived keys', async () => {
test('it returns mainnet derived keys, pt. 1', async () => {
const phrase =
'humble ramp winner eagle stumble follow gravity roast receive quote buddy start demise issue egg jewel return hurdle ball blind pulse physical uncle room';
const deriveStxMainnetAddressChain = deriveStxAddressChain(ChainID.Mainnet);
const rootNode = await deriveRootKeychainFromMnemonic(phrase);
const result = deriveStxMainnetAddressChain(rootNode);
Expand All @@ -16,12 +16,90 @@ describe('deriveStxAddressChain()', () => {
);
});

test('it returns testnet derived keys', async () => {
const deriveStxTestnetAddressChain = deriveStxAddressChain(ChainID.Testnet);
test('it returns mainnet derived keys, pt. 2', async () => {
const phrase =
'oblige boat easily source clip remind steel hockey nut arrow swallow keep run fragile fresh river expire stay monster black defy box fiber wave';
const deriveStxMainnetAddressChain = deriveStxAddressChain(ChainID.Mainnet);
const rootNode = await deriveRootKeychainFromMnemonic(phrase);
const result = deriveStxTestnetAddressChain(rootNode);
const result = deriveStxMainnetAddressChain(rootNode);
expect(result.privateKey).toEqual(
'4cf240ef1e9b467c64b196b6ff3d24d9709f287f667939056fbcfc54e4a1642901'
'd7c71a427b8a9ed870c9552f67beadc2710dbee7f29a0cf6cfd1dd96a703bf1801'
);
expect(result.address).toEqual('SP2JSAXXTH90R04677F6JDS5D4DXWNW4T3KWNFDR5');
});

describe('it behaves according to CLI library for mainnet', () => {
const phrase =
'parade vacant kitten museum voice shift tell embrace security page praise cloud stove canal sketch huge ignore cotton island hand wall blush empower movie';
const deriveStxTestnetAddressChain = deriveStxAddressChain(ChainID.Mainnet);
let rootNode: BIP32Interface;
let result: ReturnType<typeof deriveStxTestnetAddressChain>;

beforeEach(async () => {
rootNode = await deriveRootKeychainFromMnemonic(phrase);
result = deriveStxTestnetAddressChain(rootNode);
});

test('private key is derive accurately for cli mainnet', () => {
expect(result.privateKey).toEqual(
'4587afc14878fd97aa01032bfae21ab01ae9a087abeecc7d867d39393e22ce2101'
);
});

test('address is derived accurately for cli mainnet', () => {
expect(result.address).toEqual('SP398525PZNCJTPNM6K4NW0T40YXJFEZ9DEQR12TR');
});
});

//
// This test should pass if testnet key derivation is
// supposed to use derivation path `m/44'/5757'/0'/0/0`,
describe(`should pass if testnet should use derivation path "m/44'/5757'/0'/0/0"`, () => {
const phrase =
'decorate confirm shoulder gain develop name tone source potato march maple company blanket discover ship clown virus broccoli room adapt praise oak west canoe';
const deriveStxTestnetAddressChain = deriveStxAddressChain(ChainID.Testnet);
let rootNode: BIP32Interface;
let result: ReturnType<typeof deriveStxTestnetAddressChain>;

beforeEach(async () => {
rootNode = await deriveRootKeychainFromMnemonic(phrase);
result = deriveStxTestnetAddressChain(rootNode);
});

test('private key is derive accurately for cli testnet', () => {
expect(result.privateKey).toEqual(
'cbaa7cbb821fdd17077fa24529803d351eb038fd6ec8eb14fc92344dbb244da901'
);
});

test('address is derived accurately for cli testnet', () => {
expect(result.address).toEqual('ST8SHKQXP59D65B1X0PHDHTWMKKPM94N9A2RNXE6');
});
});

//
// This test should pass if testnet key derivation is
// supposed to use derivation path `m/44'/1'/0'/0/0`,
// describe(`should pass if testnet should use derivation path "m/44'/1'/0'/0/0"`, () => {
// const phrase =
// 'trumpet hole school slim beauty advance evoke chapter random broom account twice state panel grant unfair empower spy asset depend acquire potato scatter atom';
// const deriveStxTestnetAddressChain = deriveStxAddressChain(ChainID.Testnet);
// let rootNode: BIP32Interface;
// let result: ReturnType<typeof deriveStxTestnetAddressChain>;

// beforeEach(async () => {
// rootNode = await deriveRootKeychainFromMnemonic(phrase);
// result = deriveStxTestnetAddressChain(rootNode);
// });

// test('private key is derive accurately for cli testnet', () => {
// expect(result.privateKey).toEqual(
// '65d49e09d57c07951b34cdac6b4ef6bdb8ee18ac7884c31a6876b086e7131b2d01'
// );
// });

// test('address is derived accurately for cli testnet', () => {
// expect(result.address).toEqual('ST1MED1C7R0V4FAZBAEF3FPD3JVHBP000FKTTG64T');
// });
// });
});

0 comments on commit edc7b30

Please sign in to comment.