test. fix sigops counting.
This commit is contained in:
parent
11ef30b942
commit
c1fd8bb285
@ -2103,20 +2103,20 @@ Script.checkMinimal = function checkMinimal(value, flags) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Test a buffer to see if it is valid script code (no non-existent opcodes).
|
* Test a buffer to see if it is valid script code (no non-existent opcodes).
|
||||||
* @param {Buffer} buf
|
* @param {Buffer} raw
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.isCode = function isCode(buf) {
|
Script.isCode = function isCode(raw) {
|
||||||
var i, op, code;
|
var i, op, code;
|
||||||
|
|
||||||
if (!buf)
|
if (!raw)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!Buffer.isBuffer(buf))
|
if (!Buffer.isBuffer(raw))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
code = Script.decode(buf);
|
code = Script.decode(raw);
|
||||||
|
|
||||||
for (i = 0; i < code.length; i++) {
|
for (i = 0; i < code.length; i++) {
|
||||||
op = code[i];
|
op = code[i];
|
||||||
@ -3475,7 +3475,7 @@ Script.prototype.getSigops = function getSigops(accurate) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (Script.isBadPush(op))
|
if (Script.isBadPush(op))
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
if (op === opcodes.OP_CHECKSIG || op === opcodes.OP_CHECKSIGVERIFY) {
|
if (op === opcodes.OP_CHECKSIG || op === opcodes.OP_CHECKSIGVERIFY) {
|
||||||
total++;
|
total++;
|
||||||
@ -4019,34 +4019,45 @@ Script.fromRaw = function fromRaw(data, enc) {
|
|||||||
* Decode a serialized script into script code.
|
* Decode a serialized script into script code.
|
||||||
* Note that the serialized script must _not_
|
* Note that the serialized script must _not_
|
||||||
* include the varint size before it. Note that
|
* include the varint size before it. Note that
|
||||||
* this will apply hidden `pushdata` properties
|
* this will apply hidden `opcode` properties
|
||||||
* to each Buffer if the buffer was created from
|
* to each Buffer if the buffer was created from
|
||||||
* a non-standard pushdata.
|
* a non-minimal pushdata.
|
||||||
*
|
*
|
||||||
* This function does not do bounds checking
|
* BCoin parses scripts "differently" because it
|
||||||
* on buffers because some jackass could do a
|
* parses them _before they're executed_. This
|
||||||
* direct push of 30 bytes with only 20 bytes
|
* lends itself to some interesting edge cases.
|
||||||
* after it. That script would be perfectly
|
|
||||||
* fine _until_ it is executed. There are
|
|
||||||
* output scripts on the blockchain that can
|
|
||||||
* never be redeemed due to this, but they are
|
|
||||||
* in valid blocks, therefore we cannot fail
|
|
||||||
* parsing them.
|
|
||||||
*
|
*
|
||||||
|
* If bitcoind comes across a bad push, it
|
||||||
|
* will return an invalid opcode. The problem
|
||||||
|
* is bitcoind parses scripts _as_ they are
|
||||||
|
* executing, which can be slow for us because
|
||||||
|
* now every function that needs to test the
|
||||||
|
* script needs to parse the raw data. It's
|
||||||
|
* also impossible to read a script
|
||||||
|
* _backwards_ making testing for things like
|
||||||
|
* multisig outputs even more difficult.
|
||||||
|
*
|
||||||
|
* If this function comes accross a bad push
|
||||||
|
* in its parsing, it simply will _not
|
||||||
|
* consider the pushdata to be a pushdata_
|
||||||
|
* but just another opcode in the code array
|
||||||
|
* (all of the data after the pushdata op
|
||||||
|
* will also be considered opcodes rather
|
||||||
|
* than data).
|
||||||
|
|
||||||
* Also note that this function uses reference
|
* Also note that this function uses reference
|
||||||
* Buffer slices. Larger buffer slices should
|
* Buffer slices. Larger buffer slices should
|
||||||
* _never_ be passed in here.
|
* _never_ be passed in here.
|
||||||
* @param {Buffer} buf - Serialized script.
|
* @param {Buffer} raw - Serialized script.
|
||||||
* @returns {Array} Script code.
|
* @returns {Array} Script code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.decode = function decode(buf) {
|
Script.decode = function decode(raw) {
|
||||||
|
var p = new BufferReader(raw, true);
|
||||||
var code = [];
|
var code = [];
|
||||||
var p = new BufferReader(buf, true);
|
var op, size, data;
|
||||||
var off = 0;
|
|
||||||
var op, size;
|
|
||||||
|
|
||||||
assert(Buffer.isBuffer(buf));
|
assert(Buffer.isBuffer(raw));
|
||||||
|
|
||||||
while (p.left()) {
|
while (p.left()) {
|
||||||
op = p.readU8();
|
op = p.readU8();
|
||||||
@ -4225,26 +4236,10 @@ Script.encode = function encode(code, writer) {
|
|||||||
* not enough size bytes after a PUSHDATA,
|
* not enough size bytes after a PUSHDATA,
|
||||||
* or not enough data after the size.
|
* or not enough data after the size.
|
||||||
*
|
*
|
||||||
* If bitcoind comes across a bad push, it
|
* This function checks to see if an op
|
||||||
* will return an invalid opcode. The problem
|
* is a direct push, or PUSHDATA1 to
|
||||||
* is bitcoind parses scripts _as_ they are
|
* PUSHDATA4 -- these opcodes cannot exist
|
||||||
* executing, which can be slow for us because
|
* in the code array of valid parsed
|
||||||
* now every function that needs to test the
|
|
||||||
* script needs to parse the raw data. It's
|
|
||||||
* also impossible to read a script
|
|
||||||
* _backwards_ making testing for things like
|
|
||||||
* multisig outputs even more difficult.
|
|
||||||
*
|
|
||||||
* If BCoin comes accross a bad push in its
|
|
||||||
* initial parsing, it simply will _not
|
|
||||||
* consider the pushdata to be a pushdata_
|
|
||||||
* but just another opcode in the code array
|
|
||||||
* (all of the data after the pushdata op
|
|
||||||
* will also be considered opcodes rather
|
|
||||||
* than data). This function checks to see
|
|
||||||
* if an op is a direct push, or PUSHDATA1
|
|
||||||
* to PUSHDATA4 -- these opcodes cannot
|
|
||||||
* exist in the code array of valid parsed
|
|
||||||
* scripts.
|
* scripts.
|
||||||
* @param {Number|Buffer} op
|
* @param {Number|Buffer} op
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
|
|||||||
@ -1042,23 +1042,6 @@ utils.merge = function merge(target) {
|
|||||||
return target;
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a non-enumerable property.
|
|
||||||
* @param {Object} obj
|
|
||||||
* @param {String} prop - Property name.
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
|
|
||||||
utils.hidden = function hidden(obj, prop, value) {
|
|
||||||
Object.defineProperty(obj, prop, {
|
|
||||||
value: value,
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true,
|
|
||||||
writable: true
|
|
||||||
});
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort public keys lexicographically.
|
* Sort public keys lexicographically.
|
||||||
* @param {Buffer[]} keys
|
* @param {Buffer[]} keys
|
||||||
|
|||||||
@ -147,6 +147,8 @@ describe('Script', function() {
|
|||||||
'OP_1 OP_DUP OP_PUSHDATA1'
|
'OP_1 OP_DUP OP_PUSHDATA1'
|
||||||
);
|
);
|
||||||
assert(utils.equals(s.raw, new Buffer('51764c', 'hex')));
|
assert(utils.equals(s.raw, new Buffer('51764c', 'hex')));
|
||||||
|
delete s.raw;
|
||||||
|
assert(utils.equals(s.encode(), new Buffer('51764c', 'hex')));
|
||||||
try {
|
try {
|
||||||
s.execute(stack);
|
s.execute(stack);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -158,6 +160,8 @@ describe('Script', function() {
|
|||||||
'OP_1 OP_DUP OP_PUSHDATA2 0x01'
|
'OP_1 OP_DUP OP_PUSHDATA2 0x01'
|
||||||
);
|
);
|
||||||
assert(utils.equals(s.raw, new Buffer('51764d01', 'hex')));
|
assert(utils.equals(s.raw, new Buffer('51764d01', 'hex')));
|
||||||
|
delete s.raw;
|
||||||
|
assert(utils.equals(s.encode(), new Buffer('51764d01', 'hex')));
|
||||||
err = null;
|
err = null;
|
||||||
try {
|
try {
|
||||||
s.execute(stack);
|
s.execute(stack);
|
||||||
@ -170,6 +174,36 @@ describe('Script', function() {
|
|||||||
'OP_1 OP_DUP OP_PUSHDATA4 0x0001'
|
'OP_1 OP_DUP OP_PUSHDATA4 0x0001'
|
||||||
);
|
);
|
||||||
assert(utils.equals(s.raw, new Buffer('51764e0001', 'hex')));
|
assert(utils.equals(s.raw, new Buffer('51764e0001', 'hex')));
|
||||||
|
delete s.raw;
|
||||||
|
assert(utils.equals(s.encode(), new Buffer('51764e0001', 'hex')));
|
||||||
|
err = null;
|
||||||
|
try {
|
||||||
|
s.execute(stack);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
assert(err);
|
||||||
|
assert(err.code === 'BAD_OPCODE');
|
||||||
|
var s = bcoin.script.fromTestString(
|
||||||
|
'OP_1 OP_DUP OP_PUSHDATA1 0x02 0x01'
|
||||||
|
);
|
||||||
|
assert(utils.equals(s.raw, new Buffer('51764c0201', 'hex')));
|
||||||
|
delete s.raw;
|
||||||
|
assert(utils.equals(s.encode(), new Buffer('51764c0201', 'hex')));
|
||||||
|
err = null;
|
||||||
|
try {
|
||||||
|
s.execute(stack);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
assert(err);
|
||||||
|
assert(err.code === 'BAD_OPCODE');
|
||||||
|
var s = bcoin.script.fromTestString(
|
||||||
|
'OP_1 OP_DUP OP_PUSHDATA2 0x0200 0x01'
|
||||||
|
);
|
||||||
|
assert(utils.equals(s.raw, new Buffer('51764d020001', 'hex')));
|
||||||
|
delete s.raw;
|
||||||
|
assert(utils.equals(s.encode(), new Buffer('51764d020001', 'hex')));
|
||||||
err = null;
|
err = null;
|
||||||
try {
|
try {
|
||||||
s.execute(stack);
|
s.execute(stack);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user