contract creation code

pull/7/head
yann300 9 years ago
parent 006dc9b32a
commit 6518e8a54e
  1. 35
      src/asmCode.js
  2. 9
      src/codeResolver.js
  3. 18
      src/stepManager.js
  4. 39
      src/traceAnalyser.js
  5. 13
      src/traceCache.js
  6. 25
      src/traceManager.js
  7. 2
      src/traceManagerUtil.js
  8. 2
      src/txBrowser.js

@ -67,22 +67,37 @@ module.exports = React.createClass({
code: ['loading...'] code: ['loading...']
}) })
var self = this var self = this
codeResolver.resolveCode(address, currentStep, this.context.tx, function (address, code) { if (address.indexOf('(Contract Creation Code)') !== -1) {
if (window.ethDebuggerSelectedItem !== currentStep) { this.context.traceManager.getContractCreationCode(address, function (error, hexCode) {
console.log(currentStep + ' discarded. current is ' + window.ethDebuggerSelectedItem) if (error) {
return console.log(error)
} } else {
self.setState({ var codes = codeResolver.cacheExecutingCode(address, hexCode)
code: code, self.updateCode(codes.code, address, currentStep)
address: address }
}) })
self.setInstructionIndex(address, currentStep) } else {
}) codeResolver.resolveCode(address, currentStep, this.context.tx, function (address, code) {
if (window.ethDebuggerSelectedItem !== currentStep) {
console.log(currentStep + ' discarded. current is ' + window.ethDebuggerSelectedItem)
return
}
self.updateCode(code, address, currentStep)
})
}
} else { } else {
this.setInstructionIndex(this.state.address, currentStep) this.setInstructionIndex(this.state.address, currentStep)
} }
}, },
updateCode: function (code, address, currentStep) {
this.setState({
code: code,
address: address
})
this.setInstructionIndex(address, currentStep)
},
setInstructionIndex: function (address, step) { setInstructionIndex: function (address, step) {
var self = this var self = this
this.context.traceManager.getCurrentPC(step, function (error, instIndex) { this.context.traceManager.getCurrentPC(step, function (error, instIndex) {

@ -18,11 +18,6 @@ module.exports = {
return return
} }
if (address === '(Contract Creation Code)') { // start of the trace
callBack(address, this.cacheExecutingCode(address, transaction.input).code)
return
}
var self = this var self = this
this.loadCode(address, function (code) { this.loadCode(address, function (code) {
callBack(address, self.cacheExecutingCode(address, code).code) callBack(address, self.cacheExecutingCode(address, code).code)
@ -42,8 +37,8 @@ module.exports = {
cacheExecutingCode: function (address, hexCode) { cacheExecutingCode: function (address, hexCode) {
var codes = this.formatCode(hexCode) var codes = this.formatCode(hexCode)
this.codes[address] = codes[0] this.codes[address] = codes.code
this.instructionsIndexByBytesOffset[address] = codes[1] this.instructionsIndexByBytesOffset[address] = codes.instructionsIndexByBytesOffset
return codes return codes
}, },

@ -64,18 +64,27 @@ module.exports = React.createClass({
}, },
sliderMoved: function (step) { sliderMoved: function (step) {
if (step >= this.state.traceLength || step < 0) {
return
}
this.props.onStepChanged(step) this.props.onStepChanged(step)
this.changeState(step) this.changeState(step)
}, },
stepIntoForward: function () { stepIntoForward: function () {
var step = this.state.currentStepIndex + 1 var step = this.state.currentStepIndex + 1
if (step >= this.state.traceLength || step < 0) {
return
}
this.props.onStepChanged(step) this.props.onStepChanged(step)
this.changeState(step) this.changeState(step)
}, },
stepIntoBack: function () { stepIntoBack: function () {
var step = this.state.currentStepIndex - 1 var step = this.state.currentStepIndex - 1
if (step >= this.state.traceLength || step < 0) {
return
}
this.props.onStepChanged(step) this.props.onStepChanged(step)
this.refs.slider.setValue(step) this.refs.slider.setValue(step)
this.changeState(step) this.changeState(step)
@ -83,6 +92,9 @@ module.exports = React.createClass({
stepOverForward: function () { stepOverForward: function () {
var step = this.context.traceManager.findStepOverForward(this.state.currentStepIndex) var step = this.context.traceManager.findStepOverForward(this.state.currentStepIndex)
if (step >= this.state.traceLength || step < 0) {
return
}
this.props.onStepChanged(step) this.props.onStepChanged(step)
this.refs.slider.setValue(step) this.refs.slider.setValue(step)
this.changeState(step) this.changeState(step)
@ -90,6 +102,9 @@ module.exports = React.createClass({
stepOverBack: function () { stepOverBack: function () {
var step = this.context.traceManager.findStepOverBack(this.state.currentStepIndex) var step = this.context.traceManager.findStepOverBack(this.state.currentStepIndex)
if (step >= this.state.traceLength || step < 0) {
return
}
this.props.onStepChanged(step) this.props.onStepChanged(step)
this.refs.slider.setValue(step) this.refs.slider.setValue(step)
this.changeState(step) this.changeState(step)
@ -97,6 +112,9 @@ module.exports = React.createClass({
jumpToNextCall: function () { jumpToNextCall: function () {
var step = this.context.traceManager.findNextCall(this.state.currentStepIndex) var step = this.context.traceManager.findNextCall(this.state.currentStepIndex)
if (step >= this.state.traceLength || step < 0) {
return
}
this.props.onStepChanged(step) this.props.onStepChanged(step)
this.refs.slider.setValue(step) this.refs.slider.setValue(step)
this.changeState(step) this.changeState(step)

@ -6,19 +6,22 @@ function TraceAnalyser (_cache) {
this.trace = null this.trace = null
} }
TraceAnalyser.prototype.analyse = function (trace, root, callback) { TraceAnalyser.prototype.analyse = function (trace, tx, callback) {
this.trace = trace this.trace = trace
this.traceCache.pushStoreChanges(0, tx.to)
this.traceCache.pushStoreChanges(0, root)
var context = { var context = {
currentStorageAddress: root, currentStorageAddress: tx.to,
previousStorageAddress: root previousStorageAddress: tx.to
} }
var callStack = [root] var callStack = [tx.to]
this.traceCache.pushCallStack(0, { this.traceCache.pushCallStack(0, {
callStack: callStack.slice(0) callStack: callStack.slice(0)
}) })
if (tx.to === '(Contract Creation Code)') {
this.traceCache.pushContractCreation(tx.to, tx.input)
}
for (var k = 0; k < this.trace.length; k++) { for (var k = 0; k < this.trace.length; k++) {
var step = this.trace[k] var step = this.trace[k]
this.buildCalldata(k, step) this.buildCalldata(k, step)
@ -61,26 +64,30 @@ TraceAnalyser.prototype.buildStorage = function (index, step, context) {
TraceAnalyser.prototype.buildDepth = function (index, step, callStack) { TraceAnalyser.prototype.buildDepth = function (index, step, callStack) {
if (traceManagerUtil.isCallInstruction(step) && !traceManagerUtil.isCallToPrecompiledContract(index, this.trace)) { if (traceManagerUtil.isCallInstruction(step) && !traceManagerUtil.isCallToPrecompiledContract(index, this.trace)) {
var newAddress = traceManagerUtil.resolveCalledAddress(index, this.trace) if (traceManagerUtil.isCreateInstruction(step)) {
if (newAddress) { var contractToken = '(Contract Creation Code) ' + index
callStack.push(newAddress) callStack.push(contractToken)
var lastMemoryChange = this.traceCache.memoryChanges[this.traceCache.memoryChanges.length - 1]
this.traceCache.pushContractCreationFromMemory(index, contractToken, this.trace, lastMemoryChange)
} else { } else {
console.log('unable to build depth changes. ' + index + ' does not match with a CALL. depth changes will be corrupted') var newAddress = traceManagerUtil.resolveCalledAddress(index, this.trace)
if (newAddress) {
callStack.push(newAddress)
} else {
console.log('unable to build depth changes. ' + index + ' does not match with a CALL. depth changes will be corrupted')
}
} }
this.traceCache.pushCallChanges(step, index + 1) this.traceCache.pushCallChanges(step, index + 1)
this.traceCache.pushCallStack(index + 1, { this.traceCache.pushCallStack(index + 1, {
callStack: callStack.slice(0) callStack: callStack.slice(0)
}) })
} else if (traceManagerUtil.isReturnInstruction(step)) { } else if (traceManagerUtil.isReturnInstruction(step)) {
this.traceCache.pushCallChanges(step, index) callStack.pop()
this.traceCache.pushCallStack(index, { this.traceCache.pushCallChanges(step, index + 1)
this.traceCache.pushCallStack(index + 1, {
callStack: callStack.slice(0) callStack: callStack.slice(0)
}) })
callStack.pop()
} }
} }
// 0x90a99e9dbfc38ce0fd6330f97a192a9ef27b8329b57309e8b2abe47a6fe74574
// 0xc0e95f27e1482ba09dea8162c4b4090e3d89e214416df2ce9d5517ff2107de19
module.exports = TraceAnalyser module.exports = TraceAnalyser

@ -9,6 +9,7 @@ TraceCache.prototype.init = function () {
this.callChanges = [] this.callChanges = []
this.returnChanges = [] this.returnChanges = []
this.calls = {} this.calls = {}
this.contractCreation = {}
this.callDataChanges = [] this.callDataChanges = []
this.memoryChanges = [] this.memoryChanges = []
@ -32,6 +33,18 @@ TraceCache.prototype.pushCallChanges = function (step, value) {
} }
} }
TraceCache.prototype.pushContractCreationFromMemory = function (index, token, trace, lastMemoryChange) {
var memory = trace[lastMemoryChange].memory
var stack = trace[index].stack
var offset = 2 * parseInt(stack[stack.length - 2], 16)
var size = 2 * parseInt(stack[stack.length - 3], 16)
this.contractCreation[token] = '0x' + memory.substr(offset, size)
}
TraceCache.prototype.pushContractCreation = function (token, code) {
this.contractCreation[token] = code
}
TraceCache.prototype.pushReturnChanges = function (value) { TraceCache.prototype.pushReturnChanges = function (value) {
this.returnChanges.push(value) this.returnChanges.push(value)
} }

@ -30,7 +30,7 @@ TraceManager.prototype.resolveTrace = function (tx, callback) {
} else { } else {
if (result.structLogs.length > 0) { if (result.structLogs.length > 0) {
self.trace = result.structLogs self.trace = result.structLogs
self.traceAnalyser.analyse(result.structLogs, tx.to, function (error, result) { self.traceAnalyser.analyse(result.structLogs, tx, function (error, result) {
if (error) { if (error) {
console.log(error) console.log(error)
callback(false) callback(false)
@ -146,23 +146,26 @@ TraceManager.prototype.getCurrentCalledAddressAt = function (stepIndex, callback
if (addressIndex === 0) { if (addressIndex === 0) {
callback(null, self.tx.to) callback(null, self.tx.to)
} else { } else {
var step = this.trace[addressIndex] var callStack = self.traceCache.callStack[addressIndex].callStack
if (traceManagerUtil.isCreateInstruction(step)) { var calledAddress = callStack[callStack.length - 1]
callback(null, '(Contract Creation Code)') if (calledAddress) {
callback(null, calledAddress)
} else { } else {
var callStack = self.traceCache.callStack[addressIndex].callStack callback('unable to get current called address. ' + stepIndex + ' does not match with a CALL', null)
var calledAddress = callStack[callStack.length - 1]
if (calledAddress) {
callback(null, calledAddress)
} else {
callback('unable to get current called address. ' + stepIndex + ' does not match with a CALL', null)
}
} }
} }
} }
}) })
} }
TraceManager.prototype.getContractCreationCode = function (token, callback) {
if (this.traceCache.contractCreation[token]) {
callback(null, this.traceCache.contractCreation[token])
} else {
callback('no contract creation named ' + token, null)
}
}
TraceManager.prototype.getMemoryAt = function (stepIndex, callback) { TraceManager.prototype.getMemoryAt = function (stepIndex, callback) {
if (stepIndex >= this.trace.length) { if (stepIndex >= this.trace.length) {
callback('trace smaller than requested', null) callback('trace smaller than requested', null)

@ -37,7 +37,7 @@ module.exports = {
isCallInstruction: function (step) { isCallInstruction: function (step) {
return step.op === 'CALL' || step.op === 'CALLCODE' || step.op === 'CREATE' || step.op === 'DELEGATECALL' return step.op === 'CALL' || step.op === 'CALLCODE' || step.op === 'CREATE' || step.op === 'DELEGATECALL'
}, },
isCreateInstruction: function (step) { isCreateInstruction: function (step) {
return step.op === 'CREATE' return step.op === 'CREATE'
}, },

@ -12,7 +12,7 @@ module.exports = React.createClass({
}, },
getInitialState: function () { getInitialState: function () {
return {blockNumber: '1000110', txNumber: '0x71a6d583d16d142c5c3e8903060e8a4ee5a5016348a9448df6c3e63b68076ec4', from: '', to: '', hash: ''} return {blockNumber: '1000110', txNumber: '0x50a420e75151e7f04a014019598764102675e0c6c8979f1089690c594cbe871c', from: '', to: '', hash: ''}
}, },
// creation 0xa9619e1d0a35b2c1d686f5b661b3abd87f998d2844e8e9cc905edb57fc9ce349 // creation 0xa9619e1d0a35b2c1d686f5b661b3abd87f998d2844e8e9cc905edb57fc9ce349

Loading…
Cancel
Save