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