Skip to content

Commit

Permalink
isolate active_branches between jumps
Browse files Browse the repository at this point in the history
  • Loading branch information
iamdefinitelyahuman committed Dec 24, 2019
1 parent be02596 commit 1d1b64f
Showing 1 changed file with 28 additions and 35 deletions.
63 changes: 28 additions & 35 deletions brownie/network/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,6 @@ def _expand_trace(self) -> None:
# last_map gives a quick reference of previous values at each depth
last_map = {0: _get_last_map(self.receiver, self.input[:10])} # type: ignore
coverage_eval: Dict = {last_map[0]["name"]: {}}
active_branches = set()

for i in range(len(trace)):
# if depth has increased, tx has called into a different contract
Expand All @@ -422,13 +421,11 @@ def _expand_trace(self) -> None:
# update trace from last_map
last = last_map[trace[i]["depth"]]
trace[i].update(
{
"address": last["address"],
"contractName": last["name"],
"fn": last["fn"][-1],
"jumpDepth": last["jumpDepth"],
"source": False,
}
address=last["address"],
contractName=last["name"],
fn=last["fn"][-1],
jumpDepth=last["jumpDepth"],
source=False,
)

if "pc_map" not in last:
Expand All @@ -443,37 +440,35 @@ def _expand_trace(self) -> None:
continue

# calculate coverage
if pc["path"] != "<stdin>":
if "active_branches" in last:
if pc["path"] not in coverage_eval[last["name"]]:
coverage_eval[last["name"]][pc["path"]] = [set(), set(), set()]
if "statement" in pc:
coverage_eval[last["name"]][pc["path"]][0].add(pc["statement"])
if "branch" in pc:
if pc["op"] != "JUMPI":
active_branches.add(pc["branch"])
elif pc["branch"] in active_branches:
last["active_branches"].add(pc["branch"])
elif pc["branch"] in last["active_branches"]:
# false, true
key = 1 if trace[i + 1]["pc"] == trace[i]["pc"] + 1 else 2
coverage_eval[last["name"]][pc["path"]][key].add(pc["branch"])
active_branches.remove(pc["branch"])
last["active_branches"].remove(pc["branch"])

# ignore jumps with no function - they are compiler optimizations
if "jump" not in pc:
continue

# jump 'i' is calling into an internal function
if pc["jump"] == "i":
try:
fn = last["pc_map"][trace[i + 1]["pc"]]["fn"]
except (KeyError, IndexError):
continue
if fn != last["fn"][-1]:
last["fn"].append(fn)
last["jumpDepth"] += 1
# jump 'o' is returning from an internal function
elif last["jumpDepth"] > 0:
del last["fn"][-1]
last["jumpDepth"] -= 1
if "jump" in pc:
# jump 'i' is calling into an internal function
if pc["jump"] == "i":
try:
fn = last["pc_map"][trace[i + 1]["pc"]]["fn"]
except (KeyError, IndexError):
continue
if fn != last["fn"][-1]:
last["fn"].append(fn)
last["jumpDepth"] += 1
# jump 'o' is returning from an internal function
elif last["jumpDepth"] > 0:
del last["fn"][-1]
last["jumpDepth"] -= 1
coverage._add_transaction(
self.coverage_hash, dict((k, v) for k, v in coverage_eval.items() if v)
)
Expand Down Expand Up @@ -741,14 +736,12 @@ def _get_last_map(address: EthAddress, sig: str) -> Dict:
last_map = {"address": EthAddress(address), "jumpDepth": 0, "name": None}
if contract:
last_map.update(
{
"contract": contract,
"name": contract._name,
"fn": [f"{contract._name}.{contract.get_method(sig)}"],
}
contract=contract,
name=contract._name,
fn=[f"{contract._name}.{contract.get_method(sig)}"],
)
if contract._build:
last_map["pc_map"] = contract._build["pcMap"]
last_map.update(pc_map=contract._build["pcMap"], active_branches=set())
else:
last_map.update({"contract": None, "fn": [f"<UnknownContract>.{sig}"]})
last_map.update(contract=None, fn=[f"<UnknownContract>.{sig}"])
return last_map

0 comments on commit 1d1b64f

Please sign in to comment.