erigon-pulse/cmd/evm
2023-12-15 07:24:03 +07:00
..
internal Sentinel refactor (#8296) 2023-10-22 01:17:18 +02:00
testdata Spell Check: Fix typos (#8480) 2023-10-17 11:21:27 +07:00
compiler.go Upgrade urfave/cli to v2 (#6047) 2022-11-14 17:33:57 +01:00
disasm.go Upgrade urfave/cli to v2 (#6047) 2022-11-14 17:33:57 +01:00
main.go fix build of cli flags (#7377) 2023-04-24 17:47:23 +07:00
README.md cmd/evm:fix Env struct json tag (#8986) 2023-12-15 07:24:03 +07:00
runner.go evm cli: no logs if --json (#8925) 2023-12-09 13:42:07 +07:00
staterunner.go evm cli: no logs if --json (#8925) 2023-12-09 13:42:07 +07:00
t8n_test.go Update t8n_test.go (#7550) 2023-05-19 21:49:51 +01:00
transition-test.sh

EVM tool

The EVM tool provides a few useful subcommands to facilitate testing at the EVM layer.

  • transition tool (t8n) : a stateless state transition utility
  • transaction tool (t9n) : a transaction validation utility
  • block builder tool (b11r): a block assembler utility

State transition tool (t8n)

The evm t8n tool is a stateless state transition utility. It is a utility which can

  1. Take a prestate, including
  • Accounts,
  • Block context information,
  • Previous blockshashes (*optional)
  1. Apply a set of transactions,
  2. Apply a mining-reward (*optional),
  3. And generate a post-state, including
  • State root, transaction root, receipt root,
  • Information about rejected transactions,
  • Optionally: a full or partial post-state dump

Specification

The idea is to specify the behaviour of this binary very strict, so that other node implementors can build replicas based on their own state-machines, and the state generators can swap between a `geth`-based implementation and a `parityvm`-based implementation.

Command line params

Command line params that need to be supported are

    --input.alloc value            (default: "alloc.json")
    --input.env value              (default: "env.json")
    --input.txs value              (default: "txs.json")
    --output.alloc value           (default: "alloc.json")
    --output.basedir value        
    --output.body value           
    --output.result value          (default: "result.json")
    --state.chainid value          (default: 1)
    --state.fork value             (default: "GrayGlacier")
    --state.reward value           (default: 0)
    --trace.memory                 (default: false)
    --trace.nomemory               (default: true)
    --trace.noreturndata           (default: true)
    --trace.nostack                (default: false)
    --trace.returndata             (default: false)

Objects

The transition tool uses JSON objects to read and write data related to the transition operation. The following object definitions are required.

alloc

The alloc object defines the prestate that transition will begin with.

// Map of address to account definition.
type Alloc map[common.Address]Account
// Genesis account. Each field is optional.
type Account struct {
    Code       []byte                           `json:"code"`
    Storage    map[common.Hash]common.Hash      `json:"storage"`
    Balance    *big.Int                         `json:"balance"`
    Nonce      uint64                           `json:"nonce"`
    SecretKey  []byte                            `json:"secretKey"`
}
env

The env object defines the environmental context in which the transition will take place.

type Env struct {
    // required
    CurrentCoinbase  common.Address      `json:"currentCoinbase"`
    CurrentGasLimit  uint64              `json:"currentGasLimit"`
    CurrentNumber    uint64              `json:"currentNumber"`
    CurrentTimestamp uint64              `json:"currentTimestamp"`
    Withdrawals      []*Withdrawal       `json:"withdrawals"`
    // optional
    CurrentDifficulty *big.Int           `json:"currentDifficulty"`
    CurrentRandom     *big.Int           `json:"currentRandom"`
    CurrentBaseFee    *big.Int           `json:"currentBaseFee"`
    ParentDifficulty  *big.Int           `json:"parentDifficulty"`
    ParentGasUsed     uint64             `json:"parentGasUsed"`
    ParentGasLimit    uint64             `json:"parentGasLimit"`
    ParentTimestamp   uint64             `json:"parentTimestamp"`
    BlockHashes       map[uint64]common.Hash `json:"blockHashes"`
    ParentUncleHash   common.Hash        `json:"parentUncleHash"`
    Ommers            []Ommer            `json:"ommers"`
}
type Ommer struct {
    Delta   uint64         `json:"delta"`
    Address common.Address `json:"address"`
}
type Withdrawal struct {
    Index          uint64         `json:"index"`
    ValidatorIndex uint64         `json:"validatorIndex"`
    Recipient      common.Address `json:"recipient"`
    Amount         *big.Int       `json:"amount"`
}
txs

The txs object is an array of any of the transaction types: LegacyTx, AccessListTx, or DynamicFeeTx.

type LegacyTx struct {
	Nonce     uint64          `json:"nonce"`
	GasPrice  *big.Int        `json:"gasPrice"`
	Gas       uint64          `json:"gas"`
	To        *common.Address `json:"to"`
	Value     *big.Int        `json:"value"`
	Data      []byte          `json:"data"`
	V         *big.Int        `json:"v"`
	R         *big.Int        `json:"r"`
	S         *big.Int        `json:"s"`
    SecretKey *common.Hash    `json:"secretKey"`
}
type AccessList []AccessTuple
type AccessTuple struct {
	Address     common.Address `json:"address"        gencodec:"required"`
	StorageKeys []common.Hash  `json:"storageKeys"    gencodec:"required"`
}
type AccessListTx struct {
	ChainID    *big.Int        `json:"chainId"`
	Nonce      uint64          `json:"nonce"`
	GasPrice   *big.Int        `json:"gasPrice"`
	Gas        uint64          `json:"gas"`
	To         *common.Address `json:"to"`
	Value      *big.Int        `json:"value"`
	Data       []byte          `json:"data"`
	AccessList AccessList      `json:"accessList"`
	V          *big.Int        `json:"v"`
	R          *big.Int        `json:"r"`
	S          *big.Int        `json:"s"`
    SecretKey  *common.Hash     `json:"secretKey"`
}
type DynamicFeeTx struct {
	ChainID    *big.Int        `json:"chainId"`
	Nonce      uint64          `json:"nonce"`
	GasTipCap  *big.Int        `json:"maxPriorityFeePerGas"`
	GasFeeCap  *big.Int        `json:"maxFeePerGas"`
	Gas        uint64          `json:"gas"`
	To         *common.Address `json:"to"`
	Value      *big.Int        `json:"value"`
	Data       []byte          `json:"data"`
	AccessList AccessList      `json:"accessList"`
	V          *big.Int        `json:"v"`
	R          *big.Int        `json:"r"`
	S          *big.Int        `json:"s"`
    SecretKey  *common.Hash     `json:"secretKey"`
}
result

The result object is output after a transition is executed. It includes information about the post-transition environment.

type ExecutionResult struct {
    StateRoot   common.Hash    `json:"stateRoot"`
    TxRoot      common.Hash    `json:"txRoot"`
    ReceiptRoot common.Hash    `json:"receiptsRoot"`
    LogsHash    common.Hash    `json:"logsHash"`
    Bloom       types.Bloom    `json:"logsBloom"`
    Receipts    types.Receipts `json:"receipts"`
    Rejected    []*rejectedTx  `json:"rejected,omitempty"`
    Difficulty  *big.Int       `json:"currentDifficulty"`
    GasUsed     uint64         `json:"gasUsed"`
    BaseFee     *big.Int       `json:"currentBaseFee,omitempty"`
}

Error codes and output

All logging should happen against the stderr. There are a few (not many) errors that can occur, those are defined below.

EVM-based errors (2 to 9)
  • Other EVM error. Exit code 2
  • Failed configuration: when a non-supported or invalid fork was specified. Exit code 3.
  • Block history is not supplied, but needed for a BLOCKHASH operation. If BLOCKHASH is invoked targeting a block which history has not been provided for, the program will exit with code 4.
IO errors (10-20)
  • Invalid input json: the supplied data could not be marshalled. The program will exit with code 10
  • IO problems: failure to load or save files, the program will exit with code 11
# This should exit with 3
./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Frontier+1346 2>/dev/null
exitcode:3 OK

Forks

Basic usage

The chain configuration to be used for a transition is specified via the --state.fork CLI flag. A list of possible values and configurations can be found in tests/init.go.

Examples

Basic usage

Invoking it with the provided example files

./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Berlin

Two resulting files:

alloc.json:

{
 "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": {
  "balance": "0xfeed1a9d",
  "nonce": "0x1"
 },
 "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
  "balance": "0x5ffd4878be161d74",
  "nonce": "0xac"
 },
 "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
  "balance": "0xa410"
 }
}

result.json:

{
 "stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13",
 "txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d",
 "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
 "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
 "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 "receipts": [
  {
   "root": "0x",
   "status": "0x1",
   "cumulativeGasUsed": "0x5208",
   "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
   "logs": null,
   "transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673",
   "contractAddress": "0x0000000000000000000000000000000000000000",
   "gasUsed": "0x5208",
   "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
   "transactionIndex": "0x0"
  }
 ],
 "rejected": [
  {
   "index": 1,
   "error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
  }
 ],
 "currentDifficulty": "0x20000",
 "gasUsed": "0x5208"
}

We can make them spit out the data to e.g. stdout like this:

./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --output.result=stdout --output.alloc=stdout --state.fork=Berlin

Output:

{
  "alloc": {
    "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": {
      "balance": "0xfeed1a9d",
      "nonce": "0x1"
    },
    "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
      "balance": "0x5ffd4878be161d74",
      "nonce": "0xac"
    },
    "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
      "balance": "0xa410"
    }
  },
  "result": {
    "stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13",
    "txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d",
    "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
    "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "receipts": [
      {
        "root": "0x",
        "status": "0x1",
        "cumulativeGasUsed": "0x5208",
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "logs": null,
        "transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673",
        "contractAddress": "0x0000000000000000000000000000000000000000",
        "gasUsed": "0x5208",
        "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "transactionIndex": "0x0"
      }
    ],
    "rejected": [
      {
        "index": 1,
        "error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
      }
    ],
    "currentDifficulty": "0x20000",
    "gasUsed": "0x5208"
  }
}

About Ommers

Mining rewards and ommer rewards might need to be added. This is how those are applied:

  • block_reward is the block mining reward for the miner (0xaa), of a block at height N.
  • For each ommer (mined by 0xbb), with blocknumber N-delta
    • (where delta is the difference between the current block and the ommer)
    • The account 0xbb (ommer miner) is awarded (8-delta)/ 8 * block_reward
    • The account 0xaa (block miner) is awarded block_reward / 32

To make t8n apply these, the following inputs are required:

  • --state.reward
    • For ethash, it is 5000000000000000000 wei,
    • If this is not defined, mining rewards are not applied,
    • A value of 0 is valid, and causes accounts to be 'touched'.
  • For each ommer, the tool needs to be given an addres\ and a delta. This is done via the ommers field in env.

Note: the tool does not verify that e.g. the normal uncle rules apply, and allows e.g two uncles at the same height, or the uncle-distance. This means that the tool allows for negative uncle reward (distance > 8)

Example: ./testdata/5/env.json:

{
  "currentCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "currentDifficulty": "0x20000",
  "currentGasLimit": "0x750a163df65e8a",
  "currentNumber": "1",
  "currentTimestamp": "1000",
  "ommers": [
    {"delta":  1, "address": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" },
    {"delta":  2, "address": "0xcccccccccccccccccccccccccccccccccccccccc" }
  ]
}

When applying this, using a reward of 0x08 Output:

{
  "alloc": {
    "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": {
      "balance": "0x88"
    },
    "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb": {
      "balance": "0x70"
    },
    "0xcccccccccccccccccccccccccccccccccccccccc": {
      "balance": "0x60"
    }
  }
}

Future EIPS

It is also possible to experiment with future eips that are not yet defined in a hard fork. Example, putting EIP-1344 into Frontier:

./evm t8n --state.fork=Frontier+1344 --input.pre=./testdata/1/pre.json --input.txs=./testdata/1/txs.json --input.env=/testdata/1/env.json

Block history

The BLOCKHASH opcode requires blockhashes to be provided by the caller, inside the env. If a required blockhash is not provided, the exit code should be 4: Example where blockhashes are provided:

./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json  --trace --state.fork=Berlin

cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"BLOCKHASH"}
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"depth":1,"refund":0,"opName":"STOP"}
{"output":"","gasUsed":"0x17"}

In this example, the caller has not provided the required blockhash:

./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json --trace --state.fork=Berlin
ERROR(4): getHash(3) invoked, blockhash for that block not provided

Error code: 4

Chaining

Another thing that can be done, is to chain invocations:

./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Berlin --output.alloc=stdout | ./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json --state.fork=Berlin

What happened here, is that we first applied two identical transactions, so the second one was rejected. Then, taking the poststate alloc as the input for the next state, we tried again to include the same two transactions: this time, both failed due to too low nonce.

In order to meaningfully chain invocations, one would need to provide meaningful new env, otherwise the actual blocknumber (exposed to the EVM) would not increase.

Transactions in RLP form

It is possible to provide already-signed transactions as input to, using an input.txs which ends with the rlp suffix. The input format for RLP-form transactions is identical to the output format for block bodies. Therefore, it's fully possible to use the evm to go from json input to rlp input.

The following command takes json the transactions in ./testdata/13/txs.json and signs them. After execution, they are output to signed_txs.rlp.:

./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./testdata/13/txs.json --input.env=./testdata/13/env.json --output.result=alloc_jsontx.json --output.body=signed_txs.rlp
INFO [12-27|09:25:11.102] Trie dumping started                     root=e4b924..6aef61
INFO [12-27|09:25:11.102] Trie dumping complete                    accounts=3 elapsed="275.66µs"
INFO [12-27|09:25:11.102] Wrote file                               file=alloc.json
INFO [12-27|09:25:11.103] Wrote file                               file=alloc_jsontx.json
INFO [12-27|09:25:11.103] Wrote file                               file=signed_txs.rlp

The output.body is the rlp-list of transactions, encoded in hex and placed in a string a'la json encoding rules:

cat signed_txs.rlp
"0xf8d2b86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9"

We can use rlpdump to check what the contents are:

rlpdump -hex $(cat signed_txs.rlp | jq -r )
[
  02f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904,
  02f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9,
]

Now, we can now use those (or any other already signed transactions), as input, like so:

./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./signed_txs.rlp --input.env=./testdata/13/env.json --output.result=alloc_rlptx.json
INFO [12-27|09:25:11.187] Trie dumping started                     root=e4b924..6aef61
INFO [12-27|09:25:11.187] Trie dumping complete                    accounts=3 elapsed="123.676µs"
INFO [12-27|09:25:11.187] Wrote file                               file=alloc.json
INFO [12-27|09:25:11.187] Wrote file                               file=alloc_rlptx.json

You might have noticed that the results from these two invocations were stored in two separate files. And we can now finally check that they match.

cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot
"0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61"
"0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61"

Transaction tool

The transaction tool is used to perform static validity checks on transactions such as:

  • intrinsic gas calculation
  • max values on integers
  • fee semantics, such as maxFeePerGas < maxPriorityFeePerGas
  • newer tx types on old forks

Examples

./evm t9n --state.fork Homestead --input.txs testdata/15/signed_txs.rlp
[
  {
    "error": "transaction type not supported",
    "hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476"
  },
  {
    "error": "transaction type not supported",
    "hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a"
  }
]
./evm t9n --state.fork London --input.txs testdata/15/signed_txs.rlp
[
  {
    "address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
    "hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
    "intrinsicGas": "0x5208"
  },
  {
    "address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
    "hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
    "intrinsicGas": "0x5208"
  }
]

Block builder tool (b11r)

The evm b11r tool is used to assemble and seal full block rlps.

Specification

Command line params

Command line params that need to be supported are:

    --input.header value        `stdin` or file name of where to find the block header to use. (default: "header.json")
    --input.ommers value        `stdin` or file name of where to find the list of ommer header RLPs to use.
    --input.txs value           `stdin` or file name of where to find the transactions list in RLP form. (default: "txs.rlp")
    --output.basedir value      Specifies where output files are placed. Will be created if it does not exist.
    --output.block value        Determines where to put the alloc of the post-state. (default: "block.json")
                                <file> - into the file <file>
                                `stdout` - into the stdout output
                                `stderr` - into the stderr output
    --seal.clique value         Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.
    --seal.ethash               Seal block with ethash. (default: false)
    --seal.ethash.dir value     Path to ethash DAG. If none exists, a new DAG will be generated.
    --seal.ethash.mode value    Defines the type and amount of PoW verification an ethash engine makes. (default: "normal")
    --verbosity value           Sets the verbosity level. (default: 3)

Objects

header

The header object is a consensus header.

type Header struct {
        ParentHash  common.Hash       `json:"parentHash"`
        OmmerHash   *common.Hash      `json:"sha3Uncles"`
        Coinbase    *common.Address   `json:"miner"`
        Root        common.Hash       `json:"stateRoot"         gencodec:"required"`
        TxHash      *common.Hash      `json:"transactionsRoot"`
        ReceiptHash *common.Hash      `json:"receiptsRoot"`
        Bloom       types.Bloom       `json:"logsBloom"`
        Difficulty  *big.Int          `json:"difficulty"`
        Number      *big.Int          `json:"number"            gencodec:"required"`
        GasLimit    uint64            `json:"gasLimit"          gencodec:"required"`
        GasUsed     uint64            `json:"gasUsed"`
        Time        uint64            `json:"timestamp"         gencodec:"required"`
        Extra       []byte            `json:"extraData"`
        MixDigest   common.Hash       `json:"mixHash"`
        Nonce       *types.BlockNonce `json:"nonce"`
        BaseFee     *big.Int          `json:"baseFeePerGas"`
}

ommers

The ommers object is a list of RLP-encoded ommer blocks in hex representation.

type Ommers []string

txs

The txs object is a list of RLP-encoded transactions in hex representation.

type Txs []string

clique

The clique object provides the necessary information to complete a clique seal of the block.

var CliqueInfo struct {
        Key       *common.Hash    `json:"secretKey"`
        Voted     *common.Address `json:"voted"`
        Authorize *bool           `json:"authorize"`
        Vanity    common.Hash     `json:"vanity"`
}

output

The output object contains two values, the block RLP and the block hash.

type BlockInfo struct {
    Rlp  []byte      `json:"rlp"`
    Hash common.Hash `json:"hash"`
}

A Note on Encoding

The encoding of values for evm utility attempts to be relatively flexible. It generally supports hex-encoded or decimal-encoded numeric values, and hex-encoded byte values (like common.Address, common.Hash, etc). When in doubt, the execution-apis way of encoding should always be accepted.

Testing

There are many test cases in the cmd/evm/testdata directory. These fixtures are used to power the t8n tests in t8n_test.go. The best way to verify correctness of new evm implementations is to execute these and verify the output and error codes match the expected values.