better script inspection.
This commit is contained in:
parent
c1fd8bb285
commit
64b92ab073
@ -70,11 +70,13 @@ function Witness(items, mutable) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect a Witness object.
|
* Inspect a Witness object.
|
||||||
|
* @method
|
||||||
* @returns {String} Human-readable script.
|
* @returns {String} Human-readable script.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Witness.prototype.toString =
|
||||||
Witness.prototype.inspect = function inspect() {
|
Witness.prototype.inspect = function inspect() {
|
||||||
return Script.format(this.items);
|
return Witness.format(this.items);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,75 +239,6 @@ Witness.fromRaw = function fromRaw(data, enc) {
|
|||||||
return new Witness(Witness.parseRaw(data, enc));
|
return new Witness(Witness.parseRaw(data, enc));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a formatted script
|
|
||||||
* string into a witness object. _Must_
|
|
||||||
* contain only stack items (no non-push
|
|
||||||
* opcodes).
|
|
||||||
* @param {String} items - Script string.
|
|
||||||
* @returns {Witness}
|
|
||||||
* @throws Parse error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Witness.fromString = function fromString(items) {
|
|
||||||
var i, op, symbol;
|
|
||||||
|
|
||||||
if (typeof items !== 'string')
|
|
||||||
return new Witness();
|
|
||||||
|
|
||||||
items = items.trim();
|
|
||||||
|
|
||||||
if (items.length === 0)
|
|
||||||
return new Witness();
|
|
||||||
|
|
||||||
items = items.split(/\s+/);
|
|
||||||
|
|
||||||
for (i = 0; i < items.length; i++) {
|
|
||||||
op = items[i].toLowerCase();
|
|
||||||
|
|
||||||
if (op.indexOf('op_') === 0)
|
|
||||||
op = op.slice(3);
|
|
||||||
|
|
||||||
if (op === '-1' || op === '1negate') {
|
|
||||||
op = STACK_NEGATE;
|
|
||||||
} else if (op === '0' || op === 'false') {
|
|
||||||
op = STACK_FALSE;
|
|
||||||
} else if (op === 'true') {
|
|
||||||
op = STACK_TRUE;
|
|
||||||
} else if (+op >= 1 && +op <= 16) {
|
|
||||||
op = new Buffer([+op]);
|
|
||||||
} else {
|
|
||||||
symbol = 'OP_' + op.toUpperCase();
|
|
||||||
if (opcodes[symbol] == null) {
|
|
||||||
if (op[0] === '\'' || op[0] === '"') {
|
|
||||||
op = op.slice(1, -1);
|
|
||||||
op = new Buffer(op, 'ascii');
|
|
||||||
items[i] = op;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (/^-?\d+$/.test(op)) {
|
|
||||||
op = new bn(op, 10);
|
|
||||||
op = Script.array(op);
|
|
||||||
items[i] = op;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (op[0] === '[')
|
|
||||||
op = op.slice(1, -1);
|
|
||||||
if (op.indexOf('0x') === 0)
|
|
||||||
op = op.slice(2);
|
|
||||||
assert(utils.isHex(op), 'Non-stack item in witness string.');
|
|
||||||
op = new Buffer(op, 'hex');
|
|
||||||
} else {
|
|
||||||
assert(false, 'Non-stack item in witness string.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
items[i] = op;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Witness(items);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a test script/array
|
* Parse a test script/array
|
||||||
* string into a witness object. _Must_
|
* string into a witness object. _Must_
|
||||||
@ -316,14 +249,14 @@ Witness.fromString = function fromString(items) {
|
|||||||
* @throws Parse error.
|
* @throws Parse error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Witness.fromTestString = function fromTestString(items) {
|
Witness.fromString = function fromString(items) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (!Array.isArray(items)) {
|
if (!Array.isArray(items)) {
|
||||||
if (typeof items !== 'string')
|
if (typeof items !== 'string')
|
||||||
return new Witness();
|
return new Witness();
|
||||||
|
|
||||||
items = items.trim();
|
items = items.trim().split(/\s+/);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (items.length === 0)
|
if (items.length === 0)
|
||||||
@ -381,6 +314,18 @@ Witness.fromSymbolic = function fromSymbolic(items) {
|
|||||||
return new Witness(code);
|
return new Witness(code);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format script code into a human readable-string.
|
||||||
|
* @param {Array} code
|
||||||
|
* @returns {String} Human-readable string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Witness.format = function format(items) {
|
||||||
|
return items.map(function(chunk) {
|
||||||
|
return chunk.toString('hex');
|
||||||
|
}).join(' ');
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an object to see if it is a Witness.
|
* Test an object to see if it is a Witness.
|
||||||
* @param {Object} obj
|
* @param {Object} obj
|
||||||
@ -414,11 +359,13 @@ function Stack(items) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the stack.
|
* Inspect the stack.
|
||||||
|
* @method
|
||||||
* @returns {String} Human-readable stack.
|
* @returns {String} Human-readable stack.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Stack.prototype.toString =
|
||||||
Stack.prototype.inspect = function inspect() {
|
Stack.prototype.inspect = function inspect() {
|
||||||
return Script.format(this.items);
|
return Witness.format(this.items);
|
||||||
};
|
};
|
||||||
|
|
||||||
Stack.prototype.__defineGetter__('length', function() {
|
Stack.prototype.__defineGetter__('length', function() {
|
||||||
@ -939,9 +886,11 @@ Script.prototype.clone = function clone(mutable) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the script.
|
* Inspect the script.
|
||||||
|
* @method
|
||||||
* @returns {String} Human-readable script code.
|
* @returns {String} Human-readable script code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Script.prototype.toString =
|
||||||
Script.prototype.inspect = function inspect() {
|
Script.prototype.inspect = function inspect() {
|
||||||
return Script.format(this.code);
|
return Script.format(this.code);
|
||||||
};
|
};
|
||||||
@ -3396,32 +3345,48 @@ Script.isLowDER = function isLowDER(sig) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Script.format = function format(code) {
|
Script.format = function format(code) {
|
||||||
var scripts = [];
|
return code.map(function(chunk) {
|
||||||
|
var op, size;
|
||||||
|
|
||||||
if (Array.isArray(code)) {
|
if (Buffer.isBuffer(chunk)) {
|
||||||
scripts.push({ code: code });
|
op = chunk.op;
|
||||||
} else if (code instanceof Stack) {
|
if (op == null) {
|
||||||
scripts.push({ code: code.items });
|
if (chunk.length === 0) {
|
||||||
} else if (code instanceof Witness) {
|
op = opcodes.OP_0;
|
||||||
scripts.push({ code: code.items });
|
} else if (chunk.length <= 0x4b) {
|
||||||
} else if (code instanceof Script) {
|
if (chunk.length === 1) {
|
||||||
scripts.push(code);
|
if (chunk[0] === 0) {
|
||||||
} else if (code instanceof bcoin.input) {
|
op = opcodes.OP_0;
|
||||||
scripts.push(code.script);
|
return constants.opcodesByVal[op];
|
||||||
if (code.witness.length > 0)
|
} else if (chunk[0] >= 1 && chunk[0] <= 16) {
|
||||||
scripts.push({ code: code.witness.items });
|
op = chunk[0] + 0x50;
|
||||||
if (code.coin) {
|
return constants.opcodesByVal[op];
|
||||||
scripts.push(code.coin.script);
|
} else if (chunk[0] === 0x81) {
|
||||||
if (code.coin.script.isScripthash())
|
op = opcodes.OP_1NEGATE;
|
||||||
scripts.push(code.coin.script.getRedeem());
|
return constants.opcodesByVal[op];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
op = chunk.length;
|
||||||
|
} else if (chunk.length <= 0xff) {
|
||||||
|
op = opcodes.OP_PUSHDATA1;
|
||||||
|
} else if (chunk.length <= 0xffff) {
|
||||||
|
op = opcodes.OP_PUSHDATA2;
|
||||||
|
} else if (chunk.length <= 0xffffffff) {
|
||||||
|
op = opcodes.OP_PUSHDATA4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size = chunk.length.toString(16);
|
||||||
|
if (size.length < 2)
|
||||||
|
size = '0' + size;
|
||||||
|
if (!constants.opcodesByVal[op]) {
|
||||||
|
op = op.toString(16);
|
||||||
|
if (op.length < 2)
|
||||||
|
op = '0' + op;
|
||||||
|
return '0x' + op + ' 0x' + chunk.toString('hex');
|
||||||
|
}
|
||||||
|
op = constants.opcodesByVal[op];
|
||||||
|
return op + ' 0x' + size + ' 0x' + chunk.toString('hex');
|
||||||
}
|
}
|
||||||
} else if (code instanceof bcoin.output) {
|
|
||||||
scripts.push(code.script);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Script.concat(scripts).map(function(chunk) {
|
|
||||||
if (Buffer.isBuffer(chunk))
|
|
||||||
return '[' + chunk.toString('hex') + ']';
|
|
||||||
|
|
||||||
assert(typeof chunk === 'number');
|
assert(typeof chunk === 'number');
|
||||||
|
|
||||||
@ -3432,7 +3397,7 @@ Script.format = function format(code) {
|
|||||||
if (chunk.length < 2)
|
if (chunk.length < 2)
|
||||||
chunk = '0' + chunk;
|
chunk = '0' + chunk;
|
||||||
|
|
||||||
return 'UNKNOWN(' + chunk + ')';
|
return '0x' + chunk;
|
||||||
}).join(' ');
|
}).join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3531,63 +3496,6 @@ Script.prototype.getArgs = function getArgs() {
|
|||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a formatted script
|
|
||||||
* string into a script object.
|
|
||||||
* @param {String} items - Script string.
|
|
||||||
* @returns {Script}
|
|
||||||
* @throws Parse error.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Script.fromString = function fromString(code) {
|
|
||||||
var i, op, symbol;
|
|
||||||
|
|
||||||
if (typeof code !== 'string')
|
|
||||||
return new Script();
|
|
||||||
|
|
||||||
code = code.trim();
|
|
||||||
|
|
||||||
if (code.length === 0)
|
|
||||||
return new Script();
|
|
||||||
|
|
||||||
code = code.split(/\s+/);
|
|
||||||
|
|
||||||
for (i = 0; i < code.length; i++) {
|
|
||||||
op = code[i];
|
|
||||||
|
|
||||||
symbol = op.toUpperCase();
|
|
||||||
if (symbol.indexOf('OP_') !== 0)
|
|
||||||
symbol = 'OP_' + symbol;
|
|
||||||
|
|
||||||
if (opcodes[symbol] == null) {
|
|
||||||
if (op[0] === '\'' || op[0] === '"') {
|
|
||||||
op = op.slice(1, -1);
|
|
||||||
op = new Buffer(op, 'ascii');
|
|
||||||
code[i] = op;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (/^-?\d+$/.test(op)) {
|
|
||||||
op = new bn(op, 10);
|
|
||||||
op = Script.array(op);
|
|
||||||
code[i] = op;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (op[0] === '[')
|
|
||||||
op = op.slice(1, -1);
|
|
||||||
if (op.indexOf('0x') === 0)
|
|
||||||
op = op.slice(2);
|
|
||||||
assert(utils.isHex(op), 'Unknown opcode.');
|
|
||||||
op = new Buffer(op, 'hex');
|
|
||||||
code[i] = op;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
code[i] = opcodes[symbol];
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Script(code);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a bitcoind test script
|
* Parse a bitcoind test script
|
||||||
* string into a script object.
|
* string into a script object.
|
||||||
@ -3596,7 +3504,7 @@ Script.fromString = function fromString(code) {
|
|||||||
* @throws Parse error.
|
* @throws Parse error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.fromTestString = function fromTestString(code) {
|
Script.fromString = function fromString(code) {
|
||||||
var i, op, symbol, p;
|
var i, op, symbol, p;
|
||||||
|
|
||||||
if (typeof code !== 'string')
|
if (typeof code !== 'string')
|
||||||
|
|||||||
@ -143,7 +143,7 @@ describe('Script', function() {
|
|||||||
it('should handle bad size pushes correctly.', function () {
|
it('should handle bad size pushes correctly.', function () {
|
||||||
var err;
|
var err;
|
||||||
var stack = new bcoin.script.stack();
|
var stack = new bcoin.script.stack();
|
||||||
var s = bcoin.script.fromTestString(
|
var s = bcoin.script.fromString(
|
||||||
'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')));
|
||||||
@ -156,7 +156,7 @@ describe('Script', function() {
|
|||||||
}
|
}
|
||||||
assert(err);
|
assert(err);
|
||||||
assert(err.code === 'BAD_OPCODE');
|
assert(err.code === 'BAD_OPCODE');
|
||||||
var s = bcoin.script.fromTestString(
|
var s = bcoin.script.fromString(
|
||||||
'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')));
|
||||||
@ -170,7 +170,7 @@ describe('Script', function() {
|
|||||||
}
|
}
|
||||||
assert(err);
|
assert(err);
|
||||||
assert(err.code === 'BAD_OPCODE');
|
assert(err.code === 'BAD_OPCODE');
|
||||||
var s = bcoin.script.fromTestString(
|
var s = bcoin.script.fromString(
|
||||||
'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')));
|
||||||
@ -184,7 +184,7 @@ describe('Script', function() {
|
|||||||
}
|
}
|
||||||
assert(err);
|
assert(err);
|
||||||
assert(err.code === 'BAD_OPCODE');
|
assert(err.code === 'BAD_OPCODE');
|
||||||
var s = bcoin.script.fromTestString(
|
var s = bcoin.script.fromString(
|
||||||
'OP_1 OP_DUP OP_PUSHDATA1 0x02 0x01'
|
'OP_1 OP_DUP OP_PUSHDATA1 0x02 0x01'
|
||||||
);
|
);
|
||||||
assert(utils.equals(s.raw, new Buffer('51764c0201', 'hex')));
|
assert(utils.equals(s.raw, new Buffer('51764c0201', 'hex')));
|
||||||
@ -198,7 +198,7 @@ describe('Script', function() {
|
|||||||
}
|
}
|
||||||
assert(err);
|
assert(err);
|
||||||
assert(err.code === 'BAD_OPCODE');
|
assert(err.code === 'BAD_OPCODE');
|
||||||
var s = bcoin.script.fromTestString(
|
var s = bcoin.script.fromString(
|
||||||
'OP_1 OP_DUP OP_PUSHDATA2 0x0200 0x01'
|
'OP_1 OP_DUP OP_PUSHDATA2 0x0200 0x01'
|
||||||
);
|
);
|
||||||
assert(utils.equals(s.raw, new Buffer('51764d020001', 'hex')));
|
assert(utils.equals(s.raw, new Buffer('51764d020001', 'hex')));
|
||||||
@ -275,9 +275,9 @@ describe('Script', function() {
|
|||||||
|
|
||||||
comments += ' (' + expected + ')';
|
comments += ' (' + expected + ')';
|
||||||
|
|
||||||
witness = bcoin.witness.fromTestString(witness);
|
witness = bcoin.witness.fromString(witness);
|
||||||
input = bcoin.script.fromTestString(input);
|
input = bcoin.script.fromString(input);
|
||||||
output = bcoin.script.fromTestString(output);
|
output = bcoin.script.fromString(output);
|
||||||
|
|
||||||
var flag = 0;
|
var flag = 0;
|
||||||
for (var i = 0; i < flags.length; i++) {
|
for (var i = 0; i < flags.length; i++) {
|
||||||
|
|||||||
@ -152,7 +152,7 @@ describe('TX', function() {
|
|||||||
coins.forEach(function(data) {
|
coins.forEach(function(data) {
|
||||||
var hash = data[0];
|
var hash = data[0];
|
||||||
var index = data[1];
|
var index = data[1];
|
||||||
var script = bcoin.script.fromTestString(data[2]);
|
var script = bcoin.script.fromString(data[2]);
|
||||||
var value = data[3];
|
var value = data[3];
|
||||||
var coin = new bcoin.coin({
|
var coin = new bcoin.coin({
|
||||||
version: 1,
|
version: 1,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user