coins: no compressed non-zero bytes.
This commit is contained in:
parent
3d876858f9
commit
9f11875736
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user