Transaction: add Witness serialization and hashForWitnessV0

This commit is contained in:
Daniel Cousens 2016-07-14 19:50:35 +10:00 committed by Daniel Cousens
parent e8b00d63d6
commit 5c2fdb6043
3 changed files with 373 additions and 30 deletions

View file

@ -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

View file

@ -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
}
]
}

View file

@ -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)
})
})
})
})