Transaction: add Witness serialization and hashForWitnessV0
This commit is contained in:
parent
e8b00d63d6
commit
5c2fdb6043
3 changed files with 373 additions and 30 deletions
|
@ -6,6 +6,20 @@ var opcodes = require('./opcodes.json')
|
|||
var typeforce = require('typeforce')
|
||||
var types = require('./types')
|
||||
|
||||
function varSliceSize (someScript) {
|
||||
var length = someScript.length
|
||||
|
||||
return bufferutils.varIntSize(length) + length
|
||||
}
|
||||
|
||||
function vectorSize (someVector) {
|
||||
var length = someVector.length
|
||||
|
||||
return bufferutils.varIntSize(length) + someVector.reduce(function (sum, witness) {
|
||||
return sum + varSliceSize(witness)
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function Transaction () {
|
||||
this.version = 1
|
||||
this.locktime = 0
|
||||
|
@ -18,6 +32,18 @@ Transaction.SIGHASH_ALL = 0x01
|
|||
Transaction.SIGHASH_NONE = 0x02
|
||||
Transaction.SIGHASH_SINGLE = 0x03
|
||||
Transaction.SIGHASH_ANYONECANPAY = 0x80
|
||||
Transaction.ADVANCED_TRANSACTION_MARKER = 0x00
|
||||
Transaction.ADVANCED_TRANSACTION_FLAG = 0x01
|
||||
|
||||
var EMPTY_SCRIPT = new Buffer(0)
|
||||
var EMPTY_WITNESS = []
|
||||
var ZERO = new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
|
||||
var ONE = new Buffer('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
|
||||
var VALUE_UINT64_MAX = new Buffer('ffffffffffffffff', 'hex')
|
||||
var BLANK_OUTPUT = {
|
||||
script: EMPTY_SCRIPT,
|
||||
valueBuffer: VALUE_UINT64_MAX
|
||||
}
|
||||
|
||||
Transaction.fromBuffer = function (buffer, __noStrict) {
|
||||
var offset = 0
|
||||
|
@ -50,20 +76,38 @@ Transaction.fromBuffer = function (buffer, __noStrict) {
|
|||
return vi.number
|
||||
}
|
||||
|
||||
function readScript () {
|
||||
function readVarSlice () {
|
||||
return readSlice(readVarInt())
|
||||
}
|
||||
|
||||
function readVector () {
|
||||
var count = readVarInt()
|
||||
var vector = []
|
||||
for (var i = 0; i < count; i++) vector.push(readVarSlice())
|
||||
return vector
|
||||
}
|
||||
|
||||
var tx = new Transaction()
|
||||
tx.version = readInt32()
|
||||
|
||||
var marker = buffer.readUInt8(offset)
|
||||
var flag = buffer.readUInt8(offset + 1)
|
||||
|
||||
var hasWitnesses = false
|
||||
if (marker === Transaction.ADVANCED_TRANSACTION_MARKER &&
|
||||
flag === Transaction.ADVANCED_TRANSACTION_FLAG) {
|
||||
offset += 2
|
||||
hasWitnesses = true
|
||||
}
|
||||
|
||||
var vinLen = readVarInt()
|
||||
for (var i = 0; i < vinLen; ++i) {
|
||||
tx.ins.push({
|
||||
hash: readSlice(32),
|
||||
index: readUInt32(),
|
||||
script: readScript(),
|
||||
sequence: readUInt32()
|
||||
script: readVarSlice(),
|
||||
sequence: readUInt32(),
|
||||
witness: EMPTY_WITNESS
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -71,10 +115,16 @@ Transaction.fromBuffer = function (buffer, __noStrict) {
|
|||
for (i = 0; i < voutLen; ++i) {
|
||||
tx.outs.push({
|
||||
value: readUInt64(),
|
||||
script: readScript()
|
||||
script: readVarSlice()
|
||||
})
|
||||
}
|
||||
|
||||
if (hasWitnesses) {
|
||||
for (i = 0; i < vinLen; ++i) {
|
||||
tx.ins[i].witness = readVector()
|
||||
}
|
||||
}
|
||||
|
||||
tx.locktime = readUInt32()
|
||||
|
||||
if (__noStrict) return tx
|
||||
|
@ -99,8 +149,6 @@ Transaction.prototype.isCoinbase = function () {
|
|||
return this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash)
|
||||
}
|
||||
|
||||
var EMPTY_SCRIPT = new Buffer(0)
|
||||
|
||||
Transaction.prototype.addInput = function (hash, index, sequence, scriptSig) {
|
||||
typeforce(types.tuple(
|
||||
types.Hash256bit,
|
||||
|
@ -118,7 +166,8 @@ Transaction.prototype.addInput = function (hash, index, sequence, scriptSig) {
|
|||
hash: hash,
|
||||
index: index,
|
||||
script: scriptSig || EMPTY_SCRIPT,
|
||||
sequence: sequence
|
||||
sequence: sequence,
|
||||
witness: EMPTY_WITNESS
|
||||
}) - 1)
|
||||
}
|
||||
|
||||
|
@ -132,19 +181,22 @@ Transaction.prototype.addOutput = function (scriptPubKey, value) {
|
|||
}) - 1)
|
||||
}
|
||||
|
||||
Transaction.prototype.byteLength = function () {
|
||||
function scriptSize (someScript) {
|
||||
var length = someScript.length
|
||||
Transaction.prototype._hasWitnesses = function () {
|
||||
return this.ins.some(function (x) {
|
||||
return x.witness !== EMPTY_WITNESS
|
||||
})
|
||||
}
|
||||
|
||||
return bufferutils.varIntSize(length) + length
|
||||
}
|
||||
Transaction.prototype.byteLength = function () {
|
||||
var hasWitnesses = this._hasWitnesses()
|
||||
|
||||
return (
|
||||
8 +
|
||||
(hasWitnesses ? 10 : 8) +
|
||||
bufferutils.varIntSize(this.ins.length) +
|
||||
bufferutils.varIntSize(this.outs.length) +
|
||||
this.ins.reduce(function (sum, input) { return sum + 40 + scriptSize(input.script) }, 0) +
|
||||
this.outs.reduce(function (sum, output) { return sum + 8 + scriptSize(output.script) }, 0)
|
||||
this.ins.reduce(function (sum, input) { return sum + 40 + varSliceSize(input.script) }, 0) +
|
||||
this.outs.reduce(function (sum, output) { return sum + 8 + varSliceSize(output.script) }, 0) +
|
||||
(hasWitnesses ? this.ins.reduce(function (sum, input) { return sum + vectorSize(input.witness) }, 0) : 0)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -158,7 +210,8 @@ Transaction.prototype.clone = function () {
|
|||
hash: txIn.hash,
|
||||
index: txIn.index,
|
||||
script: txIn.script,
|
||||
sequence: txIn.sequence
|
||||
sequence: txIn.sequence,
|
||||
witness: txIn.witness
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -172,13 +225,6 @@ Transaction.prototype.clone = function () {
|
|||
return newTx
|
||||
}
|
||||
|
||||
var ONE = new Buffer('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
|
||||
var VALUE_UINT64_MAX = new Buffer('ffffffffffffffff', 'hex')
|
||||
var BLANK_OUTPUT = {
|
||||
script: EMPTY_SCRIPT,
|
||||
valueBuffer: VALUE_UINT64_MAX
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash transaction for signing a specific input.
|
||||
*
|
||||
|
@ -252,6 +298,92 @@ Transaction.prototype.hashForSignature = function (inIndex, prevOutScript, hashT
|
|||
return bcrypto.hash256(buffer)
|
||||
}
|
||||
|
||||
Transaction.prototype.hashForWitnessV0 = function (inIndex, prevOutScript, amount, hashType) {
|
||||
typeforce(types.tuple(types.UInt32, types.Buffer, types.Satoshi, types.UInt32), arguments)
|
||||
|
||||
var hashOutputs, hashPrevouts, hashSequence
|
||||
|
||||
var tbuffer, toffset
|
||||
function writeSlice (slice) { toffset += slice.copy(tbuffer, toffset) }
|
||||
function writeUInt32 (i) { toffset = tbuffer.writeUInt32LE(i, toffset) }
|
||||
function writeUInt64 (i) { toffset = bufferutils.writeUInt64LE(tbuffer, i, toffset) }
|
||||
function writeVarInt (i) { toffset += bufferutils.writeVarInt(tbuffer, i, toffset) }
|
||||
function writeVarSlice (slice) { writeVarInt(slice.length); writeSlice(slice) }
|
||||
|
||||
if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) {
|
||||
tbuffer = new Buffer(36 * this.ins.length)
|
||||
toffset = 0
|
||||
|
||||
this.ins.forEach(function (txIn) {
|
||||
writeSlice(txIn.hash)
|
||||
writeUInt32(txIn.index)
|
||||
})
|
||||
|
||||
hashPrevouts = bcrypto.hash256(tbuffer)
|
||||
}
|
||||
|
||||
if (!(hashType & Transaction.SIGHASH_ANYONECANPAY) &&
|
||||
(hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
|
||||
(hashType & 0x1f) !== Transaction.SIGHASH_NONE) {
|
||||
tbuffer = new Buffer(4 * this.ins.length)
|
||||
toffset = 0
|
||||
|
||||
this.ins.forEach(function (txIn) {
|
||||
writeUInt32(txIn.sequence)
|
||||
})
|
||||
|
||||
hashSequence = bcrypto.hash256(tbuffer)
|
||||
}
|
||||
|
||||
if ((hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
|
||||
(hashType & 0x1f) !== Transaction.SIGHASH_NONE) {
|
||||
var txOutsSize = this.outs.reduce(function (sum, output) {
|
||||
return sum + 8 + varSliceSize(output.script)
|
||||
}, 0)
|
||||
|
||||
tbuffer = new Buffer(txOutsSize)
|
||||
toffset = 0
|
||||
|
||||
this.outs.forEach(function (out) {
|
||||
writeUInt64(out.value)
|
||||
writeVarSlice(out.script)
|
||||
})
|
||||
|
||||
hashOutputs = bcrypto.hash256(tbuffer)
|
||||
} else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE && inIndex < this.outs.length) {
|
||||
var output = this.outs[inIndex]
|
||||
|
||||
tbuffer = new Buffer(8 + varSliceSize(output.script))
|
||||
toffset = 0
|
||||
writeUInt64(output.value)
|
||||
writeVarSlice(output.script)
|
||||
|
||||
hashOutputs = bcrypto.hash256(tbuffer)
|
||||
}
|
||||
|
||||
hashPrevouts = hashPrevouts || ZERO
|
||||
hashSequence = hashSequence || ZERO
|
||||
hashOutputs = hashOutputs || ZERO
|
||||
|
||||
tbuffer = new Buffer(156 + varSliceSize(prevOutScript))
|
||||
toffset = 0
|
||||
|
||||
var input = this.ins[inIndex]
|
||||
writeUInt32(this.version)
|
||||
writeSlice(hashPrevouts)
|
||||
writeSlice(hashSequence)
|
||||
writeSlice(input.hash)
|
||||
writeUInt32(input.index)
|
||||
writeVarSlice(prevOutScript)
|
||||
writeUInt64(amount)
|
||||
writeUInt32(input.sequence)
|
||||
writeSlice(hashOutputs)
|
||||
writeUInt32(this.locktime)
|
||||
writeUInt32(hashType)
|
||||
|
||||
return bcrypto.hash256(tbuffer)
|
||||
}
|
||||
|
||||
Transaction.prototype.getHash = function () {
|
||||
return bcrypto.hash256(this.toBuffer())
|
||||
}
|
||||
|
@ -266,19 +398,29 @@ Transaction.prototype.toBuffer = function (buffer, initialOffset) {
|
|||
|
||||
var offset = initialOffset || 0
|
||||
function writeSlice (slice) { offset += slice.copy(buffer, offset) }
|
||||
function writeUInt8 (i) { offset = buffer.writeUInt8(i, offset) }
|
||||
function writeUInt32 (i) { offset = buffer.writeUInt32LE(i, offset) }
|
||||
function writeInt32 (i) { offset = buffer.writeInt32LE(i, offset) }
|
||||
function writeUInt64 (i) { offset = bufferutils.writeUInt64LE(buffer, i, offset) }
|
||||
function writeVarInt (i) { offset += bufferutils.writeVarInt(buffer, i, offset) }
|
||||
function writeVarSlice (slice) { writeVarInt(slice.length); writeSlice(slice) }
|
||||
function writeVector (vector) { writeVarInt(vector.length); vector.forEach(writeVarSlice) }
|
||||
|
||||
writeInt32(this.version)
|
||||
|
||||
var hasWitnesses = this._hasWitnesses()
|
||||
|
||||
if (hasWitnesses) {
|
||||
writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER)
|
||||
writeUInt8(Transaction.ADVANCED_TRANSACTION_FLAG)
|
||||
}
|
||||
|
||||
writeVarInt(this.ins.length)
|
||||
|
||||
this.ins.forEach(function (txIn) {
|
||||
writeSlice(txIn.hash)
|
||||
writeUInt32(txIn.index)
|
||||
writeVarInt(txIn.script.length)
|
||||
writeSlice(txIn.script)
|
||||
writeVarSlice(txIn.script)
|
||||
writeUInt32(txIn.sequence)
|
||||
})
|
||||
|
||||
|
@ -290,15 +432,19 @@ Transaction.prototype.toBuffer = function (buffer, initialOffset) {
|
|||
writeSlice(txOut.valueBuffer)
|
||||
}
|
||||
|
||||
writeVarInt(txOut.script.length)
|
||||
writeSlice(txOut.script)
|
||||
writeVarSlice(txOut.script)
|
||||
})
|
||||
|
||||
if (hasWitnesses) {
|
||||
this.ins.forEach(function (input) {
|
||||
writeVector(input.witness)
|
||||
})
|
||||
}
|
||||
|
||||
writeUInt32(this.locktime)
|
||||
|
||||
// avoid slicing unless necessary
|
||||
if (initialOffset !== undefined) return buffer.slice(initialOffset, offset)
|
||||
|
||||
return buffer
|
||||
}
|
||||
|
||||
|
@ -312,4 +458,10 @@ Transaction.prototype.setInputScript = function (index, scriptSig) {
|
|||
this.ins[index].script = scriptSig
|
||||
}
|
||||
|
||||
Transaction.prototype.setWitness = function (index, witness) {
|
||||
typeforce(types.tuple(types.Number, types.Buffer), arguments)
|
||||
|
||||
this.ins[index].witness = witness
|
||||
}
|
||||
|
||||
module.exports = Transaction
|
||||
|
|
176
test/fixtures/transaction.json
vendored
176
test/fixtures/transaction.json
vendored
|
@ -289,5 +289,177 @@
|
|||
"hex": "0100000002f1fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe000000006b483045022100e661badd8d2cf1af27eb3b82e61b5d3f5d5512084591796ae31487f5b82df948022006df3c2a2cac79f68e4b179f4bbb8185a0bb3c4a2486d4405c59b2ba07a74c2101210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798fffffffff2fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe0100000083483045022100be54a46a44fb7e6bf4ebf348061d0dace7ddcbb92d4147ce181cf4789c7061f0022068ccab2a89a47fc29bb5074bca99ae846ab446eecf3c3aaeb238a13838783c78012102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee517a9147ccb85f0ab2d599bc17246c98babd5a20b1cdc7687ffffffff0250c30000000000001976a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88acf04902000000000017a9147ccb85f0ab2d599bc17246c98babd5a20b1cdc768700000000ffffffff"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"hashForWitnessV0": [
|
||||
{
|
||||
"description": "Native P2WPKH with SIGHASH_ALL",
|
||||
"txHex": "0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f0000000000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000",
|
||||
"inIndex": 1,
|
||||
"script": "OP_DUP OP_HASH160 1d0f172a0ecb48aee1be1f2687d2963ae33f71a1 OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"type": 1,
|
||||
"hash": "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670",
|
||||
"value": 600000000
|
||||
},
|
||||
{
|
||||
"description": "P2SH(P2WPKH) with SIGHASH_ALL",
|
||||
"txHex": "0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a54770100000000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000",
|
||||
"inIndex": 0,
|
||||
"script": "OP_DUP OP_HASH160 79091972186c449eb1ded22b78e40d009bdf0089 OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"type": 1,
|
||||
"hash": "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6",
|
||||
"value": 1000000000
|
||||
},
|
||||
{
|
||||
"description": "P2SH(P2WSH) with SIGHASH_ALL",
|
||||
"txHex": "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000",
|
||||
"inIndex": 0,
|
||||
"script": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG",
|
||||
"type": 1,
|
||||
"hash": "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c",
|
||||
"value": 987654321
|
||||
},
|
||||
{
|
||||
"description": "P2SH(P2WSH) with SIGHASH_NONE",
|
||||
"txHex": "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000",
|
||||
"inIndex": 0,
|
||||
"script": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG",
|
||||
"type": 2,
|
||||
"hash": "e9733bc60ea13c95c6527066bb975a2ff29a925e80aa14c213f686cbae5d2f36",
|
||||
"value": 987654321
|
||||
},
|
||||
{
|
||||
"description": "P2SH(P2WSH) with SIGHASH_SINGLE",
|
||||
"txHex": "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000",
|
||||
"inIndex": 0,
|
||||
"script": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG",
|
||||
"type": 3,
|
||||
"hash": "1e1f1c303dc025bd664acb72e583e933fae4cff9148bf78c157d1e8f78530aea",
|
||||
"value": 987654321
|
||||
},
|
||||
{
|
||||
"description": "P2SH(P2WSH) with SIGHASH_ALL | SIGHASH_ANYONECANPAY",
|
||||
"txHex": "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000",
|
||||
"inIndex": 0,
|
||||
"script": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG",
|
||||
"type": 129,
|
||||
"hash": "2a67f03e63a6a422125878b40b82da593be8d4efaafe88ee528af6e5a9955c6e",
|
||||
"value": 987654321
|
||||
},
|
||||
{
|
||||
"description": "P2SH(P2WSH) with SIGHASH_NONE | SIGHASH_ANYONECANPAY",
|
||||
"txHex": "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000",
|
||||
"inIndex": 0,
|
||||
"script": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG",
|
||||
"type": 130,
|
||||
"hash": "781ba15f3779d5542ce8ecb5c18716733a5ee42a6f51488ec96154934e2c890a",
|
||||
"value": 987654321
|
||||
},
|
||||
{
|
||||
"description": "P2SH(P2WSH) with SIGHASH_SINGLE | SIGHASH_ANYONECANPAY",
|
||||
"txHex": "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000",
|
||||
"inIndex": 0,
|
||||
"script": "OP_6 0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3 03b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b 034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a 033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4 03a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16 02d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b OP_6 OP_CHECKMULTISIG",
|
||||
"type": 131,
|
||||
"hash": "511e8e52ed574121fc1b654970395502128263f62662e076dc6baf05c2e6a99b",
|
||||
"value": 987654321
|
||||
}
|
||||
],
|
||||
"witness": [
|
||||
{
|
||||
"description": "P2SH(P2WSH) Multisig",
|
||||
"id": "bd38915e2aa04b8efa307e0e29ab95582954738a7062cf88730a6276224bd917",
|
||||
"hash": "17d94b2276620a7388cf62708a7354295895ab290e7e30fa8e4ba02a5e9138bd",
|
||||
"hex": "0100000000010113ae35a2063ba413c3a1bb9b3820c76291e40e83bd3f23c8ff83333f0c64d623000000002322002086b2dcecbf2e0f0e4095ef11bc8834e2e148d245f844f0b8091389fef91b69ffffffffff0180969800000000001976a914b1ae3ceac136e4bdb733663e7a1e2f0961198a1788ac03004730440220121a629bb5fee3ecaf3e7a0b111101c51de816f427eaedd992b57f49b69b228e0220402ecd144a7321b4bad6ba3bfa5876b755b9c52a8c8ab17a33830d5929a76cbe0125512103b848ab6ac853cd69baaa750c70eb352ebeadb07da0ff5bbd642cb285895ee43f51ae00000000",
|
||||
"raw": {
|
||||
"version": "1",
|
||||
"ins": [
|
||||
{
|
||||
"hash": "23d6640c3f3383ffc8233fbd830ee49162c720389bbba1c313a43b06a235ae13",
|
||||
"index": "0",
|
||||
"script": "002086b2dcecbf2e0f0e4095ef11bc8834e2e148d245f844f0b8091389fef91b69ff"
|
||||
}
|
||||
],
|
||||
"outs": [
|
||||
{
|
||||
"value": "10000000",
|
||||
"script": "OP_DUP OP_HASH160 b1ae3ceac136e4bdb733663e7a1e2f0961198a17 OP_EQUALVERIFY OP_CHECKSIG"
|
||||
}
|
||||
],
|
||||
"locktime": "0"
|
||||
},
|
||||
"coinbase": false
|
||||
},
|
||||
{
|
||||
"description": "P2SH(Multisig)",
|
||||
"id": "128f7d5f2b213bf496ebae1990800475d7c448f980e29a82bd99e83e14638e85",
|
||||
"hash": "858e63143ee899bd829ae280f948c4d77504809019aeeb96f43b212b5f7d8f12",
|
||||
"hex": "0100000000010113ae35a2063ba413c3a1bb9b3820c76291e40e83bd3f23c8ff83333f0c64d623000000007000483045022100e332e8367d5fee22c205ce1bf4e01e39f1a8decb3ba20d1336770cf38b8ee72d022076b5f83b3ee15390133b7ebf526ec189eb73cc6ee0a726f70b939bc51fa18d800125512103b848ab6ac853cd69baaa750c70eb352ebeadb07da0ff5bbd642cb285895ee43f51aeffffffff0180969800000000001976a914b1ae3ceac136e4bdb733663e7a1e2f0961198a1788ac0000000000",
|
||||
"raw": {
|
||||
"version": "1",
|
||||
"ins": [
|
||||
{
|
||||
"hash": "23d6640c3f3383ffc8233fbd830ee49162c720389bbba1c313a43b06a235ae13",
|
||||
"index": "0",
|
||||
"script": " 3045022100e332e8367d5fee22c205ce1bf4e01e39f1a8decb3ba20d1336770cf38b8ee72d022076b5f83b3ee15390133b7ebf526ec189eb73cc6ee0a726f70b939bc51fa18d8001 512103b848ab6ac853cd69baaa750c70eb352ebeadb07da0ff5bbd642cb285895ee43f51ae"
|
||||
}
|
||||
],
|
||||
"outs": [
|
||||
{
|
||||
"value": "10000000",
|
||||
"script": "OP_DUP OP_HASH160 b1ae3ceac136e4bdb733663e7a1e2f0961198a17 OP_EQUALVERIFY OP_CHECKSIG"
|
||||
}
|
||||
],
|
||||
"locktime": "0"
|
||||
},
|
||||
"coinbase": false
|
||||
},
|
||||
{
|
||||
"description": "Multisig",
|
||||
"id": "3cd3dfe7312d34798b87351d9b72b3356e6ec109d841919cec510f3efa5d291f",
|
||||
"hash": "1f295dfa3e0f51ec9c9141d809c16e6e35b3729b1d35878b79342d31e7dfd33c",
|
||||
"hex": "0100000000010113ae35a2063ba413c3a1bb9b3820c76291e40e83bd3f23c8ff83333f0c64d623000000004a00483045022100e332e8367d5fee22c205ce1bf4e01e39f1a8decb3ba20d1336770cf38b8ee72d022076b5f83b3ee15390133b7ebf526ec189eb73cc6ee0a726f70b939bc51fa18d8001ffffffff0180969800000000001976a914b1ae3ceac136e4bdb733663e7a1e2f0961198a1788ac0000000000",
|
||||
"raw": {
|
||||
"version": "1",
|
||||
"ins": [
|
||||
{
|
||||
"hash": "23d6640c3f3383ffc8233fbd830ee49162c720389bbba1c313a43b06a235ae13",
|
||||
"index": "0",
|
||||
"script": " 3045022100e332e8367d5fee22c205ce1bf4e01e39f1a8decb3ba20d1336770cf38b8ee72d022076b5f83b3ee15390133b7ebf526ec189eb73cc6ee0a726f70b939bc51fa18d8001"
|
||||
}
|
||||
],
|
||||
"outs": [
|
||||
{
|
||||
"value": "10000000",
|
||||
"script": "OP_DUP OP_HASH160 b1ae3ceac136e4bdb733663e7a1e2f0961198a17 OP_EQUALVERIFY OP_CHECKSIG"
|
||||
}
|
||||
],
|
||||
"locktime": "0"
|
||||
},
|
||||
"coinbase": false
|
||||
},
|
||||
{
|
||||
"description": "P2PK",
|
||||
"id": "6cf3688270c95846d3ced68b7fcf90f30daddd63e951ed04791cbf1f8c731c77",
|
||||
"hash": "771c738c1fbf1c7904ed51e963ddad0df390cf7f8bd6ced34658c9708268f36c",
|
||||
"hex": "0100000000010113ae35a2063ba413c3a1bb9b3820c76291e40e83bd3f23c8ff83333f0c64d623000000006a47304402203f965bdf792ea80c1f96e4292d1edb52ca62f22c7511aefca967fb9f3067063402204acbfaa4e7f1d5631227d491426d89d954d5e2abfed6f0dbc300216f01916baa012103b848ab6ac853cd69baaa750c70eb352ebeadb07da0ff5bbd642cb285895ee43fffffffff0100000000000000001976a914b1ae3ceac136e4bdb733663e7a1e2f0961198a1788ac0000000000",
|
||||
"raw": {
|
||||
"version": "1",
|
||||
"ins": [
|
||||
{
|
||||
"hash": "23d6640c3f3383ffc8233fbd830ee49162c720389bbba1c313a43b06a235ae13",
|
||||
"index": "0",
|
||||
"script": "304402203f965bdf792ea80c1f96e4292d1edb52ca62f22c7511aefca967fb9f3067063402204acbfaa4e7f1d5631227d491426d89d954d5e2abfed6f0dbc300216f01916baa01 03b848ab6ac853cd69baaa750c70eb352ebeadb07da0ff5bbd642cb285895ee43f"
|
||||
}
|
||||
],
|
||||
"outs": [
|
||||
{
|
||||
"value": "0",
|
||||
"script": "OP_DUP OP_HASH160 b1ae3ceac136e4bdb733663e7a1e2f0961198a17 OP_EQUALVERIFY OP_CHECKSIG"
|
||||
}
|
||||
],
|
||||
"locktime": "0"
|
||||
},
|
||||
"coinbase": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -50,6 +50,14 @@ describe('Transaction', function () {
|
|||
})
|
||||
})
|
||||
|
||||
fixtures.witness.forEach(function (f) {
|
||||
it('imports ' + f.description + ' (' + f.id + ')', function () {
|
||||
var actual = Transaction.fromHex(f.hex)
|
||||
|
||||
assert.strictEqual(actual.toHex(), f.hex, actual.toHex())
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.invalid.fromBuffer.forEach(function (f) {
|
||||
it('throws on ' + f.exception, function () {
|
||||
assert.throws(function () {
|
||||
|
@ -207,4 +215,15 @@ describe('Transaction', function () {
|
|||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('hashForWitnessV0', function () {
|
||||
fixtures.hashForWitnessV0.forEach(function (f) {
|
||||
it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : ''), function () {
|
||||
var tx = Transaction.fromHex(f.txHex)
|
||||
var script = bscript.fromASM(f.script)
|
||||
|
||||
assert.strictEqual(tx.hashForWitnessV0(f.inIndex, script, f.value, f.type).toString('hex'), f.hash)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue