Verified Commit 710062a3 authored by Pavel Ševčík's avatar Pavel Ševčík
Browse files

Merge branch 'feature/update-dependencies' into develop

parents fba396cf 80213f62
......@@ -159,6 +159,17 @@ class AddressesHelper {
&& scriptpubkey[1] === 0x20
}
/**
* Check if an output script is a P2TR script
* @param {Buffer} scriptpubkey - scriptpubkey
* @returns {boolean} return true if output is a P2TR script, otherwise return false
*/
isP2trScript(scriptpubkey) {
return scriptpubkey.length === 34
&& scriptpubkey[0] === OPS.OP_1
&& scriptpubkey[1] === 0x20
}
/**
* Return the bitcoin address corresponding to an output script
* @param {Buffer} scriptpubkey - scriptpubkey
......@@ -189,7 +200,10 @@ class AddressesHelper {
network: activeNet,
}).address
throw 'unknown address format'
// TODO: Add P2TR address transformation when bitcoinjs-lib supports it
// if (this.isP2trScript(scriptpubkey))
return bitcoin.address.fromOutputScript(scriptpubkey, activeNet)
}
}
......
......@@ -8,6 +8,8 @@ import path from 'path'
import QuickLRU from 'quick-lru'
import workerPool from 'workerpool'
import bitcoin from 'bitcoinjs-lib'
import BIP32Factory from 'bip32'
import * as ecc from 'tiny-secp256k1'
import bs58check from 'bs58check'
import bs58 from 'bs58'
......@@ -20,8 +22,14 @@ import addrHelper from './addresses-helper.js'
const activeNet = network.network
const keys = keysFile[network.key]
const bip32 = BIP32Factory.default(ecc)
const MAX_SAFE_INT_32 = Math.pow(2, 31) - 1
/**
* @typedef {import('bip32').BIP32Interface} BIP32Interface
*/
/**
* A singleton providing HD Accounts helper functions
*/
......@@ -269,7 +277,7 @@ class HDAccountsHelper {
const xlatedXpub = this.xlatXPUB(xpub)
// Parse input as an HD Node. Throws if invalid
const node = bitcoin.bip32.fromBase58(xlatedXpub, activeNet)
const node = bip32.fromBase58(xlatedXpub, activeNet)
// Check and see if this is a private key
if (!node.isNeutered())
......@@ -289,7 +297,7 @@ class HDAccountsHelper {
/**
* Get the hd node associated to an hd account
* @param {string} xpub - hd account
* @returns {[bitcoin.bip32.BIP32Interface, bitcoin.bip32.BIP32Interface, bitcoin.bip32.BIP32Interface]}
* @returns {[BIP32Interface, BIP32Interface, BIP32Interface]}
*/
getNode(xpub) {
return this.isValid(xpub) ? this.nodes.get(xpub) : null
......@@ -299,7 +307,7 @@ 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 {bitcoin.bip32.BIP32Interface} chainNode - Parent bip32 used for derivation
* @param {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>, address: string }
......@@ -409,7 +417,7 @@ class HDAccountsHelper {
/**
* @description Detect postmix account
* @param {[bitcoin.bip32.BIP32Interface, bitcoin.bip32.BIP32Interface, bitcoin.bip32.BIP32Interface]} node - array of BIP32 node interfaces
* @param {[BIP32Interface, BIP32Interface, BIP32Interface]} node - array of BIP32 node interfaces
* @returns {boolean}
*/
isPostmixAcct(node) {
......
......@@ -4,7 +4,8 @@
*/
import bitcoin from 'bitcoinjs-lib'
import BIP32Factory from 'bip32'
import * as ecc from 'tiny-secp256k1'
import workerPool from 'workerpool'
import errors from '../errors.js'
......@@ -13,6 +14,8 @@ import addrHelper from './addresses-helper.js'
const activeNet = network.network
const bip32 = BIP32Factory.default(ecc)
/**
* Constants duplicated from HDAccountsHelper
*/
......@@ -20,12 +23,15 @@ const BIP44 = 0
const BIP49 = 1
const BIP84 = 2
/**
* @typedef {import('bip32').BIP32Interface} BIP32Interface
*/
/**
* 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 {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>}
......@@ -68,7 +74,7 @@ async function deriveAddresses(msg) {
const isPostmixChange = msg.isPostmixChange
// Parse input as an HD Node. Throws if invalid
const node = bitcoin.bip32.fromBase58(xpub, activeNet)
const node = bip32.fromBase58(xpub, activeNet)
// Check and see if this is a private key
if (!node.isNeutered())
......
This diff is collapsed.
......@@ -79,6 +79,29 @@ const VECTOR_5 = [
]
]
const SCRIPT_PUBKEY_VECTORS = [
[
'76a914ad4308d34646441b365fb71089b25b9a8454d91388ac', // P2PKH
'mwK5VsrRPki1DdGfGtX5srtisxdJwnqrao'
],
[
'a91422d760255d1fb03d44538c0340f8e7fa59c5fe8587', // P2SH
'2MvRSyN1sefUKSEb6QGq8ZEuDXcTA2Df2S4'
],
[
'0014f60834ef165253c571b11ce9fa74e46692fc5ec1', // P2WPKH
'tb1q7cyrfmck2ffu2ud3rn5l5a8yv6f0chkp9y62q6'
],
[
'0020b1de16ca69d3946907ac5e5fe19b609eea46c06b7bd366d1ae0a831e547f014c', // P2WSH v0
'tb1qk80pdjnf6w2xjpavte07rxmqnm4ydsrt00fkd5dwp2p3u4rlq9xq65vqf8'
],
[
'5120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c', // P2WSH v1 (P2TR)
'tb1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqp3mvzv'
]
]
describe('AddressesHelper', () => {
......@@ -163,4 +186,86 @@ describe('AddressesHelper', () => {
})
})
describe('isP2pkhScript()', () => {
const p2pkhScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[0][0], 'hex')
const p2shScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[1][0], 'hex')
it('should successfully detect P2PKH scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2pkhScript(p2pkhScriptPubKey), true)
})
it('should return false for non P2PKH scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2pkhScript(p2shScriptPubKey), false)
})
})
describe('isP2shScript()', () => {
const p2shScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[1][0], 'hex')
const p2wpkhScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[2][0], 'hex')
it('should successfully detect P2SKH scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2shScript(p2shScriptPubKey), true)
})
it('should return false for non P2SKH scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2shScript(p2wpkhScriptPubKey), false)
})
})
describe('isP2wpkhScript()', () => {
const p2wpkhScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[2][0], 'hex')
const p2pkhScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[3][0], 'hex')
it('should successfully detect P2WPKH scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2wpkhScript(p2wpkhScriptPubKey), true)
})
it('should return false for non P2WPKH scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2wpkhScript(p2pkhScriptPubKey), false)
})
})
describe('isP2wshScript()', () => {
const p2wshhScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[3][0], 'hex')
const p2wpkhScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[2][0], 'hex')
it('should successfully detect P2WSH scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2wshScript(p2wshhScriptPubKey), true)
})
it('should return false for non P2WSH scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2wshScript(p2wpkhScriptPubKey), false)
})
})
describe('isP2trScript()', () => {
const p2trScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[4][0], 'hex')
const p2wshScriptPubKey = Buffer.from(SCRIPT_PUBKEY_VECTORS[3][0], 'hex')
it('should successfully detect P2TR scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2trScript(p2trScriptPubKey), true)
})
it('should return false for non P2TR scriptpubkey', () => {
assert.strictEqual(addrHelper.isP2trScript(p2wshScriptPubKey), false)
})
})
describe('outputScript2Address()', () => {
it('should return correct address corresponding to scriptpubkey', () => {
for (const [scriptPubKey, address] of SCRIPT_PUBKEY_VECTORS) {
const scriptPubKeyBuffer = Buffer.from(scriptPubKey, 'hex')
const convertedAddress = addrHelper.outputScript2Address(scriptPubKeyBuffer)
assert.strictEqual(convertedAddress, address)
}
})
it('should throw an error on invalid sciptpubkey', () => {
const randomData = Buffer.from('5120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc48705', 'hex')
assert.throws(() => addrHelper.outputScript2Address(randomData))
})
})
})
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment