From 6518e8a54e21eefdae48088437bd8759ba68dcfa Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 27 May 2016 16:16:54 +0200 Subject: [PATCH] contract creation code --- src/asmCode.js | 35 +++++++++++++++++++++++++---------- src/codeResolver.js | 9 ++------- src/stepManager.js | 18 ++++++++++++++++++ src/traceAnalyser.js | 39 +++++++++++++++++++++++---------------- src/traceCache.js | 13 +++++++++++++ src/traceManager.js | 25 ++++++++++++++----------- src/traceManagerUtil.js | 2 +- src/txBrowser.js | 2 +- 8 files changed, 97 insertions(+), 46 deletions(-) diff --git a/src/asmCode.js b/src/asmCode.js index 4e7098504c..5a9f1c960d 100644 --- a/src/asmCode.js +++ b/src/asmCode.js @@ -67,22 +67,37 @@ module.exports = React.createClass({ code: ['loading...'] }) var self = this - codeResolver.resolveCode(address, currentStep, this.context.tx, function (address, code) { - if (window.ethDebuggerSelectedItem !== currentStep) { - console.log(currentStep + ' discarded. current is ' + window.ethDebuggerSelectedItem) - return - } - self.setState({ - code: code, - address: address + if (address.indexOf('(Contract Creation Code)') !== -1) { + this.context.traceManager.getContractCreationCode(address, function (error, hexCode) { + if (error) { + console.log(error) + } else { + var codes = codeResolver.cacheExecutingCode(address, hexCode) + self.updateCode(codes.code, address, currentStep) + } }) - 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 { 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) { var self = this this.context.traceManager.getCurrentPC(step, function (error, instIndex) { diff --git a/src/codeResolver.js b/src/codeResolver.js index 77d3fec33c..a206e7b93d 100644 --- a/src/codeResolver.js +++ b/src/codeResolver.js @@ -18,11 +18,6 @@ module.exports = { return } - if (address === '(Contract Creation Code)') { // start of the trace - callBack(address, this.cacheExecutingCode(address, transaction.input).code) - return - } - var self = this this.loadCode(address, function (code) { callBack(address, self.cacheExecutingCode(address, code).code) @@ -42,8 +37,8 @@ module.exports = { cacheExecutingCode: function (address, hexCode) { var codes = this.formatCode(hexCode) - this.codes[address] = codes[0] - this.instructionsIndexByBytesOffset[address] = codes[1] + this.codes[address] = codes.code + this.instructionsIndexByBytesOffset[address] = codes.instructionsIndexByBytesOffset return codes }, diff --git a/src/stepManager.js b/src/stepManager.js index 2b5000f82f..f2c7b03621 100644 --- a/src/stepManager.js +++ b/src/stepManager.js @@ -64,18 +64,27 @@ module.exports = React.createClass({ }, sliderMoved: function (step) { + if (step >= this.state.traceLength || step < 0) { + return + } this.props.onStepChanged(step) this.changeState(step) }, stepIntoForward: function () { var step = this.state.currentStepIndex + 1 + if (step >= this.state.traceLength || step < 0) { + return + } this.props.onStepChanged(step) this.changeState(step) }, stepIntoBack: function () { var step = this.state.currentStepIndex - 1 + if (step >= this.state.traceLength || step < 0) { + return + } this.props.onStepChanged(step) this.refs.slider.setValue(step) this.changeState(step) @@ -83,6 +92,9 @@ module.exports = React.createClass({ stepOverForward: function () { var step = this.context.traceManager.findStepOverForward(this.state.currentStepIndex) + if (step >= this.state.traceLength || step < 0) { + return + } this.props.onStepChanged(step) this.refs.slider.setValue(step) this.changeState(step) @@ -90,6 +102,9 @@ module.exports = React.createClass({ stepOverBack: function () { var step = this.context.traceManager.findStepOverBack(this.state.currentStepIndex) + if (step >= this.state.traceLength || step < 0) { + return + } this.props.onStepChanged(step) this.refs.slider.setValue(step) this.changeState(step) @@ -97,6 +112,9 @@ module.exports = React.createClass({ jumpToNextCall: function () { var step = this.context.traceManager.findNextCall(this.state.currentStepIndex) + if (step >= this.state.traceLength || step < 0) { + return + } this.props.onStepChanged(step) this.refs.slider.setValue(step) this.changeState(step) diff --git a/src/traceAnalyser.js b/src/traceAnalyser.js index 873b874412..dede33cfc7 100644 --- a/src/traceAnalyser.js +++ b/src/traceAnalyser.js @@ -6,19 +6,22 @@ function TraceAnalyser (_cache) { this.trace = null } -TraceAnalyser.prototype.analyse = function (trace, root, callback) { +TraceAnalyser.prototype.analyse = function (trace, tx, callback) { this.trace = trace - - this.traceCache.pushStoreChanges(0, root) + this.traceCache.pushStoreChanges(0, tx.to) var context = { - currentStorageAddress: root, - previousStorageAddress: root + currentStorageAddress: tx.to, + previousStorageAddress: tx.to } - var callStack = [root] + var callStack = [tx.to] this.traceCache.pushCallStack(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++) { var step = this.trace[k] this.buildCalldata(k, step) @@ -61,26 +64,30 @@ TraceAnalyser.prototype.buildStorage = function (index, step, context) { TraceAnalyser.prototype.buildDepth = function (index, step, callStack) { if (traceManagerUtil.isCallInstruction(step) && !traceManagerUtil.isCallToPrecompiledContract(index, this.trace)) { - var newAddress = traceManagerUtil.resolveCalledAddress(index, this.trace) - if (newAddress) { - callStack.push(newAddress) + if (traceManagerUtil.isCreateInstruction(step)) { + var contractToken = '(Contract Creation Code) ' + index + callStack.push(contractToken) + var lastMemoryChange = this.traceCache.memoryChanges[this.traceCache.memoryChanges.length - 1] + this.traceCache.pushContractCreationFromMemory(index, contractToken, this.trace, lastMemoryChange) } 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.pushCallStack(index + 1, { callStack: callStack.slice(0) }) } else if (traceManagerUtil.isReturnInstruction(step)) { - this.traceCache.pushCallChanges(step, index) - this.traceCache.pushCallStack(index, { + callStack.pop() + this.traceCache.pushCallChanges(step, index + 1) + this.traceCache.pushCallStack(index + 1, { callStack: callStack.slice(0) }) - callStack.pop() } } -// 0x90a99e9dbfc38ce0fd6330f97a192a9ef27b8329b57309e8b2abe47a6fe74574 -// 0xc0e95f27e1482ba09dea8162c4b4090e3d89e214416df2ce9d5517ff2107de19 - module.exports = TraceAnalyser diff --git a/src/traceCache.js b/src/traceCache.js index 9fc4ac5a79..408b24ecdc 100644 --- a/src/traceCache.js +++ b/src/traceCache.js @@ -9,6 +9,7 @@ TraceCache.prototype.init = function () { this.callChanges = [] this.returnChanges = [] this.calls = {} + this.contractCreation = {} this.callDataChanges = [] 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) { this.returnChanges.push(value) } diff --git a/src/traceManager.js b/src/traceManager.js index 0ed6f4ba36..c8aa686bb0 100644 --- a/src/traceManager.js +++ b/src/traceManager.js @@ -30,7 +30,7 @@ TraceManager.prototype.resolveTrace = function (tx, callback) { } else { if (result.structLogs.length > 0) { 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) { console.log(error) callback(false) @@ -146,23 +146,26 @@ TraceManager.prototype.getCurrentCalledAddressAt = function (stepIndex, callback if (addressIndex === 0) { callback(null, self.tx.to) } else { - var step = this.trace[addressIndex] - if (traceManagerUtil.isCreateInstruction(step)) { - callback(null, '(Contract Creation Code)') + var callStack = self.traceCache.callStack[addressIndex].callStack + var calledAddress = callStack[callStack.length - 1] + if (calledAddress) { + callback(null, calledAddress) } else { - var callStack = self.traceCache.callStack[addressIndex].callStack - 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) - } + 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) { if (stepIndex >= this.trace.length) { callback('trace smaller than requested', null) diff --git a/src/traceManagerUtil.js b/src/traceManagerUtil.js index 61f3f1f7cb..cd1cafbaea 100644 --- a/src/traceManagerUtil.js +++ b/src/traceManagerUtil.js @@ -37,7 +37,7 @@ module.exports = { isCallInstruction: function (step) { return step.op === 'CALL' || step.op === 'CALLCODE' || step.op === 'CREATE' || step.op === 'DELEGATECALL' }, - + isCreateInstruction: function (step) { return step.op === 'CREATE' }, diff --git a/src/txBrowser.js b/src/txBrowser.js index a3717f4f68..30242a2935 100644 --- a/src/txBrowser.js +++ b/src/txBrowser.js @@ -12,7 +12,7 @@ module.exports = React.createClass({ }, getInitialState: function () { - return {blockNumber: '1000110', txNumber: '0x71a6d583d16d142c5c3e8903060e8a4ee5a5016348a9448df6c3e63b68076ec4', from: '', to: '', hash: ''} + return {blockNumber: '1000110', txNumber: '0x50a420e75151e7f04a014019598764102675e0c6c8979f1089690c594cbe871c', from: '', to: '', hash: ''} }, // creation 0xa9619e1d0a35b2c1d686f5b661b3abd87f998d2844e8e9cc905edb57fc9ce349