always compile scripts.
This commit is contained in:
parent
3f62a8ae42
commit
5ae6a4e02c
@ -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);
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user