Skip to content
This repository has been archived by the owner on Mar 3, 2021. It is now read-only.

Commit

Permalink
add comment in Internal call tree
Browse files Browse the repository at this point in the history
  • Loading branch information
yann300 committed Sep 11, 2019
1 parent 2260e8f commit f83b451
Showing 1 changed file with 21 additions and 1 deletion.
22 changes: 21 additions & 1 deletion remix-debug/src/solidity-decoder/internalCallTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class InternalCallTree {
if (!this.solidityProxy.loaded()) {
this.event.trigger('callTreeBuildFailed', ['compilation result not loaded. Cannot build internal call tree'])
} else {
// each recursive call to buildTree represent a new context (either call, delegatecall, internal function)
buildTree(this, 0, '', true).then((result) => {
if (result.error) {
this.event.trigger('callTreeBuildFailed', [result.error])
Expand All @@ -55,7 +56,9 @@ class InternalCallTree {
*/
reset () {
/*
scopes: map of scopes defined by range in the vmtrace {firstStep, lastStep, locals}. Keys represent the level of deepness (scopeId)
scopes: map of scopes defined by range in the vmtrace {firstStep, lastStep, locals}.
Keys represent the level of deepness (scopeId)
scopeId : <currentscope_id>.<sub_scope_id>.<sub_sub_scope_id>
*/
this.scopes = {}
/*
Expand Down Expand Up @@ -151,6 +154,7 @@ async function buildTree (tree, step, scopeId, isExternalCall) {
return { outStep: step, error: 'InternalCallTree - No source Location. ' + step }
}
var isCallInstruction = traceHelper.isCallInstruction(tree.traceManager.trace[step])
// we are checking if we jumping in a new CALL or in an internal function
if (isCallInstruction || sourceLocation.jump === 'i') {
try {
var externalCallResult = await buildTree(tree, step + 1, scopeId === '' ? subScope.toString() : scopeId + '.' + subScope, isCallInstruction)
Expand All @@ -164,9 +168,12 @@ async function buildTree (tree, step, scopeId, isExternalCall) {
return { outStep: step, error: 'InternalCallTree - ' + e.message }
}
} else if ((isExternalCall && callDepthChange(step, tree.traceManager.trace)) || (!isExternalCall && sourceLocation.jump === 'o')) {
// if not, we might be returning from a CALL or internal function. This is what is checked here.
tree.scopes[scopeId].lastStep = step
return { outStep: step + 1 }
} else {
// if not, we are in the current scope.
// We check in `includeVariableDeclaration` if there is a new local variable in scope for this specific `step`
if (tree.includeLocalVariables) {
includeVariableDeclaration(tree, step, sourceLocation, scopeId, newLocation, previousSourceLocation)
}
Expand All @@ -177,20 +184,27 @@ async function buildTree (tree, step, scopeId, isExternalCall) {
return { outStep: step }
}

// the reduced trace contain an entry only if that correspond to a new source location
function createReducedTrace (tree, index) {
tree.reducedTrace.push(index)
}

function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLocation, previousSourceLocation) {
var variableDeclaration = resolveVariableDeclaration(tree, step, sourceLocation)
// using the vm trace step, the current source location and the ast,
// we check if the current vm trace step target a new ast node of type VariableDeclaration
// that way we know that there is a new local variable from here.
if (variableDeclaration && !tree.scopes[scopeId].locals[variableDeclaration.attributes.name]) {
tree.traceManager.getStackAt(step, (error, stack) => {
// the stack length at this point is where the value of the new local will be stored.
// so, either this is the direct value, or the offset in memory. That depends on the type.
if (!error) {
tree.solidityProxy.contractNameAt(step, (error, contractName) => { // cached
if (!error) {
var states = tree.solidityProxy.extractStatesDefinitions()
var location = typesUtil.extractLocationFromAstVariable(variableDeclaration)
location = location === 'default' ? 'storage' : location
// we push the new local variable in our tree
tree.scopes[scopeId].locals[variableDeclaration.attributes.name] = {
name: variableDeclaration.attributes.name,
type: decodeInfo.parseType(variableDeclaration.attributes.type, states, contractName, location),
Expand All @@ -202,6 +216,8 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLoc
}
})
}
// we check here if we are at the beginning inside a new function.
// if that is the case, we have to add to locals tree the inputs and output params
var functionDefinition = resolveFunctionDefinition(tree, step, previousSourceLocation)
if (functionDefinition && (newLocation && traceHelper.isJumpDestInstruction(tree.traceManager.trace[step - 1]) || functionDefinition.attributes.isConstructor)) {
tree.functionCallStack.push(step)
Expand All @@ -223,6 +239,8 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLoc
}
}

// this extract all the variable declaration for a given ast and file
// and keep this in a cache
function resolveVariableDeclaration (tree, step, sourceLocation) {
if (!tree.variableDeclarationByFile[sourceLocation.file]) {
var ast = tree.solidityProxy.ast(sourceLocation)
Expand All @@ -236,6 +254,8 @@ function resolveVariableDeclaration (tree, step, sourceLocation) {
return tree.variableDeclarationByFile[sourceLocation.file][sourceLocation.start + ':' + sourceLocation.length + ':' + sourceLocation.file]
}

// this extract all the function definition for a given ast and file
// and keep this in a cache
function resolveFunctionDefinition (tree, step, sourceLocation) {
if (!tree.functionDefinitionByFile[sourceLocation.file]) {
var ast = tree.solidityProxy.ast(sourceLocation)
Expand Down

0 comments on commit f83b451

Please sign in to comment.