improve locktime checks and coinbase parsing.
This commit is contained in:
parent
4ac398e41b
commit
b3f457ee31
@ -62,7 +62,7 @@ function Block(data, subtype) {
|
||||
if (this.version >= 2) {
|
||||
tx = this.txs[0];
|
||||
if (tx && tx.inputs[0] && +tx.inputs[0].out.hash === 0) {
|
||||
height = bcoin.script.coinbaseHeight(tx.inputs[0].script);
|
||||
height = bcoin.script.coinbaseHeight(tx.inputs[0].script, this);
|
||||
if (height > 0)
|
||||
this._height = height;
|
||||
}
|
||||
|
||||
@ -384,7 +384,10 @@ script.execute = function execute(s, stack, tx, index, recurse) {
|
||||
case 'roll': {
|
||||
if (stack.length < 2)
|
||||
return false;
|
||||
n = new bn(stack.pop()).toNumber();
|
||||
v = stack.pop();
|
||||
if (v.length > 6)
|
||||
return false;
|
||||
n = new bn(v).toNumber();
|
||||
if (n < 0 || n >= stack.length)
|
||||
return false;
|
||||
v = stack[-n - 1];
|
||||
@ -772,7 +775,15 @@ script.execute = function execute(s, stack, tx, index, recurse) {
|
||||
if (!tx || stack.length === 0)
|
||||
return false;
|
||||
|
||||
lock = new bn(stack[stack.length - 1]).toNumber();
|
||||
lock = stack[stack.length - 1];
|
||||
|
||||
if (!Array.isArray(lock))
|
||||
return false;
|
||||
|
||||
if (lock.length > 6)
|
||||
return false;
|
||||
|
||||
lock = new bn(lock).toNumber();
|
||||
|
||||
if (lock < 0)
|
||||
return false;
|
||||
@ -878,11 +889,20 @@ script.standard = function standard(s) {
|
||||
};
|
||||
|
||||
script.lockTime = function lockTime(s) {
|
||||
return s.length > 3
|
||||
var lock = s[0];
|
||||
var res = s.length > 3
|
||||
&& Array.isArray(s[0])
|
||||
&& s[1] === 'checklocktimeverify'
|
||||
&& s[2] === 'drop'
|
||||
&& new bn(s[0]);
|
||||
&& s[2] === 'drop';
|
||||
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
// Number can only store 6 & 5/8 bytes
|
||||
if (lock.length > 6)
|
||||
lock = [0x1f].concat(lock.slice(0, 6));
|
||||
|
||||
return new bn(lock);
|
||||
};
|
||||
|
||||
script.spendable = function spendable(s, lockTime) {
|
||||
@ -1138,38 +1158,84 @@ script.isScripthashInput = function isScripthashInput(s, redeem) {
|
||||
return keys;
|
||||
};
|
||||
|
||||
script.coinbaseHeight = function coinbaseHeight(s) {
|
||||
var raw = s._raw || script.encode(s);
|
||||
var height;
|
||||
script.coinbaseBits = function coinbaseBits(s, block) {
|
||||
var value;
|
||||
|
||||
if (!Array.isArray(s[0]))
|
||||
return -1;
|
||||
return { type: 'value', value: s[0] };
|
||||
|
||||
if (raw[0] < 0x03 || s[0].length < 3)
|
||||
return -1;
|
||||
// Number can only store up to 53 bits (6 & 5/8 bytes)
|
||||
if (s[0].length > 6)
|
||||
return { type: 'value', value: s[0] };
|
||||
|
||||
height = new bn(s[0].reverse()).toNumber();
|
||||
value = new bn(s[0].reverse()).toNumber();
|
||||
|
||||
if (block) {
|
||||
if (value === block.bits)
|
||||
return { type: 'bits', value: value };
|
||||
|
||||
if (value === block.ts)
|
||||
return { type: 'ts', value: value };
|
||||
|
||||
if (block.version < 2)
|
||||
return { type: 'value', value: value };
|
||||
}
|
||||
|
||||
// Last v1 block
|
||||
if (height < 227835)
|
||||
return -1;
|
||||
if (s[0].length < 3 || value < 227835)
|
||||
return { type: 'value', value: value };
|
||||
|
||||
return height;
|
||||
return { type: 'height', value: value };
|
||||
};
|
||||
|
||||
script.coinbase = function coinbase(s) {
|
||||
var raw = s._raw || script.encode(s);
|
||||
var data = script.coinbaseHeight(s);
|
||||
script.coinbaseHeight = function coinbaseHeight(s, block) {
|
||||
var data = script.coinbaseBits(s, block);
|
||||
if (data.type !== 'height')
|
||||
return -1;
|
||||
return data.value;
|
||||
};
|
||||
|
||||
if (height > 0)
|
||||
raw = raw.slice(raw[0] + 1);
|
||||
script.coinbase = function coinbase(s, block) {
|
||||
var coinbase, data, nonce, flags;
|
||||
|
||||
return {
|
||||
height: height,
|
||||
coinbase = {
|
||||
script: s,
|
||||
data: raw,
|
||||
text: utils.array2utf8(raw)
|
||||
raw: s._raw || script.encode(s)
|
||||
};
|
||||
|
||||
data = script.coinbaseBits(s, block);
|
||||
|
||||
if (Array.isArray(s[1]))
|
||||
nonce = new bn(s[1]);
|
||||
|
||||
flags = s.slice(2);
|
||||
|
||||
coinbase[data.type] = data.value;
|
||||
coinbase.nonce = nonce;
|
||||
coinbase.flags = flags;
|
||||
coinbase.text = utils.array2utf8(flags);
|
||||
|
||||
return coinbase;
|
||||
};
|
||||
|
||||
script.isCoinbase = function isCoinbase(s, block) {
|
||||
var coinbase = script.coinbase(s, block);
|
||||
|
||||
if (coinbase.raw.length > 100 || s.length < 2)
|
||||
return false;
|
||||
|
||||
if (coinbase.value != null)
|
||||
return false;
|
||||
|
||||
if (coinbase.nonce == null)
|
||||
return false;
|
||||
|
||||
if (block) {
|
||||
if (coinbase.bits != null && coinbase.flags.length)
|
||||
return false;
|
||||
}
|
||||
|
||||
return coinbase;
|
||||
};
|
||||
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
|
||||
|
||||
Loading…
Reference in New Issue
Block a user