better script inspection.
This commit is contained in:
parent
c1fd8bb285
commit
64b92ab073
@ -70,11 +70,13 @@ function Witness(items, mutable) {
|
||||
|
||||
/**
|
||||
* Inspect a Witness object.
|
||||
* @method
|
||||
* @returns {String} Human-readable script.
|
||||
*/
|
||||
|
||||
Witness.prototype.toString =
|
||||
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));
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* string into a witness object. _Must_
|
||||
@ -316,14 +249,14 @@ Witness.fromString = function fromString(items) {
|
||||
* @throws Parse error.
|
||||
*/
|
||||
|
||||
Witness.fromTestString = function fromTestString(items) {
|
||||
Witness.fromString = function fromString(items) {
|
||||
var result;
|
||||
|
||||
if (!Array.isArray(items)) {
|
||||
if (typeof items !== 'string')
|
||||
return new Witness();
|
||||
|
||||
items = items.trim();
|
||||
items = items.trim().split(/\s+/);
|
||||
}
|
||||
|
||||
if (items.length === 0)
|
||||
@ -381,6 +314,18 @@ Witness.fromSymbolic = function fromSymbolic(items) {
|
||||
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.
|
||||
* @param {Object} obj
|
||||
@ -414,11 +359,13 @@ function Stack(items) {
|
||||
|
||||
/**
|
||||
* Inspect the stack.
|
||||
* @method
|
||||
* @returns {String} Human-readable stack.
|
||||
*/
|
||||
|
||||
Stack.prototype.toString =
|
||||
Stack.prototype.inspect = function inspect() {
|
||||
return Script.format(this.items);
|
||||
return Witness.format(this.items);
|
||||
};
|
||||
|
||||
Stack.prototype.__defineGetter__('length', function() {
|
||||
@ -939,9 +886,11 @@ Script.prototype.clone = function clone(mutable) {
|
||||
|
||||
/**
|
||||
* Inspect the script.
|
||||
* @method
|
||||
* @returns {String} Human-readable script code.
|
||||
*/
|
||||
|
||||
Script.prototype.toString =
|
||||
Script.prototype.inspect = function inspect() {
|
||||
return Script.format(this.code);
|
||||
};
|
||||
@ -3396,32 +3345,48 @@ Script.isLowDER = function isLowDER(sig) {
|
||||
*/
|
||||
|
||||
Script.format = function format(code) {
|
||||
var scripts = [];
|
||||
return code.map(function(chunk) {
|
||||
var op, size;
|
||||
|
||||
if (Array.isArray(code)) {
|
||||
scripts.push({ code: code });
|
||||
} else if (code instanceof Stack) {
|
||||
scripts.push({ code: code.items });
|
||||
} else if (code instanceof Witness) {
|
||||
scripts.push({ code: code.items });
|
||||
} else if (code instanceof Script) {
|
||||
scripts.push(code);
|
||||
} else if (code instanceof bcoin.input) {
|
||||
scripts.push(code.script);
|
||||
if (code.witness.length > 0)
|
||||
scripts.push({ code: code.witness.items });
|
||||
if (code.coin) {
|
||||
scripts.push(code.coin.script);
|
||||
if (code.coin.script.isScripthash())
|
||||
scripts.push(code.coin.script.getRedeem());
|
||||
if (Buffer.isBuffer(chunk)) {
|
||||
op = chunk.op;
|
||||
if (op == null) {
|
||||
if (chunk.length === 0) {
|
||||
op = opcodes.OP_0;
|
||||
} else if (chunk.length <= 0x4b) {
|
||||
if (chunk.length === 1) {
|
||||
if (chunk[0] === 0) {
|
||||
op = opcodes.OP_0;
|
||||
return constants.opcodesByVal[op];
|
||||
} else if (chunk[0] >= 1 && chunk[0] <= 16) {
|
||||
op = chunk[0] + 0x50;
|
||||
return constants.opcodesByVal[op];
|
||||
} else if (chunk[0] === 0x81) {
|
||||
op = opcodes.OP_1NEGATE;
|
||||
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');
|
||||
|
||||
@ -3432,7 +3397,7 @@ Script.format = function format(code) {
|
||||
if (chunk.length < 2)
|
||||
chunk = '0' + chunk;
|
||||
|
||||
return 'UNKNOWN(' + chunk + ')';
|
||||
return '0x' + chunk;
|
||||
}).join(' ');
|
||||
};
|
||||
|
||||
@ -3531,63 +3496,6 @@ Script.prototype.getArgs = function getArgs() {
|
||||
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
|
||||
* string into a script object.
|
||||
@ -3596,7 +3504,7 @@ Script.fromString = function fromString(code) {
|
||||
* @throws Parse error.
|
||||
*/
|
||||
|
||||
Script.fromTestString = function fromTestString(code) {
|
||||
Script.fromString = function fromString(code) {
|
||||
var i, op, symbol, p;
|
||||
|
||||
if (typeof code !== 'string')
|
||||
|
||||
@ -143,7 +143,7 @@ describe('Script', function() {
|
||||
it('should handle bad size pushes correctly.', function () {
|
||||
var err;
|
||||
var stack = new bcoin.script.stack();
|
||||
var s = bcoin.script.fromTestString(
|
||||
var s = bcoin.script.fromString(
|
||||
'OP_1 OP_DUP OP_PUSHDATA1'
|
||||
);
|
||||
assert(utils.equals(s.raw, new Buffer('51764c', 'hex')));
|
||||
@ -156,7 +156,7 @@ describe('Script', function() {
|
||||
}
|
||||
assert(err);
|
||||
assert(err.code === 'BAD_OPCODE');
|
||||
var s = bcoin.script.fromTestString(
|
||||
var s = bcoin.script.fromString(
|
||||
'OP_1 OP_DUP OP_PUSHDATA2 0x01'
|
||||
);
|
||||
assert(utils.equals(s.raw, new Buffer('51764d01', 'hex')));
|
||||
@ -170,7 +170,7 @@ describe('Script', function() {
|
||||
}
|
||||
assert(err);
|
||||
assert(err.code === 'BAD_OPCODE');
|
||||
var s = bcoin.script.fromTestString(
|
||||
var s = bcoin.script.fromString(
|
||||
'OP_1 OP_DUP OP_PUSHDATA4 0x0001'
|
||||
);
|
||||
assert(utils.equals(s.raw, new Buffer('51764e0001', 'hex')));
|
||||
@ -184,7 +184,7 @@ describe('Script', function() {
|
||||
}
|
||||
assert(err);
|
||||
assert(err.code === 'BAD_OPCODE');
|
||||
var s = bcoin.script.fromTestString(
|
||||
var s = bcoin.script.fromString(
|
||||
'OP_1 OP_DUP OP_PUSHDATA1 0x02 0x01'
|
||||
);
|
||||
assert(utils.equals(s.raw, new Buffer('51764c0201', 'hex')));
|
||||
@ -198,7 +198,7 @@ describe('Script', function() {
|
||||
}
|
||||
assert(err);
|
||||
assert(err.code === 'BAD_OPCODE');
|
||||
var s = bcoin.script.fromTestString(
|
||||
var s = bcoin.script.fromString(
|
||||
'OP_1 OP_DUP OP_PUSHDATA2 0x0200 0x01'
|
||||
);
|
||||
assert(utils.equals(s.raw, new Buffer('51764d020001', 'hex')));
|
||||
@ -275,9 +275,9 @@ describe('Script', function() {
|
||||
|
||||
comments += ' (' + expected + ')';
|
||||
|
||||
witness = bcoin.witness.fromTestString(witness);
|
||||
input = bcoin.script.fromTestString(input);
|
||||
output = bcoin.script.fromTestString(output);
|
||||
witness = bcoin.witness.fromString(witness);
|
||||
input = bcoin.script.fromString(input);
|
||||
output = bcoin.script.fromString(output);
|
||||
|
||||
var flag = 0;
|
||||
for (var i = 0; i < flags.length; i++) {
|
||||
|
||||
@ -152,7 +152,7 @@ describe('TX', function() {
|
||||
coins.forEach(function(data) {
|
||||
var hash = data[0];
|
||||
var index = data[1];
|
||||
var script = bcoin.script.fromTestString(data[2]);
|
||||
var script = bcoin.script.fromString(data[2]);
|
||||
var value = data[3];
|
||||
var coin = new bcoin.coin({
|
||||
version: 1,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user