From 5b25679e15058cd6b9021b0213afab218d540ec0 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Tue, 16 Sep 2014 14:35:26 -0700 Subject: [PATCH] Transaction --- lib/transaction.js | 77 +++++++++++++++++++++++++++++++++++++++++ test/transaction.js | 84 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 lib/transaction.js create mode 100644 test/transaction.js diff --git a/lib/transaction.js b/lib/transaction.js new file mode 100644 index 000000000..51c27a1f5 --- /dev/null +++ b/lib/transaction.js @@ -0,0 +1,77 @@ +var Txin = require('./txin'); +var Txout = require('./txout'); +var BufferWriter = require('./bufferwriter'); +var BufferReader = require('./bufferreader'); +var Varint = require('./varint'); + +var Transaction = function Transaction(version, txinsvarint, txins, txoutsvarint, txouts, nlocktime) { + if (!(this instanceof Transaction)) + return new Transaction(version, txinsvarint, txins, txoutsvarint, txouts, nlocktime); + if (typeof version === 'number') { + this.set({ + version: version, + txinsvarint: txinsvarint, + txins: txins, + txoutsvarint: txoutsvarint, + txouts: txouts, + nlocktime: nlocktime + }); + } else if (version) { + var obj = version; + this.set(obj); + } +}; + +Transaction.prototype.set = function(obj) { + this.version = typeof obj.version !== 'undefined' ? obj.version : this.version; + this.txinsvarint = obj.txinsvarint || this.txinsvarint; + this.txins = obj.txins || this.txins; + this.txoutsvarint = obj.txoutsvarint || this.txoutsvarint; + this.txouts = obj.txouts || this.txouts; + this.nlocktime = typeof obj.nlocktime !== 'undefined' ? obj.nlocktime : this.nlocktime; + return this; +}; + +Transaction.prototype.fromBuffer = function(buf) { + return this.fromBufferReader(BufferReader(buf)); +}; + +Transaction.prototype.fromBufferReader = function(br) { + this.version = br.readUInt32LE(); + this.txinsvarint = Varint(br.readVarintBuf()); + var txinsnum = this.txinsvarint.toNumber(); + this.txins = []; + for (var i = 0; i < txinsnum; i++) { + this.txins.push(Txin().fromBufferReader(br)); + } + this.txoutsvarint = Varint(br.readVarintBuf()); + var txoutsnum = this.txoutsvarint.toNumber(); + this.txouts = []; + for (var i = 0; i < txoutsnum; i++) { + this.txouts.push(Txout().fromBufferReader(br)); + } + this.nlocktime = br.readUInt32LE(); + return this; +}; + +Transaction.prototype.toBuffer = function() { + return this.toBufferWriter().concat(); +}; + +Transaction.prototype.toBufferWriter = function(bw) { + if (!bw) + bw = new BufferWriter(); + bw.writeUInt32LE(this.version); + bw.write(this.txinsvarint.buf); + for (var i = 0; i < this.txins.length; i++) { + this.txins[i].toBufferWriter(bw); + } + bw.write(this.txoutsvarint.buf) + for (var i = 0; i < this.txouts.length; i++) { + this.txouts[i].toBufferWriter(bw); + } + bw.writeUInt32LE(this.nlocktime); + return bw; +}; + +module.exports = Transaction; diff --git a/test/transaction.js b/test/transaction.js new file mode 100644 index 000000000..13f23cab4 --- /dev/null +++ b/test/transaction.js @@ -0,0 +1,84 @@ +var Varint = require('../lib/varint'); +var Transaction = require('../lib/transaction'); +var Txin = require('../lib/txin'); +var Txout = require('../lib/txout'); +var should = require('chai').should(); +var BufferReader = require('../lib/bufferreader'); +var BufferWriter = require('../lib/bufferwriter'); + +describe('Transaction', function() { + + it('should make a new transaction', function() { + var tx = new Transaction(); + should.exist(tx); + tx = Transaction(); + should.exist(tx); + }); + + var txin = Txin().fromBuffer(new Buffer('00000000000000000000000000000000000000000000000000000000000000000000000001ae00000000', 'hex')); + var txout = Txout().fromBuffer(new Buffer('050000000000000001ae', 'hex')); + var tx = Transaction().set({ + version: 0, + txinsvarint: Varint(1), + txins: [txin], + txoutsvarint: Varint(1), + txouts: [txout], + nlocktime: 0 + }); + var txhex = '000000000100000000000000000000000000000000000000000000000000000000000000000000000001ae0000000001050000000000000001ae00000000'; + var txbuf = new Buffer(txhex, 'hex'); + + describe('#set', function() { + + it('should set all the basic parameters', function() { + var tx = Transaction().set({ + version: 0, + txinsvarint: Varint(1), + txins: [txin], + txoutsvarint: Varint(1), + txouts: [txout], + nlocktime: 0 + }); + should.exist(tx.version); + should.exist(tx.txinsvarint); + should.exist(tx.txins); + should.exist(tx.txoutsvarint); + should.exist(tx.txouts); + should.exist(tx.nlocktime); + }); + + }); + + describe('#fromBuffer', function() { + + it('should recover from this known tx', function() { + Transaction().fromBuffer(txbuf).toBuffer().toString('hex').should.equal(txhex); + }); + + }); + + describe('#fromBufferReader', function() { + + it('should recover from this known tx', function() { + Transaction().fromBufferReader(BufferReader(txbuf)).toBuffer().toString('hex').should.equal(txhex); + }); + + }); + + describe('#toBuffer', function() { + + it('should produce this known tx', function() { + Transaction().fromBuffer(txbuf).toBuffer().toString('hex').should.equal(txhex); + }); + + }); + + describe('#toBufferWriter', function() { + + it('should produce this known tx', function() { + Transaction().fromBuffer(txbuf).toBufferWriter().concat().toString('hex').should.equal(txhex); + }); + + }); + +});