script encoding.

This commit is contained in:
Christopher Jeffrey 2016-03-15 02:59:09 -07:00
parent 94b20355ea
commit 4b1e055a05

View File

@ -2466,25 +2466,16 @@ Script.sign = function sign(msg, key, type) {
Script.decode = function decode(buf) {
var code = [];
var i = 0;
var off = 0;
var b, opcode, len;
if (!buf)
return [];
while (i < buf.length) {
b = buf[i++];
// Next `b` bytes should be pushed to stack
if (b >= 0x01 && b <= 0x4b) {
code.push(utils.slice(buf, i, i + b));
i += b;
utils.hidden(code[code.length - 1], 'pushdata', {
opcode: null,
len: b
});
continue;
}
// NOTE: We can't use a BufferReader here since
// script parsing was originally non-strict.
while (off < buf.length) {
b = buf[off++];
// OP_0, OP_FALSE
// Special case: this is an empty array
@ -2494,6 +2485,17 @@ Script.decode = function decode(buf) {
continue;
}
// Next `b` bytes should be pushed to stack
if (b >= 0x01 && b <= 0x4b) {
code.push(utils.slice(buf, off, off + b));
off += b;
utils.hidden(code[code.length - 1], 'pushdata', {
opcode: null,
len: b
});
continue;
}
// OP_1, OP_TRUE, OP_2-OP_16
// Special case: these get to be number
// literals. Note: 1negate is not included.
@ -2504,34 +2506,34 @@ Script.decode = function decode(buf) {
opcode = constants.opcodesByVal[b];
if (i >= buf.length) {
if (off >= buf.length) {
code.push(opcode || b);
continue;
}
if (opcode === 'pushdata1') {
len = buf[i];
i += 1;
code.push(utils.slice(buf, i, i + len));
i += len;
len = buf[off];
off += 1;
code.push(utils.slice(buf, off, off + len));
off += len;
utils.hidden(code[code.length - 1], 'pushdata', {
opcode: opcode,
len: len
});
} else if (opcode === 'pushdata2') {
len = utils.readU16(buf, i);
i += 2;
code.push(utils.slice(buf, i, i + len));
i += len;
len = utils.readU16(buf, off);
off += 2;
code.push(utils.slice(buf, off, off + len));
off += len;
utils.hidden(code[code.length - 1], 'pushdata', {
opcode: opcode,
len: len
});
} else if (opcode === 'pushdata4') {
len = utils.readU32(buf, i);
i += 4;
code.push(utils.slice(buf, i, i + len));
i += len;
len = utils.readU32(buf, off);
off += 4;
code.push(utils.slice(buf, off, off + len));
off += len;
utils.hidden(code[code.length - 1], 'pushdata', {
opcode: opcode,
len: len
@ -2545,111 +2547,65 @@ Script.decode = function decode(buf) {
};
Script.encode = function encode(code) {
var p = new bcoin.protocol.framer.BufferWriter();
var opcodes = constants.opcodes;
var i = 0;
var instr;
var total = 0;
var off = 0;
var buf;
if (!code)
return new Buffer([]);
if (code._raw)
return code._raw;
var op;
for (i = 0; i < code.length; i++) {
instr = code[i];
if (Buffer.isBuffer(instr)) {
if (instr.pushdata) {
if (instr.pushdata.opcode === null) {
total += 1 + instr.length;
} else if (instr.pushdata.opcode === 'pushdata1') {
total += 1 + 1 + instr.length;
} else if (instr.pushdata.opcode === 'pushdata2') {
total += 1 + 2 + instr.length;
} else if (instr.pushdata.opcode === 'pushdata4') {
total += 1 + 4 + instr.length;
}
continue;
}
if (instr.length === 0) {
total += 1;
} else if (1 <= instr.length && instr.length <= 0x4b) {
total += 1 + instr.length;
} else if (instr.length <= 0xff) {
total += 1 + 1 + instr.length;
} else if (instr.length <= 0xffff) {
total += 1 + 2 + instr.length;
} else {
total += 1 + 4 + instr.length;
}
continue;
}
total += 1;
}
buf = new Buffer(total);
for (i = 0; i < code.length; i++) {
instr = code[i];
assert(!Array.isArray(instr));
op = code[i];
// Push value to stack
if (Buffer.isBuffer(instr)) {
if (Buffer.isBuffer(op)) {
// Check for nonstandard pushdatas that
// may have been decoded from before.
if (instr.pushdata) {
if (instr.pushdata.opcode === null) {
buf[off++] = instr.pushdata.len;
off += instr.copy(buf, off, 0, instr.length);
} else if (instr.pushdata.opcode === 'pushdata1') {
buf[off++] = opcodes.pushdata1;
buf[off++] = instr.pushdata.len;
off += instr.copy(buf, off, 0, instr.length);
} else if (instr.pushdata.opcode === 'pushdata2') {
buf[off++] = opcodes.pushdata2;
off += utils.writeU16(buf, instr.pushdata.len, off);
off += instr.copy(buf, off, 0, instr.length);
} else if (instr.pushdata.opcode === 'pushdata4') {
buf[off++] = opcodes.pushdata4;
off += utils.writeU32(buf, instr.pushdata.len, off);
off += instr.copy(buf, off, 0, instr.length);
if (op.pushdata) {
if (op.pushdata.opcode === null) {
p.writeU8(op.pushdata.len);
p.writeBytes(op);
} else if (op.pushdata.opcode === 'pushdata1') {
p.writeU8(opcodes.pushdata1);
p.writeU8(op.pushdata.len);
p.writeBytes(op);
} else if (op.pushdata.opcode === 'pushdata2') {
p.writeU8(opcodes.pushdata2);
p.writeU16(op.pushdata.len);
p.writeBytes(op);
} else if (op.pushdata.opcode === 'pushdata4') {
p.writeU8(opcodes.pushdata4);
p.writeU32(op.pushdata.len);
p.writeBytes(op);
}
continue;
}
if (instr.length === 0) {
buf[off++] = opcodes['0'];
} else if (1 <= instr.length && instr.length <= 0x4b) {
buf[off++] = instr.length;
off += instr.copy(buf, off, 0, instr.length);
} else if (instr.length <= 0xff) {
buf[off++] = opcodes.pushdata1;
buf[off++] = instr.length;
off += instr.copy(buf, off, 0, instr.length);
} else if (instr.length <= 0xffff) {
buf[off++] = opcodes.pushdata2;
off += utils.writeU16(buf, instr.length, off);
off += instr.copy(buf, off, 0, instr.length);
// Standard minimaldata encoding
if (op.length === 0) {
p.writeU8(opcodes['0']);
} else if (op.length <= 0x4b) {
p.writeU8(op.length);
p.writeBytes(op);
} else if (op.length <= 0xff) {
p.writeU8(opcodes.pushdata1);
p.writeU8(op.length);
p.writeBytes(op);
} else if (op.length <= 0xffff) {
p.writeU8(opcodes.pushdata2);
p.writeU16(op.length);
p.writeBytes(op);
} else {
buf[off++] = opcodes.pushdata4;
off += utils.writeU32(buf, instr.length, off);
off += instr.copy(buf, off, 0, instr.length);
p.writeU8(opcodes.pushdata4);
p.writeU32(op.length);
p.writeBytes(op);
}
continue;
}
assert(opcodes[instr] != null || typeof instr === 'number');
assert(opcodes[op] != null || typeof op === 'number');
buf[off++] = opcodes[instr] || instr;
p.writeU8(opcodes[op] || op);
}
assert(off === buf.length);
return buf;
return p.render();
};
Script.witness = Witness;