always compile scripts.

This commit is contained in:
Christopher Jeffrey 2016-06-13 22:39:05 -07:00
parent 3f62a8ae42
commit 5ae6a4e02c
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 92 additions and 296 deletions

View File

@ -156,10 +156,10 @@ Coins.prototype.toRaw = function toRaw(writer) {
// Saves up to 7 bytes.
if (output.script.isPubkeyhash()) {
prefix = 1;
hash = output.script.raw.slice(3, 23);
hash = output.script.code[2].data;
} else if (output.script.isScripthash()) {
prefix = 2;
hash = output.script.raw.slice(2, 22);
hash = output.script.code[1].data;
}
p.writeU8(prefix);

View File

@ -812,40 +812,36 @@ Stack.isStack = function isStack(obj) {
* @property {Script?} redeem - Redeem script.
*/
function Script(code) {
if (code instanceof Script)
return code;
function Script(raw) {
if (raw instanceof Script)
return raw;
if (!(this instanceof Script))
return new Script(code);
return new Script(raw);
if (!code)
code = STACK_FALSE;
if (!raw)
raw = STACK_FALSE;
if (code.raw)
code = code.raw;
if (raw.raw)
raw = raw.raw;
this.raw = code;
this.raw = null;
this.code = null;
this._code = null;
this.redeem = null;
if (Array.isArray(code))
this.raw = Script.encodeArray(code);
if (Array.isArray(raw)) {
raw = Script.parseArray(raw);
this.raw = Script.encode(raw);
this.code = raw;
} else {
this.raw = raw;
this.code = Script.decode(raw);
}
assert(Buffer.isBuffer(this.raw));
assert(Array.isArray(this.code));
}
Script.prototype.__defineGetter__('code', function() {
if (!this._code)
this._code = Script.decode(this.raw);
return this._code;
});
Script.prototype.__defineSetter__('code', function(code) {
return this._code = code;
});
Script.prototype.toArray = function toArray() {
var code = [];
var i, op;
@ -859,22 +855,9 @@ Script.prototype.toArray = function toArray() {
};
Script.fromArray = function fromArray(code) {
var raw = Script.encodeArray(code);
return new Script(raw);
return new Script(code);
};
Script.prototype.toOps = function toOps() {
return this.code.slice();
};
Script.fromOps = function fromOps(code) {
var raw = Script.encode(code);
var script = new Script(raw);
script.code = code;
return script;
};
/**
* Clone the script.
* @returns {Script} Cloned script.
@ -960,7 +943,7 @@ Script.prototype.getSubscript = function getSubscript(lastSep) {
code.push(op);
}
return Script.fromOps(code);
return new Script(code);
};
/**
@ -986,7 +969,7 @@ Script.prototype.removeSeparators = function removeSeparators() {
if (code.length === this.code.length)
return this.clone();
return Script.fromOps(code);
return new Script(code);
};
/**
@ -2107,7 +2090,7 @@ Script.prototype.concat = function concat(scripts) {
*/
Script.createPubkey = function createPubkey(key) {
return Script.fromArray([key, opcodes.OP_CHECKSIG]);
return new Script([key, opcodes.OP_CHECKSIG]);
};
/**
@ -2117,7 +2100,7 @@ Script.createPubkey = function createPubkey(key) {
*/
Script.createPubkeyhash = function createPubkeyhash(hash) {
return Script.fromArray([
return new Script([
opcodes.OP_DUP,
opcodes.OP_HASH160,
hash,
@ -2152,7 +2135,7 @@ Script.createMultisig = function createMultisig(keys, m, n) {
code.push(n + 0x50);
code.push(opcodes.OP_CHECKMULTISIG);
return Script.fromArray(code);
return new Script(code);
};
/**
@ -2163,7 +2146,7 @@ Script.createMultisig = function createMultisig(keys, m, n) {
Script.createScripthash = function createScripthash(hash) {
assert(hash.length === 20);
return Script.fromArray([
return new Script([
opcodes.OP_HASH160,
hash,
opcodes.OP_EQUAL
@ -2179,7 +2162,7 @@ Script.createScripthash = function createScripthash(hash) {
Script.createNulldata = function createNulldata(flags) {
assert(Buffer.isBuffer(flags));
assert(flags.length <= constants.script.MAX_OP_RETURN, 'Nulldata too large.');
return Script.fromArray([
return new Script([
opcodes.OP_RETURN,
flags
]);
@ -2196,7 +2179,7 @@ Script.createWitnessProgram = function createWitnessProgram(version, data) {
assert(typeof version === 'number' && version >= 0 && version <= 16);
assert(Buffer.isBuffer(data));
assert(data.length >= 2 && data.length <= 32);
return Script.fromArray([version === 0 ? 0 : version + 0x50, data]);
return new Script([version === 0 ? 0 : version + 0x50, data]);
};
/**
@ -2219,7 +2202,7 @@ Script.createCommitment = function createCommitment(hash, flags) {
p.writeU32BE(0xaa21a9ed);
p.writeHash(hash);
return Script.fromArray([
return new Script([
opcodes.OP_RETURN,
p.render(),
flags
@ -3838,9 +3821,42 @@ Script.fromRaw = function fromRaw(data, enc) {
function Opcode(value, data) {
this.value = value;
this.data = data;
this.data = data || null;
}
Opcode.fromData = function fromData(data) {
if (data.length === 0)
return new Opcode(opcodes.OP_0);
if (data.length <= 0x4b) {
if (data.length === 1) {
if (data[0] >= 1 && data[0] <= 16)
return new Opcode(data[0] + 0x50);
if (data[0] === 0x81)
return new Opcode(opcodes.OP_1NEGATE);
}
return new Opcode(data.length, data);
}
if (data.length <= 0xff)
return new Opcode(opcodes.OP_PUSHDATA1, data);
if (data.length <= 0xffff)
return new Opcode(opcodes.OP_PUSHDATA2, data);
if (data.length <= 0xffffffff)
return new Opcode(opcodes.OP_PUSHDATA4, data);
assert(false, 'Bad pushdata size.');
};
Opcode.fromOp = function fromOp(op) {
return new Opcode(op);
};
Script.opcode = Opcode;
Script.decode = function decode(raw) {
var p = new BufferReader(raw, true);
var code = [];
@ -3948,54 +3964,47 @@ Script.encode = function encode(code, writer) {
return p;
};
Script.encodeArray = function encodeArray(code, writer) {
var p = new BufferWriter(writer);
Script.parseArray = function parseArray(code, writer) {
var out = [];
var i, op;
assert(Array.isArray(code));
if (code[0] instanceof Opcode)
return code;
for (i = 0; i < code.length; i++) {
op = code[i];
if (Buffer.isBuffer(op)) {
if (op.length === 0) {
p.writeU8(opcodes.OP_0);
out.push(new Opcode(opcodes.OP_0));
} else if (op.length <= 0x4b) {
if (op.length === 1) {
if (op[0] >= 1 && op[0] <= 16) {
p.writeU8(op[0] + 0x50);
out.push(new Opcode(op[0] + 0x50));
continue;
} else if (op[0] === 0x81) {
p.writeU8(opcodes.OP_1NEGATE);
out.push(new Opcode(opcodes.OP_1NEGATE));
continue;
}
}
p.writeU8(op.length);
p.writeBytes(op);
out.push(new Opcode(op.length, op));
} else if (op.length <= 0xff) {
p.writeU8(opcodes.OP_PUSHDATA1);
p.writeU8(op.length);
p.writeBytes(op);
out.push(new Opcode(opcodes.OP_PUSHDATA1, op));
} else if (op.length <= 0xffff) {
p.writeU8(opcodes.OP_PUSHDATA2);
p.writeU16(op.length);
p.writeBytes(op);
out.push(new Opcode(opcodes.OP_PUSHDATA2, op));
} else if (op.length <= 0xffffffff) {
p.writeU8(opcodes.OP_PUSHDATA4);
p.writeU32(op.length);
p.writeBytes(op);
out.push(new Opcode(opcodes.OP_PUSHDATA4, op));
} else {
assert(false, 'Bad pushdata op.');
}
continue;
}
assert(typeof op === 'number');
p.writeU8(op);
out.push(new Opcode(op));
}
if (!writer)
p = p.render();
return p;
return out;
};
/**
@ -4029,10 +4038,8 @@ Script.encodePush = function encodePush(data) {
return p.render();
};
function ScriptWriter(script) {
this.writer = new BufferWriter();
if (script)
this.writer.writeBytes(script.data);
function ScriptWriter() {
this.ops = [];
}
ScriptWriter.prototype.writeString = function writeString(str, enc) {
@ -4049,17 +4056,17 @@ ScriptWriter.prototype.writeData = function writeData(data, op) {
return this.writePush(data, op);
if (data.length === 0) {
p.writeU8(opcodes.OP_0);
this.ops.push(new Opcode(opcodes.OP_0));
return;
}
if (data.length === 1) {
if (data[0] >= 1 && data[0] <= 16) {
p.writeU8(data[0] + 0x50);
this.ops.push(new Opcode(data[0] + 0x50));
return;
}
if (data[0] === 0x81) {
p.writeU8(opcodes.OP_1NEGATE);
this.ops.push(new Opcode(opcodes.OP_1NEGATE));
return;
}
}
@ -4071,73 +4078,39 @@ ScriptWriter.prototype.writePush = function writePush(data, op) {
var p = this.writer;
if (op != null) {
if (op >= 0x01 && op <= 0x4b) {
p.writeU8(op);
p.writeBytes(data);
return;
}
if (op === opcodes.OP_PUSHDATA1) {
p.writeU8(op);
p.writeU8(data.length);
p.writeBytes(data);
return;
}
if (op === opcodes.OP_PUSHDATA2) {
p.writeU8(op);
p.writeU16(data.length);
p.writeBytes(data);
return;
}
if (op === opcodes.OP_PUSHDATA4) {
p.writeU8(op);
p.writeU32(data.length);
p.writeBytes(data);
return;
}
assert('Bad opcode.');
this.ops.push(new Opcode(op, data));
return;
}
if (data.length <= 0x4b) {
p.writeU8(data.length);
p.writeBytes(data);
this.ops.push(new Opcode(data.length, data));
return;
}
if (data.length <= 0xff) {
p.writeU8(opcodes.OP_PUSHDATA1);
p.writeU8(data.length);
p.writeBytes(data);
this.ops.push(new Opcode(opcodes.OP_PUSHDATA1, data));
return;
}
if (data.length <= 0xffff) {
p.writeU8(opcodes.OP_PUSHDATA2);
p.writeU16(data.length);
p.writeBytes(data);
this.ops.push(new Opcode(opcodes.OP_PUSHDATA2, data));
return;
}
if (data.length <= 0xffffffff) {
p.writeU8(opcodes.OP_PUSHDATA4);
p.writeU32(data.length);
p.writeBytes(data);
this.ops.push(new Opcode(opcodes.OP_PUSHDATA4, data));
return;
}
throw new Error('Pushdata too large.');
};
ScriptWriter.prototype.writeBytes = function writeBytes(data) {
this.writer.writeBytes(data);
};
ScriptWriter.prototype.writeScript = function writeScript(script) {
this.writeData(script.raw);
};
ScriptWriter.prototype.writeOp = function writeOp(opcode) {
this.writer.writeU8(opcode);
this.ops.push(new Opcode(opcode));
};
ScriptWriter.prototype.writeNumber = function writeNumber(num) {
@ -4165,182 +4138,7 @@ ScriptWriter.prototype.writeNumber = function writeNumber(num) {
};
ScriptWriter.prototype.toScript = function toScript() {
return new Script(this.writer.render());
};
function ScriptReader(script) {
this.raw = script.raw || script;
this.opcode = -1;
this.offset = 0;
this.ip = 0;
this.data = null;
}
ScriptReader.prototype.isMinimal = function isMinimal(flags) {
return Script.checkMinimal(this.data, this.opcode, flags);
};
ScriptReader.prototype.isInvalid = function isInvalid() {
return this.opcode === -1;
};
ScriptReader.prototype.reset = function reset() {
this.offset = 0;
this.ip = 0;
this.opcode = -1;
this.data = null;
};
ScriptReader.prototype.readString = function readString(enc) {
var str = this.readData();
if (!str)
return;
return str.toString(enc);
};
ScriptReader.prototype.readScript = function readScript() {
var script = this.readData();
if (!script)
return;
return new Script(script);
};
ScriptReader.prototype.readNumber = function readNumber(limit) {
this.next();
if (this.opcode === opcodes.OP_1NEGATE)
return -1;
if (this.opcode === opcodes.OP_0)
return 0;
if (this.opcode >= opcodes.OP_1 && this.opcode <= opcodes.OP_16)
return this.opcode - 0x50;
if (this.data)
return Script.num(this.data, 0, limit);
return null;
};
ScriptReader.prototype.readSmall = function readSmall() {
var op = this.readOp();
if (op === opcodes.OP_0)
return 0;
if (op >= opcodes.OP_1 && op <= opcodes.OP_16)
return op - 0x50;
return -1;
};
ScriptReader.prototype.readOp = function readOp() {
this.next(true);
return this.opcode;
};
ScriptReader.prototype.readData = function readData() {
this.next();
return this.data;
};
ScriptReader.prototype.seek = function seek() {
return this.next(true);
};
ScriptReader.prototype.peek = function peek() {
if (this.left() === 0)
return -1;
return this.raw[this.offset];
};
ScriptReader.prototype.left = function left() {
return this.raw.length - this.offset;
};
ScriptReader.prototype.next = function next(seek) {
var p = this.reader;
var op, data, size;
this.ip = this.offset;
this.opcode = -1;
this.data = null;
if (this.left() === 0)
return false;
op = this.raw[this.offset++];
if (op >= 0x01 && op <= 0x4b) {
if (this.left() < op) {
this.offset = this.raw.length;
return true;
}
if (!seek)
this.data = this.raw.slice(this.offset, this.offset + op);
this.offset += op;
this.opcode = op;
return true;
}
if (op === opcodes.OP_PUSHDATA1) {
if (this.left() < 1) {
this.offset = this.raw.length;
return true;
}
size = this.raw[this.offset++];
if (this.left() < size) {
this.offset = this.raw.length;
return true;
}
if (!seek)
this.data = this.raw.slice(this.offset, this.offset + size);
this.offset += size;
this.opcode = op;
return true;
}
if (op === opcodes.OP_PUSHDATA2) {
if (this.left() < 2) {
this.offset = this.raw.length;
return true;
}
size = this.raw.readUInt16LE(this.offset, true);
this.offset += 2;
if (this.left() < size) {
this.offset = this.raw.length;
return true;
}
if (!seek)
this.data = this.raw.slice(this.offset, this.offset + size);
this.offset += size;
this.opcode = op;
return true;
}
if (op === opcodes.OP_PUSHDATA4) {
if (this.left() < 4) {
this.offset = this.raw.length;
return true;
}
size = this.raw.readUInt32LE(this.offset, true);
this.offset += 4;
if (this.left() < size) {
this.offset = this.raw.length;
return true;
}
if (!seek)
this.data = this.raw.slice(this.offset, this.offset + size);
this.offset += size;
this.opcode = op;
return true;
}
this.opcode = op;
return true;
return new Script(this.ops);
};
/**

View File

@ -1039,10 +1039,8 @@ TX.prototype.getLegacySigops = function getLegacySigops() {
for (i = 0; i < this.inputs.length; i++)
total += this.inputs[i].script.getSigops(false);
for (i = 0; i < this.outputs.length; i++) {
for (i = 0; i < this.outputs.length; i++)
total += this.outputs[i].script.getSigops(false);
this.outputs[i].script.code = null;
}
return total;
};