Skip to content

Commit d6e55de

Browse files
author
Danny Diekroeger
committed
added support for BCASH signing (was breaking before)
1 parent a48098f commit d6e55de

File tree

4 files changed

+47
-33
lines changed

4 files changed

+47
-33
lines changed

app/sign.js

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ const utxoNetworks = {
1515
dash: utxoLib.networks.dash,
1616
tltc: utxoLib.networks.litecoin,
1717
tbtc: utxoLib.networks.testnet,
18-
tbch: utxoLib.networks.bitcoincash,
19-
tzec: utxoLib.networks.zcash,
20-
tdash: utxoLib.networks.dash,
18+
tbch: utxoLib.networks.bitcoincashTestnet,
19+
tzec: utxoLib.networks.zcashTest,
20+
tdash: utxoLib.networks.dashTest,
2121
};
2222

2323
const coinDecimals = {
@@ -33,7 +33,10 @@ const coinDecimals = {
3333
teth: 18,
3434
txrp: 6,
3535
tltc: 8,
36-
txlm: 7
36+
txlm: 7,
37+
tbch: 8,
38+
tzec: 8,
39+
tdash: 8,
3740
};
3841

3942
const TEN = new BN(10);
@@ -63,7 +66,7 @@ const getHDNodeAndVerify = function(xprv, expectedXpub) {
6366
let node;
6467

6568
try {
66-
node = prova.HDNode.fromBase58(xprv);
69+
node = utxoLib.HDNode.fromBase58(xprv);
6770
} catch (e) {
6871
throw new Error('invalid private key');
6972
}
@@ -87,6 +90,7 @@ const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
8790
throw new Error(`Unsupported coin: ${recoveryRequest.coin}`);
8891
}
8992

93+
const isBCH = recoveryRequest.coin === 'bch' || recoveryRequest.coin === 'tbch';
9094
const transaction = utxoLib.Transaction.fromHex(recoveryRequest.transactionHex, network);
9195

9296
const outputs = transaction.outs.map(out => ({
@@ -106,6 +110,13 @@ const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
106110
// force override network as we use btc mainnet xpubs for all utxo coins
107111
backupKeyNode.keyPair.network = network;
108112

113+
// For BCH we need to add the input values to each input, because input values must be signed
114+
if (isBCH) {
115+
transaction.ins.forEach(function (input, i) {
116+
transaction.ins[i].value = recoveryRequest.inputs[i].amount;
117+
})
118+
}
119+
109120
const txBuilder = utxoLib.TransactionBuilder.fromTransaction(transaction, network);
110121

111122
_.forEach(recoveryRequest.inputs, function(input, i) {
@@ -121,19 +132,23 @@ const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
121132

122133
console.log(`Signing input ${ i + 1 } of ${ recoveryRequest.inputs.length } with ${ derivedHDNode.neutered().toBase58() } (${ input.chainPath })`);
123134

124-
if (isBech32) {
125-
const witnessScript = Buffer.from(input.witnessScript, 'hex');
126-
const witnessScriptHash = utxoLib.crypto.sha256(witnessScript);
127-
const prevOutScript = utxoLib.script.witnessScriptHash.output.encode(witnessScriptHash);
128-
txBuilder.sign(i, derivedHDNode.keyPair, prevOutScript, utxoLib.Transaction.SIGHASH_ALL, input.amount, witnessScript);
129-
} else {
135+
if (isBCH) {
130136
const redeemScript = new Buffer(input.redeemScript, 'hex');
131-
132-
if (isSegwit) {
133-
const witnessScript = new Buffer(input.witnessScript, 'hex');
134-
txBuilder.sign(i, derivedHDNode.keyPair, redeemScript, utxoLib.Transaction.SIGHASH_ALL, input.amount, witnessScript)
137+
txBuilder.sign(i, derivedHDNode.keyPair, redeemScript, utxoLib.Transaction.SIGHASH_BITCOINCASHBIP143 | utxoLib.Transaction.SIGHASH_ALL, input.amount);
138+
} else {
139+
if (isBech32) {
140+
const witnessScript = Buffer.from(input.witnessScript, 'hex');
141+
const witnessScriptHash = utxoLib.crypto.sha256(witnessScript);
142+
const prevOutScript = utxoLib.script.witnessScriptHash.output.encode(witnessScriptHash);
143+
txBuilder.sign(i, derivedHDNode.keyPair, prevOutScript, utxoLib.Transaction.SIGHASH_ALL, input.amount, witnessScript);
135144
} else {
136-
txBuilder.sign(i, derivedHDNode.keyPair, redeemScript, utxoLib.Transaction.SIGHASH_ALL);
145+
const redeemScript = new Buffer(input.redeemScript, 'hex');
146+
if (isSegwit) {
147+
const witnessScript = new Buffer(input.witnessScript, 'hex');
148+
txBuilder.sign(i, derivedHDNode.keyPair, redeemScript, utxoLib.Transaction.SIGHASH_ALL, input.amount, witnessScript)
149+
} else {
150+
txBuilder.sign(i, derivedHDNode.keyPair, redeemScript, utxoLib.Transaction.SIGHASH_ALL);
151+
}
137152
}
138153
}
139154
});
@@ -308,7 +323,7 @@ const parseKey = function(rawkey, coin, path) {
308323

309324
}
310325
// if it doesn't have commas, we expect it is an xprv or xlmsecret properly formatted
311-
return key;
326+
return rawkey;
312327
}
313328

314329
const handleSign = function(args) {

bin/admin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ const admin = require('../app/admin');
55

66
Promise.try(admin.run).catch(function(e) {
77
console.log(e.message);
8+
console.log(e.stack);
89
admin.db.connection.close();
910
});

package-lock.json

Lines changed: 13 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"argparse": "^1.0.10",
1919
"bignumber.js": "^7.2.1",
2020
"bitcoinjs-message": "^2.0.0",
21-
"bitgo-utxo-lib": "^1.1.2",
21+
"bitgo-utxo-lib": "^1.2.1",
2222
"body-parser": "^1.18.3",
2323
"dotenv": "^6.2.0",
2424
"ethereumjs-tx": "^1.3.7",

0 commit comments

Comments
 (0)