Skip to content

Commit 3b4998e

Browse files
authored
Merge pull request #90 from BitGo/BG-34381.use-bitgo-dep
chore(package): use @bitgo/utxo-lib
2 parents 76462f0 + 055d881 commit 3b4998e

File tree

6 files changed

+1709
-16646
lines changed

6 files changed

+1709
-16646
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
*.swp
2+
*.iml
23
.idea/
34
node_modules
45
npm-debug.log

app/sign.js

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const Promise = require('bluebird');
22
const co = Promise.coroutine;
3-
const utxoLib = require('bitgo-utxo-lib');
3+
const bip32 = require('bip32');
4+
const utxolib = require('@bitgo/utxo-lib');
45
const accountLib = require('@bitgo/account-lib');
56
const statics = require('@bitgo/statics');
67
const fs = require('fs');
@@ -14,18 +15,18 @@ const bitgojs = require('bitgo');
1415
let bitgo;
1516

1617
const utxoNetworks = {
17-
btc: utxoLib.networks.bitcoin,
18-
ltc: utxoLib.networks.litecoin,
19-
bch: utxoLib.networks.bitcoincash,
20-
bsv: utxoLib.networks.bitcoinsv,
21-
zec: utxoLib.networks.zcash,
22-
dash: utxoLib.networks.dash,
23-
tltc: utxoLib.networks.litecoin,
24-
tbtc: utxoLib.networks.testnet,
25-
tbch: utxoLib.networks.bitcoincashTestnet,
26-
tbsv: utxoLib.networks.bitcoinsvTestnet,
27-
tzec: utxoLib.networks.zcashTest,
28-
tdash: utxoLib.networks.dashTest
18+
btc: utxolib.networks.bitcoin,
19+
ltc: utxolib.networks.litecoin,
20+
bch: utxolib.networks.bitcoincash,
21+
bsv: utxolib.networks.bitcoinsv,
22+
zec: utxolib.networks.zcash,
23+
dash: utxolib.networks.dash,
24+
tltc: utxolib.networks.litecoin,
25+
tbtc: utxolib.networks.testnet,
26+
tbch: utxolib.networks.bitcoincashTestnet,
27+
tbsv: utxolib.networks.bitcoinsvTestnet,
28+
tzec: utxolib.networks.zcashTest,
29+
tdash: utxolib.networks.dashTest
2930
};
3031

3132
const coinDecimals = {
@@ -90,7 +91,7 @@ const getHDNodeAndVerify = function(xprv, expectedXpub) {
9091
let node;
9192

9293
try {
93-
node = utxoLib.HDNode.fromBase58(xprv);
94+
node = bip32.fromBase58(xprv);
9495
} catch (e) {
9596
throw new Error('invalid private key');
9697
}
@@ -131,12 +132,10 @@ const promptForConfirmationAndKey = function(recoveryRequest, outputs, skipConfi
131132
* Gets the backup private key that can be used to sign the transaction.
132133
* @param xprv The provided extended private key (BIP32).
133134
* @param expectedXpub The public key specified with the request.
134-
* @returns The private key to sign the transaction.
135+
* @returns {Buffer} - the private key buffer to sign the transaction.
135136
*/
136137
const getBackupSigningKey = function(xprv, expectedXpub) {
137-
const backupKeyNode = getHDNodeAndVerify(xprv, expectedXpub);
138-
139-
return backupKeyNode.keyPair.getPrivateKeyBuffer();
138+
return getHDNodeAndVerify(xprv, expectedXpub).privateKey;
140139
};
141140

142141
const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
@@ -148,25 +147,26 @@ const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
148147
}
149148

150149
const txHex = getTransactionHexFromRequest(recoveryRequest);
151-
const transaction = utxoLib.Transaction.fromHex(txHex, network);
150+
const transaction = utxolib.Transaction.fromHex(txHex, network);
152151

153152
const outputs = transaction.outs.map(out => ({
154-
address: utxoLib.address.fromOutputScript(out.script, network),
153+
address: utxolib.address.fromOutputScript(out.script, network),
155154
amount: ( new BN(out.value) ).div( TEN.pow(decimals) ).toString()
156155
}));
157156

158157
key = promptForConfirmationAndKey(recoveryRequest, outputs, skipConfirm, key);
159158

160-
const backupKeyNode = getHDNodeAndVerify(key, recoveryRequest.backupKey);
161-
162159
// force override network as we use btc mainnet xpubs for all utxo coins
163-
backupKeyNode.keyPair.network = network;
160+
const backupKeyNode = Object.assign(
161+
getHDNodeAndVerify(key, recoveryRequest.backupKey),
162+
{ network }
163+
);
164164

165165
transaction.ins.forEach(function (input, i) {
166166
transaction.ins[i].value = recoveryRequest.inputs[i].amount;
167167
});
168168

169-
const txBuilder = utxoLib.TransactionBuilder.fromTransaction(transaction, network);
169+
const txBuilder = utxolib.TransactionBuilder.fromTransaction(transaction, network);
170170

171171
_.forEach(recoveryRequest.inputs, function(input, i) {
172172

@@ -183,8 +183,8 @@ const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
183183
// Handle BCH
184184
if (BCH_COINS.includes(recoveryRequest.coin)) {
185185
const redeemScript = new Buffer(input.redeemScript, 'hex');
186-
txBuilder.sign(i, derivedHDNode.keyPair, redeemScript,
187-
utxoLib.Transaction.SIGHASH_BITCOINCASHBIP143 | utxoLib.Transaction.SIGHASH_ALL, input.amount);
186+
txBuilder.sign(i, derivedHDNode, redeemScript,
187+
utxolib.Transaction.SIGHASH_BITCOINCASHBIP143 | utxolib.Transaction.SIGHASH_ALL, input.amount);
188188
// in a Lodash forEach loop, 'return' operates like 'continue' does
189189
// in a regular javascript loop. It finishes this iteration and moves to the next iteration
190190
return;
@@ -193,24 +193,24 @@ const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
193193
// Handle Bech32
194194
if (!input.redeemScript) {
195195
const witnessScript = Buffer.from(input.witnessScript, 'hex');
196-
const witnessScriptHash = utxoLib.crypto.sha256(witnessScript);
197-
const prevOutScript = utxoLib.script.witnessScriptHash.output.encode(witnessScriptHash);
198-
txBuilder.sign(i, derivedHDNode.keyPair, prevOutScript,
199-
utxoLib.Transaction.SIGHASH_ALL, input.amount, witnessScript);
196+
const witnessScriptHash = utxolib.crypto.sha256(witnessScript);
197+
const prevOutScript = utxolib.script.witnessScriptHash.output.encode(witnessScriptHash);
198+
txBuilder.sign(i, derivedHDNode, prevOutScript,
199+
utxolib.Transaction.SIGHASH_ALL, input.amount, witnessScript);
200200
return;
201201
}
202202

203203
// Handle Wrapped Segwit
204204
const redeemScript = new Buffer(input.redeemScript, 'hex');
205205
if (input.witnessScript) {
206206
const witnessScript = new Buffer(input.witnessScript, 'hex');
207-
txBuilder.sign(i, derivedHDNode.keyPair, redeemScript,
208-
utxoLib.Transaction.SIGHASH_ALL, input.amount, witnessScript);
207+
txBuilder.sign(i, derivedHDNode, redeemScript,
208+
utxolib.Transaction.SIGHASH_ALL, input.amount, witnessScript);
209209
return;
210210
}
211211

212212
// Handle all other requests
213-
txBuilder.sign(i, derivedHDNode.keyPair, redeemScript, utxoLib.Transaction.SIGHASH_ALL, input.amount);
213+
txBuilder.sign(i, derivedHDNode, redeemScript, utxolib.Transaction.SIGHASH_ALL, input.amount);
214214
});
215215

216216
return txBuilder.build().toHex();
@@ -347,8 +347,8 @@ const handleSignXrp = function(recoveryRequest, key, skipConfirm) {
347347

348348
const backupKeyNode = getHDNodeAndVerify(key, recoveryRequest.backupKey);
349349

350-
const backupAddress = rippleKeypairs.deriveAddress(backupKeyNode.keyPair.getPublicKeyBuffer().toString('hex'));
351-
const privateKeyHex = backupKeyNode.keyPair.getPrivateKeyBuffer().toString('hex');
350+
const backupAddress = rippleKeypairs.deriveAddress(backupKeyNode.publicKey.toString('hex'));
351+
const privateKeyHex = backupKeyNode.privateKey.toString('hex');
352352
const cosignedTx = utils.signXrpWithPrivateKey(txHex, privateKeyHex, { signAs: backupAddress });
353353

354354
return rippleApi.combine([txHex, cosignedTx.signedTransaction]).signedTransaction;
@@ -421,20 +421,18 @@ const parseKey = co(function *(rawkey, coin, path) {
421421
throw new Error('Invalid mnemonic');
422422
}
423423
const seed = yield bip39.mnemonicToSeed(mnemonic);
424-
let node = utxoLib.HDNode.fromSeedBuffer(seed);
424+
let node = bip32.fromSeed(seed);
425425
if (path) {
426426
node = node.derivePath(path);
427427
}
428428
const xprv = node.toBase58();
429429
return xprv;
430430

431431
}
432-
// if it doesn't have commas, we expect it is an xprv or xlmsecret properly formatted
433432
if (path) {
434-
let node = utxoLib.HDNode.fromPrivateKeyBuffer(Buffer.from(rawkey, 'hex'));
435-
node = node.derivePath(path);
436-
return node.toBase58();
433+
throw new Error('can only derive subkey from bip32 xprv');
437434
}
435+
// if it doesn't have commas or a path, return unchanged input
438436
return rawkey;
439437
});
440438

app/utils.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
const bip32 = require('bip32');
12
const Promise = require('bluebird');
23
const co = Promise.coroutine;
34
const Q = require('q');
45
const binary = require('ripple-binary-codec');
56
const nodemailer = require('nodemailer');
67
const smtpTransport = require('nodemailer-smtp-transport');
78
const jsrender = require('jsrender');
8-
const prova = require('prova-lib');
9-
const utxoLib = require('bitgo-utxo-lib');
9+
const utxolib = require('@bitgo/utxo-lib');
1010
const stellar = require('stellar-base');
1111
const stellarHd = require('stellar-hd-wallet');
1212
const rippleParse = require('ripple-binary-codec');
@@ -111,7 +111,7 @@ function IsValidBip32Seed(input) {
111111

112112
exports.deriveChildKey = function(master, derivationPath, type, neuter) {
113113
if (type === 'xpub' || type === 'xprv') {
114-
const masterNode = utxoLib.HDNode.fromBase58(master);
114+
const masterNode = bip32.fromBase58(master);
115115
const childKey = masterNode.derivePath(derivationPath);
116116

117117
if (neuter) {
@@ -151,7 +151,7 @@ exports.signXrpWithPrivateKey = function(txHex, privateKey, options) {
151151
if (privateKeyBuffer.length === 33 && privateKeyBuffer[0] === 0) {
152152
privateKeyBuffer = privateKeyBuffer.slice(1, 33);
153153
}
154-
const privateKeyObject = prova.ECPair.fromPrivateKeyBuffer(privateKeyBuffer);
154+
const privateKeyObject = utxolib.bitgo.keyutil.privateKeyBufferToECPair(privateKeyBuffer);
155155
const publicKey = privateKeyObject.getPublicKeyBuffer().toString('hex').toUpperCase();
156156

157157
let tx;

0 commit comments

Comments
 (0)