From a868d2740748b8fe8c9276951739061c237038bd Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 19 Oct 2017 11:22:17 +1100 Subject: [PATCH] TxBuilder: add support for RSBuffer type keyPairs and .publicKey --- src/transaction_builder.js | 13 +++++++++---- test/transaction_builder.js | 13 +++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/transaction_builder.js b/src/transaction_builder.js index e2469e4..4892e06 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -667,7 +667,8 @@ function canSign (input) { } TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashType, witnessValue, witnessScript) { - if (keyPair.network !== this.network) throw new Error('Inconsistent network') + // TODO: remove keyPair.network matching in 4.0.0 + if (keyPair.network && keyPair.network !== this.network) throw new TypeError('Inconsistent network') if (!this.inputs[vin]) throw new Error('No input at index: ' + vin) hashType = hashType || Transaction.SIGHASH_ALL @@ -680,7 +681,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy throw new Error('Inconsistent redeemScript') } - var kpPubKey = keyPair.getPublicKeyBuffer() + var kpPubKey = keyPair.publicKey || keyPair.getPublicKeyBuffer() if (!canSign(input)) { if (witnessValue !== undefined) { if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue') @@ -699,14 +700,18 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy } else { signatureHash = this.tx.hashForSignature(vin, input.signScript, hashType) } + // enforce in order signing of public keys var signed = input.pubKeys.some(function (pubKey, i) { if (!kpPubKey.equals(pubKey)) return false if (input.signatures[i]) throw new Error('Signature already exists') - if (!keyPair.compressed && + if (kpPubKey.length !== 33 && input.signType === scriptTypes.P2WPKH) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH') - input.signatures[i] = keyPair.sign(signatureHash).toScriptSignature(hashType) + var signature = keyPair.sign(signatureHash) + if (Buffer.isBuffer(signature)) signature = ECSignature.fromRSBuffer(signature) + + input.signatures[i] = signature.toScriptSignature(hashType) return true }) diff --git a/test/transaction_builder.js b/test/transaction_builder.js index 82dda19..bcc331e 100644 --- a/test/transaction_builder.js +++ b/test/transaction_builder.js @@ -294,6 +294,19 @@ describe('TransactionBuilder', function () { }) describe('sign', function () { + it('supports the alternative abstract interface { publicKey, sign }', function () { + var keyPair = { + publicKey: Buffer.alloc(33, 0x03), + sign: function (hash) { return Buffer.alloc(64) } + } + + var txb = new TransactionBuilder() + txb.addInput('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 1) + txb.addOutput('1111111111111111111114oLvT2', 100000) + txb.sign(0, keyPair) + assert.equal(txb.build().toHex(), '0100000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010000002c0930060201000201000121030303030303030303030303030303030303030303030303030303030303030303ffffffff01a0860100000000001976a914000000000000000000000000000000000000000088ac00000000') + }) + fixtures.invalid.sign.forEach(function (f) { it('throws on ' + f.exception + (f.description ? ' (' + f.description + ')' : ''), function () { var txb = construct(f, true)