test. fix sigops counting.

This commit is contained in:
Christopher Jeffrey 2016-04-20 13:14:38 -07:00
parent 11ef30b942
commit c1fd8bb285
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 72 additions and 60 deletions

View File

@ -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}

View File

@ -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

View File

@ -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);