diff --git a/src/ecpair.js b/src/ecpair.js index 0e2cf26..777c254 100644 --- a/src/ecpair.js +++ b/src/ecpair.js @@ -36,9 +36,23 @@ ECPair.prototype.toWIF = function () { return wif.encode(this.network.wif, this.__d, this.compressed) } -ECPair.prototype.sign = function (hash) { +ECPair.prototype.sign = function (hash, lowR) { if (!this.__d) throw new Error('Missing private key') - return ecc.sign(hash, this.__d) + if (lowR !== undefined && typeof lowR !== 'boolean') throw new Error('lowR must be a boolean') + + let signature = ecc.sign(hash, this.__d) + + if (lowR) { + let counter = 0 + let extraEntropy = Buffer.alloc(32, 0) + while (signature[0] > 0x7f) { + counter++ + extraEntropy.writeUIntLE(counter, 0, 6) + signature = ecc.sign(hash, this.__d, extraEntropy) + } + } + + return signature } ECPair.prototype.verify = function (hash, signature) { diff --git a/src/transaction_builder.js b/src/transaction_builder.js index 8706841..99d8b62 100644 --- a/src/transaction_builder.js +++ b/src/transaction_builder.js @@ -438,6 +438,7 @@ function TransactionBuilder (network, maximumFeeRate) { this.__inputs = [] this.__tx = new Transaction() this.__tx.version = 2 + this.__lowR = false } TransactionBuilder.prototype.setLockTime = function (locktime) { @@ -462,6 +463,12 @@ TransactionBuilder.prototype.setVersion = function (version) { this.__tx.version = version } +TransactionBuilder.prototype.setLowR = function (lowR) { + typeforce(types.Boolean, lowR) + + this.__lowR = lowR +} + TransactionBuilder.fromTransaction = function (transaction, network) { const txb = new TransactionBuilder(network) @@ -680,7 +687,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH') } - const signature = keyPair.sign(signatureHash) + const signature = keyPair.sign(signatureHash, this.__lowR) input.signatures[i] = bscript.signature.encode(signature, hashType) return true })