From 2384164ab8b110d9bfac5fddfd53844862c13ca9 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Mon, 7 Mar 2016 20:49:55 -0500 Subject: [PATCH] transaction: start to implement segwit serialization --- lib/transaction/transaction.js | 37 +++++++++++++++++++++++++----- test/data/bitcoind/tx_invalid.json | 3 --- test/transaction/transaction.js | 17 ++++++++++++++ 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 276b7fb..3b6eb52 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -38,6 +38,8 @@ function Transaction(serialized) { } this.inputs = []; this.outputs = []; + this.witness = []; + this._hasWitness = false; this._inputAmount = undefined; this._outputAmount = undefined; @@ -57,7 +59,7 @@ function Transaction(serialized) { this._newTransaction(); } } - +var SERIALIZE_TRANSACTION_WITNESS = 0x40000000; var CURRENT_VERSION = 1; var DEFAULT_NLOCKTIME = 0; var MAX_BLOCK_SIZE = 1000000; @@ -299,22 +301,45 @@ Transaction.prototype.fromBuffer = function(buffer) { Transaction.prototype.fromBufferReader = function(reader) { $.checkArgument(!reader.finished(), 'No transaction data received'); - var i, sizeTxIns, sizeTxOuts; this.version = reader.readInt32LE(); - sizeTxIns = reader.readVarintNum(); - for (i = 0; i < sizeTxIns; i++) { + var sizeTxIns = reader.readVarintNum(); + + // check for segwit + this._hasWitness = false; + if (sizeTxIns === 0 && reader.buf[reader.pos] !== 0) { + reader.pos += 1; + this._hasWitness = true; + sizeTxIns = reader.readVarintNum(); + } + + for (var i = 0; i < sizeTxIns; i++) { var input = Input.fromBufferReader(reader); this.inputs.push(input); } - sizeTxOuts = reader.readVarintNum(); - for (i = 0; i < sizeTxOuts; i++) { + + var sizeTxOuts = reader.readVarintNum(); + for (var j = 0; j < sizeTxOuts; j++) { this.outputs.push(Output.fromBufferReader(reader)); } + + if (this._hasWitness) { + this._fromBufferReaderScriptWitnesses(reader); + } + this.nLockTime = reader.readUInt32LE(); return this; }; +Transaction.prototype._fromBufferReaderScriptWitnesses = function(reader) { + var itemCount = reader.readVarintNum(); + for (var i = 0; i < itemCount; i++) { + var size = reader.readVarintNum(); + var item = reader.read(size); + this.witness.push(item); + } +}; + Transaction.prototype.toObject = Transaction.prototype.toJSON = function toObject() { var inputs = []; this.inputs.forEach(function(input) { diff --git a/test/data/bitcoind/tx_invalid.json b/test/data/bitcoind/tx_invalid.json index a9f5ff0..e304985 100644 --- a/test/data/bitcoind/tx_invalid.json +++ b/test/data/bitcoind/tx_invalid.json @@ -24,9 +24,6 @@ "010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "P2SH"], ["Tests for CheckTransaction()"], -["No inputs"], -[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], -"0100000000010000000000000000015100000000", "P2SH"], ["No outputs"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]], diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 994150d..0504b5c 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -1226,6 +1226,23 @@ describe('Transaction', function() { }); }); }); + + describe('Segregated Witness', function() { + it('identify as segwit transaction', function() { + // https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki + var version = new Buffer('01000000', 'hex'); + var marker = new Buffer('00', 'hex'); //always zero + var flag = new Buffer('01', 'hex'); //non zero + var inputCount = new Buffer('00', 'hex'); + var outputCount = new Buffer('00', 'hex'); + var witness = new Buffer('00', 'hex'); + var locktime = new Buffer('00000000', 'hex'); + var txBuffer = Buffer.concat([version, marker, flag, inputCount, outputCount, witness, locktime]); + var tx = bitcore.Transaction().fromBuffer(txBuffer); + tx._hasWitness.should.equal(true); + }); + }); + });