diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index bdf2a2fb..cd00c346 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -209,16 +209,22 @@ Block.prototype.getCoinbase = function getCoinbase() { }; Block.prototype.inspect = function inspect() { - var copy = bcoin.block(this); - copy.__proto__ = null; - delete copy._raw; - delete copy._chain; - copy.hash = this.hash('hex'); - copy.rhash = this.rhash; - copy.reward = utils.btc(this.getReward()); - copy.fee = utils.btc(this.getFee()); - copy.date = new Date((copy.ts || 0) * 1000).toISOString(); - return copy; + return { + type: this.type, + height: this.height, + hash: utils.revHex(this.hash('hex')), + reward: utils.btc(this.getReward()), + fee: utils.btc(this.getFee()), + date: new Date((this.ts || 0) * 1000).toISOString(), + version: this.version, + prevBlock: utils.revHex(this.prevBlock), + merkleRoot: utils.revHex(this.merkleRoot), + ts: this.ts, + bits: this.bits, + nonce: this.nonce, + totalTX: this.totalTX, + txs: this.txs + }; }; Block.prototype.toJSON = function toJSON() { diff --git a/lib/bcoin/blockdb.js b/lib/bcoin/blockdb.js index bd9e4ece..b910f463 100644 --- a/lib/bcoin/blockdb.js +++ b/lib/bcoin/blockdb.js @@ -417,7 +417,7 @@ BlockDB.prototype.fillTXs = function fillTXs(txs, callback) { callback = utils.asyncify(callback); - utils.forEach(txs, function(err, next) { + utils.forEach(txs, function(tx, next) { self.fillTX(tx, function(err) { if (err) return next(err); diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 08416839..92761769 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1335,12 +1335,6 @@ Chain.prototype.add = function add(initial, peer, callback, force) { if (self.total % 10 === 0) bcoin.profiler.snapshot(); - // We intentionally did not asyncify the - // callback so if it calls chain.add, it - // still gets added to the queue. The - // chain.add below needs to be in a nextTick - // so we don't cause a stack overflow if - // these end up being all sync chain.adds. utils.nextTick(function() { unlock(); if (err) diff --git a/lib/bcoin/input.js b/lib/bcoin/input.js index 0e6cd808..f7cfb10b 100644 --- a/lib/bcoin/input.js +++ b/lib/bcoin/input.js @@ -14,7 +14,7 @@ var constants = bcoin.protocol.constants; * Input */ -function Input(options) { +function Input(options, tx) { var prevout; if (!(this instanceof Input)) @@ -35,14 +35,11 @@ function Input(options) { if (Buffer.isBuffer(this.prevout.hash)) this.prevout.hash = utils.toHex(this.prevout.hash); - // this.script = options.script ? options.script.slice() : []; this.script = options.script || []; this.sequence = options.sequence == null ? 0xffffffff : options.sequence; this._size = options._size || 0; this._offset = options._offset || 0; - - // if (options.script && options.script._raw) - // utils.hidden(this.script, '_raw', options.script._raw); + this._mutable = !tx || (tx instanceof bcoin.mtx); } Input.prototype.__defineGetter__('data', function() { @@ -51,9 +48,9 @@ Input.prototype.__defineGetter__('data', function() { if (this._data) return this._data; - data = Input.getData(this); + data = this.getData(); - if (this.script.length && this.output) + if (!this._mutable) utils.hidden(this, '_data', data); return data; @@ -163,7 +160,7 @@ Input.prototype.__defineGetter__('value', function() { // locktime: Number, // value: bn, // script: Array, -// seq: Number, +// sequence: Number, // prev: String, // index: Number, // none: Boolean @@ -178,7 +175,7 @@ Input.getData = function getData(input) { side: 'input', value: new bn(0), script: input.script, - seq: input.seq + sequence: input.sequence }; def.prev = input.prevout.hash; @@ -206,17 +203,43 @@ Input.prototype.getData = function getData() { }; Input.prototype.getType = function getType() { - var prev = this.output ? this.output.script : null; + var type; + if (this.isCoinbase()) return 'coinbase'; - return bcoin.script.getInputType(this.script, prev); + + if (this.output) + return this.output.getType(); + + if (this._type) + return this._type; + + type = bcoin.script.getInputType(this.script); + + if (!this._mutable) + this._type = type; + + return type; }; Input.prototype.getAddress = function getAddress() { - var prev = this.output ? this.output.script : null; + var address; + if (this.isCoinbase()) return; - return bcoin.script.getInputAddress(this.script, prev); + + if (this.output) + return this.output.getAddress(); + + if (this._address) + return this._address; + + address = bcoin.script.getInputAddress(this.script); + + if (!this._mutable) + this._address = address; + + return address; }; Input.prototype.isRBF = function isRBF() { @@ -320,8 +343,7 @@ Input.prototype.inspect = function inspect() { ? this.output.inspect() : { type: 'unknown', value: '0.0' }; - output.hash = this.prevout.hash; - output.rhash = utils.revHex(this.prevout.hash); + output.hash = utils.revHex(this.prevout.hash); output.index = this.prevout.index; return { @@ -338,7 +360,7 @@ Input.prototype.inspect = function inspect() { value: utils.btc(output.value), script: bcoin.script.format(this.script), redeem: this.redeem ? bcoin.script.format(this.redeem) : null, - seq: this.seq, + sequence: this.sequence, output: output }; }; diff --git a/lib/bcoin/mtx.js b/lib/bcoin/mtx.js index 52abe82e..788e6886 100644 --- a/lib/bcoin/mtx.js +++ b/lib/bcoin/mtx.js @@ -107,7 +107,7 @@ MTX.prototype.addInput = function addInput(options, index) { // i = this._inputIndex(options.prevout.hash, options.prevout.index); // assert(i === -1); - input = bcoin.input(options); + input = bcoin.input(options, this); this.inputs.push(input); @@ -560,7 +560,7 @@ MTX.prototype.addOutput = function addOutput(obj, value) { options = obj; } - output = bcoin.output(options); + output = bcoin.output(options, this); this.outputs.push(output); diff --git a/lib/bcoin/output.js b/lib/bcoin/output.js index 60674111..a62c5c95 100644 --- a/lib/bcoin/output.js +++ b/lib/bcoin/output.js @@ -14,7 +14,7 @@ var constants = bcoin.protocol.constants; * Output */ -function Output(options) { +function Output(options, tx) { var value; if (!(this instanceof Output)) @@ -30,10 +30,10 @@ function Output(options) { } this.value = utils.satoshi(value || new bn(0)); - // this.script = options.script ? options.script.slice() : []; this.script = options.script || []; this._size = options._size || 0; this._offset = options._offset || 0; + this._mutable = !tx || (tx instanceof bcoin.mtx); // For safety: do not allow usage of // Numbers, do not allow negative values. @@ -41,9 +41,6 @@ function Output(options) { assert(!this.value.isNeg()) assert(this.value.bitLength() <= 63); assert(!(this.value.toArray('be', 8)[0] & 0x80)); - - // if (options.script && options.script._raw) - // utils.hidden(this.script, '_raw', options.script._raw); } Output.prototype.__defineGetter__('data', function() { @@ -52,9 +49,9 @@ Output.prototype.__defineGetter__('data', function() { if (this._data) return this._data; - data = Output.getData(this); + data = this.getData(); - if (this.script.length) + if (!this._mutable) utils.hidden(this, '_data', data); return data; @@ -173,11 +170,31 @@ Output.prototype.getData = function getData() { }; Output.prototype.getType = function getType() { - return bcoin.script.getOutputType(this.script); + var type; + + if (this._type) + return this._type; + + type = bcoin.script.getOutputType(this.script); + + if (!this._mutable) + this._type = type; + + return type; }; Output.prototype.getAddress = function getAddress() { - return bcoin.script.getOutputAddress(this.script); + var address; + + if (this._address) + return this._address; + + address = bcoin.script.getOutputAddress(this.script); + + if (!this._mutable) + this._address = address; + + return address; }; Output.prototype.getID = function getID() { @@ -186,38 +203,6 @@ Output.prototype.getID = function getID() { return '[' + this.type + ':' + hash.slice(0, 7) + ']'; }; -Output.prototype.testScript = function testScript(key, hash, keys, scriptHash, type) { - if (!type || type === 'pubkey') { - if (key) { - if (bcoin.script.isPubkey(this.script, key)) - return true; - } - } - - if (!type || type === 'pubkeyhash') { - if (hash) { - if (bcoin.script.isPubkeyhash(this.script, hash)) - return true; - } - } - - if (!type || type === 'multisig') { - if (keys) { - if (bcoin.script.isMultisig(this.script, keys)) - return true; - } - } - - if (!type || type === 'scripthash') { - if (scriptHash) { - if (bcoin.script.isScripthash(this.script, scriptHash)) - return true; - } - } - - return false; -}; - Output.prototype.test = function test(addressTable) { var address = this.getAddress(); diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 93f422a6..6d38da13 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -44,11 +44,11 @@ function TX(data, block, index) { // assert(data.outputs.length !== 0); data.inputs.forEach(function(input) { - this.inputs.push(new bcoin.input(input)); + this.inputs.push(new bcoin.input(input, this)); }, this); data.outputs.forEach(function(output) { - this.outputs.push(new bcoin.output(output)); + this.outputs.push(new bcoin.output(output, this)); }, this); if (block && this.ts === 0) { @@ -742,24 +742,27 @@ TX.prototype.__defineGetter__('priority', function() { }); TX.prototype.inspect = function inspect() { - var copy = this.clone(); - copy.__proto__ = null; - delete copy._raw; - delete copy._chain; - copy.hash = this.hash('hex'); - copy.rhash = this.rhash; - copy.rblock = this.rblock; - copy.value = utils.btc(this.getValue()); - copy.fee = utils.btc(this.getFee()); - copy.confirmations = this.getConfirmations(); - copy.priority = this.getPriority().toString(10); - copy.date = new Date((copy.ts || 0) * 1000).toISOString(); - return copy; + return { + type: this.type, + hash: utils.revHex(this.hash('hex')), + height: this.height, + value: utils.btc(this.getValue()), + fee: utils.btc(this.getFee()), + confirmations: this.getConfirmations(), + priority: this.getPriority().toString(10), + date: new Date((this.ts || 0) * 1000).toISOString(), + block: this.block ? utils.revHex(this.block) : null, + ts: this.ts, + version: this.version, + inputs: this.inputs, + outputs: this.outputs, + locktime: this.locktime + }; }; TX.prototype.toCompact = function toCompact(coins) { return { - type: 'tx', + type: this.type, block: this.block, height: this.height, ts: this.ts, @@ -773,8 +776,6 @@ TX.prototype.toCompact = function toCompact(coins) { TX._fromCompact = function _fromCompact(json) { var raw, data, tx; - assert.equal(json.type, 'tx'); - raw = new Buffer(json.tx, 'hex'); data = bcoin.protocol.parser.parseTX(raw); @@ -795,12 +796,13 @@ TX._fromCompact = function _fromCompact(json) { }; TX.fromCompact = function fromCompact(json) { + assert.equal(json.type, 'tx'); return new TX(TX._fromCompact(json)); }; TX.prototype.toJSON = function toJSON() { return { - type: 'tx', + type: this.type, hash: utils.revHex(this.hash('hex')), height: this.height, block: this.block ? utils.revHex(this.block) : null, @@ -833,6 +835,7 @@ TX._fromJSON = function fromJSON(json) { }; TX.fromJSON = function fromJSON(json) { + assert.equal(json.type, 'tx'); return new TX(TX._fromJSON(json)); }; diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index 60337f43..c052a60d 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -1604,7 +1604,7 @@ utils.buildMerkleTree = function buildMerkleTree(items) { for (i = 0; i < size; i += 2) { i2 = Math.min(i + 1, size - 1); if (i2 === i + 1 && i2 + 1 === size - && tree[j + i] === tree[j + i2]) { + && utils.isEqual(tree[j + i], tree[j + i2])) { return; } hash = Buffer.concat([tree[j + i], tree[j + i2]]);