|
|
@ -16,6 +16,7 @@ const activeNet = network.network |
|
|
|
const keys = require('../../keys/')[network.key] |
|
|
|
const addrHelper = require('./addresses-helper') |
|
|
|
|
|
|
|
const MAX_SAFE_INT_32 = Math.pow(2, 31) - 1; |
|
|
|
|
|
|
|
/** |
|
|
|
* A singleton providing HD Accounts helper functions |
|
|
@ -32,6 +33,12 @@ class HDAccountsHelper { |
|
|
|
this.BIP84 = 2 |
|
|
|
this.LOCKED = 1<<7 |
|
|
|
|
|
|
|
// known HD accounts
|
|
|
|
this.RICOCHET_ACCT = MAX_SAFE_INT_32; |
|
|
|
this.POSTMIX_ACCT = MAX_SAFE_INT_32 - 1; |
|
|
|
this.PREMIX_ACCT = MAX_SAFE_INT_32 - 2; |
|
|
|
this.BADBANK_ACCT = MAX_SAFE_INT_32 - 3; |
|
|
|
|
|
|
|
// Magic numbers
|
|
|
|
this.MAGIC_XPUB = 0x0488b21e |
|
|
|
this.MAGIC_TPUB = 0x043587cf |
|
|
@ -276,7 +283,7 @@ class HDAccountsHelper { |
|
|
|
/** |
|
|
|
* Get the hd node associated to an hd account |
|
|
|
* @param {string} xpub - hd account |
|
|
|
* @returns {bip32} |
|
|
|
* @returns {[bitcoin.bip32.BIP32Interface, bitcoin.bip32.BIP32Interface, bitcoin.bip32.BIP32Interface]} |
|
|
|
*/ |
|
|
|
getNode(xpub) { |
|
|
|
if (this.isValid(xpub)) |
|
|
@ -289,10 +296,10 @@ class HDAccountsHelper { |
|
|
|
* Derives an address for an hd account |
|
|
|
* @param {number} chain - chain to be derived |
|
|
|
* must have a value on [0,1] for BIP44/BIP49/BIP84 derivation |
|
|
|
* @param {bip32} chainNode - Parent bip32 used for derivation |
|
|
|
* @param {bitcoin.bip32.BIP32Interface} chainNode - Parent bip32 used for derivation |
|
|
|
* @param {number} index - index to be derived |
|
|
|
* @param {number} type - type of derivation |
|
|
|
* @returns {Promise<object>} returns an object {address: '...', chain: <int>, index: <int>} |
|
|
|
* @returns {Promise<object>} returns an object {address: '...', chain: <int>, index: <int>, publicKey: <Buffer>, address: string } |
|
|
|
*/ |
|
|
|
async deriveAddress(chain, chainNode, index, type) { |
|
|
|
// Derive M/chain/index
|
|
|
@ -300,7 +307,8 @@ class HDAccountsHelper { |
|
|
|
|
|
|
|
const addr = { |
|
|
|
chain: chain, |
|
|
|
index: index |
|
|
|
index: index, |
|
|
|
publicKey: indexNode.publicKey |
|
|
|
} |
|
|
|
|
|
|
|
switch (type) { |
|
|
@ -325,7 +333,7 @@ class HDAccountsHelper { |
|
|
|
* must have a value on [0,1] for BIP44/BIP49/BIP84 derivation |
|
|
|
* @param {number[]} indices - array of indices to be derived |
|
|
|
* @param {number} type - type of derivation |
|
|
|
* @returns {Promise<object[]>} array of {address: '...', chain: <int>, index: <int>} |
|
|
|
* @returns {Promise<{ chain: number, index: number, publicKey: Buffer, address: string }[]>} array of address objects |
|
|
|
*/ |
|
|
|
async deriveAddresses(xpub, chain, indices, type) { |
|
|
|
const ret = [] |
|
|
@ -355,10 +363,18 @@ class HDAccountsHelper { |
|
|
|
) { |
|
|
|
// Few addresses to be derived or external derivation deactivated
|
|
|
|
// Let's do it here
|
|
|
|
let promises = indices.map(index => { |
|
|
|
const addresses = await Promise.all(indices.map(index => { |
|
|
|
return this.deriveAddress(chain, chainNode, index, info.type) |
|
|
|
}) |
|
|
|
return Promise.all(promises) |
|
|
|
})) |
|
|
|
|
|
|
|
// Generate additional change address types for postmix account
|
|
|
|
if (this.isPostmixAcct(node) && chain === 1) { |
|
|
|
const additionalPostmixAddresses = this._generateAdditionalChangeAddresses(addresses) |
|
|
|
|
|
|
|
addresses.push(...additionalPostmixAddresses) |
|
|
|
} |
|
|
|
|
|
|
|
return addresses; |
|
|
|
|
|
|
|
} else { |
|
|
|
// Many addresses to be derived
|
|
|
@ -375,6 +391,13 @@ class HDAccountsHelper { |
|
|
|
const msg = await this.derivationPool.exec('deriveAddresses', [data]) |
|
|
|
|
|
|
|
if (msg.status === 'ok') { |
|
|
|
// Generate additional change address types for postmix account
|
|
|
|
if (this.isPostmixAcct(node) && chain === 1) { |
|
|
|
const additionalPostmixAddresses = this._generateAdditionalChangeAddresses(msg.addresses) |
|
|
|
|
|
|
|
msg.addresses.push(...additionalPostmixAddresses) |
|
|
|
} |
|
|
|
|
|
|
|
resolve(msg.addresses) |
|
|
|
} else { |
|
|
|
Logger.error(null, 'HdAccountsHelper : A problem was met during parallel addresses derivation') |
|
|
@ -393,6 +416,40 @@ class HDAccountsHelper { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description Derive additional change addresses (P2PKH & P2SH) for postmix account |
|
|
|
* @param addresses {{ chain: number, index: number, publicKey: Buffer, address: string }[]} - list of derived addresses |
|
|
|
* @returns {{ chain: number, index: number, publicKey: Buffer, address: string }[]} - array of additional address types |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
_generateAdditionalChangeAddresses(addresses) { |
|
|
|
const additionalPostmixAddresses = addresses.map((address) => { |
|
|
|
const newP2PKHAddress = {...address} |
|
|
|
const newP2SHAddress = {...address} |
|
|
|
|
|
|
|
newP2PKHAddress.address = addrHelper.p2pkhAddress(address.publicKey) |
|
|
|
newP2SHAddress.address = addrHelper.p2wpkhP2shAddress(address.publicKey) |
|
|
|
|
|
|
|
return [newP2PKHAddress, newP2SHAddress]; |
|
|
|
}) |
|
|
|
|
|
|
|
return additionalPostmixAddresses.flat() |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description Detect postmix account |
|
|
|
* @param {[bitcoin.bip32.BIP32Interface, bitcoin.bip32.BIP32Interface, bitcoin.bip32.BIP32Interface]} node - array of BIP32 node interfaces |
|
|
|
* @returns {boolean} |
|
|
|
*/ |
|
|
|
isPostmixAcct(node) { |
|
|
|
const index = node[2].index |
|
|
|
const threshold = Math.pow(2,31) |
|
|
|
const hardened = (index >= threshold) |
|
|
|
const account = hardened ? (index - threshold) : index |
|
|
|
|
|
|
|
return account === this.POSTMIX_ACCT |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
module.exports = new HDAccountsHelper() |
|
|
|