coins: no compressed non-zero bytes.

This commit is contained in:
Christopher Jeffrey 2016-12-01 04:11:14 -08:00
parent 3d876858f9
commit 9f11875736
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -221,37 +221,24 @@ Coins.prototype.isEmpty = function isEmpty() {
Coins.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var len = this.outputs.length;
var first = len > 0 && this.outputs[0];
var second = len > 1 && this.outputs[1];
var size = 0;
var nonzero = 0;
var size = Math.floor((len + 5) / 8);
var first = this.has(0);
var second = this.has(1);
var offset = 0;
var i, j, code, ch, output;
// Throw if we're fully spent.
assert(len !== 0, 'Cannot serialize fully-spent coins.');
// Calculate number of unspents and spent field size.
// size = number of bytes required for the bit field.
// nonzero = number of non-zero bytes required.
for (i = 0; 2 + i * 8 < len; i++) {
for (j = 0; j < 8 && 2 + i * 8 + j < len; j++) {
if (this.outputs[2 + i * 8 + j]) {
size = i + 1;
nonzero++;
break;
}
}
}
// First and second bits
// have a double meaning.
if (!first && !second) {
assert(nonzero !== 0);
nonzero -= 1;
assert(size !== 0);
offset = 1;
}
// Calculate header code.
code = 8 * nonzero;
code = 8 * (size - offset);
if (this.coinbase)
code += 1;
@ -300,8 +287,11 @@ Coins.prototype.toRaw = function toRaw() {
Coins.prototype.fromRaw = function fromRaw(data, hash) {
var br = new BufferReader(data);
var i, code, field, nonzero, ch, unspent, coin;
var first = null;
var second = null;
var i, j, code, size, offset, ch;
// Inject hash (passed by caller).
this.hash = hash;
// Read headers.
@ -310,41 +300,36 @@ Coins.prototype.fromRaw = function fromRaw(data, hash) {
code = br.readVarint();
this.coinbase = (code & 1) !== 0;
// Setup spent field.
field = [
(code & 2) !== 0,
(code & 4) !== 0
];
// Recalculate number of non-zero bytes.
nonzero = code / 8 | 0;
size = code / 8 | 0;
if ((code & 6) === 0)
nonzero += 1;
size += 1;
// Read spent field.
while (nonzero > 0) {
ch = br.readU8();
for (i = 0; i < 8; i++) {
unspent = (ch & (1 << i)) !== 0;
field.push(unspent);
}
if (ch !== 0)
nonzero--;
}
// Setup spent field.
offset = br.offset;
br.seek(size);
// Read first two outputs.
if ((code & 2) !== 0)
first = CoinEntry.fromReader(br);
if ((code & 4) !== 0)
second = CoinEntry.fromReader(br);
this.outputs.push(first);
this.outputs.push(second);
// Read outputs.
for (i = 0; i < field.length; i++) {
if (!field[i]) {
this.outputs.push(null);
continue;
for (i = 0; i < size; i++) {
ch = br.data[offset++];
for (j = 0; j < 8; j++) {
if ((ch & (1 << j)) === 0) {
this.outputs.push(null);
continue;
}
this.outputs.push(CoinEntry.fromReader(br));
}
// Store the offset and size
// in the compressed coin object.
coin = CoinEntry.fromReader(br);
this.outputs.push(coin);
}
this.cleanup();
@ -363,8 +348,9 @@ Coins.prototype.fromRaw = function fromRaw(data, hash) {
Coins.parseCoin = function parseCoin(data, hash, index) {
var br = new BufferReader(data);
var coin = new Coin();
var i, code, field, nonzero, ch, unspent;
var i, j, code, size, offset, ch;
// Inject outpoint (passed by caller).
coin.hash = hash;
coin.index = index;
@ -374,56 +360,49 @@ Coins.parseCoin = function parseCoin(data, hash, index) {
code = br.readVarint();
coin.coinbase = (code & 1) !== 0;
// Setup spent field.
field = [
(code & 2) !== 0,
(code & 4) !== 0
];
// Recalculate number of non-zero bytes.
nonzero = code / 8 | 0;
size = code / 8 | 0;
if ((code & 6) === 0)
nonzero += 1;
size += 1;
// Read spent field.
while (nonzero > 0 && field.length <= index) {
ch = br.readU8();
for (i = 0; i < 8; i++) {
unspent = (ch & (1 << i)) !== 0;
field.push(unspent);
}
if (ch !== 0)
nonzero--;
}
if (field.length <= index)
if (index >= 2 + size * 8)
return;
while (nonzero > 0) {
if (br.readU8() !== 0)
nonzero--;
}
// Read spent field.
offset = br.offset;
br.seek(size);
// Read outputs.
for (i = 0; i < field.length; i++) {
if (i === index) {
if (!field[i])
for (i = 2; i <= 4; i += 2) {
if ((code & i) !== 0) {
if (index === 0) {
decompress.coin(coin, br);
return coin;
}
decompress.skip(br);
} else {
if (index === 0)
return;
// Read compressed output.
decompress.coin(coin, br);
break;
}
if (!field[i])
continue;
decompress.skip(br);
index -= 1;
}
return coin;
for (i = 0; i < size; i++) {
ch = br.data[offset++];
for (j = 0; j < 8; j++) {
if ((ch & (1 << j)) !== 0) {
if (index === 0) {
decompress.coin(coin, br);
return coin;
}
decompress.skip(br);
} else {
if (index === 0)
return;
}
index -= 1;
}
}
};
/**