deferred.

This commit is contained in:
Christopher Jeffrey 2016-06-12 05:23:28 -07:00
parent 95b62b4b65
commit 0abf791bb7
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -115,48 +115,6 @@ Coins.prototype.spend = function spend(index) {
return coin; 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. * Serialize the coins object.
* @param {TX|Coins} tx * @param {TX|Coins} tx
@ -187,7 +145,7 @@ Coins.prototype.toRaw = function toRaw(writer) {
} }
if (output instanceof DeferredCoin) { if (output instanceof DeferredCoin) {
p.writeBytes(output.raw); p.writeBytes(output.toRaw());
continue; continue;
} }
@ -228,7 +186,7 @@ Coins.prototype.toRaw = function toRaw(writer) {
Coins.parseRaw = function parseRaw(data, hash, index) { Coins.parseRaw = function parseRaw(data, hash, index) {
var p = new BufferReader(data); var p = new BufferReader(data);
var i = 0; var i = 0;
var version, height, coins, mask, prefix, raw; var version, height, coins, mask, prefix, offset, size;
version = p.readVarint(); version = p.readVarint();
height = p.readU32(); height = p.readU32();
@ -245,8 +203,7 @@ Coins.parseRaw = function parseRaw(data, hash, index) {
coins.height = -1; coins.height = -1;
while (p.left()) { while (p.left()) {
p.start(); offset = p.start();
mask = p.readU8(); mask = p.readU8();
if (mask === 0xff) { if (mask === 0xff) {
@ -272,15 +229,14 @@ Coins.parseRaw = function parseRaw(data, hash, index) {
p.readVarint(); p.readVarint();
size = p.end();
if (index != null && i !== index) { if (index != null && i !== index) {
p.end();
i++; i++;
continue; continue;
} }
raw = p.endData(true); coins.outputs.push(new DeferredCoin(offset, size, data));
coins.outputs.push(new DeferredCoin(raw));
if (index != null) if (index != null)
return coins.outputs[0].toCoin(coins, i); return coins.outputs[0].toCoin(coins, i);
@ -288,44 +244,11 @@ Coins.parseRaw = function parseRaw(data, hash, index) {
i++; i++;
} }
assert(index == null, 'Bad index.');
return coins; 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. * Parse a single serialized coin.
* @param {Buffer} data * @param {Buffer} data
@ -335,6 +258,7 @@ DeferredCoin.prototype.toRaw = function toRaw() {
*/ */
Coins.parseCoin = function parseCoin(data, hash, index) { Coins.parseCoin = function parseCoin(data, hash, index) {
assert(index != null, 'Bad index.');
return Coins.parseCoins(data, hash, 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 * Helpers
*/ */