chain: refactor coins.
This commit is contained in:
parent
2d94935ddd
commit
9bc92abb41
@ -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
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user