This repository has been archived by the owner on Nov 30, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 161
evm: module specification #538
Merged
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
cfa4578
evm: module specification
fedekunze 7fb39ff
params and events
fedekunze 0d6501f
readme and messages
fedekunze d7f9b5b
minor updates
fedekunze fbfef66
Merge branch 'development' of github.com:ChainSafe/ethermint into fed…
fedekunze e9eb6d8
concepts
fedekunze 4bbe0ed
genesis state concept
fedekunze 66f8a12
begin and end block
fedekunze 66a30cc
Merge branch 'development' into fedekunze/evm-spec
fedekunze 21a4a77
merge develop
fedekunze 32c0f79
Merge branch 'development' into fedekunze/evm-spec
fedekunze 626f33a
Merge branch 'development' into fedekunze/evm-spec
fedekunze 2189e71
update parameters and genesis
fedekunze f7a00c4
state objects
fedekunze 79e574f
state table
fedekunze ef16558
use permalink
fedekunze 4305780
Merge branch 'development' into fedekunze/evm-spec
fedekunze ff6eaec
init and export genesis
fedekunze 14e56a5
Merge branch 'fedekunze/evm-spec' of https://github.com/cosmos/etherm…
fedekunze 1885e4b
update abci
fedekunze e26df43
extra eips param
fedekunze fecb670
Merge branch 'development' into fedekunze/evm-spec
fedekunze 285db3f
review comments
fedekunze ba8bff9
precision
fedekunze cce210a
link to photon doc
fedekunze File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,8 @@ import ( | |
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
ethtypes "github.com/ethereum/go-ethereum/core/types" | ||
|
||
"github.com/cosmos/ethermint/x/evm/types" | ||
) | ||
|
||
// BeginBlock sets the block hash -> block height map for the previous block height | ||
|
@@ -22,7 +21,12 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { | |
// Gas costs are handled within msg handler so costs should be ignored | ||
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) | ||
|
||
k.SetBlockHash(ctx, req.Header.LastBlockId.GetHash(), req.Header.GetHeight()-1) | ||
// Set the hash -> height and height -> hash mapping. | ||
hash := req.Header.LastBlockId.GetHash() | ||
height := req.Header.GetHeight() - 1 | ||
|
||
k.SetHeightHash(ctx, uint64(height), common.BytesToHash(hash)) | ||
k.SetBlockHash(ctx, hash, height) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not combine SetHeightHash and SetBlockHash into one function? |
||
|
||
// reset counters that are used on CommitStateDB.Prepare | ||
k.Bloom = big.NewInt(0) | ||
|
@@ -37,13 +41,6 @@ func (k Keeper) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.Valid | |
// Gas costs are handled within msg handler so costs should be ignored | ||
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) | ||
|
||
// Set the hash for the current height. | ||
// NOTE: we set the hash here instead of on BeginBlock in order to set the final block prior to | ||
// an upgrade. If we set it on BeginBlock the last block from prior to the upgrade wouldn't be | ||
// included on the store. | ||
hash := types.HashFromContext(ctx) | ||
k.SetHeightHash(ctx, uint64(ctx.BlockHeight()), hash) | ||
|
||
// Update account balances before committing other parts of state | ||
k.UpdateAccounts(ctx) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<!-- | ||
order: 1 | ||
--> | ||
|
||
# Concepts | ||
|
||
## EVM | ||
|
||
The Ethereum Virtual Machine [EVM](https://ethereum.org/en/developers/docs/evm/) is a state machine | ||
that provides the necessary tools to run or create a contract on a given state. | ||
|
||
## State DB | ||
|
||
The `StateDB` interface from geth represents an EVM database for full state querying of both | ||
contracts and accounts. The concrete type that fulfills this interface on Ethermint is the | ||
`CommitStateDB`. | ||
|
||
## State Object | ||
|
||
A `stateObject` represents an Ethereum account which is being modified. | ||
The usage pattern is as follows: | ||
|
||
* First you need to obtain a state object. | ||
* Account values can be accessed and modified through the object. | ||
|
||
## Genesis State | ||
|
||
The `x/evm` module `GenesisState` defines the state necessary for initializing the chain from a previous exported height. | ||
|
||
+++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/genesis.go#L14-L20 | ||
|
||
### Genesis Accounts | ||
|
||
The `GenesisAccount` type corresponds to an adaptation of the Ethereum `GenesisAccount` type. Its | ||
main difference is that the one on Ethermint uses a custom `Storage` type that uses a slice instead | ||
of maps for the evm `State` (due to non-determinism), and that it doesn't contain the private key | ||
field. | ||
|
||
It is also important to note that since the `auth` and `bank` SDK modules manage the accounts and | ||
balance state, the `Address` must correspond to an `EthAccount` that is stored in the `auth`'s | ||
module `AccountKeeper` and the balance must match the balance of the `EvmDenom` token denomination | ||
defined on the `GenesisState`'s `Param`. The values for the address and the balance amount maintain | ||
the same format as the ones from the SDK to make manual inspections easier on the genesis.json. | ||
|
||
+++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/genesis.go#L22-L30 | ||
|
||
### Transaction Logs | ||
|
||
On every Ethermint transaction, its result contains the Ethereum `Log`s from the state machine | ||
execution that are used by the JSON-RPC Web3 server for for filter querying. Since Cosmos upgrades | ||
don't persist the transactions on the blockchain state, we need to persist the logs the EVM module | ||
state to prevent the queries from failing. | ||
|
||
`TxsLogs` is the field that contains all the transaction logs that need to be persisted after an | ||
upgrade. It uses an array instead of a map to ensure determinism on the iteration. | ||
|
||
+++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/logs.go#L12-L18 | ||
|
||
### Chain Config | ||
|
||
The `ChainConfig` is a custom type that contains the same fields as the go-ethereum `ChainConfig` | ||
parameters, but using `sdk.Int` types instead of `*big.Int`. It also defines additional YAML tags | ||
for pretty printing. | ||
|
||
The `ChainConfig` type is not a configurable SDK `Param` since the SDK does not allow for validation | ||
against a previous stored parameter values or `Context` fields. Since most of this type's fields | ||
rely on the block height value, this limitation prevents the validation of of potential new | ||
parameter values against the current block height (eg: to prevent updating the config block values | ||
to a past block). | ||
|
||
If you want to update the config values, use an software upgrade procedure. | ||
|
||
+++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/chain_config.go#L16-L45 | ||
|
||
### Params | ||
|
||
See the [params](07_params.md) document for further information about parameters. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
<!-- | ||
order: 2 | ||
--> | ||
|
||
# State | ||
|
||
The `x/evm` module keeps the following objects in state: | ||
|
||
| | Key | Value | | ||
|-----------------|---------------------------------------------------|---------------------------| | ||
| Block Height | `[]byte{1} + []byte(block.Hash)` | `BigEndian(block.Height)` | | ||
| Bloom | `[]byte{2} + []byte(block.Height)` | `[]byte(Bloom)` | | ||
| Tx Logs | `[]byte{3} + []byte(tx.Hash)` | `amino([]Log)` | | ||
| Account Code | `[]byte{4} + []byte(code.Hash)` | `[]byte(Code)` | | ||
| Account Storage | `[]byte{5} + []byte(address) + []byte(state.Key)` | `[]byte(state.Value)` | | ||
| Chain Config | `[]byte{6}` | `amino(ChainConfig)` | | ||
|
||
## `CommitStateDB` | ||
|
||
`StateDB`s within the ethereum protocol are used to store anything within the IAVL tree. `StateDB`s | ||
take care of caching and storing nested states. It's the general query interface to retrieve | ||
contracts and accounts | ||
|
||
The Ethermint `CommitStateDB` is a concrete type that implements the EVM `StateDB` interface. | ||
Instead of using a trie and database for querying and persistence, the `CommitStateDB` uses | ||
`KVStores` (key-value stores) and Cosmos SDK `Keeper`s to facilitate state transitions. | ||
|
||
The `CommitStateDB` contains a store key that allows the DB to write to a concrete subtree of the | ||
multistore that is only accessible to the EVM module. | ||
|
||
+++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/statedb.go#L33-L85 | ||
|
||
The functionalities provided by the Ethermint `StateDB` are: | ||
|
||
* CRUD of `stateObject`s and accounts: | ||
* Balance | ||
* Code | ||
* Nonce | ||
* State | ||
* EVM module parameter getter and setter | ||
* State transition logic | ||
* Preparation: transaction index and hash, block hash | ||
* CRUD of transaction logs | ||
* Aggregate queries | ||
* Snapshot state | ||
* Identify current state with a revision | ||
* Revert state to a given revision | ||
* State transition and persistence | ||
* Preparation: tx and block context | ||
* Commit state objects | ||
* Finalise state objects | ||
* Export state for upgrades | ||
* Auxiliary functions | ||
* Copy state | ||
* Reset state | ||
|
||
## State Objects | ||
|
||
State objects are used by the VM which is unable to deal with database-level errors. Any error that occurs during a database read is memoized here and will eventually be returned by `StateDB.Commit`. | ||
|
||
The Ethermint `stateObject` is a concrete type that mimics the functionality from the `go-ethereum` | ||
private `stateObject` type. It keeps track of the interim values for the contract bytecode, storage | ||
state and balance of an `EthAccount`. | ||
|
||
The storage entries (original and "dirty") for each state object are represented as slices instead | ||
of maps since latter can cause non-deterministic block app hashes, which result in the chain | ||
halting. | ||
|
||
When a `stateObject` is committed during `EndBlock`. It sets sets the account contract code to store, as well as the dirty storage state. The account's nonce and the account balance are updated by calling the `auth` and `bank` module setter functions, respectively. | ||
|
||
+++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/state_object.go#L49-L81 | ||
|
||
The functionalities provided by the Ethermint `stateObject` are: | ||
|
||
* Storage state getter and setter (temporary) | ||
* Contract bytecode getter and setter (temporary) | ||
* Balance getter and setter (temporary) | ||
* Balance accounting (temporary) | ||
* Account nonce and address getter and setter (temporary) | ||
* Auxiliary functions: copy, RLP encoding, empty | ||
* Commit state object (final) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<!-- | ||
order: 3 | ||
--> | ||
|
||
# State Transitions | ||
|
||
<!-- define state transitions for accounts and storage --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<!-- | ||
order: 4 | ||
--> | ||
|
||
# Messages | ||
|
||
## MsgEthereumTx | ||
|
||
An EVM state transition can be achieved by using the `MsgEthereumTx`. This message encapsulates an | ||
Ethereum transaction as an SDK message and contains the necessary transaction data fields. | ||
|
||
One remark about the `MsgEthereumTx` is that it implements both the [`sdk.Msg`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.2/types/tx_msg.go#L7-L29) and [`sdk.Tx`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.2/types/tx_msg.go#L33-L41) | ||
interfaces (generally SDK messages only implement the former, while the latter is a group of | ||
messages bundled together). The reason of this, is because the `MsgEthereumTx` must not be included in a [`auth.StdTx`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.2/x/auth/types/stdtx.go#L23-L30) (SDK's standard transaction type) as it performs gas and fee checks using the Ethereum logic from Geth instead of the Cosmos SDK checks done on the `auth` module `AnteHandler`. | ||
|
||
+++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/msg.go#L117-L124 | ||
|
||
+++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/tx_data.go#L12-L29 | ||
|
||
This message validation is expected to fail if: | ||
|
||
- `Data.Price` (i.e gas price) is ≤ 0. | ||
- `Data.Amount` is negative | ||
|
||
The transaction execution is expected to fail if: | ||
|
||
- Any of the custom `AnteHandler` Ethereum decorators checks fail: | ||
- Minimum gas amount requirements for transaction | ||
- Tx sender account doesn't exist or hasn't enough balance for fees | ||
- Account sequence doesn't match the transaction `Data.AccountNonce` | ||
- Message signature verification fails | ||
- EVM contract creation (i.e `evm.Create`) fails, or `evm.Call` fails |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<!-- | ||
order: 5 | ||
--> | ||
|
||
# ABCI | ||
|
||
## InitGenesis | ||
|
||
`InitGenesis` initializes the EVM module genesis state by setting the `GenesisState` fields to the | ||
store. In particular it sets the parameters, configuration, accounts and transaction logs. | ||
|
||
The function also performs the invariant that the EVM balance from the `GenesisAccount` matches the | ||
balance amount from the `EthAccount` as defined on the `auth` module. | ||
|
||
## ExportGenesis | ||
|
||
The `ExportGenesis` ABCI function exports the genesis state of the EVM module. In particular, it | ||
retrieves all the accounts with their bytecode, balance and storage, the transaction logs, and the | ||
EVM parameters and chain configuration. | ||
|
||
## BeginBlock | ||
|
||
The EVM module `BeginBlock` logic is executed prior to handling the state transitions from the | ||
transactions. The main objective of this function is to: | ||
|
||
* Set the block header hash mappings to the module state (`hash -> height` and `height -> hash`). | ||
This workaround is due to the fact that until the `v0.34.0` Tendermint version it wasn't possible | ||
to query and subscribe to a block by hash. | ||
|
||
* Reset bloom filter and block transaction count. These variables, which are fields of the EVM | ||
`Keeper`, are updated on every EVM transaction. | ||
|
||
## EndBlock | ||
|
||
The EVM module `EndBlock` logic occurs after executing all the state transitions from the | ||
transactions. The main objective of this function is to: | ||
|
||
* Update the accounts. This operation retrieves the current account and balance values for each | ||
state object and updates the account represented on the stateObject with the given values. This is | ||
done since the account might have been updated by transactions other than the ones defined by the | ||
`x/evm` module, such as bank send or IBC transfers. | ||
* Commit dirty state objects and delete empty ones from the store. This operation writes the | ||
contract code to the key value store in the case of contracts and updates the account's balance, | ||
which is set to the the bank module's `Keeper`. | ||
* Clear account cache. This clears cache of state objects to handle account changes outside of the | ||
EVM. | ||
* Store the block bloom to state. This is due for Web3 compatibility as the Ethereum headers contain | ||
this type as a field. The Ethermint RPC uses this query to construct an Ethereum Header from a | ||
Tendermint Header. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<!-- | ||
order: 6 | ||
--> | ||
|
||
# Events | ||
|
||
The EVM module emits the Cosmos SDK [events](./../../../docs/quickstart/events.md#sdk-and-tendermint-events) after a state execution. It can be expected that the type `message`, with an | ||
attribute key of `action` will represent the first event for each message being processed as emitted | ||
by the Cosmos SDK's `Baseapp` (i.e the the basic application that implements Tendermint Core's ABCI | ||
interface). | ||
|
||
## MsgEthereumTx | ||
|
||
| Type | Attribute Key | Attribute Value | | ||
|----------|---------------|-----------------| | ||
| ethereum | `"amount"` | `{amount}` | | ||
| ethereum | `"recipient"` | `{eth_address}` | | ||
| message | `"sender"` | `{eth_address}` | | ||
| message | `"action"` | `"ethereum"` | | ||
| message | `"module"` | `"evm"` | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<!-- | ||
order: 7 | ||
--> | ||
|
||
# Parameters | ||
|
||
The evm module contains the following parameters: | ||
|
||
| Key | Type | Default Value | | ||
|----------------|--------|---------------| | ||
| `EVMDenom` | string | `"aphoton"` | | ||
| `EnableCreate` | bool | `true` | | ||
| `EnableCall` | bool | `true` | | ||
| `ExtraEIPs` | []int | TBD | | ||
|
||
## EVM denom | ||
|
||
The evm denomination parameter defines the token denomination used on the EVM state transitions and | ||
gas consumption for EVM messages. | ||
|
||
The EVM Denom is used on the following cases: | ||
|
||
* `AnteHandler`: for calculating sufficient balance to pay for gas cost or transaction fees. | ||
* `journal`: to revert certain state executions (`balanceChange` and `suicideChange`). | ||
* `stateObject`: to track the `evm_denom` balance of the object account. | ||
* `CommitStateDB`: to update account balance from an existing state object. | ||
|
||
For example, on Ethereum, the `evm_denom` would be `ETH`. In the case of Ethermint, the default denomination is the [atto photon](./../../../docs/basics/photon.md). In terms of precision, the `PHOTON` and `ETH` share the same value, _i.e_ `1 PHOTON = 10^18 atto photon` and `1 ETH = 10^18 wei`. | ||
|
||
::: danger | ||
SDK applications that want to import the EVM module as a dependency will need to set their own `evm_denom` (i.e not `"aphoton"`). | ||
::: | ||
|
||
## Enable Create | ||
|
||
The enable create parameter toggles state transitions that use the `vm.Create` function. When the | ||
parameter is disabled, it will prevent all contract creation functionality. | ||
|
||
## Enable Transfer | ||
|
||
The enable transfer toggles state transitions that use the `vm.Call` function. When the parameter is | ||
disabled, it will prevent transfers between accounts and executing a smart contract call. | ||
|
||
## Extra EIPs | ||
|
||
The extra EIPs parameter defines the set of activateable Ethereum Improvement Proposals ([EIPs](https://ethereum.org/en/eips/)) | ||
on the Ethereum VM `Config` that apply custom jump tables. | ||
The supported activateable EIPS are: | ||
|
||
* [EIP 1344](https://eips.ethereum.org/EIPS/eip-1344) | ||
* [EIP 1884](https://eips.ethereum.org/EIPS/eip-1884) | ||
* [EIP 2200](https://eips.ethereum.org/EIPS/eip-2200) | ||
* [EIP 2315](https://eips.ethereum.org/EIPS/eip-2315) | ||
* [EIP 2929](https://eips.ethereum.org/EIPS/eip-2929) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this no longer in
EndBlock
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because the values won't be exported so there's no need to add it on the end block