Brooke's Thoughts on FileCoin VM Options

Per request, here’s the source copy/pasta


It sounds like the EVM is the likely choice already, but I’ve been pointed at this thread so I should probably give my two cents. I previously worked on improving the design of the EVM, and have given the topic of blockchain execution some thought. These are just my opinions, and hope that they’re helpful or at least thought provoking. I haven’t been directly in the Ethereum space the past year-and-a-bit, but from what I can tell, all of the below is still relevant.

One of the biggest takeaways from my time in Ethereum was that it’s impractical to retire a public network’s VM. Even with the eventual switch to ETH 2.0, there’s an expectation that existing contracts will live on. Not doing so breaks the implicit contract with users. Clearly the choice of VM for FileCoin has not been taken lightly so far, but a cautionary double underline on the fact that the one(s) you choose will be with you for a very long time.

TL;DR Recommendation

  • Solidity (not the EVM) is table stakes for claiming to have smart contracts (SCs from here on)
  • Design an instruction set architecture (ISA) that:
    • Has no undefined behaviour
    • Maps easily to the LLVM IR
    • Is tailored to the FileCoin use case
      • FileCoin is has the potential to have special properties that we don’t see widely elsewhere
  • Build bridges with an established chains-of-chains (e.g. Cosmos)

Alternately, consider work being done on “enhanced” EVM-compatible VMs, such as IELE (semantics)

Opportunity

Why should someone use FileCoin instead of <insert blockchain here>? There are quite a few chains that provide very similar solutions to each other. I believe that FileCoin has a strong differentiator having started with storage built-in. Most blockchains can be seen as extremely high availability data stores, but where the cost of storage is very high. FileCoin very explicitly builds an open market for data, and can efficiently provide both storage in volume and potentially efficient execution.

Content addressed distributed storage coupled with an open compute platform has a ton of potential beyond what we see today: we can store the output of any function (including partial applications), run adaptive optimization (hotspot) across all SCs globally & collaboratively(!), embarrassingly parallel computation on large datasets, and so on. IPFS bridges to the web and is already deeply embedded in this ecosystem.

  • Ease of participation
    • Low barrier to entry (don’t need an auditor just to get started)
    • Familiar languages and idioms
    • Express your domain easily / pave the cowpaths
  • Security and trust
    • Determinism (all but required on a blockchain)
    • Automated code validation
    • Make the right thing the easy thing / “remove the foot guns”
  • Efficiency
    • Keep costs down
    • Don’t DoS the network
  • Extensibility
    • Powerful enough to express unexpected use cases
    • Room in the ISA to grow (you’ll need more than you think, 2-byte opcodes ranges can’t hurt)

Multiple Engines

Multiple engines can be introduced — even the wording used in FileCoin today (actors) suggests a well-isolated approach.

If code from multiple engines can interact, two things happen: you inherit the weaker invariants between the systems, and new unspecified behaviour can emerge from the interaction of the two. Many properties do not compose, and security in particular can break in unexpected ways.

The EVM

It is very clear now that the EVM has become THE smart contracts standard.

Agreed. The EVM leaves quite a lot to be desired (see below), but from a social standpoint it has won. In many cases it’s a required checkbox to say that you have a smart contract platform at all (true story).

The EVM is surprisingly low level for a platform that so heavily handles finance. It’s a difficult balance to strike, so I see how it got here, but it’s also not ideal. It’s possible but very difficult to formally verify EVM bytecode, largely due to the unstructured nature of the ISA (in the “structured programming” sense), and you really do need to verify the bytecode output as a source of truth.

It’s also quite inefficient for common classes of computation due to unusual word size. This isn’t all bad: having 256-bit words actually makes it more efficient than Wasm for a lot of cryptographic applications. I think that this mostly speaks to the advantages of tuning your ISA to the use case. Further, being a (more) special-purpose smart contract focused VM means being able to add instructions for the use cases that this community cares about without having to content with the very broad use cases that the Wasm WG is (rightly) concerned with.

Compiler Backend for Solidity > EVM Bytecode

Historically there’s a perceptual conflation between Solidity support and the EVM itself in the Ethereum community. There are many languages that target the EVM, but the overwhelming majority of code is in Solidity. When folks say that they want EVM-compatibility, it’s less that they want it to run already compiled EVM bytecode, and more that the platform should be a compile target for Solidity. This is definitely achievable, though some bytecode hacks may not translate. Many of the other EVM-targeted languages have reasonably portable IRs, which can also target a different backend.

Formally Verified VMs

There’s a distinction between formally verifying the VM, and a well specified ISA or IR. We can formally verify brainfuck, but it won’t be very easy to work with or analyze. The big question is “which properties should a blockchain execution engine have?” I agree that Michelson does a good job here, but is also certainly not the only option (DAML, Formality, &c)

Were I designing such a system, these are some of the things I’d focus on (off the top of my head):

Build an IR or higher level ISA, include useful semantics for the domain (storage, deals, ID, auth, &c) and any relevant syscalls.

Emphasize totality. Turning completeness means that code can run forever, which is an explicit anti-goal for public blockchain execution. Ethereum caps the amount of gas per transaction as a form of artificial forced termination. Turing completeness also makes formally verifying a smart contract more difficult. Enforcing total functions for even just most operations (ideally all) means that you can run all kinds of optimizations, strip the runtime cost dynamics from overhead and get much more accurate ahead-of-time gas costs as part of adaptive optimization. This is often achievable without loss of expressiveness in a blockchain context since it’s already going to be forced to terminate in a finite number of steps.

Determinism is a given, since this is a public blockchain. Deterministic concurrency would certainly be a nice-to-have.

They’re already called actors; use a message passing model and enforce strict isolation. It’s also very natural to most programmers.

Bake-in first class exceptions and well-defined signalling codes (think HTTP status codes or Erlang’s convention atoms).

Get a correct-by-construction spec during the design phase (i.e. no undefined behaviour). Make it easy to write SCs that aren’t broken. I personally think that Runtime Verification does beautiful work in this area.

Remember Telser’s Law, and that a dogmatically “simple” ISA means that you’re pushing complexity to the developers (see again Turing Taript).

————

That ended up being longer than I initially planned — I guess I do have opinions :sweat_smile: I’m (clearly) happy to share what I’ve learned in this space, and to respond to any of the above :pray: