Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ethereum VM C interface #56

Closed
chfast opened this issue Jan 14, 2016 · 19 comments
Closed

Ethereum VM C interface #56

chfast opened this issue Jan 14, 2016 · 19 comments

Comments

@chfast
Copy link
Contributor

chfast commented Jan 14, 2016

Motivation

Based on work done in EVM JIT project https://github.com/ethereum/evmjit I would like to propose C-like interface specification for Ethereum VM ABI that could be used to create high performance VM implementations.

Specification

Types

  • uint256be - unsigned 256-bit big endian integer (32 bytes)
  • uint256 - unsigned 256-bit host endian integer (32 bytes)
  • uint64 - unsigned 64-bit host endian integer (8 bytes)
  • int64 - signed 64-bit host endian integer (8 bytes)
  • address - Ethereum address (20 bytes)
  • byte - a byte
  • ptr - a pointer to byte array

Inputs

Name Type Was Comment
gas uint256 int64 Execution with more than 263 gas is very theoretic.
gas price uint256 int64
input_data ptr Data must be available to VM until execution is finished.
input_data_size uint64
address address
caller address
origin address
transfer_value uint256
apparent_value uint256 Added in Homestead.
coinbase address
difficulty uint256
gas limit uint256
block number uint64
timestamp int64
code_hash uint256be The hash of the code to be executed.
code ptr The code is requested with get_code query.
code_size uint64

Outputs

  • status/result (ok, oog)
  • output data
  • storage modification list
  • suicide list
  • other state changes?

Queries (aka Callbacks)

VM uses this query functions to get additional information from a Ethereum node.

Declaration Description
uint256be keccak(ptr data, uint64 size) Ask VM to compute Keccak hash of the given data. This should be replaced with internal implementation of Keccak.
uint256 balance(address) Query the balance of the given address. See BALANCE instruction.
uint256be blockhash(uint256 number) Get hash of a block with given number. See BLOCKHASH instruction.
(ptr, uint64) extcode(address) Get the code of the given account. This should be used to get the code of the current execution request. In case the code has been compiled and cached the query is not needed.
void log(ptr data, uint64 size, uint256be topic1, uint256be topic2, uint256be topic3, uint256be topic4) Send logs. This should not be needed. Logs should be aggregates by the VM and provided to Ethereum node with other output.
uint256be sload(uint256be key) Load a word from the storage.
void sstore(uint256be key, uint256be value) Store a word in the storage. To count gas for that the VM needs to check the previous value with sload.
bool call(...) Call other contract.
void create(...) Create new contract.
@debris
Copy link

debris commented Mar 15, 2016

there should be transferValue and apparentValue instead of value (Homestead change).

p. 9, yellowpaper

https://github.com/ethereum/libethereum/blob/develop/evmjit/include/evmjit/JIT-c.h#L35

@debris
Copy link

debris commented Mar 15, 2016

also gas and gasPrice should be uint256

@debris
Copy link

debris commented Mar 15, 2016

apart from that, LGTM 👍

@chfast
Copy link
Contributor Author

chfast commented Mar 16, 2016

I always tried to avoid gas as 256-bit integer as that will never happen in live network. But I think I will need to move that optimization inside VM.

@chfast chfast changed the title Ethereum VM ABI ERC: Ethereum VM ABI Mar 19, 2016
@chfast chfast changed the title ERC: Ethereum VM ABI ERC: Ethereum VM C interface Mar 19, 2016
@chfast
Copy link
Contributor Author

chfast commented Mar 19, 2016

@debris, any issues with input data being passed by pointer? It needs to be available on the Rust side all the time execution is in progress.

Moreover, is it ok to timestamp being int64 and block number being uint64?

@debris
Copy link

debris commented Mar 19, 2016

@debris, any issues with input data being passed by pointer? It needs to be available on the Rust side all the time execution is in progress.

No

Moreover, is it ok to timestamp being int64 and block number being uint64?

Yes 👍

@gcolvin
Copy link
Contributor

gcolvin commented Apr 12, 2016

@chfast At least in the interpreter gas and memory must be less than 2^63. There is no way on earth to use that much. If sometime in the future there is, this code will be long gone anyway. And otherwise gas and memory calculations become very slow, and gas calculations are almost pure overhead already. In the JIT perhaps the 256-bit operations can be optimized to 64-bit?

@chfast
Copy link
Contributor Author

chfast commented Apr 12, 2016

I 100% agree. The problem is the spec allow the gas value to be very high and there are some tests in the test repo that exploits that. I agree that it makes no sense but users of evmjit usually complain that it does not pass all tests.

Having gas limit of 2^63 make it fit in a regular CPU register and allows easy overflow detection.

What I plan to do is to check the gas value in the first place and if it is less than 2^63 run the code in "fast" mode. Otherwise run in "compatibility" mode.

@gcolvin
Copy link
Contributor

gcolvin commented Apr 13, 2016

The spec and the tests need to be fixed. Running in a separate mode just to pass tests means we have to write two interpreters and not test the one we actually run. Similar thing with memory. Conceptually it's infinite, but nobody can afford even a gigabyte, and it's not like you could allocate even 2^63 anyway.

@chfast
Copy link
Contributor Author

chfast commented Apr 13, 2016

Let's propose lowering the maximum gas per transaction: #92.

@wanderer wanderer changed the title ERC: Ethereum VM C interface Ethereum VM C interface Apr 14, 2016
@chfast
Copy link
Contributor Author

chfast commented May 18, 2016

I try to design C interface for EVMJIT. Can you review ethereum/evmjit#55?

@axic
Copy link
Member

axic commented Aug 21, 2016

@chfast these suggestions are based on latest interface as defined by evm.h: https://github.com/ethereum/evmjit/blob/develop/include/evm.h

  • evm_get_info should return NULL if the key is not found.
  • evm_execute should have a field for specifying bytecode type. As you have proposed, that could be part of evm_mode, but it seems that EVM1 and EVM2 bytecode will coexist on the same blockchain.
  • evm_result should have an execution outcome enum (SUCCESS, OOG, INVALID_INSTRUCTION, EXCEPTION, etc.) and a string for the detailed reason (can be NULL if not present)

Also the evmjit_* definitions should be removed from evm.h or renamed appropriately.

@axic
Copy link
Member

axic commented Aug 21, 2016

For those interested, there's now an eWASM implementation using this C API: https://github.com/ewasm/hera

@chfast
Copy link
Contributor Author

chfast commented Aug 21, 2016

@axic:
I prefer EVM-C to be more pragmatic than beautiful.

  • For bytecode version I propose to use evm_mode. For your case can the values be e.g. EVM_FUTUREETHEREUM_EVM1 and EVM_FUTUREETHEREUM_EVM2. We have at least 32 bits in the value of evm_mode to be used.
  • I don't like the name evm_mode but evm_compatibility_mode feels a bit to long. Any suggestions for better name? evm_bytecode_version?
  • The execution result is just success of failure by design because compliant VM implementation is not required to provide details about the reason of the failure. I exploit this in evmjit. However, we can discuss that if this information is needed.

@axic
Copy link
Member

axic commented Aug 21, 2016

For bytecode version I propose to use evm_mode.

I'm not sure at this stage yet, whether that will be a viable solution.

The execution result is just success of failure by design because compliant VM implementation is not required to provide details about the reason of the failure.

They are not required, but why should they be disallowed doing so? Some VMs do provide the result with greater detail (ethereumjs, Parity).

@chfast
Copy link
Contributor Author

chfast commented Aug 21, 2016

The generated docs are now auto-updated: http://ethereum.github.io/evmjit/docs/group__EVMC.html

@chfast
Copy link
Contributor Author

chfast commented Mar 3, 2017

This is work in progress. I will update soon.

@Souptacular
Copy link
Contributor

Pinged @chfast to check into this. If it is still a WIP no problem, just want to get an update :)

@axic
Copy link
Member

axic commented Sep 4, 2018

The live specification is maintained at https://github.com/ethereum/evmc.

@chfast any point to keep this issue open? Should we create an ERC56 which has a copy of evmc.h with ABI v5 and create a new ERC with every new ABI version deprecating the old one?

@chfast chfast closed this as completed Sep 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants