├── docker ├── README.md └── Dockerfile ├── .gitmodules ├── .gitattributes ├── .travis.yml ├── requirements.txt ├── LICENSE ├── resources ├── 0x829bb7e1211b1f6f85b9944c2ba1a1614a7d7dedebe9e6bd530ca93dae126a16.json ├── block_with_single_short_transaction.json └── 0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659.json ├── onchain ├── test │ ├── test_utils.py │ └── test_ProvethVerifier.py ├── ProvethVerifierTestHelper.sol └── ProvethVerifier.sol ├── README.md ├── .gitignore ├── offchain └── proveth.py └── specification.md /docker/README.md: -------------------------------------------------------------------------------- 1 | This directory contains the Dockerfile for building and testing on Travis-CI. 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "onchain/Solidity-RLP"] 2 | path = onchain/Solidity-RLP 3 | url = https://github.com/hamdiallam/Solidity-RLP.git 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | # force code files to not be crlf'd 4 | *.sol text linguist-language=Solidity eol=lf 5 | *.py text eol=lf 6 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | 3 | # House keeping 4 | RUN apt-get update 5 | 6 | # Python 3.6 and pip dependencies 7 | RUN apt-get -y install apt-utils python3.6 python3.6-dev python3-pip git gcc && apt-get -y install pkg-config libffi6 autoconf automake libtool openssl libssl-dev 8 | 9 | # Solidity 10 | RUN apt-get -y install software-properties-common && add-apt-repository -y ppa:ethereum/ethereum && apt-get update && apt-get -y install solc 11 | 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | 6 | before_install: 7 | - docker pull lorenzb/proveth@sha256:243f6a6ef2b90c636f29eb384214a2471a567bd7943d1eb32f47629fe12ccdeb 8 | 9 | script: 10 | - ls 11 | - pwd 12 | - docker run -v $PWD:/repo lorenzb/proveth@sha256:243f6a6ef2b90c636f29eb384214a2471a567bd7943d1eb32f47629fe12ccdeb bash -c "cp -r /repo /repo2 && cd /repo2/ && python3.6 -m pip install -r requirements.txt && python3.6 onchain/test/test_ProvethVerifier.py" 13 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | asn1crypto==0.24.0 2 | certifi==2019.3.9 3 | cffi==1.12.2 4 | chardet==3.0.4 5 | coincurve==11.0.0 6 | cytoolz==0.9.0.1 7 | eth-hash==0.2.0 8 | eth-typing==2.1.0 9 | eth-utils==1.4.1 10 | ethereum==2.3.2 11 | future==0.17.1 12 | idna==2.8 13 | pbkdf2==1.3 14 | py-ecc==1.4.7 15 | py-solc==3.2.0 16 | pycparser==2.19 17 | pycryptodome==3.7.3 18 | pyethash==0.1.27 19 | pysha3==1.0.2 20 | PyYAML==3.13 21 | repoze.lru==0.7 22 | requests==2.21.0 23 | rlp==1.1.0 24 | scrypt==0.8.13 25 | semantic-version==2.6.0 26 | toolz==0.9.0 27 | trie==1.3.8 28 | urllib3==1.24.1 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018: 4 | - Lorenz Breidenbach 5 | - Tyler Kell 6 | - Alex Manuskin 7 | - Casey Detrio 8 | - Derek Chin 9 | - Shayan Eskandari 10 | - Stephane Gosselin 11 | - Yael Doweck 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | 31 | -------------------------------------------------------------------------------- /resources/0x829bb7e1211b1f6f85b9944c2ba1a1614a7d7dedebe9e6bd530ca93dae126a16.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": 1, 4 | "result": { 5 | "difficulty": "0x5e912df0de47", 6 | "extraData": "0xe4b883e5bda9e7a59ee4bb99e9b1bc", 7 | "gasLimit": "0x3cfdbc", 8 | "gasUsed": "0x0", 9 | "hash": "0x829bb7e1211b1f6f85b9944c2ba1a1614a7d7dedebe9e6bd530ca93dae126a16", 10 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 11 | "miner": "0x61c808d82a3ac53231750dadc13c777b59310bd9", 12 | "mixHash": "0xda38c375c3538e86605ff20952712bfe6a56e7501018913ae106a9af2e37404f", 13 | "nonce": "0x05b8b8a0036198c5", 14 | "number": "0x2dc6c9", 15 | "parentHash": "0x9263c42eee23f04212696aa24877596f55c6a0d0d053e4eacb6408cac507d17b", 16 | "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 17 | "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 18 | "size": "0x214", 19 | "stateRoot": "0xdecb66e3abe1ebe9f88d7e49a1a0111ff4f302ecb370b30e9befeed1e59d52b5", 20 | "timestamp": "0x587b4b21", 21 | "totalDifficulty": "0x681042fccffd811d2", 22 | "transactions": [], 23 | "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 24 | "uncles": [] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /onchain/test/test_utils.py: -------------------------------------------------------------------------------- 1 | from ethereum.abi import ContractTranslator 2 | from ethereum.tools import tester 3 | from ethereum import utils 4 | from solc import compile_standard 5 | 6 | def rec_hex(x): 7 | if isinstance(x, list): 8 | return [rec_hex(elem) for elem in x] 9 | else: 10 | return "0x" + utils.encode_hex(x) 11 | 12 | 13 | def rec_bin(x): 14 | if isinstance(x, list): 15 | return [rec_bin(elem) for elem in x] 16 | elif isinstance(x, int): 17 | return x 18 | elif isinstance(x, str): 19 | if x.startswith("0x"): 20 | return utils.decode_hex(x[2:]) 21 | else: 22 | return utils.decode_hex(x) 23 | 24 | def deploy_solidity_contract(chain, solc_config_sources, allow_paths, contract_file, contract_name, startgas): 25 | compiled = compile_standard({ 26 | 'language': 'Solidity', 27 | 'sources': solc_config_sources, 28 | 'settings': {'evmVersion': 'byzantium', 29 | 'outputSelection': {'*': {'*': ['abi', 'evm.bytecode']}}, 30 | }, 31 | }, allow_paths=allow_paths) 32 | 33 | abi = compiled['contracts'][contract_file][contract_name]['abi'] 34 | binary = compiled['contracts'][contract_file][contract_name]['evm']['bytecode']['object'] 35 | address = chain.contract( 36 | utils.decode_hex(binary), language='evm', value=0, startgas=startgas, sender=tester.k0) 37 | contract = tester.ABIContract(chain, abi, address) 38 | return contract 39 | 40 | 41 | def deploy_solidity_contract_with_args(chain, solc_config_sources, allow_paths, contract_file, contract_name, startgas, args=[]): 42 | compiled = compile_standard({ 43 | 'language': 'Solidity', 44 | 'sources': solc_config_sources, 45 | 'settings': {'evmVersion': 'byzantium', 46 | 'outputSelection': {'*': {'*': ['abi', 'evm.bytecode']}}, 47 | }, 48 | }, allow_paths=allow_paths) 49 | 50 | abi = compiled['contracts'][contract_file][contract_name]['abi'] 51 | binary = compiled['contracts'][contract_file][contract_name]['evm']['bytecode']['object'] 52 | ct = ContractTranslator(abi) 53 | address = chain.contract( 54 | (utils.decode_hex(binary) + ct.encode_constructor_arguments(args) if args else b''), language='evm', value=0, startgas=startgas, sender=tester.k0) 55 | contract = tester.ABIContract(chain, ct, address) 56 | return contract 57 | 58 | -------------------------------------------------------------------------------- /resources/block_with_single_short_transaction.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": 1, 4 | "result": { 5 | "difficulty": "0x20e59", 6 | "extraData": "0xd883010702846765746887676f312e392e328664617277696e", 7 | "gasLimit": "0x47f3a6", 8 | "gasUsed": "0xcf08", 9 | "hash": "0x2c9c6ceccef4fa8417b081c4399dbe3a417b3c94231adb7b9066f5a0145d597f", 10 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 11 | "miner": "0x7d1480f9e92a91387e88e6acd1ea82c4acf87c87", 12 | "mixHash": "0x52e215b0f8e16e5a6ea8144847e380d1abd1e792de214b520f3aaece493b22d7", 13 | "nonce": "0x24ad3cdf8c7cc0c5", 14 | "number": "0x3c", 15 | "parentHash": "0x186667ebe6cfb07aa1efec30c2164bb3b6ab3a55656dde002163963a15cb57f7", 16 | "receiptsRoot": "0x65c4d1b533902562730f0d110bcce51643ce4725ca03d85c33d5812c0ed308bf", 17 | "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 18 | "size": "0x22c", 19 | "stateRoot": "0x632f0ed8953dcd4d02104c490e38f33bd353437c2b15304e00e155ad4e023853", 20 | "timestamp": "0x5b572bc0", 21 | "totalDifficulty": "0x79fa3b", 22 | "transactions": [ 23 | { 24 | "blockHash": "0x2c9c6ceccef4fa8417b081c4399dbe3a417b3c94231adb7b9066f5a0145d597f", 25 | "blockNumber": "0x3c", 26 | "from": "0xd550d7613367f74915438a77ce85f4abfb3052e1", 27 | "gas": "0xf4240", 28 | "gasPrice": "0x2540be400", 29 | "hash": "0x1796a0671fb4c3cd5a6253de5fe95c88d78a9d522aace28adb12f6736c2599c8", 30 | "input": "0x", 31 | "nonce": "0x0", 32 | "to": null, 33 | "transactionIndex": "0x0", 34 | "value": "0x0", 35 | "v": "0x1b", 36 | "r": "0x1", 37 | "s": "0x1" 38 | } 39 | ], 40 | "transactionsRoot": "0xfda3939fa8a1ed195cfbfc96387d3748ca4437f4122d0deada172d92ea1ccc53", 41 | "uncles": [] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /onchain/ProvethVerifierTestHelper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./ProvethVerifier.sol"; 4 | 5 | // This contract is for testing. It exposes internal methods of 6 | // ProvethVerifier so that we can test them. 7 | // 8 | // ************************************************************* 9 | // *** Never deploy this contract! *** 10 | // ************************************************************* 11 | contract ProvethVerifierTestHelper is ProvethVerifier { 12 | 13 | function exposedDecodeUnsignedTx(bytes calldata rlpUnsignedTx) external pure returns ( 14 | uint256 nonce, 15 | uint256 gasprice, 16 | uint256 startgas, 17 | address to, 18 | uint256 value, 19 | bytes memory data, 20 | bool isContractCreation 21 | ) { 22 | UnsignedTransaction memory tx = decodeUnsignedTx(rlpUnsignedTx); 23 | return ( 24 | tx.nonce, 25 | tx.gasprice, 26 | tx.startgas, 27 | tx.to, 28 | tx.value, 29 | tx.data, 30 | tx.isContractCreation 31 | ); 32 | } 33 | 34 | function exposedDecodeSignedTx(bytes calldata rlpSignedTx) external pure returns ( 35 | uint256 nonce, 36 | uint256 gasprice, 37 | uint256 startgas, 38 | address to, 39 | uint256 value, 40 | bytes memory data, 41 | uint256 v, 42 | uint256 r, 43 | uint256 s, 44 | bool isContractCreation 45 | ) { 46 | SignedTransaction memory tx = decodeSignedTx(rlpSignedTx); 47 | return ( 48 | tx.nonce, 49 | tx.gasprice, 50 | tx.startgas, 51 | tx.to, 52 | tx.value, 53 | tx.data, 54 | tx.v, 55 | tx.r, 56 | tx.s, 57 | tx.isContractCreation 58 | ); 59 | } 60 | 61 | 62 | function exposedMerklePatriciaCompactDecode( 63 | bytes calldata compact 64 | ) external pure returns ( 65 | bool isLeaf, 66 | bytes memory nibbles 67 | ) { 68 | return merklePatriciaCompactDecode(compact); 69 | } 70 | 71 | function exposedValidateMPTProof( 72 | bytes32 rootHash, 73 | bytes calldata mptPath, 74 | bytes calldata rlpStack 75 | ) external pure returns ( 76 | bytes memory value 77 | ) { 78 | return validateMPTProof( 79 | rootHash, 80 | mptPath, 81 | RLPReader.toList(RLPReader.toRlpItem(rlpStack))); 82 | } 83 | 84 | function exposedSharedPrefixLength( 85 | uint xsOffset, 86 | bytes calldata xs, 87 | bytes calldata ys 88 | ) external pure returns (uint) { 89 | return sharedPrefixLength(xsOffset, xs, ys); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Proveth 2 | 3 | [![Build Status](https://travis-ci.org/lorenzb/proveth.svg?branch=master)](https://travis-ci.org/lorenzb/proveth) 4 | ![Python >= 3.6](https://img.shields.io/badge/python-%3E%3D%203.6-blue.svg) 5 | ![Solidity >= 0.5.0](https://img.shields.io/badge/solidity-%3E%3D%200.5.0-blue.svg) 6 | 7 | Ethereum's design [makes heavy use](https://blog.ethereum.org/2015/11/15/merkling-in-ethereum/) of [Merkle trees](https://en.wikipedia.org/wiki/Merkle_tree) enabling *light clients* to interact with the blockchain without having to download full blocks or its complete state. 8 | 9 | Ethereum uses its own variant of Merkle trees, called [Merkle Patricia Tries](https://github.com/ethereum/wiki/wiki/Patricia-Tree), which provide a [dictionary](https://en.wikipedia.org/wiki/Associative_array)-like interface and enable the generation and verification of small proofs (logarithmic in the number of items in the dictionary) that a given key-value-pair is present/absent from the dictionary. Ethereum uses Merkle Patricia Tries to store transactions, transactions receipts, and the *state* (all accounts with their balances, code, and storage). 10 | 11 | (If you want to learn more about Merkle Patricia Tries, check out the links above and have a look at this [cool visualisation](https://beta.observablehq.com/@cdetrio/ethereum-txtrie-merkle-patricia-trie-viz) Casey built.) 12 | 13 | ## Project goals 14 | 15 | Proveth aims to provide 16 | - a [clearly specified format for these proofs](specification.md); 17 | - a high-quality off-chain proof generator that can connect to an Ethereum node and generate such proofs; 18 | - a high-quality on-chain proof verifier (smart contract) that can verify a proof that a given transaction/state item/... is indeed part of the Ethereum blockchain. 19 | 20 | ## Project state 21 | 22 | Proveth is under active development. We currently support generating and verifying proofs of transaction inclusion/exclusion, i.e. proofs of statements of the form "the transaction `tx` was present/absent at index `i` in the block with blockhash `h`". 23 | 24 | We aim to extend this to: 25 | - proofs of transaction receipt inclusion/exclusion 26 | - proofs about the Ethereum state 27 | 28 | ## Contributing 29 | 30 | We welcome contributions. Have a look at any open issues, add more tests/documentation or come up with your own improvements. Before starting work on a large PR, we suggest opening an issue to discuss your approach with the maintainers. 31 | 32 | We ❤️ tests & docs, so please write lots of them! 33 | 34 | We follow [PEP-8](https://www.python.org/dev/peps/pep-0008/) for Python and the [official style](http://solidity.readthedocs.io/en/v0.4.24/style-guide.html) for Solidity. 35 | 36 | ## Authors 37 | 38 | Proveth's development was started by the *Submarines* group at the [2018 IC3 Ethereum bootcamp](http://www.initc3.org/events/2018-07-12-IC3-Ethereum-Crypto-Boot-Camp.html): 39 | - Lorenz Breidenbach 40 | - Tyler Kell 41 | - Alex Manuskin 42 | - Casey Detrio 43 | - Derek Chin 44 | - Shayan Eskandari 45 | - Stephane Gosselin 46 | - Yael Doweck 47 | 48 | ## Acknowledgements 49 | 50 | Our design is inspired by [PeaceRelay](https://medium.com/@loiluu/peacerelay-connecting-the-many-ethereum-blockchains-22605c300ad3). Thanks to Nate Rush for answering our questions. 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/go,vim,osx,emacs,linux,python,windows,solidity,intellij,virtualenv 3 | 4 | ### Emacs ### 5 | # -*- mode: gitignore; -*- 6 | *~ 7 | \#*\# 8 | /.emacs.desktop 9 | /.emacs.desktop.lock 10 | *.elc 11 | auto-save-list 12 | tramp 13 | .\#* 14 | 15 | # Org-mode 16 | .org-id-locations 17 | *_archive 18 | 19 | # flymake-mode 20 | *_flymake.* 21 | 22 | # eshell files 23 | /eshell/history 24 | /eshell/lastdir 25 | 26 | # elpa packages 27 | /elpa/ 28 | 29 | # reftex files 30 | *.rel 31 | 32 | # AUCTeX auto folder 33 | /auto/ 34 | 35 | # cask packages 36 | .cask/ 37 | dist/ 38 | 39 | # Flycheck 40 | flycheck_*.el 41 | 42 | # server auth directory 43 | /server/ 44 | 45 | # projectiles files 46 | .projectile 47 | 48 | # directory configuration 49 | .dir-locals.el 50 | 51 | ### Go ### 52 | # Binaries for programs and plugins 53 | *.exe 54 | *.exe~ 55 | *.dll 56 | *.so 57 | *.dylib 58 | 59 | # Test binary, build with `go test -c` 60 | *.test 61 | 62 | # Output of the go coverage tool, specifically when used with LiteIDE 63 | *.out 64 | 65 | ### Intellij ### 66 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 67 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 68 | 69 | # User-specific stuff 70 | .idea/**/workspace.xml 71 | .idea/**/tasks.xml 72 | .idea/**/usage.statistics.xml 73 | .idea/**/dictionaries 74 | .idea/**/shelf 75 | 76 | # Sensitive or high-churn files 77 | .idea/**/dataSources/ 78 | .idea/**/dataSources.ids 79 | .idea/**/dataSources.local.xml 80 | .idea/**/sqlDataSources.xml 81 | .idea/**/dynamic.xml 82 | .idea/**/uiDesigner.xml 83 | .idea/**/dbnavigator.xml 84 | 85 | # Gradle 86 | .idea/**/gradle.xml 87 | .idea/**/libraries 88 | 89 | # CMake 90 | cmake-build-*/ 91 | 92 | # Mongo Explorer plugin 93 | .idea/**/mongoSettings.xml 94 | 95 | # File-based project format 96 | *.iws 97 | 98 | # IntelliJ 99 | out/ 100 | 101 | # mpeltonen/sbt-idea plugin 102 | .idea_modules/ 103 | 104 | # JIRA plugin 105 | atlassian-ide-plugin.xml 106 | 107 | # Cursive Clojure plugin 108 | .idea/replstate.xml 109 | 110 | # Crashlytics plugin (for Android Studio and IntelliJ) 111 | com_crashlytics_export_strings.xml 112 | crashlytics.properties 113 | crashlytics-build.properties 114 | fabric.properties 115 | 116 | # Editor-based Rest Client 117 | .idea/httpRequests 118 | 119 | ### Intellij Patch ### 120 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 121 | 122 | # *.iml 123 | # modules.xml 124 | # .idea/misc.xml 125 | # *.ipr 126 | 127 | # Sonarlint plugin 128 | .idea/sonarlint 129 | 130 | ### Linux ### 131 | 132 | # temporary files which can be created if a process still has a handle open of a deleted file 133 | .fuse_hidden* 134 | 135 | # KDE directory preferences 136 | .directory 137 | 138 | # Linux trash folder which might appear on any partition or disk 139 | .Trash-* 140 | 141 | # .nfs files are created when an open file is removed but is still being accessed 142 | .nfs* 143 | 144 | ### OSX ### 145 | # General 146 | .DS_Store 147 | .AppleDouble 148 | .LSOverride 149 | 150 | # Icon must end with two \r 151 | Icon 152 | 153 | # Thumbnails 154 | ._* 155 | 156 | # Files that might appear in the root of a volume 157 | .DocumentRevisions-V100 158 | .fseventsd 159 | .Spotlight-V100 160 | .TemporaryItems 161 | .Trashes 162 | .VolumeIcon.icns 163 | .com.apple.timemachine.donotpresent 164 | 165 | # Directories potentially created on remote AFP share 166 | .AppleDB 167 | .AppleDesktop 168 | Network Trash Folder 169 | Temporary Items 170 | .apdisk 171 | 172 | ### Python ### 173 | # Byte-compiled / optimized / DLL files 174 | __pycache__/ 175 | *.py[cod] 176 | *$py.class 177 | 178 | # C extensions 179 | 180 | # Distribution / packaging 181 | .Python 182 | build/ 183 | develop-eggs/ 184 | downloads/ 185 | eggs/ 186 | .eggs/ 187 | lib/ 188 | lib64/ 189 | parts/ 190 | sdist/ 191 | var/ 192 | wheels/ 193 | *.egg-info/ 194 | .installed.cfg 195 | *.egg 196 | MANIFEST 197 | 198 | # PyInstaller 199 | # Usually these files are written by a python script from a template 200 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 201 | *.manifest 202 | *.spec 203 | 204 | # Installer logs 205 | pip-log.txt 206 | pip-delete-this-directory.txt 207 | 208 | # Unit test / coverage reports 209 | htmlcov/ 210 | .tox/ 211 | .coverage 212 | .coverage.* 213 | .cache 214 | nosetests.xml 215 | coverage.xml 216 | *.cover 217 | .hypothesis/ 218 | .pytest_cache/ 219 | 220 | # Translations 221 | *.mo 222 | *.pot 223 | 224 | # Django stuff: 225 | *.log 226 | local_settings.py 227 | db.sqlite3 228 | 229 | # Flask stuff: 230 | instance/ 231 | .webassets-cache 232 | 233 | # Scrapy stuff: 234 | .scrapy 235 | 236 | # Sphinx documentation 237 | docs/_build/ 238 | 239 | # PyBuilder 240 | target/ 241 | 242 | # Jupyter Notebook 243 | .ipynb_checkpoints 244 | 245 | # pyenv 246 | .python-version 247 | 248 | # celery beat schedule file 249 | celerybeat-schedule 250 | 251 | # SageMath parsed files 252 | *.sage.py 253 | 254 | # Environments 255 | .env 256 | .venv 257 | env/ 258 | venv/ 259 | ENV/ 260 | env.bak/ 261 | venv.bak/ 262 | 263 | # Spyder project settings 264 | .spyderproject 265 | .spyproject 266 | 267 | # Rope project settings 268 | .ropeproject 269 | 270 | # mkdocs documentation 271 | /site 272 | 273 | # mypy 274 | .mypy_cache/ 275 | 276 | ### Python Patch ### 277 | .venv/ 278 | 279 | ### Solidity ### 280 | # Logs 281 | logs 282 | npm-debug.log* 283 | yarn-debug.log* 284 | yarn-error.log* 285 | 286 | # Runtime data 287 | pids 288 | *.pid 289 | *.seed 290 | *.pid.lock 291 | 292 | # Directory for instrumented libs generated by jscoverage/JSCover 293 | lib-cov 294 | 295 | # Coverage directory used by tools like istanbul 296 | coverage 297 | 298 | # nyc test coverage 299 | .nyc_output 300 | 301 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 302 | .grunt 303 | 304 | # Bower dependency directory (https://bower.io/) 305 | bower_components 306 | 307 | # node-waf configuration 308 | .lock-wscript 309 | 310 | # Compiled binary addons (https://nodejs.org/api/addons.html) 311 | build/Release 312 | 313 | # Dependency directories 314 | node_modules/ 315 | jspm_packages/ 316 | 317 | # TypeScript v1 declaration files 318 | typings/ 319 | 320 | # Optional npm cache directory 321 | .npm 322 | 323 | # Optional eslint cache 324 | .eslintcache 325 | 326 | # Optional REPL history 327 | .node_repl_history 328 | 329 | # Output of 'npm pack' 330 | *.tgz 331 | 332 | # Yarn Integrity file 333 | .yarn-integrity 334 | 335 | # dotenv environment variables file 336 | 337 | # parcel-bundler cache (https://parceljs.org/) 338 | 339 | # next.js build output 340 | .next 341 | 342 | # nuxt.js build output 343 | .nuxt 344 | 345 | # vuepress build output 346 | .vuepress/dist 347 | 348 | # Serverless directories 349 | .serverless 350 | 351 | ### Vim ### 352 | # Swap 353 | [._]*.s[a-v][a-z] 354 | [._]*.sw[a-p] 355 | [._]s[a-rt-v][a-z] 356 | [._]ss[a-gi-z] 357 | [._]sw[a-p] 358 | 359 | # Session 360 | Session.vim 361 | 362 | # Temporary 363 | .netrwhist 364 | # Auto-generated tag files 365 | tags 366 | # Persistent undo 367 | [._]*.un~ 368 | 369 | ### VirtualEnv ### 370 | # Virtualenv 371 | # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ 372 | [Bb]in 373 | [Ii]nclude 374 | [Ll]ib 375 | [Ll]ib64 376 | [Ll]ocal 377 | [Ss]cripts 378 | pyvenv.cfg 379 | pip-selfcheck.json 380 | 381 | ### Windows ### 382 | # Windows thumbnail cache files 383 | Thumbs.db 384 | ehthumbs.db 385 | ehthumbs_vista.db 386 | 387 | # Dump file 388 | *.stackdump 389 | 390 | # Folder config file 391 | [Dd]esktop.ini 392 | 393 | # Recycle Bin used on file shares 394 | $RECYCLE.BIN/ 395 | 396 | # Windows Installer files 397 | *.cab 398 | *.msi 399 | *.msix 400 | *.msm 401 | *.msp 402 | 403 | # Windows shortcuts 404 | *.lnk 405 | 406 | 407 | # End of https://www.gitignore.io/api/go,vim,osx,emacs,linux,python,windows,solidity,intellij,virtualenv 408 | -------------------------------------------------------------------------------- /offchain/proveth.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import json 3 | import sys 4 | from typing import List, Tuple 5 | 6 | from ethereum import ( 7 | block, 8 | messages, 9 | transactions, 10 | utils 11 | ) 12 | import pprint 13 | import requests 14 | import rlp 15 | from trie import HexaryTrie 16 | from trie.constants import ( 17 | BLANK_NODE, 18 | BLANK_NODE_HASH, 19 | NODE_TYPE_BLANK, 20 | NODE_TYPE_LEAF, 21 | NODE_TYPE_EXTENSION, 22 | NODE_TYPE_BRANCH, 23 | BLANK_HASH, 24 | ) 25 | from trie.utils.nodes import * 26 | from trie.utils.nibbles import encode_nibbles, decode_nibbles, bytes_to_nibbles 27 | import math 28 | 29 | MODULE_DEBUG = False 30 | 31 | def rec_hex(x): 32 | if isinstance(x, list): 33 | return [rec_hex(elem) for elem in x] 34 | else: 35 | return utils.encode_hex(x) 36 | 37 | def rec_bin(x): 38 | if isinstance(x, list): 39 | return [rec_bin(elem) for elem in x] 40 | elif isinstance(x, int): 41 | return x 42 | elif isinstance(x, str): 43 | if x.startswith("0x"): 44 | if len(x) != 2: 45 | return utils.decode_hex(x[2:]) 46 | else: 47 | return 0 48 | else: 49 | return utils.decode_hex(x) 50 | elif x is None: 51 | return 0 52 | 53 | def normalize_bytes(hash): 54 | if isinstance(hash, str): 55 | if hash.startswith("0x"): 56 | hash = hash[2:] 57 | if len(hash) % 2 != 0: 58 | hash = '0' + hash 59 | return utils.decode_hex(hash) 60 | elif isinstance(hash, int): 61 | return hash.to_bytes(length=(math.ceil(hash.bit_length() / 8)), 62 | byteorder="big", 63 | signed=False) 64 | else: 65 | return bytes(hash) 66 | 67 | def str2bool(v): 68 | if v.lower() in ('yes', 'true', 't', 'y', '1'): 69 | return True 70 | elif v.lower() in ('no', 'false', 'f', 'n', '0'): 71 | return False 72 | else: 73 | raise argparse.ArgumentTypeError('Boolean value expected.') 74 | 75 | def get_args(): 76 | parser = argparse.ArgumentParser( 77 | description="Patricia Merkle Trie Proof Generating Tool", 78 | formatter_class=argparse.RawTextHelpFormatter) 79 | # TODO add stuff around adding a block header and then generating proofs of 80 | # inclusion / exclusion etc etc etc 81 | blockInfoGroup = parser.add_mutually_exclusive_group(required=True) 82 | blockInfoGroup.add_argument('-n', '--block-number', 83 | default="", 84 | help="Block number that transaction exists in") 85 | blockInfoGroup.add_argument('-b', '--block-hash', 86 | default="", 87 | help="Block hash that transaction exists in") 88 | parser.add_argument('-tr', '--transaction_receipt_mode', required=False, 89 | type=str2bool, default="False", 90 | help="If the proof should be for a transaction receipt") 91 | parser.add_argument('-i', '--transaction_index', required=True, type=int, 92 | default="", 93 | help="Zero-based index of the transaction in the " 94 | "block (e.g. the third transaction in the block is at " 95 | "index 2)") 96 | parser.add_argument('-r', '--rpc', required=True, 97 | default="", 98 | help="URL of web3 rpc node. (e.g. " 99 | "http://localhost:8545)") 100 | parser.add_argument('-v', '--verbose', required=False, action='store_true', 101 | help="Print verbose output") 102 | return parser.parse_args() 103 | 104 | def block_header(block_dict: dict): 105 | b = block.BlockHeader( 106 | normalize_bytes(block_dict["parentHash"]), 107 | normalize_bytes(block_dict["sha3Uncles"]), 108 | utils.normalize_address(block_dict["miner"]), 109 | normalize_bytes(block_dict["stateRoot"]), 110 | normalize_bytes(block_dict["transactionsRoot"]), 111 | normalize_bytes(block_dict["receiptsRoot"]), 112 | utils.bytes_to_int(normalize_bytes(block_dict["logsBloom"])), 113 | utils.parse_as_int(block_dict['difficulty']), 114 | utils.parse_as_int(block_dict['number']), 115 | utils.parse_as_int(block_dict['gasLimit']), 116 | utils.parse_as_int(block_dict['gasUsed']), 117 | utils.parse_as_int(block_dict['timestamp']), 118 | normalize_bytes(block_dict["extraData"]), 119 | normalize_bytes(block_dict["mixHash"]), 120 | normalize_bytes(block_dict["nonce"]), 121 | ) 122 | if normalize_bytes(block_dict["hash"]) != b.hash: 123 | raise ValueError( 124 | """Blockhash does not match. 125 | Received invalid block header? {} vs {}""".format( 126 | str(normalize_bytes(block_dict["hash"])), 127 | str(b.hash))) 128 | return b 129 | 130 | def rlp_transaction(tx_dict: dict): 131 | t = transactions.Transaction( 132 | utils.parse_as_int(tx_dict['nonce']), 133 | utils.parse_as_int(tx_dict['gasPrice']), 134 | utils.parse_as_int(tx_dict['gas']), 135 | normalize_bytes(tx_dict['to'] or ''), 136 | utils.parse_as_int(tx_dict['value']), 137 | utils.decode_hex(tx_dict['input']), 138 | utils.parse_as_int(tx_dict['v']), 139 | utils.bytes_to_int(normalize_bytes(tx_dict['r'])), 140 | utils.bytes_to_int(normalize_bytes(tx_dict['s'])), 141 | ) 142 | if normalize_bytes(tx_dict['hash']) != t.hash: 143 | raise ValueError("""Tx hash does not match. Received invalid transaction? 144 | hashes: {} {} 145 | nonce: {} 146 | gasPrice: {} 147 | gas: {} 148 | to: {} 149 | value: {} 150 | input: {} 151 | v: {} 152 | r: {} 153 | s: {} 154 | """.format( 155 | tx_dict['hash'], t.hash, 156 | utils.parse_as_int(tx_dict['nonce']), 157 | utils.parse_as_int(tx_dict['gasPrice']), 158 | utils.parse_as_int(tx_dict['gas']), 159 | normalize_bytes(tx_dict['to'] or ''), 160 | utils.parse_as_int(tx_dict['value']), 161 | utils.decode_hex(tx_dict['input']), 162 | utils.parse_as_int(tx_dict['v']), 163 | utils.bytes_to_int(normalize_bytes(tx_dict['r'])), 164 | utils.bytes_to_int(normalize_bytes(tx_dict['s'])), 165 | )) 166 | return rlp.encode(t) 167 | 168 | 169 | def generate_proof(mpt, mpt_key_nibbles: bytes): 170 | if not all(0 <= nibble < 16 for nibble in mpt_key_nibbles): 171 | raise ValueError("mpt_key_nibbles has non-nibble elements {}".format(str(mpt_key_nibbles))) 172 | EMPTY = 128 173 | stack_indexes = [] 174 | stack = [] 175 | 176 | def aux(node_hash, mpt_key_nibbles): 177 | nonlocal stack_indexes 178 | nonlocal stack 179 | 180 | node = mpt.get_node(node_hash) 181 | if get_node_type(node) == NODE_TYPE_BLANK: 182 | if MODULE_DEBUG: 183 | print("Hit an empty node, returning") 184 | return 185 | elif get_node_type(node) == NODE_TYPE_BRANCH: 186 | if MODULE_DEBUG: 187 | print("Hit a branch node") 188 | if mpt_key_nibbles: 189 | i = mpt_key_nibbles[0] 190 | stack_indexes.append(i) 191 | stack.append(node) 192 | aux(node[i], mpt_key_nibbles[1:]) 193 | else: 194 | i = 16 195 | stack_indexes.append(i) 196 | stack.append(node) 197 | elif get_node_type(node) in [NODE_TYPE_EXTENSION, NODE_TYPE_LEAF]: 198 | if MODULE_DEBUG: 199 | print("Hit an extension/branch node") 200 | key = extract_key(node) 201 | prefix, key_remainder, mpt_key_nibbles_remainder = \ 202 | consume_common_prefix(key, mpt_key_nibbles) 203 | if not key_remainder: 204 | if MODULE_DEBUG: 205 | print("Non-divergent leaf/extension") 206 | stack_indexes.append(1) 207 | stack.append(node) 208 | if get_node_type(node) == NODE_TYPE_EXTENSION: 209 | aux(node[1], mpt_key_nibbles_remainder) 210 | else: 211 | if MODULE_DEBUG: 212 | print("Divergent leaf/extension") 213 | stack_indexes.append(0xff) 214 | stack.append(node) 215 | else: 216 | raise ValueError("Unknown node type: {}".format( 217 | get_node_type(node))) 218 | 219 | 220 | root_node = mpt.get_node(mpt.root_hash) 221 | if get_node_type(root_node) == NODE_TYPE_BLANK: 222 | if MODULE_DEBUG: 223 | print("Blank root node") 224 | else: 225 | aux(mpt.root_hash, mpt_key_nibbles) 226 | 227 | if MODULE_DEBUG: 228 | print('key nibbles: ', mpt_key_nibbles) 229 | print('Stack: ', rec_hex(stack)) 230 | print('StackIndexes:', stack_indexes) 231 | 232 | return stack 233 | 234 | def construct_proof_from_mpt(mpt, header, tx_index, proof_type): 235 | mpt_key_nibbles = bytes_to_nibbles(rlp.encode(tx_index)) 236 | stack = generate_proof(mpt, mpt_key_nibbles) 237 | 238 | proof_blob = rlp.encode([ 239 | proof_type, 240 | header, 241 | tx_index, 242 | stack, 243 | ]) 244 | return proof_blob 245 | 246 | def generate_proof_blob(block_dict, tx_index): 247 | header = block_header(block_dict) 248 | 249 | mpt = HexaryTrie(db={}) 250 | for tx_dict in block_dict["transactions"]: 251 | key = rlp.encode(utils.parse_as_int(tx_dict['transactionIndex'])) 252 | mpt.set(key, rlp_transaction(tx_dict)) 253 | 254 | if mpt.root_hash != normalize_bytes(block_dict['transactionsRoot']): 255 | raise ValueError( 256 | "Tx trie root hash does not match. Calculated: {} Sent: {}" 257 | .format(mpt.root_hash.hex(), 258 | normalize_bytes(block_dict['transactionsRoot']).hex())) 259 | 260 | return construct_proof_from_mpt(mpt, header, tx_index, 1) 261 | 262 | 263 | def decode_int_from_hex(x): 264 | return utils.decode_int(utils.decode_hex(x).lstrip(b"\x00")) 265 | 266 | def get_receipt_from_jsonrpc(response): 267 | if MODULE_DEBUG: 268 | print(response) 269 | assert response['jsonrpc'] == '2.0' 270 | assert 'id' in response 271 | assert 'result' in response 272 | receipt = response['result'] 273 | logs = [] 274 | for log in receipt['logs']: 275 | topics = [decode_int_from_hex(x) for x in log['topics']] 276 | logs.append(messages.Log( 277 | address = utils.normalize_address(log['address']), 278 | topics = topics, 279 | data = utils.decode_hex(log['data']))) 280 | # pre Byzantium returns a root 281 | if 'root' in receipt: 282 | return messages.Receipt( 283 | state_root = normalize_bytes(receipt['root']), 284 | gas_used = utils.parse_as_int(receipt['cumulativeGasUsed']), 285 | bloom = utils.parse_as_int(receipt['logsBloom']), 286 | logs = logs) 287 | receipt = messages.Receipt( 288 | state_root = (b'\x01' if receipt['status'] else b''), 289 | gas_used = utils.parse_as_int(receipt['cumulativeGasUsed']), 290 | bloom = utils.parse_as_int(receipt['logsBloom']), 291 | logs = logs) 292 | if MODULE_DEBUG: 293 | print("Rlp encoded receipt:") 294 | print(rec_hex(rlp.encode(receipt))) 295 | return receipt 296 | 297 | def get_receipt(url, transaction_hash): 298 | request = { 299 | "jsonrpc":"2.0", 300 | "method":"eth_getTransactionReceipt", 301 | "params":[transaction_hash], 302 | "id":1, 303 | } 304 | if MODULE_DEBUG: 305 | print(request) 306 | r = requests.post(url, json=request) 307 | r.raise_for_status() 308 | return get_receipt_from_jsonrpc(r.json()) 309 | 310 | def generate_proof_blob_receipt(block_dict, tx_index, url): 311 | header = block_header(block_dict) 312 | 313 | mpt = HexaryTrie(db={}) 314 | for tx_dict in block_dict["transactions"]: 315 | key = rlp.encode(utils.parse_as_int(tx_dict['transactionIndex'])) 316 | receipt = get_receipt(url, tx_dict['hash']) 317 | mpt.set(key, rlp.encode(receipt)) 318 | 319 | if mpt.root_hash != normalize_bytes(block_dict['receiptsRoot']): 320 | if MODULE_DEBUG: 321 | print("mpt.root_hash " + str(utils.encode_hex(mpt.root_hash))) 322 | print("receiptRoot " + 323 | str(normalize_bytes(utils.encode_hex(block_dict['receiptsRoot'])))) 324 | raise ValueError("Block receiptRoot hash does not match.") 325 | 326 | return construct_proof_from_mpt(mpt, header, tx_index, 2) 327 | 328 | def generate_proof_blob_from_jsonrpc_response(response, tx_index, 329 | url="", receipt_mode=False): 330 | if MODULE_DEBUG: 331 | print(response) 332 | assert response['jsonrpc'] == '2.0' 333 | assert 'id' in response 334 | assert 'result' in response 335 | if receipt_mode: 336 | return generate_proof_blob_receipt(response['result'], tx_index, url) 337 | return generate_proof_blob(response['result'], tx_index) 338 | 339 | 340 | def generate_proof_blob_from_jsonrpc_using_hash(url, block_hash, 341 | tx_index, receipt_mode=False): 342 | request = { 343 | "jsonrpc":"2.0", 344 | "method":"eth_getBlockByHash", 345 | "params":['0x' + utils.encode_hex(block_hash), True], 346 | "id":1, 347 | } 348 | if MODULE_DEBUG: 349 | print(request) 350 | r = requests.post(url, json=request) 351 | r.raise_for_status() 352 | return generate_proof_blob_from_jsonrpc_response(r.json(), tx_index, 353 | url, receipt_mode) 354 | 355 | def generate_proof_blob_from_jsonrpc_using_number(url, block_number, 356 | tx_index, receipt_mode=False): 357 | request = { 358 | "jsonrpc":"2.0", 359 | "method":"eth_getBlockByNumber", 360 | "params":[str(hex(block_number)), True], 361 | "id":1, 362 | } 363 | if MODULE_DEBUG: 364 | print(request) 365 | r = requests.post(url, json=request) 366 | r.raise_for_status() 367 | return generate_proof_blob_from_jsonrpc_response(r.json(), tx_index, 368 | url, receipt_mode) 369 | 370 | def main(): 371 | args = get_args() 372 | if args.verbose: 373 | global MODULE_DEBUG 374 | MODULE_DEBUG = True 375 | if args.block_hash: 376 | proof_blob = generate_proof_blob_from_jsonrpc_using_hash( 377 | args.rpc, utils.decode_hex(args.block_hash), 378 | args.transaction_index, args.transaction_receipt_mode) 379 | elif args.block_number: 380 | proof_blob = generate_proof_blob_from_jsonrpc_using_number( 381 | args.rpc, int(args.block_number), 382 | args.transaction_index, args.transaction_receipt_mode) 383 | else: 384 | print("Either --block-hash or --block-number are required") 385 | exit(1) 386 | 387 | print("Final Output: ") 388 | print(rec_hex(proof_blob)) 389 | exit(0) 390 | 391 | if __name__ == "__main__": 392 | main() 393 | -------------------------------------------------------------------------------- /onchain/ProvethVerifier.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./Solidity-RLP/contracts/RLPReader.sol"; 4 | 5 | contract ProvethVerifier { 6 | using RLPReader for RLPReader.RLPItem; 7 | using RLPReader for bytes; 8 | 9 | uint256 constant TX_ROOT_HASH_INDEX = 4; 10 | 11 | struct UnsignedTransaction { 12 | uint256 nonce; 13 | uint256 gasprice; 14 | uint256 startgas; 15 | address to; 16 | uint256 value; 17 | bytes data; 18 | bool isContractCreation; 19 | } 20 | 21 | struct SignedTransaction { 22 | uint256 nonce; 23 | uint256 gasprice; 24 | uint256 startgas; 25 | address to; 26 | uint256 value; 27 | bytes data; 28 | uint256 v; 29 | uint256 r; 30 | uint256 s; 31 | bool isContractCreation; 32 | } 33 | 34 | function isEmpty(RLPReader.RLPItem memory item) internal pure returns (bool) { 35 | if (item.len != 1) { 36 | return false; 37 | } 38 | uint8 b; 39 | uint memPtr = item.memPtr; 40 | assembly { 41 | b := byte(0, mload(memPtr)) 42 | } 43 | return b == 0x80 /* empty byte string */ || b == 0xc0 /* empty list */; 44 | } 45 | 46 | function isEmptyBytesequence(RLPReader.RLPItem memory item) internal pure returns (bool) { 47 | if (item.len != 1) { 48 | return false; 49 | } 50 | uint8 b; 51 | uint memPtr = item.memPtr; 52 | assembly { 53 | b := byte(0, mload(memPtr)) 54 | } 55 | return b == 0x80 /* empty byte string */; 56 | } 57 | 58 | 59 | function decodeUnsignedTx(bytes memory rlpUnsignedTx) internal pure returns (UnsignedTransaction memory t) { 60 | RLPReader.RLPItem[] memory fields = rlpUnsignedTx.toRlpItem().toList(); 61 | require(fields.length == 6); 62 | address potentialAddress; 63 | bool isContractCreation; 64 | if(isEmpty(fields[3])) { 65 | potentialAddress = 0x0000000000000000000000000000000000000000; 66 | isContractCreation = true; 67 | } else { 68 | potentialAddress = fields[3].toAddress(); 69 | isContractCreation = false; 70 | } 71 | t = UnsignedTransaction( 72 | fields[0].toUint(), // nonce 73 | fields[1].toUint(), // gasprice 74 | fields[2].toUint(), // startgas 75 | potentialAddress, // to 76 | fields[4].toUint(), // value 77 | fields[5].toBytes(), // data 78 | isContractCreation 79 | ); 80 | } 81 | 82 | function decodeSignedTx(bytes memory rlpSignedTx) internal pure returns (SignedTransaction memory t) { 83 | RLPReader.RLPItem[] memory fields = rlpSignedTx.toRlpItem().toList(); 84 | address potentialAddress; 85 | bool isContractCreation; 86 | if(isEmpty(fields[3])) { 87 | potentialAddress = 0x0000000000000000000000000000000000000000; 88 | isContractCreation = true; 89 | } else { 90 | potentialAddress = fields[3].toAddress(); 91 | isContractCreation = false; 92 | } 93 | t = SignedTransaction( 94 | fields[0].toUint(), 95 | fields[1].toUint(), 96 | fields[2].toUint(), 97 | potentialAddress, 98 | fields[4].toUint(), 99 | fields[5].toBytes(), 100 | fields[6].toUint(), 101 | fields[7].toUint(), 102 | fields[8].toUint(), 103 | isContractCreation 104 | ); 105 | } 106 | 107 | function decodeNibbles(bytes memory compact, uint skipNibbles) internal pure returns (bytes memory nibbles) { 108 | require(compact.length > 0); 109 | 110 | uint length = compact.length * 2; 111 | require(skipNibbles <= length); 112 | length -= skipNibbles; 113 | 114 | nibbles = new bytes(length); 115 | uint nibblesLength = 0; 116 | 117 | for (uint i = skipNibbles; i < skipNibbles + length; i += 1) { 118 | if (i % 2 == 0) { 119 | nibbles[nibblesLength] = bytes1((uint8(compact[i/2]) >> 4) & 0xF); 120 | } else { 121 | nibbles[nibblesLength] = bytes1((uint8(compact[i/2]) >> 0) & 0xF); 122 | } 123 | nibblesLength += 1; 124 | } 125 | 126 | assert(nibblesLength == nibbles.length); 127 | } 128 | 129 | function merklePatriciaCompactDecode(bytes memory compact) internal pure returns (bool isLeaf, bytes memory nibbles) { 130 | require(compact.length > 0); 131 | uint first_nibble = uint8(compact[0]) >> 4 & 0xF; 132 | uint skipNibbles; 133 | if (first_nibble == 0) { 134 | skipNibbles = 2; 135 | isLeaf = false; 136 | } else if (first_nibble == 1) { 137 | skipNibbles = 1; 138 | isLeaf = false; 139 | } else if (first_nibble == 2) { 140 | skipNibbles = 2; 141 | isLeaf = true; 142 | } else if (first_nibble == 3) { 143 | skipNibbles = 1; 144 | isLeaf = true; 145 | } else { 146 | // Not supposed to happen! 147 | revert(); 148 | } 149 | return (isLeaf, decodeNibbles(compact, skipNibbles)); 150 | } 151 | 152 | function sharedPrefixLength(uint xsOffset, bytes memory xs, bytes memory ys) internal pure returns (uint) { 153 | uint i; 154 | for (i = 0; i + xsOffset < xs.length && i < ys.length; i++) { 155 | if (xs[i + xsOffset] != ys[i]) { 156 | return i; 157 | } 158 | } 159 | return i; 160 | } 161 | 162 | struct Proof { 163 | uint256 kind; 164 | bytes rlpBlockHeader; 165 | bytes32 txRootHash; 166 | bytes rlpTxIndex; 167 | uint txIndex; 168 | bytes mptKey; 169 | RLPReader.RLPItem[] stack; 170 | } 171 | 172 | function decodeProofBlob(bytes memory proofBlob) internal pure returns (Proof memory proof) { 173 | RLPReader.RLPItem[] memory proofFields = proofBlob.toRlpItem().toList(); 174 | bytes memory rlpTxIndex = proofFields[2].toRlpBytes(); 175 | proof = Proof( 176 | proofFields[0].toUint(), 177 | proofFields[1].toRlpBytes(), 178 | bytes32(proofFields[1].toList()[TX_ROOT_HASH_INDEX].toUint()), 179 | rlpTxIndex, 180 | proofFields[2].toUint(), 181 | decodeNibbles(rlpTxIndex, 0), 182 | proofFields[3].toList() 183 | ); 184 | } 185 | 186 | uint8 constant public TX_PROOF_RESULT_PRESENT = 1; 187 | uint8 constant public TX_PROOF_RESULT_ABSENT = 2; 188 | 189 | function txProof( 190 | bytes32 blockHash, 191 | bytes memory proofBlob 192 | ) public pure returns ( 193 | uint8 result, // see TX_PROOF_RESULT_* 194 | uint256 index, 195 | uint256 nonce, 196 | uint256 gasprice, 197 | uint256 startgas, 198 | address to, // 20 byte address for "regular" tx, 199 | // empty for contract creation tx 200 | uint256 value, 201 | bytes memory data, 202 | uint256 v, 203 | uint256 r, 204 | uint256 s, 205 | bool isContractCreation 206 | ) { 207 | SignedTransaction memory t; 208 | (result, index, t) = validateTxProof(blockHash, proofBlob); 209 | nonce = t.nonce; 210 | gasprice = t.gasprice; 211 | startgas = t.startgas; 212 | to = t.to; 213 | value = t.value; 214 | data = t.data; 215 | v = t.v; 216 | r = t.r; 217 | s = t.s; 218 | isContractCreation = t.isContractCreation; 219 | } 220 | 221 | function validateTxProof( 222 | bytes32 blockHash, 223 | bytes memory proofBlob 224 | ) internal pure returns (uint8 result, uint256 index, SignedTransaction memory t) { 225 | result = 0; 226 | index = 0; 227 | Proof memory proof = decodeProofBlob(proofBlob); 228 | if (proof.kind != 1) { 229 | revert(); 230 | } 231 | 232 | if (keccak256(proof.rlpBlockHeader) != blockHash) { 233 | revert(); 234 | } 235 | 236 | 237 | bytes memory rlpTx = validateMPTProof(proof.txRootHash, proof.mptKey, proof.stack); 238 | 239 | if (rlpTx.length == 0) { 240 | // empty node 241 | return ( 242 | TX_PROOF_RESULT_ABSENT, 243 | proof.txIndex, 244 | t 245 | ); 246 | } else { 247 | return ( 248 | TX_PROOF_RESULT_PRESENT, 249 | proof.txIndex, 250 | decodeSignedTx(rlpTx) 251 | ); 252 | } 253 | } 254 | 255 | /// @dev Computes the hash of the Merkle-Patricia-Trie hash of the input. 256 | /// Merkle-Patricia-Tries use a weird "hash function" that outputs 257 | /// *variable-length* hashes: If the input is shorter than 32 bytes, 258 | /// the MPT hash is the input. Otherwise, the MPT hash is the 259 | /// Keccak-256 hash of the input. 260 | /// The easiest way to compare variable-length byte sequences is 261 | /// to compare their Keccak-256 hashes. 262 | /// @param input The byte sequence to be hashed. 263 | /// @return Keccak-256(MPT-hash(input)) 264 | function mptHashHash(bytes memory input) internal pure returns (bytes32) { 265 | if (input.length < 32) { 266 | return keccak256(input); 267 | } else { 268 | return keccak256(abi.encodePacked(keccak256(abi.encodePacked(input)))); 269 | } 270 | } 271 | 272 | /// @dev Validates a Merkle-Patricia-Trie proof. 273 | /// If the proof proves the inclusion of some key-value pair in the 274 | /// trie, the value is returned. Otherwise, i.e. if the proof proves 275 | /// the exclusion of a key from the trie, an empty byte array is 276 | /// returned. 277 | /// @param rootHash is the Keccak-256 hash of the root node of the MPT. 278 | /// @param mptKey is the key (consisting of nibbles) of the node whose 279 | /// inclusion/exclusion we are proving. 280 | /// @param stack is the stack of MPT nodes (starting with the root) that 281 | /// need to be traversed during verification. 282 | /// @return value whose inclusion is proved or an empty byte array for 283 | /// a proof of exclusion 284 | function validateMPTProof( 285 | bytes32 rootHash, 286 | bytes memory mptKey, 287 | RLPReader.RLPItem[] memory stack 288 | ) internal pure returns (bytes memory value) { 289 | uint mptKeyOffset = 0; 290 | 291 | bytes32 nodeHashHash; 292 | bytes memory rlpNode; 293 | RLPReader.RLPItem[] memory node; 294 | 295 | RLPReader.RLPItem memory rlpValue; 296 | 297 | if (stack.length == 0) { 298 | // Root hash of empty Merkle-Patricia-Trie 299 | require(rootHash == 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421); 300 | return new bytes(0); 301 | } 302 | 303 | // Traverse stack of nodes starting at root. 304 | for (uint i = 0; i < stack.length; i++) { 305 | 306 | // We use the fact that an rlp encoded list consists of some 307 | // encoding of its length plus the concatenation of its 308 | // *rlp-encoded* items. 309 | rlpNode = stack[i].toRlpBytes(); 310 | // The root node is hashed with Keccak-256 ... 311 | if (i == 0 && rootHash != keccak256(rlpNode)) { 312 | revert(); 313 | } 314 | // ... whereas all other nodes are hashed with the MPT 315 | // hash function. 316 | if (i != 0 && nodeHashHash != mptHashHash(rlpNode)) { 317 | revert(); 318 | } 319 | // We verified that stack[i] has the correct hash, so we 320 | // may safely decode it. 321 | node = stack[i].toList(); 322 | 323 | if (node.length == 2) { 324 | // Extension or Leaf node 325 | 326 | bool isLeaf; 327 | bytes memory nodeKey; 328 | (isLeaf, nodeKey) = merklePatriciaCompactDecode(node[0].toBytes()); 329 | 330 | uint prefixLength = sharedPrefixLength(mptKeyOffset, mptKey, nodeKey); 331 | mptKeyOffset += prefixLength; 332 | 333 | if (prefixLength < nodeKey.length) { 334 | // Proof claims divergent extension or leaf. (Only 335 | // relevant for proofs of exclusion.) 336 | // An Extension/Leaf node is divergent iff it "skips" over 337 | // the point at which a Branch node should have been had the 338 | // excluded key been included in the trie. 339 | // Example: Imagine a proof of exclusion for path [1, 4], 340 | // where the current node is a Leaf node with 341 | // path [1, 3, 3, 7]. For [1, 4] to be included, there 342 | // should have been a Branch node at [1] with a child 343 | // at 3 and a child at 4. 344 | 345 | // Sanity check 346 | if (i < stack.length - 1) { 347 | // divergent node must come last in proof 348 | revert(); 349 | } 350 | 351 | return new bytes(0); 352 | } 353 | 354 | if (isLeaf) { 355 | // Sanity check 356 | if (i < stack.length - 1) { 357 | // leaf node must come last in proof 358 | revert(); 359 | } 360 | 361 | if (mptKeyOffset < mptKey.length) { 362 | return new bytes(0); 363 | } 364 | 365 | rlpValue = node[1]; 366 | return rlpValue.toBytes(); 367 | } else { // extension 368 | // Sanity check 369 | if (i == stack.length - 1) { 370 | // shouldn't be at last level 371 | revert(); 372 | } 373 | 374 | if (!node[1].isList()) { 375 | // rlp(child) was at least 32 bytes. node[1] contains 376 | // Keccak256(rlp(child)). 377 | nodeHashHash = keccak256(node[1].toBytes()); 378 | } else { 379 | // rlp(child) was at less than 32 bytes. node[1] contains 380 | // rlp(child). 381 | nodeHashHash = keccak256(node[1].toRlpBytes()); 382 | } 383 | } 384 | } else if (node.length == 17) { 385 | // Branch node 386 | 387 | if (mptKeyOffset != mptKey.length) { 388 | // we haven't consumed the entire path, so we need to look at a child 389 | uint8 nibble = uint8(mptKey[mptKeyOffset]); 390 | mptKeyOffset += 1; 391 | if (nibble >= 16) { 392 | // each element of the path has to be a nibble 393 | revert(); 394 | } 395 | 396 | if (isEmptyBytesequence(node[nibble])) { 397 | // Sanity 398 | if (i != stack.length - 1) { 399 | // leaf node should be at last level 400 | revert(); 401 | } 402 | 403 | return new bytes(0); 404 | } else if (!node[nibble].isList()) { 405 | nodeHashHash = keccak256(node[nibble].toBytes()); 406 | } else { 407 | nodeHashHash = keccak256(node[nibble].toRlpBytes()); 408 | } 409 | } else { 410 | // we have consumed the entire mptKey, so we need to look at what's contained in this node. 411 | 412 | // Sanity 413 | if (i != stack.length - 1) { 414 | // should be at last level 415 | revert(); 416 | } 417 | 418 | return node[16].toBytes(); 419 | } 420 | } 421 | } 422 | } 423 | } 424 | -------------------------------------------------------------------------------- /specification.md: -------------------------------------------------------------------------------- 1 | # Proveth proof-blob format specification 2 | 3 | #### Table of Contents 4 | 5 | * [Proof kind](#proof-kind) 6 | * [Proof of transaction inclusion/exclusion](#proof-of-transaction-inclusionexclusion) 7 | * [Examples](#examples) 8 | * [Transaction 0 of block 5000000 (mainnet)](#transaction-0-of-block-5000000-mainnet) 9 | * [Transaction 109 of block 5000000 (mainnet)](#transaction-109-of-block-5000000-mainnet) 10 | * [Transaction 6000 of block 6027762 (mainnet)](#transaction-6000-of-block-6027762-mainnet) 11 | 12 | ---- 13 | 14 | Throughout this document, we will use zero-based indexing and refer to the initial element of a sequence as the zeroth element. 15 | 16 | We also assume that you're somewhat familiar with Ethereum's [RLP encoding](https://github.com/ethereum/wiki/wiki/RLP) and 17 | [Merkle-Patricia-Tries](https://github.com/ethereum/wiki/wiki/Patricia-Tree). 18 | 19 | ## Proof kind 20 | 21 | Every proveth proof-blob is an RLP-encoded list. 22 | The zeroth element of the list is a uint that specifies the *kind* of proof the proof-blob represents: 23 | ``` 24 | [kind, actual proof...] 25 | ``` 26 | 27 | Currently we support two types of proofs: 28 | - Type `1` proofs of inclusion/exclusion for the transaction requests aka transactions. 29 | - Type `2` proofs of inclusion/exclusion for the transaction outcomes aka transactions receipts. 30 | 31 | ## Proof of transaction (receipt) inclusion/exclusion 32 | 33 | A proof of inclusion proves a statement of the form "the given transaction is present at the given index in the given block". A proof of exclusion proves a statement of the form "there is no transaction at the given index in the given block". Replace "transaction" with "transaction receipt" in the previous sentence in case of a proof of type 2. 34 | 35 | A proof consists of 4 elements: 36 | - 0: *kind* equals `1` for transactions and equals `2` for transaction receipts. 37 | - 1: *consensus block header*, consisting of 38 | ``` 39 | [, 40 | , 41 | , 42 | , 43 | , 44 | , 45 | , 46 | , 47 | , 48 | , 49 | , 50 | , 51 | , 52 | , 53 | ] 54 | ``` 55 | - 2: *transaction index* (zero-based, i.e. the initial transaction in the block has index 0) 56 | - 3: *Merkle-Patricia-Trie nodes* on the path to the transaction. Each node is a list of length 2 (for *extension* and *leaf* nodes) or a list of length 17 (for *branch* nodes). 57 | 58 | ### Examples 59 | 60 | For better readability, we hex-encode all bytestrings in the examples below. 61 | 62 | You can use the following python functions to decode and encode the proof-blobs in the examples: 63 | ```python 64 | import rlp 65 | 66 | def decode_proof_blob(hex_blob): 67 | blob = bytes.fromhex(hex_blob) 68 | return rec_hex(rlp.decode(blob)) 69 | 70 | def encode_proof_blob(list): 71 | blob = rlp.encode(rec_bin(list)) 72 | return blob.hex() 73 | 74 | def rec_hex(x): 75 | if isinstance(x, list): 76 | return [rec_hex(elem) for elem in x] 77 | else: 78 | return x.hex() 79 | 80 | def rec_bin(x): 81 | if isinstance(x, list): 82 | return [rec_bin(elem) for elem in x] 83 | elif isinstance(x, int): 84 | return x 85 | elif isinstance(x, str): 86 | if x.startswith("0x"): 87 | return bytes.fromhex(x[2:]) 88 | else: 89 | return bytes.fromhex(x) 90 | ``` 91 | 92 | #### Transaction 0 of block 5000000 (mainnet) 93 | 94 | This is proof-blob for transaction 0 of block 5000000 on the mainnet: 95 | ``` 96 | 'f9039601f90204a0cae4df80f5862e4321690857eded0d8a40136dafb8155453920bade5bd0c46c0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a06092dfd6bcdd375764d8718c365ce0e8323034da3d3b0c6d72cf7304996b86ada091dfce7cc2174482b5ebcf6f4beedce854641982eadb1a8cf538e3206abf7836a06db67db55d5d972c59646a3bda26a39422e71fe400e4cdf9eb7f5c09b0efa7d0b901008584009c4dd8101162295d8604b1850200788d4c81f39044821155049d2c036a8a00d07f2a10383180984400b0290ba00293400c1d414a5018104a010220101909b918c601251215109755b90003c6a2c23490829e319a506281d9641ac39a840d3aa03e4a287900e0c09641594409a2010543016e966382c02040754030430e2d708316ec64008f0c0100c713b51f8004005bd48980143e08b22bf2262365b8b2658804a560f1028207666d10288144a5a14609a5bcb221280b13da2f4c8800d8422cc27126a46a04f08c00ca9004081d65cc75d10c62862256118481d2e881a993780808e0a00086e321a4602cb214c0044215281c2ccbca824aca00824a8087090c21c56929b2834c4b40837a121d8379fac5845a70760d83743132a094cd4e844619ee20989578276a0a9046877d569d37ba076bf2e8e34f76189dea884617a20003ba3f2580f9018af90111a0915214954ddbb2b08a9d9de48b2bc31289d3bda55b8f017242f376ff8df56b93a00106fad9e6c0d6c92e84893ba3c26aba93b4e2a1ab3fa52587a6946b7eedebada074fd2bf3665a2576317a74c0215cd4ac19ee0305191df1ae5f5eaa6788c2a9a9a04157e0398ade02f9acf5e4183d5c554af0e39387b7f5c4da6990b3df177ddd32a013e1c573e8e8f09e3d23d30ccfccbafd4ef9666f7df578999bdc5b9c65bdcc80a041a8eb6c4616c8e12c56a6fafbe9013478e14bce6afad04f9b28f47bdcb5373aa09c08f2a7050bdd3e0d6922ff9c8ce801436afcd078a79df6ffae267a2a755b0b80a012e7ff44f271d1f5968b23a258b21f703cacfe3061e0fafe9ea04b810537a6068080808080808080f87430b871f86f820fef851f3305bc008301d8a89488a690553913a795c3c668275297635b903a29e5882c250d42400204008025a05df5034c46551b630553201581bd690e021c13b3134f37d14eb19ea971292a39a04f263a9ef7b6e6d18d1b6c120f051e51aa737e12aabcf9466377779eb60656a9' 97 | ``` 98 | When we decode it, we get the following: 99 | ``` 100 | [ 101 | # kind 102 | 1, 103 | # consensus block header 104 | # '91dfce7cc2174482b5ebcf6f4beedce854641982eadb1a8cf538e3206abf7836' is the hash of the transaction Merkle-Patricia-Trie 105 | ['cae4df80f5862e4321690857eded0d8a40136dafb8155453920bade5bd0c46c0', '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', 'b2930b35844a230f00e51431acae96fe543a0347', '6092dfd6bcdd375764d8718c365ce0e8323034da3d3b0c6d72cf7304996b86ad', '91dfce7cc2174482b5ebcf6f4beedce854641982eadb1a8cf538e3206abf7836', '6db67db55d5d972c59646a3bda26a39422e71fe400e4cdf9eb7f5c09b0efa7d0', '8584009c4dd8101162295d8604b1850200788d4c81f39044821155049d2c036a8a00d07f2a10383180984400b0290ba00293400c1d414a5018104a010220101909b918c601251215109755b90003c6a2c23490829e319a506281d9641ac39a840d3aa03e4a287900e0c09641594409a2010543016e966382c02040754030430e2d708316ec64008f0c0100c713b51f8004005bd48980143e08b22bf2262365b8b2658804a560f1028207666d10288144a5a14609a5bcb221280b13da2f4c8800d8422cc27126a46a04f08c00ca9004081d65cc75d10c62862256118481d2e881a993780808e0a00086e321a4602cb214c0044215281c2ccbca824aca00824a80', '090c21c56929b2', '4c4b40', '7a121d', '79fac5', '5a70760d', '743132', '94cd4e844619ee20989578276a0a9046877d569d37ba076bf2e8e34f76189dea', '4617a20003ba3f25'], 106 | # transaction index 107 | 0, 108 | # Merkle-Patricia-Trie nodes on path to transaction 109 | # the 8t element of the zeroth node is '12e7ff44f271d1f5968b23a258b21f703cacfe3061e0fafe9ea04b810537a606', which is the hash of the first node 110 | # the 1st element of the first node is 'f86f820fef851f3305...6377779eb60656a9', which is the rlp-encoded transaction 111 | [ 112 | # Root node in the transaction Merkle-Patricia-Trie (this is a "branch node") 113 | ['915214954ddbb2b08a9d9de48b2bc31289d3bda55b8f017242f376ff8df56b93', '0106fad9e6c0d6c92e84893ba3c26aba93b4e2a1ab3fa52587a6946b7eedebad', '74fd2bf3665a2576317a74c0215cd4ac19ee0305191df1ae5f5eaa6788c2a9a9', '4157e0398ade02f9acf5e4183d5c554af0e39387b7f5c4da6990b3df177ddd32', '13e1c573e8e8f09e3d23d30ccfccbafd4ef9666f7df578999bdc5b9c65bdcc80', '41a8eb6c4616c8e12c56a6fafbe9013478e14bce6afad04f9b28f47bdcb5373a', '9c08f2a7050bdd3e0d6922ff9c8ce801436afcd078a79df6ffae267a2a755b0b', '', '12e7ff44f271d1f5968b23a258b21f703cacfe3061e0fafe9ea04b810537a606', '', '', '', '', '', '', '', ''], 114 | # 1st child of root node in the transaction Merkle-Patricia-Trie (this is a "leaf node") 115 | ['30', 'f86f820fef851f3305bc008301d8a89488a690553913a795c3c668275297635b903a29e5882c250d42400204008025a05df5034c46551b630553201581bd690e021c13b3134f37d14eb19ea971292a39a04f263a9ef7b6e6d18d1b6c120f051e51aa737e12aabcf9466377779eb60656a9'] 116 | ] 117 | ] 118 | ``` 119 | 120 | #### Transaction 109 of block 5000000 (mainnet) 121 | 122 | This is a proof of exclusion since no transaction with index 109 exists in block 5000000. Proof-blob: 123 | ``` 124 | f904d401f90204a0cae4df80f5862e4321690857eded0d8a40136dafb8155453920bade5bd0c46c0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a06092dfd6bcdd375764d8718c365ce0e8323034da3d3b0c6d72cf7304996b86ada091dfce7cc2174482b5ebcf6f4beedce854641982eadb1a8cf538e3206abf7836a06db67db55d5d972c59646a3bda26a39422e71fe400e4cdf9eb7f5c09b0efa7d0b901008584009c4dd8101162295d8604b1850200788d4c81f39044821155049d2c036a8a00d07f2a10383180984400b0290ba00293400c1d414a5018104a010220101909b918c601251215109755b90003c6a2c23490829e319a506281d9641ac39a840d3aa03e4a287900e0c09641594409a2010543016e966382c02040754030430e2d708316ec64008f0c0100c713b51f8004005bd48980143e08b22bf2262365b8b2658804a560f1028207666d10288144a5a14609a5bcb221280b13da2f4c8800d8422cc27126a46a04f08c00ca9004081d65cc75d10c62862256118481d2e881a993780808e0a00086e321a4602cb214c0044215281c2ccbca824aca00824a8087090c21c56929b2834c4b40837a121d8379fac5845a70760d83743132a094cd4e844619ee20989578276a0a9046877d569d37ba076bf2e8e34f76189dea884617a20003ba3f256df902c8f90111a0915214954ddbb2b08a9d9de48b2bc31289d3bda55b8f017242f376ff8df56b93a00106fad9e6c0d6c92e84893ba3c26aba93b4e2a1ab3fa52587a6946b7eedebada074fd2bf3665a2576317a74c0215cd4ac19ee0305191df1ae5f5eaa6788c2a9a9a04157e0398ade02f9acf5e4183d5c554af0e39387b7f5c4da6990b3df177ddd32a013e1c573e8e8f09e3d23d30ccfccbafd4ef9666f7df578999bdc5b9c65bdcc80a041a8eb6c4616c8e12c56a6fafbe9013478e14bce6afad04f9b28f47bdcb5373aa09c08f2a7050bdd3e0d6922ff9c8ce801436afcd078a79df6ffae267a2a755b0b80a012e7ff44f271d1f5968b23a258b21f703cacfe3061e0fafe9ea04b810537a6068080808080808080f901b1a0926c9592f6e3f3fdb9510de57fb60b0413fa0e8c9bc9b3ae25536487354a136ca078df5aef8d73d86c9c875323a90584e70638b590bb9314ebb91a010a7f3b0874a0e86be9fc7f24962a2a5872b4aac6fbe62149b11e787982b3b89f3f59ba6e68d9a0277156f773f0db978ce9a8248447188868ac05a13fb5d3fb595bf58ab715c58da0fbb50c6c762e920d12b36be8e6cf3f62fc15bed2b3826a9295dde31e0eaca92aa0d252a56cb1f2ff5d8beb51cd7e38d8e9bbf113e6719628e8cab574fba68a33cda03d6db3090e80411df76c76aabed90a36ecbb7ca78d4dcbdbd45787ebac96adeba04ce247a831382c25b3cecf5824077af5d8340d2f531343da143a8f24b5623c91a008b5b9bad14b02c79370f9b741b7051a195301773aac7ff7fbf626c95e9fa89ca0cfeb46c773370ca40ccba0066d4685bb8ffa58a8b471748f22fc1f04c07f20fda03905a9d97fccfb9e5d2a0b9030dc32da7e461bd90eb66179368ac5ac5f913e80a02c042434f04cfcca5f418778fe9fcb05e753a1437a1a636000d021a90c6e2643a06ff3f067699fdcf7d7a76c61988dc152ba52984eb5230d15db058c7f04447cf980808080 125 | ``` 126 | 127 | Decoded proof-blob: 128 | ``` 129 | [ 130 | # kind 131 | '01', 132 | # consensus block header 133 | # '91dfce7cc2174482b5ebcf6f4beedce854641982eadb1a8cf538e3206abf7836' is the hash of the transaction Merkle-Patricia-Trie 134 | ['cae4df80f5862e4321690857eded0d8a40136dafb8155453920bade5bd0c46c0', '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', 'b2930b35844a230f00e51431acae96fe543a0347', '6092dfd6bcdd375764d8718c365ce0e8323034da3d3b0c6d72cf7304996b86ad', '91dfce7cc2174482b5ebcf6f4beedce854641982eadb1a8cf538e3206abf7836', '6db67db55d5d972c59646a3bda26a39422e71fe400e4cdf9eb7f5c09b0efa7d0', '8584009c4dd8101162295d8604b1850200788d4c81f39044821155049d2c036a8a00d07f2a10383180984400b0290ba00293400c1d414a5018104a010220101909b918c601251215109755b90003c6a2c23490829e319a506281d9641ac39a840d3aa03e4a287900e0c09641594409a2010543016e966382c02040754030430e2d708316ec64008f0c0100c713b51f8004005bd48980143e08b22bf2262365b8b2658804a560f1028207666d10288144a5a14609a5bcb221280b13da2f4c8800d8422cc27126a46a04f08c00ca9004081d65cc75d10c62862256118481d2e881a993780808e0a00086e321a4602cb214c0044215281c2ccbca824aca00824a80', '090c21c56929b2', '4c4b40', '7a121d', '79fac5', '5a70760d', '743132', '94cd4e844619ee20989578276a0a9046877d569d37ba076bf2e8e34f76189dea', '4617a20003ba3f25'], 135 | # transaction index (0x6d == 119) 136 | '6d', 137 | # Merkle-Patricia-Trie nodes on path to transaction 138 | # the 6th element of the zeroth node is '12e7ff44f271d1f5968b23a258b21f703cacfe3061e0fafe9ea04b810537a606', which is the hash of the first node 139 | # the 13th element of the first node is '', which indicates that the node has no child in this position. 140 | # Hence there is no transaction with index 0x6d. 141 | [ 142 | ['915214954ddbb2b08a9d9de48b2bc31289d3bda55b8f017242f376ff8df56b93', '0106fad9e6c0d6c92e84893ba3c26aba93b4e2a1ab3fa52587a6946b7eedebad', '74fd2bf3665a2576317a74c0215cd4ac19ee0305191df1ae5f5eaa6788c2a9a9', '4157e0398ade02f9acf5e4183d5c554af0e39387b7f5c4da6990b3df177ddd32', '13e1c573e8e8f09e3d23d30ccfccbafd4ef9666f7df578999bdc5b9c65bdcc80', '41a8eb6c4616c8e12c56a6fafbe9013478e14bce6afad04f9b28f47bdcb5373a', '9c08f2a7050bdd3e0d6922ff9c8ce801436afcd078a79df6ffae267a2a755b0b', '', '12e7ff44f271d1f5968b23a258b21f703cacfe3061e0fafe9ea04b810537a606', '', '', '', '', '', '', '', ''], 143 | # Note that the 0xd-th element of this Merkle-Patricia branch node is empty, indicating that no transaction exists 144 | ['926c9592f6e3f3fdb9510de57fb60b0413fa0e8c9bc9b3ae25536487354a136c', '78df5aef8d73d86c9c875323a90584e70638b590bb9314ebb91a010a7f3b0874', 'e86be9fc7f24962a2a5872b4aac6fbe62149b11e787982b3b89f3f59ba6e68d9', '277156f773f0db978ce9a8248447188868ac05a13fb5d3fb595bf58ab715c58d', 'fbb50c6c762e920d12b36be8e6cf3f62fc15bed2b3826a9295dde31e0eaca92a', 'd252a56cb1f2ff5d8beb51cd7e38d8e9bbf113e6719628e8cab574fba68a33cd', '3d6db3090e80411df76c76aabed90a36ecbb7ca78d4dcbdbd45787ebac96adeb', '4ce247a831382c25b3cecf5824077af5d8340d2f531343da143a8f24b5623c91', '08b5b9bad14b02c79370f9b741b7051a195301773aac7ff7fbf626c95e9fa89c', 'cfeb46c773370ca40ccba0066d4685bb8ffa58a8b471748f22fc1f04c07f20fd', '3905a9d97fccfb9e5d2a0b9030dc32da7e461bd90eb66179368ac5ac5f913e80', '2c042434f04cfcca5f418778fe9fcb05e753a1437a1a636000d021a90c6e2643', '6ff3f067699fdcf7d7a76c61988dc152ba52984eb5230d15db058c7f04447cf9', '', '', '', ''] 145 | ] 146 | ] 147 | ``` 148 | 149 | #### Transaction 6000 of block 6027762 (mainnet) 150 | 151 | This is a proof of exclusion since no transaction with index 6000 exists in block 6027762. Proof-blob: 152 | ``` 153 | f903ec01f90216a00947e6d3e6884ef3b6d54251200719e10c71d93b822be696afea9a1a2d93ae0ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea674fdde714fd979de3edf0f56aa9716b898ec8a093f095892d0c46d3f7c73989f29e910979c396dee9d0fc885f3407861eb96bf9a0758cb2c904e1229497d8d610a23ee5a4bc0d4968811d366029eb65c9d73d75dca0164b57685b6c40430979391aab93eb4945c782145f78b44ad7dbd3ef4ee33bebb9010002000000000200000000000000008002000000000000000004100010100000000000000000000000008000000001000000020000004000000000804000000000100000000000000000000000002000200000000400000000000200002002000004000000000000001100014000000000000000000000000000000400000000000000020000080000000000200090004000000000000000400020100000000100000010000000000080200200000005000000000800000000000000000000000000000004000000000000008000800200008040000000080120000008024000000000001000000000000004000000008000000000400008000000000040000010870c76cdc3636820835bf9f28379f3798379c749845b587d739565746865726d696e652d6177732d61736961312d32a0199d055cf2a0283e8362d40c538970d1c25b843cf284c70d134b69cd46636c2e88c2ae5ff80e4b9873821770f901ccf90131a0ba8ac26a1ecca80036646825fe83c23819b2826d21db47a8c4345fec9247366fa017d86d5d4ada9c618a533c4f396a653b230fb00aee249e4b408218d44e6ce519a02d49848c73d037a07e77379965b6197b42c90c15978c0959cd5c6a72397bf666a02bc76e23c38782cc0072173b7f1e985f6256c84d721747489a6e2390aa222462a00222513b6138798cf398dd32d1d7127da0a8d9caad87218b1927b7228aff3519a01a795302578a2619aee9f1c30c2417a6ae992d3563133093683bf9037971a7fba09d9221fd4ef863d040d9f724ad84e3268141a1caba51254f078fa53c3122276da07dbbb758386cd6410ca616d0c01294d53e741a088c71f7a0254db2633ea565a7a01acb734cb4301016fd8bd7e19cecf0ef6fd30d7f001404e690c847c0872b3f9e8080808080808080f871a0fb98cd012e9c6cd332d6c2895e39dbd2dbc376005950963fff1209e691b1a856a094af3f83b301d9e07550ed4c9c327d0ae3780de51899eb9e7d3adb2f7dab026ba0c0658d28f3e6f71e6d59b14cde67919cff0ed7908b3af848bec2eaaeb76ae29a8080808080808080808080808080e4820001a0b8433f2f0b1efd01978a094160436af2f1228050103ed93b64ea952f68eae807 154 | ``` 155 | 156 | Decoded proof-blob: 157 | ``` 158 | [ 159 | # kind 160 | '01', 161 | # consensus block header 162 | # '758cb2c904e1229497d8d610a23ee5a4bc0d4968811d366029eb65c9d73d75dc' is the hash of the transaction Merkle-Patricia-Trie 163 | ['0947e6d3e6884ef3b6d54251200719e10c71d93b822be696afea9a1a2d93ae0c', '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', 'ea674fdde714fd979de3edf0f56aa9716b898ec8', '93f095892d0c46d3f7c73989f29e910979c396dee9d0fc885f3407861eb96bf9', '758cb2c904e1229497d8d610a23ee5a4bc0d4968811d366029eb65c9d73d75dc', '164b57685b6c40430979391aab93eb4945c782145f78b44ad7dbd3ef4ee33beb', '02000000000200000000000000008002000000000000000004100010100000000000000000000000008000000001000000020000004000000000804000000000100000000000000000000000002000200000000400000000000200002002000004000000000000001100014000000000000000000000000000000400000000000000020000080000000000200090004000000000000000400020100000000100000010000000000080200200000005000000000800000000000000000000000000000004000000000000008000800200008040000000080120000008024000000000001000000000000004000000008000000000400008000000000040000010', '0c76cdc3636820', '5bf9f2', '79f379', '79c749', '5b587d73', '65746865726d696e652d6177732d61736961312d32', '199d055cf2a0283e8362d40c538970d1c25b843cf284c70d134b69cd46636c2e', 'c2ae5ff80e4b9873'], 164 | # transaction index (0x1770 == 6000) 165 | '1770', 166 | # Nodes on path: 167 | # the 8th element of the zeroth node is '1acb734cb4301016fd8bd7e19cecf0ef6fd30d7f001404e690c847c0872b3f9e', which is the hash of the first node 168 | # the 2nd element of the first node is 'c0658d28f3e6f71e6d59b14cde67919cff0ed7908b3af848bec2eaaeb76ae29a', which is the hash of the second node 169 | # the second node is an extension node with path [0,1], proving that no transaction exists at 080201070700. 170 | # the special index 'ff' indicates that this extension node diverges from the desired path 080201070700. 171 | [ 172 | ['ba8ac26a1ecca80036646825fe83c23819b2826d21db47a8c4345fec9247366f', '17d86d5d4ada9c618a533c4f396a653b230fb00aee249e4b408218d44e6ce519', '2d49848c73d037a07e77379965b6197b42c90c15978c0959cd5c6a72397bf666', '2bc76e23c38782cc0072173b7f1e985f6256c84d721747489a6e2390aa222462', '0222513b6138798cf398dd32d1d7127da0a8d9caad87218b1927b7228aff3519', '1a795302578a2619aee9f1c30c2417a6ae992d3563133093683bf9037971a7fb', '9d9221fd4ef863d040d9f724ad84e3268141a1caba51254f078fa53c3122276d', '7dbbb758386cd6410ca616d0c01294d53e741a088c71f7a0254db2633ea565a7', '1acb734cb4301016fd8bd7e19cecf0ef6fd30d7f001404e690c847c0872b3f9e', '', '', '', '', '', '', '', ''], 173 | ['fb98cd012e9c6cd332d6c2895e39dbd2dbc376005950963fff1209e691b1a856', '94af3f83b301d9e07550ed4c9c327d0ae3780de51899eb9e7d3adb2f7dab026b', 'c0658d28f3e6f71e6d59b14cde67919cff0ed7908b3af848bec2eaaeb76ae29a', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 174 | ['0001', 'b8433f2f0b1efd01978a094160436af2f1228050103ed93b64ea952f68eae807'] 175 | ] 176 | ] 177 | ``` 178 | -------------------------------------------------------------------------------- /onchain/test/test_ProvethVerifier.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import copy 3 | import json 4 | import os 5 | import sys 6 | import unittest 7 | 8 | from ethereum import utils 9 | from ethereum import config 10 | from ethereum.tools import tester as t 11 | from ethereum.utils import mk_contract_address, checksum_encode 12 | import rlp 13 | import trie 14 | import trie.utils.nibbles 15 | 16 | from test_utils import rec_hex, rec_bin, deploy_solidity_contract 17 | 18 | sys.path.append(os.path.join(os.path.dirname(__file__), '../../offchain')) 19 | import proveth 20 | 21 | class TestVerifier(unittest.TestCase): 22 | def null_address(self): 23 | return '0x' + '0' * 40 24 | 25 | def assertEqualAddr(self, *args, **kwargs): 26 | return self.assertEqual(checksum_encode(args[0]), checksum_encode(args[1]), *args[2:], **kwargs) 27 | 28 | def setUp(self): 29 | config.config_metropolis['BLOCK_GAS_LIMIT'] = 2**60 30 | self.chain = t.Chain(env=config.Env(config=config.config_metropolis)) 31 | self.chain.mine() 32 | 33 | contract_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) 34 | self.verifier_contract = deploy_solidity_contract( 35 | self.chain, 36 | {'ProvethVerifier.sol': {'urls': [os.path.join(contract_dir, 'ProvethVerifier.sol')]}, 37 | 'Solidity-RLP/contracts/RLPReader.sol': {'urls': [os.path.join(contract_dir, 'Solidity-RLP/contracts/RLPReader.sol')]}, 38 | 'ProvethVerifierTestHelper.sol': {'urls': [os.path.join(contract_dir, 'ProvethVerifierTestHelper.sol')]}, 39 | }, 40 | contract_dir, 41 | 'ProvethVerifierTestHelper.sol', 42 | 'ProvethVerifierTestHelper', 43 | 10**7, 44 | ) 45 | 46 | self.rpc_cache = {} 47 | 48 | def test_decodeUnsignedTx(self): 49 | tx = collections.OrderedDict([ 50 | ('nonce', 3), 51 | ('gasprice', 0x06fc23ac00), 52 | ('startgas', 0x0494e5), 53 | ('to', rec_bin('0xb13f6f423781bd1934fc8599782f5e161ce7c816')), 54 | ('value', 0x2386f26fc10000), 55 | ('data', rec_bin('0xf435f5a7000000000000000000000000c198eccab3fe1f35e9160b48eb18af7934a13262')), 56 | ]) 57 | rlp_tx = rlp.encode(list(tx.values())) 58 | print(rec_hex(utils.sha3(rlp_tx))) 59 | (nonce, gasprice, startgas, to, value, data, is_contract_creation) = \ 60 | self.verifier_contract.exposedDecodeUnsignedTx( 61 | rlp_tx 62 | ) 63 | self.assertEqual(nonce, tx['nonce']) 64 | self.assertEqual(gasprice, tx['gasprice']) 65 | self.assertEqual(startgas, tx['startgas']) 66 | self.assertEqualAddr(to, tx['to']) 67 | self.assertEqual(value, tx['value']) 68 | self.assertEqual(data, tx['data']) 69 | self.assertFalse(is_contract_creation) 70 | 71 | def test_decodeSignedTx(self): 72 | tx = collections.OrderedDict([ 73 | ('nonce', 3), 74 | ('gasprice', 0x06fc23ac00), 75 | ('startgas', 0x0494e5), 76 | ('to', rec_bin('0xb13f6f423781bd1934fc8599782f5e161ce7c816')), 77 | ('value', 0x2386f26fc10000), 78 | ('data', rec_bin('0xf435f5a7000000000000000000000000c198eccab3fe1f35e9160b48eb18af7934a13262')), 79 | ('v', 28), 80 | ('r', 115792089237316195423570985008687907852837564279074904382605163141518161494337 - 1), 81 | ('s', 17), 82 | ]) 83 | rlp_tx = rlp.encode(list(tx.values())) 84 | print(rec_hex(utils.sha3(rlp_tx))) 85 | (nonce, gasprice, startgas, to, value, data, v, r, s, is_contract_creation) = \ 86 | self.verifier_contract.exposedDecodeSignedTx( 87 | rlp_tx 88 | ) 89 | self.assertEqual(nonce, tx['nonce']) 90 | self.assertEqual(gasprice, tx['gasprice']) 91 | self.assertEqual(startgas, tx['startgas']) 92 | self.assertEqualAddr(to, tx['to']) 93 | self.assertEqual(value, tx['value']) 94 | self.assertEqual(data, tx['data']) 95 | self.assertEqual(v, tx['v']) 96 | self.assertEqual(r, tx['r']) 97 | self.assertEqual(s, tx['s']) 98 | self.assertFalse(is_contract_creation) 99 | 100 | def test_sharedPrefixLength(self): 101 | self.assertEqual( 102 | self.verifier_contract.exposedSharedPrefixLength(0, b'', b'a'), 103 | 0) 104 | self.assertEqual( 105 | self.verifier_contract.exposedSharedPrefixLength(0, b'b', b'a'), 106 | 0) 107 | self.assertEqual( 108 | self.verifier_contract.exposedSharedPrefixLength(0, b'b', b''), 109 | 0) 110 | self.assertEqual( 111 | self.verifier_contract.exposedSharedPrefixLength(0, b'a', b'a'), 112 | 1) 113 | self.assertEqual( 114 | self.verifier_contract.exposedSharedPrefixLength(0, b'aaac', b'aaab'), 115 | 3) 116 | self.assertEqual( 117 | self.verifier_contract.exposedSharedPrefixLength(1, b'aaac', b'aaab'), 118 | 2) 119 | self.assertEqual( 120 | self.verifier_contract.exposedSharedPrefixLength(3, b'aaac', b'aaab'), 121 | 0) 122 | self.assertEqual( 123 | self.verifier_contract.exposedSharedPrefixLength(4, b'aaaa', b'aaaa'), 124 | 0) 125 | 126 | def test_merklePatriciaCompactDecode(self): 127 | self.assertEqual( 128 | [False, utils.decode_hex('')], 129 | self.verifier_contract.exposedMerklePatriciaCompactDecode(utils.decode_hex('00'))) 130 | self.assertEqual( 131 | [False, utils.decode_hex('00')], 132 | self.verifier_contract.exposedMerklePatriciaCompactDecode(utils.decode_hex('10'))) 133 | self.assertEqual( 134 | [False, utils.decode_hex('0102030405')], 135 | self.verifier_contract.exposedMerklePatriciaCompactDecode(utils.decode_hex('112345'))) 136 | self.assertEqual( 137 | [False, utils.decode_hex('000102030405')], 138 | self.verifier_contract.exposedMerklePatriciaCompactDecode(utils.decode_hex('00012345'))) 139 | self.assertEqual( 140 | [True, utils.decode_hex('000f010c0b08')], 141 | self.verifier_contract.exposedMerklePatriciaCompactDecode(utils.decode_hex('200f1cb8'))) 142 | self.assertEqual( 143 | [True, utils.decode_hex('0f010c0b08')], 144 | self.verifier_contract.exposedMerklePatriciaCompactDecode(utils.decode_hex('3f1cb8'))) 145 | 146 | def test_validateMPTProof(self): 147 | def assert_at_mpt_key(mpt, mpt_key, value): 148 | mpt_key = bytes(mpt_key) 149 | stack = proveth.generate_proof(mpt, mpt_key) 150 | self.assertEqual( 151 | self.verifier_contract.exposedValidateMPTProof( 152 | mpt.root_hash, 153 | bytes(mpt_key), 154 | rlp.encode(stack), 155 | ), 156 | value) 157 | 158 | mpt = trie.HexaryTrie(db={}) 159 | 160 | # empty trie 161 | assert_at_mpt_key(mpt, [], b'') 162 | assert_at_mpt_key(mpt, [1], b'') 163 | assert_at_mpt_key(mpt, [1, 2], b'') 164 | assert_at_mpt_key(mpt, [1, 2, 3], b'') 165 | assert_at_mpt_key(mpt, [1, 2, 3, 4], b'') 166 | 167 | # trie with one element 168 | key = bytes([127]) 169 | mpt_key = list(trie.utils.nibbles.bytes_to_nibbles(rlp.encode(key))) 170 | value = b'hello' 171 | mpt.set(key, value) 172 | 173 | self.assertEqual(mpt_key, [7, 15]) 174 | assert_at_mpt_key(mpt, mpt_key, b'hello') 175 | assert_at_mpt_key(mpt, [], b'') 176 | assert_at_mpt_key(mpt, [6], b'') 177 | assert_at_mpt_key(mpt, [7], b'') 178 | assert_at_mpt_key(mpt, [7, 14], b'') 179 | assert_at_mpt_key(mpt, [7, 15, 0], b'') 180 | 181 | # trie with two elements 182 | key = bytes([126]) 183 | mpt_key = list(trie.utils.nibbles.bytes_to_nibbles(rlp.encode(key))) 184 | value = b'bonjour' 185 | mpt.set(key, value) 186 | 187 | self.assertEqual(mpt_key, [7, 14]) 188 | assert_at_mpt_key(mpt, mpt_key, b'bonjour') 189 | assert_at_mpt_key(mpt, [7, 15], b'hello') 190 | assert_at_mpt_key(mpt, [], b'') 191 | assert_at_mpt_key(mpt, [6], b'') 192 | assert_at_mpt_key(mpt, [7], b'') 193 | assert_at_mpt_key(mpt, [7, 14, 0], b'') 194 | 195 | def test_manual1(self): 196 | # from block 1322230 on ropsten 197 | decoded_proof_blob = [ 198 | '01', 199 | [ 200 | '5b5782c32df715c083da95b805959d4718ec698915a4b0288e325aa346436be1', 201 | '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', 202 | 'fee3a49dc4243fa92019fc4331228043b3c5e825', 203 | '13a50145091c1b5bae07abe10da88c54c5111c3fbb74fc91074ad2ffec311f6b', 204 | '0c673fc4822ba97cc737cfa7a839d6f6f755deedb1506490911f710bfa9315bf', 205 | '0c1fcb2441331ab1abc2e174a7293acce160d0b04f35a4b791bf89e9fd452b10', 206 | '00000000000000200000000000000000000000000010002000000000000000000040000000000000000000000010000000000000000000000040000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000100', 207 | '0c0b580c', 208 | '142cf6', 209 | '47e7c4', 210 | '0428a1', 211 | '596e599f', 212 | 'd883010606846765746887676f312e382e338664617277696e', 213 | '6ebda3617b113ba6550d08cb34119f940ddb96b509c62b7d0a8420722329d5b4', 214 | '61ebb9e58c93ac26', 215 | ], 216 | '01', 217 | [ 218 | ['da42945ae3c75118e89abff39ad566fd0a30b574e5df8ae70ce59d4cc5f19cb1', '', '', '', '', '', '', '', 'ca85a0d0ed219e8583feadf2dce0a73aa05e7d6a790c32efcc1dd6c901195f16', '', '', '', '', '', '', '', ''], 219 | ['', 'e61bb422a77353192ae2b4b29c3773b018da71d1425b2a48cca04d7da9917fab', '6b46aad90e0a9eeede8f2ad992401e52b3e52ce7d5bf723a48922401d5af95cc', '997f63912b72cdf8a907025644e1df51c313015c4e9e51500fa6ffa52241eef4', '5ad4d0c46a043da4e1da601955a1d29d5bd3b6c5b2dfc2776c8a898f998af498', '457048648440cf69193e770035a2df6f42ab5a6b8bc4d789a92074dc2beb2091', '', '', '', '', '', '', '', '', '', '', ''], 220 | ['20', 'f88b820beb8506fc23ac00832dd5d8943d04303126cd6e75324825455685b028401e0ec280a4e733ca974e6964610000000000000000000000000000000000000000000000000000000029a0f5405ffd54b78fc27dc56c49364ec22ba94c471f4639f052cfe324e3fc05d1d3a041291d64a8cdf499c386fde5bc04a1ca743aa81f65dc59198d29f8d66ee588a5'], 221 | ], 222 | ] 223 | block_hash = utils.decode_hex('51c92d45e39db17e43f0f7333de44c592b504bb8ac24dc3c39135d46655bae4f') 224 | result, index, nonce, gas_price, gas, to, value, data, v, r, s, contract_creation = self.verifier_contract.txProof( 225 | block_hash, 226 | rlp.encode(rec_bin(decoded_proof_blob)), 227 | startgas=10**6) 228 | self.assertEqual(result, self.verifier_contract.TX_PROOF_RESULT_PRESENT()) 229 | self.assertEqual(index, 1) 230 | 231 | def assert_failed_call(modified_decoded_proof_blob, block_hash=block_hash): 232 | with self.assertRaises(t.TransactionFailed): 233 | _ = self.verifier_contract.txProof( 234 | block_hash, 235 | rlp.encode(rec_bin(modified_decoded_proof_blob)), 236 | startgas=10**6) 237 | 238 | assert_failed_call(decoded_proof_blob, block_hash=utils.decode_hex('51c92d45e39db17e43f0f7333de44c592b504bb8ac24dc3c39135d46655bae40')) 239 | 240 | modified_decoded_proof_blob = copy.deepcopy(decoded_proof_blob) 241 | modified_decoded_proof_blob[0] = 'ab' 242 | assert_failed_call(modified_decoded_proof_blob) 243 | 244 | modified_decoded_proof_blob = copy.deepcopy(decoded_proof_blob) 245 | modified_decoded_proof_blob[1][0] = '5b5782c32df715c083da95b805959d4718ec698915a4b0288e325aa346436be2' 246 | assert_failed_call(modified_decoded_proof_blob) 247 | 248 | modified_decoded_proof_blob = copy.deepcopy(decoded_proof_blob) 249 | modified_decoded_proof_blob[2] = '02' 250 | assert_failed_call(modified_decoded_proof_blob) 251 | 252 | modified_decoded_proof_blob = copy.deepcopy(decoded_proof_blob) 253 | modified_decoded_proof_blob[3][0][0] = 'da42945ae3c75118e89abff39ad566fd0a30b574e5df8ae70ce59d4cc5f19cb2' 254 | assert_failed_call(modified_decoded_proof_blob) 255 | 256 | modified_decoded_proof_blob = copy.deepcopy(decoded_proof_blob) 257 | modified_decoded_proof_blob[3][1][1] = 'e61bb422a77353192ae2b4b29c3773b018da71d1425b2a48cca04d7da9917fac' 258 | assert_failed_call(modified_decoded_proof_blob) 259 | 260 | modified_decoded_proof_blob = copy.deepcopy(decoded_proof_blob) 261 | modified_decoded_proof_blob[3][2][0] = '21' 262 | assert_failed_call(modified_decoded_proof_blob) 263 | 264 | modified_decoded_proof_blob = copy.deepcopy(decoded_proof_blob) 265 | modified_decoded_proof_blob[3][2][1] = modified_decoded_proof_blob[3][2][1].replace( 266 | 'e733ca974e69646100000000000000000000000000000000000000000000000000000000', 267 | 'f733ca974e69646100000000000000000000000000000000000000000000000000000000') 268 | assert_failed_call(modified_decoded_proof_blob) 269 | 270 | 271 | def test_manual2(self): 272 | proof_blob = utils.decode_hex('f904bb01f90203a0e7c29816452c474e261b1d02d3bab489df00069892863bc654ddd609b7f7fc4ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a00272d32e39cf493242e079965942776e1a6492e74532eb25d5ed8f56aab40331a01b0134ed566a1bf54f29bd55929b75139de4450d8bf43d33b02a1b26b4873af6a0b9b5d8d9f58ad6b835be1b1bde2461e809905257c2610329fe94de5109c2cfadb9010003424803034030147969000005008084532a1c8a0020000400000424302c0578310012204d0883204010ca0000401800020448800000909104008110e02b006000060142000000994112c20924a0200002820020002402000801001020004412203000281600200000c1802940080a1c0010a029080410408a0020150400681c32020104600800004400100900032840000285000800209440420209010500800606200010420003050010100064884080000c23a02080c130028054a401080040086402088c0252005c00000000e82000406005824800412011200c2020a0010810000901120010020c08c4a000828440040008a004608950810200c208008887090e046147907c834c4d6b837a11d38379ca58845a709667827331a0915aa3cd5dea74d24e39ffd6acc5da3b2b692d4b3fcc6cc26222b9205fd64b46880eb2c4f807cb14248182f902aff90131a08e61195faa58f0c8467b7f62a15ec6122d7f9484021eaf7b9fe372fffde310b8a05b9674e1d977f6a30fc12a9ac35aeecbbe0d49dcc0d8952e5d833539504ca649a05262513c779d4d62f559300126b4a34435923dceadd291ec3e1d4da6d284b8fca0672d7beb02403cbf570f2aa2956d3d6a8be5b928a425ee263e744db509958d06a0cb1005949f6f4f14beeaf39c9ee07fc2cf68fcb804aaecc4168828bb265f3f1ca0d89a971d2813936524ef4e38ee2dd300cf02764bec57845b8c0064118246ab97a014d80d349c773c690ef2711a7c4c916cec6a333594d378d2b6cebf2bff1c9ce2a0a932d14ab39608d22c0ba8a0e2fafa8a9359968f29b34827cff06e3cc5d0fdeea059d69a507142ffd21a40f829f094f283758e8a32b077c8373a6215cc0e0d61328080808080808080f851a0af2178a9930004f22ee1e2eb87f1035e559971de937dc9ae6f6ba7b6640df2a7a0d92a714520fe45d10652c6b429ca037104644bae3fe13edb8e52b2efb645e16a808080808080808080808080808080e218a01bf683031aaa6ef9c75509021a8ba5f4c9eb6f134413d57b2d3ae92699f58d95f891a06b621312dca8604610878ecf0384c9855dd6e388a0d587441be1dedfe2c73804a0530e3712b1763a989ef0b80b5a90619e7b0452069f1cf4ba3be0a7459a8654cca05f174cd7f8bd7be186b9f8127e181be52bb94cc662f36a8ec1fa3c6083db0ec7a0d94d6ab7f87669a948645e2191b193672be0720018f15115e71720140a027f3e80808080808080808080808080f87020b86df86b821935843b9aca00825208944ce3adf23418a3c3f4a61cde1c7057677befd9bf86719a2d5d6e008025a0121772bdbd0945dcfea42152186b9f7ae6d0271fdd6d1777fcadf5383a88336ca021196e93025480173f429c9e9a27c1921dd6c10b3705c30125424285250bd5a5') 273 | block_hash = utils.decode_hex('23d2df699671ac564b382f5b046e0cf533ebc44ab8e36426cef9d60486c3a220') 274 | result, index, nonce, gas_price, gas, to, value, data, v, r, s, contract_creation = self.verifier_contract.txProof( 275 | block_hash, 276 | proof_blob, 277 | startgas=10**6) 278 | self.assertEqual(result, self.verifier_contract.TX_PROOF_RESULT_PRESENT()) 279 | self.assertEqual(index, 130) 280 | 281 | 282 | def help_test_entire_block(self, path_to_jsonrpc_response): 283 | PRESENT = self.verifier_contract.TX_PROOF_RESULT_PRESENT() 284 | ABSENT = self.verifier_contract.TX_PROOF_RESULT_ABSENT() 285 | with open(path_to_jsonrpc_response, 'r') as f: 286 | jsonrpc = json.load(f) 287 | block_dict = jsonrpc['result'] 288 | for i in range(len(block_dict['transactions']) + 20): 289 | proof_blob = proveth.generate_proof_blob_from_jsonrpc_response(jsonrpc, i) 290 | result, index, nonce, gas_price, gas, to, value, data, v, r, s, contract_creation = self.verifier_contract.txProof( 291 | utils.decode_hex(block_dict['hash']), 292 | proof_blob, 293 | startgas=10**7) 294 | print(i) 295 | present = i < len(block_dict['transactions']) 296 | self.assertEqual(result, PRESENT if present else ABSENT) 297 | self.assertEqual(index, i) 298 | if present: 299 | self.assertEqual(nonce, utils.parse_as_int(block_dict['transactions'][i]['nonce'])) 300 | self.assertEqual(gas_price, utils.parse_as_int(block_dict['transactions'][i]['gasPrice'])) 301 | self.assertEqual(gas, utils.parse_as_int(block_dict['transactions'][i]['gas'])) 302 | # contract creation corner case 303 | if utils.normalize_address(block_dict['transactions'][i]['to'] or '', allow_blank=True) == b'': 304 | self.assertEqual(utils.normalize_address(to), utils.normalize_address("0x0000000000000000000000000000000000000000")) 305 | self.assertEqual(utils.parse_as_int(contract_creation), 1) 306 | else: 307 | self.assertEqual(utils.normalize_address(to), utils.normalize_address(block_dict['transactions'][i]['to'])) 308 | self.assertEqual(utils.parse_as_int(contract_creation), 0) 309 | self.assertEqual(value, utils.parse_as_int(block_dict['transactions'][i]['value'])) 310 | self.assertEqual(data, utils.decode_hex(block_dict['transactions'][i]['input'])) 311 | self.assertEqual(v, utils.parse_as_int(block_dict['transactions'][i]['v'])) 312 | self.assertEqual(r, utils.parse_as_int(block_dict['transactions'][i]['r'])) 313 | self.assertEqual(s, utils.parse_as_int(block_dict['transactions'][i]['s'])) 314 | if i > 0 and i % 100 == 0: 315 | self.chain.mine() 316 | 317 | 318 | def test_mainnet_blocks(self): 319 | blocks = [ 320 | '0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659.json', 321 | '0x23d2df699671ac564b382f5b046e0cf533ebc44ab8e36426cef9d60486c3a220.json', 322 | '0x2471ea6da13bb9926a988580fae95056ef1610291d3628aca0ef7f91456c9ef4.json', 323 | '0x829bb7e1211b1f6f85b9944c2ba1a1614a7d7dedebe9e6bd530ca93dae126a16.json', 324 | ] 325 | for block in blocks: 326 | with self.subTest(block=block): 327 | print(block) 328 | self.help_test_entire_block(os.path.join('resources', block)) 329 | 330 | 331 | def test_single_short_transaction(self): 332 | self.help_test_entire_block('resources/block_with_single_short_transaction.json') 333 | 334 | def test_big_block_with_short_transaction(self): 335 | self.help_test_entire_block('resources/big_block_with_short_transaction.json') 336 | 337 | def test_txValidate(self): 338 | block_hash = '0x51c92d45e39db17e43f0f7333de44c592b504bb8ac24dc3c39135d46655bae4f' 339 | print("Testing Tx validation for tx 0 in (ropsten) block {}" 340 | .format(block_hash)) 341 | 342 | block_header = [ 343 | "0x5b5782c32df715c083da95b805959d4718ec698915a4b0288e325aa346436be1", 344 | "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 345 | "0xfee3a49dc4243fa92019fc4331228043b3c5e825", 346 | "0x13a50145091c1b5bae07abe10da88c54c5111c3fbb74fc91074ad2ffec311f6b", 347 | "0x0c673fc4822ba97cc737cfa7a839d6f6f755deedb1506490911f710bfa9315bf", 348 | "0x0c1fcb2441331ab1abc2e174a7293acce160d0b04f35a4b791bf89e9fd452b10", 349 | "0x00000000000000200000000000000000000000000010002000000000000000000040000000000000000000000010000000000000000000000040000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000100", 350 | 202070028, 351 | 1322230, 352 | 4712388, 353 | 272545, 354 | 1500404127, 355 | "0xd883010606846765746887676f312e382e338664617277696e", 356 | "0x6ebda3617b113ba6550d08cb34119f940ddb96b509c62b7d0a8420722329d5b4", 357 | "0x61ebb9e58c93ac26", 358 | ] 359 | 360 | self.assertEqual(utils.sha3(rlp.encode(rec_bin(block_header))), rec_bin(block_hash)) 361 | 362 | 363 | tx = collections.OrderedDict([ 364 | ('nonce', 3), 365 | ('gasprice', 0x06fc23ac00), 366 | ('startgas', 0x0494e5), 367 | ('to', rec_bin('0xb13f6f423781bd1934fc8599782f5e161ce7c816')), 368 | ('value', 0x2386f26fc10000), 369 | ('data', rec_bin('0xf435f5a7000000000000000000000000c198eccab3fe1f35e9160b48eb18af7934a13262')), 370 | ('v', 0x29), 371 | ('r', 0x4602fcb7ef369fbe1e6d7d1658934a18bcc3b373454fc33dedb53cd9dd0226d2), 372 | ('s', 0x3a94a58becc2493007a6411b73a2b5c5a58b17b7a79bbb103568cc62b8945961), 373 | ]) 374 | 375 | proof_type = 1 376 | tx_index = 0 377 | stack = [ 378 | ['da42945ae3c75118e89abff39ad566fd0a30b574e5df8ae70ce59d4cc5f19cb1', '', '', '', '', '', '', '', 'ca85a0d0ed219e8583feadf2dce0a73aa05e7d6a790c32efcc1dd6c901195f16', '', '', '', '', '', '', '', ''], 379 | ['30', rec_hex(rlp.encode(list(tx.values())))], 380 | ] 381 | 382 | proof_blob = rlp.encode(rec_bin([ 383 | proof_type, 384 | block_header, 385 | tx_index, 386 | stack, 387 | ])) 388 | 389 | (result, index, nonce, gasprice, startgas, to, value, data, v, r, s, contract_creation) = \ 390 | self.verifier_contract.txProof( 391 | rec_bin(block_hash), 392 | proof_blob, 393 | startgas=10**6, 394 | ) 395 | self.assertEqual(result, self.verifier_contract.TX_PROOF_RESULT_PRESENT()) 396 | self.assertEqual(index, 0) 397 | self.assertEqual(nonce, tx['nonce']) 398 | self.assertEqual(gasprice, tx['gasprice']) 399 | self.assertEqual(startgas, tx['startgas']) 400 | self.assertEqualAddr(to, tx['to']) 401 | self.assertEqual(value, tx['value']) 402 | self.assertEqual(data, tx['data']) 403 | self.assertEqual(v, tx['v']) 404 | self.assertEqual(r, tx['r']) 405 | self.assertEqual(s, tx['s']) 406 | self.assertEqual(contract_creation, False) 407 | 408 | if __name__ == '__main__': 409 | unittest.main() 410 | 411 | -------------------------------------------------------------------------------- /resources/0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": 1, 4 | "result": { 5 | "difficulty": "0xc5c76b20797b3", 6 | "extraData": "0x65746865726d696e652d657532", 7 | "gasLimit": "0x7a121d", 8 | "gasUsed": "0x79effd", 9 | "hash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 10 | "logsBloom": "0x646b8fa1bc10820c0b2a9a054c12334e04ae8408400c14c887a4219000299c44f23f44536581003322014d0c04516210e968048c033ce14a0317150f7a400c297319f1cc1401801f841aa18c018001a0e31a20c02822000a004ac32860219155082050408620800666117f4097117cca005b20c308a708494a042fda50a0a2e0d13500a3ad074a0022b042459080104552084841c53fc01400212944013201a04c4685244b400816867f0b6308d0096e02cb51582b34890f10d800b4051c0662541dc0a38084f080c808183431217004180260abb8ed328328222040f25828387085114a5a8809a081110c84045f00b4005608cc09cb8a30101040e4b35150dd", 11 | "miner": "0xea674fdde714fd979de3edf0f56aa9716b898ec8", 12 | "mixHash": "0x4095b5d28065546f4704cea6234e4fc1754d9580b589c83a96576ebcacf43f2c", 13 | "nonce": "0xedbd2a80051618b3", 14 | "number": "0x5bf98b", 15 | "parentHash": "0x99b7c4d9281b110a851d9cd5333e16fb22c9e63b1ac59b72b757054ab9c70b9b", 16 | "receiptsRoot": "0x9dcd179c417ed8e9d88586cb78ab88b25024942923ccd8692c16ffe3d16dde7e", 17 | "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 18 | "size": "0x4f47", 19 | "stateRoot": "0x97594eb4c26b705981af1bf2ed30b66a3f05988329fa2b269821940e89b463f6", 20 | "timestamp": "0x5b5877cb", 21 | "totalDifficulty": "0x12e6461e354f474166c", 22 | "transactions": [ 23 | { 24 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 25 | "blockNumber": "0x5bf98b", 26 | "from": "0xac164bbb6bf6ab7c0524e0a49ff2ddab9c6e86c0", 27 | "gas": "0x249f0", 28 | "gasPrice": "0x174876e800", 29 | "hash": "0x62c1aa79282ece6cc0d3c64f32616dd9d4a0a56f53d0a09e0f327d22bfa4d69a", 30 | "input": "0x0f2c9329000000000000000000000000fbb1b73c4f0bda4f67dca266ce6ef42f520fbb98000000000000000000000000e592b0d8baa2cb677034389b76a71b0d1823e0d1", 31 | "nonce": "0x1c0", 32 | "to": "0xe94b04a0fed112f3664e45adb2b8915693dd5ff3", 33 | "transactionIndex": "0x0", 34 | "value": "0x22f3edccaf46c00", 35 | "v": "0x26", 36 | "r": "0xa4d514aab04f918c182cefe3573518aee2f3aefbb244a29e2ca1ec68a824abe2", 37 | "s": "0x1e8a9bc9c549ffb34a3b590409d3cd4391584ca584fc0d4549e6664653923491" 38 | }, 39 | { 40 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 41 | "blockNumber": "0x5bf98b", 42 | "from": "0xb0e3fcf63740a036aa58b5285b25bc33a7f94bde", 43 | "gas": "0x9002", 44 | "gasPrice": "0x98bca5a00", 45 | "hash": "0xde83b34f13c9d60223279d7482299dd7a113089389015fc3eaa2f1f17acc02bf", 46 | "input": "0xa9059cbb000000000000000000000000182351e018138dfe1594e84a88349d398de02b36000000000000000000000000000000000000000000000000000000000005922c", 47 | "nonce": "0x0", 48 | "to": "0xf900501cf5a848654bb5bc07f6af23382d637a02", 49 | "transactionIndex": "0x1", 50 | "value": "0x0", 51 | "v": "0x25", 52 | "r": "0x1ac55890edf96d0286c9c435844c8e6e03bbe506a1b44c6724dba88b494d6c21", 53 | "s": "0x74046857082511f9a0037b3e45efe8f83e49b96dadce5308fc12e046542e3f0a" 54 | }, 55 | { 56 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 57 | "blockNumber": "0x5bf98b", 58 | "from": "0xe7ebbec0a89efd478dd72dc769be475a9f1ce50a", 59 | "gas": "0x493e0", 60 | "gasPrice": "0x4e3b29200", 61 | "hash": "0xda5cbef23e5f1d87882fe2c3b983af70874cad83ee6e85088ddb5b37583db59c", 62 | "input": "0xee5301d50000000000000000000000009c50287cc6c1e2af4670305e86fdb915b8d605d9694322419ce93263e1663d72495485ce1f2dbd9629aeb9ad471b5ced5564c6f2f18c712450fb684fe1fb4e5615bbc478c31a3c3ce10b4d6d965d5eeb3d5d5e2000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000010d1083ea401e907cc1f2d9e483839a805552ef631a89568ded77d793ff6c0249000000000000000000000000000000000000000000000000000000000000001f636f6465783a3a35623538373763336432663464393635666336306265323800", 63 | "nonce": "0x42", 64 | "to": "0x8853b05833029e3cf8d3cbb592f9784fa43d2a79", 65 | "transactionIndex": "0x2", 66 | "value": "0x0", 67 | "v": "0x1c", 68 | "r": "0xed9ccc2b800e5721c9d9a92c47aa1bbcd51508ad98182269c7ef86a35de3f533", 69 | "s": "0x726a9f4fdfa492c0687ddbaab9124eb9f66e465665d3b19c0f36115c8628dee1" 70 | }, 71 | { 72 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 73 | "blockNumber": "0x5bf98b", 74 | "from": "0x1911f4954d2e48e6cdfff3fe45c3df05013b0d38", 75 | "gas": "0x5208", 76 | "gasPrice": "0x1a13b8600", 77 | "hash": "0x867e7b18e7749ec8386a74c7fa25cc89d121b50b152936c25e75f3236a7dd2b4", 78 | "input": "0x", 79 | "nonce": "0x0", 80 | "to": "0xc1d221438f5c49396082407647c08346c8c03781", 81 | "transactionIndex": "0x3", 82 | "value": "0x61aabf91a63d000", 83 | "v": "0x25", 84 | "r": "0xb30c6860a838cc2384bcb0b82f8ff5fdbbc3042d6cce8d6fe26c282957e4e8a7", 85 | "s": "0x72196ff6cfab09b1fb85f9e9607b9166014dee253f9aa6cbe889060672893d39" 86 | }, 87 | { 88 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 89 | "blockNumber": "0x5bf98b", 90 | "from": "0x459262e178acb30d0109edc46023169a85fdc364", 91 | "gas": "0x5208", 92 | "gasPrice": "0x165a0bc00", 93 | "hash": "0x4d1d0bc4481102d214dabf1fc7e59567ebd482d0e1dce4c33d7d4f73bc9a7fef", 94 | "input": "0x", 95 | "nonce": "0x2", 96 | "to": "0x764094eef2ce0d61ae27078774570dffafad196f", 97 | "transactionIndex": "0x4", 98 | "value": "0x680e8ddaaf3000", 99 | "v": "0x1c", 100 | "r": "0x2ffcf2d1f36a3c6893eea98fc3f0a3f573bc27ab36eec320a930f25714f36ae8", 101 | "s": "0x79ae4ba916b5b72e98104af41a21c6d18a4850a11d6cd07a78721bab47000073" 102 | }, 103 | { 104 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 105 | "blockNumber": "0x5bf98b", 106 | "from": "0x82415e00df6fe1f763827e512002f3c0e118da15", 107 | "gas": "0x5208", 108 | "gasPrice": "0x165a0bc00", 109 | "hash": "0x14b56b70116fa9e1fe514677c4480ad10609f20a8dbf8f8417de00ef2005b96d", 110 | "input": "0x", 111 | "nonce": "0x0", 112 | "to": "0x261c55f48449ed461dfc5288607b925db80c0f15", 113 | "transactionIndex": "0x5", 114 | "value": "0xe91f435c9325800", 115 | "v": "0x1b", 116 | "r": "0xf88adf7d76415eb1a00328ae0afe438d0514dfdbc27393b80366923e4cae0a87", 117 | "s": "0x777fcd2a51b048b8c796cedcb5ee9169580a66f58e9e51a1d4e18efd0a562ea6" 118 | }, 119 | { 120 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 121 | "blockNumber": "0x5bf98b", 122 | "from": "0xbc75d0ba790157e8c0b819648640cf10f708bc3f", 123 | "gas": "0x15f90", 124 | "gasPrice": "0x12a05f200", 125 | "hash": "0xe530537142ff08fce31367587f232dd3b81505eef1bfa35a5a12a56e45164303", 126 | "input": "0xa9059cbb000000000000000000000000e93381fb4c4f14bda253907b18fad305d799241a0000000000000000000000000000000000000000000000000000000da7feca90", 127 | "nonce": "0x0", 128 | "to": "0xcb97e65f07da24d46bcdd078ebebd7c6e6e3d750", 129 | "transactionIndex": "0x6", 130 | "value": "0x0", 131 | "v": "0x25", 132 | "r": "0x7d725ec0823c623f1279c3d62a493bbc8d48c89355335982fcd7feaf04deff6d", 133 | "s": "0x3cff3a78e9865116daca566a88aeef356c3c6b91e07517e60158299bdf6b1aba" 134 | }, 135 | { 136 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 137 | "blockNumber": "0x5bf98b", 138 | "from": "0xfa046be86536d0b23a609d8b9476f2022d6bae86", 139 | "gas": "0xa410", 140 | "gasPrice": "0xb2d05e00", 141 | "hash": "0x16f07e3c16d8b32e9ebe873b67c1ba0f09947d3b7524199aeb3cd948620d8d96", 142 | "input": "0x0000000000000000000000000000000000000000", 143 | "nonce": "0x52", 144 | "to": "0xc179fbddc946694d11185d4e15dbba5fd0adac0a", 145 | "transactionIndex": "0x7", 146 | "value": "0xb60af1f0854000", 147 | "v": "0x25", 148 | "r": "0x25bd75c01a4a42b765fec2a944876c0f79115acf5ef1df03ba79d26690d9bbf2", 149 | "s": "0x6a69880a4235c6e96112edad92f2662ad31c4a3cdf30a6ef1f53d8871b1c8487" 150 | }, 151 | { 152 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 153 | "blockNumber": "0x5bf98b", 154 | "from": "0xa7a0a362b4a826df2a37f24eb56c555486d18720", 155 | "gas": "0x65a421", 156 | "gasPrice": "0xb2d05e00", 157 | "hash": "0xb1f69e9bd7c075402ef6a9a8f5a2d3c3a36ed6b32c43b9d9a5753fa7b2d71d67", 158 | "input": "0xbb0a64b60000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000198000000000000000000000000078fceca5bf5ec79c23effece97ae758665ba4f5500000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000e8507ad13cd24e392c0172d65881de362d5d3b63000000000000000000000000cc9eaa50af7a0978ff5528d267fdb7be872ea1980000000000000000000000001dc48fc52ea4b54766f37ffcd5025719c51191a6000000000000000000000000f30c05d3d3da64b01d8ffe5446750dfc9ded8f72000000000000000000000000794f38f04becf1029f3271dfbf77925a3fa2455f000000000000000000000000b52ba587b8b27ac3f9b842dd2075aec1a150e1a7000000000000000000000000001ad837734bc021ec507ec758917cedb1573ebe0000000000000000000000002445cb594d9ca861cf5820de22d7019569b8431f000000000000000000000000995ea4f2f90127ed826373f72e3c41725ddd12ee000000000000000000000000b552fb131d06be02ba426d69cffa7b843d77013d0000000000000000000000001364824f0eeea1491041fa652a6adef4563e06d20000000000000000000000009b09bf6f124cb30bd07741e4116b9c3f00a39ed0000000000000000000000000187532bf7ae7dcefd660114e3474d3a2399fda3000000000000000000000000043ba726f5b7c4dfdefd21fdd62ff62a5d0344b4200000000000000000000000004f8695f466c533f4c922737f9d582a2e25369b900000000000000000000000077eccf6bac06f2863e37004935d846b806abb7da000000000000000000000000aa9cf7a106057362111344908914f90f5bcecc3300000000000000000000000058b4a3a6e4efae60b2f93519539e68582caee9f9000000000000000000000000583738ce1e6306978df5fc3e89abdc131079b319000000000000000000000000298ffdfa758bea1f3d13d5d676f36361a0560919000000000000000000000000e2f5f596c05d552e930355e6d8356ceddf85e1140000000000000000000000009c1eadf2cee216f26a2e885653de1106072da8e10000000000000000000000009cdc1f82d6f2b35be0d7380947ebdc5c3a6f2007000000000000000000000000153babb8746e655b692b2110183ae969a793c90000000000000000000000000092dd84466472f88b5ff31d8ab8ef01646f617c8d0000000000000000000000008317c57e4b531cf28d999cfedaf357c7763a600800000000000000000000000047ea7b43468fac581916f9a60b12d5ab85f361bb00000000000000000000000033d6c88214587c420ae5032445b1e29ad950d3ce000000000000000000000000913714e1add93aa1a2bfebd439bbcc360686e0eb000000000000000000000000543df48ec0314653652ffd23355d388d455ab3950000000000000000000000004a00ecd2ccb4016d7ce085cb85f5daf21858c58900000000000000000000000096a4c7e47c10990b361551e39546b2887b9707b800000000000000000000000019470d749ec0ef2a7828c051cc132b24c1f83fb500000000000000000000000014e04ac890bd74a809ff6821ee7888a35ec15b7c000000000000000000000000d08c80cc719a5e65a3885272e503127fd2a0557d000000000000000000000000bbc13546dd5a488a4700ad7ede36d1735a636ac600000000000000000000000029a82884c0c985f9ab49d721f90c6925ba31db7b0000000000000000000000002630b16acede5057a10bc3c74689c5aa35cfdd430000000000000000000000000c6a2cb0e343f42952a5cb1a639209f121851e79000000000000000000000000672fabc8563b9716af318de74bc5da19920b9a9d00000000000000000000000067f993e0d9a791c9602b4b604e44f6655c9df87f00000000000000000000000028596b0307595c30f091c6b9ae30f946fb0466920000000000000000000000004a8c5e445746110098d70c0fef2104a0954e30cb000000000000000000000000745dcc19cae0d47b0d9b7093a33b56e12d375e5d00000000000000000000000050346864fb969c4332f1662b40df2fa1ab2328ff000000000000000000000000790c90fe18065c1b5b4f25c94a2654297f36c808000000000000000000000000d9ab4908aa3d43e0686719ada7be18f2effb6c97000000000000000000000000a490aeddd5626acd2990cda15273c0a66c4a7d3100000000000000000000000086d72162508a09ca0dd4b409cf21da2ca8afc83a000000000000000000000000722f211660937dba6dcd563fae91e75930cdafba0000000000000000000000009f6b16197c16dd4c39164bc10ef0847d1a7ee7b1000000000000000000000000eb3af238212da418498ad038fb3a4856d7f38ec10000000000000000000000005ee360ca0a595a09562a9cdb33f6f95988b6c700000000000000000000000000c0c533e93ae2dbd8a58e105acf9ae0a96cdb32690000000000000000000000009217b9b08f880b755e1e4e25dbedf804fd0c63fe0000000000000000000000008ee653c3f09dc00d7e00e1544c44c59d4b74b80d000000000000000000000000396f2b4a1d8e496959297c00cd988bc0c3efa3bb000000000000000000000000b883f0727f22634e85710fbe36665e59bd7ca117000000000000000000000000e3d9969e9084a8f3a213fcce5d3ca6771b0468e2000000000000000000000000580fcba59c1f5b3bbdb5c8f33ccf44a3199986670000000000000000000000006d6eb2e0d2cac822ebcadde5873cb0dc0e43d5340000000000000000000000001e7031385d2b8741ff5c1c4013f9bbc0df6369fa000000000000000000000000c5e86714b0eac702de11f58fd2ebad29828aeb0c0000000000000000000000006614e5974beda737a251d7aea6e024a26ba7389a000000000000000000000000c9c88e1638f2b5c31152e6ff3a28b89d68a95dba00000000000000000000000060a54f1f68d14b11749c864e19e09b6bc224949a000000000000000000000000f43a0e1ab1cc0e9974192b8f4e3bce39f2b521e4000000000000000000000000e2d135b03b5e2a6470d5b660e6bfd03721d8898300000000000000000000000061abd89468b511dcbe25943d6f076e814f543f3a00000000000000000000000065611ae014abd9ddeb7b0f0a4daaa1d2d52e2c170000000000000000000000000bf402e23cc15c28efe714b207808fd0466d8936000000000000000000000000ae6234e9ae6b4528a98bd29a1acf6231a738d554000000000000000000000000a1614945f0ad568cb8dedfd5afc7b45c2e235065000000000000000000000000c7b682145a95d811e5fb9c5d72252e76b3fbfaac000000000000000000000000cfc9c826ac5f8e9905799383b14dfae289b5b0d0000000000000000000000000c219f945facb75ef2ebdfb8d0671e9726c3a42db00000000000000000000000077bcfd4c55c04cdcd22d6eb381bb09e52114b7ed00000000000000000000000063a78d9c98375516451733bea563f19e09d1c5b20000000000000000000000001ef50d743a7fe05250f858f0e442a8c2604e9ce5000000000000000000000000bb007ecd77157be6c2cd0be4a0e21bb95a4f26180000000000000000000000008cebf73d237c925a279f3920d69d00bb2ec87b8c000000000000000000000000373fe4c17da2b46958e8cb460660249538a7943700000000000000000000000060b454b5ec1421b27e77276dd629021ba6230f55000000000000000000000000ea1a2c0b2860afa97c8fe1c0a01e41a08ed437f3000000000000000000000000d1b9fc3495bb77b32a92e32888d4fe2b4069bf3f0000000000000000000000006e8f092ad0e5de6fa7a4abbd0aeae051d1e0c55600000000000000000000000034b13783987e00791602dc9c51c80019da08ecc6000000000000000000000000af698a002f6c2f8de9844c49439a0b81e672c2a100000000000000000000000031a3c23933aa2c8d71597d97fe616b3b6cabde0000000000000000000000000009e9c479da23bbb7c438b316c93df5e805575fb0000000000000000000000000005440a267f8937356b2098daa3a4b2d13589b0000000000000000000000000008c0933300c476db766e828f7ad5c21a2fe423f80000000000000000000000009a29786d574df13917ce7229f29bba712422f6c3000000000000000000000000acbc851897741dfdb4b6eb1d97af569dcfad42b3000000000000000000000000500bd655b595759346f46e2eea21e02ed4471cc00000000000000000000000006177882dbbd558044446893b82f034c86511731a000000000000000000000000619ad0068b4181cf0a66e52bb3cfe336da705c1e000000000000000000000000fdfccd2d9e00137eb88c8027e141136883e7d0190000000000000000000000006c93bec4e6c8a1833e0f491abe5bc5cbaec71462000000000000000000000000273016b0b0ac4ad547ceee32faa2d4a12df318fe000000000000000000000000c2bd0a23e822175572d531f353d74ae54f4c047000000000000000000000000093119a616b2e86685c045a530b83a796478a330b0000000000000000000000000c539f0f85af9d80a2876b1a045a25b29da1e6ee00000000000000000000000057590e83dbe930b1b252bb5f50a4ea4c2867ba600000000000000000000000004abbf9d10f830c090febc979228718fe782050af00000000000000000000000074be51b227bfceea491af762703e058a80198f9b000000000000000000000000e520ed98c62800748c4af6435772a2e13af7a3d100000000000000000000000033fb61872bf33c5d7cca8a172c2de47880b79687000000000000000000000000b29e15757f7f6525bad0547e04d8fb1b81c0616e0000000000000000000000004c800bdbddfa9297e107aa6a4ede36fcfe12feca000000000000000000000000765f43491c9e49ba76877facaacd56c75c2be1cb0000000000000000000000006d8fbf78fdb7ed69a2e816f97633f5b8ba972899000000000000000000000000b2c4b974f359b3317e3b8107e70d60afb3cb880400000000000000000000000010c83adc05e89148e86503ca7cce3c27f597268500000000000000000000000073299780f9a10da57e4da13783901c967fb68bab000000000000000000000000b669705d21e68bc2a7863c2f6376bd67cf8ce787000000000000000000000000165376928d166454d11fdce9625c52055313a2f6000000000000000000000000171392bd603c77d49236a43ee6ce21a80cca3e0b0000000000000000000000007f4bbc79a316bd0fac94a48d5b5ef285a3889757000000000000000000000000297ffd8280a92123aede8e34ea362017b1a4f22300000000000000000000000024f1b1f02d22f5eb42231c379d8008dbedac7e5b000000000000000000000000b6cc72b5601ced07c54ae3689e132fcece84cb940000000000000000000000009b1ac4bacf1d26c21eb318f0e8d3ef6323f9f7f10000000000000000000000008a8e73389caaee99dcddca269c5d080d5f634ab9000000000000000000000000f76b37fc738de9ab0eb485e13c7ae0ce3d988cdb000000000000000000000000dce1b5f62eb0425cc28b83cef3a19ba603728270000000000000000000000000b2d6d0c12b440a2cf4b2b5f0fe6c4c44e5de58730000000000000000000000009acca15f0a4fade8d9d87ad504994c8aba927bc10000000000000000000000002a1f338f2818a528d09519f433159df93c6ea5b4000000000000000000000000ce3650b01fdeb8c0c7a5285545a78b78a0caca7200000000000000000000000041abd0191bf59d8ec666d9d0b479eb2857c25dc3000000000000000000000000eca9ee13fc076625209ea1c5debd7c017df77afe00000000000000000000000064f6ac44cafed2cb3f3c3d5a1ac40618fc4a9d87000000000000000000000000ef1f8547800ea62b50b4917e49b0b9e50272e53c0000000000000000000000007392ea46698590add6c0700a341eed204b7e012500000000000000000000000039547ef820d521fa2cedb6bcbf427fbee29a613e000000000000000000000000c5769de44b79e6e02e76bc5601e64b02f5eb0aca0000000000000000000000008c0bea5c758c8f000abb9c34d6b022141ee684bc0000000000000000000000007522f1f3a770e829d3a227b6c1f69b21c30bd860000000000000000000000000b4a9c1b76186ccea1cab4107d4574c13da62fab500000000000000000000000022057a6738f9f33c8d3f3f8ba5300729f4ba10ea00000000000000000000000094352009a2b52c9179288a435521c28d502fefb6000000000000000000000000e5ba9bcc4731b427837006ab5e495eb835ad725b000000000000000000000000a86c079e1d7f30ec40cfed5b1804ee1b0af28dd6000000000000000000000000ed3319d18013c704b8c71651ef34f313bdc61ed30000000000000000000000006878b312a886cecac9db1ece5b6478e2ad1fcc13000000000000000000000000cf665eccfeb8dedcb6a4f59761162737ca1cd6e500000000000000000000000036695e185791405ddf27b32e87dfe5dd5e4cca4600000000000000000000000031054bb46d9810c63310efd32ec1bf31e6c868520000000000000000000000002969b0e1f150ff210d7e7e3761396b6249b8cd2800000000000000000000000083ffaacbdca08a521dbc92e42fd83d0e47e93b0b0000000000000000000000005812e6cbdb7ede36439a736ac381e60bcbc40abd000000000000000000000000eb3721a657b25208e45690feed41dedbd18b4880000000000000000000000000246277e3dcc9cfe40c247dfc9cddcacc2d9d2e2f0000000000000000000000006f05ef0852181b912b36b2d2893acf5e69f886070000000000000000000000006ddb074b0b2b2fbb5417e49ab4f52d268a21a3af000000000000000000000000312ef2b16666e53ae7a3b161dc6a992bf7407799000000000000000000000000ed90c549ec49539f3c7cba26ccf256d54e40bb66000000000000000000000000accfd4933590a6c66c4ae2741ed00591f69dd75a0000000000000000000000005c2da9b2dcccb1c185b0bf4133c20c2fde468159000000000000000000000000330438b974cb7e76a58f2385ac692f36c677863f000000000000000000000000e5b7f9f7f2f57ef4523050059a3bbe343cea51a4000000000000000000000000ef90eb9fbd1587a9cf8233396a96336edad7fc4d000000000000000000000000494f19cef47981065c35fe6747cfb93f4106fa980000000000000000000000007786f1c3f4ad9211f72e83486a0005489816420700000000000000000000000052a39e59da16bd5e42887a4fbdde3aefd038b8be0000000000000000000000000905545341220d07eb6d6e48cdd10e6ea1cc81b9000000000000000000000000cbe4c1d896eb046a0ea00bc1678f2cbb578d87a800000000000000000000000073a0afc565454f4618d07732a79471d60486338a000000000000000000000000d1d6dd9a03fa62bf5e626bc64b1f6c40d94667230000000000000000000000007d57ba6db02a4c25e55862b48454cca340fdaab2000000000000000000000000879497bdd0078063c22372b4c784d5f51ba228a800000000000000000000000087557ec35b54337c999b4102ddfd549f83ef39620000000000000000000000008c3b5fb9f028deb4053c7ea0706859bf6b3edabb0000000000000000000000004b0ca747bb24ca0b903af9df7b2ded9df39991a6000000000000000000000000304c9ddfb19ef931606e8284dd9090f369a0e7cc000000000000000000000000c4a9fddf73547b9eda209e490faf866615f5329c00000000000000000000000048b6bf41fbf2a15ff10db0eab881a223bf8a816700000000000000000000000020912b1cac1e896def8534b6a3c631928388b15f0000000000000000000000008927114e0ba296a5c4e57f12d2c3fae48eddfde8000000000000000000000000583a6e2bee37477a34dd86f98877e2694f575d570000000000000000000000006a85ba1a02da6688079baf3e854bbe7a60500582000000000000000000000000349c0922d5e4c98c6b3cef19ee84b347f58fa1a1000000000000000000000000e232f3585984c0152fe5059640a69e2878481d2600000000000000000000000067094d068409ed208b67cf15c844a3786350a3b90000000000000000000000001cab2dc688fd6a5b88fe0c9dc12ba89fc22c222c0000000000000000000000000db7974025dc469347869358b5cbb566245ba25d0000000000000000000000000bec35570662adddb2cb940e933a3d965c2c1716000000000000000000000000f1f6593917024e8bc4f1ba90c32bd69caccf793600000000000000000000000037da0efbc7705108fbcb0c632d12979b50e81eb500000000000000000000000028358057fa2e95f1c42cf05d70162ef9ed6547a3000000000000000000000000e36a3197791d1b36fab7f4e857b4b5efcd1ab75f0000000000000000000000002953b38dcc39d12160d64323bf253e9260bb211b00000000000000000000000015bd322e9cf3e4e1bdfff5cb776244fd30b613b500000000000000000000000072f25fa4ad411121430a0eeb445c283acad7023a0000000000000000000000007390cb656f18e09627330ec383b71720c4d8de5d000000000000000000000000e59fdc9f8fe2d449894d5fdd9c11432a417b98bf000000000000000000000000a60371260fb95a34803f6e901b636d1914b2fe00000000000000000000000000eb2fe5fb60bcff48b0e2584ef2f5b1581a49da9300000000000000000000000038bab693398e3511db9c5144e68110283d7d18e000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008ac7230489e80000", 159 | "nonce": "0x46", 160 | "to": "0xbdd2497c1a7d0bcae6143b0ad6509717265f621e", 161 | "transactionIndex": "0x8", 162 | "value": "0x0", 163 | "v": "0x25", 164 | "r": "0x8883d7317ac96db87111ecd5d20bafb3fbc48f77e25f6a5af181e5fda99dc4a9", 165 | "s": "0x1c49d8eb5268739bcb6a72930d8451a20d0b79259331fb2a794d29a5e27d962f" 166 | }, 167 | { 168 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 169 | "blockNumber": "0x5bf98b", 170 | "from": "0xaa121a1c1decab779fd582e9335755fbd73773be", 171 | "gas": "0x5208", 172 | "gasPrice": "0x77359400", 173 | "hash": "0xf1e175906dd0c1619f3479c22c899b220f695113a152db33b21d6a2d5d927dce", 174 | "input": "0x", 175 | "nonce": "0x2c3", 176 | "to": "0x8f23ab876dff5f63bea0d23a7106d094a84f9166", 177 | "transactionIndex": "0x9", 178 | "value": "0xb5e620f48000", 179 | "v": "0x26", 180 | "r": "0xf92056291225453b79ecc1d595eab02c81455d249453ff68d95ed4b77c8623fb", 181 | "s": "0x3c48eb591cd847502dab084e4fb969e51d3c1272d2b009ae960046f83fc95a2d" 182 | }, 183 | { 184 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 185 | "blockNumber": "0x5bf98b", 186 | "from": "0xaa121a1c1decab779fd582e9335755fbd73773be", 187 | "gas": "0x5208", 188 | "gasPrice": "0x77359400", 189 | "hash": "0xc0a0595633079a860ebc6147d9de1cddd2b50c62784663115953f3888390195c", 190 | "input": "0x", 191 | "nonce": "0x2c4", 192 | "to": "0x34601b1bb19104e3a716dd895690a7e172a2236d", 193 | "transactionIndex": "0xa", 194 | "value": "0xb5e620f48000", 195 | "v": "0x26", 196 | "r": "0xdd3eac918a5f6a23b59fbd52e9b84233c50e8f17a2ac289bb3a0bb3bf644e9c2", 197 | "s": "0x5ee7704c715a7e8fbd68e5d857d9daf0f9ca92dc4f58cd5125c72109763ab68f" 198 | }, 199 | { 200 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 201 | "blockNumber": "0x5bf98b", 202 | "from": "0xbf8f3d38a8c9b5b0138ab92e9962f3e11d7a7248", 203 | "gas": "0x3d090", 204 | "gasPrice": "0x77359400", 205 | "hash": "0x650ae0d6597f55b66a214fe454009a933fd84eb8182e52ec02b2326dea63e7b5", 206 | "input": "0x338b5dea00000000000000000000000050ee674689d75c0f88e8f83cfe8c4b69e8fd590d0000000000000000000000000000000000000000000000000000000077359400", 207 | "nonce": "0xa", 208 | "to": "0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208", 209 | "transactionIndex": "0xb", 210 | "value": "0x0", 211 | "v": "0x1b", 212 | "r": "0x1bf2260137ca454d21098c4785b142105698fc52d69cc0ba14f19fdf99b46406", 213 | "s": "0x496e9c7ca5214633c3d51ba54b2b5170b40c182571dfde9c293d2c0edefe24ae" 214 | }, 215 | { 216 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 217 | "blockNumber": "0x5bf98b", 218 | "from": "0x30e61647353393e5ca7930a0e26763387dfd9a1f", 219 | "gas": "0x1a7f4", 220 | "gasPrice": "0x59682f00", 221 | "hash": "0x5eed2bdaf3ea90302f77416ff1a399408f745d513b2e2b79361ae51a34a2e27f", 222 | "input": "0x1801fbe5417a6c65687269612e4604ea4916916707010000036687713deb9c873e620ef30000000001e0fc325ea7641645e0d368f95195099e471d69dda40e390d04f63a", 223 | "nonce": "0x30", 224 | "to": "0xb3dc3c839a02134f9932cbd60f3566c231cc90cc", 225 | "transactionIndex": "0xc", 226 | "value": "0x0", 227 | "v": "0x1b", 228 | "r": "0xd329b0cef52210915444651316ac2a64c7889cece46d74cd2b7ad02c1a1e823b", 229 | "s": "0x30e99923154fc21cf3f2608b5726731c34ddf28b9448ddba342f7d95706e32ad" 230 | }, 231 | { 232 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 233 | "blockNumber": "0x5bf98b", 234 | "from": "0x8563b157c87652290af56846711dd401cda3b19e", 235 | "gas": "0x7a120", 236 | "gasPrice": "0x4981b040", 237 | "hash": "0x093268d5d63dd6947752e394ca65e660597ac7d6a284e78dc45e8d8be6ecda2c", 238 | "input": "0x8f38f30900000000000000000000000000000000000000000000000000000000000000db0000000000000000000000000000000000000000000000000000000000000002", 239 | "nonce": "0x2ab", 240 | "to": "0x0ad3227eb47597b566ec138b3afd78cfea752de5", 241 | "transactionIndex": "0xd", 242 | "value": "0x12367f41b3e9d", 243 | "v": "0x25", 244 | "r": "0x6332c6602141f8284c4d9738604b786f4e580e41e3f6b32c3e512f0c84fb5119", 245 | "s": "0x6bfac29d3993d3cca82df72e1ae82e02eac72651b9dfa5b4deb16a9de717fbf0" 246 | }, 247 | { 248 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 249 | "blockNumber": "0x5bf98b", 250 | "from": "0x71dc0eddc0fdeea94d16e82dcb39ea30565b066c", 251 | "gas": "0xea60", 252 | "gasPrice": "0x48b45e80", 253 | "hash": "0xaf876c5eceb6e00e84ea2dbcc250eac2b48795ff9f0941bf1609f0d5512d01ce", 254 | "input": "0xa9059cbb0000000000000000000000000699659cd22fdb9144634468bf4f0e7dced4ccfe0000000000000000000000000000000000000000000000000de0b6b3a7640000", 255 | "nonce": "0x0", 256 | "to": "0xcba82d33ae7e6c28cb56b5412239b621e21c503b", 257 | "transactionIndex": "0xe", 258 | "value": "0x0", 259 | "v": "0x25", 260 | "r": "0x9e7effda880db73212d7ba1a2831e79d98995fb12e2f5406869cf9ff18d06071", 261 | "s": "0x69dbd646fd63611f4b47772f6cb08ba1d1b30b8d567c676e4839d723b5190b14" 262 | }, 263 | { 264 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 265 | "blockNumber": "0x5bf98b", 266 | "from": "0x68e55f054dc7ff9fc05a42859fec90eb9741639f", 267 | "gas": "0x186a0", 268 | "gasPrice": "0x481f2280", 269 | "hash": "0x5af7b68017e773ce400eaef78fa3ae892ad899fc04ad2ccd29d41481a45b9319", 270 | "input": "0x", 271 | "nonce": "0x0", 272 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 273 | "transactionIndex": "0xf", 274 | "value": "0x0", 275 | "v": "0x1b", 276 | "r": "0x718a8c8109da67ec5b4461d15d982f25d07fc4810451fb2ed3fdb48cdb6a2d23", 277 | "s": "0x1241cfe712d03c4ab38f5e1c45572f93efd50e581380891412503e87208ae4f5" 278 | }, 279 | { 280 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 281 | "blockNumber": "0x5bf98b", 282 | "from": "0x68c7cd90c94fb48017e10d4a83eeaf3a10eb353d", 283 | "gas": "0x186a0", 284 | "gasPrice": "0x481f2280", 285 | "hash": "0x3711ba4c55cbf4d73833657d26203a27e61c35efe934b0318cc2073efb2762ee", 286 | "input": "0x", 287 | "nonce": "0x0", 288 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 289 | "transactionIndex": "0x10", 290 | "value": "0x0", 291 | "v": "0x1c", 292 | "r": "0x9acf5d52411e014ac9128f987edebf127734f46bda996b754757eacdac956ac3", 293 | "s": "0x4a8370b40ad459f69e9ab3da1941b86648c1f7885e7b7f3f79efb4c3b487204a" 294 | }, 295 | { 296 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 297 | "blockNumber": "0x5bf98b", 298 | "from": "0x68c02ca6715b1859bd3a19be77a7d1a2e5475773", 299 | "gas": "0x186a0", 300 | "gasPrice": "0x481f2280", 301 | "hash": "0x2bfba9c14f05d54f32114b89d6fec031f4dde0d6a77b593d284e71c9fdbd4fa9", 302 | "input": "0x", 303 | "nonce": "0x0", 304 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 305 | "transactionIndex": "0x11", 306 | "value": "0x0", 307 | "v": "0x1b", 308 | "r": "0x8a26f4ea5713c9df6e23cd4c7c6efcf412803e860ef73cb085891658068ba9f3", 309 | "s": "0x3c868b83daa0d3740a5d4cc029845712593825d6a1d02c9d51e68e2910555e5f" 310 | }, 311 | { 312 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 313 | "blockNumber": "0x5bf98b", 314 | "from": "0x68b7c22dfd8d597bc37852812ee4e91d99390677", 315 | "gas": "0x186a0", 316 | "gasPrice": "0x481f2280", 317 | "hash": "0xd1333a49ed9463c0e63717e2ae8d2b31b14b3e8671b3aac53a876bd0418e0191", 318 | "input": "0x", 319 | "nonce": "0x0", 320 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 321 | "transactionIndex": "0x12", 322 | "value": "0x0", 323 | "v": "0x1b", 324 | "r": "0x426a8ff42e0956185f39e399dd74e7836e5f6ecfabd1b31273106456b901e9a7", 325 | "s": "0x1d5070017a6270ce42720daba14463e373e20247a68ea80694389cdcb3f629c4" 326 | }, 327 | { 328 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 329 | "blockNumber": "0x5bf98b", 330 | "from": "0x67eef587ff56862b293324414337161b1ce2c9c3", 331 | "gas": "0x186a0", 332 | "gasPrice": "0x481f2280", 333 | "hash": "0x8610d85b6faa56e270ac0132eb0600fff3033ea9b88e9cfcea4655386e37268f", 334 | "input": "0x", 335 | "nonce": "0x0", 336 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 337 | "transactionIndex": "0x13", 338 | "value": "0x0", 339 | "v": "0x1c", 340 | "r": "0xcf22bceb8d1d511305bf061e8904d1977cdac25d1d7758ea9350d9727f7348d0", 341 | "s": "0x523df918009874790c25f7c50fb0ef5ef7902cad32084b21e2263d6ce1bc391b" 342 | }, 343 | { 344 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 345 | "blockNumber": "0x5bf98b", 346 | "from": "0x67e6c751263720cd94f74b8f6b3d38a65d9dfddd", 347 | "gas": "0x186a0", 348 | "gasPrice": "0x481f2280", 349 | "hash": "0x51c5110aedfc83c3baafcfaee589a19cbc78775be90a94e89b770b8279bded0b", 350 | "input": "0x", 351 | "nonce": "0x0", 352 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 353 | "transactionIndex": "0x14", 354 | "value": "0x0", 355 | "v": "0x1b", 356 | "r": "0xfdcfc6e2364db5c5a4596bfdc18d4165caec992e06c2ad953ab6ce01aa4a8f57", 357 | "s": "0x50f6339b35edfa93c4e3535d596ff7002637310f5798acfcc2e7a9ae87154dc6" 358 | }, 359 | { 360 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 361 | "blockNumber": "0x5bf98b", 362 | "from": "0x67e25fd5ff7412c559d635a9559659d10cd430e2", 363 | "gas": "0x186a0", 364 | "gasPrice": "0x481f2280", 365 | "hash": "0x7478e45a5466141007055c09e48432efb403df27392fec1b58af07954e94f66b", 366 | "input": "0x", 367 | "nonce": "0x0", 368 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 369 | "transactionIndex": "0x15", 370 | "value": "0x0", 371 | "v": "0x1c", 372 | "r": "0x5e11a4094bd06f031f2e58a83c2b2098db91c24e4c3f7df455f35b1594ab928e", 373 | "s": "0x1c1b2389882ec7496e4f3beb13421a39da425f3299e678fba6e6567a85ca69a4" 374 | }, 375 | { 376 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 377 | "blockNumber": "0x5bf98b", 378 | "from": "0x67b18ad5477a5af7429de400b4f41f8b882fea58", 379 | "gas": "0x186a0", 380 | "gasPrice": "0x481f2280", 381 | "hash": "0x072fe4e4fb402c53b96be159638cbf2e58b254424ad4fd74ead4e921289d9c9e", 382 | "input": "0x", 383 | "nonce": "0x0", 384 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 385 | "transactionIndex": "0x16", 386 | "value": "0x0", 387 | "v": "0x1c", 388 | "r": "0x6463562b6bbd227c4dd74706f3a5aa8b12306f1243642c87c31e3b4be92d8927", 389 | "s": "0x2ce9084fe59b1b33bc2ad8b6122f8569b414c16c58996a50b2ed8bed10f86fdc" 390 | }, 391 | { 392 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 393 | "blockNumber": "0x5bf98b", 394 | "from": "0x67a961b0ec34934822a564822cf7bd8694b57a2f", 395 | "gas": "0x186a0", 396 | "gasPrice": "0x481f2280", 397 | "hash": "0x57531fbae03a3dedf76f9ed4268e6c2c2a3107f05f77199944766e590e9fdf94", 398 | "input": "0x", 399 | "nonce": "0x0", 400 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 401 | "transactionIndex": "0x17", 402 | "value": "0x0", 403 | "v": "0x1b", 404 | "r": "0x41a0f0671a774d3c937e12faf47de382ee92e2e15831214775757ccf677dab40", 405 | "s": "0x2b45a1cf1cf6e7992eea641352457b2a75f2a676e070eaccc8821e1ff0dd502" 406 | }, 407 | { 408 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 409 | "blockNumber": "0x5bf98b", 410 | "from": "0x66cf4b0112c254b0a3b4ef2b8f9875013e431182", 411 | "gas": "0x186a0", 412 | "gasPrice": "0x481f2280", 413 | "hash": "0xcc23dbd5bbf3820f26744dcfca2cd10c67051b238853954db0e1c4d33d5a2c3c", 414 | "input": "0x", 415 | "nonce": "0x0", 416 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 417 | "transactionIndex": "0x18", 418 | "value": "0x0", 419 | "v": "0x1c", 420 | "r": "0x10eaf90b9eab4cd393efc20782701e87a80a96c3114e2c13f63cb271fc159f14", 421 | "s": "0x5bb2d594adbbe90f471b95f5c183149b51b99584afabf6d201982b7dcc2645ea" 422 | }, 423 | { 424 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 425 | "blockNumber": "0x5bf98b", 426 | "from": "0x66ca37ebe15aed296988b0d22f56dadd03ed0150", 427 | "gas": "0x186a0", 428 | "gasPrice": "0x481f2280", 429 | "hash": "0xf2f4e0c3ddbd508abc5ea9540ae9a22e343402a856793a862c188024c3d35a5e", 430 | "input": "0x", 431 | "nonce": "0x0", 432 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 433 | "transactionIndex": "0x19", 434 | "value": "0x0", 435 | "v": "0x1b", 436 | "r": "0xda118b86ed5d9f06aa106427d41830d0822b43fdd25aabf699e94f8f1f7f200f", 437 | "s": "0x488dc560d5a0211758a79022bed34d40f33c670173772130f9505c7b128bf497" 438 | }, 439 | { 440 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 441 | "blockNumber": "0x5bf98b", 442 | "from": "0x66c7416c61acf2706c0ca9ecd7dda3cf2be65788", 443 | "gas": "0x186a0", 444 | "gasPrice": "0x481f2280", 445 | "hash": "0x8aceec1bf09bd17aacd0ff71177560277f1d9746fcabea3f35e2f4b8a28ff676", 446 | "input": "0x", 447 | "nonce": "0x0", 448 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 449 | "transactionIndex": "0x1a", 450 | "value": "0x0", 451 | "v": "0x1b", 452 | "r": "0x9ea14831e07295cec52c4b1380eae778f6a2c1f778e4e4f360bbfcc70e68d0e5", 453 | "s": "0xbac8d596b1e597134c2eec77e99345fd6dca51301bf6b39839c5a7341498c10" 454 | }, 455 | { 456 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 457 | "blockNumber": "0x5bf98b", 458 | "from": "0x3ef4de072e16307a67abf9aa9178c4a698d630f6", 459 | "gas": "0x186a0", 460 | "gasPrice": "0x481f2280", 461 | "hash": "0x95477ccd804a4a5ffdd85f9c3b0c7d2d606030a07c3cf4d0636dd87e8ecc4108", 462 | "input": "0x", 463 | "nonce": "0x0", 464 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 465 | "transactionIndex": "0x1b", 466 | "value": "0x0", 467 | "v": "0x1c", 468 | "r": "0x8838943118812eef03b8ecb7f96023d067e23f67a29877fb16ce1e22e5ecf6e9", 469 | "s": "0x6ddc49279886fef521f078a59848b5e86ebca9f44fcddfe88e488c4aa1460806" 470 | }, 471 | { 472 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 473 | "blockNumber": "0x5bf98b", 474 | "from": "0x3eedb4b2df23a2389ece1bcca9c6b6c2aa535221", 475 | "gas": "0x186a0", 476 | "gasPrice": "0x481f2280", 477 | "hash": "0x1f29010252af579b2b87fc2d7d4c551d1f488ee4c49174732ef1437b1a8c08fc", 478 | "input": "0x", 479 | "nonce": "0x0", 480 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 481 | "transactionIndex": "0x1c", 482 | "value": "0x0", 483 | "v": "0x1c", 484 | "r": "0x4a60bd9f0888925c5c36b5bf273d04995f6efac2753c830aed460c3f49358bf6", 485 | "s": "0x2b8d14fbe4d4d16058e8bf9e3568c90ff7a61f637370d03beff40c254963714f" 486 | }, 487 | { 488 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 489 | "blockNumber": "0x5bf98b", 490 | "from": "0x3edaf2928858d9c26fc1fb3a53c3c48921e803b2", 491 | "gas": "0x186a0", 492 | "gasPrice": "0x481f2280", 493 | "hash": "0xb9e68a05ac57dabcd1c1598c6c6d1b66df5d0d70e00076c98eb688d0861e0b2d", 494 | "input": "0x", 495 | "nonce": "0x0", 496 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 497 | "transactionIndex": "0x1d", 498 | "value": "0x0", 499 | "v": "0x1b", 500 | "r": "0x4b06079736f43a77ff6502087368aa38793872d69f92386caf7066f6f9381359", 501 | "s": "0x64e9bb16d5204a4b2f7d87f0c0968fb21651dd3e027b4ba2e7caba3694ac8548" 502 | }, 503 | { 504 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 505 | "blockNumber": "0x5bf98b", 506 | "from": "0x3ed25ce187a3ca9d6589f5da3c8b5c9dd1f9df73", 507 | "gas": "0x186a0", 508 | "gasPrice": "0x481f2280", 509 | "hash": "0x579fed81bb59abd864b004581119ee07c0bdadd0461f6a93d4bb03a9eb1fdcba", 510 | "input": "0x", 511 | "nonce": "0x0", 512 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 513 | "transactionIndex": "0x1e", 514 | "value": "0x0", 515 | "v": "0x1c", 516 | "r": "0x1606b0f5d647393c6eef4bf5f500c688ba3dcb2807c3a90a415795e656cddc0f", 517 | "s": "0x3bd712ac4b65394949c9ac9673668674f87a981ed652e89d181dca612ddc5239" 518 | }, 519 | { 520 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 521 | "blockNumber": "0x5bf98b", 522 | "from": "0x3ec2d5314c1c7d8776b5f862e1772efae178efc6", 523 | "gas": "0x186a0", 524 | "gasPrice": "0x481f2280", 525 | "hash": "0xa63b242020dea6b048c8596d1ad66ae755fd3d44a3c7ab0e18e5e1408118390b", 526 | "input": "0x", 527 | "nonce": "0x0", 528 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 529 | "transactionIndex": "0x1f", 530 | "value": "0x0", 531 | "v": "0x1c", 532 | "r": "0x5b23011bd6837422286e5a3923c1af576a290a6f4955fb0d8d826df8cc2d36c4", 533 | "s": "0x66cfd057975b6db91af2a1d2a7deff80b42299185938d9c002f56399b7577f7b" 534 | }, 535 | { 536 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 537 | "blockNumber": "0x5bf98b", 538 | "from": "0x3e7e0379e962de4e715435132efffa0d9b77f380", 539 | "gas": "0x186a0", 540 | "gasPrice": "0x481f2280", 541 | "hash": "0x37c53b021d75d16795782c446eee4b8646686df932094dc674266d721f5f78ff", 542 | "input": "0x", 543 | "nonce": "0x0", 544 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 545 | "transactionIndex": "0x20", 546 | "value": "0x0", 547 | "v": "0x1c", 548 | "r": "0xba383b11406c3403c9f904ab999787835e79860d778e0cd7c5d48fd6c68fb177", 549 | "s": "0x1e8962c9f8d520624e618fdfaa38c59077022dad36094beaf23597ea7f6b8add" 550 | }, 551 | { 552 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 553 | "blockNumber": "0x5bf98b", 554 | "from": "0x3e7d19c65a51fc12002e75539e83e9732ab2d301", 555 | "gas": "0x186a0", 556 | "gasPrice": "0x481f2280", 557 | "hash": "0xaff9ddaa3c9c420ee30dfa7b2d7af5a07bbafc3d79a824e02eb11bc638440195", 558 | "input": "0x", 559 | "nonce": "0x0", 560 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 561 | "transactionIndex": "0x21", 562 | "value": "0x0", 563 | "v": "0x1b", 564 | "r": "0x651bc956fcf3ff147824fc9a1aab6d94e48b0f1593c8c05c0c4beb3046b9c02b", 565 | "s": "0x6c0655aead360b2eb5208591ad195869d7d4c6650804e9b264e8fb4f4c4a29f2" 566 | }, 567 | { 568 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 569 | "blockNumber": "0x5bf98b", 570 | "from": "0x3e664b0187015d5a9a9ba69f4a0445f335635df6", 571 | "gas": "0x186a0", 572 | "gasPrice": "0x481f2280", 573 | "hash": "0xaada1072210975c62c28eacf26858c2ab39035937caef3d0fb7fc60fa2d4fd37", 574 | "input": "0x", 575 | "nonce": "0x0", 576 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 577 | "transactionIndex": "0x22", 578 | "value": "0x0", 579 | "v": "0x1b", 580 | "r": "0xdb802a6807279da54508731a6c4b013e45cd2bf3b19d21a6225a98a656d04877", 581 | "s": "0x6e085da686b3861e4df3ef4a19a0c555a5abe8999d49c8174f8eed3dcbf56ee" 582 | }, 583 | { 584 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 585 | "blockNumber": "0x5bf98b", 586 | "from": "0x3e0a145bcb3170e9e1da18d74f13b22e67d7b62b", 587 | "gas": "0x186a0", 588 | "gasPrice": "0x481f2280", 589 | "hash": "0x375dc38562b551e28e1ef76d4f046f42c3fe1c489ee6244abeb395a14d1d3c6c", 590 | "input": "0x", 591 | "nonce": "0x0", 592 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 593 | "transactionIndex": "0x23", 594 | "value": "0x0", 595 | "v": "0x1b", 596 | "r": "0x7fe8055625069374b13705dfd0c7a126df6a63936a981dcf30158d406ba28306", 597 | "s": "0x4932891f7de970437bf6c3d975f4883818d50df861e24e3711c01d190b3b37ca" 598 | }, 599 | { 600 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 601 | "blockNumber": "0x5bf98b", 602 | "from": "0x3dedb6e518f5e93b3669010f245130c9ba9f872a", 603 | "gas": "0x186a0", 604 | "gasPrice": "0x481f2280", 605 | "hash": "0x4a9ce6da7ea9263568cad2a441b73915f62f5eb1d7c75ad628836bdc30b55d13", 606 | "input": "0x", 607 | "nonce": "0x0", 608 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 609 | "transactionIndex": "0x24", 610 | "value": "0x0", 611 | "v": "0x1c", 612 | "r": "0x38456576266f4911d423bff464f177782fe38ad08e94394719e26b5d1783868d", 613 | "s": "0xf53a82bfd0ce7c3c5b6616d774d4b8ef5dc55e00fcb320ce763ac50c102fbce" 614 | }, 615 | { 616 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 617 | "blockNumber": "0x5bf98b", 618 | "from": "0x3deaaef1c64aef9166e24ce6c4a82ccc97027eaa", 619 | "gas": "0x186a0", 620 | "gasPrice": "0x481f2280", 621 | "hash": "0xd325915bb15243e1614a632a61e4be4470dc2baba14d910d33e545d3d25fdf33", 622 | "input": "0x", 623 | "nonce": "0x0", 624 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 625 | "transactionIndex": "0x25", 626 | "value": "0x0", 627 | "v": "0x1c", 628 | "r": "0x6822b577d4ac918687cbe8d61ca5009ce3ae3ab32051cc5d8df60a048d8d2b83", 629 | "s": "0x6005e5f079ed6f21d786b6c92e07ee02e4cb642ca2c3a73caf96b892a3508843" 630 | }, 631 | { 632 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 633 | "blockNumber": "0x5bf98b", 634 | "from": "0x3dbe1b017c5033218903eeb338d5de56e8e0681a", 635 | "gas": "0x186a0", 636 | "gasPrice": "0x481f2280", 637 | "hash": "0x6cc019f10be8d5d7c5055bb3d6ea18929704d3ae66ae880e0c713449ed5d5a51", 638 | "input": "0x", 639 | "nonce": "0x0", 640 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 641 | "transactionIndex": "0x26", 642 | "value": "0x0", 643 | "v": "0x1c", 644 | "r": "0xb602b666eaeb96215c39892655236de55ae01963ac18423aed9194197afcbda5", 645 | "s": "0x1332db400dc5ef69bb5016c33fa591a8a102800b1a684e5a4365b02fad534114" 646 | }, 647 | { 648 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 649 | "blockNumber": "0x5bf98b", 650 | "from": "0x3db37535da0d9347aba0b183f25a3f5465055be9", 651 | "gas": "0x186a0", 652 | "gasPrice": "0x481f2280", 653 | "hash": "0x437da23836c2f15d7802ba7ae12c05b6ad27d337dfdcd1054572ffad5dd697e6", 654 | "input": "0x", 655 | "nonce": "0x0", 656 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 657 | "transactionIndex": "0x27", 658 | "value": "0x0", 659 | "v": "0x1b", 660 | "r": "0x5a4ce8e0f79414dd33aeeaaa17ead7ca19ddd7c02bb3498fda465473afb6b06c", 661 | "s": "0x663ec573eeaec1fbcfe5b937dfe14da76b4fa29a6aee3961238f0caaf8ccd93c" 662 | }, 663 | { 664 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 665 | "blockNumber": "0x5bf98b", 666 | "from": "0x3db082c7dab85c448fd18b64c91e74687db35b3f", 667 | "gas": "0x186a0", 668 | "gasPrice": "0x481f2280", 669 | "hash": "0x39aa36cc99403ff1e722c8cdc103613f418759d85cb92600ade557fe2123f768", 670 | "input": "0x", 671 | "nonce": "0x0", 672 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 673 | "transactionIndex": "0x28", 674 | "value": "0x0", 675 | "v": "0x1c", 676 | "r": "0xf0b833725b820e04c47640885bde000bff764284e2bf7c78564c5717b0972f72", 677 | "s": "0x58729db40541ec9dbec06424929e8392be9c2b0df770f752de52e3bb9b36fb03" 678 | }, 679 | { 680 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 681 | "blockNumber": "0x5bf98b", 682 | "from": "0x3d97f04c08690bf1d2c817f240cc4c4c933b6c7c", 683 | "gas": "0x186a0", 684 | "gasPrice": "0x481f2280", 685 | "hash": "0x31107e7bf53a1a60d5ae0cde6826835a4116fa111703ef703d16c880557ae2de", 686 | "input": "0x", 687 | "nonce": "0x0", 688 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 689 | "transactionIndex": "0x29", 690 | "value": "0x0", 691 | "v": "0x1c", 692 | "r": "0xb3f02cf505c5ab7b7a81790aafa11e89ea74514b29e0152ff027cdbc8b5fd438", 693 | "s": "0x153eec5832749a66ce9fd86f97cba7055d016392854dc71174ff0add0acdd642" 694 | }, 695 | { 696 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 697 | "blockNumber": "0x5bf98b", 698 | "from": "0x3d87c69f1b9a2d56d86fb6b5dbdf655d2bfdedb8", 699 | "gas": "0x186a0", 700 | "gasPrice": "0x481f2280", 701 | "hash": "0xb18c48895df0d3b70599c8621ae0e065d34d47d0adeb321c063995e81e814e18", 702 | "input": "0x", 703 | "nonce": "0x0", 704 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 705 | "transactionIndex": "0x2a", 706 | "value": "0x0", 707 | "v": "0x1b", 708 | "r": "0x74916f6842f2e1dca9804af9b9e7a45e05beb7816f980d07a6d1f28bfa75ad2d", 709 | "s": "0x6469eb72505bcbcdbfabda412bb767bddae39bdbd66bffa16eaaaa418c485388" 710 | }, 711 | { 712 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 713 | "blockNumber": "0x5bf98b", 714 | "from": "0x3d5b9857a6e8f092482494df4cd94c202cce8fb1", 715 | "gas": "0x186a0", 716 | "gasPrice": "0x481f2280", 717 | "hash": "0x51a08f9a65dac2be724fea2a348a2d10bd3ef783fe13ec1539921d8485b1e7fe", 718 | "input": "0x", 719 | "nonce": "0x0", 720 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 721 | "transactionIndex": "0x2b", 722 | "value": "0x0", 723 | "v": "0x1b", 724 | "r": "0xc1d29bd6b1c278e103c3e0b89784072747d5e430e8f3d9292600141916f327ac", 725 | "s": "0x1fc2e8a37d0762db1473f8c29065407b690f674f17550a94bfcf5ad63782c7de" 726 | }, 727 | { 728 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 729 | "blockNumber": "0x5bf98b", 730 | "from": "0x3d370de4b716ba712563d6da7255e727e19613e0", 731 | "gas": "0x186a0", 732 | "gasPrice": "0x481f2280", 733 | "hash": "0xdf2896eed76ce02355151d54e6bfcbf1d8c8a52becd2a7a2eea27716e058e96b", 734 | "input": "0x", 735 | "nonce": "0x0", 736 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 737 | "transactionIndex": "0x2c", 738 | "value": "0x0", 739 | "v": "0x1b", 740 | "r": "0x309ecb33c3178ce4219651eaf97a7a2fa2ad7c44ff33fa375a3ba3bcd94184b7", 741 | "s": "0x6c64bdff92bf0f9725f7ff9a16f6ff2518e32767f401a8e9a658c8ea9ff66ef6" 742 | }, 743 | { 744 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 745 | "blockNumber": "0x5bf98b", 746 | "from": "0x3d189cd40c7c245300bb4fbf0bff53cfe242fef5", 747 | "gas": "0x186a0", 748 | "gasPrice": "0x481f2280", 749 | "hash": "0xc1928c0b6b8585462b985cf2fb2b70c0c5039c585e152551e41e0f8b57f8c100", 750 | "input": "0x", 751 | "nonce": "0x0", 752 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 753 | "transactionIndex": "0x2d", 754 | "value": "0x0", 755 | "v": "0x1b", 756 | "r": "0x1df3a7ac666882a3d8a2ebc9266c22ffb4863799baedbd183b53c975beb62b25", 757 | "s": "0x79b99d50c670d121652fe9a72be4a5a0bee53f473a201a3eac759f1b788433e1" 758 | }, 759 | { 760 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 761 | "blockNumber": "0x5bf98b", 762 | "from": "0x3c707b9a3b22d9fb015a68766495c1304c8d427a", 763 | "gas": "0x186a0", 764 | "gasPrice": "0x481f2280", 765 | "hash": "0x3945e69adba15c3f61ce4a53e5bedf2325996074e84e9ca713da84553c34f38a", 766 | "input": "0x", 767 | "nonce": "0x0", 768 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 769 | "transactionIndex": "0x2e", 770 | "value": "0x0", 771 | "v": "0x1c", 772 | "r": "0xe7255eaffc72e53f35f5de1aad0b227a8264f1be7afc2c219b96e23192e09165", 773 | "s": "0x580e9a9943e6bb4695ca14a211ef877cc2aa59833cffbc7894042c355875af5" 774 | }, 775 | { 776 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 777 | "blockNumber": "0x5bf98b", 778 | "from": "0x3c653ab877bdf5d2dc06cc734b8ff7cda96a0c1e", 779 | "gas": "0x186a0", 780 | "gasPrice": "0x481f2280", 781 | "hash": "0x95ba31ba6b9643070831d41538dd7c043a5c8b715e150a0fb9f820c989e3b8a1", 782 | "input": "0x", 783 | "nonce": "0x0", 784 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 785 | "transactionIndex": "0x2f", 786 | "value": "0x0", 787 | "v": "0x1c", 788 | "r": "0xa32b05863d7d3f8bc5901588f84d3990c02327872ccefc3e8827ac1aab8cf10", 789 | "s": "0x1bf9585451f78201d4020ad6ce963949b40001039f6fd26c431f5b8cb930ef2e" 790 | }, 791 | { 792 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 793 | "blockNumber": "0x5bf98b", 794 | "from": "0x3c5b4eba126dc8f5563495a785ad49720487ea00", 795 | "gas": "0x186a0", 796 | "gasPrice": "0x481f2280", 797 | "hash": "0x443f67a0a7eaa8a2cdb76628c447d47b4dd1feda1fe5e39ebcf8e59d40407771", 798 | "input": "0x", 799 | "nonce": "0x0", 800 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 801 | "transactionIndex": "0x30", 802 | "value": "0x0", 803 | "v": "0x1c", 804 | "r": "0xd7b9992a0abbf1a6ff99200bd4618d6ced2ecd29ccf5a7e47ed9fccc5d58c24c", 805 | "s": "0x45751bad8716f15e9aec6cc38defab843c038c93fb5a4d66d7dd578c8794fee7" 806 | }, 807 | { 808 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 809 | "blockNumber": "0x5bf98b", 810 | "from": "0x3c557bd67b9e316cc018fdddfc31bcf8da557153", 811 | "gas": "0x186a0", 812 | "gasPrice": "0x481f2280", 813 | "hash": "0x9fb007fbbe81d2c6aa4fbf3bc0d6f47ff043bba16bfcf52193ee638919377ef4", 814 | "input": "0x", 815 | "nonce": "0x0", 816 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 817 | "transactionIndex": "0x31", 818 | "value": "0x0", 819 | "v": "0x1c", 820 | "r": "0x50ef555cbc36f37b97783a2ba076e76ef342d81de5eed26ffa2e774157fdcd8e", 821 | "s": "0x621d0620a255d9b79d027e1ead336ceb0eb1529058c05eb9e46f560125a25bf0" 822 | }, 823 | { 824 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 825 | "blockNumber": "0x5bf98b", 826 | "from": "0x3c4f7d9ac0b0b894117985748de0a5072f6fa8aa", 827 | "gas": "0x186a0", 828 | "gasPrice": "0x481f2280", 829 | "hash": "0x8853228ccf79102ae5e28264abe905e432d42b8aa6d2582bfa9a943e1f35ec8a", 830 | "input": "0x", 831 | "nonce": "0x0", 832 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 833 | "transactionIndex": "0x32", 834 | "value": "0x0", 835 | "v": "0x1c", 836 | "r": "0x656d909486b2e71a86a34686e56e229d46563274c7bb21837f8fe98ecaa62594", 837 | "s": "0x54fc44caa9adc65d7dcb227dd77c6f4d962f1998a54bbf9218a1a4389a2b3b8d" 838 | }, 839 | { 840 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 841 | "blockNumber": "0x5bf98b", 842 | "from": "0x3c4cf5b5cd72670c5cf873f030b0cda8890b2eff", 843 | "gas": "0x186a0", 844 | "gasPrice": "0x481f2280", 845 | "hash": "0xeddbe8729690679509dac0ab2f268059fa1e9cb39781175af36bc619608f58e1", 846 | "input": "0x", 847 | "nonce": "0x0", 848 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 849 | "transactionIndex": "0x33", 850 | "value": "0x0", 851 | "v": "0x1c", 852 | "r": "0x4ffd18a9ff93fefdfc9c584bd5598529135b5121d26f3ee8baa157c0c50b5cf3", 853 | "s": "0x26889d69f6b8cdd4e08634e25c32490531f3d5cde19c027a1026be9c1b2f5424" 854 | }, 855 | { 856 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 857 | "blockNumber": "0x5bf98b", 858 | "from": "0x3bff1af978bc549ca1da7e4b029387121dae162c", 859 | "gas": "0x186a0", 860 | "gasPrice": "0x481f2280", 861 | "hash": "0x8a3cb98e34d4ffa3c6a1fe4057985da4858b77cd45c325985db063e0b04f6cb0", 862 | "input": "0x", 863 | "nonce": "0x0", 864 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 865 | "transactionIndex": "0x34", 866 | "value": "0x0", 867 | "v": "0x1b", 868 | "r": "0xd22e980c57720e84ad8a30ccd4a0fd88fabb00b4ad918f1c610436db3c80e31d", 869 | "s": "0x1c218d6526e73943c1a210499d9f01721301dbcd3abdc2c99a2baa46ece2d477" 870 | }, 871 | { 872 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 873 | "blockNumber": "0x5bf98b", 874 | "from": "0x3be92f33abff4809329db57d178c5e3a9528e2c3", 875 | "gas": "0x186a0", 876 | "gasPrice": "0x481f2280", 877 | "hash": "0x7d5347be0bfda72b9f89bdadd2aeca5a3e1686f45640711c3f6dd18c7b3daeb3", 878 | "input": "0x", 879 | "nonce": "0x0", 880 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 881 | "transactionIndex": "0x35", 882 | "value": "0x0", 883 | "v": "0x1c", 884 | "r": "0x95770fb46ff06471714afac82bfbcdd0b5edb06f3d6165a4321c7eae0b1a9d42", 885 | "s": "0x49e7344b6dc87e03772b44f7fe0edf669979475ff71e135f594a29a7d3e66ff2" 886 | }, 887 | { 888 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 889 | "blockNumber": "0x5bf98b", 890 | "from": "0x3bcdfaaee223528374be86b00580fcee80558383", 891 | "gas": "0x186a0", 892 | "gasPrice": "0x481f2280", 893 | "hash": "0x2c4113e1654d9cce43192dff28e445c5fcdc574c74a452124df22d0211d4b208", 894 | "input": "0x", 895 | "nonce": "0x0", 896 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 897 | "transactionIndex": "0x36", 898 | "value": "0x0", 899 | "v": "0x1b", 900 | "r": "0x63a5f390f467da9ae44b9c5cb51d264fc457d4deccbf073dc35adc1e34e27eb2", 901 | "s": "0x494c510482b36118882187b3c7d5067d51f5a23c67fa52ca650a926087c60dc8" 902 | }, 903 | { 904 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 905 | "blockNumber": "0x5bf98b", 906 | "from": "0x8ff43e16815785161f8356a0de2cb0e15c25ca85", 907 | "gas": "0x186a0", 908 | "gasPrice": "0x481f2280", 909 | "hash": "0xb916ab88b48645d94a2dc432caa9540c9c263b60d82d5006088c4764521c167e", 910 | "input": "0x", 911 | "nonce": "0x0", 912 | "to": "0x8a88f04e0c905054d2f33b26bb3a46d7091a039a", 913 | "transactionIndex": "0x37", 914 | "value": "0x0", 915 | "v": "0x1b", 916 | "r": "0xc5d08c6d68f3f2a131c40968f16276184bbd8457c795dcce9d2306a369811017", 917 | "s": "0x7c42feadc13b93d57708e36ac15a9f7ad710b6afd18354af62e5338b1cf23d67" 918 | }, 919 | { 920 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 921 | "blockNumber": "0x5bf98b", 922 | "from": "0x0c120689f43665e53292fb27e5d6e2e650f8c844", 923 | "gas": "0x61a8", 924 | "gasPrice": "0x481f2280", 925 | "hash": "0x4767bd2f9e935f5d05be4958c36ff921359458fa0a6291b0fa82001ebdedef2c", 926 | "input": "0x", 927 | "nonce": "0x1ea", 928 | "to": "0x082f8f3048b5787b8f3c9fdf24691d26b56a709c", 929 | "transactionIndex": "0x38", 930 | "value": "0xb014033a8000", 931 | "v": "0x25", 932 | "r": "0xc31e89535ca57e5ca82db8a53514c9ed149507f8336dc67decba349749e544b1", 933 | "s": "0x5183700ec981dcbaa185fa1d197da1d98fac3fa0c61f88483d621db4b257a923" 934 | }, 935 | { 936 | "blockHash": "0x0b963d785005ee2d25cb078daba5dd5cae1b376707ac53533d8ad638f9cb9659", 937 | "blockNumber": "0x5bf98b", 938 | "from": "0x0c120689f43665e53292fb27e5d6e2e650f8c844", 939 | "gas": "0x61a8", 940 | "gasPrice": "0x481f2280", 941 | "hash": "0x674da8c06262100c76e768ab58a490091fc251537d8985d346c70545a27c04f0", 942 | "input": "0x", 943 | "nonce": "0x1eb", 944 | "to": "0x462ac948029132fbb231f4c04a051dafe072fda6", 945 | "transactionIndex": "0x39", 946 | "value": "0xb014033a8000", 947 | "v": "0x26", 948 | "r": "0x7fb170d8c73a1a495ea46993f0f2fa48ddc2cc615d796826a4164938b99d2d56", 949 | "s": "0x47995b18183043020ae6ad0e514af3e8469c710c9a25e8566b5afc9dcc6ed4f6" 950 | } 951 | ], 952 | "transactionsRoot": "0xa6a15446cdde08204fa23edab00e36a91370cabf62ebaf6d2d0fc579194f4f23", 953 | "uncles": [] 954 | } 955 | } 956 | --------------------------------------------------------------------------------