Browse Source

rm ECSignature, add script.signature instead

addLowRGrinding
Daniel Cousens 8 years ago
parent
commit
c58ada362e
  1. 6
      src/ecdsa.js
  2. 97
      src/ecsignature.js
  3. 1
      src/index.js
  4. 1
      src/script.js
  5. 51
      src/script_signature.js
  6. 7
      src/transaction_builder.js
  7. 9
      test/bitcoin.core.js
  8. 31
      test/ecdsa.js
  9. 61
      test/fixtures/ecdsa.json
  10. 140
      test/fixtures/signature.json
  11. 11
      test/integration/cltv.js
  12. 2
      test/integration/crypto.js
  13. 2
      test/integration/transactions.js
  14. 65
      test/signature.js

6
src/ecdsa.js

@ -4,7 +4,6 @@ var typeforce = require('typeforce')
var types = require('./types') var types = require('./types')
var BigInteger = require('bigi') var BigInteger = require('bigi')
var ECSignature = require('./ecsignature')
var ZERO = Buffer.alloc(1, 0) var ZERO = Buffer.alloc(1, 0)
var ONE = Buffer.alloc(1, 1) var ONE = Buffer.alloc(1, 1)
@ -102,7 +101,10 @@ function sign (hash, d) {
s = n.subtract(s) s = n.subtract(s)
} }
return new ECSignature(r, s) return {
r: r,
s: s
}
} }
function verify (hash, signature, Q) { function verify (hash, signature, Q) {

97
src/ecsignature.js

@ -1,97 +0,0 @@
var bip66 = require('bip66')
var typeforce = require('typeforce')
var types = require('./types')
var BigInteger = require('bigi')
function ECSignature (r, s) {
typeforce(types.tuple(types.BigInt, types.BigInt), arguments)
this.r = r
this.s = s
}
ECSignature.parseCompact = function (buffer) {
typeforce(types.BufferN(65), buffer)
var flagByte = buffer.readUInt8(0) - 27
if (flagByte !== (flagByte & 7)) throw new Error('Invalid signature parameter')
var compressed = !!(flagByte & 4)
var recoveryParam = flagByte & 3
var signature = ECSignature.fromRSBuffer(buffer.slice(1))
return {
compressed: compressed,
i: recoveryParam,
signature: signature
}
}
ECSignature.fromRSBuffer = function (buffer) {
typeforce(types.BufferN(64), buffer)
var r = BigInteger.fromBuffer(buffer.slice(0, 32))
var s = BigInteger.fromBuffer(buffer.slice(32, 64))
return new ECSignature(r, s)
}
ECSignature.fromDER = function (buffer) {
var decode = bip66.decode(buffer)
var r = BigInteger.fromDERInteger(decode.r)
var s = BigInteger.fromDERInteger(decode.s)
return new ECSignature(r, s)
}
// BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed)
ECSignature.parseScriptSignature = function (buffer) {
var hashType = buffer.readUInt8(buffer.length - 1)
var hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0x00 || hashTypeMod >= 0x04) throw new Error('Invalid hashType ' + hashType)
return {
signature: ECSignature.fromDER(buffer.slice(0, -1)),
hashType: hashType
}
}
ECSignature.prototype.toCompact = function (i, compressed) {
if (compressed) {
i += 4
}
i += 27
var buffer = Buffer.alloc(65)
buffer.writeUInt8(i, 0)
this.toRSBuffer(buffer, 1)
return buffer
}
ECSignature.prototype.toDER = function () {
var r = Buffer.from(this.r.toDERInteger())
var s = Buffer.from(this.s.toDERInteger())
return bip66.encode(r, s)
}
ECSignature.prototype.toRSBuffer = function (buffer, offset) {
buffer = buffer || Buffer.alloc(64)
this.r.toBuffer(32).copy(buffer, offset)
this.s.toBuffer(32).copy(buffer, offset + 32)
return buffer
}
ECSignature.prototype.toScriptSignature = function (hashType) {
var hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
var hashTypeBuffer = Buffer.alloc(1)
hashTypeBuffer.writeUInt8(hashType, 0)
return Buffer.concat([this.toDER(), hashTypeBuffer])
}
module.exports = ECSignature

1
src/index.js

@ -8,7 +8,6 @@ for (var key in templates) {
module.exports = { module.exports = {
Block: require('./block'), Block: require('./block'),
ECPair: require('./ecpair'), ECPair: require('./ecpair'),
ECSignature: require('./ecsignature'),
HDNode: require('./hdnode'), HDNode: require('./hdnode'),
Transaction: require('./transaction'), Transaction: require('./transaction'),
TransactionBuilder: require('./transaction_builder'), TransactionBuilder: require('./transaction_builder'),

1
src/script.js

@ -206,6 +206,7 @@ module.exports = {
toStack: toStack, toStack: toStack,
number: require('./script_number'), number: require('./script_number'),
signature: require('./script_signature'),
isCanonicalPubKey: isCanonicalPubKey, isCanonicalPubKey: isCanonicalPubKey,
isCanonicalSignature: isCanonicalSignature, isCanonicalSignature: isCanonicalSignature,

51
src/script_signature.js

@ -0,0 +1,51 @@
var bip66 = require('bip66')
var BigInteger = require('bigi')
var typeforce = require('typeforce')
var types = require('./types')
// BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed)
function decode (buffer) {
var hashType = buffer.readUInt8(buffer.length - 1)
var hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
var decode = bip66.decode(buffer.slice(0, -1))
return {
signature: {
r: BigInteger.fromDERInteger(decode.r),
s: BigInteger.fromDERInteger(decode.s)
},
hashType: hashType
}
}
function fromRSBuffer (buffer) {
typeforce(types.BufferN(64), buffer)
var r = BigInteger.fromBuffer(buffer.slice(0, 32))
var s = BigInteger.fromBuffer(buffer.slice(32, 64))
return { r: r, s: s }
}
function encode (signature, hashType) {
var hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
var hashTypeBuffer = new Buffer(1)
hashTypeBuffer.writeUInt8(hashType, 0)
var r = new Buffer(signature.r.toDERInteger())
var s = new Buffer(signature.s.toDERInteger())
return Buffer.concat([
bip66.encode(r, s),
hashTypeBuffer
])
}
module.exports = {
fromRSBuffer,
decode: decode,
encode: encode
}

7
src/transaction_builder.js

@ -12,7 +12,6 @@ var SIGNABLE = [btemplates.types.P2PKH, btemplates.types.P2PK, btemplates.types.
var P2SH = SIGNABLE.concat([btemplates.types.P2WPKH, btemplates.types.P2WSH]) var P2SH = SIGNABLE.concat([btemplates.types.P2WPKH, btemplates.types.P2WSH])
var ECPair = require('./ecpair') var ECPair = require('./ecpair')
var ECSignature = require('./ecsignature')
var Transaction = require('./transaction') var Transaction = require('./transaction')
function supportedType (type) { function supportedType (type) {
@ -190,7 +189,7 @@ function fixMultisigOrder (input, transaction, vin) {
if (!signature) return false if (!signature) return false
// TODO: avoid O(n) hashForSignature // TODO: avoid O(n) hashForSignature
var parsed = ECSignature.parseScriptSignature(signature) var parsed = bscript.signature.decode(signature)
var hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType) var hash = transaction.hashForSignature(vin, input.redeemScript, parsed.hashType)
// skip if signature does not match pubKey // skip if signature does not match pubKey
@ -717,9 +716,9 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
)) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH') )) throw new Error('BIP143 rejects uncompressed public keys in P2WPKH or P2WSH')
var signature = keyPair.sign(signatureHash) var signature = keyPair.sign(signatureHash)
if (Buffer.isBuffer(signature)) signature = ECSignature.fromRSBuffer(signature) if (Buffer.isBuffer(signature)) signature = bscript.signature.fromRSBuffer(signature)
input.signatures[i] = signature.toScriptSignature(hashType) input.signatures[i] = bscript.signature.encode(signature, hashType)
return true return true
}) })

9
test/bitcoin.core.js

@ -198,13 +198,14 @@ describe('Bitcoin-core', function () {
}) })
}) })
describe('ECSignature.parseScriptSignature', function () { describe('script.signature.decode', function () {
sigCanonical.forEach(function (hex) { sigCanonical.forEach(function (hex) {
var buffer = Buffer.from(hex, 'hex') var buffer = Buffer.from(hex, 'hex')
it('can parse ' + hex, function () { it('can parse ' + hex, function () {
var parsed = bitcoin.ECSignature.parseScriptSignature(buffer) var parsed = bitcoin.script.signature.decode(buffer)
var actual = parsed.signature.toScriptSignature(parsed.hashType) var actual = bitcoin.script.signature.encode(parsed.signature, parsed.hashType)
assert.strictEqual(actual.toString('hex'), hex) assert.strictEqual(actual.toString('hex'), hex)
}) })
}) })
@ -218,7 +219,7 @@ describe('Bitcoin-core', function () {
it('throws on ' + description, function () { it('throws on ' + description, function () {
assert.throws(function () { assert.throws(function () {
bitcoin.ECSignature.parseScriptSignature(buffer) bitcoin.script.signature.decode(buffer)
}, /Expected DER (integer|sequence)|(R|S) value (excessively padded|is negative)|(R|S|DER sequence) length is (zero|too short|too long|invalid)|Invalid hashType/) }, /Expected DER (integer|sequence)|(R|S) value (excessively padded|is negative)|(R|S|DER sequence) length is (zero|too short|too long|invalid)|Invalid hashType/)
}) })
}) })

31
test/ecdsa.js

@ -2,17 +2,31 @@
var assert = require('assert') var assert = require('assert')
var bcrypto = require('../src/crypto') var bcrypto = require('../src/crypto')
var bscript = require('../src/script')
var ecdsa = require('../src/ecdsa') var ecdsa = require('../src/ecdsa')
var hoodwink = require('hoodwink') var hoodwink = require('hoodwink')
var BigInteger = require('bigi') var BigInteger = require('bigi')
var ECSignature = require('../src/ecsignature')
var curve = ecdsa.__curve var curve = ecdsa.__curve
var fixtures = require('./fixtures/ecdsa.json') var fixtures = require('./fixtures/ecdsa.json')
describe('ecdsa', function () { describe('ecdsa', function () {
function fromRaw (signature) {
return {
r: new BigInteger(signature.r, 16),
s: new BigInteger(signature.s, 16)
}
}
function toRaw (signature) {
return {
r: signature.r.toHex(),
s: signature.s.toHex()
}
}
describe('deterministicGenerateK', function () { describe('deterministicGenerateK', function () {
function checkSig () { function checkSig () {
return true return true
@ -80,9 +94,9 @@ describe('ecdsa', function () {
it('produces a deterministic signature for "' + f.message + '"', function () { it('produces a deterministic signature for "' + f.message + '"', function () {
var d = BigInteger.fromHex(f.d) var d = BigInteger.fromHex(f.d)
var hash = bcrypto.sha256(f.message) var hash = bcrypto.sha256(f.message)
var signature = ecdsa.sign(hash, d).toDER() var signature = ecdsa.sign(hash, d)
assert.strictEqual(signature.toString('hex'), f.signature) assert.deepEqual(toRaw(signature), f.signature)
}) })
}) })
@ -101,7 +115,7 @@ describe('ecdsa', function () {
it('verifies a valid signature for "' + f.message + '"', function () { it('verifies a valid signature for "' + f.message + '"', function () {
var d = BigInteger.fromHex(f.d) var d = BigInteger.fromHex(f.d)
var H = bcrypto.sha256(f.message) var H = bcrypto.sha256(f.message)
var signature = ECSignature.fromDER(Buffer.from(f.signature, 'hex')) var signature = fromRaw(f.signature)
var Q = curve.G.multiply(d) var Q = curve.G.multiply(d)
assert(ecdsa.verify(H, signature, Q)) assert(ecdsa.verify(H, signature, Q))
@ -112,14 +126,7 @@ describe('ecdsa', function () {
it('fails to verify with ' + f.description, function () { it('fails to verify with ' + f.description, function () {
var H = bcrypto.sha256(f.message) var H = bcrypto.sha256(f.message)
var d = BigInteger.fromHex(f.d) var d = BigInteger.fromHex(f.d)
var signature = fromRaw(f.signature)
var signature
if (f.signature) {
signature = ECSignature.fromDER(Buffer.from(f.signature, 'hex'))
} else if (f.signatureRaw) {
signature = new ECSignature(new BigInteger(f.signatureRaw.r, 16), new BigInteger(f.signatureRaw.s, 16))
}
var Q = curve.G.multiply(d) var Q = curve.G.multiply(d)
assert.strictEqual(ecdsa.verify(H, signature, Q), false) assert.strictEqual(ecdsa.verify(H, signature, Q), false)

61
test/fixtures/ecdsa.json

@ -5,50 +5,64 @@
"d": "01", "d": "01",
"k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5", "k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5",
"message": "Everything should be made as simple as possible, but not simpler.", "message": "Everything should be made as simple as possible, but not simpler.",
"i": 0, "signature": {
"signature": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262" "r": "33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c9",
"s": "6f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262"
}
}, },
{ {
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4", "k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4",
"message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.", "message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.",
"i": 0, "signature": {
"signature": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5" "r": "54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed",
"s": "07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
}
}, },
{ {
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5", "k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5",
"message": "Not only is the Universe stranger than we think, it is stranger than we can think.", "message": "Not only is the Universe stranger than we think, it is stranger than we can think.",
"i": 0, "signature": {
"signature": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283" "r": "ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd0",
"s": "6fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283"
}
}, },
{ {
"d": "0000000000000000000000000000000000000000000000000000000000000001", "d": "0000000000000000000000000000000000000000000000000000000000000001",
"k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f", "k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f",
"message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.", "message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.",
"i": 1, "signature": {
"signature": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3" "r": "c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3",
"s": "75afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3"
}
}, },
{ {
"d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64", "d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64",
"k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97", "k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97",
"message": "Computer science is no more about computers than astronomy is about telescopes.", "message": "Computer science is no more about computers than astronomy is about telescopes.",
"i": 0, "signature": {
"signature": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6" "r": "7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d",
"s": "0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6"
}
}, },
{ {
"d": "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637", "d": "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637",
"k": "097b5c8ee22c3ea78a4d3635e0ff6fe85a1eb92ce317ded90b9e71aab2b861cb", "k": "097b5c8ee22c3ea78a4d3635e0ff6fe85a1eb92ce317ded90b9e71aab2b861cb",
"message": "...if you aren't, at any given time, scandalized by code you wrote five or even three years ago, you're not learning anywhere near enough", "message": "...if you aren't, at any given time, scandalized by code you wrote five or even three years ago, you're not learning anywhere near enough",
"i": 1, "signature": {
"signature": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37" "r": "fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda487",
"s": "0e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37"
}
}, },
{ {
"d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3", "d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3",
"k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b", "k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b",
"message": "The question of whether computers can think is like the question of whether submarines can swim.", "message": "The question of whether computers can think is like the question of whether submarines can swim.",
"i": 1, "signature": {
"signature": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef" "r": "cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9",
"s": "06ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef"
}
} }
], ],
"rfc6979": [ "rfc6979": [
@ -130,13 +144,16 @@
"description": "The wrong signature", "description": "The wrong signature",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signature": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5" "signature": {
"r": "54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed",
"s": "07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5"
}
}, },
{ {
"description": "Invalid r value (< 0)", "description": "Invalid r value (< 0)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signatureRaw": { "signature": {
"r": "-01", "r": "-01",
"s": "02" "s": "02"
} }
@ -145,7 +162,7 @@
"description": "Invalid r value (== 0)", "description": "Invalid r value (== 0)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signatureRaw": { "signature": {
"r": "00", "r": "00",
"s": "02" "s": "02"
} }
@ -154,7 +171,7 @@
"description": "Invalid r value (>= n)", "description": "Invalid r value (>= n)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signatureRaw": { "signature": {
"r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "r": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
"s": "02" "s": "02"
} }
@ -163,7 +180,7 @@
"description": "Invalid s value (< 0)", "description": "Invalid s value (< 0)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signatureRaw": { "signature": {
"r": "02", "r": "02",
"s": "-01" "s": "-01"
} }
@ -172,7 +189,7 @@
"description": "Invalid s value (== 0)", "description": "Invalid s value (== 0)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signatureRaw": { "signature": {
"r": "02", "r": "02",
"s": "00" "s": "00"
} }
@ -181,7 +198,7 @@
"description": "Invalid s value (>= n)", "description": "Invalid s value (>= n)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signatureRaw": { "signature": {
"r": "02", "r": "02",
"s": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" "s": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
} }
@ -190,7 +207,7 @@
"description": "Invalid r, s values (r = s = -n)", "description": "Invalid r, s values (r = s = -n)",
"d": "01", "d": "01",
"message": "foo", "message": "foo",
"signatureRaw": { "signature": {
"r": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "r": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
"s": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" "s": "-fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
} }

140
test/fixtures/signature.json

@ -0,0 +1,140 @@
{
"valid": [
{
"hashType": 1,
"hex": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa5434226201",
"raw": {
"r": "23362334225185207751494092901091441011938859014081160902781146257181456271561",
"s": "50433721247292933944369538617440297985091596895097604618403996029256432099938"
}
},
{
"hashType": 2,
"hex": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a502",
"raw": {
"r": "38341707918488238920692284707283974715538935465589664377561695343399725051885",
"s": "3180566392414476763164587487324397066658063772201694230600609996154610926757"
}
},
{
"hashType": 3,
"hex": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b28303",
"raw": {
"r": "115464191557905790016094131873849783294273568009648050793030031933291767741904",
"s": "50562520307781850052192542766631199590053690478900449960232079510155113443971"
}
},
{
"hashType": 129,
"hex": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d381",
"raw": {
"r": "87230998027579607140680851455601772643840468630989315269459846730712163783123",
"s": "53231320085894623106179381504478252331065330583563809963303318469380290929875"
}
},
{
"hashType": 130,
"hex": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df682",
"raw": {
"r": "51348483531757779992459563033975330355971795607481991320287437101831125115997",
"s": "6277080015686056199074771961940657638578000617958603212944619747099038735862"
}
},
{
"hashType": 131,
"hex": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd3783",
"raw": {
"r": "113979859486826658566290715281614250298918272782414232881639314569529560769671",
"s": "6517071009538626957379450615706485096874328019806177698938278220732027419959"
}
},
{
"hashType": 129,
"hex": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef81",
"raw": {
"r": "93122007060065279508564838030979550535085999589142852106617159184757394422777",
"s": "3078539468410661027472930027406594684630312677495124015420811882501887769839"
}
}
],
"invalid": [
{
"exception": "DER sequence length is too short",
"hex": "ffffffffffffff01"
},
{
"exception": "DER sequence length is too long",
"hex": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01"
},
{
"exception": "Expected DER sequence",
"hex": "00ffff0400ffffff020400ffffff01"
},
{
"exception": "DER sequence length is invalid",
"hex": "30ff020400ffffff020400ffffff01"
},
{
"exception": "DER sequence length is invalid",
"hex": "300c030400ffffff030400ffffff000001"
},
{
"exception": "Expected DER integer",
"hex": "300cff0400ffffff020400ffffff01"
},
{
"exception": "Expected DER integer \\(2\\)",
"hex": "300c020200ffffff020400ffffff01"
},
{
"exception": "R length is zero",
"hex": "30080200020400ffffff01"
},
{
"exception": "S length is zero",
"hex": "3008020400ffffff020001"
},
{
"exception": "R length is too long",
"hex": "300c02dd00ffffff020400ffffff01"
},
{
"exception": "S length is invalid",
"hex": "300c020400ffffff02dd00ffffff01"
},
{
"exception": "R value is negative",
"hex": "300c020480000000020400ffffff01"
},
{
"exception": "S value is negative",
"hex": "300c020400ffffff02048000000001"
},
{
"exception": "R value excessively padded",
"hex": "300c02040000ffff020400ffffff01"
},
{
"exception": "S value excessively padded",
"hex": "300c020400ffffff02040000ffff01"
},
{
"exception": "Invalid hashType 7",
"hashType": 7,
"hex": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa5434226207",
"raw": {
"r": "23362334225185207751494092901091441011938859014081160902781146257181456271561",
"s": "50433721247292933944369538617440297985091596895097604618403996029256432099938"
}
},
{
"exception": "Invalid hashType 140",
"hashType": 140,
"hex": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa543422628c",
"raw": {
"r": "23362334225185207751494092901091441011938859014081160902781146257181456271561",
"s": "50433721247292933944369538617440297985091596895097604618403996029256432099938"
}
}
]
}

11
test/integration/cltv.js

@ -56,7 +56,7 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
var tx = txb.buildIncomplete() var tx = txb.buildIncomplete()
var signatureHash = tx.hashForSignature(0, redeemScript, hashType) var signatureHash = tx.hashForSignature(0, redeemScript, hashType)
var redeemScriptSig = bitcoin.script.scriptHash.input.encode([ var redeemScriptSig = bitcoin.script.scriptHash.input.encode([
alice.sign(signatureHash).toScriptSignature(hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE
], redeemScript) ], redeemScript)
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig)
@ -100,7 +100,7 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
var tx = txb.buildIncomplete() var tx = txb.buildIncomplete()
var signatureHash = tx.hashForSignature(0, redeemScript, hashType) var signatureHash = tx.hashForSignature(0, redeemScript, hashType)
var redeemScriptSig = bitcoin.script.scriptHash.input.encode([ var redeemScriptSig = bitcoin.script.scriptHash.input.encode([
alice.sign(signatureHash).toScriptSignature(hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE
], redeemScript) ], redeemScript)
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig)
@ -154,8 +154,8 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
var tx = txb.buildIncomplete() var tx = txb.buildIncomplete()
var signatureHash = tx.hashForSignature(0, redeemScript, hashType) var signatureHash = tx.hashForSignature(0, redeemScript, hashType)
var redeemScriptSig = bitcoin.script.scriptHash.input.encode([ var redeemScriptSig = bitcoin.script.scriptHash.input.encode([
alice.sign(signatureHash).toScriptSignature(hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bob.sign(signatureHash).toScriptSignature(hashType), bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
bitcoin.opcodes.OP_FALSE bitcoin.opcodes.OP_FALSE
], redeemScript) ], redeemScript)
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig)
@ -196,7 +196,8 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
var tx = txb.buildIncomplete() var tx = txb.buildIncomplete()
var signatureHash = tx.hashForSignature(0, redeemScript, hashType) var signatureHash = tx.hashForSignature(0, redeemScript, hashType)
var redeemScriptSig = bitcoin.script.scriptHash.input.encode([ var redeemScriptSig = bitcoin.script.scriptHash.input.encode([
alice.sign(signatureHash).toScriptSignature(hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE
], redeemScript) ], redeemScript)
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig)

2
test/integration/crypto.js

@ -21,7 +21,7 @@ describe('bitcoinjs-lib (crypto)', function () {
assert(bitcoin.script.pubKeyHash.input.check(scriptChunks), 'Expected pubKeyHash script') assert(bitcoin.script.pubKeyHash.input.check(scriptChunks), 'Expected pubKeyHash script')
var prevOutScript = bitcoin.address.toOutputScript('1ArJ9vRaQcoQ29mTWZH768AmRwzb6Zif1z') var prevOutScript = bitcoin.address.toOutputScript('1ArJ9vRaQcoQ29mTWZH768AmRwzb6Zif1z')
var scriptSignature = bitcoin.ECSignature.parseScriptSignature(scriptChunks[0]) var scriptSignature = bitcoin.script.signature.decode(scriptChunks[0])
var publicKey = bitcoin.ECPair.fromPublicKeyBuffer(scriptChunks[1]) var publicKey = bitcoin.ECPair.fromPublicKeyBuffer(scriptChunks[1])
var m = tx.hashForSignature(vin, prevOutScript, scriptSignature.hashType) var m = tx.hashForSignature(vin, prevOutScript, scriptSignature.hashType)

2
test/integration/transactions.js

@ -230,7 +230,7 @@ describe('bitcoinjs-lib (transactions)', function () {
var keyPair = keyPairs[i] var keyPair = keyPairs[i]
var prevOutScript = bitcoin.address.toOutputScript(keyPair.getAddress()) var prevOutScript = bitcoin.address.toOutputScript(keyPair.getAddress())
var scriptSig = bitcoin.script.pubKeyHash.input.decode(input.script) var scriptSig = bitcoin.script.pubKeyHash.input.decode(input.script)
var ss = bitcoin.ECSignature.parseScriptSignature(scriptSig.signature) var ss = bitcoin.script.signature.decode(scriptSig.signature)
var hash = tx.hashForSignature(i, prevOutScript, ss.hashType) var hash = tx.hashForSignature(i, prevOutScript, ss.hashType)
assert.strictEqual(scriptSig.pubKey.toString('hex'), keyPair.getPublicKeyBuffer().toString('hex')) assert.strictEqual(scriptSig.pubKey.toString('hex'), keyPair.getPublicKeyBuffer().toString('hex'))

65
test/signature.js

@ -0,0 +1,65 @@
/* global describe, it */
var assert = require('assert')
var bscriptSig = require('../src/script').signature
var BigInteger = require('bigi')
var fixtures = require('./fixtures/signature.json')
describe('Script Signatures', function () {
function fromRaw (signature) {
return {
r: new BigInteger(signature.r),
s: new BigInteger(signature.s)
}
}
function toRaw (signature) {
return {
r: signature.r.toString(),
s: signature.s.toString()
}
}
describe('encode', function () {
fixtures.valid.forEach(function (f) {
it('encodes ' + f.hex, function () {
var buffer = bscriptSig.encode(fromRaw(f.raw), f.hashType)
assert.strictEqual(buffer.toString('hex'), f.hex)
})
})
fixtures.invalid.forEach(function (f) {
if (!f.raw) return
it('throws ' + f.exception, function () {
var signature = fromRaw(f.raw)
assert.throws(function () {
bscriptSig.encode(signature, f.hashType)
}, new RegExp(f.exception))
})
})
})
describe('decode', function () {
fixtures.valid.forEach(function (f) {
it('decodes ' + f.hex, function () {
var decode = bscriptSig.decode(new Buffer(f.hex, 'hex'))
assert.deepEqual(toRaw(decode.signature), f.raw)
assert.strictEqual(decode.hashType, f.hashType)
})
})
fixtures.invalid.forEach(function (f) {
it('throws on ' + f.hex, function () {
var buffer = new Buffer(f.hex, 'hex')
assert.throws(function () {
bscriptSig.decode(buffer)
}, new RegExp(f.exception))
})
})
})
})
Loading…
Cancel
Save