github.com/core-coin/go-core/v2@v2.1.9/cmd/cvm/README.md (about)

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