commit
00620484e8
@ -0,0 +1,4 @@ |
||||
build |
||||
node_modules |
||||
npm-debug.log |
||||
lint.xml |
@ -1,356 +1,370 @@ |
||||
var React = require('react'); |
||||
'use strict' |
||||
var React = require('react') |
||||
var BasicPanel = require('./basicPanel') |
||||
var Sticker = require('./sticker') |
||||
var ButtonNavigator = require('./vmTraceButtonNavigator') |
||||
var codeUtils = require('./codeUtils') |
||||
var style = require('./basicStyles') |
||||
var Slider = require('./slider'); |
||||
var Slider = require('./slider') |
||||
|
||||
module.exports = React.createClass({ |
||||
contextTypes: { |
||||
web3: React.PropTypes.object |
||||
}, |
||||
|
||||
getInitialState: function() |
||||
{ |
||||
return { |
||||
currentSelected: -1, // current selected item in the vmTrace
|
||||
selectedInst: -1, // current selected item in the contract assembly code
|
||||
currentAddress: null, |
||||
currentStack: null, |
||||
currentLevels: null, |
||||
currentStorage: null, |
||||
currentMemory: null, |
||||
currentCallData: null, |
||||
currentStepInfo: null, |
||||
codes: {}, // assembly items instructions list by contract addesses
|
||||
instructionsIndexByBytesOffset: {}, // mapping between bytes offset and instructions index.
|
||||
callStack: {} |
||||
}; |
||||
}, |
||||
|
||||
getDefaultProps: function()
|
||||
{ |
||||
return { |
||||
vmTrace: null |
||||
}; |
||||
},
|
||||
|
||||
render: function()
|
||||
{
|
||||
return ( |
||||
<div style={this.props.vmTrace === null ? style.hidden : style.display} > |
||||
<div style={style.container}><span style={style.address}>Current code: {this.state.currentAddress}</span></div> |
||||
<div style={style.container}> |
||||
<Slider ref="slider" onChange={this.selectState} min="0" max={this.props.vmTrace ? this.props.vmTrace.length : 0}/> |
||||
<ButtonNavigator |
||||
vmTraceLength={this.props.vmTrace ? this.props.vmTrace.length : 0} step={this.state.currentSelected} stepIntoBack={this.stepIntoBack}
|
||||
stepIntoForward={this.stepIntoForward} stepOverBack={this.stepOverBack} stepOverForward={this.stepOverForward} /> |
||||
</div> |
||||
<div style={style.container}> |
||||
<table> |
||||
<tbody> |
||||
<tr> |
||||
<td> |
||||
<select size="10" ref='itemsList' style={style.instructionsList} value={this.state.selectedInst}> |
||||
{ this.renderAssemblyItems() } |
||||
</select> |
||||
<div style={Object.assign(style.inline, style.sticker)}> |
||||
<Sticker data={this.state.currentStepInfo} /> |
||||
</div> |
||||
</td> |
||||
<td> |
||||
<BasicPanel name="CallData" data={this.state.currentCallData} /> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<BasicPanel name="Stack" data={this.state.currentStack} /> |
||||
</td> |
||||
<td> |
||||
<BasicPanel name="CallStack" data={this.state.currentCallStack} />
|
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<BasicPanel name="Storage" data={this.state.currentStorage} renderRow={this.renderStorageRow} /> |
||||
</td> |
||||
<td> |
||||
<BasicPanel name="Memory" data={this.state.currentMemory} renderRow={this.renderMemoryRow} /> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
); |
||||
}, |
||||
|
||||
renderStorageRow: function(data) |
||||
{ |
||||
var ret = [] |
||||
if (data) |
||||
{ |
||||
for (var key in data) |
||||
ret.push(<tr key={key} ><td>{key}</td><td>{data[key]}</td></tr>) |
||||
} |
||||
return ret |
||||
}, |
||||
|
||||
renderMemoryRow: function(data) |
||||
{ |
||||
var ret = [] |
||||
if (data) |
||||
{ |
||||
for (var key in data) |
||||
{ |
||||
var memSlot = data[key] |
||||
ret.push(<tr key={key} ><td>{memSlot.address}</td><td>{memSlot.content.raw}</td><td>{memSlot.content.ascii}</td></tr>) |
||||
} |
||||
} |
||||
return ret |
||||
}, |
||||
|
||||
resolveAddress: function(address) |
||||
{ |
||||
if (!this.state.codes[address]) |
||||
{ |
||||
var hexCode = web3.eth.getCode(address)
|
||||
var code = codeUtils.nameOpCodes(new Buffer(hexCode.substring(2), 'hex')) |
||||
this.state.codes[address] = code[0] |
||||
this.state.instructionsIndexByBytesOffset[address] = code[1] |
||||
} |
||||
},
|
||||
|
||||
renderAssemblyItems: function() |
||||
{ |
||||
if (this.props.vmTrace) |
||||
{ |
||||
return this.state.codes[this.state.currentAddress].map(function(item, i)
|
||||
{ |
||||
return <option key={i} value={i} >{item}</option>; |
||||
});
|
||||
} |
||||
}, |
||||
|
||||
componentWillReceiveProps: function (nextProps)
|
||||
{
|
||||
if (!nextProps.vmTrace) |
||||
return |
||||
this.buildCallStack(nextProps.vmTrace) |
||||
this.setState({"currentSelected": -1}) |
||||
this.updateState(nextProps, 0) |
||||
}, |
||||
|
||||
buildCallStack: function(vmTrace) |
||||
{ |
||||
if (!vmTrace) |
||||
return |
||||
var callStack = [] |
||||
var depth = -1 |
||||
for (var k = 0; k < vmTrace.length; k++) |
||||
{ |
||||
var trace = vmTrace[k] |
||||
if (trace.depth === undefined || trace.depth === depth) |
||||
continue |
||||
if (trace.depth > depth) |
||||
callStack.push(trace.address) // new context
|
||||
else if (trace.depth < depth) |
||||
callStack.pop() // returning from context
|
||||
depth = trace.depth |
||||
this.state.callStack[k] = callStack.slice(0) |
||||
} |
||||
}, |
||||
|
||||
updateState: function(props, vmTraceIndex) |
||||
{ |
||||
if (!props.vmTrace || !props.vmTrace[vmTraceIndex]) |
||||
return |
||||
var previousIndex = this.state.currentSelected |
||||
var stateChanges = {} |
||||
|
||||
if (props.vmTrace[vmTraceIndex].stack) // there's always a stack
|
||||
{ |
||||
var stack = props.vmTrace[vmTraceIndex].stack |
||||
stack.reverse() |
||||
stateChanges["currentStack"] = stack |
||||
} |
||||
|
||||
var currentAddress = this.state.currentAddress |
||||
var addressIndex = this.shouldUpdateStateProperty("address", vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (addressIndex > -1) |
||||
{ |
||||
currentAddress = props.vmTrace[addressIndex].address |
||||
this.resolveAddress(currentAddress) |
||||
Object.assign(stateChanges, { "currentAddress": currentAddress }) |
||||
} |
||||
|
||||
var depthIndex = this.shouldUpdateStateProperty("depth", vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (depthIndex > -1) |
||||
Object.assign(stateChanges, { "currentCallStack": this.state.callStack[depthIndex] }) |
||||
|
||||
var storageIndex = this.shouldUpdateStateProperty("storage", vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (storageIndex > -1) |
||||
Object.assign(stateChanges, { "currentStorage": props.vmTrace[storageIndex].storage }) |
||||
|
||||
var memoryIndex = this.shouldUpdateStateProperty("memory", vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (memoryIndex > -1) |
||||
Object.assign(stateChanges, { "currentMemory": this.formatMemory(props.vmTrace[memoryIndex].memory, 16) }) |
||||
|
||||
var callDataIndex = this.shouldUpdateStateProperty("calldata", vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (callDataIndex > -1) |
||||
Object.assign(stateChanges, { "currentCallData": [props.vmTrace[callDataIndex].calldata] }) |
||||
|
||||
stateChanges["selectedInst"] = this.state.instructionsIndexByBytesOffset[currentAddress][props.vmTrace[vmTraceIndex].pc] |
||||
stateChanges["currentSelected"] = vmTraceIndex |
||||
|
||||
stateChanges["currentStepInfo"] = [ |
||||
"Current Step: " + props.vmTrace[vmTraceIndex].steps, |
||||
"Adding Memory: " + (props.vmTrace[vmTraceIndex].memexpand ? props.vmTrace[vmTraceIndex].memexpand : ""), |
||||
"Step Cost: " + props.vmTrace[vmTraceIndex].gascost, |
||||
"Remaining Gas: " + props.vmTrace[vmTraceIndex].gas |
||||
] |
||||
this.refs.slider.setValue(vmTraceIndex) |
||||
this.setState(stateChanges) |
||||
}, |
||||
|
||||
shouldUpdateStateProperty: function(vmTraceName, nextIndex, previousIndex, vmTrace) |
||||
{ |
||||
var propIndex = -1 |
||||
if (previousIndex + 1 === nextIndex) |
||||
propIndex = nextIndex |
||||
else |
||||
propIndex = this.retrieveLastSeenProperty(nextIndex, vmTraceName, vmTrace) |
||||
|
||||
if (propIndex > -1 && vmTrace[propIndex][vmTraceName] !== undefined) |
||||
return propIndex |
||||
else |
||||
return -1 |
||||
}, |
||||
|
||||
retrieveLastSeenProperty: function(currentIndex, propertyName, vmTrace) |
||||
{ |
||||
var index = currentIndex |
||||
while (index > 0) |
||||
{ |
||||
if (vmTrace[index][propertyName]) |
||||
break |
||||
index-- |
||||
} |
||||
return index
|
||||
}, |
||||
|
||||
stepIntoBack: function() |
||||
{ |
||||
this.moveSelection(-1) |
||||
}, |
||||
|
||||
stepIntoForward: function() |
||||
{ |
||||
this.moveSelection(1) |
||||
}, |
||||
|
||||
stepOverBack: function() |
||||
{ |
||||
if (this.isReturnInstruction(this.state.currentSelected - 1)) |
||||
this.stepOutBack(); |
||||
else |
||||
this.moveSelection(-1); |
||||
}, |
||||
|
||||
stepOverForward: function() |
||||
{ |
||||
if (this.isCallInstruction(this.state.currentSelected)) |
||||
this.stepOutForward(); |
||||
else |
||||
this.moveSelection(1); |
||||
}, |
||||
|
||||
isCallInstruction: function(index) |
||||
{ |
||||
var state = this.props.vmTrace[index]; |
||||
return state.instname === "CALL" || state.instname === "CALLCODE" || state.instname === "CREATE" || state.instname === "DELEGATECALL" |
||||
}, |
||||
|
||||
isReturnInstruction: function(index) |
||||
{ |
||||
var state = this.props.vmTrace[index]; |
||||
return state.instname === "RETURN" |
||||
}, |
||||
|
||||
stepOutBack: function() |
||||
{ |
||||
var i = this.state.currentSelected - 1; |
||||
var depth = 0; |
||||
while (--i >= 0)
|
||||
{ |
||||
if (this.isCallInstruction(i)) |
||||
{ |
||||
if (depth == 0) |
||||
break; |
||||
else |
||||
depth--; |
||||
} |
||||
else if (this.isReturnInstruction(i)) |
||||
depth++; |
||||
|
||||
} |
||||
this.selectState(i); |
||||
}, |
||||
|
||||
stepOutForward: function() |
||||
{ |
||||
var i = this.state.currentSelected |
||||
var depth = 0 |
||||
while (++i < this.props.vmTrace.length)
|
||||
{ |
||||
if (this.isReturnInstruction(i)) |
||||
{ |
||||
if (depth == 0) |
||||
break |
||||
else |
||||
depth-- |
||||
} |
||||
else if (this.isCallInstruction(i)) |
||||
depth++ |
||||
} |
||||
this.selectState(i + 1); |
||||
}, |
||||
|
||||
moveSelection: function(incr) |
||||
{ |
||||
this.selectState(this.state.currentSelected + incr) |
||||
}, |
||||
|
||||
selectState: function(index) |
||||
{ |
||||
this.updateState(this.props, index) |
||||
}, |
||||
|
||||
formatMemory: function(mem, width) |
||||
{ |
||||
var ret = [] |
||||
for (var k = 0; k < mem.length; k += (width * 2)) |
||||
{ |
||||
var memory = mem.substr(k, width * 2) |
||||
ret.push({ |
||||
address: web3.toHex(k), |
||||
content: this.tryAsciiFormat(memory) |
||||
}) |
||||
} |
||||
return ret |
||||
}, |
||||
|
||||
tryAsciiFormat: function(memorySlot) |
||||
{ |
||||
var ret = { ascii: "", raw: "" } |
||||
for (var k = 0; k < memorySlot.length; k += 2) |
||||
{ |
||||
var raw = memorySlot.substr(k, 2) |
||||
var ascii = web3.toAscii(raw) |
||||
if (ascii === String.fromCharCode(0)) |
||||
ret.ascii += "?" |
||||
else |
||||
ret.ascii += ascii |
||||
ret.raw += " " + raw |
||||
} |
||||
return ret |
||||
} |
||||
getInitialState: function () { |
||||
return { |
||||
currentSelected: -1, // current selected item in the vmTrace
|
||||
selectedInst: -1, // current selected item in the contract assembly code
|
||||
currentAddress: null, |
||||
currentStack: null, |
||||
currentLevels: null, |
||||
currentStorage: null, |
||||
currentMemory: null, |
||||
currentCallData: null, |
||||
currentStepInfo: null, |
||||
codes: {}, // assembly items instructions list by contract addesses
|
||||
instructionsIndexByBytesOffset: {}, // mapping between bytes offset and instructions index.
|
||||
callStack: {} |
||||
} |
||||
}, |
||||
|
||||
getDefaultProps: function () { |
||||
return { |
||||
vmTrace: null |
||||
} |
||||
}, |
||||
|
||||
render: function () { |
||||
return ( |
||||
<div style={this.props.vmTrace === null ? style.hidden : style.display}> |
||||
<div style={style.container}> |
||||
<span style={style.address}>Current code: {this.state.currentAddress}</span> |
||||
</div> |
||||
<div style={style.container}> |
||||
<Slider |
||||
ref='slider' |
||||
onChange={this.selectState} |
||||
min='0' |
||||
max={this.props.vmTrace ? this.props.vmTrace.length : 0} /> |
||||
<ButtonNavigator |
||||
vmTraceLength={this.props.vmTrace ? this.props.vmTrace.length : 0} |
||||
step={this.state.currentSelected} |
||||
stepIntoBack={this.stepIntoBack} |
||||
stepIntoForward={this.stepIntoForward} |
||||
stepOverBack={this.stepOverBack} |
||||
stepOverForward={this.stepOverForward} /> |
||||
</div> |
||||
<div style={style.container}> |
||||
<table> |
||||
<tbody> |
||||
<tr> |
||||
<td> |
||||
<select |
||||
size='10' |
||||
ref='itemsList' |
||||
style={style.instructionsList} |
||||
value={this.state.selectedInst}> |
||||
{this.renderAssemblyItems()} |
||||
</select> |
||||
<div style={Object.assign(style.inline, style.sticker)}> |
||||
<Sticker data={this.state.currentStepInfo} /> |
||||
</div> |
||||
</td> |
||||
<td> |
||||
<BasicPanel name='CallData' data={this.state.currentCallData} /> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<BasicPanel name='Stack' data={this.state.currentStack} /> |
||||
</td> |
||||
<td> |
||||
<BasicPanel name='CallStack' data={this.state.currentCallStack} /> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<BasicPanel name='Storage' data={this.state.currentStorage} renderRow={this.renderStorageRow} /> |
||||
</td> |
||||
<td> |
||||
<BasicPanel name='Memory' data={this.state.currentMemory} renderRow={this.renderMemoryRow} /> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
) |
||||
}, |
||||
|
||||
renderStorageRow: function (data) { |
||||
var ret = [] |
||||
if (data) { |
||||
for (var key in data) { |
||||
ret.push( |
||||
<tr key={key}> |
||||
<td> |
||||
{key} |
||||
</td> |
||||
<td> |
||||
{data[key]} |
||||
</td> |
||||
</tr>) |
||||
} |
||||
} |
||||
return ret |
||||
}, |
||||
|
||||
renderMemoryRow: function (data) { |
||||
var ret = [] |
||||
if (data) { |
||||
for (var key in data) { |
||||
var memSlot = data[key] |
||||
ret.push( |
||||
<tr key={key}> |
||||
<td> |
||||
{memSlot.address} |
||||
</td> |
||||
<td> |
||||
{memSlot.content.raw} |
||||
</td> |
||||
<td> |
||||
{memSlot.content.ascii} |
||||
</td> |
||||
</tr>) |
||||
} |
||||
} |
||||
return ret |
||||
}, |
||||
|
||||
resolveAddress: function (address) { |
||||
if (!this.state.codes[address]) { |
||||
var hexCode = this.context.web3.eth.getCode(address) |
||||
var code = codeUtils.nameOpCodes(new Buffer(hexCode.substring(2), 'hex')) |
||||
this.state.codes[address] = code[0] |
||||
this.state.instructionsIndexByBytesOffset[address] = code[1] |
||||
} |
||||
}, |
||||
|
||||
renderAssemblyItems: function () { |
||||
if (this.props.vmTrace) { |
||||
return this.state.codes[this.state.currentAddress].map(function (item, i) { |
||||
return <option key={i} value={i}>{item}</option> |
||||
}) |
||||
} |
||||
}, |
||||
|
||||
componentWillReceiveProps: function (nextProps) { |
||||
if (!nextProps.vmTrace) { |
||||
return |
||||
} |
||||
this.buildCallStack(nextProps.vmTrace) |
||||
this.setState({'currentSelected': -1}) |
||||
this.updateState(nextProps, 0) |
||||
}, |
||||
|
||||
buildCallStack: function (vmTrace) { |
||||
if (!vmTrace) { |
||||
return |
||||
} |
||||
var callStack = [] |
||||
var depth = -1 |
||||
for (var k = 0; k < vmTrace.length; k++) { |
||||
var trace = vmTrace[k] |
||||
if (trace.depth === undefined || trace.depth === depth) { |
||||
continue |
||||
} |
||||
if (trace.depth > depth) { |
||||
callStack.push(trace.address) // new context
|
||||
} else if (trace.depth < depth) { |
||||
callStack.pop() // returning from context
|
||||
} |
||||
depth = trace.depth |
||||
this.state.callStack[k] = callStack.slice(0) |
||||
} |
||||
}, |
||||
|
||||
updateState: function (props, vmTraceIndex) { |
||||
if (!props.vmTrace || !props.vmTrace[vmTraceIndex]) { |
||||
return |
||||
} |
||||
var previousIndex = this.state.currentSelected |
||||
var stateChanges = {} |
||||
|
||||
if (props.vmTrace[vmTraceIndex].stack) { // there's always a stack
|
||||
var stack = props.vmTrace[vmTraceIndex].stack |
||||
stack.reverse() |
||||
stateChanges['currentStack'] = stack |
||||
} |
||||
|
||||
var currentAddress = this.state.currentAddress |
||||
var addressIndex = this.shouldUpdateStateProperty('address', vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (addressIndex > -1) { |
||||
currentAddress = props.vmTrace[addressIndex].address |
||||
this.resolveAddress(currentAddress) |
||||
Object.assign(stateChanges, { 'currentAddress': currentAddress }) |
||||
} |
||||
|
||||
var depthIndex = this.shouldUpdateStateProperty('depth', vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (depthIndex > -1) { |
||||
Object.assign(stateChanges, { 'currentCallStack': this.state.callStack[depthIndex] }) |
||||
} |
||||
|
||||
var storageIndex = this.shouldUpdateStateProperty('storage', vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (storageIndex > -1) { |
||||
Object.assign(stateChanges, { 'currentStorage': props.vmTrace[storageIndex].storage }) |
||||
} |
||||
|
||||
var memoryIndex = this.shouldUpdateStateProperty('memory', vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (memoryIndex > -1) { |
||||
Object.assign(stateChanges, { 'currentMemory': this.formatMemory(props.vmTrace[memoryIndex].memory, 16) }) |
||||
} |
||||
|
||||
var callDataIndex = this.shouldUpdateStateProperty('calldata', vmTraceIndex, previousIndex, props.vmTrace) |
||||
if (callDataIndex > -1) { |
||||
Object.assign(stateChanges, { 'currentCallData': [props.vmTrace[callDataIndex].calldata] }) |
||||
} |
||||
|
||||
stateChanges['selectedInst'] = this.state.instructionsIndexByBytesOffset[currentAddress][props.vmTrace[vmTraceIndex].pc] |
||||
stateChanges['currentSelected'] = vmTraceIndex |
||||
|
||||
stateChanges['currentStepInfo'] = [ |
||||
'Current Step: ' + props.vmTrace[vmTraceIndex].steps, |
||||
'Adding Memory: ' + (props.vmTrace[vmTraceIndex].memexpand ? props.vmTrace[vmTraceIndex].memexpand : ''), |
||||
'Step Cost: ' + props.vmTrace[vmTraceIndex].gascost, |
||||
'Remaining Gas: ' + props.vmTrace[vmTraceIndex].gas |
||||
] |
||||
this.refs.slider.setValue(vmTraceIndex) |
||||
this.setState(stateChanges) |
||||
}, |
||||
|
||||
shouldUpdateStateProperty: function (vmTraceName, nextIndex, previousIndex, vmTrace) { |
||||
var propIndex = -1 |
||||
if (previousIndex + 1 === nextIndex) { |
||||
propIndex = nextIndex |
||||
} else { |
||||
propIndex = this.retrieveLastSeenProperty(nextIndex, vmTraceName, vmTrace) |
||||
} |
||||
|
||||
if (propIndex > -1 && vmTrace[propIndex][vmTraceName] !== undefined) { |
||||
return propIndex |
||||
} else { |
||||
return -1 |
||||
} |
||||
}, |
||||
|
||||
retrieveLastSeenProperty: function (currentIndex, propertyName, vmTrace) { |
||||
var index = currentIndex |
||||
while (index > 0) { |
||||
if (vmTrace[index][propertyName]) { |
||||
break |
||||
} |
||||
index-- |
||||
} |
||||
return index |
||||
}, |
||||
|
||||
stepIntoBack: function () { |
||||
this.moveSelection(-1) |
||||
}, |
||||
|
||||
stepIntoForward: function () { |
||||
this.moveSelection(1) |
||||
}, |
||||
|
||||
stepOverBack: function () { |
||||
if (this.isReturnInstruction(this.state.currentSelected - 1)) { |
||||
this.stepOutBack() |
||||
} else { |
||||
this.moveSelection(-1) |
||||
} |
||||
}, |
||||
|
||||
stepOverForward: function () { |
||||
if (this.isCallInstruction(this.state.currentSelected)) { |
||||
this.stepOutForward() |
||||
} else { |
||||
this.moveSelection(1) |
||||
} |
||||
}, |
||||
|
||||
isCallInstruction: function (index) { |
||||
var state = this.props.vmTrace[index] |
||||
return state.instname === 'CALL' || state.instname === 'CALLCODE' || state.instname === 'CREATE' || state.instname === 'DELEGATECALL' |
||||
}, |
||||
|
||||
isReturnInstruction: function (index) { |
||||
var state = this.props.vmTrace[index] |
||||
return state.instname === 'RETURN' |
||||
}, |
||||
|
||||
stepOutBack: function () { |
||||
var i = this.state.currentSelected - 1 |
||||
var depth = 0 |
||||
while (--i >= 0) { |
||||
if (this.isCallInstruction(i)) { |
||||
if (depth === 0) { |
||||
break |
||||
} else { |
||||
depth-- |
||||
} |
||||
} else if (this.isReturnInstruction(i)) { |
||||
depth++ |
||||
} |
||||
} |
||||
this.selectState(i) |
||||
}, |
||||
|
||||
stepOutForward: function () { |
||||
var i = this.state.currentSelected |
||||
var depth = 0 |
||||
while (++i < this.props.vmTrace.length) { |
||||
if (this.isReturnInstruction(i)) { |
||||
if (depth === 0) { |
||||
break |
||||
} else { |
||||
depth-- |
||||
} |
||||
} else if (this.isCallInstruction(i)) { |
||||
depth++ |
||||
} |
||||
} |
||||
this.selectState(i + 1) |
||||
}, |
||||
|
||||
moveSelection: function (incr) { |
||||
this.selectState(this.state.currentSelected + incr) |
||||
}, |
||||
|
||||
selectState: function (index) { |
||||
this.updateState(this.props, index) |
||||
}, |
||||
|
||||
formatMemory: function (mem, width) { |
||||
var ret = [] |
||||
for (var k = 0; k < mem.length; k += (width * 2)) { |
||||
var memory = mem.substr(k, width * 2) |
||||
ret.push({ |
||||
address: this.context.web3.toHex(k), |
||||
content: this.tryAsciiFormat(memory) |
||||
}) |
||||
} |
||||
return ret |
||||
}, |
||||
|
||||
tryAsciiFormat: function (memorySlot) { |
||||
var ret = { ascii: '', raw: '' } |
||||
for (var k = 0; k < memorySlot.length; k += 2) { |
||||
var raw = memorySlot.substr(k, 2) |
||||
var ascii = this.context.web3.toAscii(raw) |
||||
if (ascii === String.fromCharCode(0)) { |
||||
ret.ascii += '?' |
||||
} else { |
||||
ret.ascii += ascii |
||||
} |
||||
ret.raw += ' ' + raw |
||||
} |
||||
return ret |
||||
} |
||||
}) |
||||
|
@ -1,45 +1,50 @@ |
||||
var React = require('react'); |
||||
'use strict' |
||||
var React = require('react') |
||||
var style = require('./basicStyles') |
||||
|
||||
module.exports = React.createClass({ |
||||
getDefaultProps: function () { |
||||
return { |
||||
data: null, |
||||
name: null, |
||||
renderRow: null |
||||
} |
||||
}, |
||||
|
||||
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> |
||||
) |
||||
}, |
||||
|
||||
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)
|
||||
}
|
||||
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) |
||||
} |
||||
} |
||||
}) |
||||
|
@ -1,62 +1,49 @@ |
||||
'use strict' |
||||
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' |
||||
} |
||||
} |
||||
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' |
||||
} |
||||
} |
||||
|
@ -1,43 +1,40 @@ |
||||
'use strict' |
||||
var opcodes = require('./opcodes') |
||||
|
||||
module.exports = { |
||||
nameOpCodes: function (raw) { |
||||
var pushData = '' |
||||
var codeMap = {} |
||||
var code = [] |
||||
|
||||
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 |
||||
} |
||||
|
||||
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 ] |
||||
}, |
||||
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 |
||||
}, |
||||
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) |
||||
}, |
||||
log: function (num, base) { |
||||
return Math.log(num) / Math.log(base) |
||||
}, |
||||
|
||||
roundLog: function (num, base) { |
||||
return Math.ceil(this.log(num, base)) |
||||
} |
||||
} |
||||
roundLog: function (num, base) { |
||||
return Math.ceil(this.log(num, base)) |
||||
} |
||||
} |
||||
|
@ -1,32 +1,44 @@ |
||||
var React = require('react'); |
||||
var TxBrowser = require('./txBrowser'); |
||||
var VmTraceManager = require('./vmTraceManager'); |
||||
var VmTraceBrowser = require('./vmTraceBrowser'); |
||||
'use strict' |
||||
var React = require('react') |
||||
var TxBrowser = require('./txBrowser') |
||||
var VmTraceBrowser = require('./vmTraceBrowser') |
||||
var style = require('./basicStyles') |
||||
|
||||
module.exports = React.createClass({ |
||||
getInitialState: function() { |
||||
return {vmTrace: null, state: "", currentStep: -1} |
||||
}, |
||||
getInitialState: function () { |
||||
return {vmTrace: null, state: '', currentStep: -1} |
||||
}, |
||||
|
||||
render: function() { |
||||
return ( |
||||
<div style={style.wrapper} > |
||||
<h1 style={style.container} >Eth Debugger</h1> |
||||
<TxBrowser onNewTxRequested={this.retrieveVmTrace} /> |
||||
<div style={style.container} >{this.state.state}</div> |
||||
<VmTraceBrowser vmTrace={this.state.vmTrace} /> |
||||
</div> |
||||
); |
||||
}, |
||||
childContextTypes: { |
||||
web3: React.PropTypes.object |
||||
}, |
||||
|
||||
retrieveVmTrace: function(blockNumber, txNumber) |
||||
{ |
||||
this.setState({state: "loading..."}) |
||||
var deb = this |
||||
VmTraceManager.retrieveVmTrace(blockNumber, txNumber, function(error, result) |
||||
{ |
||||
deb.setState({vmTrace: result, state: ""}); |
||||
}) |
||||
} |
||||
}); |
||||
getChildContext: function () { |
||||
return { web3: this.props.web3 } |
||||
}, |
||||
|
||||
render: function () { |
||||
return ( |
||||
<div style={style.wrapper}> |
||||
<h1 style={style.container}>Eth Debugger</h1> |
||||
<TxBrowser onNewTxRequested={this.retrieveVmTrace} /> |
||||
<div style={style.container}> |
||||
{this.state.state} |
||||
</div> |
||||
<VmTraceBrowser vmTrace={this.state.vmTrace} /> |
||||
</div> |
||||
) |
||||
}, |
||||
|
||||
retrieveVmTrace: function (blockNumber, txNumber) { |
||||
this.setState({state: 'loading...'}) |
||||
var self = this |
||||
this.props.web3.debug.trace(blockNumber, parseInt(txNumber), function (error, result) { |
||||
if (error) { |
||||
console.log(error) |
||||
} else { |
||||
self.setState({vmTrace: result, state: ''}) |
||||
} |
||||
}) |
||||
} |
||||
}) |
||||
|
@ -1,15 +1,19 @@ |
||||
var ReactDOM = require('react-dom'); |
||||
var React = require('react'); |
||||
var Web3 = require('web3'); |
||||
'use strict' |
||||
var ReactDOM = require('react-dom') |
||||
var React = require('react') |
||||
var Web3 = require('web3') |
||||
var Web3Admin = require('./web3Admin') |
||||
|
||||
web3 = new Web3(); |
||||
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); |
||||
Web3Admin.extend(web3); |
||||
function loadWeb3 () { |
||||
var web3 = new Web3() |
||||
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')) |
||||
Web3Admin.extend(web3) |
||||
return web3 |
||||
} |
||||
|
||||
var Debugger = require('./debugger'); |
||||
var Debugger = require('./debugger') |
||||
|
||||
ReactDOM.render( |
||||
<Debugger/>, |
||||
document.getElementById('app') |
||||
); |
||||
<Debugger web3={loadWeb3()} />, |
||||
document.getElementById('app') |
||||
) |
||||
|
@ -1,36 +1,43 @@ |
||||
var React = require('react'); |
||||
'use strict' |
||||
var React = require('react') |
||||
var style = require('./sliderStyles') |
||||
|
||||
module.exports = React.createClass({ |
||||
propTypes: { |
||||
onChange: React.PropTypes.func.isRequired |
||||
}, |
||||
|
||||
propTypes: { |
||||
onChange: React.PropTypes.func.isRequired, |
||||
}, |
||||
|
||||
getDefaultProps: function () { |
||||
return { |
||||
min: 0, |
||||
max: 500 |
||||
}; |
||||
}, |
||||
getDefaultProps: function () { |
||||
return { |
||||
min: 0, |
||||
max: 500 |
||||
} |
||||
}, |
||||
|
||||
render: function () { |
||||
return ( |
||||
<div> |
||||
<input ref="rule" style={style.rule} type="range" min={this.props.min} max={this.props.max} onMouseUp={this.onMouseUp} /> |
||||
</div> |
||||
); |
||||
}, |
||||
render: function () { |
||||
return ( |
||||
<div> |
||||
<input |
||||
ref='rule' |
||||
style={style.rule} |
||||
type='range' |
||||
min={this.props.min} |
||||
max={this.props.max} |
||||
onMouseUp={this.onMouseUp} /> |
||||
</div> |
||||
) |
||||
}, |
||||
|
||||
onMouseUp: function (event) { |
||||
this.props.onChange(parseInt(this.refs.rule.value)) |
||||
}, |
||||
onMouseUp: function (event) { |
||||
this.props.onChange(parseInt(this.refs.rule.value)) |
||||
}, |
||||
|
||||
setValue: function (value) { |
||||
var diff = value - this.refs.rule.value |
||||
if (diff > 0) |
||||
this.refs.rule.stepUp(diff) |
||||
else |
||||
this.refs.rule.stepDown(Math.abs(diff)) |
||||
setValue: function (value) { |
||||
var diff = value - this.refs.rule.value |
||||
if (diff > 0) { |
||||
this.refs.rule.stepUp(diff) |
||||
} else { |
||||
this.refs.rule.stepDown(Math.abs(diff)) |
||||
} |
||||
} |
||||
}) |
||||
|
@ -1,17 +1,16 @@ |
||||
'use strict' |
||||
module.exports = { |
||||
rule: |
||||
{ |
||||
'width': '600px', |
||||
},
|
||||
runner: |
||||
{ |
||||
'position': 'absolute', |
||||
'width': '16px', |
||||
'height': '16px', |
||||
'margin': '0', |
||||
'padding': '0', |
||||
'overflow': 'hidden', |
||||
'border': '1px solid #a4bed4', |
||||
'background-color': '#f1f7ff' |
||||
} |
||||
} |
||||
rule: { |
||||
'width': '600px' |
||||
}, |
||||
runner: { |
||||
'position': 'absolute', |
||||
'width': '16px', |
||||
'height': '16px', |
||||
'margin': '0', |
||||
'padding': '0', |
||||
'overflow': 'hidden', |
||||
'border': '1px solid #a4bed4', |
||||
'background-color': '#f1f7ff' |
||||
} |
||||
} |
||||
|
@ -1,36 +1,38 @@ |
||||
var React = require('react'); |
||||
var style = require('./basicStyles') |
||||
'use strict' |
||||
var React = require('react') |
||||
|
||||
module.exports = React.createClass({ |
||||
getDefaultProps: function () { |
||||
return { |
||||
data: null |
||||
} |
||||
}, |
||||
|
||||
getDefaultProps: function()
|
||||
{ |
||||
return { |
||||
data: null, |
||||
}; |
||||
}, |
||||
render: function () { |
||||
return ( |
||||
<div> |
||||
<table> |
||||
<tbody> |
||||
{this.renderItems()} |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
) |
||||
}, |
||||
|
||||
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 |
||||
}, |
||||
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 |
||||
} |
||||
}) |
||||
|
@ -1,43 +1,59 @@ |
||||
var React = require('react'); |
||||
'use strict' |
||||
var React = require('react') |
||||
var style = require('./basicStyles') |
||||
|
||||
module.exports = React.createClass({ |
||||
propTypes: { |
||||
onNewTxRequested: React.PropTypes.func.isRequired, |
||||
}, |
||||
contextTypes: { |
||||
web3: React.PropTypes.object |
||||
}, |
||||
|
||||
getInitialState: function() { |
||||
return {blockNumber: "1382256", txNumber: "1", from: "", to: "", hash: ""} |
||||
}, |
||||
propTypes: { |
||||
onNewTxRequested: React.PropTypes.func.isRequired |
||||
}, |
||||
|
||||
submit: function() |
||||
{ |
||||
var tx = web3.eth.getTransactionFromBlock(this.state.blockNumber, this.state.txNumber) |
||||
if (tx) |
||||
this.setState({from: tx.from, to: tx.to, hash: tx.hash}) |
||||
this.props.onNewTxRequested(this.state.blockNumber, parseInt(this.state.txNumber)) |
||||
}, |
||||
|
||||
updateBlockN: function(ev) { |
||||
this.state.blockNumber = ev.target.value; |
||||
}, |
||||
|
||||
updateTxN: function(ev) { |
||||
this.state.txNumber = ev.target.value; |
||||
}, |
||||
getInitialState: function () { |
||||
return {blockNumber: '1382256', txNumber: '1', from: '', to: '', hash: ''} |
||||
}, |
||||
|
||||
render: function() {
|
||||
return ( |
||||
<div style={style.container} > |
||||
<input onChange={this.updateBlockN} type="text" placeholder= {"Block number or hash (default 1382256)" + this.state.blockNumber}></input> |
||||
<input onChange={this.updateTxN} type="text" placeholder={"Transaction Number (default 1) " + this.state.txNumber}></input> |
||||
<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> |
||||
); |
||||
} |
||||
submit: function () { |
||||
var tx = this.context.web3.eth.getTransactionFromBlock(this.state.blockNumber, this.state.txNumber) |
||||
if (tx) { |
||||
this.setState({from: tx.from, to: tx.to, hash: tx.hash}) |
||||
} |
||||
this.props.onNewTxRequested(this.state.blockNumber, parseInt(this.state.txNumber)) |
||||
} |
||||
|
||||
updateBlockN: function (ev) { |
||||
this.state.blockNumber = ev.target.value |
||||
}, |
||||
|
||||
updateTxN: function (ev) { |
||||
this.state.txNumber = ev.target.value |
||||
}, |
||||
|
||||
render: function () { |
||||
return ( |
||||
<div style={style.container}> |
||||
<input onChange={this.updateBlockN} type='text' placeholder={'Block number or hash (default 1382256)' + this.state.blockNumber}></input> |
||||
<input onChange={this.updateTxN} type='text' placeholder={'Transaction Number (default 1) ' + this.state.txNumber}></input> |
||||
<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> |
||||
) |
||||
} |
||||
}) |
||||
|
@ -1,13 +1,13 @@ |
||||
var React = require('react'); |
||||
var AssemblyItemsBrowser = require('./assemblyItemsBrowser'); |
||||
'use strict' |
||||
var React = require('react') |
||||
var AssemblyItemsBrowser = require('./assemblyItemsBrowser') |
||||
|
||||
module.exports = React.createClass({ |
||||
|
||||
render: function() { |
||||
return (
|
||||
<div>
|
||||
<AssemblyItemsBrowser vmTrace={this.props.vmTrace} />
|
||||
</div> |
||||
) |
||||
}, |
||||
}); |
||||
render: function () { |
||||
return ( |
||||
<div> |
||||
<AssemblyItemsBrowser vmTrace={this.props.vmTrace} /> |
||||
</div> |
||||
) |
||||
} |
||||
}) |
||||
|
@ -1,30 +1,38 @@ |
||||
var React = require('react'); |
||||
'use strict' |
||||
var React = require('react') |
||||
|
||||
module.exports = React.createClass({ |
||||
|
||||
propTypes: { |
||||
stepIntoBack: React.PropTypes.func.isRequired, |
||||
stepIntoForward: React.PropTypes.func.isRequired, |
||||
stepOverBack: React.PropTypes.func.isRequired, |
||||
stepOverForward: React.PropTypes.func.isRequired, |
||||
}, |
||||
|
||||
render: function() {
|
||||
return ( |
||||
<div> |
||||
<button onClick={this.props.stepIntoBack} disabled={this.checkButtonState(-1)} >Step Into Back</button> |
||||
<button onClick={this.props.stepOverBack} disabled={this.checkButtonState(-1)} >Step Over Back</button> |
||||
<button onClick={this.props.stepOverForward} disabled={this.checkButtonState(1)} >Step Over Forward</button> |
||||
<button onClick={this.props.stepIntoForward} disabled={this.checkButtonState(1)} >Step Into Forward</button> |
||||
</div> |
||||
); |
||||
}, |
||||
|
||||
checkButtonState: function(incr) |
||||
{ |
||||
if (incr === -1) |
||||
return this.props.step === 0 ? "disabled" : "" |
||||
else if (incr === 1) |
||||
return this.props.step >= this.props.vmTraceLength - 1 ? "disabled" : ""
|
||||
}, |
||||
}) |
||||
propTypes: { |
||||
stepIntoBack: React.PropTypes.func.isRequired, |
||||
stepIntoForward: React.PropTypes.func.isRequired, |
||||
stepOverBack: React.PropTypes.func.isRequired, |
||||
stepOverForward: React.PropTypes.func.isRequired |
||||
}, |
||||
|
||||
render: function () { |
||||
return ( |
||||
<div> |
||||
<button onClick={this.props.stepIntoBack} disabled={this.checkButtonState(-1)}> |
||||
Step Into Back |
||||
</button> |
||||
<button onClick={this.props.stepOverBack} disabled={this.checkButtonState(-1)}> |
||||
Step Over Back |
||||
</button> |
||||
<button onClick={this.props.stepOverForward} disabled={this.checkButtonState(1)}> |
||||
Step Over Forward |
||||
</button> |
||||
<button onClick={this.props.stepIntoForward} disabled={this.checkButtonState(1)}> |
||||
Step Into Forward |
||||
</button> |
||||
</div> |
||||
) |
||||
}, |
||||
|
||||
checkButtonState: function (incr) { |
||||
if (incr === -1) { |
||||
return this.props.step === 0 ? 'disabled' : '' |
||||
} else if (incr === 1) { |
||||
return this.props.step >= this.props.vmTraceLength - 1 ? 'disabled' : '' |
||||
} |
||||
} |
||||
}) |
||||
|
@ -1,8 +1,8 @@ |
||||
'use strict' |
||||
module.exports = { |
||||
retrieveVmTrace: function(blockNumber, txNumber, callBack) { |
||||
web3.debug.trace(blockNumber, parseInt(txNumber), function(error, result) |
||||
{ |
||||
callBack(error, result) |
||||
}); |
||||
} |
||||
retrieveVmTrace: function (blockNumber, txNumber, callBack) { |
||||
this.context.web3.debug.trace(blockNumber, parseInt(txNumber), function (error, result) { |
||||
callBack(error, result) |
||||
}) |
||||
} |
||||
} |
||||
|
@ -1,277 +1,263 @@ |
||||
'use strict' |
||||
module.exports = { |
||||
extend: function(web3) { |
||||
extend: function (web3) { |
||||
// ADMIN
|
||||
web3._extend({ |
||||
property: 'admin', |
||||
methods: [ |
||||
new web3._extend.Method({ |
||||
name: 'addPeer', |
||||
call: 'admin_addPeer', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.fromDecimal], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'exportChain', |
||||
call: 'admin_exportChain', |
||||
params: 1, |
||||
inputFormatter: [null], |
||||
outputFormatter: function (obj) { return obj } |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'importChain', |
||||
call: 'admin_importChain', |
||||
params: 1, |
||||
inputFormatter: [null], |
||||
outputFormatter: function (obj) { return obj } |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'verbosity', |
||||
call: 'admin_verbosity', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'setSolc', |
||||
call: 'admin_setSolc', |
||||
params: 1, |
||||
inputFormatter: [null], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'startRPC', |
||||
call: 'admin_startRPC', |
||||
params: 4, |
||||
inputFormatter: [null, web3._extend.utils.formatInputInteger, null, null], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'stopRPC', |
||||
call: 'admin_stopRPC', |
||||
params: 0, |
||||
inputFormatter: [], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'vmTrace', |
||||
call: 'admin_eth_vmTrace', |
||||
inputFormatter: [null, null, null], |
||||
params: 3 |
||||
}) |
||||
], |
||||
properties: [ |
||||
new web3._extend.Property({ |
||||
name: 'nodeInfo', |
||||
getter: 'admin_nodeInfo', |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'peers', |
||||
getter: 'admin_peers', |
||||
outputFormatter: function (obj) { return obj } |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'datadir', |
||||
getter: 'admin_datadir', |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'chainSyncStatus', |
||||
getter: 'admin_chainSyncStatus', |
||||
outputFormatter: function (obj) { return obj } |
||||
}) |
||||
] |
||||
}) |
||||
|
||||
// ADMIN
|
||||
web3._extend({ |
||||
property: 'admin', |
||||
methods: |
||||
[ |
||||
new web3._extend.Method({ |
||||
name: 'addPeer', |
||||
call: 'admin_addPeer', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.fromDecimal], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'exportChain', |
||||
call: 'admin_exportChain', |
||||
params: 1, |
||||
inputFormatter: [null], |
||||
outputFormatter: function(obj) { return obj; } |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'importChain', |
||||
call: 'admin_importChain', |
||||
params: 1, |
||||
inputFormatter: [null], |
||||
outputFormatter: function(obj) { return obj; } |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'verbosity', |
||||
call: 'admin_verbosity', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'setSolc', |
||||
call: 'admin_setSolc', |
||||
params: 1, |
||||
inputFormatter: [null], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'startRPC', |
||||
call: 'admin_startRPC', |
||||
params: 4, |
||||
inputFormatter: [null,web3._extend.utils.formatInputInteger,null,null], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'stopRPC', |
||||
call: 'admin_stopRPC', |
||||
params: 0, |
||||
inputFormatter: [], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'vmTrace', |
||||
call: 'admin_eth_vmTrace', |
||||
inputFormatter: [null, null, null], |
||||
params: 3 |
||||
}),
|
||||
], |
||||
properties: |
||||
[ |
||||
new web3._extend.Property({ |
||||
name: 'nodeInfo', |
||||
getter: 'admin_nodeInfo', |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'peers', |
||||
getter: 'admin_peers', |
||||
outputFormatter: function(obj) { return obj; } |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'datadir', |
||||
getter: 'admin_datadir', |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'chainSyncStatus', |
||||
getter: 'admin_chainSyncStatus', |
||||
outputFormatter: function(obj) { return obj; } |
||||
}) |
||||
] |
||||
}); |
||||
// DEBUG
|
||||
web3._extend({ |
||||
property: 'debug', |
||||
methods: [ |
||||
new web3._extend.Method({ |
||||
name: 'trace', |
||||
call: 'debug_trace', |
||||
inputFormatter: [null, null], |
||||
params: 2 |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'printBlock', |
||||
call: 'debug_printBlock', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'getBlockRlp', |
||||
call: 'debug_getBlockRlp', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'setHead', |
||||
call: 'debug_setHead', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'processBlock', |
||||
call: 'debug_processBlock', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: function (obj) { return obj } |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'seedHash', |
||||
call: 'debug_seedHash', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'dumpBlock', |
||||
call: 'debug_dumpBlock', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: function (obj) { return obj } |
||||
}) |
||||
], |
||||
properties: [] |
||||
}) |
||||
|
||||
// DEBUG
|
||||
web3._extend({ |
||||
property: 'debug', |
||||
methods: |
||||
[ |
||||
new web3._extend.Method({ |
||||
name: 'trace', |
||||
call: 'debug_trace', |
||||
params: 1, |
||||
inputFormatter: [null, null], |
||||
params: 2 |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'printBlock', |
||||
call: 'debug_printBlock', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'getBlockRlp', |
||||
call: 'debug_getBlockRlp', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'setHead', |
||||
call: 'debug_setHead', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'processBlock', |
||||
call: 'debug_processBlock', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: function(obj) { return obj; } |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'seedHash', |
||||
call: 'debug_seedHash', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}) , |
||||
new web3._extend.Method({ |
||||
name: 'dumpBlock', |
||||
call: 'debug_dumpBlock', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: function(obj) { return obj; } |
||||
}) |
||||
], |
||||
properties: |
||||
[ |
||||
] |
||||
}); |
||||
// MINER
|
||||
web3._extend({ |
||||
property: 'miner', |
||||
methods: [ |
||||
new web3._extend.Method({ |
||||
name: 'start', |
||||
call: 'miner_start', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'stop', |
||||
call: 'miner_stop', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'setExtra', |
||||
call: 'miner_setExtra', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.formatInputString], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'setGasPrice', |
||||
call: 'miner_setGasPrice', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.formatInputString], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'startAutoDAG', |
||||
call: 'miner_startAutoDAG', |
||||
params: 0, |
||||
inputFormatter: [], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'stopAutoDAG', |
||||
call: 'miner_stopAutoDAG', |
||||
params: 0, |
||||
inputFormatter: [], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'makeDAG', |
||||
call: 'miner_makeDAG', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}) |
||||
], |
||||
properties: [ |
||||
new web3._extend.Property({ |
||||
name: 'hashrate', |
||||
getter: 'miner_hashrate', |
||||
outputFormatter: web3._extend.utils.toDecimal |
||||
}) |
||||
] |
||||
}) |
||||
|
||||
// MINER
|
||||
web3._extend({ |
||||
property: 'miner', |
||||
methods: |
||||
[ |
||||
new web3._extend.Method({ |
||||
name: 'start', |
||||
call: 'miner_start', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'stop', |
||||
call: 'miner_stop', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.formatInputInt], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'setExtra', |
||||
call: 'miner_setExtra', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.formatInputString], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'setGasPrice', |
||||
call: 'miner_setGasPrice', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.formatInputString], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'startAutoDAG', |
||||
call: 'miner_startAutoDAG', |
||||
params: 0, |
||||
inputFormatter: [], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'stopAutoDAG', |
||||
call: 'miner_stopAutoDAG', |
||||
params: 0, |
||||
inputFormatter: [], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'makeDAG', |
||||
call: 'miner_makeDAG', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}) |
||||
], |
||||
properties: |
||||
[ |
||||
new web3._extend.Property({ |
||||
name: 'hashrate', |
||||
getter: 'miner_hashrate', |
||||
outputFormatter: web3._extend.utils.toDecimal |
||||
}) |
||||
] |
||||
}); |
||||
|
||||
// NETWORK
|
||||
web3._extend({ |
||||
property: 'network', |
||||
methods: |
||||
[ |
||||
new web3._extend.Method({ |
||||
name: 'addPeer', |
||||
call: 'net_addPeer', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.formatInputString], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'getPeerCount', |
||||
call: 'net_peerCount', |
||||
params: 0, |
||||
inputFormatter: [], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}) |
||||
], |
||||
properties: |
||||
[ |
||||
new web3._extend.Property({ |
||||
name: 'listening', |
||||
getter: 'net_listening', |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'peerCount', |
||||
getter: 'net_peerCount', |
||||
outputFormatter: web3._extend.utils.toDecimal |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'peers', |
||||
getter: 'net_peers', |
||||
outputFormatter: function(obj) { return obj; } |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'version', |
||||
getter: 'net_version', |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}) |
||||
] |
||||
}); |
||||
|
||||
// TX POOL
|
||||
web3._extend({ |
||||
property: 'txpool', |
||||
methods: |
||||
[ |
||||
], |
||||
properties: |
||||
[ |
||||
new web3._extend.Property({ |
||||
name: 'status', |
||||
getter: 'txpool_status', |
||||
outputFormatter: function(obj) { return obj; } |
||||
}) |
||||
] |
||||
}); |
||||
} |
||||
}; |
||||
// NETWORK
|
||||
web3._extend({ |
||||
property: 'network', |
||||
methods: [ |
||||
new web3._extend.Method({ |
||||
name: 'addPeer', |
||||
call: 'net_addPeer', |
||||
params: 1, |
||||
inputFormatter: [web3._extend.utils.formatInputString], |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Method({ |
||||
name: 'getPeerCount', |
||||
call: 'net_peerCount', |
||||
params: 0, |
||||
inputFormatter: [], |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}) |
||||
], |
||||
properties: [ |
||||
new web3._extend.Property({ |
||||
name: 'listening', |
||||
getter: 'net_listening', |
||||
outputFormatter: web3._extend.formatters.formatOutputBool |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'peerCount', |
||||
getter: 'net_peerCount', |
||||
outputFormatter: web3._extend.utils.toDecimal |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'peers', |
||||
getter: 'net_peers', |
||||
outputFormatter: function (obj) { return obj } |
||||
}), |
||||
new web3._extend.Property({ |
||||
name: 'version', |
||||
getter: 'net_version', |
||||
outputFormatter: web3._extend.formatters.formatOutputString |
||||
}) |
||||
] |
||||
}) |
||||
|
||||
// TX POOL
|
||||
web3._extend({ |
||||
property: 'txpool', |
||||
methods: [], |
||||
properties: [ |
||||
new web3._extend.Property({ |
||||
name: 'status', |
||||
getter: 'txpool_status', |
||||
outputFormatter: function (obj) { return obj } |
||||
}) |
||||
] |
||||
}) |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue