From 0abf791bb71e92cbf9a514fc1ea08774e799990b Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sun, 12 Jun 2016 05:23:28 -0700 Subject: [PATCH] deferred. --- lib/bcoin/coins.js | 154 ++++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 85 deletions(-) diff --git a/lib/bcoin/coins.js b/lib/bcoin/coins.js index 7849a39d..58c3dc75 100644 --- a/lib/bcoin/coins.js +++ b/lib/bcoin/coins.js @@ -115,48 +115,6 @@ Coins.prototype.spend = function spend(index) { return coin; }; -/** - * Fill transaction(s) with coins. - * @param {TX} tx - * @param {Boolean?} spend - Whether the coins should - * be spent when filling. - * @returns {Boolean} True if all inputs were filled. - */ - -Coins.prototype.fill = function fill(tx) { - var res = true; - var i, input, prevout; - - for (i = 0; i < tx.inputs.length; i++) { - input = tx.inputs[i]; - prevout = input.prevout; - if (prevout.hash !== this.hash) - continue; - input.coin = this.spend(prevout.index); - if (!input.coin) - res = false; - } - - return res; -}; - -/** - * Convert collection to an array. - * @returns {Coin[]} - */ - -Coins.prototype.toArray = function toArray() { - var out = []; - var i; - - for (i = 0; i < this.outputs.length; i++) { - if (this.outputs[i]) - out.push(this.outputs[i]); - } - - return out; -}; - /** * Serialize the coins object. * @param {TX|Coins} tx @@ -187,7 +145,7 @@ Coins.prototype.toRaw = function toRaw(writer) { } if (output instanceof DeferredCoin) { - p.writeBytes(output.raw); + p.writeBytes(output.toRaw()); continue; } @@ -228,7 +186,7 @@ Coins.prototype.toRaw = function toRaw(writer) { Coins.parseRaw = function parseRaw(data, hash, index) { var p = new BufferReader(data); var i = 0; - var version, height, coins, mask, prefix, raw; + var version, height, coins, mask, prefix, offset, size; version = p.readVarint(); height = p.readU32(); @@ -245,8 +203,7 @@ Coins.parseRaw = function parseRaw(data, hash, index) { coins.height = -1; while (p.left()) { - p.start(); - + offset = p.start(); mask = p.readU8(); if (mask === 0xff) { @@ -272,15 +229,14 @@ Coins.parseRaw = function parseRaw(data, hash, index) { p.readVarint(); + size = p.end(); + if (index != null && i !== index) { - p.end(); i++; continue; } - raw = p.endData(true); - - coins.outputs.push(new DeferredCoin(raw)); + coins.outputs.push(new DeferredCoin(offset, size, data)); if (index != null) return coins.outputs[0].toCoin(coins, i); @@ -288,44 +244,11 @@ Coins.parseRaw = function parseRaw(data, hash, index) { i++; } + assert(index == null, 'Bad index.'); + return coins; }; -function DeferredCoin(raw) { - this.raw = raw; -} - -DeferredCoin.prototype.toCoin = function toCoin(coins, index) { - var p = new BufferReader(this.raw); - var prefix = p.readU8() & 3; - var script, value; - - if (prefix === 0) - script = new bcoin.script(bcoin.protocol.parser.parseScript(p)); - else if (prefix === 1) - script = bcoin.script.createPubkeyhash(p.readBytes(20)); - else if (prefix === 2) - script = bcoin.script.createScripthash(p.readBytes(20)); - else - assert(false, 'Bad prefix.'); - - value = p.readVarint(); - - return new bcoin.coin({ - version: coins.version, - coinbase: coins.coinbase, - height: coins.height, - hash: coins.hash, - index: index, - script: script, - value: value - }); -}; - -DeferredCoin.prototype.toRaw = function toRaw() { - return this.raw; -}; - /** * Parse a single serialized coin. * @param {Buffer} data @@ -335,6 +258,7 @@ DeferredCoin.prototype.toRaw = function toRaw() { */ Coins.parseCoin = function parseCoin(data, hash, index) { + assert(index != null, 'Bad index.'); return Coins.parseCoins(data, hash, index); }; @@ -376,6 +300,66 @@ Coins.fromTX = function fromTX(tx) { }); }; +/** + * A "deferred" coin is an object which defers + * parsing of a compressed coin. Say there is + * a transaction with 100 outputs. When block + * comes in, there may only be _one_ input in + * that entire block which redeems an output + * from that transaction. When parsing the + * Coins, there is no sense to get _all_ of + * them into their abstract form. A "deferred" + * coin is just a pointer to that coin in the + * Coins buffer, as well as a size. Parsing + * is done only if that coin is being redeemed. + * @exposes DeferredCoin + * @constructor + * @private + * @param {Number} offset + * @param {Number} size + * @param {Buffer} raw + */ + +function DeferredCoin(offset, size, raw) { + this.offset = offset; + this.size = size; + this.raw = raw; +} + +DeferredCoin.prototype.toCoin = function toCoin(coins, index) { + var p = new BufferReader(this.raw); + var prefix, script, value; + + p.seek(this.offset); + + prefix = p.readU8() & 3; + + if (prefix === 0) + script = new bcoin.script(bcoin.protocol.parser.parseScript(p)); + else if (prefix === 1) + script = bcoin.script.createPubkeyhash(p.readBytes(20)); + else if (prefix === 2) + script = bcoin.script.createScripthash(p.readBytes(20)); + else + assert(false, 'Bad prefix.'); + + value = p.readVarint(); + + return new bcoin.coin({ + version: coins.version, + coinbase: coins.coinbase, + height: coins.height, + hash: coins.hash, + index: index, + script: script, + value: value + }); +}; + +DeferredCoin.prototype.toRaw = function toRaw() { + return this.raw.slice(this.offset, this.offset + this.size); +}; + /* * Helpers */