github.com/jimmyx0x/go-ethereum@v1.10.28/cmd/evm/transition-test.sh (about)

     1  #!/bin/bash
     2  ticks="\`\`\`"
     3  
     4  function showjson(){
     5    echo "\`$1\`:"
     6    echo "${ticks}json"
     7    cat $1
     8    echo ""
     9    echo "$ticks"
    10  }
    11  function demo(){
    12    echo "$ticks"
    13    echo "$1"
    14    $1
    15    echo ""
    16    echo "$ticks"
    17    echo ""
    18  }
    19  function tick(){
    20    echo "$ticks"
    21  }
    22  
    23  function code(){
    24    echo "$ticks$1"
    25  }
    26  
    27  cat << "EOF"
    28  # EVM tool
    29  
    30  The EVM tool provides a few useful subcommands to facilitate testing at the EVM
    31  layer.
    32  
    33  * transition tool    (`t8n`) : a stateless state transition utility
    34  * transaction tool   (`t9n`) : a transaction validation utility
    35  * block builder tool (`b11r`): a block assembler utility
    36  
    37  ## State transition tool (`t8n`)
    38  
    39  
    40  The `evm t8n` tool is a stateless state transition utility. It is a utility
    41  which can
    42  
    43  1. Take a prestate, including
    44    - Accounts,
    45    - Block context information,
    46    - Previous blockshashes (*optional)
    47  2. Apply a set of transactions,
    48  3. Apply a mining-reward (*optional),
    49  4. And generate a post-state, including
    50    - State root, transaction root, receipt root,
    51    - Information about rejected transactions,
    52    - Optionally: a full or partial post-state dump
    53  
    54  ### Specification
    55  
    56  The idea is to specify the behaviour of this binary very _strict_, so that other
    57  node implementors can build replicas based on their own state-machines, and the
    58  state generators can swap between a \`geth\`-based implementation and a \`parityvm\`-based
    59  implementation.
    60  
    61  #### Command line params
    62  
    63  Command line params that need to be supported are
    64  
    65  ```
    66  EOF
    67  ./evm t8n -h | grep "\-\-trace\.\|\-\-output\.\|\-\-state\.\|\-\-input"
    68  cat << "EOF"
    69  ```
    70  #### Objects
    71  
    72  The transition tool uses JSON objects to read and write data related to the transition operation. The
    73  following object definitions are required.
    74  
    75  ##### `alloc`
    76  
    77  The `alloc` object defines the prestate that transition will begin with.
    78  
    79  ```go
    80  // Map of address to account definition.
    81  type Alloc map[common.Address]Account
    82  // Genesis account. Each field is optional.
    83  type Account struct {
    84      Code       []byte                           `json:"code"`
    85      Storage    map[common.Hash]common.Hash      `json:"storage"`
    86      Balance    *big.Int                         `json:"balance"`
    87      Nonce      uint64                           `json:"nonce"`
    88      SecretKey  []byte                            `json:"secretKey"`
    89  }
    90  ```
    91  
    92  ##### `env`
    93  
    94  The `env` object defines the environmental context in which the transition will
    95  take place.
    96  
    97  ```go
    98  type Env struct {
    99      // required
   100      CurrentCoinbase  common.Address      `json:"currentCoinbase"`
   101      CurrentGasLimit  uint64              `json:"currentGasLimit"`
   102      CurrentNumber    uint64              `json:"currentNumber"`
   103      CurrentTimestamp uint64              `json:"currentTimestamp"`
   104      Withdrawals      []*Withdrawal       `json:"withdrawals"`
   105      // optional
   106      CurrentDifficulty *big.Int           `json:"currentDifficuly"`
   107      CurrentRandom     *big.Int           `json:"currentRandom"`
   108      CurrentBaseFee    *big.Int           `json:"currentBaseFee"`
   109      ParentDifficulty  *big.Int           `json:"parentDifficulty"`
   110      ParentGasUsed     uint64             `json:"parentGasUsed"`
   111      ParentGasLimit    uint64             `json:"parentGasLimit"`
   112      ParentTimestamp   uint64             `json:"parentTimestamp"`
   113      BlockHashes       map[uint64]common.Hash `json:"blockHashes"`
   114      ParentUncleHash   common.Hash        `json:"parentUncleHash"`
   115      Ommers            []Ommer            `json:"ommers"`
   116  }
   117  type Ommer struct {
   118      Delta   uint64         `json:"delta"`
   119      Address common.Address `json:"address"`
   120  }
   121  type Withdrawal struct {
   122      Index          uint64         `json:"index"`
   123      ValidatorIndex uint64         `json:"validatorIndex"`
   124      Recipient      common.Address `json:"recipient"`
   125      Amount         *big.Int       `json:"amount"`
   126  }
   127  ```
   128  
   129  ##### `txs`
   130  
   131  The `txs` object is an array of any of the transaction types: `LegacyTx`,
   132  `AccessListTx`, or `DynamicFeeTx`.
   133  
   134  ```go
   135  type LegacyTx struct {
   136  	Nonce     uint64          `json:"nonce"`
   137  	GasPrice  *big.Int        `json:"gasPrice"`
   138  	Gas       uint64          `json:"gas"`
   139  	To        *common.Address `json:"to"`
   140  	Value     *big.Int        `json:"value"`
   141  	Data      []byte          `json:"data"`
   142  	V         *big.Int        `json:"v"`
   143  	R         *big.Int        `json:"r"`
   144  	S         *big.Int        `json:"s"`
   145      SecretKey *common.Hash    `json:"secretKey"`
   146  }
   147  type AccessList []AccessTuple
   148  type AccessTuple struct {
   149  	Address     common.Address `json:"address"        gencodec:"required"`
   150  	StorageKeys []common.Hash  `json:"storageKeys"    gencodec:"required"`
   151  }
   152  type AccessListTx struct {
   153  	ChainID    *big.Int        `json:"chainId"`
   154  	Nonce      uint64          `json:"nonce"`
   155  	GasPrice   *big.Int        `json:"gasPrice"`
   156  	Gas        uint64          `json:"gas"`
   157  	To         *common.Address `json:"to"`
   158  	Value      *big.Int        `json:"value"`
   159  	Data       []byte          `json:"data"`
   160  	AccessList AccessList      `json:"accessList"`
   161  	V          *big.Int        `json:"v"`
   162  	R          *big.Int        `json:"r"`
   163  	S          *big.Int        `json:"s"`
   164      SecretKey  *common.Hash     `json:"secretKey"`
   165  }
   166  type DynamicFeeTx struct {
   167  	ChainID    *big.Int        `json:"chainId"`
   168  	Nonce      uint64          `json:"nonce"`
   169  	GasTipCap  *big.Int        `json:"maxPriorityFeePerGas"`
   170  	GasFeeCap  *big.Int        `json:"maxFeePerGas"`
   171  	Gas        uint64          `json:"gas"`
   172  	To         *common.Address `json:"to"`
   173  	Value      *big.Int        `json:"value"`
   174  	Data       []byte          `json:"data"`
   175  	AccessList AccessList      `json:"accessList"`
   176  	V          *big.Int        `json:"v"`
   177  	R          *big.Int        `json:"r"`
   178  	S          *big.Int        `json:"s"`
   179      SecretKey  *common.Hash     `json:"secretKey"`
   180  }
   181  ```
   182  
   183  ##### `result`
   184  
   185  The `result` object is output after a transition is executed. It includes
   186  information about the post-transition environment.
   187  
   188  ```go
   189  type ExecutionResult struct {
   190      StateRoot   common.Hash    `json:"stateRoot"`
   191      TxRoot      common.Hash    `json:"txRoot"`
   192      ReceiptRoot common.Hash    `json:"receiptsRoot"`
   193      LogsHash    common.Hash    `json:"logsHash"`
   194      Bloom       types.Bloom    `json:"logsBloom"`
   195      Receipts    types.Receipts `json:"receipts"`
   196      Rejected    []*rejectedTx  `json:"rejected,omitempty"`
   197      Difficulty  *big.Int       `json:"currentDifficulty"`
   198      GasUsed     uint64         `json:"gasUsed"`
   199      BaseFee     *big.Int       `json:"currentBaseFee,omitempty"`
   200  }
   201  ```
   202  
   203  #### Error codes and output
   204  
   205  All logging should happen against the `stderr`.
   206  There are a few (not many) errors that can occur, those are defined below.
   207  
   208  ##### EVM-based errors (`2` to `9`)
   209  
   210  - Other EVM error. Exit code `2`
   211  - Failed configuration: when a non-supported or invalid fork was specified. Exit code `3`.
   212  - Block history is not supplied, but needed for a `BLOCKHASH` operation. If `BLOCKHASH`
   213    is invoked targeting a block which history has not been provided for, the program will
   214    exit with code `4`.
   215  
   216  ##### IO errors (`10`-`20`)
   217  
   218  - Invalid input json: the supplied data could not be marshalled.
   219    The program will exit with code `10`
   220  - IO problems: failure to load or save files, the program will exit with code `11`
   221  
   222  ```
   223  # This should exit with 3
   224  ./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
   225  EOF
   226  ./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
   227  exitcode=$?
   228  if [ $exitcode !=  3 ]; then
   229  	echo "Failed, exitcode should be 3,was $exitcode"
   230  else
   231    echo "exitcode:$exitcode OK"
   232  fi
   233  cat << "EOF"
   234  ```
   235  #### Forks
   236  ### Basic usage
   237  
   238  The chain configuration to be used for a transition is specified via the
   239  `--state.fork` CLI flag. A list of possible values and configurations can be
   240  found in [`tests/init.go`](tests/init.go).
   241  
   242  #### Examples
   243  ##### Basic usage
   244  
   245  Invoking it with the provided example files
   246  EOF
   247  cmd="./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Berlin"
   248  tick;echo "$cmd"; tick
   249  $cmd 2>/dev/null
   250  echo "Two resulting files:"
   251  echo ""
   252  showjson alloc.json
   253  showjson result.json
   254  echo ""
   255  
   256  echo "We can make them spit out the data to e.g. \`stdout\` like this:"
   257  cmd="./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"
   258  tick;echo "$cmd"; tick
   259  output=`$cmd 2>/dev/null`
   260  echo "Output:"
   261  echo "${ticks}json"
   262  echo "$output"
   263  echo "$ticks"
   264  
   265  cat << "EOF"
   266  
   267  #### About Ommers
   268  
   269  Mining rewards and ommer rewards might need to be added. This is how those are applied:
   270  
   271  - `block_reward` is the block mining reward for the miner (`0xaa`), of a block at height `N`.
   272  - For each ommer (mined by `0xbb`), with blocknumber `N-delta`
   273     - (where `delta` is the difference between the current block and the ommer)
   274     - The account `0xbb` (ommer miner) is awarded `(8-delta)/ 8 * block_reward`
   275     - The account `0xaa` (block miner) is awarded `block_reward / 32`
   276  
   277  To make `t8n` apply these, the following inputs are required:
   278  
   279  - `--state.reward`
   280    - For ethash, it is `5000000000000000000` `wei`,
   281    - If this is not defined, mining rewards are not applied,
   282    - A value of `0` is valid, and causes accounts to be 'touched'.
   283  - For each ommer, the tool needs to be given an `addres\` and a `delta`. This
   284    is done via the `ommers` field in `env`.
   285  
   286  Note: the tool does not verify that e.g. the normal uncle rules apply,
   287  and allows e.g two uncles at the same height, or the uncle-distance. This means that
   288  the tool allows for negative uncle reward (distance > 8)
   289  
   290  Example:
   291  EOF
   292  
   293  showjson ./testdata/5/env.json
   294  
   295  echo "When applying this, using a reward of \`0x08\`"
   296  cmd="./evm t8n --input.alloc=./testdata/5/alloc.json -input.txs=./testdata/5/txs.json --input.env=./testdata/5/env.json  --output.alloc=stdout --state.reward=0x80 --state.fork=Berlin"
   297  output=`$cmd 2>/dev/null`
   298  echo "Output:"
   299  echo "${ticks}json"
   300  echo "$output"
   301  echo "$ticks"
   302  
   303  echo "#### Future EIPS"
   304  echo ""
   305  echo "It is also possible to experiment with future eips that are not yet defined in a hard fork."
   306  echo "Example, putting EIP-1344 into Frontier: "
   307  cmd="./evm t8n --state.fork=Frontier+1344 --input.pre=./testdata/1/pre.json --input.txs=./testdata/1/txs.json --input.env=/testdata/1/env.json"
   308  tick;echo "$cmd"; tick
   309  echo ""
   310  
   311  echo "#### Block history"
   312  echo ""
   313  echo "The \`BLOCKHASH\` opcode requires blockhashes to be provided by the caller, inside the \`env\`."
   314  echo "If a required blockhash is not provided, the exit code should be \`4\`:"
   315  echo "Example where blockhashes are provided: "
   316  demo "./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json  --trace --state.fork=Berlin"
   317  cmd="cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2"
   318  tick && echo $cmd && tick
   319  echo "$ticks"
   320  cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
   321  echo "$ticks"
   322  echo ""
   323  
   324  echo "In this example, the caller has not provided the required blockhash:"
   325  cmd="./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json  --trace --state.fork=Berlin"
   326  tick && echo $cmd && $cmd 2>&1
   327  errc=$?
   328  tick
   329  echo "Error code: $errc"
   330  echo ""
   331  
   332  echo "#### Chaining"
   333  echo ""
   334  echo "Another thing that can be done, is to chain invocations:"
   335  cmd1="./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"
   336  cmd2="./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json --state.fork=Berlin"
   337  echo "$ticks"
   338  echo "$cmd1 | $cmd2"
   339  output=$($cmd1 | $cmd2 )
   340  echo $output
   341  echo "$ticks"
   342  echo "What happened here, is that we first applied two identical transactions, so the second one was rejected. "
   343  echo "Then, taking the poststate alloc as the input for the next state, we tried again to include"
   344  echo "the same two transactions: this time, both failed due to too low nonce."
   345  echo ""
   346  echo "In order to meaningfully chain invocations, one would need to provide meaningful new \`env\`, otherwise the"
   347  echo "actual blocknumber (exposed to the EVM) would not increase."
   348  echo ""
   349  
   350  echo "#### Transactions in RLP form"
   351  echo ""
   352  echo "It is possible to provide already-signed transactions as input to, using an \`input.txs\` which ends with the \`rlp\` suffix."
   353  echo "The input format for RLP-form transactions is _identical_ to the _output_ format for block bodies. Therefore, it's fully possible"
   354  echo "to use the evm to go from \`json\` input to \`rlp\` input."
   355  echo ""
   356  echo "The following command takes **json** the transactions in \`./testdata/13/txs.json\` and signs them. After execution, they are output to \`signed_txs.rlp\`.:"
   357  cmd="./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"
   358  echo "$ticks"
   359  echo $cmd
   360  $cmd 2>&1
   361  echo "$ticks"
   362  echo ""
   363  echo "The \`output.body\` is the rlp-list of transactions, encoded in hex and placed in a string a'la \`json\` encoding rules:"
   364  demo "cat signed_txs.rlp"
   365  echo "We can use \`rlpdump\` to check what the contents are: "
   366  echo "$ticks"
   367  echo "rlpdump -hex \$(cat signed_txs.rlp | jq -r )"
   368  rlpdump -hex $(cat signed_txs.rlp | jq -r )
   369  echo "$ticks"
   370  echo "Now, we can now use those (or any other already signed transactions), as input, like so: "
   371  cmd="./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"
   372  echo "$ticks"
   373  echo $cmd
   374  $cmd 2>&1
   375  echo "$ticks"
   376  echo "You might have noticed that the results from these two invocations were stored in two separate files. "
   377  echo "And we can now finally check that they match."
   378  echo "$ticks"
   379  echo "cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot"
   380  cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot
   381  echo "$ticks"
   382  
   383  cat << "EOF"
   384  
   385  ## Transaction tool
   386  
   387  The transaction tool is used to perform static validity checks on transactions such as:
   388  * intrinsic gas calculation
   389  * max values on integers
   390  * fee semantics, such as `maxFeePerGas < maxPriorityFeePerGas`
   391  * newer tx types on old forks
   392  
   393  ### Examples
   394  
   395  EOF
   396  
   397  cmd="./evm t9n --state.fork Homestead --input.txs testdata/15/signed_txs.rlp"
   398  tick;echo "$cmd";
   399  $cmd 2>/dev/null
   400  tick
   401  
   402  cmd="./evm t9n --state.fork London --input.txs testdata/15/signed_txs.rlp"
   403  tick;echo "$cmd";
   404  $cmd 2>/dev/null
   405  tick
   406  
   407  cat << "EOF"
   408  ## Block builder tool (b11r)
   409  
   410  The `evm b11r` tool is used to assemble and seal full block rlps.
   411  
   412  ### Specification
   413  
   414  #### Command line params
   415  
   416  Command line params that need to be supported are:
   417  
   418  ```
   419      --input.header value        `stdin` or file name of where to find the block header to use. (default: "header.json")
   420      --input.ommers value        `stdin` or file name of where to find the list of ommer header RLPs to use.
   421      --input.txs value           `stdin` or file name of where to find the transactions list in RLP form. (default: "txs.rlp")
   422      --output.basedir value      Specifies where output files are placed. Will be created if it does not exist.
   423      --output.block value        Determines where to put the alloc of the post-state. (default: "block.json")
   424                                  <file> - into the file <file>
   425                                  `stdout` - into the stdout output
   426                                  `stderr` - into the stderr output
   427      --seal.clique value         Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.
   428      --seal.ethash               Seal block with ethash. (default: false)
   429      --seal.ethash.dir value     Path to ethash DAG. If none exists, a new DAG will be generated.
   430      --seal.ethash.mode value    Defines the type and amount of PoW verification an ethash engine makes. (default: "normal")
   431      --verbosity value           Sets the verbosity level. (default: 3)
   432  ```
   433  
   434  #### Objects
   435  
   436  ##### `header`
   437  
   438  The `header` object is a consensus header.
   439  
   440  ```go=
   441  type Header struct {
   442          ParentHash  common.Hash       `json:"parentHash"`
   443          OmmerHash   *common.Hash      `json:"sha3Uncles"`
   444          Coinbase    *common.Address   `json:"miner"`
   445          Root        common.Hash       `json:"stateRoot"         gencodec:"required"`
   446          TxHash      *common.Hash      `json:"transactionsRoot"`
   447          ReceiptHash *common.Hash      `json:"receiptsRoot"`
   448          Bloom       types.Bloom       `json:"logsBloom"`
   449          Difficulty  *big.Int          `json:"difficulty"`
   450          Number      *big.Int          `json:"number"            gencodec:"required"`
   451          GasLimit    uint64            `json:"gasLimit"          gencodec:"required"`
   452          GasUsed     uint64            `json:"gasUsed"`
   453          Time        uint64            `json:"timestamp"         gencodec:"required"`
   454          Extra       []byte            `json:"extraData"`
   455          MixDigest   common.Hash       `json:"mixHash"`
   456          Nonce       *types.BlockNonce `json:"nonce"`
   457          BaseFee     *big.Int          `json:"baseFeePerGas"`
   458  }
   459  ```
   460  #### `ommers`
   461  
   462  The `ommers` object is a list of RLP-encoded ommer blocks in hex
   463  representation.
   464  
   465  ```go=
   466  type Ommers []string
   467  ```
   468  
   469  #### `txs`
   470  
   471  The `txs` object is a list of RLP-encoded transactions in hex representation.
   472  
   473  ```go=
   474  type Txs []string
   475  ```
   476  
   477  #### `clique`
   478  
   479  The `clique` object provides the neccesary information to complete a clique
   480  seal of the block.
   481  
   482  ```go=
   483  var CliqueInfo struct {
   484          Key       *common.Hash    `json:"secretKey"`
   485          Voted     *common.Address `json:"voted"`
   486          Authorize *bool           `json:"authorize"`
   487          Vanity    common.Hash     `json:"vanity"`
   488  }
   489  ```
   490  
   491  #### `output`
   492  
   493  The `output` object contains two values, the block RLP and the block hash.
   494  
   495  ```go=
   496  type BlockInfo struct {
   497      Rlp  []byte      `json:"rlp"`
   498      Hash common.Hash `json:"hash"`
   499  }
   500  ```
   501  
   502  ## A Note on Encoding
   503  
   504  The encoding of values for `evm` utility attempts to be relatively flexible. It
   505  generally supports hex-encoded or decimal-encoded numeric values, and
   506  hex-encoded byte values (like `common.Address`, `common.Hash`, etc). When in
   507  doubt, the [`execution-apis`](https://github.com/ethereum/execution-apis) way
   508  of encoding should always be accepted.
   509  
   510  ## Testing
   511  
   512  There are many test cases in the [`cmd/evm/testdata`](./testdata) directory.
   513  These fixtures are used to power the `t8n` tests in
   514  [`t8n_test.go`](./t8n_test.go). The best way to verify correctness of new `evm`
   515  implementations is to execute these and verify the output and error codes match
   516  the expected values.
   517  
   518  EOF