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