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

EVMC modules for implementations of precompiled contracts #2003

Merged
merged 20 commits into from
Jun 6, 2019
Merged
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions EIPS/eip-2003.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
eip: 2003
title: EVMC modules for implementations of precompiled contracts
author: Paweł Bylica (@chfast)
discussions-to: https://github.com/ethereum/evmc/issues/259
status: Draft
type: Informational
created: 2019-05-09
requires: 1352
---

## Abstract

[EVMC] specifies a generic API for Ethereum execution engines.
This EIP specifies a way of providing implementations of Ethereum precompiled contracts
using the [EVMC VM API].

## Specification
axic marked this conversation as resolved.
Show resolved Hide resolved

For the complete [EVMC] specification visit the [EVMC documentation first].
axic marked this conversation as resolved.
Show resolved Hide resolved
This EIP is based on and is compatible with EVMC ABI version 6.

The EVMC module with implementations of precompiled contracts SHOULD:

1. Advertise the [`EVMC_CAPABILITY_PRECOMPILES`] capability
in the [`get_capabilities()`] method.
2. Implement the [`execute()`] method in the following way:
1. Check if the call destination address ([`evmc_message::destination`])
is within the range of precompiled contracts defined by [EIP-1352].
If not, abort execution with the [`EVMC_REJECTED`] status code.
2. Check if the call destination address ([`evmc_message::destination`])
targets existing precompiled contract.
Consider the EVM revision ([`evmc_revision`]) requested by
the `rev` parameter of [`execute()`].
If yes, execute as follows:
1. Inspect the input data ([`evmc_message::input_data`], [`evmc_message::input_size`])
and calculate the _gas cost_ of the execution.
2. Compute the amount of _gas left_ after execution by
subtracting the _gas cost_ from the call gas limit ([`evmc_message::gas`]).
3. If _gas left_ is negative,
abort execution with the [`EVMC_OUT_OF_GAS`] status code.
4. Otherwise,
axic marked this conversation as resolved.
Show resolved Hide resolved
execute the code of the precompiled contract,
return the [`EVMC_SUCCESS`] status code, the output and _gas left_
([`evmc_result::output_data`], [`evmc_result::output_size`], [`evmc_result::gas_left`]).
3. Otherwise, emulate execution of empty code by returning
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this emulation thing makes sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping @chfast

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does because then you have exclusive subsets of addresses - precompiles set and other, and the Precompiles VM is able to handle the matching set fully.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes that no code can be deployed in the precompiles address space.

the [`EVMC_SUCCESS`] status code
and _gas left_ equal the call gas limit ([`evmc_message::gas`]).

Precompiled contract implementations are allowed to return two more EVMC error codes:
- [`EVMC_FAILURE`] if the failure was caused due to something other than out of gas (e.g. input validation error)
- [`EVMC_REVERT`] if the precompile doesn't want to forfeit all supplied gas (as of May 2019 no such precompile exists)

The Client is not required to provide the Host interface (by setting the [`evmc_context`] argument of [`execute()`] to null).
chfast marked this conversation as resolved.
Show resolved Hide resolved
Therefore, the precompiled contracts implementation MUST NOT access the `evmc_context`.


## Rationale

It is very unlikely that any precompile will need to access or modify a contract state.
Not requiring the Client to implement the EVMC Host interface removes the big portion of work
needed for full EVMC integration.


## Test Cases

EVMC provides the [evmc-vmtester] tool for checking compatibility with the EVMC specification.

## Implementations

- [Example of Precompiles VM implementation][example_precompiles_vm.cpp]
- [ewasm precompiles]
- Aleth code for precompiles
- Parity code for precompiles


## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

## References

- [EVMC – Ethereum Client-VM Connector API][EVMC]
- [EVMC documentation]
- [EVMC VM Implementation Guide][EVMC VM API]
- [EIP 1352: Specify restricted address range for precompiles/system contracts][EIP-1352]

## TODO

- What if message::kind is CREATE?
chfast marked this conversation as resolved.
Show resolved Hide resolved
- What if message contains code?
chfast marked this conversation as resolved.
Show resolved Hide resolved
- Links to EVMC repo are not pinned to particular commit. Probably should be pinned to v6.3.0 later on.


[EIP-1352]: https://eips.ethereum.org/EIPS/eip-1352
[EVMC]: https://github.com/ethereum/evmc
[EVMC documentation]: https://ethereum.github.io/evmc/
[EVMC VM API]: https://ethereum.github.io/evmc/vmguide.html
[evmc-vmtester]: https://ethereum.github.io/evmc/vmtester.html
[example_precompiles_vm.cpp]: https://github.com/ethereum/evmc/blob/master/examples/example_precompiles_vm/example_precompiles_vm.cpp
[ewasm precompiles]: https://github.com/ewasm/ewasm-precompiles

[`EVMC_CAPABILITY_PRECOMPILES`]: https://ethereum.github.io/evmc/group__EVMC.html#gga44f9ecb88cf6422a0072936494fd6ac7a43ea2aa7b099a2d67bc53c118ff3683d
[`EVMC_REJECTED`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920a2f3e0d8777f8d974ead27ae2a6eb2005
[`EVMC_OUT_OF_GAS`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920abfc47f75656c996c0b29c0553c00fc18
[`EVMC_SUCCESS`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920a4bc3069fec2bab2a55355a72b7db68b7
[`execute()`]: https://ethereum.github.io/evmc/structevmc__instance.html#a0823ebff21f9b0395b157e8c6b14a207
[`get_capabilities()`]: https://ethereum.github.io/evmc/structevmc__instance.html#ae63b9ca898aa41cbd1e2fe86ca8f4e1c
[`evmc_message::destination`]: https://ethereum.github.io/evmc/structevmc__message.html#a88ecfaa03a85a31c6da36fa043b98cea
[`evmc_message::input_data`]: https://ethereum.github.io/evmc/structevmc__message.html#a1adee3454b105eb29cd659ee0cf65c77
[`evmc_message::input_size`]: https://ethereum.github.io/evmc/structevmc__message.html#a2cf1deebd0dbbb20f25ecdfa299f4b5d
[`evmc_message::gas`]: https://ethereum.github.io/evmc/structevmc__message.html#ae8deff46588584fa27890e74c82db5e7
[`evmc_result::gas_left`]: https://ethereum.github.io/evmc/structevmc__result.html#af8478c93dbcc3cb2876037c5a5afd4c0
[`evmc_result::output_data`]: https://ethereum.github.io/evmc/structevmc__result.html#a61978e85f9d795a7b9695b9cbf1748d6
[`evmc_result::output_size`]: https://ethereum.github.io/evmc/structevmc__result.html#a93bb7419aff492cdef754421c6d74e26
[`evmc_revision`]: https://ethereum.github.io/evmc/group__EVMC.html#gae5759b1590071966ccf6a505b52a0ef7