Geth vs Ethermint Filters and Logs Comparison: Upgradable contract === During a workshop demonstration, we identified a problem with some JSON-RPC methods related to logs and filters. To validate if this is an issue on Ethermint or is the expected behavior, some test were performed to analyze and compare the responses. The results of these tests are presented below. The cases analyzed comprises getting logs and registering filters based on topics emitted when upgrading an upgradable contract. This analysis brought to light that there are some discrepancies when using the `getLogs` JSON-RPC method. ## Methodology The different test cases where performed manually while running a local node. Initially, a go-ethereum node was started. The tests were performed using the geth JavaScript console and curl tools. Once finished all tests and recorded the results, the procedure was repeated with an Ethermint node. For each of the test cases, the nodes were restarted, deleting previous tests state changes. ### Test cases Below is a list of the test cases analyzed: 1. Perform upgrade transaction and call `getLogs` method specifying the corresponding topics. 2. Perform upgrade transaction and call `getLogs` method specifying the corresponding topics and a block range. 3. **First register a filter** including the corresponding topics. Then perform the upgrade transaction 4. **First register a filter** including the corresponding topics and a block range. Then perform the upgrade transaction 5. **First perform upgrade transaction**. Then register filter including the corresponding topics. 6. **First perform upgrade transaction**. Then register filter including the corresponding topics and a block range. A final step for test cases 4 to 9 is calling the `eth_getFilterChanges` method to analyze the response. ### Procedure 1. Start a local node 2. Wait to initailize properly the JSON-RPC server 3. Perform the corresponding operations for each test case 4. Record results for further comparison ### Geth local node setup Spin up a geth node in developer mode and with JSON-RPC enabled. Also, initialize the geth JS console to interact with the node. You can do all this using the following command: ``` geth --dev --http=true console ``` ### Ethermint local node setup Spin up a local Ethermint node using the following command: ``` ./scripts/run-integration-tests.sh ``` Attach the geth JS console to the node using: ``` geth attach http://127.0.0.1:8545 ``` ### Resources used #### Hardhat repository This [Hardhat repository](https://github.com/facs95/hardhat-tests) was used to deploy the upgradable contract. Deploy an upgradable contract and perform the upgrade running the following command: ``` npx hardhat test ./test/upgrade-test.ts --network localhost ``` When using the geth node, you should make a minor change on the `hardhat.config.ts` file. Make sure to comment out the accounts mnemonic in the localhost network configuration: ``` ... localhost: { url: "http://localhost:8545/", // accounts: { // mnemonic: mnemonic_24 // }, }, ... ``` #### Geth JS console The geth JS console was used to get logs, register filters and get filter changes. Examples: ``` eth.getLogs({topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x000000000000000000000000b65e3da47c0a1400fd627e8932850e0755254811"]}) ``` #### curl Due to the fact that the `eth_getFilterChanges` method is not included in geth JS console, I used curl to call it. ## Results The results for all the test cases are presented in a table for comparison. For more detail about the requests and responses of each test case, read the Appendix section. | Test case | Description | Geth | Ethermint | | | --------- | ------------- | ----- | -------- | ---- | | 1 | Do tx, then `getLogs` w/ topics | `[log1]` | `[]` | :x: | 2 | Do tx, then `getLogs` w/ topics & block range | `[log1]`| `[log1]` | :heavy_check_mark: | 3 | Register filter w/ topic, then do tx | `[log1, log2]` | `[log1, log2, log3]` | :heavy_check_mark: | 4 | Register filter w/ topic & block range, then do tx | `[log1, log2]` | `[log1, log2, log3]` | :heavy_check_mark: | 5 | Do tx, then register filter w/ topic | `[]` | `[]` | :heavy_check_mark: | 6 | Do tx, then register filter w/ topic & block range | `[]` | `[]` | :heavy_check_mark: ## Conclusions & Observations The results show that the responses match mostly. However, there's discrepancy in the response for test case 1. This is the case where the upgrade is performed and then the `getLogs` method is called with the corresponding topics. In case of the geth node, it returns the log information. Conversely, the Ethermint node returns none. Further investigation will be carried out to understand this behavior. There is a difference on the amount of logs returned when using the filter for the topic `0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b`. Although there's no investigation about this yet, this could be due to the fact that the test setup in hardhat is different for the Ethermint node (i.e. changes in the hardhat config file). Additionally, when using the Ethermint node, running the hardhat script to deploy the contract throws an error the first few times. After the second try, it deploys the contract correctly but does not upgrade successfully. Finally, on the fourth attempt all the operations are completed successfully. This may be the reason why there is an extra log on the response (compared to geth response). ## Apendix - Requests & Responses Filters created for only the upgrade topic that repeats on all cases: ``` eth.filter({topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b"]}) ``` With block range: ``` eth.filter({fromBlock:"0x1", toBlock: "latest", topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b"]}) ``` ### Test case 1: #### Geth node ``` > eth.getLogs({topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x000000000000000000000000b65e3da47c0a1400fd627e8932850e0755254811"]}) [{ address: "0xac2e0e628cc2c1a511a2ef8e445a498ca954b532", blockHash: "0x5b799a316439702fdba18d678e1918cdd88a3ea3aa9df7abab44574e76c3303e", blockNumber: "0x4", data: "0x", logIndex: "0x0", removed: false, topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x000000000000000000000000b65e3da47c0a1400fd627e8932850e0755254811"], transactionHash: "0x2341fb7ebb075975e18adc9404a6b3379c6aa24956e883814ff6ca0af1ec7bd5", transactionIndex: "0x0" }] ``` #### Ethermint node ``` > eth.getLogs({topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000005740b613cc08a8ed765a898e82aa62e49137b5f8"]}) [] ``` ### Test case 2: #### Geth node ``` > eth.getLogs({fromBlock: "0x1", toBlock: "latest", topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x000000000000000000000000ffd28be57002800e015c2ddd70b7fbcaff2b47a0"]}) [{ address: "0xa2a5ef8f3e9e3ccde02904cdf91403b23b6bcd67", blockHash: "0x5d1b301c11915253efd45bca6b3899b8abe7b1c52e37750f23d24547b2ecfa72", blockNumber: "0x4", data: "0x", logIndex: "0x0", removed: false, topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x000000000000000000000000ffd28be57002800e015c2ddd70b7fbcaff2b47a0"], transactionHash: "0xc355048f8c39fe70dda74d7927f882a4594e2076545eaa0c6ef86b92276360e0", transactionIndex: "0x0" }] ``` #### Ethermint node ``` > eth.getLogs({fromBlock: "0x1", toBlock: "latest", topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000005740b613cc08a8ed765a898e82aa62e49137b5f8"]}) [{ address: "0xc09473c15be5a4b9d1a587a45dc8ef46f6872935", blockHash: "0x95e6f4b921356f1b8e24119a85f67191824d0a16e5d49c997ab3f410a07b824d", blockNumber: "0x57", data: "0x", logIndex: "0x0", removed: false, topics: ["0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000005740b613cc08a8ed765a898e82aa62e49137b5f8"], transactionHash: "0x057e18a2b030c423cd41afccbc4e32461059ce7f6083071d5477967f30fedf02", transactionIndex: "0x0" }] ``` ### Test case 3: #### Geth node ``` curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0xb0198e3d4c74089622337951a7fb0510"],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | jq { "jsonrpc": "2.0", "id": 1, "result": [ { "address": "0x6358b41b68d15a07a3ceaab790b3ed5385feb8c0", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x000000000000000000000000f33ae3519631a2cb41b040194a91ecb9e41a90a9" ], "data": "0x", "blockNumber": "0x2", "transactionHash": "0xf4d76e4808c2c1eb1d6d8ee3964480d847155f6ce9c96c77f8f875d76df41b50", "transactionIndex": "0x0", "blockHash": "0x7df94f7b967711fd6c40d3df767eb9c39440f5908e1473e868a4be830a617f3b", "logIndex": "0x0", "removed": false }, { "address": "0x6358b41b68d15a07a3ceaab790b3ed5385feb8c0", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x000000000000000000000000772e802f83c563358c4cc43a0be6f5099ccb6882" ], "data": "0x", "blockNumber": "0x4", "transactionHash": "0xfd5c018d4d65f41d492ceeb5d086b0fa3b78028aa12ab7c9fbb795b8884eb845", "transactionIndex": "0x0", "blockHash": "0xc5decc83bfcbe37f07aedb2c031b99bb7ac1a062695e4c191102d587f4fba026", "logIndex": "0x0", "removed": false } ] } ``` #### Ethermint node ``` curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x7a66920ac77b3713d5b95d3676b7241a"],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | jq { "jsonrpc": "2.0", "id": 1, "result": [ { "address": "0x3bf5b9b163662dff052e5e5b632b0dbb9a1a66be", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000007673ce09b30e758d68f0ab707e0daf6e0e180748" ], "data": "0x", "blockNumber": "0x4c", "transactionHash": "0xa16b80c9548efe13ac639e1dd8389fdf94d02d73d7634a6ac11328880801005a", "transactionIndex": "0x0", "blockHash": "0x27cb7ada7f4e56017ec163760a59e08c1190c964fa8ea912e087ac65c3e831ea", "logIndex": "0x0", "removed": false }, { "address": "0xc09473c15be5a4b9d1a587a45dc8ef46f6872935", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000007673ce09b30e758d68f0ab707e0daf6e0e180748" ], "data": "0x", "blockNumber": "0x55", "transactionHash": "0x131aa337bd022fc70d3da51ee8a5a8de7a3f5e9598ec363413a32070f74605a3", "transactionIndex": "0x0", "blockHash": "0x50399a509492b4cf6e97f827458bb5252b22f7eb22a52f83b768e47c305c0aac", "logIndex": "0x0", "removed": false }, { "address": "0xc09473c15be5a4b9d1a587a45dc8ef46f6872935", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000005740b613cc08a8ed765a898e82aa62e49137b5f8" ], "data": "0x", "blockNumber": "0x60", "transactionHash": "0xca6fe8f59896294c2d0b16b35b823281c684d879fc9ea99765b67b9f9bb4389c", "transactionIndex": "0x0", "blockHash": "0x88a4acad13853e4b2bbb76b8dafc6313082dc2917448bec9bfabdf14d7b96b7d", "logIndex": "0x0", "removed": false } ] } ``` ### Test case 4: #### Geth node ``` curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0xde9b75668c6ce9be7ffd5100ae9dd96d"],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | jq { "jsonrpc": "2.0", "id": 1, "result": [ { "address": "0x35933f9598e8c936dfac220dbfebe8096344e437", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x00000000000000000000000032290232e047824ff6a17ef30fabe58fa4333dd2" ], "data": "0x", "blockNumber": "0x2", "transactionHash": "0xc700cf1b20446fe136f386b29cde10b1b81081ba5b9d80e0956dbd9617208b75", "transactionIndex": "0x0", "blockHash": "0x498e405442e5e895b55845639fcd135a9f5ac31839bcffb95c3f7c6317ed5b0d", "logIndex": "0x0", "removed": false }, { "address": "0x35933f9598e8c936dfac220dbfebe8096344e437", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x00000000000000000000000027e55987a6b8c25444c4cfc7308c3ca2e4ca364c" ], "data": "0x", "blockNumber": "0x4", "transactionHash": "0x608302b20a7f9e93387739cd18060b3faf4acb0037395861ea2503dd471756d7", "transactionIndex": "0x0", "blockHash": "0x7d9dce969a06192bbfa3c0a01d08d755cdf6ef0764b7b83cb50ed3c2602aed2c", "logIndex": "0x0", "removed": false } ] } ``` #### Ethermint node ``` curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0xd35923778e6b5be747e1417611d2083a"],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | jq { "jsonrpc": "2.0", "id": 1, "result": [ { "address": "0x3bf5b9b163662dff052e5e5b632b0dbb9a1a66be", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000007673ce09b30e758d68f0ab707e0daf6e0e180748" ], "data": "0x", "blockNumber": "0x170", "transactionHash": "0x181cd7adac51ad7629a32aa34b3e2333c5d7a0e2ec99724fe3a0d10bb6fc0a41", "transactionIndex": "0x0", "blockHash": "0xce66f3948536e6db6da8a36266da2e91487c87ac49443fe98082485258dbac31", "logIndex": "0x0", "removed": false }, { "address": "0xc09473c15be5a4b9d1a587a45dc8ef46f6872935", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000007673ce09b30e758d68f0ab707e0daf6e0e180748" ], "data": "0x", "blockNumber": "0x184", "transactionHash": "0x24bc0c67645fb55b4a1bb9bd23412cf6f23af09a3bc89eb2b4e9b39f32aae857", "transactionIndex": "0x0", "blockHash": "0x8c5ff41cdcd336399488db98d42d557636b951c6261aa3642c993f05e0e6567a", "logIndex": "0x0", "removed": false }, { "address": "0xc09473c15be5a4b9d1a587a45dc8ef46f6872935", "topics": [ "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", "0x0000000000000000000000005740b613cc08a8ed765a898e82aa62e49137b5f8" ], "data": "0x", "blockNumber": "0x18e", "transactionHash": "0x1604ef4eab2f034a8164405994ff89f01ad94b5fa9c3a866a7fa0003353287a6", "transactionIndex": "0x0", "blockHash": "0xb0d25c8355b2bc92b91c5436ca67146f309e26ecf5745cf1a737265071545f53", "logIndex": "0x0", "removed": false } ] } ``` ### Test case 5: #### Geth node ``` curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x8599a1cde14eb618314008f3f764ad6e"],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | jq { "jsonrpc": "2.0", "id": 1, "result": [] } ``` #### Ethermint node ``` curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0xa91ed2a04b9f3b5c3151b349832e1640"],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | jq { "jsonrpc": "2.0", "id": 1, "result": [] } ``` ### Test case 6: #### Geth node ``` curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0xbd7e9f98ed9b14dff3e4cbf5e93926a5"],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | jq { "jsonrpc": "2.0", "id": 1, "result": [] } ``` #### Ethermint node ``` curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0xefd059a9e9422214353ada81f44f5f3b"],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | jq { "jsonrpc": "2.0", "id": 1, "result": [] } ```