Commit b21d55ba authored by chriseth's avatar chriseth

Merge pull request #13 from yann300/debuggerPanels

Debugger panels (stack, storage, memory, ...)
parents e1da5e6b d7b46729
This diff is collapsed.
var React = require('react');
var style = require('./basicStyles')
module.exports = React.createClass({
getDefaultProps: function()
{
return {
data: null,
name: null,
renderRow: null
};
},
render: function()
{
return (
<div style={style.panel.container}>
<div style={style.panel.title} >{this.props.name}</div>
<div style={style.panel.tableContainer} >
<table style={style.panel.table}>
<tbody>
{this.renderItems()}
</tbody>
</table>
</div>
</div>
);
},
renderItems: function()
{
if (!this.props.data)
return []
if (!this.props.renderRow)
{
var ret = []
for (var key in this.props.data)
ret.push(<tr key={key} ><td>{this.props.data[key]}</td></tr>)
return ret
}
else
return this.props.renderRow(this.props.data)
}
})
module.exports = {
wrapper:
{
'fontFamily': "arial,sans-serif"
},
container:
{
'margin': '10px',
'padding': '5px'
},
address:
{
'fontStyle': 'italic'
},
instructionsList:
{
'width': "320px"
},
transactionInfo:
{
'marginTop': '5px'
},
panel:
{
container:
{
'border': '1px solid',
'width': '600px'
},
tableContainer:
{
'height': '150px',
'overflowY': 'auto'
},
table:
{
'padding': '5px'
},
title:
{
'padding': '5px',
'fontStyle': 'italic'
}
},
hidden:
{
'display': 'none'
},
display:
{
'display': 'block'
},
sticker:
{
'verticalAlign': 'top',
'margin': '5px'
},
inline:
{
'display': 'inline-block'
}
}
\ No newline at end of file
var opcodes = require('./opcodes')
module.exports = {
nameOpCodes: function (raw)
{
var pushData = ''
var codeMap = {}
var code = []
for (var i = 0; i < raw.length; i++)
{
var pc = i
var curOpCode = opcodes(raw[pc], false).name
codeMap[i] = code.length
// no destinations into the middle of PUSH
if (curOpCode.slice(0, 4) === 'PUSH')
{
var jumpNum = raw[pc] - 0x5f
pushData = raw.slice(pc + 1, pc + jumpNum + 1)
i += jumpNum
}
code.push(this.pad(pc, this.roundLog(raw.length, 10)) + ' ' + curOpCode + ' ' + pushData.toString('hex'))
pushData = ''
}
return [ code, codeMap ]
},
pad: function (num, size) {
var s = num + ''
while (s.length < size) s = '0' + s
return s
},
log: function (num, base) {
return Math.log(num) / Math.log(base)
},
roundLog: function (num, base) {
return Math.ceil(this.log(num, base))
}
}
\ No newline at end of file
...@@ -2,17 +2,19 @@ var React = require('react'); ...@@ -2,17 +2,19 @@ var React = require('react');
var TxBrowser = require('./txBrowser'); var TxBrowser = require('./txBrowser');
var VmTraceManager = require('./vmTraceManager'); var VmTraceManager = require('./vmTraceManager');
var VmTraceBrowser = require('./vmTraceBrowser'); var VmTraceBrowser = require('./vmTraceBrowser');
var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
getInitialState: function() { getInitialState: function() {
return {vmTrace: null} return {vmTrace: null, state: ""}
}, },
render: function() { render: function() {
return ( return (
<div> <div style={style.wrapper} >
<h1>Debugger</h1> <h1 style={style.container} >Eth Debugger</h1>
<TxBrowser onNewTxRequested={this.retrieveVmTrace} /> <TxBrowser onNewTxRequested={this.retrieveVmTrace} />
<div style={style.container} >{this.state.state}</div>
<VmTraceBrowser vmTrace={this.state.vmTrace} /> <VmTraceBrowser vmTrace={this.state.vmTrace} />
</div> </div>
); );
...@@ -20,6 +22,11 @@ module.exports = React.createClass({ ...@@ -20,6 +22,11 @@ module.exports = React.createClass({
retrieveVmTrace: function(blockNumber, txNumber) retrieveVmTrace: function(blockNumber, txNumber)
{ {
this.setState({vmTrace: VmTraceManager.retrieveVmTrace(blockNumber, txNumber)}); this.setState({state: "loading..."})
var deb = this
VmTraceManager.retrieveVmTrace(blockNumber, txNumber, function(error, result)
{
deb.setState({vmTrace: result, state: ""});
})
} }
}); });
const codes = {
// 0x0 range - arithmetic ops
// name, baseCost, off stack, on stack, dynamic
0x00: ['STOP', 0, 0, 0, false],
0x01: ['ADD', 3, 2, 1, false],
0x02: ['MUL', 5, 2, 1, false],
0x03: ['SUB', 3, 2, 1, false],
0x04: ['DIV', 5, 2, 1, false],
0x05: ['SDIV', 5, 2, 1, false],
0x06: ['MOD', 5, 2, 1, false],
0x07: ['SMOD', 5, 2, 1, false],
0x08: ['ADDMOD', 8, 3, 1, false],
0x09: ['MULMOD', 8, 3, 1, false],
0x0a: ['EXP', 10, 2, 1, false],
0x0b: ['SIGNEXTEND', 5, 1, 1, false],
// 0x10 range - bit ops
0x10: ['LT', 3, 2, 1, false],
0x11: ['GT', 3, 2, 1, false],
0x12: ['SLT', 3, 2, 1, false],
0x13: ['SGT', 3, 2, 1, false],
0x14: ['EQ', 3, 2, 1, false],
0x15: ['ISZERO', 3, 1, 1, false],
0x16: ['AND', 3, 2, 1, false],
0x17: ['OR', 3, 2, 1, false],
0x18: ['XOR', 3, 2, 1, false],
0x19: ['NOT', 3, 1, 1, false],
0x1a: ['BYTE', 3, 2, 1, false],
// 0x20 range - crypto
0x20: ['SHA3', 30, 2, 1, false],
// 0x30 range - closure state
0x30: ['ADDRESS', 2, 0, 1, true],
0x31: ['BALANCE', 20, 1, 1, true],
0x32: ['ORIGIN', 2, 0, 1, true],
0x33: ['CALLER', 2, 0, 1, true],
0x34: ['CALLVALUE', 2, 0, 1, true],
0x35: ['CALLDATALOAD', 3, 1, 1, true],
0x36: ['CALLDATASIZE', 2, 0, 1, true],
0x37: ['CALLDATACOPY', 3, 3, 0, true],
0x38: ['CODESIZE', 2, 0, 1, false],
0x39: ['CODECOPY', 3, 3, 0, false],
0x3a: ['GASPRICE', 2, 0, 1, false],
0x3b: ['EXTCODESIZE', 20, 1, 1, true],
0x3c: ['EXTCODECOPY', 20, 4, 0, true],
// '0x40' range - block operations
0x40: ['BLOCKHASH', 20, 1, 1, true],
0x41: ['COINBASE', 2, 0, 1, true],
0x42: ['TIMESTAMP', 2, 0, 1, true],
0x43: ['NUMBER', 2, 0, 1, true],
0x44: ['DIFFICULTY', 2, 0, 1, true],
0x45: ['GASLIMIT', 2, 0, 1, true],
// 0x50 range - 'storage' and execution
0x50: ['POP', 2, 1, 0, false],
0x51: ['MLOAD', 3, 1, 1, false],
0x52: ['MSTORE', 3, 2, 0, false],
0x53: ['MSTORE8', 3, 2, 0, false],
0x54: ['SLOAD', 50, 1, 1, true],
0x55: ['SSTORE', 0, 2, 0, true],
0x56: ['JUMP', 8, 1, 0, false],
0x57: ['JUMPI', 10, 2, 0, false],
0x58: ['PC', 2, 0, 1, false],
0x59: ['MSIZE', 2, 0, 1, false],
0x5a: ['GAS', 2, 0, 1, false],
0x5b: ['JUMPDEST', 1, 0, 0, false],
// 0x60, range
0x60: ['PUSH', 3, 0, 1, false],
0x61: ['PUSH', 3, 0, 1, false],
0x62: ['PUSH', 3, 0, 1, false],
0x63: ['PUSH', 3, 0, 1, false],
0x64: ['PUSH', 3, 0, 1, false],
0x65: ['PUSH', 3, 0, 1, false],
0x66: ['PUSH', 3, 0, 1, false],
0x67: ['PUSH', 3, 0, 1, false],
0x68: ['PUSH', 3, 0, 1, false],
0x69: ['PUSH', 3, 0, 1, false],
0x6a: ['PUSH', 3, 0, 1, false],
0x6b: ['PUSH', 3, 0, 1, false],
0x6c: ['PUSH', 3, 0, 1, false],
0x6d: ['PUSH', 3, 0, 1, false],
0x6e: ['PUSH', 3, 0, 1, false],
0x6f: ['PUSH', 3, 0, 1, false],
0x70: ['PUSH', 3, 0, 1, false],
0x71: ['PUSH', 3, 0, 1, false],
0x72: ['PUSH', 3, 0, 1, false],
0x73: ['PUSH', 3, 0, 1, false],
0x74: ['PUSH', 3, 0, 1, false],
0x75: ['PUSH', 3, 0, 1, false],
0x76: ['PUSH', 3, 0, 1, false],
0x77: ['PUSH', 3, 0, 1, false],
0x78: ['PUSH', 3, 0, 1, false],
0x79: ['PUSH', 3, 0, 1, false],
0x7a: ['PUSH', 3, 0, 1, false],
0x7b: ['PUSH', 3, 0, 1, false],
0x7c: ['PUSH', 3, 0, 1, false],
0x7d: ['PUSH', 3, 0, 1, false],
0x7e: ['PUSH', 3, 0, 1, false],
0x7f: ['PUSH', 3, 0, 1, false],
0x80: ['DUP', 3, 0, 1, false],
0x81: ['DUP', 3, 0, 1, false],
0x82: ['DUP', 3, 0, 1, false],
0x83: ['DUP', 3, 0, 1, false],
0x84: ['DUP', 3, 0, 1, false],
0x85: ['DUP', 3, 0, 1, false],
0x86: ['DUP', 3, 0, 1, false],
0x87: ['DUP', 3, 0, 1, false],
0x88: ['DUP', 3, 0, 1, false],
0x89: ['DUP', 3, 0, 1, false],
0x8a: ['DUP', 3, 0, 1, false],
0x8b: ['DUP', 3, 0, 1, false],
0x8c: ['DUP', 3, 0, 1, false],
0x8d: ['DUP', 3, 0, 1, false],
0x8e: ['DUP', 3, 0, 1, false],
0x8f: ['DUP', 3, 0, 1, false],
0x90: ['SWAP', 3, 0, 0, false],
0x91: ['SWAP', 3, 0, 0, false],
0x92: ['SWAP', 3, 0, 0, false],
0x93: ['SWAP', 3, 0, 0, false],
0x94: ['SWAP', 3, 0, 0, false],
0x95: ['SWAP', 3, 0, 0, false],
0x96: ['SWAP', 3, 0, 0, false],
0x97: ['SWAP', 3, 0, 0, false],
0x98: ['SWAP', 3, 0, 0, false],
0x99: ['SWAP', 3, 0, 0, false],
0x9a: ['SWAP', 3, 0, 0, false],
0x9b: ['SWAP', 3, 0, 0, false],
0x9c: ['SWAP', 3, 0, 0, false],
0x9d: ['SWAP', 3, 0, 0, false],
0x9e: ['SWAP', 3, 0, 0, false],
0x9f: ['SWAP', 3, 0, 0, false],
0xa0: ['LOG', 375, 2, 0, false],
0xa1: ['LOG', 375, 3, 0, false],
0xa2: ['LOG', 375, 4, 0, false],
0xa3: ['LOG', 375, 5, 0, false],
0xa4: ['LOG', 375, 6, 0, false],
// '0xf0' range - closures
0xf0: ['CREATE', 32000, 3, 1, true],
0xf1: ['CALL', 40, 7, 1, true],
0xf2: ['CALLCODE', 40, 7, 1, true],
0xf3: ['RETURN', 0, 2, 0, false],
0xf4: ['DELEGATECALL', 40, 6, 1, true],
// '0x70', range - other
0xff: ['SUICIDE', 0, 1, 0, false]
}
module.exports = function (op, full) {
var code = codes[op] ? codes[op] : ['INVALID', 0]
var opcode = code[0]
if (full) {
if (opcode === 'LOG') {
opcode += op - 0xa0
}
if (opcode === 'PUSH') {
opcode += op - 0x5f
}
if (opcode === 'DUP') {
opcode += op - 0x7f
}
if (opcode === 'SWAP') {
opcode += op - 0x8f
}
}
return {name: opcode, fee: code[1], in: code[2], out: code[3], dynamic: code[4], async: code[5]}
}
\ No newline at end of file
var React = require('react');
var style = require('./basicStyles')
module.exports = React.createClass({
getDefaultProps: function()
{
return {
data: null,
};
},
render: function()
{
return (
<div>
<table><tbody>
{this.renderItems()}
</tbody></table>
</div>
);
},
renderItems: function()
{
if (this.props.data)
{
var ret = []
for (var key in this.props.data)
ret.push(<tr key={key}><td>{this.props.data[key]}</td></tr>)
return ret
}
return null
},
})
var React = require('react'); var React = require('react');
var style = require('./basicStyles')
module.exports = React.createClass({ module.exports = React.createClass({
propTypes: { propTypes: {
...@@ -6,12 +7,14 @@ module.exports = React.createClass({ ...@@ -6,12 +7,14 @@ module.exports = React.createClass({
}, },
getInitialState: function() { getInitialState: function() {
return {blockNumber: "1160004", txNumber: "1"} return {blockNumber: "1382256", txNumber: "1", from: "", to: "", hash: ""}
}, },
submit: function() submit: function()
{ {
this.props.onNewTxRequested(this.state.blockNumber, parseInt(this.state.txNumber)); var tx = web3.eth.getTransactionFromBlock(this.state.blockNumber, this.state.txNumber)
this.setState({from: tx.from, to: tx.to, hash: tx.hash})
this.props.onNewTxRequested(this.state.blockNumber, parseInt(this.state.txNumber))
}, },
updateBlockN: function(ev) { updateBlockN: function(ev) {
...@@ -24,11 +27,15 @@ module.exports = React.createClass({ ...@@ -24,11 +27,15 @@ module.exports = React.createClass({
render: function() { render: function() {
return ( return (
<div> <div style={style.container} >
<div><h3>Transaction details</h3></div> <input onChange={this.updateBlockN} type="text" placeholder= {"Block number or hash (default 1382256)" + this.state.blockNumber}></input>
<input onChange={this.updateBlockN} type="text" placeholder= {"Block number e.g. : " + this.state.blockNumber}></input> <input onChange={this.updateTxN} type="text" placeholder={"Transaction Number (default 1) " + this.state.txNumber}></input>
<input onChange={this.updateTxN} type="text" placeholder={"Transaction Number e.g. : " + this.state.txNumber}></input>
<button onClick={this.submit}>Get</button> <button onClick={this.submit}>Get</button>
<div style={style.transactionInfo}>
<div>Hash: {this.state.hash}</div>
<div>From: {this.state.from}</div>
<div>To: {this.state.to}</div>
</div>
</div> </div>
); );
} }
......
module.exports = { module.exports = {
retrieveVmTrace: function(blockNumber, txNumber) { retrieveVmTrace: function(blockNumber, txNumber, callBack) {
return web3.admin.vmTrace(blockNumber, parseInt(txNumber)); web3.debug.trace(blockNumber, parseInt(txNumber), function(error, result)
{
callBack(error, result)
});
} }
} }
...@@ -58,8 +58,8 @@ module.exports = { ...@@ -58,8 +58,8 @@ module.exports = {
new web3._extend.Method({ new web3._extend.Method({
name: 'vmTrace', name: 'vmTrace',
call: 'admin_eth_vmTrace', call: 'admin_eth_vmTrace',
inputFormatter: [null, null], inputFormatter: [null, null, null],
params: 2 params: 3
}), }),
], ],
properties: properties:
...@@ -93,6 +93,13 @@ module.exports = { ...@@ -93,6 +93,13 @@ module.exports = {
methods: methods:
[ [
new web3._extend.Method({ new web3._extend.Method({
name: 'trace',
call: 'debug_trace',
params: 1,
inputFormatter: [null, null],
params: 2
}),
new web3._extend.Method({
name: 'printBlock', name: 'printBlock',
call: 'debug_printBlock', call: 'debug_printBlock',
params: 1, params: 1,
...@@ -266,5 +273,5 @@ module.exports = { ...@@ -266,5 +273,5 @@ module.exports = {
] ]
}); });
} }
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment