standard opcodes. remove tx methods.
This commit is contained in:
parent
6f4609792f
commit
3745577837
@ -38,22 +38,54 @@ exports.filterFlags = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.opcodes = {
|
exports.opcodes = {
|
||||||
0: 0,
|
// 'false': 0x00,
|
||||||
|
'0': 0x00,
|
||||||
|
|
||||||
pushdata1: 0x4c,
|
pushdata1: 0x4c,
|
||||||
pushdata2: 0x4d,
|
pushdata2: 0x4d,
|
||||||
pushdata4: 0x4e,
|
pushdata4: 0x4e,
|
||||||
// negate1: 0x4f,
|
|
||||||
|
'1negate': 0x4f,
|
||||||
|
|
||||||
|
reserved: 0x50,
|
||||||
|
|
||||||
|
// 'true': 0x51,
|
||||||
|
'1': 0x51,
|
||||||
|
'2': 0x52,
|
||||||
|
'3': 0x53,
|
||||||
|
'4': 0x54,
|
||||||
|
'5': 0x55,
|
||||||
|
'6': 0x56,
|
||||||
|
'7': 0x57,
|
||||||
|
'8': 0x58,
|
||||||
|
'9': 0x59,
|
||||||
|
'10': 0x5a,
|
||||||
|
'11': 0x5b,
|
||||||
|
'12': 0x5c,
|
||||||
|
'13': 0x5d,
|
||||||
|
'14': 0x5e,
|
||||||
|
'15': 0x5f,
|
||||||
|
'16': 0x60,
|
||||||
|
|
||||||
nop: 0x61,
|
nop: 0x61,
|
||||||
if_: 0x63,
|
ver: 0x62,
|
||||||
|
'if': 0x63,
|
||||||
notif: 0x64,
|
notif: 0x64,
|
||||||
else_: 0x67,
|
verif: 0x65,
|
||||||
|
vernotif: 0x66,
|
||||||
|
'else': 0x67,
|
||||||
endif: 0x68,
|
endif: 0x68,
|
||||||
verify: 0x69,
|
verify: 0x69,
|
||||||
ret: 0x6a,
|
'return': 0x6a,
|
||||||
|
|
||||||
toaltstack: 0x6b,
|
toaltstack: 0x6b,
|
||||||
fromaltstack: 0x6c,
|
fromaltstack: 0x6c,
|
||||||
|
'2drop': 0x6d,
|
||||||
|
'2dup': 0x6e,
|
||||||
|
'3dup': 0x6f,
|
||||||
|
'2over': 0x70,
|
||||||
|
'2rot': 0x71,
|
||||||
|
'2swap': 0x72,
|
||||||
ifdup: 0x73,
|
ifdup: 0x73,
|
||||||
depth: 0x74,
|
depth: 0x74,
|
||||||
drop: 0x75,
|
drop: 0x75,
|
||||||
@ -65,14 +97,8 @@ exports.opcodes = {
|
|||||||
rot: 0x7b,
|
rot: 0x7b,
|
||||||
swap: 0x7c,
|
swap: 0x7c,
|
||||||
tuck: 0x7d,
|
tuck: 0x7d,
|
||||||
drop2: 0x6d,
|
|
||||||
dup2: 0x6e,
|
|
||||||
dup3: 0x6f,
|
|
||||||
over2: 0x70,
|
|
||||||
rot2: 0x71,
|
|
||||||
swap2: 0x72,
|
|
||||||
|
|
||||||
cat: 0x74,
|
cat: 0x7e,
|
||||||
substr: 0x7f,
|
substr: 0x7f,
|
||||||
left: 0x80,
|
left: 0x80,
|
||||||
right: 0x81,
|
right: 0x81,
|
||||||
@ -82,17 +108,20 @@ exports.opcodes = {
|
|||||||
and: 0x84,
|
and: 0x84,
|
||||||
or: 0x85,
|
or: 0x85,
|
||||||
xor: 0x86,
|
xor: 0x86,
|
||||||
eq: 0x87,
|
equal: 0x87,
|
||||||
eqverify: 0x88,
|
equalverify: 0x88,
|
||||||
|
|
||||||
add1: 0x8b,
|
reserved1: 0x89,
|
||||||
sub1: 0x8c,
|
reserved2: 0x8a,
|
||||||
mul2: 0x8d,
|
|
||||||
div2: 0x8e,
|
'1add': 0x8b,
|
||||||
|
'1sub': 0x8c,
|
||||||
|
'2mul': 0x8d,
|
||||||
|
'2div': 0x8e,
|
||||||
negate: 0x8f,
|
negate: 0x8f,
|
||||||
abs: 0x90,
|
abs: 0x90,
|
||||||
not: 0x91,
|
not: 0x91,
|
||||||
noteq0: 0x92,
|
'0notequal': 0x92,
|
||||||
add: 0x93,
|
add: 0x93,
|
||||||
sub: 0x94,
|
sub: 0x94,
|
||||||
mul: 0x95,
|
mul: 0x95,
|
||||||
@ -102,13 +131,13 @@ exports.opcodes = {
|
|||||||
rshift: 0x99,
|
rshift: 0x99,
|
||||||
booland: 0x9a,
|
booland: 0x9a,
|
||||||
boolor: 0x9b,
|
boolor: 0x9b,
|
||||||
numeq: 0x9c,
|
numequal: 0x9c,
|
||||||
numeqverify: 0x9d,
|
numequalverify: 0x9d,
|
||||||
numneq: 0x9e,
|
numnotequal: 0x9e,
|
||||||
lt: 0x9f,
|
lessthan: 0x9f,
|
||||||
gt: 0xa0,
|
greaterthan: 0xa0,
|
||||||
lte: 0xa1,
|
lessthanorequal: 0xa1,
|
||||||
gte: 0xa2,
|
greaterthanorequal: 0xa2,
|
||||||
min: 0xa3,
|
min: 0xa3,
|
||||||
max: 0xa4,
|
max: 0xa4,
|
||||||
within: 0xa5,
|
within: 0xa5,
|
||||||
@ -118,27 +147,36 @@ exports.opcodes = {
|
|||||||
sha256: 0xa8,
|
sha256: 0xa8,
|
||||||
hash160: 0xa9,
|
hash160: 0xa9,
|
||||||
hash256: 0xaa,
|
hash256: 0xaa,
|
||||||
codesep: 0xab,
|
codeseparator: 0xab,
|
||||||
checksig: 0xac,
|
checksig: 0xac,
|
||||||
checksigverify: 0xad,
|
checksigverify: 0xad,
|
||||||
checkmultisig: 0xae,
|
checkmultisig: 0xae,
|
||||||
checkmultisigverify: 0xaf,
|
checkmultisigverify: 0xaf,
|
||||||
|
|
||||||
eval_: 0xb0,
|
// 'eval': 0xb0,
|
||||||
checklocktimeverify: 0xb1
|
nop1: 0xb0,
|
||||||
|
// nop2: 0xb1,
|
||||||
|
checklocktimeverify: 0xb1,
|
||||||
|
nop3: 0xb2,
|
||||||
|
nop4: 0xb3,
|
||||||
|
nop5: 0xb4,
|
||||||
|
nop6: 0xb5,
|
||||||
|
nop7: 0xb6,
|
||||||
|
nop8: 0xb7,
|
||||||
|
nop9: 0xb8,
|
||||||
|
nop10: 0xb9,
|
||||||
|
|
||||||
|
pubkeyhash: 0xfd,
|
||||||
|
pubkey: 0xfe,
|
||||||
|
invalidopcode: 0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.opcodes['-1'] = 0x50 + -1;
|
|
||||||
|
|
||||||
for (i = 1; i <= 16; i++)
|
|
||||||
exports.opcodes[i] = 0x50 + i;
|
|
||||||
|
|
||||||
for (i = 0; i <= 7; i++)
|
|
||||||
exports.opcodes['nop' + (i + 3)] = 0xb2 + i;
|
|
||||||
|
|
||||||
exports.opcodesByVal = new Array(256);
|
exports.opcodesByVal = new Array(256);
|
||||||
Object.keys(exports.opcodes).forEach(function(name) {
|
Object.keys(exports.opcodes).forEach(function(name) {
|
||||||
exports.opcodesByVal[exports.opcodes[name]] = name;
|
var val = exports.opcodes[name];
|
||||||
|
// if (val === 0x00 || (val >= 0x51 && val <= 0x60))
|
||||||
|
// name = +name;
|
||||||
|
exports.opcodesByVal[val] = name;
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.hashType = {
|
exports.hashType = {
|
||||||
|
|||||||
@ -37,14 +37,18 @@ script.decode = function decode(s) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zero
|
// OP_0, OP_FALSE
|
||||||
if (b === 0) {
|
// Special case: this is an empty array
|
||||||
|
// because it can be seen as an empty pushdata.
|
||||||
|
if (b === 0x00) {
|
||||||
opcodes.push([]);
|
opcodes.push([]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw number (-1 and 1-16)
|
// OP_1, OP_TRUE, OP_2-OP_16
|
||||||
if (b === 0x4f || (b >= 0x51 && b <= 0x60)) {
|
// Special case: these get to be number
|
||||||
|
// literals. Note: 1negate is not included.
|
||||||
|
if (b >= 0x51 && b <= 0x60) {
|
||||||
opcodes.push(b - 0x50);
|
opcodes.push(b - 0x50);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -126,8 +130,7 @@ script.encode = function encode(s) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (instr.length === 0) {
|
if (instr.length === 0) {
|
||||||
// OP_FALSE
|
res.push(opcodes['0']);
|
||||||
res.push(0);
|
|
||||||
} else if (1 <= instr.length && instr.length <= 0x4b) {
|
} else if (1 <= instr.length && instr.length <= 0x4b) {
|
||||||
res = res.concat(instr.length, instr);
|
res = res.concat(instr.length, instr);
|
||||||
} else if (instr.length <= 0xff) {
|
} else if (instr.length <= 0xff) {
|
||||||
@ -150,6 +153,47 @@ script.encode = function encode(s) {
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script.normalize = function normalize(s) {
|
||||||
|
var i, op;
|
||||||
|
|
||||||
|
// Remove OP_ prefixes and lowercase
|
||||||
|
for (i = 0; i < s.length; i++) {
|
||||||
|
op = s[i];
|
||||||
|
if (typeof op === 'string') {
|
||||||
|
op = op.toLowerCase();
|
||||||
|
if (op.indexOf('op_') === 0)
|
||||||
|
op = op.slice(3);
|
||||||
|
}
|
||||||
|
s[i] = op;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert OP_0 to array, convert OP_1-OP_16
|
||||||
|
// to number literals, convert -1 to OP_1NEGATE.
|
||||||
|
// Convert hex strings to arrays.
|
||||||
|
for (i = 0; i < s.length; i++) {
|
||||||
|
op = s[i];
|
||||||
|
|
||||||
|
if (op === '-1' || op === -1)
|
||||||
|
op = '1negate';
|
||||||
|
else if (op === '0' || op === 0 || op === 'false')
|
||||||
|
op = [];
|
||||||
|
else if (op === 'true')
|
||||||
|
op = 1;
|
||||||
|
else if (+op >= 1 && +op <= 16)
|
||||||
|
op = +op;
|
||||||
|
|
||||||
|
if (typeof op === 'string' && constants.opcodes[op] == null) {
|
||||||
|
if (op[0] === '[')
|
||||||
|
op = op.slice(1, -1);
|
||||||
|
op = utils.toArray(op, 'hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
s[i] = op;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
script.verify = function verify(input, output, tx, i, flags) {
|
script.verify = function verify(input, output, tx, i, flags) {
|
||||||
var copy, res, redeem;
|
var copy, res, redeem;
|
||||||
var stack = [];
|
var stack = [];
|
||||||
@ -218,11 +262,11 @@ script.subscript = function subscript(s, lastSep) {
|
|||||||
if (lastSep == null)
|
if (lastSep == null)
|
||||||
lastSep = -1;
|
lastSep = -1;
|
||||||
|
|
||||||
assert(lastSep <= 0 || s[lastSep] === 'codesep');
|
assert(lastSep <= 0 || s[lastSep] === 'codeseparator');
|
||||||
|
|
||||||
res = [];
|
res = [];
|
||||||
for (i = lastSep + 1; i < s.length; i++) {
|
for (i = lastSep + 1; i < s.length; i++) {
|
||||||
if (s[i] !== 'codesep')
|
if (s[i] !== 'codeseparator')
|
||||||
res.push(s[i]);
|
res.push(s[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,9 +307,9 @@ script._next = function _next(to, s, pc) {
|
|||||||
while (s[pc]) {
|
while (s[pc]) {
|
||||||
o = s[pc];
|
o = s[pc];
|
||||||
|
|
||||||
if (o === 'if_' || o === 'notif')
|
if (o === 'if' || o === 'notif')
|
||||||
depth++;
|
depth++;
|
||||||
else if (o === 'else_')
|
else if (o === 'else')
|
||||||
depth--;
|
depth--;
|
||||||
else if (o === 'endif')
|
else if (o === 'endif')
|
||||||
depth--;
|
depth--;
|
||||||
@ -276,7 +320,7 @@ script._next = function _next(to, s, pc) {
|
|||||||
if (depth === 0 && o === to)
|
if (depth === 0 && o === to)
|
||||||
return pc;
|
return pc;
|
||||||
|
|
||||||
if (o === 'else_')
|
if (o === 'else')
|
||||||
depth++;
|
depth++;
|
||||||
|
|
||||||
pc++;
|
pc++;
|
||||||
@ -319,7 +363,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o === -1 || (o >= 1 && o <= 16)) {
|
if (o >= 1 && o <= 16) {
|
||||||
stack.push([o]);
|
stack.push([o]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -336,7 +380,11 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
case 'nop10': {
|
case 'nop10': {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'if_':
|
case '1negate': {
|
||||||
|
stack.push([-1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'if':
|
||||||
case 'notif': {
|
case 'notif': {
|
||||||
if (stack.length < 1)
|
if (stack.length < 1)
|
||||||
return false;
|
return false;
|
||||||
@ -345,7 +393,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
if (o === 'notif')
|
if (o === 'notif')
|
||||||
val = !val;
|
val = !val;
|
||||||
if_ = pc;
|
if_ = pc;
|
||||||
else_ = script._next('else_', s, pc);
|
else_ = script._next('else', s, pc);
|
||||||
endif = script._next('endif', s, pc);
|
endif = script._next('endif', s, pc);
|
||||||
// Splice out the statement blocks we don't need
|
// Splice out the statement blocks we don't need
|
||||||
if (val) {
|
if (val) {
|
||||||
@ -372,7 +420,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
pc--;
|
pc--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'else_': {
|
case 'else': {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case 'endif': {
|
case 'endif': {
|
||||||
@ -385,7 +433,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'ret': {
|
case 'return': {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case 'toaltstack': {
|
case 'toaltstack': {
|
||||||
@ -479,14 +527,14 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
stack.splice(stack.length - 2, 0, stack[stack.length - 1]);
|
stack.splice(stack.length - 2, 0, stack[stack.length - 1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'drop2': {
|
case '2drop': {
|
||||||
if (stack.length < 2)
|
if (stack.length < 2)
|
||||||
return false;
|
return false;
|
||||||
stack.pop();
|
stack.pop();
|
||||||
stack.pop();
|
stack.pop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'dup2': {
|
case '2dup': {
|
||||||
if (stack.length < 2)
|
if (stack.length < 2)
|
||||||
return false;
|
return false;
|
||||||
v1 = stack[stack.length - 2];
|
v1 = stack[stack.length - 2];
|
||||||
@ -495,7 +543,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
stack.push(v2);
|
stack.push(v2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'dup3': {
|
case '3dup': {
|
||||||
if (stack.length < 3)
|
if (stack.length < 3)
|
||||||
return false;
|
return false;
|
||||||
v1 = stack[stack.length - 3];
|
v1 = stack[stack.length - 3];
|
||||||
@ -506,7 +554,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
stack.push(v3);
|
stack.push(v3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'over2': {
|
case '2over': {
|
||||||
if (stack.length < 4)
|
if (stack.length < 4)
|
||||||
return false;
|
return false;
|
||||||
v1 = stack[stack.length - 4];
|
v1 = stack[stack.length - 4];
|
||||||
@ -515,7 +563,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
stack.push(v2);
|
stack.push(v2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'rot2': {
|
case '2rot': {
|
||||||
if (stack.length < 6)
|
if (stack.length < 6)
|
||||||
return false;
|
return false;
|
||||||
v1 = stack[stack.length - 6];
|
v1 = stack[stack.length - 6];
|
||||||
@ -525,7 +573,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
stack.push(v2);
|
stack.push(v2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'swap2': {
|
case '2swap': {
|
||||||
if (stack.length < 4)
|
if (stack.length < 4)
|
||||||
return false;
|
return false;
|
||||||
v4 = stack[stack.length - 4];
|
v4 = stack[stack.length - 4];
|
||||||
@ -544,20 +592,20 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
stack.push(script.array(stack[stack.length - 1].length || 0));
|
stack.push(script.array(stack[stack.length - 1].length || 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'add1':
|
case '1add':
|
||||||
case 'sub1':
|
case '1sub':
|
||||||
case 'negate':
|
case 'negate':
|
||||||
case 'abs':
|
case 'abs':
|
||||||
case 'not':
|
case 'not':
|
||||||
case 'noteq0': {
|
case '0notequal': {
|
||||||
if (stack.length < 1)
|
if (stack.length < 1)
|
||||||
return false;
|
return false;
|
||||||
n = script.num(stack.pop());
|
n = script.num(stack.pop());
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case 'add1':
|
case '1add':
|
||||||
n.iadd(1);
|
n.iadd(1);
|
||||||
break;
|
break;
|
||||||
case 'sub1':
|
case '1sub':
|
||||||
n.isub(1);
|
n.isub(1);
|
||||||
break;
|
break;
|
||||||
case 'negate':
|
case 'negate':
|
||||||
@ -570,7 +618,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
case 'not':
|
case 'not':
|
||||||
n = n.cmpn(0) === 0;
|
n = n.cmpn(0) === 0;
|
||||||
break;
|
break;
|
||||||
case 'noteq0':
|
case '0notequal':
|
||||||
n = n.cmpn(0) !== 0;
|
n = n.cmpn(0) !== 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -585,13 +633,13 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
case 'sub':
|
case 'sub':
|
||||||
case 'booland':
|
case 'booland':
|
||||||
case 'boolor':
|
case 'boolor':
|
||||||
case 'numeq':
|
case 'numequal':
|
||||||
case 'numeqverify':
|
case 'numequalverify':
|
||||||
case 'numneq':
|
case 'numnotequal':
|
||||||
case 'lt':
|
case 'lessthan':
|
||||||
case 'gt':
|
case 'greaterthan':
|
||||||
case 'lte':
|
case 'lessthanorequal':
|
||||||
case 'gte':
|
case 'greaterthanorequal':
|
||||||
case 'min':
|
case 'min':
|
||||||
case 'max': {
|
case 'max': {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
@ -599,13 +647,13 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
case 'sub':
|
case 'sub':
|
||||||
case 'booland':
|
case 'booland':
|
||||||
case 'boolor':
|
case 'boolor':
|
||||||
case 'numeq':
|
case 'numequal':
|
||||||
case 'numeqverify':
|
case 'numequalverify':
|
||||||
case 'numneq':
|
case 'numnotequal':
|
||||||
case 'lt':
|
case 'lessthan':
|
||||||
case 'gt':
|
case 'greaterthan':
|
||||||
case 'lte':
|
case 'lessthanorequal':
|
||||||
case 'gte':
|
case 'greaterthanorequal':
|
||||||
case 'min':
|
case 'min':
|
||||||
case 'max':
|
case 'max':
|
||||||
if (stack.length < 2)
|
if (stack.length < 2)
|
||||||
@ -626,25 +674,25 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
case 'boolor':
|
case 'boolor':
|
||||||
n = n1.cmpn(0) !== 0 || n2.cmpn(0) !== 0;
|
n = n1.cmpn(0) !== 0 || n2.cmpn(0) !== 0;
|
||||||
break;
|
break;
|
||||||
case 'numeq':
|
case 'numequal':
|
||||||
n = n1.cmp(n2) === 0;
|
n = n1.cmp(n2) === 0;
|
||||||
break;
|
break;
|
||||||
case 'numeqverify':
|
case 'numequalverify':
|
||||||
n = n1.cmp(n2) === 0;
|
n = n1.cmp(n2) === 0;
|
||||||
break;
|
break;
|
||||||
case 'numneq':
|
case 'numnotequal':
|
||||||
n = n1.cmp(n2) !== 0;
|
n = n1.cmp(n2) !== 0;
|
||||||
break;
|
break;
|
||||||
case 'lt':
|
case 'lessthan':
|
||||||
n = n1.cmp(n2) < 0;
|
n = n1.cmp(n2) < 0;
|
||||||
break;
|
break;
|
||||||
case 'gt':
|
case 'greaterthan':
|
||||||
n = n1.cmp(n2) > 0;
|
n = n1.cmp(n2) > 0;
|
||||||
break;
|
break;
|
||||||
case 'lte':
|
case 'lessthanorequal':
|
||||||
n = n1.cmp(n2) <= 0;
|
n = n1.cmp(n2) <= 0;
|
||||||
break;
|
break;
|
||||||
case 'gte':
|
case 'greaterthanorequal':
|
||||||
n = n1.cmp(n2) >= 0;
|
n = n1.cmp(n2) >= 0;
|
||||||
break;
|
break;
|
||||||
case 'min':
|
case 'min':
|
||||||
@ -659,7 +707,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
if (typeof n === 'boolean')
|
if (typeof n === 'boolean')
|
||||||
n = script.num(+n);
|
n = script.num(+n);
|
||||||
res = n.cmpn(0) !== 0;
|
res = n.cmpn(0) !== 0;
|
||||||
if (o === 'numeqverify') {
|
if (o === 'numequalverify') {
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -679,7 +727,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'codesep': {
|
case 'codeseparator': {
|
||||||
lastSep = pc;
|
lastSep = pc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -713,12 +761,12 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
stack.push(utils.ripesha(stack.pop()));
|
stack.push(utils.ripesha(stack.pop()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'eqverify':
|
case 'equalverify':
|
||||||
case 'eq': {
|
case 'equal': {
|
||||||
if (stack.length < 2)
|
if (stack.length < 2)
|
||||||
return false;
|
return false;
|
||||||
res = utils.isEqual(stack.pop(), stack.pop());
|
res = utils.isEqual(stack.pop(), stack.pop());
|
||||||
if (o === 'eqverify') {
|
if (o === 'equalverify') {
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -886,7 +934,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'eval_': {
|
case 'nop1': {
|
||||||
// OP_EVAL = OP_NOP1
|
// OP_EVAL = OP_NOP1
|
||||||
if (!flags.allowEval)
|
if (!flags.allowEval)
|
||||||
break;
|
break;
|
||||||
@ -904,7 +952,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
evalScript = script.decode(evalScript);
|
evalScript = script.decode(evalScript);
|
||||||
|
|
||||||
res = evalScript.some(function(op) {
|
res = evalScript.some(function(op) {
|
||||||
return op === 'codesep';
|
return op === 'codeseparator';
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
@ -1023,7 +1071,7 @@ script.checkPush = function checkPush(op, value) {
|
|||||||
return op >= constants.opcodes['1'] && op <= constants.opcodes['16'];
|
return op >= constants.opcodes['1'] && op <= constants.opcodes['16'];
|
||||||
|
|
||||||
if (value.length === 1 && value[0] === -1)
|
if (value.length === 1 && value[0] === -1)
|
||||||
return op === constants.opcodes['-1'];
|
return op === constants.opcodes['1negate'];
|
||||||
|
|
||||||
if (value.length <= 75)
|
if (value.length <= 75)
|
||||||
return op === value.length;
|
return op === value.length;
|
||||||
@ -1037,24 +1085,26 @@ script.checkPush = function checkPush(op, value) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
script.redeem = function redeem(keys, m, n) {
|
script.createMultisig = function createMultisig(keys, m, n) {
|
||||||
if (keys.length !== n)
|
if (keys.length !== n)
|
||||||
throw new Error(n + ' keys are required to generate redeem script');
|
throw new Error(n + ' keys are required to generate multisig script');
|
||||||
|
|
||||||
assert(m >= 1 && m <= n);
|
assert(m >= 1 && m <= n);
|
||||||
assert(n >= 1 && n <= 15);
|
assert(n >= 1 && n <= 15);
|
||||||
|
|
||||||
while (keys.length < n)
|
|
||||||
keys.push([]);
|
|
||||||
|
|
||||||
keys = utils.sortKeys(keys);
|
|
||||||
|
|
||||||
return [m].concat(
|
return [m].concat(
|
||||||
keys,
|
utils.sortKeys(keys),
|
||||||
[n, 'checkmultisig']
|
[n, 'checkmultisig']
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script.redeem = function redeem(s) {
|
||||||
|
if (!Array.isArray(s[s.length - 1]))
|
||||||
|
return;
|
||||||
|
|
||||||
|
return bcoin.script.decode(s[s.length - 1]);
|
||||||
|
};
|
||||||
|
|
||||||
script.standard = function standard(s) {
|
script.standard = function standard(s) {
|
||||||
return (script.isPubkey(s) && 'pubkey')
|
return (script.isPubkey(s) && 'pubkey')
|
||||||
|| (script.isPubkeyhash(s) && 'pubkeyhash')
|
|| (script.isPubkeyhash(s) && 'pubkeyhash')
|
||||||
@ -1099,7 +1149,7 @@ script.isLockTime = function isLockTime(s, check) {
|
|||||||
&& Array.isArray(s[0])
|
&& Array.isArray(s[0])
|
||||||
&& s[1] === 'checklocktimeverify'
|
&& s[1] === 'checklocktimeverify'
|
||||||
&& s[2] === 'drop'
|
&& s[2] === 'drop'
|
||||||
&& s[3] === 'codesep';
|
&& s[3] === 'codeseparator';
|
||||||
};
|
};
|
||||||
|
|
||||||
script.lockTime = function lockTime(s) {
|
script.lockTime = function lockTime(s) {
|
||||||
@ -1292,7 +1342,7 @@ script.isPubkeyhash = function isPubkeyhash(s, hash) {
|
|||||||
res = s[0] === 'dup'
|
res = s[0] === 'dup'
|
||||||
&& s[1] === 'hash160'
|
&& s[1] === 'hash160'
|
||||||
&& script.isHash(s[2])
|
&& script.isHash(s[2])
|
||||||
&& s[3] === 'eqverify'
|
&& s[3] === 'equalverify'
|
||||||
&& s[4] === 'checksig';
|
&& s[4] === 'checksig';
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
@ -1386,7 +1436,7 @@ script.isScripthash = function isScripthash(s, hash) {
|
|||||||
|
|
||||||
res = s[0] === 'hash160'
|
res = s[0] === 'hash160'
|
||||||
&& script.isHash(s[1])
|
&& script.isHash(s[1])
|
||||||
&& s[2] === 'eq';
|
&& s[2] === 'equal';
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
@ -1405,7 +1455,7 @@ script.isNulldata = function isNulldata(s) {
|
|||||||
if (s.length !== 2)
|
if (s.length !== 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
res = s[0] === 'ret' && script.isData(s[1]);
|
res = s[0] === 'return' && script.isData(s[1]);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
@ -1485,7 +1535,7 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
|||||||
assert(keys.length >= 2);
|
assert(keys.length >= 2);
|
||||||
assert(tx);
|
assert(tx);
|
||||||
assert(i != null);
|
assert(i != null);
|
||||||
o = script.redeem(keys, s.length - 1, keys.length);
|
o = script.createMultisig(keys, s.length - 1, keys.length);
|
||||||
if (!script.verify(s, o, tx, i))
|
if (!script.verify(s, o, tx, i))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1494,7 +1544,7 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
|||||||
// var recovered = [];
|
// var recovered = [];
|
||||||
// for (i = 1; i < s.length; i++) {
|
// for (i = 1; i < s.length; i++) {
|
||||||
// var sig = s[i];
|
// var sig = s[i];
|
||||||
// var prev = script.redeem(keys, s.length - 1, keys.length);
|
// var prev = script.createMultisig(keys, s.length - 1, keys.length);
|
||||||
// var msg = tx.signatureHash(i, prev, s[s.length - 1]);
|
// var msg = tx.signatureHash(i, prev, s[s.length - 1]);
|
||||||
// var key = bcoin.ecdsa.recoverPubKey(msg, sig.slice(0, -1), 0).toArray();
|
// var key = bcoin.ecdsa.recoverPubKey(msg, sig.slice(0, -1), 0).toArray();
|
||||||
// recovered.push(key);
|
// recovered.push(key);
|
||||||
@ -1889,9 +1939,7 @@ script.pushOnly = function pushOnly(s) {
|
|||||||
var i, op;
|
var i, op;
|
||||||
for (i = 0; i < s.length; i++) {
|
for (i = 0; i < s.length; i++) {
|
||||||
op = s[i];
|
op = s[i];
|
||||||
// if (Array.isArray(op) || (constants.opcodes[op] <= constants.opcodes['16']))
|
if (Array.isArray(op) || op === '1negate' || (op >= 1 && op <= 16))
|
||||||
// continue;
|
|
||||||
if (Array.isArray(op) || (op >= -1 && op <= 16))
|
|
||||||
continue;
|
continue;
|
||||||
if (constants.opcodes[op] == null)
|
if (constants.opcodes[op] == null)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -450,68 +450,6 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
return signatures === m;
|
return signatures === m;
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.prevOut = function outputScript(i) {
|
|
||||||
var input;
|
|
||||||
|
|
||||||
if (typeof i !== 'number')
|
|
||||||
i = this.inputs.indexOf(i);
|
|
||||||
|
|
||||||
input = this.inputs[i];
|
|
||||||
|
|
||||||
if (!input.out.tx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
return input.out.tx.outputs[input.out.index];
|
|
||||||
};
|
|
||||||
|
|
||||||
TX.prototype.outputScript = function outputScript(i) {
|
|
||||||
var output = this.prevOut(i);
|
|
||||||
if (!output)
|
|
||||||
return;
|
|
||||||
return output.script;
|
|
||||||
};
|
|
||||||
|
|
||||||
bcoin.script.redeemScript = function redeemScript(s) {
|
|
||||||
if (!Array.isArray(s[s.length - 1]))
|
|
||||||
return;
|
|
||||||
|
|
||||||
return bcoin.script.decode(s[s.length - 1]);
|
|
||||||
};
|
|
||||||
|
|
||||||
TX.prototype.redeemScript = function redeemScript(i) {
|
|
||||||
var input, prev;
|
|
||||||
|
|
||||||
if (typeof i !== 'number')
|
|
||||||
i = this.inputs.indexOf(i);
|
|
||||||
|
|
||||||
input = this.inputs[i];
|
|
||||||
prev = this.outputScript(i);
|
|
||||||
|
|
||||||
if (prev && bcoin.script.isScripthash(prev))
|
|
||||||
return bcoin.script.redeemScript(input.script);
|
|
||||||
|
|
||||||
return prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
TX.prototype.finalize = function finalize() {
|
|
||||||
var i, input, s, len, j;
|
|
||||||
for (i = 0; i < this.inputs.length; i++) {
|
|
||||||
input = this.inputs[i];
|
|
||||||
s = input.out.tx.getSubscript(input.out.index);
|
|
||||||
len = s.length;
|
|
||||||
|
|
||||||
if (bcoin.script.isScripthash(s))
|
|
||||||
len--;
|
|
||||||
|
|
||||||
for (j = len - 1; j >= 1; j--) {
|
|
||||||
if (bcoin.script.isEmpty(input.script[j])) {
|
|
||||||
input.script.splice(j, 1);
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
|
TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
|
||||||
var input;
|
var input;
|
||||||
|
|
||||||
@ -621,7 +559,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
if (!(n >= 1 && n <= (options.scripthash ? 15 : 3)))
|
if (!(n >= 1 && n <= (options.scripthash ? 15 : 3)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
script = bcoin.script.redeem(keys, m, n);
|
script = bcoin.script.createMultisig(keys, m, n);
|
||||||
} else if (bcoin.wallet.validateAddress(options.address, 'scripthash')) {
|
} else if (bcoin.wallet.validateAddress(options.address, 'scripthash')) {
|
||||||
// P2SH Transaction
|
// P2SH Transaction
|
||||||
// https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
|
// https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
|
||||||
@ -629,7 +567,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
script = [
|
script = [
|
||||||
'hash160',
|
'hash160',
|
||||||
bcoin.wallet.addr2hash(options.address, 'scripthash'),
|
bcoin.wallet.addr2hash(options.address, 'scripthash'),
|
||||||
'eq'
|
'equal'
|
||||||
];
|
];
|
||||||
} else if (options.address) {
|
} else if (options.address) {
|
||||||
// P2PKH Transaction
|
// P2PKH Transaction
|
||||||
@ -638,7 +576,7 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
'dup',
|
'dup',
|
||||||
'hash160',
|
'hash160',
|
||||||
bcoin.wallet.addr2hash(options.address, 'pubkeyhash'),
|
bcoin.wallet.addr2hash(options.address, 'pubkeyhash'),
|
||||||
'eqverify',
|
'equalverify',
|
||||||
'checksig'
|
'checksig'
|
||||||
];
|
];
|
||||||
} else if (options.key) {
|
} else if (options.key) {
|
||||||
@ -650,14 +588,14 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
];
|
];
|
||||||
} else if (options.flags) {
|
} else if (options.flags) {
|
||||||
// Nulldata Transaction
|
// Nulldata Transaction
|
||||||
// ret [data]
|
// return [data]
|
||||||
flags = options.flags;
|
flags = options.flags;
|
||||||
if (typeof flags === 'string')
|
if (typeof flags === 'string')
|
||||||
flags = utils.ascii2array(flags);
|
flags = utils.ascii2array(flags);
|
||||||
assert(utils.isBuffer(flags));
|
assert(utils.isBuffer(flags));
|
||||||
assert(flags.length <= constants.script.maxOpReturn);
|
assert(flags.length <= constants.script.maxOpReturn);
|
||||||
script = [
|
script = [
|
||||||
'ret',
|
'return',
|
||||||
flags
|
flags
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -670,14 +608,14 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
bcoin.script.array(options.lock),
|
bcoin.script.array(options.lock),
|
||||||
'checklocktimeverify',
|
'checklocktimeverify',
|
||||||
'drop',
|
'drop',
|
||||||
'codesep'
|
'codeseparator'
|
||||||
].concat(script);
|
].concat(script);
|
||||||
}
|
}
|
||||||
hash = utils.ripesha(bcoin.script.encode(script));
|
hash = utils.ripesha(bcoin.script.encode(script));
|
||||||
script = [
|
script = [
|
||||||
'hash160',
|
'hash160',
|
||||||
hash,
|
hash,
|
||||||
'eq'
|
'equal'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -261,12 +261,14 @@ Wallet.prototype.getScript = function getScript() {
|
|||||||
'dup',
|
'dup',
|
||||||
'hash160',
|
'hash160',
|
||||||
this.getKeyHash(),
|
this.getKeyHash(),
|
||||||
'eqverify',
|
'equalverify',
|
||||||
'checksig'
|
'checksig'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bcoin.script.encode(bcoin.script.redeem(this.keys, this.m, this.n));
|
return bcoin.script.encode(
|
||||||
|
bcoin.script.createMultisig(this.keys, this.m, this.n)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getScriptHash = function getScriptHash() {
|
Wallet.prototype.getScriptHash = function getScriptHash() {
|
||||||
|
|||||||
@ -47,7 +47,7 @@ describe('Script', function() {
|
|||||||
|
|
||||||
it('should handle if statements correctly', function () {
|
it('should handle if statements correctly', function () {
|
||||||
var inputScript = [1, 2];
|
var inputScript = [1, 2];
|
||||||
var prevOutScript = [2, 'eq', 'if_', 3, 'else_', 4, 'endif', 5];
|
var prevOutScript = [2, 'equal', 'if', 3, 'else', 4, 'endif', 5];
|
||||||
var stack = [];
|
var stack = [];
|
||||||
bcoin.script.execute(inputScript, stack);
|
bcoin.script.execute(inputScript, stack);
|
||||||
var res = bcoin.script.execute(prevOutScript, stack);
|
var res = bcoin.script.execute(prevOutScript, stack);
|
||||||
@ -55,7 +55,7 @@ describe('Script', function() {
|
|||||||
assert.deepEqual(stack.slice(), [[1], [3], [5]]);
|
assert.deepEqual(stack.slice(), [[1], [3], [5]]);
|
||||||
|
|
||||||
var inputScript = [1, 2];
|
var inputScript = [1, 2];
|
||||||
var prevOutScript = [9, 'eq', 'if_', 3, 'else_', 4, 'endif', 5];
|
var prevOutScript = [9, 'equal', 'if', 3, 'else', 4, 'endif', 5];
|
||||||
var stack = [];
|
var stack = [];
|
||||||
bcoin.script.execute(inputScript, stack);
|
bcoin.script.execute(inputScript, stack);
|
||||||
var res = bcoin.script.execute(prevOutScript, stack);
|
var res = bcoin.script.execute(prevOutScript, stack);
|
||||||
@ -63,7 +63,7 @@ describe('Script', function() {
|
|||||||
assert.deepEqual(stack.slice(), [[1], [4], [5]]);
|
assert.deepEqual(stack.slice(), [[1], [4], [5]]);
|
||||||
|
|
||||||
var inputScript = [1, 2];
|
var inputScript = [1, 2];
|
||||||
var prevOutScript = [2, 'eq', 'if_', 3, 'endif', 5];
|
var prevOutScript = [2, 'equal', 'if', 3, 'endif', 5];
|
||||||
var stack = [];
|
var stack = [];
|
||||||
bcoin.script.execute(inputScript, stack);
|
bcoin.script.execute(inputScript, stack);
|
||||||
var res = bcoin.script.execute(prevOutScript, stack);
|
var res = bcoin.script.execute(prevOutScript, stack);
|
||||||
@ -71,7 +71,7 @@ describe('Script', function() {
|
|||||||
assert.deepEqual(stack.slice(), [[1], [3], [5]]);
|
assert.deepEqual(stack.slice(), [[1], [3], [5]]);
|
||||||
|
|
||||||
var inputScript = [1, 2];
|
var inputScript = [1, 2];
|
||||||
var prevOutScript = [9, 'eq', 'if_', 3, 'endif', 5];
|
var prevOutScript = [9, 'equal', 'if', 3, 'endif', 5];
|
||||||
var stack = [];
|
var stack = [];
|
||||||
bcoin.script.execute(inputScript, stack);
|
bcoin.script.execute(inputScript, stack);
|
||||||
var res = bcoin.script.execute(prevOutScript, stack);
|
var res = bcoin.script.execute(prevOutScript, stack);
|
||||||
@ -79,7 +79,7 @@ describe('Script', function() {
|
|||||||
assert.deepEqual(stack.slice(), [[1], [5]]);
|
assert.deepEqual(stack.slice(), [[1], [5]]);
|
||||||
|
|
||||||
var inputScript = [1, 2];
|
var inputScript = [1, 2];
|
||||||
var prevOutScript = [9, 'eq', 'notif', 3, 'endif', 5];
|
var prevOutScript = [9, 'equal', 'notif', 3, 'endif', 5];
|
||||||
var stack = [];
|
var stack = [];
|
||||||
bcoin.script.execute(inputScript, stack);
|
bcoin.script.execute(inputScript, stack);
|
||||||
var res = bcoin.script.execute(prevOutScript, stack);
|
var res = bcoin.script.execute(prevOutScript, stack);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user