coins: refactor compression.
This commit is contained in:
parent
7fd2c409ae
commit
1997864ec2
@ -383,7 +383,7 @@ Coins.parseCoin = function parseCoin(data, hash, index) {
|
|||||||
if (pos === index) {
|
if (pos === index) {
|
||||||
if (spent)
|
if (spent)
|
||||||
return;
|
return;
|
||||||
decompress.script(br, coin.script);
|
decompress.script(coin.script, br);
|
||||||
coin.value = br.readVarint();
|
coin.value = br.readVarint();
|
||||||
return coin;
|
return coin;
|
||||||
}
|
}
|
||||||
@ -505,7 +505,7 @@ CoinEntry.prototype.toCoin = function toCoin(coins, index) {
|
|||||||
// Seek to the coin's offset.
|
// Seek to the coin's offset.
|
||||||
br.seek(this.offset);
|
br.seek(this.offset);
|
||||||
|
|
||||||
decompress.script(br, coin.script);
|
decompress.script(coin.script, br);
|
||||||
|
|
||||||
coin.value = br.readVarint();
|
coin.value = br.readVarint();
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,6 @@ var ec = require('../crypto/ec');
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function compressScript(script, bw) {
|
function compressScript(script, bw) {
|
||||||
var prefix = 0;
|
|
||||||
var data;
|
var data;
|
||||||
|
|
||||||
// Attempt to compress the output scripts.
|
// Attempt to compress the output scripts.
|
||||||
@ -28,62 +27,80 @@ function compressScript(script, bw) {
|
|||||||
// they are serialized as minimaldata, as
|
// they are serialized as minimaldata, as
|
||||||
// we need to recreate them when we read
|
// we need to recreate them when we read
|
||||||
// them.
|
// them.
|
||||||
|
|
||||||
|
// P2PKH -> 1 | key-hash
|
||||||
|
// Saves 5 bytes.
|
||||||
if (script.isPubkeyhash(true)) {
|
if (script.isPubkeyhash(true)) {
|
||||||
prefix = 1;
|
|
||||||
data = script.code[2].data;
|
data = script.code[2].data;
|
||||||
} else if (script.isScripthash()) {
|
bw.writeU8(1);
|
||||||
prefix = 2;
|
bw.writeBytes(data);
|
||||||
data = script.code[1].data;
|
return bw;
|
||||||
} else if (script.isPubkey(true)) {
|
|
||||||
prefix = 3;
|
|
||||||
data = script.code[0].data;
|
|
||||||
|
|
||||||
// Try to compress the key.
|
|
||||||
data = compressKey(data);
|
|
||||||
|
|
||||||
// If we can't compress it,
|
|
||||||
// just store the script.
|
|
||||||
if (!data)
|
|
||||||
prefix = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bw.writeU8(prefix);
|
// P2SH -> 2 | script-hash
|
||||||
|
// Saves 3 bytes.
|
||||||
if (prefix === 0)
|
if (script.isScripthash()) {
|
||||||
bw.writeVarBytes(script.toRaw());
|
data = script.code[1].data;
|
||||||
else
|
bw.writeU8(2);
|
||||||
bw.writeBytes(data);
|
bw.writeBytes(data);
|
||||||
|
return bw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// P2PK -> 3 | compressed-key
|
||||||
|
// Only works if the key is valid.
|
||||||
|
// Saves up to 34 bytes.
|
||||||
|
if (script.isPubkey(true)) {
|
||||||
|
data = script.code[0].data;
|
||||||
|
if (ec.publicKeyVerify(data)) {
|
||||||
|
data = compressKey(data);
|
||||||
|
bw.writeU8(3);
|
||||||
|
bw.writeBytes(data);
|
||||||
|
return bw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw -> 0 | varlen | script
|
||||||
|
bw.writeU8(0);
|
||||||
|
bw.writeVarBytes(script.toRaw());
|
||||||
|
|
||||||
|
return bw;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decompress a script from buffer reader.
|
* Decompress a script from buffer reader.
|
||||||
* @param {BufferReader} br
|
|
||||||
* @param {Script} script
|
* @param {Script} script
|
||||||
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function decompressScript(br, script) {
|
function decompressScript(script, br) {
|
||||||
var key;
|
var data;
|
||||||
|
|
||||||
// Decompress the script.
|
// Decompress the script.
|
||||||
switch (br.readU8()) {
|
switch (br.readU8()) {
|
||||||
case 0:
|
case 0:
|
||||||
script.fromRaw(br.readVarBytes());
|
data = br.readVarBytes();
|
||||||
|
script.fromRaw(data);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
script.fromPubkeyhash(br.readBytes(20));
|
data = br.readBytes(20, true);
|
||||||
|
script.fromPubkeyhash(data);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
script.fromScripthash(br.readBytes(20));
|
data = br.readBytes(20, true);
|
||||||
|
script.fromScripthash(data);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
data = br.readBytes(33, true);
|
||||||
// Decompress the key. If this fails,
|
// Decompress the key. If this fails,
|
||||||
// we have database corruption!
|
// we have database corruption!
|
||||||
key = decompressKey(br.readBytes(33));
|
data = decompressKey(data);
|
||||||
script.fromPubkey(key);
|
script.fromPubkey(data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error('Bad prefix.');
|
throw new Error('Bad prefix.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,10 +174,6 @@ function decompressValue(value) {
|
|||||||
function compressKey(key) {
|
function compressKey(key) {
|
||||||
var out;
|
var out;
|
||||||
|
|
||||||
// We can't compress it if it's not valid.
|
|
||||||
if (!ec.publicKeyVerify(key))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (key[0]) {
|
switch (key[0]) {
|
||||||
case 0x02:
|
case 0x02:
|
||||||
case 0x03:
|
case 0x03:
|
||||||
|
|||||||
@ -303,7 +303,7 @@ Coin.prototype.fromCompressed = function fromCompressed(data) {
|
|||||||
this.height = bits >>> 1;
|
this.height = bits >>> 1;
|
||||||
this.coinbase = (bits & 1) !== 0;
|
this.coinbase = (bits & 1) !== 0;
|
||||||
this.value = br.readVarint();
|
this.value = br.readVarint();
|
||||||
decompress.script(br, this.script);
|
decompress.script(this.script, br);
|
||||||
|
|
||||||
if (this.height === 0x7fffffff)
|
if (this.height === 0x7fffffff)
|
||||||
this.height = -1;
|
this.height = -1;
|
||||||
|
|||||||
@ -1507,10 +1507,18 @@ Script.isCode = function isCode(raw) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Script.prototype.fromPubkey = function fromPubkey(key) {
|
Script.prototype.fromPubkey = function fromPubkey(key) {
|
||||||
assert(Buffer.isBuffer(key) && key.length >= 33);
|
assert(Buffer.isBuffer(key) && key.length >= 33 && key.length <= 65);
|
||||||
this.push(key);
|
|
||||||
this.push(opcodes.OP_CHECKSIG);
|
this.raw = new Buffer(1 + key.length + 1);
|
||||||
this.compile();
|
this.raw[0] = key.length;
|
||||||
|
key.copy(this.raw, 1);
|
||||||
|
this.raw[1 + key.length] = opcodes.OP_CHECKSIG;
|
||||||
|
|
||||||
|
key = this.raw.slice(1, 1 + key.length);
|
||||||
|
|
||||||
|
this.code.push(new Opcode(key.length, key));
|
||||||
|
this.code.push(new Opcode(opcodes.OP_CHECKSIG));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user