From 5cb23020ff3f168f7a93c6a98b40a0ba6e0c4ce0 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 2 Jul 2016 17:20:46 -0700 Subject: [PATCH] implement coin spent field. --- lib/bcoin/coins.js | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/lib/bcoin/coins.js b/lib/bcoin/coins.js index 8311fe11..10ba7cda 100644 --- a/lib/bcoin/coins.js +++ b/lib/bcoin/coins.js @@ -177,9 +177,9 @@ Coins.prototype.getLength = function getLength() { * Coins serialization: * version: varint * bits: varint ((height << 1) | coinbase-flag) + * spent-field: varint size | bitmap (0=unspent, 1=spent) * outputs (repeated): - * prefix: 0xff = spent - * 0x00 = varint size | raw script + * prefix: 0x00 = varint size | raw script * 0x01 = 20 byte pubkey hash * 0x02 = 20 byte script hash * 0x03 = 33 byte compressed key @@ -197,7 +197,7 @@ Coins.prototype.toRaw = function toRaw(writer) { var p = new BufferWriter(writer); var height = this.height; var length = this.getLength(); - var i, output, prefix, data, bits; + var i, output, prefix, data, bits, field, pos, bit, oct; // Unfortunately, we don't have a compact // way to store unconfirmed height. @@ -215,13 +215,25 @@ Coins.prototype.toRaw = function toRaw(writer) { p.writeVarint(this.version); p.writeVarint(bits); + field = new Buffer(Math.ceil(length / 8)); + field.fill(0); + pos = 0; + + for (i = 0; i < length; i++) { + output = this.outputs[i] ? 0 : 1; + bit = pos % 8; + oct = (pos - bit) / 8; + field[oct] |= output << (7 - bit); + pos++; + } + + p.writeVarBytes(field); + for (i = 0; i < length; i++) { output = this.outputs[i]; - if (!output) { - p.writeU8(0xff); + if (!output) continue; - } if (output instanceof CompressedCoin) { p.writeBytes(output.toRaw()); @@ -280,7 +292,7 @@ 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, prefix, offset, size; + var bits, coin, prefix, offset, size, field, bit, oct, spent; this.version = p.readVarint(); @@ -293,14 +305,15 @@ Coins.prototype.fromRaw = function fromRaw(data, hash, index) { if (this.height === 0x7fffffff) this.height = -1; + field = p.readVarBytes(true); + while (p.left()) { - offset = p.start(); - prefix = p.readU8(); + bit = i % 8; + oct = (i - bit) / 8; + spent = (field[oct] >>> (7 - bit)) & 1; // Already spent. - if (prefix === 0xff) { - p.end(); - + if (spent) { // Don't bother pushing outputs on if // we're seeking to a specific index. if (index != null) { @@ -315,6 +328,9 @@ Coins.prototype.fromRaw = function fromRaw(data, hash, index) { continue; } + offset = p.start(); + prefix = p.readU8(); + // Skip past the compressed scripts. switch (prefix & 3) { case 0: