chain: refactor coins.

This commit is contained in:
Christopher Jeffrey 2016-11-26 04:50:32 -08:00
parent 2d94935ddd
commit 9bc92abb41
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -317,8 +317,9 @@ Coins.prototype.toRaw = function toRaw(writer) {
Coins.prototype.fromRaw = function fromRaw(data, hash, index) {
var p = new BufferReader(data);
var i = 0;
var bits, coin, offset, size, fstart, flen, bit, oct, spent;
var pos = 0;
var fstart, flen, bit, oct;
var bits, coin, spent;
this.version = p.readVarint();
@ -339,72 +340,25 @@ Coins.prototype.fromRaw = function fromRaw(data, hash, index) {
while (p.left()) {
// Read a single bit out of the spent field.
bit = i % 8;
oct = (i - bit) / 8;
bit = pos % 8;
oct = (pos - bit) / 8;
spent = (p.data[fstart + oct] >>> (7 - bit)) & 1;
// Already spent.
if (spent) {
// Don't bother pushing outputs on if
// we're seeking to a specific index.
if (index != null) {
if (i === index)
return;
i++;
continue;
}
this.outputs.push(null);
i++;
continue;
}
offset = p.offset;
// Skip past the compressed scripts.
switch (p.readU8()) {
case 0:
p.seek(p.readVarint());
break;
case 1:
case 2:
p.seek(20);
break;
case 3:
p.seek(33);
break;
default:
throw new Error('Bad prefix.');
}
// Skip past the value.
p.readVarint();
size = p.offset - offset;
// Keep going if we're seeking
// to a specific index.
if (index != null && i !== index) {
i++;
pos++;
continue;
}
// Store the offset and size
// in the compressed coin object.
coin = new CompressedCoin(offset, size, data);
// We found our coin.
if (index != null)
return coin.toCoin(this, i);
coin = CompressedCoin.fromRaw(p);
this.outputs.push(coin);
i++;
pos++;
}
// We couldn't find our coin.
if (index != null)
return;
return this;
};
@ -417,8 +371,56 @@ Coins.prototype.fromRaw = function fromRaw(data, hash, index) {
*/
Coins.parseCoin = function parseCoin(data, hash, index) {
assert(index != null, 'Bad coin index.');
return new Coins().fromRaw(data, hash, index);
var p = new BufferReader(data);
var coin = new Coin();
var pos = 0;
var fstart, flen, bit, oct;
var spent, bits;
coin.version = p.readVarint();
bits = p.readU32();
coin.hash = hash;
coin.index = index;
coin.height = bits >>> 1;
coin.hash = hash;
coin.coinbase = (bits & 1) !== 0;
if (coin.height === 0x7fffffff)
coin.height = -1;
// Mark the start of the spent field and
// seek past it to avoid reading a buffer.
flen = p.readVarint();
fstart = p.offset;
p.seek(flen);
while (p.left()) {
// Read a single bit out of the spent field.
bit = pos % 8;
oct = (pos - bit) / 8;
spent = (p.data[fstart + oct] >>> (7 - bit)) & 1;
// We found our coin.
if (pos === index) {
if (spent)
return;
decompress.script(p, coin.script);
coin.value = p.readVarint();
return coin;
}
// Already spent.
if (spent) {
pos++;
continue;
}
// Skip passed the compressed coin.
skipCoin(p);
pos++;
}
};
/**
@ -439,7 +441,7 @@ Coins.fromRaw = function fromRaw(data, hash) {
*/
Coins.prototype.fromTX = function fromTX(tx) {
var i;
var i, output;
this.version = tx.version;
this.hash = tx.hash('hex');
@ -447,10 +449,13 @@ Coins.prototype.fromTX = function fromTX(tx) {
this.coinbase = tx.isCoinbase();
for (i = 0; i < tx.outputs.length; i++) {
if (tx.outputs[i].script.isUnspendable()) {
output = tx.outputs[i];
if (output.script.isUnspendable()) {
this.outputs.push(null);
continue;
}
this.outputs.push(Coin.fromTX(tx, i));
}
@ -487,9 +492,6 @@ Coins.fromTX = function fromTX(tx) {
*/
function CompressedCoin(offset, size, raw) {
if (!(this instanceof CompressedCoin))
return new CompressedCoin(offset, size, raw);
this.offset = offset;
this.size = size;
this.raw = raw;
@ -534,6 +536,47 @@ CompressedCoin.prototype.toRaw = function toRaw() {
return this.raw.slice(this.offset, this.offset + this.size);
};
/**
* Instantiate compressed coin from reader.
* @param {BufferReader} p
* @returns {CompressedCoin}
*/
CompressedCoin.fromRaw = function fromRaw(p) {
var offset = p.offset;
var size = skipCoin(p);
return new CompressedCoin(offset, size, p.data);
};
/*
* Helpers
*/
function skipCoin(p) {
var start = p.offset;
// Skip past the compressed scripts.
switch (p.readU8()) {
case 0:
p.seek(p.readVarint());
break;
case 1:
case 2:
p.seek(20);
break;
case 3:
p.seek(33);
break;
default:
throw new Error('Bad prefix.');
}
// Skip past the value.
p.readVarint();
return p.offset - start;
}
/*
* Expose
*/