From cfa45785c0ee37a6e5db75b770cd340bfc2507a5 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 23 Sep 2020 22:15:26 +0200 Subject: [PATCH 01/17] evm: module specification --- x/evm/spec/01_concepts.md | 5 ++++ x/evm/spec/02_state.md | 5 ++++ x/evm/spec/03_state_transitions.md | 5 ++++ x/evm/spec/04_messages.md | 5 ++++ x/evm/spec/05_abci.md | 5 ++++ x/evm/spec/06_events.md | 5 ++++ x/evm/spec/07_paramaters.md | 5 ++++ x/evm/spec/README.md | 43 +++++++++++++++++++++++++++--- 8 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 x/evm/spec/01_concepts.md create mode 100644 x/evm/spec/02_state.md create mode 100644 x/evm/spec/03_state_transitions.md create mode 100644 x/evm/spec/04_messages.md create mode 100644 x/evm/spec/05_abci.md create mode 100644 x/evm/spec/06_events.md create mode 100644 x/evm/spec/07_paramaters.md diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md new file mode 100644 index 000000000..31cbdc546 --- /dev/null +++ b/x/evm/spec/01_concepts.md @@ -0,0 +1,5 @@ + + +# Concepts diff --git a/x/evm/spec/02_state.md b/x/evm/spec/02_state.md new file mode 100644 index 000000000..3fd81541e --- /dev/null +++ b/x/evm/spec/02_state.md @@ -0,0 +1,5 @@ + + +# State diff --git a/x/evm/spec/03_state_transitions.md b/x/evm/spec/03_state_transitions.md new file mode 100644 index 000000000..4782e38a4 --- /dev/null +++ b/x/evm/spec/03_state_transitions.md @@ -0,0 +1,5 @@ + + +# State Transitions diff --git a/x/evm/spec/04_messages.md b/x/evm/spec/04_messages.md new file mode 100644 index 000000000..f644c71a6 --- /dev/null +++ b/x/evm/spec/04_messages.md @@ -0,0 +1,5 @@ + + +# Messages diff --git a/x/evm/spec/05_abci.md b/x/evm/spec/05_abci.md new file mode 100644 index 000000000..932c4e780 --- /dev/null +++ b/x/evm/spec/05_abci.md @@ -0,0 +1,5 @@ + + +# ABCI diff --git a/x/evm/spec/06_events.md b/x/evm/spec/06_events.md new file mode 100644 index 000000000..ed27b9128 --- /dev/null +++ b/x/evm/spec/06_events.md @@ -0,0 +1,5 @@ + + +# Events diff --git a/x/evm/spec/07_paramaters.md b/x/evm/spec/07_paramaters.md new file mode 100644 index 000000000..05d123aba --- /dev/null +++ b/x/evm/spec/07_paramaters.md @@ -0,0 +1,5 @@ + + +# Parameters diff --git a/x/evm/spec/README.md b/x/evm/spec/README.md index fc9247e5d..d191dd5d1 100644 --- a/x/evm/spec/README.md +++ b/x/evm/spec/README.md @@ -9,8 +9,45 @@ parent: ## Abstract - +This document defines the specification of the Ethereum Virtual Machine (EVM) as a Cosmos SDK module. -## Content +## Contents - \ No newline at end of file +1. **[Concepts](01_concepts.md)** +2. **[State](02_state.md)** +3. **[State Transitions](03_state_transitions.md)** +4. **[Messages](04_messages.md)** +5. **[ABCI](05_abci.md)** +6. **[Events](06_events.md)** +7. **[Parameters](07_params.md)** + +## Module Architecture + +> **NOTE for auditors**: If you're not familiar with the overall module structure from +the SDK modules, please check this [document](https://docs.cosmos.network/master/building-modules/structure.html) as +prerequisite reading. + +```shell +evm/ +├── client +│ └── cli +│ ├── query.go +│    └── tx.go +├── keeper +│ ├── keeper.go +│ └── querier.go +├── types +│   ├── chain_config.go +│   ├── codec.go # Type registration for encoding +│   ├── errors.go # Module-specific errors +│   ├── events.go # Events exposed to the Tendermint PubSub/Websocket +│   ├── genesis.go # Genesis state for the module +│   ├── journal.go # Ethereum Journal of state transitions +│   ├── msg.go # EVM module transaction messages +│   ├── params.go # Module parameters that can be customized with governance parameter change proposals +│   ├── keys.go # Store keys and utility functions +│   └── tx_data.go # Ethereum transaction data types +├── abci.go # ABCI BeginBlock and EndBlock logic +├── handler.go # Message routing +└── module.go # Module setup for the module manager +``` From 7fb39ffb71f63702e3450391f5ad12130e27ba7c Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 23 Sep 2020 22:49:56 +0200 Subject: [PATCH 02/17] params and events --- x/evm/spec/02_state.md | 2 +- x/evm/spec/06_events.md | 15 +++++++++++++++ x/evm/spec/07_paramaters.md | 5 ----- x/evm/spec/07_params.md | 29 +++++++++++++++++++++++++++++ x/evm/spec/README.md | 2 +- 5 files changed, 46 insertions(+), 7 deletions(-) delete mode 100644 x/evm/spec/07_paramaters.md create mode 100644 x/evm/spec/07_params.md diff --git a/x/evm/spec/02_state.md b/x/evm/spec/02_state.md index 3fd81541e..b57ac80f2 100644 --- a/x/evm/spec/02_state.md +++ b/x/evm/spec/02_state.md @@ -1,5 +1,5 @@ # State diff --git a/x/evm/spec/06_events.md b/x/evm/spec/06_events.md index ed27b9128..1cdd24b64 100644 --- a/x/evm/spec/06_events.md +++ b/x/evm/spec/06_events.md @@ -3,3 +3,18 @@ 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 | diff --git a/x/evm/spec/07_paramaters.md b/x/evm/spec/07_paramaters.md deleted file mode 100644 index 05d123aba..000000000 --- a/x/evm/spec/07_paramaters.md +++ /dev/null @@ -1,5 +0,0 @@ - - -# Parameters diff --git a/x/evm/spec/07_params.md b/x/evm/spec/07_params.md new file mode 100644 index 000000000..887bba565 --- /dev/null +++ b/x/evm/spec/07_params.md @@ -0,0 +1,29 @@ + + +# Parameters + +The evm module contains the following parameters: + +| Key | Type | Default Value | +|------------|--------|---------------| +| `EVMDenom` | string | `aphoton` | + +## EVMDenom + +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. + +::: 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"`). +::: diff --git a/x/evm/spec/README.md b/x/evm/spec/README.md index d191dd5d1..29916ab64 100644 --- a/x/evm/spec/README.md +++ b/x/evm/spec/README.md @@ -23,7 +23,7 @@ This document defines the specification of the Ethereum Virtual Machine (EVM) as ## Module Architecture -> **NOTE for auditors**: If you're not familiar with the overall module structure from +> **NOTE:**: If you're not familiar with the overall module structure from the SDK modules, please check this [document](https://docs.cosmos.network/master/building-modules/structure.html) as prerequisite reading. From 0d6501f916d6d017b5f1556736ea256414fd51c3 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 23 Sep 2020 23:27:47 +0200 Subject: [PATCH 03/17] readme and messages --- x/evm/spec/04_messages.md | 41 +++++++++++++++++++++++++++++++++++++++ x/evm/spec/README.md | 17 +++++++++++----- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/x/evm/spec/04_messages.md b/x/evm/spec/04_messages.md index f644c71a6..4ea7d754e 100644 --- a/x/evm/spec/04_messages.md +++ b/x/evm/spec/04_messages.md @@ -3,3 +3,44 @@ order: 4 --> # Messages + +## MsgEthereumTx + +An EVM state transition can be achieved by using the `MsgEthereumTx`: + +```go +// MsgEthereumTx encapsulates an Ethereum transaction as an SDK message. +type MsgEthereumTx struct { + Data TxData + + // caches + size atomic.Value + from atomic.Value +} +``` + +```go +// TxData implements the Ethereum transaction data structure. It is used +// solely as intended in Ethereum abiding by the protocol. +type TxData struct { + AccountNonce uint64 `json:"nonce"` + Price *big.Int `json:"gasPrice"` + GasLimit uint64 `json:"gas"` + Recipient *ethcmn.Address `json:"to" rlp:"nil"` // nil means contract creation + Amount *big.Int `json:"value"` + Payload []byte `json:"input"` + + // signature values + V *big.Int `json:"v"` + R *big.Int `json:"r"` + S *big.Int `json:"s"` + + // hash is only used when marshaling to JSON + Hash *ethcmn.Hash `json:"hash" rlp:"-"` +} +``` + +This message is expected to fail if: + +- `Data.Price` (i.e gas price) is ≤ 0. +- `Data.Amount` is negative diff --git a/x/evm/spec/README.md b/x/evm/spec/README.md index 29916ab64..863ab7878 100644 --- a/x/evm/spec/README.md +++ b/x/evm/spec/README.md @@ -31,11 +31,13 @@ prerequisite reading. evm/ ├── client │ └── cli -│ ├── query.go -│    └── tx.go +│ ├── query.go # CLI query commands for the module +│    └── tx.go # CLI transaction commands for the module ├── keeper -│ ├── keeper.go -│ └── querier.go +│ ├── keeper.go # Store keeper that handles the business logic of the module and has access to a specific subtree of the state tree. +│ ├── params.go # Parameter getter and setter +│ ├── querier.go # State query functions +│ └── statedb.go # Functions from types/statedb with a passed in sdk.Context ├── types │   ├── chain_config.go │   ├── codec.go # Type registration for encoding @@ -43,11 +45,16 @@ evm/ │   ├── events.go # Events exposed to the Tendermint PubSub/Websocket │   ├── genesis.go # Genesis state for the module │   ├── journal.go # Ethereum Journal of state transitions +│   ├── keys.go # Store keys and utility functions +│   ├── logs.go # Types for persisting Ethereum tx logs on state after chain upgrades │   ├── msg.go # EVM module transaction messages │   ├── params.go # Module parameters that can be customized with governance parameter change proposals -│   ├── keys.go # Store keys and utility functions +│   ├── state_object.go # EVM state object +│   ├── statedb.go # Implementation of the StateDb interface +│   ├── storage.go # Implementation of the Ethereum state storage map using arrays to prevent non-determinism │   └── tx_data.go # Ethereum transaction data types ├── abci.go # ABCI BeginBlock and EndBlock logic +├── genesis.go # ABCI InitGenesis and ExportGenesis functionality ├── handler.go # Message routing └── module.go # Module setup for the module manager ``` From d7f9b5bb2a1a7b3bfd9b456c3d3fc9e0dd5f7952 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Thu, 24 Sep 2020 10:11:53 +0200 Subject: [PATCH 04/17] minor updates --- x/evm/spec/01_concepts.md | 12 ++++++++++++ x/evm/spec/02_state.md | 3 +++ x/evm/spec/03_state_transitions.md | 2 ++ x/evm/spec/04_messages.md | 19 ++++++++++++++++--- x/evm/spec/05_abci.md | 8 ++++++++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md index 31cbdc546..bd1d98430 100644 --- a/x/evm/spec/01_concepts.md +++ b/x/evm/spec/01_concepts.md @@ -3,3 +3,15 @@ order: 1 --> # Concepts + +## EVM + +EVM is the Ethereum Virtual Machine that the necessary tools to run or create a contract on a given state. + +## State DB + +The `StateDB` is represents an EVM database for full state querying of both contracts and accounts. + +## State Object + +## Chain Config diff --git a/x/evm/spec/02_state.md b/x/evm/spec/02_state.md index b57ac80f2..40347ff30 100644 --- a/x/evm/spec/02_state.md +++ b/x/evm/spec/02_state.md @@ -3,3 +3,6 @@ order: 2 --> # State + + + \ No newline at end of file diff --git a/x/evm/spec/03_state_transitions.md b/x/evm/spec/03_state_transitions.md index 4782e38a4..58c6c178d 100644 --- a/x/evm/spec/03_state_transitions.md +++ b/x/evm/spec/03_state_transitions.md @@ -3,3 +3,5 @@ order: 3 --> # State Transitions + + \ No newline at end of file diff --git a/x/evm/spec/04_messages.md b/x/evm/spec/04_messages.md index 4ea7d754e..9dfd0659d 100644 --- a/x/evm/spec/04_messages.md +++ b/x/evm/spec/04_messages.md @@ -6,10 +6,14 @@ order: 4 ## MsgEthereumTx -An EVM state transition can be achieved by using the `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.1/types/tx_msg.go#L7-L29) and [`sdk.Tx`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.1/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.1/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`. ```go -// MsgEthereumTx encapsulates an Ethereum transaction as an SDK message. type MsgEthereumTx struct { Data TxData @@ -40,7 +44,16 @@ type TxData struct { } ``` -This message is expected to fail if: +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 diff --git a/x/evm/spec/05_abci.md b/x/evm/spec/05_abci.md index 932c4e780..4de02bea2 100644 --- a/x/evm/spec/05_abci.md +++ b/x/evm/spec/05_abci.md @@ -3,3 +3,11 @@ order: 5 --> # ABCI + +## InitGenesis + +## ExportGenesis + +## BeginBlock + +## EndBlock From e9eb6d83bc345f6fd2437fd779e0d5311a02faf8 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 21:02:26 +0200 Subject: [PATCH 05/17] concepts --- x/evm/spec/01_concepts.md | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md index bd1d98430..8fc515e4b 100644 --- a/x/evm/spec/01_concepts.md +++ b/x/evm/spec/01_concepts.md @@ -15,3 +15,70 @@ The `StateDB` is represents an EVM database for full state querying of both cont ## State Object ## 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. + +```go +type ChainConfig struct { + HomesteadBlock sdk.Int `json:"homestead_block" yaml:"homestead_block"` // Homestead switch block (< 0 no fork, 0 = already homestead) + + DAOForkBlock sdk.Int `json:"dao_fork_block" yaml:"dao_fork_block"` // TheDAO hard-fork switch block (< 0 no fork) + DAOForkSupport bool `json:"dao_fork_support" yaml:"dao_fork_support"` // Whether the nodes supports or opposes the DAO hard-fork + + // EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) + EIP150Block sdk.Int `json:"eip150_block" yaml:"eip150_block"` // EIP150 HF block (< 0 no fork) + EIP150Hash string `json:"eip150_hash" yaml:"eip150_hash"` // EIP150 HF hash (needed for header only clients as only gas pricing changed) + + EIP155Block sdk.Int `json:"eip155_block" yaml:"eip155_block"` // EIP155 HF block + EIP158Block sdk.Int `json:"eip158_block" yaml:"eip158_block"` // EIP158 HF block + + ByzantiumBlock sdk.Int `json:"byzantium_block" yaml:"byzantium_block"` // Byzantium switch block (< 0 no fork, 0 = already on byzantium) + ConstantinopleBlock sdk.Int `json:"constantinople_block" yaml:"constantinople_block"` // Constantinople switch block (< 0 no fork, 0 = already activated) + PetersburgBlock sdk.Int `json:"petersburg_block" yaml:"petersburg_block"` // Petersburg switch block (< 0 same as Constantinople) + IstanbulBlock sdk.Int `json:"istanbul_block" yaml:"istanbul_block"` // Istanbul switch block (< 0 no fork, 0 = already on istanbul) + MuirGlacierBlock sdk.Int `json:"muir_glacier_block" yaml:"muir_glacier_block"` // Eip-2384 (bomb delay) switch block (< 0 no fork, 0 = already activated) + + YoloV1Block sdk.Int `json:"yoloV1_block" yaml:"yoloV1_block"` // YOLO v1: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet) + EWASMBlock sdk.Int `json:"ewasm_block" yaml:"ewasm_block"` // EWASM switch block (< 0 no fork, 0 = already activated) +} +``` + +## Genesis State + +The `x/evm` module `GenesisState` defines the state necessary for initializing the chain from a previous exported height. + + + +```go +// GenesisState defines the evm module genesis state +type GenesisState struct { + Accounts []GenesisAccount `json:"accounts"` + TxsLogs []TransactionLogs `json:"txs_logs"` + ChainConfig ChainConfig `json:"chain_config"` + Params Params `json:"params"` +} +``` + +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`,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 AccountKeeper and the balance must match the balance of the `EvmDenom` token denomination defined on the `GenesisState`'s `Param`. + +```go +type GenesisAccount struct { + Address ethcmn.Address `json:"address"` + Balance *big.Int `json:"balance"` + Code hexutil.Bytes `json:"code,omitempty"` + Storage Storage `json:"storage,omitempty"` +} +``` From 4bbe0edfbe99d070a958a7a5db1ba05501be74e1 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 30 Sep 2020 10:35:39 +0200 Subject: [PATCH 06/17] genesis state concept --- x/evm/spec/01_concepts.md | 82 +++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md index 8fc515e4b..6c86ab3a9 100644 --- a/x/evm/spec/01_concepts.md +++ b/x/evm/spec/01_concepts.md @@ -10,11 +10,59 @@ EVM is the Ethereum Virtual Machine that the necessary tools to run or create a ## State DB -The `StateDB` is represents an EVM database for full state querying of both contracts and accounts. +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 -## Chain Config + + +## Genesis State + +The `x/evm` module `GenesisState` defines the state necessary for initializing the chain from a previous exported height. + +```go +// GenesisState defines the evm module genesis state +type GenesisState struct { + Accounts []GenesisAccount `json:"accounts"` + TxsLogs []TransactionLogs `json:"txs_logs"` + ChainConfig ChainConfig `json:"chain_config"` + Params Params `json:"params"` +} +``` + +### 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`,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 AccountKeeper and the balance must match the balance of the `EvmDenom` token denomination defined on the `GenesisState`'s `Param`. + +```go +type GenesisAccount struct { + Address ethcmn.Address `json:"address"` + Balance *big.Int `json:"balance"` + Code hexutil.Bytes `json:"code,omitempty"` + Storage Storage `json:"storage,omitempty"` +} +``` + +### 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. + +```go +type TransactionLogs struct { + Hash ethcmn.Hash `json:"hash"` + Logs []*ethtypes.Log `json:"logs"` +} +``` + +### 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 @@ -53,32 +101,6 @@ type ChainConfig struct { } ``` -## Genesis State - -The `x/evm` module `GenesisState` defines the state necessary for initializing the chain from a previous exported height. - - - -```go -// GenesisState defines the evm module genesis state -type GenesisState struct { - Accounts []GenesisAccount `json:"accounts"` - TxsLogs []TransactionLogs `json:"txs_logs"` - ChainConfig ChainConfig `json:"chain_config"` - Params Params `json:"params"` -} -``` - -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`,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 AccountKeeper and the balance must match the balance of the `EvmDenom` token denomination defined on the `GenesisState`'s `Param`. +### Params -```go -type GenesisAccount struct { - Address ethcmn.Address `json:"address"` - Balance *big.Int `json:"balance"` - Code hexutil.Bytes `json:"code,omitempty"` - Storage Storage `json:"storage,omitempty"` -} -``` +See the [params](07_params.md) document for further information about parameters. From 66f8a12ba3b0170f9ba6f190d698ea2b4d95a065 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 30 Sep 2020 12:54:24 +0200 Subject: [PATCH 07/17] begin and end block --- x/evm/abci.go | 1 - x/evm/spec/01_concepts.md | 4 ++++ x/evm/spec/05_abci.md | 13 +++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/x/evm/abci.go b/x/evm/abci.go index 61c40c7bb..a215294c8 100644 --- a/x/evm/abci.go +++ b/x/evm/abci.go @@ -25,7 +25,6 @@ func BeginBlock(k Keeper, ctx sdk.Context, req abci.RequestBeginBlock) { } // EndBlock updates the accounts and commits states objects to the KV Store. -// func EndBlock(k Keeper, ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { // Gas costs are handled within msg handler so costs should be ignored ctx = ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter()) diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md index 6c86ab3a9..cc7a1f347 100644 --- a/x/evm/spec/01_concepts.md +++ b/x/evm/spec/01_concepts.md @@ -14,7 +14,11 @@ The `StateDB` interface from geth represents an EVM database for full state quer ## State Object +`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 diff --git a/x/evm/spec/05_abci.md b/x/evm/spec/05_abci.md index 4de02bea2..3f0988422 100644 --- a/x/evm/spec/05_abci.md +++ b/x/evm/spec/05_abci.md @@ -10,4 +10,17 @@ order: 5 ## 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 to the module state. 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. From 2189e71e7d8ed421481acf4040b6ae0fe99c3f11 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 7 Dec 2020 13:29:06 -0300 Subject: [PATCH 08/17] update parameters and genesis --- x/evm/spec/01_concepts.md | 14 +++++++------- x/evm/spec/05_abci.md | 30 +++++++++++++++++++++--------- x/evm/spec/07_params.md | 20 ++++++++++++++++---- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md index cc7a1f347..091d285be 100644 --- a/x/evm/spec/01_concepts.md +++ b/x/evm/spec/01_concepts.md @@ -39,14 +39,14 @@ type GenesisState struct { 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`,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 AccountKeeper and the balance must match the balance of the `EvmDenom` token denomination defined on the `GenesisState`'s `Param`. +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. ```go type GenesisAccount struct { - Address ethcmn.Address `json:"address"` - Balance *big.Int `json:"balance"` - Code hexutil.Bytes `json:"code,omitempty"` - Storage Storage `json:"storage,omitempty"` + Address string `json:"address"` + Balance sdk.Int `json:"balance"` + Code hexutil.Bytes `json:"code,omitempty"` + Storage Storage `json:"storage,omitempty"` } ``` @@ -68,7 +68,7 @@ type TransactionLogs struct { ### Chain Config -The `ChainConfig` is a custom type that contains the same fields as the go-ethereum ChainConfig +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. @@ -100,7 +100,7 @@ type ChainConfig struct { IstanbulBlock sdk.Int `json:"istanbul_block" yaml:"istanbul_block"` // Istanbul switch block (< 0 no fork, 0 = already on istanbul) MuirGlacierBlock sdk.Int `json:"muir_glacier_block" yaml:"muir_glacier_block"` // Eip-2384 (bomb delay) switch block (< 0 no fork, 0 = already activated) - YoloV1Block sdk.Int `json:"yoloV1_block" yaml:"yoloV1_block"` // YOLO v1: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet) + YoloV2Block sdk.Int `json:"yoloV2_block" yaml:"yoloV2_block"` // YOLO v2: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet) EWASMBlock sdk.Int `json:"ewasm_block" yaml:"ewasm_block"` // EWASM switch block (< 0 no fork, 0 = already activated) } ``` diff --git a/x/evm/spec/05_abci.md b/x/evm/spec/05_abci.md index 3f0988422..45f7685de 100644 --- a/x/evm/spec/05_abci.md +++ b/x/evm/spec/05_abci.md @@ -10,17 +10,29 @@ order: 5 ## 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: +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 to the module state. 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. +* Set the block header hash to the module state. 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. +* 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. +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. diff --git a/x/evm/spec/07_params.md b/x/evm/spec/07_params.md index 887bba565..4186c46bc 100644 --- a/x/evm/spec/07_params.md +++ b/x/evm/spec/07_params.md @@ -6,11 +6,13 @@ order: 7 The evm module contains the following parameters: -| Key | Type | Default Value | -|------------|--------|---------------| -| `EVMDenom` | string | `aphoton` | +| Key | Type | Default Value | +|----------------|--------|---------------| +| `EVMDenom` | string | `aphoton` | +| `EnableCreate` | bool | `true` | +| `EnableCall` | bool | `true` | -## EVMDenom +## EVM denom The evm denomination parameter defines the token denomination used on the EVM state transitions and gas consumption for EVM messages. @@ -27,3 +29,13 @@ For example, on Ethereum, the `evm_denom` would be `ETH`. In the case of Ethermi ::: 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. From f7a00c45cd487dad156488a4e8b207cd9c26fe7a Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 7 Dec 2020 16:50:51 -0300 Subject: [PATCH 09/17] state objects --- x/evm/spec/01_concepts.md | 20 ++++++++++++++------ x/evm/spec/02_state.md | 31 ++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md index 091d285be..c822f5068 100644 --- a/x/evm/spec/01_concepts.md +++ b/x/evm/spec/01_concepts.md @@ -10,15 +10,17 @@ EVM is the Ethereum Virtual Machine that the necessary tools to run or create a ## 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`. +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 `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. +* First you need to obtain a state object. +* Account values can be accessed and modified through the object. ## Genesis State @@ -37,9 +39,14 @@ type GenesisState struct { ### 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`,and that it doesn't contain the private key field. +main difference is that the one on Ethermint uses a custom `Storage` type that uses a slice instead +of maps for the evm `State`,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. +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. ```go type GenesisAccount struct { @@ -57,7 +64,8 @@ execution that are used by the JSON-RPC Web3 server for for filter querying. Sin 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. +`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. ```go type TransactionLogs struct { diff --git a/x/evm/spec/02_state.md b/x/evm/spec/02_state.md index 40347ff30..3def41548 100644 --- a/x/evm/spec/02_state.md +++ b/x/evm/spec/02_state.md @@ -4,5 +4,34 @@ order: 2 # State + - \ No newline at end of file + +## `CommitStateDB` + + +## 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. + + + +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) From 79e574fd232db88b442e91abd3308c7b4ace8923 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 7 Dec 2020 18:19:53 -0300 Subject: [PATCH 10/17] state table --- x/evm/spec/02_state.md | 48 ++++++++++++++++++++++++++++++++++++++++-- x/evm/spec/README.md | 2 +- x/evm/types/statedb.go | 2 +- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/x/evm/spec/02_state.md b/x/evm/spec/02_state.md index 3def41548..5fc15d5c9 100644 --- a/x/evm/spec/02_state.md +++ b/x/evm/spec/02_state.md @@ -4,11 +4,55 @@ 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 @@ -24,7 +68,7 @@ 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: diff --git a/x/evm/spec/README.md b/x/evm/spec/README.md index 863ab7878..272704a62 100644 --- a/x/evm/spec/README.md +++ b/x/evm/spec/README.md @@ -34,6 +34,7 @@ evm/ │ ├── query.go # CLI query commands for the module │    └── tx.go # CLI transaction commands for the module ├── keeper +│ ├── keeper.go # ABCI BeginBlock and EndBlock logic │ ├── keeper.go # Store keeper that handles the business logic of the module and has access to a specific subtree of the state tree. │ ├── params.go # Parameter getter and setter │ ├── querier.go # State query functions @@ -53,7 +54,6 @@ evm/ │   ├── statedb.go # Implementation of the StateDb interface │   ├── storage.go # Implementation of the Ethereum state storage map using arrays to prevent non-determinism │   └── tx_data.go # Ethereum transaction data types -├── abci.go # ABCI BeginBlock and EndBlock logic ├── genesis.go # ABCI InitGenesis and ExportGenesis functionality ├── handler.go # Message routing └── module.go # Module setup for the module manager diff --git a/x/evm/types/statedb.go b/x/evm/types/statedb.go index 688bb7c5a..84ee2176a 100644 --- a/x/evm/types/statedb.go +++ b/x/evm/types/statedb.go @@ -32,7 +32,7 @@ type revision struct { // CommitStateDB implements the Geth state.StateDB interface. Instead of using // a trie and database for querying and persistence, the Keeper uses KVStores -// and an account mapper is used to facilitate state transitions. +// and an AccountKeeper to facilitate state transitions. // // TODO: This implementation is subject to change in regards to its statefull // manner. In otherwords, how this relates to the keeper in this module. From ef16558f23b310db9c17d0edd520a45ee4292ec4 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 7 Dec 2020 18:32:15 -0300 Subject: [PATCH 11/17] use permalink --- x/evm/spec/01_concepts.md | 51 +++------------------------------------ x/evm/spec/04_messages.md | 33 +++---------------------- 2 files changed, 7 insertions(+), 77 deletions(-) diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md index c822f5068..ff8b23bbb 100644 --- a/x/evm/spec/01_concepts.md +++ b/x/evm/spec/01_concepts.md @@ -26,15 +26,7 @@ The usage pattern is as follows: The `x/evm` module `GenesisState` defines the state necessary for initializing the chain from a previous exported height. -```go -// GenesisState defines the evm module genesis state -type GenesisState struct { - Accounts []GenesisAccount `json:"accounts"` - TxsLogs []TransactionLogs `json:"txs_logs"` - ChainConfig ChainConfig `json:"chain_config"` - Params Params `json:"params"` -} -``` ++++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/genesis.go#L14-L20 ### Genesis Accounts @@ -48,14 +40,7 @@ module `AccountKeeper` and the balance must match the balance of the `EvmDenom` 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. -```go -type GenesisAccount struct { - Address string `json:"address"` - Balance sdk.Int `json:"balance"` - Code hexutil.Bytes `json:"code,omitempty"` - Storage Storage `json:"storage,omitempty"` -} -``` ++++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/genesis.go#L22-L30 ### Transaction Logs @@ -67,12 +52,7 @@ 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. -```go -type TransactionLogs struct { - Hash ethcmn.Hash `json:"hash"` - Logs []*ethtypes.Log `json:"logs"` -} -``` ++++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/logs.go#L12-L18 ### Chain Config @@ -88,30 +68,7 @@ to a past block). If you want to update the config values, use an software upgrade procedure. -```go -type ChainConfig struct { - HomesteadBlock sdk.Int `json:"homestead_block" yaml:"homestead_block"` // Homestead switch block (< 0 no fork, 0 = already homestead) - - DAOForkBlock sdk.Int `json:"dao_fork_block" yaml:"dao_fork_block"` // TheDAO hard-fork switch block (< 0 no fork) - DAOForkSupport bool `json:"dao_fork_support" yaml:"dao_fork_support"` // Whether the nodes supports or opposes the DAO hard-fork - - // EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) - EIP150Block sdk.Int `json:"eip150_block" yaml:"eip150_block"` // EIP150 HF block (< 0 no fork) - EIP150Hash string `json:"eip150_hash" yaml:"eip150_hash"` // EIP150 HF hash (needed for header only clients as only gas pricing changed) - - EIP155Block sdk.Int `json:"eip155_block" yaml:"eip155_block"` // EIP155 HF block - EIP158Block sdk.Int `json:"eip158_block" yaml:"eip158_block"` // EIP158 HF block - - ByzantiumBlock sdk.Int `json:"byzantium_block" yaml:"byzantium_block"` // Byzantium switch block (< 0 no fork, 0 = already on byzantium) - ConstantinopleBlock sdk.Int `json:"constantinople_block" yaml:"constantinople_block"` // Constantinople switch block (< 0 no fork, 0 = already activated) - PetersburgBlock sdk.Int `json:"petersburg_block" yaml:"petersburg_block"` // Petersburg switch block (< 0 same as Constantinople) - IstanbulBlock sdk.Int `json:"istanbul_block" yaml:"istanbul_block"` // Istanbul switch block (< 0 no fork, 0 = already on istanbul) - MuirGlacierBlock sdk.Int `json:"muir_glacier_block" yaml:"muir_glacier_block"` // Eip-2384 (bomb delay) switch block (< 0 no fork, 0 = already activated) - - YoloV2Block sdk.Int `json:"yoloV2_block" yaml:"yoloV2_block"` // YOLO v2: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet) - EWASMBlock sdk.Int `json:"ewasm_block" yaml:"ewasm_block"` // EWASM switch block (< 0 no fork, 0 = already activated) -} -``` ++++ https://github.com/cosmos/ethermint/blob/v0.3.1/x/evm/types/chain_config.go#L16-L45 ### Params diff --git a/x/evm/spec/04_messages.md b/x/evm/spec/04_messages.md index 9dfd0659d..fccb9a3d1 100644 --- a/x/evm/spec/04_messages.md +++ b/x/evm/spec/04_messages.md @@ -13,36 +13,9 @@ One remark about the `MsgEthereumTx` is that it implements both the [`sdk.Msg`]( 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.1/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`. -```go -type MsgEthereumTx struct { - Data TxData - - // caches - size atomic.Value - from atomic.Value -} -``` - -```go -// TxData implements the Ethereum transaction data structure. It is used -// solely as intended in Ethereum abiding by the protocol. -type TxData struct { - AccountNonce uint64 `json:"nonce"` - Price *big.Int `json:"gasPrice"` - GasLimit uint64 `json:"gas"` - Recipient *ethcmn.Address `json:"to" rlp:"nil"` // nil means contract creation - Amount *big.Int `json:"value"` - Payload []byte `json:"input"` - - // signature values - V *big.Int `json:"v"` - R *big.Int `json:"r"` - S *big.Int `json:"s"` - - // hash is only used when marshaling to JSON - Hash *ethcmn.Hash `json:"hash" rlp:"-"` -} -``` ++++ 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: From ff6eaec5a87358f6204f8cefb577709dc305694d Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 7 Dec 2020 18:55:12 -0300 Subject: [PATCH 12/17] init and export genesis --- x/evm/spec/05_abci.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/x/evm/spec/05_abci.md b/x/evm/spec/05_abci.md index 45f7685de..c3490b2e3 100644 --- a/x/evm/spec/05_abci.md +++ b/x/evm/spec/05_abci.md @@ -6,8 +6,18 @@ order: 5 ## 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 From 1885e4bf0f87e162c83a933c13789a624f839c27 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 7 Dec 2020 19:01:46 -0300 Subject: [PATCH 13/17] update abci --- x/evm/keeper/abci.go | 17 +++++++---------- x/evm/spec/05_abci.md | 5 +++-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/x/evm/keeper/abci.go b/x/evm/keeper/abci.go index 896a66577..8c8495a8b 100644 --- a/x/evm/keeper/abci.go +++ b/x/evm/keeper/abci.go @@ -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) // 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) diff --git a/x/evm/spec/05_abci.md b/x/evm/spec/05_abci.md index c3490b2e3..4f2db2790 100644 --- a/x/evm/spec/05_abci.md +++ b/x/evm/spec/05_abci.md @@ -23,8 +23,9 @@ EVM parameters and chain configuration. 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 to the module state. 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. +* 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. From e26df43df89f13f12b5fb8f2712de8127c35d31e Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 8 Dec 2020 10:23:31 -0300 Subject: [PATCH 14/17] extra eips param --- x/evm/spec/04_messages.md | 4 ++-- x/evm/spec/06_events.md | 10 +++++----- x/evm/spec/07_params.md | 23 ++++++++++++++++++----- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/x/evm/spec/04_messages.md b/x/evm/spec/04_messages.md index fccb9a3d1..d31efae84 100644 --- a/x/evm/spec/04_messages.md +++ b/x/evm/spec/04_messages.md @@ -9,9 +9,9 @@ order: 4 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.1/types/tx_msg.go#L7-L29) and [`sdk.Tx`](https://github.com/cosmos/cosmos-sdk/blob/v0.39.1/types/tx_msg.go#L33-L41) +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.1/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`. +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 diff --git a/x/evm/spec/06_events.md b/x/evm/spec/06_events.md index 1cdd24b64..7fbb807cc 100644 --- a/x/evm/spec/06_events.md +++ b/x/evm/spec/06_events.md @@ -13,8 +13,8 @@ interface). | Type | Attribute Key | Attribute Value | |----------|---------------|-----------------| -| ethereum | amount | {amount} | -| ethereum | recipient | {eth_address} | -| message | sender | {eth_address} | -| message | action | ethereum | -| message | module | evm | +| ethereum | `"amount"` | `{amount}` | +| ethereum | `"recipient"` | `{eth_address}` | +| message | `"sender"` | `{eth_address}` | +| message | `"action"` | `"ethereum"` | +| message | `"module"` | `"evm"` | diff --git a/x/evm/spec/07_params.md b/x/evm/spec/07_params.md index 4186c46bc..48b398b05 100644 --- a/x/evm/spec/07_params.md +++ b/x/evm/spec/07_params.md @@ -8,9 +8,10 @@ The evm module contains the following parameters: | Key | Type | Default Value | |----------------|--------|---------------| -| `EVMDenom` | string | `aphoton` | +| `EVMDenom` | string | `"aphoton"` | | `EnableCreate` | bool | `true` | | `EnableCall` | bool | `true` | +| `ExtraEIPs` | []int | TBD | ## EVM denom @@ -19,10 +20,10 @@ 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. +* `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. @@ -39,3 +40,15 @@ parameter is disabled, it will prevent all contract creation functionality. 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) From 285db3fffa1713c0e62651439d8cfde0f4dfa12a Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 9 Dec 2020 11:09:41 -0300 Subject: [PATCH 15/17] review comments --- x/evm/spec/01_concepts.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/x/evm/spec/01_concepts.md b/x/evm/spec/01_concepts.md index ff8b23bbb..4ac6be4f7 100644 --- a/x/evm/spec/01_concepts.md +++ b/x/evm/spec/01_concepts.md @@ -6,7 +6,8 @@ order: 1 ## EVM -EVM is the Ethereum Virtual Machine that the necessary tools to run or create a contract on a given state. +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 @@ -16,7 +17,7 @@ contracts and accounts. The concrete type that fulfills this interface on Etherm ## State Object -`stateObject` represents an Ethereum account which is being modified. +A `stateObject` represents an Ethereum account which is being modified. The usage pattern is as follows: * First you need to obtain a state object. @@ -32,7 +33,8 @@ The `x/evm` module `GenesisState` defines the state necessary for initializing t 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`,and that it doesn't contain the private key field. +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 From ba8bff90ff8f4995b1ab4a1e98a8f8692bc920d9 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 9 Dec 2020 16:02:54 -0300 Subject: [PATCH 16/17] precision --- x/evm/spec/07_params.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/evm/spec/07_params.md b/x/evm/spec/07_params.md index 48b398b05..f2227a433 100644 --- a/x/evm/spec/07_params.md +++ b/x/evm/spec/07_params.md @@ -25,7 +25,7 @@ The EVM Denom is used on the following cases: * `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. +For example, on Ethereum, the `evm_denom` would be `ETH`. In the case of Ethermint, the default denomination is the atto photon. In terms of precision, the `PHOTON` and `ETH` share the same value, `1 PHOTON = 10^18 attophoton` 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"`). From cce210a6347642bb972c7d7e83dc9d99c1309a57 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 9 Dec 2020 16:04:59 -0300 Subject: [PATCH 17/17] link to photon doc --- x/evm/spec/07_params.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/evm/spec/07_params.md b/x/evm/spec/07_params.md index f2227a433..85a02354d 100644 --- a/x/evm/spec/07_params.md +++ b/x/evm/spec/07_params.md @@ -25,7 +25,7 @@ The EVM Denom is used on the following cases: * `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. In terms of precision, the `PHOTON` and `ETH` share the same value, `1 PHOTON = 10^18 attophoton` and `1 ETH = 10^18 wei`. +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"`).