Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wallet: support import of x/y/zpubkey (BIP49 and BIP84) #616

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
move purpose definition to common
  • Loading branch information
pinheadmz committed Nov 20, 2019
commit 59e56a6c0ebdad7e82f627875ea88b3727b59977
36 changes: 36 additions & 0 deletions lib/hd/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,39 @@ common.isAccount = function isAccount(key, account) {
*/

common.ZERO_KEY = Buffer.alloc(33, 0x00);

/**
* Purposes from extended key prefix bytes.
* @enum {Number}
* @default
*/

common.purposes = {
x: 0,
y: 1,
z: 2
};

/**
* Purposes by value.
* @enum {Number}
* @default
*/

common.purposesByVal = [
'x',
'y',
'z'
];

/**
* BIP44 "purpose" values by extended key prefix bytes
* @enum {Number}
* @default
*/

common.purposePath = {
x: 44,
y: 49,
z: 84
};
5 changes: 1 addition & 4 deletions lib/hd/private.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,7 @@ class HDPrivateKey {
assert(Buffer.isBuffer(options.privateKey));

if (options.purpose) {
assert(
['x','y','z'].indexOf(options.purpose) !== -1,
'Bad purpose'
);
assert(common.purposes[options.purpose] !== undefined, 'Bad purpose');
this.purpose = options.purpose;
} else {
this.purpose = 'x';
pinheadmz marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
5 changes: 1 addition & 4 deletions lib/hd/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,7 @@ class HDPublicKey {
assert(Buffer.isBuffer(options.publicKey));

if (options.purpose) {
assert(
['x','y','z'].indexOf(options.purpose) !== -1,
'Bad purpose'
);
assert(common.purposes[options.purpose] !== undefined, 'Bad purpose');
this.purpose = options.purpose;
} else {
this.purpose = 'x';
Expand Down
50 changes: 10 additions & 40 deletions lib/wallet/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,10 @@ class Account {
}

if (options.purpose != null) {
assert(typeof options.purpose === 'string');
assert(
['x','y','z'].indexOf(options.purpose) !== -1,
'Bad purpose'
);
assert(common.purposes[options.purpose] !== undefined, 'Bad purpose');
this.purpose = options.purpose;
} else {
this.purpose = 'x';
}

if (this.purpose === 'y' || this.purpose === 'z')
Expand Down Expand Up @@ -482,19 +480,11 @@ class Account {
let key;
if (master && master.key && !this.watchOnly) {
const coinType = this.network.keyPrefix.coinType;

switch (this.purpose) {
case 'x':
key = master.key.deriveAccount(44, coinType, this.accountIndex);
break;
case 'y':
key = master.key.deriveAccount(49, coinType, this.accountIndex);
break;
case 'z':
key = master.key.deriveAccount(84, coinType, this.accountIndex);
break;
}

key = master.key.deriveAccount(
common.purposePath[this.purpose],
coinType,
this.accountIndex
);
key = key.derive(branch).derive(index);
} else {
key = this.accountKey.derive(branch).derive(index);
Expand Down Expand Up @@ -890,7 +880,7 @@ class Account {
if (this.witness)
flags |= 2;

const purposeBits = Account.purposes[this.purpose];
const purposeBits = common.purposes[this.purpose];
flags |= (purposeBits << 6);

bw.writeU8(flags);
Expand Down Expand Up @@ -922,7 +912,7 @@ class Account {
const flags = br.readU8();

const purposeBits = flags >> 6;
this.purpose = Account.purposesByVal[purposeBits];
this.purpose = common.purposesByVal[purposeBits];

this.initialized = (flags & 1) !== 0;
this.witness = (flags & 2) !== 0;
Expand Down Expand Up @@ -989,26 +979,6 @@ Account.typesByVal = [
'MULTISIG'
];

/**
* Account purposes.
* @enum {Number}
* @default
*/

Account.purposes = {
x: 0,
y: 1,
z: 2
};

/**
* Account purposes by value.
* @enum {Number}
* @default
*/

Account.purposesByVal = ['x', 'y', 'z'];

/**
* Default address lookahead.
* @const {Number}
Expand Down
36 changes: 36 additions & 0 deletions lib/wallet/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,39 @@ common.sortDeps = function sortDeps(txs) {

return result;
};

/**
* Purposes from extended key prefix bytes.
* @enum {Number}
* @default
*/

common.purposes = {
x: 0,
y: 1,
z: 2
};

/**
* Purposes by value.
* @enum {Number}
* @default
*/

common.purposesByVal = [
'x',
'y',
'z'
];

/**
* BIP44 "purpose" values by extended key prefix bytes
* @enum {Number}
* @default
*/

common.purposePath = {
x: 44,
y: 49,
z: 84
};
16 changes: 5 additions & 11 deletions lib/wallet/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -600,17 +600,11 @@ class Wallet extends EventEmitter {
} else {
assert(this.master.key);
const coinType = this.network.keyPrefix.coinType;
switch (this.purpose) {
case 'x':
key = this.master.key.deriveAccount(44, coinType, this.accountDepth);
break;
case 'y':
key = this.master.key.deriveAccount(49, coinType, this.accountDepth);
break;
case 'z':
key = this.master.key.deriveAccount(84, coinType, this.accountDepth);
break;
}
key = this.master.key.deriveAccount(
common.purposePath[this.purpose],
coinType,
this.accountDepth
);
key = key.toPublic();
}

Expand Down