better script conformance.
This commit is contained in:
parent
282639b5b1
commit
0ba31eeb59
@ -184,62 +184,43 @@ Input.prototype.__defineGetter__('scriptaddr', function() {
|
|||||||
|
|
||||||
// Schema and defaults for data object:
|
// Schema and defaults for data object:
|
||||||
// {
|
// {
|
||||||
// type: null,
|
// type: String,
|
||||||
// subtype: null,
|
// subtype: String,
|
||||||
// side: 'input',
|
// side: 'input',
|
||||||
// signatures: [],
|
// signatures: Array,
|
||||||
// keys: [],
|
// keys: Array,
|
||||||
// hashes: [],
|
// hashes: Array,
|
||||||
// addresses: [],
|
// addresses: Array,
|
||||||
// redeem: null,
|
// redeem: Array,
|
||||||
// scripthash: null,
|
// scripthash: Array,
|
||||||
// scriptaddress: null,
|
// scriptaddress: String,
|
||||||
// m: 0,
|
// m: Number,
|
||||||
// n: 0,
|
// n: Number,
|
||||||
// height: -1,
|
// height: Number,
|
||||||
// flags: null,
|
// flags: Array,
|
||||||
// text: null,
|
// text: String,
|
||||||
// lock: 0,
|
// lock: Number,
|
||||||
// value: new bn(0),
|
// value: bn,
|
||||||
// script: s,
|
// script: Array,
|
||||||
// seq: input.seq,
|
// seq: Number,
|
||||||
// prev: null,
|
// prev: String,
|
||||||
// index: null,
|
// index: Number,
|
||||||
// _script: null,
|
// none: Boolean
|
||||||
// none: false
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Input.getData = function getData(input) {
|
Input.getData = function getData(input) {
|
||||||
var s, sub, def, signature, key, hash, address, redeem, data, output, val;
|
var def, data, output;
|
||||||
|
|
||||||
if (Array.isArray(input)) {
|
|
||||||
input = {
|
|
||||||
out: {
|
|
||||||
tx: null,
|
|
||||||
hash: utils.toHex(constants.oneHash),
|
|
||||||
index: 0
|
|
||||||
},
|
|
||||||
script: input,
|
|
||||||
seq: 0xffffffff
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!input || !input.script)
|
if (!input || !input.script)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s = input.script;
|
|
||||||
sub = bcoin.script.subscript(input.script);
|
|
||||||
|
|
||||||
def = {
|
def = {
|
||||||
side: 'input',
|
side: 'input',
|
||||||
value: new bn(0),
|
value: new bn(0),
|
||||||
script: s,
|
script: input.script,
|
||||||
seq: input.seq
|
seq: input.seq
|
||||||
};
|
};
|
||||||
|
|
||||||
if (bcoin.script.lockTime(sub))
|
|
||||||
sub = sub.slice(3);
|
|
||||||
|
|
||||||
if (input.out) {
|
if (input.out) {
|
||||||
def.prev = input.out.hash;
|
def.prev = input.out.hash;
|
||||||
def.index = input.out.index;
|
def.index = input.out.index;
|
||||||
@ -247,100 +228,22 @@ Input.getData = function getData(input) {
|
|||||||
|
|
||||||
if (input.out && +input.out.hash === 0) {
|
if (input.out && +input.out.hash === 0) {
|
||||||
data = bcoin.script.coinbase(input.script);
|
data = bcoin.script.coinbase(input.script);
|
||||||
return utils.merge(def, {
|
return utils.merge(def, data, {
|
||||||
type: 'coinbase',
|
type: 'coinbase',
|
||||||
height: data.height != null ? data.height : -1,
|
|
||||||
flags: data.flags,
|
|
||||||
text: data.text,
|
|
||||||
none: true
|
none: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.out && input.out.tx) {
|
if (input.out && input.out.tx) {
|
||||||
output = input.out.tx.outputs[input.out.index];
|
output = input.out.tx.outputs[input.out.index];
|
||||||
data = bcoin.output.getData(output);
|
if (output) {
|
||||||
if (data.type === 'pubkey' ) {
|
data = bcoin.script.getData(input.script, output.script);
|
||||||
data.signatures = [sub[0]];
|
data.value = output.value;
|
||||||
} else if (data.type === 'pubkeyhash') {
|
return utils.merge(def, data);
|
||||||
data.signatures = [sub[0]];
|
|
||||||
data.keys = [sub[1]];
|
|
||||||
} else if (data.type === 'multisig') {
|
|
||||||
data.signatures = sub.slice(1);
|
|
||||||
} else if (data.type === 'scripthash') {
|
|
||||||
// We work backwards here: scripthash is one of the few cases
|
|
||||||
// where we get more data from the input than the output.
|
|
||||||
val = bcoin.input.getData({
|
|
||||||
out: { hash: input.out.hash, index: input.out.index },
|
|
||||||
script: input.script,
|
|
||||||
seq: input.seq
|
|
||||||
});
|
|
||||||
val.lock = data.lock;
|
|
||||||
val.value = data.value;
|
|
||||||
val.script = data.script;
|
|
||||||
data = val;
|
|
||||||
}
|
}
|
||||||
return utils.merge(data, {
|
|
||||||
seq: def.seq,
|
|
||||||
prev: def.prev,
|
|
||||||
index: def.index,
|
|
||||||
_script: def.script
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcoin.script.isPubkeyInput(s)) {
|
return utils.merge(def, bcoin.script.getInputData(input.script));
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'pubkey',
|
|
||||||
signatures: [sub[0]],
|
|
||||||
none: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bcoin.script.isPubkeyhashInput(s)) {
|
|
||||||
key = sub[1];
|
|
||||||
hash = utils.ripesha(key);
|
|
||||||
address = bcoin.wallet.hash2addr(hash);
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'pubkeyhash',
|
|
||||||
signatures: [sub[0]],
|
|
||||||
keys: [key],
|
|
||||||
hashes: [hash],
|
|
||||||
addresses: [address]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bcoin.script.isMultisigInput(s)) {
|
|
||||||
signature = sub.slice(1);
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'multisig',
|
|
||||||
signatures: signature,
|
|
||||||
m: signature.length,
|
|
||||||
none: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bcoin.script.isScripthashInput(s)) {
|
|
||||||
redeem = sub[sub.length - 1];
|
|
||||||
hash = utils.ripesha(redeem);
|
|
||||||
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
|
||||||
redeem = bcoin.script.decode(redeem);
|
|
||||||
val = bcoin.input.getData(sub.slice(0, -1));
|
|
||||||
data = bcoin.output.getData(redeem);
|
|
||||||
return utils.merge(val, data, {
|
|
||||||
type: 'scripthash',
|
|
||||||
subtype: data.type,
|
|
||||||
side: 'input',
|
|
||||||
redeem: redeem,
|
|
||||||
scripthash: hash,
|
|
||||||
scriptaddress: address,
|
|
||||||
script: s,
|
|
||||||
seq: input.seq
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'unknown',
|
|
||||||
none: true
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Input.prototype.inspect = function inspect() {
|
Input.prototype.inspect = function inspect() {
|
||||||
@ -356,6 +259,7 @@ Input.prototype.inspect = function inspect() {
|
|||||||
type: this.type,
|
type: this.type,
|
||||||
subtype: this.data.subtype,
|
subtype: this.data.subtype,
|
||||||
address: this.address,
|
address: this.address,
|
||||||
|
addresses: this.addresses,
|
||||||
signatures: this.signatures.map(utils.toHex),
|
signatures: this.signatures.map(utils.toHex),
|
||||||
keys: this.keys.map(utils.toHex),
|
keys: this.keys.map(utils.toHex),
|
||||||
text: this.text,
|
text: this.text,
|
||||||
|
|||||||
@ -105,10 +105,7 @@ Output.prototype.__defineGetter__('n', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('lock', function() {
|
Output.prototype.__defineGetter__('lock', function() {
|
||||||
var lock = bcoin.script.lockTime(this.script);
|
return bcoin.script.lockTime(this.script);
|
||||||
if (!lock)
|
|
||||||
return 0;
|
|
||||||
return lock.toNumber();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('text', function() {
|
Output.prototype.__defineGetter__('text', function() {
|
||||||
@ -154,123 +151,43 @@ Output.prototype.__defineGetter__('scriptaddr', function() {
|
|||||||
|
|
||||||
// Schema and defaults for data object:
|
// Schema and defaults for data object:
|
||||||
// {
|
// {
|
||||||
// type: null,
|
// type: String,
|
||||||
// subtype: null,
|
// subtype: String,
|
||||||
// side: 'output',
|
// side: 'output',
|
||||||
// signatures: [],
|
// signatures: Array,
|
||||||
// keys: [],
|
// keys: Array,
|
||||||
// hashes: [],
|
// hashes: Array,
|
||||||
// addresses: [],
|
// addresses: Array,
|
||||||
// redeem: null,
|
// redeem: Array,
|
||||||
// scripthash: null,
|
// scripthash: Array,
|
||||||
// scriptaddress: null,
|
// scriptaddress: String,
|
||||||
// m: 0,
|
// m: Number,
|
||||||
// n: 0,
|
// n: Number,
|
||||||
// height: -1,
|
// height: Number,
|
||||||
// flags: null,
|
// flags: Array,
|
||||||
// text: null,
|
// text: String,
|
||||||
// lock: lock ? lock.toNumber() : 0,
|
// lock: Number,
|
||||||
// value: output.value,
|
// value: bn,
|
||||||
// script: s,
|
// script: Array,
|
||||||
// seq: null,
|
// seq: Number,
|
||||||
// prev: null,
|
// prev: String,
|
||||||
// index: null,
|
// index: Number,
|
||||||
// _script: null,
|
// none: Boolean
|
||||||
// none: false
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Output.getData = function getData(output) {
|
Output.getData = function getData(output) {
|
||||||
var s, sub, lock, def, key, hash, address, keys, data;
|
var def;
|
||||||
|
|
||||||
if (Array.isArray(output)) {
|
|
||||||
output = {
|
|
||||||
script: output,
|
|
||||||
value: new bn(0)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!output || !output.script)
|
if (!output || !output.script)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s = output.script;
|
|
||||||
sub = bcoin.script.subscript(output.script);
|
|
||||||
lock = bcoin.script.lockTime(s);
|
|
||||||
|
|
||||||
def = {
|
def = {
|
||||||
side: 'output',
|
side: 'output',
|
||||||
value: output.value,
|
value: output.value,
|
||||||
script: s
|
script: output.script
|
||||||
};
|
};
|
||||||
|
|
||||||
if (lock) {
|
return utils.merge(def, bcoin.script.getOutputData(output.script));
|
||||||
sub = sub.slice(3);
|
|
||||||
def.lock = lock.toNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bcoin.script.isPubkey(s)) {
|
|
||||||
key = sub[0];
|
|
||||||
hash = utils.ripesha(key);
|
|
||||||
address = bcoin.wallet.hash2addr(hash);
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'pubkey',
|
|
||||||
keys: [key],
|
|
||||||
hashes: [hash],
|
|
||||||
addresses: [address]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bcoin.script.isPubkeyhash(s)) {
|
|
||||||
hash = sub[2];
|
|
||||||
address = bcoin.wallet.hash2addr(hash);
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'pubkeyhash',
|
|
||||||
hashes: [hash],
|
|
||||||
addresses: [address]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bcoin.script.isMultisig(s)) {
|
|
||||||
keys = sub.slice(1, -2);
|
|
||||||
hash = keys.map(function(key) {
|
|
||||||
return utils.ripesha(key);
|
|
||||||
});
|
|
||||||
address = hash.map(function(hash) {
|
|
||||||
return bcoin.wallet.hash2addr(hash);
|
|
||||||
});
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'multisig',
|
|
||||||
keys: keys,
|
|
||||||
hashes: hash,
|
|
||||||
addresses: address,
|
|
||||||
m: new bn(sub[0]).toNumber(),
|
|
||||||
n: new bn(sub[sub.length - 2]).toNumber()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bcoin.script.isScripthash(s)) {
|
|
||||||
hash = sub[1];
|
|
||||||
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'scripthash',
|
|
||||||
scripthash: hash,
|
|
||||||
scriptaddress: address
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bcoin.script.isNulldata(s)) {
|
|
||||||
data = bcoin.script.nulldata(s);
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'nulldata',
|
|
||||||
flags: data,
|
|
||||||
text: utils.array2utf8(data),
|
|
||||||
none: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return utils.merge(def, {
|
|
||||||
type: 'unknown',
|
|
||||||
none: true
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Output.prototype.inspect = function inspect() {
|
Output.prototype.inspect = function inspect() {
|
||||||
|
|||||||
@ -168,7 +168,7 @@ script.verify = function verify(input, output, tx, i, flags) {
|
|||||||
res = script.execute(output, stack, tx, i, flags);
|
res = script.execute(output, stack, tx, i, flags);
|
||||||
|
|
||||||
// Verify the script did not fail as well as the stack values
|
// Verify the script did not fail as well as the stack values
|
||||||
if (!res || stack.length === 0 || new bn(stack.pop()).cmpn(0) === 0)
|
if (!res || stack.length === 0 || script.num(stack.pop()).cmpn(0) === 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If the script is P2SH, execute the real output script
|
// If the script is P2SH, execute the real output script
|
||||||
@ -196,7 +196,7 @@ script.verify = function verify(input, output, tx, i, flags) {
|
|||||||
res = script.execute(redeem, stack, tx, i, flags);
|
res = script.execute(redeem, stack, tx, i, flags);
|
||||||
|
|
||||||
// Verify the script did not fail as well as the stack values
|
// Verify the script did not fail as well as the stack values
|
||||||
if (!res || stack.length === 0 || new bn(stack.pop()).cmpn(0) === 0)
|
if (!res || stack.length === 0 || script.num(stack.pop()).cmpn(0) === 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
if (stack.length < 1)
|
if (stack.length < 1)
|
||||||
return false;
|
return false;
|
||||||
v = stack.pop();
|
v = stack.pop();
|
||||||
val = new bn(v).cmpn(0) !== 0;
|
val = script.num(v).cmpn(0) !== 0;
|
||||||
if (o === 'notif')
|
if (o === 'notif')
|
||||||
val = !val;
|
val = !val;
|
||||||
if_ = pc;
|
if_ = pc;
|
||||||
@ -391,7 +391,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
case 'verify': {
|
case 'verify': {
|
||||||
if (stack.length === 0)
|
if (stack.length === 0)
|
||||||
return false;
|
return false;
|
||||||
if (new bn(stack.pop()).cmpn(0) === 0)
|
if (script.num(stack.pop()).cmpn(0) === 0)
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -413,12 +413,12 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
case 'ifdup': {
|
case 'ifdup': {
|
||||||
if (stack.length === 0)
|
if (stack.length === 0)
|
||||||
return false;
|
return false;
|
||||||
if (new bn(stack[stack.length - 1]).cmpn(0) !== 0)
|
if (script.num(stack[stack.length - 1]).cmpn(0) !== 0)
|
||||||
stack.push(new bn(stack[stack.length - 1]).toArray());
|
stack.push(script.numArray(stack[stack.length - 1]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'depth': {
|
case 'depth': {
|
||||||
stack.push(new bn(stack.length).toArray());
|
stack.push(script.numArray(stack.length));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'drop': {
|
case 'drop': {
|
||||||
@ -452,7 +452,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
v = stack.pop();
|
v = stack.pop();
|
||||||
if (v.length > 6)
|
if (v.length > 6)
|
||||||
return false;
|
return false;
|
||||||
n = new bn(v).toNumber();
|
n = script.num(v, true);
|
||||||
if (n < 0 || n >= stack.length)
|
if (n < 0 || n >= stack.length)
|
||||||
return false;
|
return false;
|
||||||
v = stack[-n - 1];
|
v = stack[-n - 1];
|
||||||
@ -551,7 +551,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
case 'size': {
|
case 'size': {
|
||||||
if (stack.length < 1)
|
if (stack.length < 1)
|
||||||
return false;
|
return false;
|
||||||
stack.push(new bn(stack[stack.length - 1].length || 0).toArray());
|
stack.push(script.numArray(stack[stack.length - 1].length || 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'add1':
|
case 'add1':
|
||||||
@ -562,7 +562,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
case 'noteq0': {
|
case 'noteq0': {
|
||||||
if (stack.length < 1)
|
if (stack.length < 1)
|
||||||
return false;
|
return false;
|
||||||
n = new bn(stack.pop());
|
n = script.num(stack.pop());
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case 'add1':
|
case 'add1':
|
||||||
n.iadd(1);
|
n.iadd(1);
|
||||||
@ -587,8 +587,8 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (typeof n === 'boolean')
|
if (typeof n === 'boolean')
|
||||||
n = new bn(+n);
|
n = script.num(+n);
|
||||||
stack.push(n.toArray());
|
stack.push(script.numArray(n));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'add':
|
case 'add':
|
||||||
@ -620,9 +620,9 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
case 'max':
|
case 'max':
|
||||||
if (stack.length < 2)
|
if (stack.length < 2)
|
||||||
return false;
|
return false;
|
||||||
n2 = new bn(stack.pop());
|
n2 = script.num(stack.pop());
|
||||||
n1 = new bn(stack.pop());
|
n1 = script.num(stack.pop());
|
||||||
n = new bn(0);
|
n = script.num(0);
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case 'add':
|
case 'add':
|
||||||
n = n1.add(n2);
|
n = n1.add(n2);
|
||||||
@ -667,21 +667,21 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (typeof n === 'boolean')
|
if (typeof n === 'boolean')
|
||||||
n = new bn(+n);
|
n = script.num(+n);
|
||||||
res = n.cmpn(0) !== 0;
|
res = n.cmpn(0) !== 0;
|
||||||
if (o === 'numeqverify') {
|
if (o === 'numeqverify') {
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
stack.push(n.toArray());
|
stack.push(script.numArray(n));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'within':
|
case 'within':
|
||||||
if (stack.length < 3)
|
if (stack.length < 3)
|
||||||
return false;
|
return false;
|
||||||
n3 = new bn(stack.pop());
|
n3 = script.num(stack.pop());
|
||||||
n2 = new bn(stack.pop());
|
n2 = script.num(stack.pop());
|
||||||
n1 = new bn(stack.pop());
|
n1 = script.num(stack.pop());
|
||||||
val = n2.cmp(n1) <= 0 && n1.cmp(n3) < 0;
|
val = n2.cmp(n1) <= 0 && n1.cmp(n3) < 0;
|
||||||
stack.push(val.cmpn(0) !== 0 ? [ 1 ] : []);
|
stack.push(val.cmpn(0) !== 0 ? [ 1 ] : []);
|
||||||
break;
|
break;
|
||||||
@ -778,16 +778,11 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
if (!tx || stack.length < 3)
|
if (!tx || stack.length < 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
n = stack.pop();
|
n = script.num(stack.pop(), true);
|
||||||
|
|
||||||
if (!Array.isArray(n))
|
if (!(n >= 1 && n <= 15))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (n.length !== 1 || !(n[0] >= 1 && n[0] <= 15))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n = n[0];
|
|
||||||
|
|
||||||
if (stack.length < n + 1)
|
if (stack.length < n + 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -800,16 +795,11 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
keys.push(key);
|
keys.push(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
m = stack.pop();
|
m = script.num(stack.pop(), true);
|
||||||
|
|
||||||
if (!Array.isArray(m))
|
if (!(m >= 1 && m <= n))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m.length !== 1 || !(m[0] >= 1 && m[0] <= n))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m = m[0];
|
|
||||||
|
|
||||||
if (stack.length < m + 1)
|
if (stack.length < m + 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -878,7 +868,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
if (lock.length > 6)
|
if (lock.length > 6)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
lock = new bn(lock).toNumber();
|
lock = script.num(lock, true);
|
||||||
|
|
||||||
if (lock < 0)
|
if (lock < 0)
|
||||||
return false;
|
return false;
|
||||||
@ -948,7 +938,40 @@ script.num = function num(value, useNum) {
|
|||||||
|
|
||||||
assert(utils.isBuffer(value));
|
assert(utils.isBuffer(value));
|
||||||
|
|
||||||
value = new bn(value, 'le');
|
if (script.requireminimal && value.length > 0) {
|
||||||
|
// If the low bits on the last byte are unset,
|
||||||
|
// fail if The value's second to last byte does
|
||||||
|
// not have the high bit set. A number can't
|
||||||
|
// justify having the last byte's low bits unset
|
||||||
|
// unless they ran out of space for the sign bit
|
||||||
|
// in the second to last bit. This also takes
|
||||||
|
// care of negative We also fail on [0] to avoid
|
||||||
|
// negative zero (also avoids positive zero).
|
||||||
|
if (!(value[value.length - 1] & 0x7f)) {
|
||||||
|
if (value.length === 1 || !(value[value.length - 2] & 0x80)) {
|
||||||
|
// We should technically fail here by
|
||||||
|
// throwing and catching, but return zero for now.
|
||||||
|
return useNum ? 0 : new bn(0, 'le');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize by avoiding big numbers
|
||||||
|
if (useNum && value.length <= 1)
|
||||||
|
return value.length === 0 ? 0 : value[0];
|
||||||
|
|
||||||
|
// If we are signed, do (~num + 1) to get
|
||||||
|
// the positive counterpart and set bn's
|
||||||
|
// negative flag.
|
||||||
|
if (value[value.length - 1] & 0x80) {
|
||||||
|
if (utils.isNegZero(value, 'le')) {
|
||||||
|
value = new bn(0, 'le');
|
||||||
|
} else {
|
||||||
|
value = new bn(value, 'le').notn(64).addn(1).neg();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = new bn(value, 'le');
|
||||||
|
}
|
||||||
|
|
||||||
if (useNum) {
|
if (useNum) {
|
||||||
try {
|
try {
|
||||||
@ -961,6 +984,55 @@ script.num = function num(value, useNum) {
|
|||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script.numArray = function(value) {
|
||||||
|
if (Array.isArray(value))
|
||||||
|
return value.slice();
|
||||||
|
|
||||||
|
if (utils.isFinite(value))
|
||||||
|
value = new bn(value, 'le');
|
||||||
|
|
||||||
|
assert(value instanceof bn);
|
||||||
|
|
||||||
|
// Convert the number to the
|
||||||
|
// negative byte representation.
|
||||||
|
if (value.isNeg()) {
|
||||||
|
if (value.cmpn(0) === 0)
|
||||||
|
value = new bn(0);
|
||||||
|
else
|
||||||
|
value = value.neg().notn(64).addn(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.cmpn(0) === 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
return value.toArray('le');
|
||||||
|
};
|
||||||
|
|
||||||
|
script.checkPush = function checkPush(op, value) {
|
||||||
|
if (!script.requireminimal)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (value.length === 1 && value[0] === 0)
|
||||||
|
return op === constants.opcodes['0'];
|
||||||
|
|
||||||
|
if (value.length === 1 && value[0] >= 1 && value[0] <= 16)
|
||||||
|
return op >= constants.opcodes['1'] && op <= constants.opcodes['16'];
|
||||||
|
|
||||||
|
if (value.length === 1 && value[0] === -1)
|
||||||
|
return op === constants.opcodes['-1'];
|
||||||
|
|
||||||
|
if (value.length <= 75)
|
||||||
|
return op === value.length;
|
||||||
|
|
||||||
|
if (value.length <= 255)
|
||||||
|
return op === constants.opcodes.pushdata1;
|
||||||
|
|
||||||
|
if (value.length <= 65535)
|
||||||
|
return op === constants.opcodes.pushdata2;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
script.redeem = function redeem(keys, m, n) {
|
script.redeem = function redeem(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 redeem script');
|
||||||
@ -989,17 +1061,18 @@ script.standard = function standard(s) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
script.isStandard = function isStandard(s) {
|
script.isStandard = function isStandard(s) {
|
||||||
var type = script.standard(s);
|
|
||||||
var m, n;
|
var m, n;
|
||||||
|
|
||||||
if (type === 'multisig') {
|
if (script.isMultisig(s)) {
|
||||||
m = new bn(s[0]).toNumber();
|
m = s[0];
|
||||||
n = new bn(s[s.length - 2]).toNumber();
|
n = s[s.length - 2];
|
||||||
|
|
||||||
if (n < 1 || n > 3)
|
if (n < 1 || n > 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m < 1 || m > n)
|
if (m < 1 || m > n)
|
||||||
return false;
|
return false;
|
||||||
} else if (type === 'nulldata') {
|
} else if (script.isNulldata(s)) {
|
||||||
if (script.size(s) > constants.script.maxOpReturnBytes)
|
if (script.size(s) > constants.script.maxOpReturnBytes)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1010,53 +1083,183 @@ script.isStandard = function isStandard(s) {
|
|||||||
script.size = function size(s) {
|
script.size = function size(s) {
|
||||||
if (s._raw)
|
if (s._raw)
|
||||||
return s._raw.length;
|
return s._raw.length;
|
||||||
return bcoin.script.encode(s).length;
|
return script.encode(s).length;
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isEncoded = function isEncoded(s) {
|
script.isEncoded = function isEncoded(s) {
|
||||||
return utils.isBytes(s);
|
return utils.isBytes(s);
|
||||||
};
|
};
|
||||||
|
|
||||||
script.normalize = function normalize(s) {
|
script.isLockTime = function isLockTime(s, check) {
|
||||||
if (script.isEncoded(s))
|
return s.length > 4
|
||||||
s = script.decode(s);
|
&& Array.isArray(s[0])
|
||||||
|
&& s[1] === 'checklocktimeverify'
|
||||||
s = script.subscript(s);
|
&& s[2] === 'drop'
|
||||||
|
&& s[3] === 'codesep';
|
||||||
if (script.lockTime(s))
|
|
||||||
s = s.slice(3);
|
|
||||||
|
|
||||||
return s;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
script.lockTime = function lockTime(s) {
|
script.lockTime = function lockTime(s) {
|
||||||
var lock = s[0];
|
if (!script.isLockTime(s))
|
||||||
var res = s.length > 3
|
|
||||||
&& Array.isArray(s[0])
|
|
||||||
&& s[1] === 'checklocktimeverify'
|
|
||||||
&& s[2] === 'drop';
|
|
||||||
|
|
||||||
if (!res)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Number can only store 6 & 5/8 bytes
|
return script.num(s[0], true);
|
||||||
if (lock.length > 6)
|
|
||||||
lock = lock.slice(0, 6);
|
|
||||||
|
|
||||||
return new bn(lock);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
script.spendable = function spendable(s, lockTime) {
|
script.spendable = function spendable(s, lockTime) {
|
||||||
if (!script.standard(s))
|
if (script.lockTime(s) > lockTime)
|
||||||
return false;
|
|
||||||
|
|
||||||
var lock = script.lockTime(s);
|
|
||||||
if (lock && lock.toNumber() > lockTime)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script.getData = function getData(s, prev) {
|
||||||
|
var output;
|
||||||
|
|
||||||
|
if (prev && !script.isScripthash(prev)) {
|
||||||
|
output = script.getOutputData(prev);
|
||||||
|
output.side = 'input';
|
||||||
|
|
||||||
|
if (output.type === 'pubkey') {
|
||||||
|
output.signatures = [s[0]];
|
||||||
|
} else if (output.type === 'pubkeyhash') {
|
||||||
|
output.signatures = [s[0]];
|
||||||
|
output.keys = [s[1]];
|
||||||
|
} else if (output.type === 'multisig') {
|
||||||
|
output.signatures = s.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
return script.getInputData(s);
|
||||||
|
};
|
||||||
|
|
||||||
|
script.getInputData = function getInputData(s) {
|
||||||
|
var sig, key, hash, raw, redeem, lock, hash, address, input, output;
|
||||||
|
|
||||||
|
if (script.isPubkeyInput(s)) {
|
||||||
|
key = s[0];
|
||||||
|
return {
|
||||||
|
type: 'pubkey',
|
||||||
|
side: 'input',
|
||||||
|
signatures: [sig],
|
||||||
|
none: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.isPubkeyhashInput(s)) {
|
||||||
|
sig = s[0];
|
||||||
|
key = s[1];
|
||||||
|
hash = bcoin.wallet.key2hash(key);
|
||||||
|
address = bcoin.wallet.hash2addr(hash, 'pubkeyhash');
|
||||||
|
return {
|
||||||
|
type: 'pubkeyhash',
|
||||||
|
side: 'input',
|
||||||
|
signatures: [sig],
|
||||||
|
keys: [key],
|
||||||
|
hashes: [hash],
|
||||||
|
addresses: [address]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.isMultisigInput(s)) {
|
||||||
|
sig = s.slice(1);
|
||||||
|
return {
|
||||||
|
type: 'multisig',
|
||||||
|
side: 'input',
|
||||||
|
signatures: sig,
|
||||||
|
m: sig.length,
|
||||||
|
none: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.isScripthashInput(s)) {
|
||||||
|
raw = s[s.length - 1];
|
||||||
|
redeem = script.decode(raw);
|
||||||
|
lock = script.lockTime(redeem);
|
||||||
|
hash = bcoin.wallet.key2hash(raw);
|
||||||
|
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
||||||
|
input = script.getInputData(s.slice(0, -1));
|
||||||
|
delete input.none;
|
||||||
|
output = script.getOutputData(script.subscript(redeem));
|
||||||
|
return utils.merge(input, output, {
|
||||||
|
type: 'scripthash',
|
||||||
|
side: 'input',
|
||||||
|
subtype: output.type,
|
||||||
|
redeem: redeem,
|
||||||
|
scripthash: hash,
|
||||||
|
scriptaddress: address,
|
||||||
|
lock: lock
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'unknown',
|
||||||
|
none: true
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
script.getOutputData = function getOutputData(s) {
|
||||||
|
var key, hash, address;
|
||||||
|
|
||||||
|
if (script.isPubkey(s)) {
|
||||||
|
key = s[0];
|
||||||
|
hash = bcoin.wallet.key2hash(key);
|
||||||
|
address = bcoin.wallet.hash2addr(hash, 'pubkey');
|
||||||
|
return {
|
||||||
|
type: 'pubkey',
|
||||||
|
side: 'output',
|
||||||
|
keys: [key],
|
||||||
|
hashes: [hash],
|
||||||
|
addresses: [address]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.isPubkeyhash(s)) {
|
||||||
|
hash = s[2];
|
||||||
|
return {
|
||||||
|
type: 'pubkeyhash',
|
||||||
|
side: 'output',
|
||||||
|
hashes: [hash],
|
||||||
|
addresses: [bcoin.wallet.hash2addr(hash, 'pubkeyhash')]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.isMultisig(s)) {
|
||||||
|
key = s.slice(1, -2);
|
||||||
|
hash = key.map(function(key) {
|
||||||
|
return bcoin.wallet.key2hash(key);
|
||||||
|
});
|
||||||
|
address = hash.map(function(hash) {
|
||||||
|
return bcoin.wallet.hash2addr(hash, 'multisig');
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
type: 'multisig',
|
||||||
|
side: 'output',
|
||||||
|
keys: key,
|
||||||
|
hashes: hash,
|
||||||
|
addresses: address,
|
||||||
|
m: s[0],
|
||||||
|
n: s[s.length - 2]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.isScripthash(s)) {
|
||||||
|
hash = s[1];
|
||||||
|
return {
|
||||||
|
type: 'scripthash',
|
||||||
|
side: 'output',
|
||||||
|
scripthash: hash,
|
||||||
|
scriptaddress: bcoin.wallet.hash2addr(hash, 'scripthash')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'unknown',
|
||||||
|
none: true
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
script.isPubkey = function isPubkey(s, key) {
|
script.isPubkey = function isPubkey(s, key) {
|
||||||
var res;
|
var res;
|
||||||
|
|
||||||
@ -1068,10 +1271,12 @@ script.isPubkey = function isPubkey(s, key) {
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (key)
|
if (key) {
|
||||||
return utils.isEqual(s[0], key);
|
if (!utils.isEqual(s[0], key))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return s[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isPubkeyhash = function isPubkeyhash(s, hash) {
|
script.isPubkeyhash = function isPubkeyhash(s, hash) {
|
||||||
@ -1089,10 +1294,12 @@ script.isPubkeyhash = function isPubkeyhash(s, hash) {
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (hash)
|
if (hash) {
|
||||||
return utils.isEqual(s[2], hash);
|
if (!utils.isEqual(s[2], hash))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return s[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isMultisig = function isMultisig(s, keys) {
|
script.isMultisig = function isMultisig(s, keys) {
|
||||||
@ -1107,6 +1314,15 @@ script.isMultisig = function isMultisig(s, keys) {
|
|||||||
|
|
||||||
n = s[s.length - 2];
|
n = s[s.length - 2];
|
||||||
|
|
||||||
|
if (Array.isArray(n)) {
|
||||||
|
if (n.length !== 0)
|
||||||
|
return false;
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof n !== 'number')
|
||||||
|
return false;
|
||||||
|
|
||||||
// Bitcoind technically doesn't check for the
|
// Bitcoind technically doesn't check for the
|
||||||
// 15 limit here. It just counts the sigops
|
// 15 limit here. It just counts the sigops
|
||||||
// later.
|
// later.
|
||||||
@ -1115,6 +1331,15 @@ script.isMultisig = function isMultisig(s, keys) {
|
|||||||
|
|
||||||
m = s[0];
|
m = s[0];
|
||||||
|
|
||||||
|
if (Array.isArray(m)) {
|
||||||
|
if (m.length !== 0)
|
||||||
|
return false;
|
||||||
|
m = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof m !== 'number')
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!(m >= 1 && m <= n))
|
if (!(m >= 1 && m <= n))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1126,21 +1351,27 @@ script.isMultisig = function isMultisig(s, keys) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keys)
|
if (keys) {
|
||||||
return true;
|
keys = utils.sortKeys(keys);
|
||||||
|
|
||||||
keys = utils.sortKeys(keys);
|
for (i = 1; i < n + 1; i++) {
|
||||||
|
for (j = 0; j < keys.length; j++) {
|
||||||
for (i = 1; i < n + 1; i++) {
|
if (utils.isEqual(s[i], keys[j])) {
|
||||||
for (j = 0; j < keys.length; j++) {
|
total++;
|
||||||
if (utils.isEqual(s[i], keys[j])) {
|
break;
|
||||||
total++;
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (total !== n)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return total === n;
|
return {
|
||||||
|
keys: s.slice(1, n + 1),
|
||||||
|
m: m,
|
||||||
|
n: n
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isScripthash = function isScripthash(s, hash) {
|
script.isScripthash = function isScripthash(s, hash) {
|
||||||
@ -1156,23 +1387,25 @@ script.isScripthash = function isScripthash(s, hash) {
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (hash)
|
if (hash) {
|
||||||
return utils.isEqual(s[1], hash);
|
if (!utils.isEqual(s[1], hash))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return s[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isNulldata = function isNulldata(s) {
|
script.isNulldata = function isNulldata(s) {
|
||||||
|
var res;
|
||||||
|
|
||||||
if (s.length !== 2)
|
if (s.length !== 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return s[0] === 'ret'
|
res = s[0] === 'ret'
|
||||||
&& Array.isArray(s[1])
|
&& Array.isArray(s[1])
|
||||||
&& s[1].length <= constants.script.maxOpReturn;
|
&& s[1].length <= constants.script.maxOpReturn;
|
||||||
};
|
|
||||||
|
|
||||||
script.nulldata = function nulldata(s) {
|
if (!res)
|
||||||
if (!script.isNulldata(s))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return s[1];
|
return s[1];
|
||||||
@ -1187,7 +1420,7 @@ script.standardInput = function standardInput(s) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
|
script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
|
||||||
if (s.length !== 1 || !Array.isArray(s[0]))
|
if (s.length !== 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!script.isSignature(s[0]))
|
if (!script.isSignature(s[0]))
|
||||||
@ -1199,14 +1432,15 @@ script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
|
|||||||
if (key) {
|
if (key) {
|
||||||
assert(tx);
|
assert(tx);
|
||||||
assert(i != null);
|
assert(i != null);
|
||||||
return script.verify(s, [key, 'checksig'], tx, i);
|
if (!script.verify(s, [key, 'checksig'], tx, i))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return s[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
||||||
if (s.length !== 2 || !Array.isArray(s[0]) || !Array.isArray(s[1]))
|
if (s.length !== 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!script.isSignature(s[0]))
|
if (!script.isSignature(s[0]))
|
||||||
@ -1215,10 +1449,12 @@ script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
|||||||
if (!script.isKey(s[1]))
|
if (!script.isKey(s[1]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (key)
|
if (key) {
|
||||||
return utils.isEqual(s[1], key);
|
if (!utils.isEqual(s[1], key))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return s[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
||||||
@ -1248,7 +1484,8 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
|||||||
assert(tx);
|
assert(tx);
|
||||||
assert(i != null);
|
assert(i != null);
|
||||||
o = script.redeem(keys, s.length - 1, keys.length);
|
o = script.redeem(keys, s.length - 1, keys.length);
|
||||||
return script.verify(s, o, tx, i);
|
if (!script.verify(s, o, tx, i))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We also also try to recover the keys from the signatures.
|
// We also also try to recover the keys from the signatures.
|
||||||
@ -1261,7 +1498,10 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
|||||||
// recovered.push(key);
|
// recovered.push(key);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return true;
|
return {
|
||||||
|
signatures: s.slice(1),
|
||||||
|
m: s.length - 1
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isScripthashInput = function isScripthashInput(s, data) {
|
script.isScripthashInput = function isScripthashInput(s, data) {
|
||||||
@ -1297,12 +1537,16 @@ script.isScripthashInput = function isScripthashInput(s, data) {
|
|||||||
// Check data against last array in case
|
// Check data against last array in case
|
||||||
// a raw redeem script was passed in.
|
// a raw redeem script was passed in.
|
||||||
if (data && utils.isEqual(data, raw))
|
if (data && utils.isEqual(data, raw))
|
||||||
return true;
|
return raw;
|
||||||
|
|
||||||
// Test against all other script types
|
// Test against all other script types
|
||||||
return script.isPubkey(redeem, data)
|
if (!script.isPubkey(redeem, data)
|
||||||
|| script.isPubkeyhash(redeem, data)
|
&& !script.isPubkeyhash(redeem, data)
|
||||||
|| script.isMultisig(redeem, data);
|
&& !script.isMultisig(redeem, data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
script.coinbaseBits = function coinbaseBits(s, block) {
|
script.coinbaseBits = function coinbaseBits(s, block) {
|
||||||
@ -1319,7 +1563,7 @@ script.coinbaseBits = function coinbaseBits(s, block) {
|
|||||||
if (s[0].length > 6)
|
if (s[0].length > 6)
|
||||||
return { type: 'value', value: s[0] };
|
return { type: 'value', value: s[0] };
|
||||||
|
|
||||||
value = new bn(s[0].slice().reverse()).toNumber();
|
value = script.num(s[0], true);
|
||||||
|
|
||||||
// Test for bits and ts
|
// Test for bits and ts
|
||||||
if (block && block.version < 2) {
|
if (block && block.version < 2) {
|
||||||
@ -1366,7 +1610,7 @@ script.coinbase = function coinbase(s, block) {
|
|||||||
data = script.coinbaseBits(s, block);
|
data = script.coinbaseBits(s, block);
|
||||||
|
|
||||||
if (Array.isArray(s[1]))
|
if (Array.isArray(s[1]))
|
||||||
extraNonce = new bn(s[1]);
|
extraNonce = script.num(s[1]);
|
||||||
|
|
||||||
flags = s.slice(2);
|
flags = s.slice(2);
|
||||||
|
|
||||||
@ -1377,6 +1621,9 @@ script.coinbase = function coinbase(s, block) {
|
|||||||
flags.map(utils.array2utf8).join('')
|
flags.map(utils.array2utf8).join('')
|
||||||
.replace(/[\u0000-\u0019\u007f-\u00ff]/g, '');
|
.replace(/[\u0000-\u0019\u007f-\u00ff]/g, '');
|
||||||
|
|
||||||
|
if (coinbase.height == null)
|
||||||
|
coinbase.height = -1;
|
||||||
|
|
||||||
return coinbase;
|
return coinbase;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1684,7 +1931,7 @@ script.args = function args(s) {
|
|||||||
keys = s.slice(1, -2);
|
keys = s.slice(1, -2);
|
||||||
if (!pub)
|
if (!pub)
|
||||||
return -1;
|
return -1;
|
||||||
m = new bn(s[0]).toNumber();
|
m = s[0];
|
||||||
if (keys.length < 1 || m < 1)
|
if (keys.length < 1 || m < 1)
|
||||||
return -1;
|
return -1;
|
||||||
return m + 1;
|
return m + 1;
|
||||||
|
|||||||
@ -197,8 +197,6 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
|
|||||||
|
|
||||||
// Grab `n` value (number of keys).
|
// Grab `n` value (number of keys).
|
||||||
n = s[s.length - 2];
|
n = s[s.length - 2];
|
||||||
if (Array.isArray(n))
|
|
||||||
n = n[0];
|
|
||||||
|
|
||||||
// Fill script with `n` signature slots.
|
// Fill script with `n` signature slots.
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
@ -315,13 +313,9 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
|
|
||||||
// Grab `m` value (number of sigs required).
|
// Grab `m` value (number of sigs required).
|
||||||
m = s[0];
|
m = s[0];
|
||||||
if (Array.isArray(m))
|
|
||||||
m = m[0];
|
|
||||||
|
|
||||||
// Grab `n` value (number of keys).
|
// Grab `n` value (number of keys).
|
||||||
n = s[s.length - 2];
|
n = s[s.length - 2];
|
||||||
if (Array.isArray(n))
|
|
||||||
n = n[0];
|
|
||||||
|
|
||||||
// Something is very wrong here. Abort.
|
// Something is very wrong here. Abort.
|
||||||
if (len - 1 > n)
|
if (len - 1 > n)
|
||||||
@ -565,9 +559,10 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
if (options.scripthash) {
|
if (options.scripthash) {
|
||||||
if (options.lock != null) {
|
if (options.lock != null) {
|
||||||
script = [
|
script = [
|
||||||
new bn(options.lock).toArray(),
|
bcoin.script.numArray(options.lock),
|
||||||
'checklocktimeverify',
|
'checklocktimeverify',
|
||||||
'drop'
|
'drop',
|
||||||
|
'codesep'
|
||||||
].concat(script);
|
].concat(script);
|
||||||
}
|
}
|
||||||
hash = utils.ripesha(bcoin.script.encode(script));
|
hash = utils.ripesha(bcoin.script.encode(script));
|
||||||
@ -757,8 +752,6 @@ TX.prototype.maxSize = function maxSize() {
|
|||||||
// Bare Multisig
|
// Bare Multisig
|
||||||
// Get the previous m value:
|
// Get the previous m value:
|
||||||
m = s[0];
|
m = s[0];
|
||||||
if (Array.isArray(m))
|
|
||||||
m = m[0];
|
|
||||||
// OP_0
|
// OP_0
|
||||||
size += 1;
|
size += 1;
|
||||||
// OP_PUSHDATA0 [signature] ...
|
// OP_PUSHDATA0 [signature] ...
|
||||||
|
|||||||
@ -704,7 +704,7 @@ utils.isBytes = function isBytes(data) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = 0; i < data.length; i++) {
|
for (i = 0; i < data.length; i++) {
|
||||||
if (typeof data[i] !== 'number')
|
if (typeof data[i] !== 'number' || data[i] < 0x00 || data[i] > 0xff)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user