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