diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 0c2d569..2084cbc 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -282,7 +282,19 @@ Transaction.prototype.toBuffer = function() { }; Transaction.prototype.toBufferWriter = function(writer) { - writer.writeUInt32LE(this.version); + if (!this.fOverwintered) { + writer.writeUInt32LE(this.version); + } else { + // We don't use bitwise operators which expect 32 bit operands and return a 32 bit signed integer. + // For example, var header = 0x80000000 | this.version; returns -7fffffff (-2147483645). + var header = 0x80000000 + this.version; + writer.writeUInt32LE(header); + } + + if (this.fOverwintered) { + writer.writeUInt32LE(this.nVersionGroupId); + } + writer.writeVarintNum(this.inputs.length); _.each(this.inputs, function(input) { input.toBufferWriter(writer); @@ -292,6 +304,11 @@ Transaction.prototype.toBufferWriter = function(writer) { output.toBufferWriter(writer); }); writer.writeUInt32LE(this.nLockTime); + + if (this.fOverwintered) { + writer.writeUInt32LE(this.nExpiryHeight); + } + if (this.version >= 2) { writer.writeVarintNum(this.joinSplits.length); _.each(this.joinSplits, function(jsdesc) { @@ -314,15 +331,15 @@ Transaction.prototype.fromBufferReader = function(reader) { $.checkArgument(!reader.finished(), 'No transaction data received'); var i, sizeTxIns, sizeTxOuts, sizeJSDescs; var header = reader.readUInt32LE(); - this.fOverwintered = header & 0x80000000; - if ( this.fOverwintered == true ) { - this.version = header & 0x7fffffff; + this.fOverwintered = ((header >>> 31) == 1); + if (this.fOverwintered == true) { + this.version = header & 0x7fffffff; } else { - this.version = header; + this.version = header; } - if ( this.version >= 3 ){ + if (this.version >= 3 ){ this.nVersionGroupId = reader.readUInt32LE(); } @@ -335,10 +352,13 @@ Transaction.prototype.fromBufferReader = function(reader) { for (i = 0; i < sizeTxOuts; i++) { this.outputs.push(Output.fromBufferReader(reader)); } + this.nLockTime = reader.readUInt32LE(); + if (this.version >= 3) { this.nExpiryHeight = reader.readUInt32LE(); } + if (this.version >= 2) { sizeJSDescs = reader.readVarintNum(); for (i = 0; i < sizeJSDescs; i++) { @@ -363,12 +383,19 @@ Transaction.prototype.toObject = Transaction.prototype.toJSON = function toObjec }); var obj = { hash: this.hash, + fOverwintered: this.fOverwintered, version: this.version, inputs: inputs, outputs: outputs, nLockTime: this.nLockTime }; - if (this.version >= 3) { + + if (this.fOverwintered) { + obj.nVersionGroupId = this.nVersionGroupId; + obj.nExpiryHeight = this.nExpiryHeight; + } + + if (this.version >= 2) { var joinSplits = []; this.joinSplits.forEach(function(joinSplit) { joinSplits.push(joinSplit.toObject()); @@ -435,6 +462,17 @@ Transaction.prototype.fromObject = function fromObject(arg) { } this.nLockTime = transaction.nLockTime; this.version = transaction.version; + + + this.fOverwintered = transaction.fOverwintered; + if (this.fOverwintered) { + this.nExpiryHeight = transaction.nExpiryHeight; + this.nVersionGroupId = transaction.nVersionGroupId; + } + + + + if (this.version >= 2) { _.each(transaction.joinSplits, function(joinSplit) { self.joinSplits.push(new JSDescription(joinSplit));