gitee.com/liu-zhao234568/cntest@v1.0.0/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. 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":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""} 241 {"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"BLOCKHASH","error":""} 242 {"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"STOP","error":""} 243 {"output":"","gasUsed":"0x17","time":142709} 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 [01-21|22:41:22.963] rejected tx index=1 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1" 260 INFO [01-21|22:41:22.966] rejected tx index=0 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1" 261 INFO [01-21|22:41:22.967] rejected tx index=1 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1" 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.