Skip to content

v0.7.0 Plan (Experimental)  #346

@cgewecke

Description

@cgewecke

Rewrite this tool as a hybrid of solidity-coverage and 0xProject's opcode tracing sol-cov.

Mechanics

  • instead of a file of event hashes written by testrpc-sc, maintain an in memory map of them.
  • example instrumentation where bytes32(0xabc..etc) is a hash we can pick off the top of the VM step's stack and associate with an entry in the injection map.
contract Test {
  function coverage_0xab123(bytes32 c__0xab123) public pure {}

  function a(uint x) public {

    coverage_0xab123(0xdc08f...08ed1); /* function */ 
    coverage_0xab123(0xa9065...549e2); /* line */         
    coverage_0xab123(0x6ac83...f2037); /* statement */ 
  
    if (x == 1) {
  
      coverage_0xab123(0x85e7e...afacf); /* branch */ 
      coverage_0xab123(0xfa262...4fb28); /* line */  
      coverage_0xab123(0xa3e17...38d49); /* statement */ 
  
      x = 3;
  
    } else { 
      coverage_0xab123(0xb54c1...3ef6b); /* branch */ 
    }
}
  • listen to the vm step of a ganache-core in-process provider
const Ganache = require("ganache-core");
// ... some setup w/ web3
const vm = web3.currentProvider.engine.manager.state.blockchain.vm;

const self = this;
this.vm.on("step", function(info){

  if (info.opcode.name.includes("PUSH1") && info.stack.length > 0){
    const idx = info.stack.length - 1;
    const hash = web3Utils.toHex(info.stack[idx]).toString(); // Could be ours! 

    if(self.instrumentationData[hash]){
      self.instrumentationData[hash].hits++;
    }
  }
})

Interface

  • Truffle plugin. We'll get fed the config and then we:

    • Instantiate a ganache provider (hooking into the step)
    • instrument
    • run truffle-workflow-compile
      • .coverageEnv --> build directory
      • optimization off
      • hide compilation warnings about unused variables
    • run truffle-core.test
      • .coverageEnv --> contracts_directory
      • listen to step
    • generate coverage
  • Buidler plugin - similar, simpler.

  • Abstract the design enough that any build tool can consume.

Benefits

  • No more copying folders etc.
  • No more abi modification, double compilation, weird problems w/ libraries
  • No more testrpc-sc to update (eventually)
  • Get rid of most options, user config
  • Much faster & simpler.

Problems

  • Gas cost distortion (+13 gas per instrumentation statement).
  • Ternary expressions still un-coverable.
  • Stack too deep? This blog post suggests risks might be comparable to present. Not sure, could be a blocker though. (Solved)
  • Requires in-process client
  • Are there cases where gas sensitive solidity checks require compilation w/ solc optimization enabled? (This would impact any opcode tracer though) Does solc optimize assembly?

Why is this preferable to the opcode-to-sourcemap approach?

  • small modification of what we already have.
  • truffle-debugger and the 0x tools are complex
  • Not currently supported on 0x. Why?
  • source to opcode mapping / trace has gaps & oddities
  • embark, after spending months building an opcode tracing solution, abandoned that work to pursue event instrumentation (?!). Why?
  • we know we instrument ok (mostly).

In the medium term we can probably resolve any gas distortion issues using etherumjs-vm V4's Interpreter API which lets you process opcodes arbitrarily following a new EEI spec. Have opened an issue there seeking advice about this.

We can probably instrument assembly eventually (#176)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions