github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/cmd/evm/README.md (about)

     1  ## EVM state transition tool
     2  
     3  The `evm t8n` tool is a stateless state transition utility. It is a utility
     4  which can
     5  
     6  1. Take a prestate, including
     7    - Accounts,
     8    - Block context information,
     9    - Previous blockshashes (*optional)
    10  2. Apply a set of transactions,
    11  3. Apply a mining-reward (*optional),
    12  4. And generate a post-state, including
    13    - State root, transaction root, receipt root,
    14    - Information about rejected transactions,
    15    - Optionally: a full or partial post-state dump
    16  
    17  ## Specification
    18  
    19  The idea is to specify the behaviour of this binary very _strict_, so that other
    20  node implementors can build replicas based on their own state-machines, and the
    21  state generators can swap between a `geth`-based implementation and a `parityvm`-based
    22  implementation.
    23  
    24  ### Command line params
    25  
    26  Command line params that has to be supported are
    27  ```
    28  
    29     --trace                            Output full trace logs to files <txhash>.jsonl
    30     --trace.nomemory                   Disable full memory dump in traces
    31     --trace.nostack                    Disable stack output in traces
    32     --trace.noreturndata               Disable return data output in traces
    33     --output.basedir value             Specifies where output files are placed. Will be created if it does not exist. (default: ".")
    34     --output.alloc alloc               Determines where to put the alloc of the post-state.
    35                                        `stdout` - into the stdout output
    36                                        `stderr` - into the stderr output
    37     --output.result result             Determines where to put the result (stateroot, txroot etc) of the post-state.
    38                                        `stdout` - into the stdout output
    39                                        `stderr` - into the stderr output
    40     --state.fork value                 Name of ruleset to use.
    41     --state.chainid value              ChainID to use (default: 1)
    42     --state.reward value               Mining reward. Set to -1 to disable (default: 0)
    43  
    44  ```
    45  
    46  ### Error codes and output
    47  
    48  All logging should happen against the `stderr`.
    49  There are a few (not many) errors that can occur, those are defined below.
    50  
    51  #### EVM-based errors (`2` to `9`)
    52  
    53  - Other EVM error. Exit code `2`
    54  - Failed configuration: when a non-supported or invalid fork was specified. Exit code `3`.
    55  - Block history is not supplied, but needed for a `BLOCKHASH` operation. If `BLOCKHASH`
    56    is invoked targeting a block which history has not been provided for, the program will
    57    exit with code `4`.
    58  
    59  #### IO errors (`10`-`20`)
    60  
    61  - Invalid input json: the supplied data could not be marshalled.
    62    The program will exit with code `10`
    63  - IO problems: failure to load or save files, the program will exit with code `11`
    64  
    65  ## Examples
    66  ### Basic usage
    67  
    68  Invoking it with the provided example files
    69  ```
    70  ./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json
    71  ```
    72  Two resulting files:
    73  
    74  `alloc.json`:
    75  ```json
    76  {
    77   "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": {
    78    "balance": "0xfeed1a9d",
    79    "nonce": "0x1"
    80   },
    81   "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
    82    "balance": "0x5ffd4878be161d74",
    83    "nonce": "0xac"
    84   },
    85   "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
    86    "balance": "0xa410"
    87   }
    88  }
    89  ```
    90  `result.json`:
    91  ```json
    92  {
    93   "stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13",
    94   "txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d",
    95   "receiptRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
    96   "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    97   "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    98   "receipts": [
    99    {
   100     "root": "0x",
   101     "status": "0x1",
   102     "cumulativeGasUsed": "0x5208",
   103     "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
   104     "logs": null,
   105     "transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673",
   106     "contractAddress": "0x0000000000000000000000000000000000000000",
   107     "gasUsed": "0x5208",
   108     "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
   109     "transactionIndex": "0x0"
   110    }
   111   ],
   112   "rejected": [
   113    1
   114   ]
   115  }
   116  ```
   117  
   118  We can make them spit out the data to e.g. `stdout` like this:
   119  ```
   120  ./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
   121  ```
   122  Output:
   123  ```json
   124  {
   125   "alloc": {
   126    "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": {
   127     "balance": "0xfeed1a9d",
   128     "nonce": "0x1"
   129    },
   130    "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
   131     "balance": "0x5ffd4878be161d74",
   132     "nonce": "0xac"
   133    },
   134    "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
   135     "balance": "0xa410"
   136    }
   137   },
   138   "result": {
   139    "stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13",
   140    "txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d",
   141    "receiptRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
   142    "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
   143    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
   144    "receipts": [
   145     {
   146      "root": "0x",
   147      "status": "0x1",
   148      "cumulativeGasUsed": "0x5208",
   149      "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
   150      "logs": null,
   151      "transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673",
   152      "contractAddress": "0x0000000000000000000000000000000000000000",
   153      "gasUsed": "0x5208",
   154      "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
   155      "transactionIndex": "0x0"
   156     }
   157    ],
   158    "rejected": [
   159     1
   160    ]
   161   }
   162  }
   163  ```
   164  
   165  ## About Ommers
   166  
   167  Mining rewards and ommer rewards might need to be added. This is how those are applied:
   168  
   169  - `block_reward` is the block mining reward for the miner (`0xaa`), of a block at height `N`.
   170  - For each ommer (mined by `0xbb`), with blocknumber `N-delta`
   171     - (where `delta` is the difference between the current block and the ommer)
   172     - The account `0xbb` (ommer miner) is awarded `(8-delta)/ 8 * block_reward`
   173     - The account `0xaa` (block miner) is awarded `block_reward / 32`
   174  
   175  To make `state_t8n` apply these, the following inputs are required:
   176  
   177  - `state.reward`
   178    - For ethash, it is `5000000000000000000` `wei`,
   179    - If this is not defined, mining rewards are not applied,
   180    - A value of `0` is valid, and causes accounts to be 'touched'.
   181  - For each ommer, the tool needs to be given an `address` and a `delta`. This
   182    is done via the `env`.
   183  
   184  Note: the tool does not verify that e.g. the normal uncle rules apply,
   185  and allows e.g two uncles at the same height, or the uncle-distance. This means that
   186  the tool allows for negative uncle reward (distance > 8)
   187  
   188  Example:
   189  `./testdata/5/env.json`:
   190  ```json
   191  {
   192    "currentCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
   193    "currentDifficulty": "0x20000",
   194    "currentGasLimit": "0x750a163df65e8a",
   195    "currentNumber": "1",
   196    "currentTimestamp": "1000",
   197    "ommers": [
   198      {"delta":  1, "address": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" },
   199      {"delta":  2, "address": "0xcccccccccccccccccccccccccccccccccccccccc" }
   200    ]
   201  }
   202  ```
   203  When applying this, using a reward of `0x08`
   204  Output:
   205  ```json
   206  {
   207   "alloc": {
   208    "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": {
   209     "balance": "0x88"
   210    },
   211    "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb": {
   212     "balance": "0x70"
   213    },
   214    "0xcccccccccccccccccccccccccccccccccccccccc": {
   215     "balance": "0x60"
   216    }
   217   }
   218  }
   219  ```
   220  ### Future EIPS
   221  
   222  It is also possible to experiment with future eips that are not yet defined in a hard fork.
   223  Example, putting EIP-1344 into Frontier: 
   224  ```
   225  ./evm t8n --state.fork=Frontier+1344 --input.pre=./testdata/1/pre.json --input.txs=./testdata/1/txs.json --input.env=/testdata/1/env.json
   226  ```
   227  
   228  ### Block history
   229  
   230  The `BLOCKHASH` opcode requires blockhashes to be provided by the caller, inside the `env`.
   231  If a required blockhash is not provided, the exit code should be `4`:
   232  Example where blockhashes are provided: 
   233  ```
   234  ./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace
   235  ```
   236  ```
   237  cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
   238  ```
   239  ```
   240  {"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"PUSH1","error":""}
   241  {"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
   242  {"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"returnData":null,"depth":1,"refund":0,"opName":"STOP","error":""}
   243  {"output":"","gasUsed":"0x17","time":112885}
   244  ```
   245  
   246  In this example, the caller has not provided the required blockhash:
   247  ```
   248  ./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json --trace
   249  ```
   250  ```
   251  ERROR(4): getHash(3) invoked, blockhash for that block not provided
   252  ```
   253  Error code: 4
   254  ### Chaining
   255  
   256  Another thing that can be done, is to chain invocations:
   257  ```
   258  ./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --output.alloc=stdout | ./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json
   259  INFO [08-03|15:25:15.168] rejected tx                              index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
   260  INFO [08-03|15:25:15.169] rejected tx                              index=0 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
   261  INFO [08-03|15:25:15.169] rejected tx                              index=1 hash="0557ba…18d673" from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low"
   262  
   263  ```
   264  What happened here, is that we first applied two identical transactions, so the second one was rejected. 
   265  Then, taking the poststate alloc as the input for the next state, we tried again to include
   266  the same two transactions: this time, both failed due to too low nonce.
   267  
   268  In order to meaningfully chain invocations, one would need to provide meaningful new `env`, otherwise the
   269  actual blocknumber (exposed to the EVM) would not increase.
   270