Browse Source

Derive additional change addresses for postmix account

Pavel Ševčík 4 years ago
parent
commit
442af30da2
No known key found for this signature in database GPG Key ID: CFA54E4C0CD58DF0
  1. 59
      lib/bitcoin/hd-accounts-helper.js
  2. 4
      lib/bitcoin/hd-accounts-service.js
  3. 5
      lib/bitcoin/parallel-address-derivation.js
  4. 3
      tracker/transaction.js

59
lib/bitcoin/hd-accounts-helper.js

@ -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
@ -292,7 +299,7 @@ class HDAccountsHelper {
* @param {bip32} 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>}
*/
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) {
@ -344,6 +352,13 @@ class HDAccountsHelper {
const info = this.classify(type)
// Detect postmix account
const index = node[2].index
const threshold = Math.pow(2,31)
const hardened = (index >= threshold)
const account = hardened ? (index - threshold) : index
const isPostmixAcct = account === this.POSTMIX_ACCT
// Node at M/chain
const chainNode = node[chain]
@ -355,10 +370,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 (isPostmixAcct && chain === 1) {
const additionalPostmixAddresses = this.generateAdditionalChangeAddresses(addresses)
addresses.push(...additionalPostmixAddresses)
}
return addresses;
} else {
// Many addresses to be derived
@ -375,6 +398,13 @@ class HDAccountsHelper {
const msg = await this.derivationPool.exec('deriveAddresses', [data])
if (msg.status === 'ok') {
// Generate additional change address types for postmix account
if (isPostmixAcct && 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 +423,25 @@ class HDAccountsHelper {
}
}
/**
* @description Derive additional change addresses (P2PKH & P2SH) for postmix account
* @param addresses {object[]} - list of derived addresses
* @returns {Array<object>} - array of additional address types
*/
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()
}
}
module.exports = new HDAccountsHelper()

4
lib/bitcoin/hd-accounts-service.js

@ -152,8 +152,8 @@ class HDAccountsService {
/**
* Rescan the blockchain for a hd account
* @param {string} xpub - xpub
* @param {number} gapLimit - (optional) gap limit for derivation
* @param {number} startIndex - (optional) rescan shall start from this index
* @param {number=} gapLimit - (optional) gap limit for derivation
* @param {number=} startIndex - (optional) rescan shall start from this index
* @returns {Promise}
*/
async rescan(xpub, gapLimit, startIndex) {

5
lib/bitcoin/parallel-address-derivation.js

@ -25,7 +25,7 @@ const BIP84 = 2
* @param {bip32} 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>}
*/
async function deriveAddress(chain, chainNode, index, type) {
// Derive M/chain/index
@ -33,7 +33,8 @@ async function deriveAddress(chain, chainNode, index, type) {
const addr = {
chain: chain,
index: index
index: index,
publicKey: indexNode.publicKey
}
switch (type) {

3
tracker/transaction.js

@ -365,7 +365,8 @@ class Transaction {
const indices = _.range(minIdx, maxIdx)
const derived = await hdaHelper.deriveAddresses(xpub, chain, indices, hdType)
Array.prototype.push.apply(newAddresses, derived)
newAddresses.push(...derived)
Logger.info(`Tracker : Derived hdID(${hdAccount.hdID}) M/${chain}/${indices.join(',')}`)

Loading…
Cancel
Save