eth_subscribe returns wrong value for logIndex field
Describe the bug
The values returned by eth_subscribe for logIndex are inconsistent with the values returned by eth_getLogs for the same log events.
Geth conforms to the rpc spec, which states that logIndex should be the index of the log into the block. Besu has its own non-compliant logIndex field, which is an index into the transaction rather than the block. There is currently an open PR for bringing Besu into compliance with the spec, which looks likely to be merged sometime soon (https://github.com/hyperledger/besu/pull/4355).
I have to say, I really appreciate the behavior of Nethermind's eth_getLogs, which is the best of both worlds: it returns the canonical geth style logIndex as logIndex, and the pathological besu-style logIndex as transactionLogIndex. Excellent!
Unfortunately,eth_subscribe does not do this, and instead returns only the besu-style logindex as logIndex. Because the same transaction has two different values for logIndex depending on whether it was returned by eth_subscribe or eth_getLogs, that makes it very easy for a client connecting to Nethermind's rpc server to become confused and malfunction.
We built our client around geth originally. Then had to build special behavior in for besu's bug, so now it can handle either. But it isn't working well with Nethermind, where the field is inconsistent and depends on how you receive the logs.
To Reproduce Steps to reproduce the behavior:
- Create a subscription to log events for an active contract using
eth_subscribecall over ws. - Save a handful of log events to a file.
- Re-request the same logs using
eth_getLogs - Notice that the
logIndexvalues returned frometh_subscribedo not match thelogIndexvalues returned frometh_getLogs. Instead of being an index into the block, it's an index into the transaction, which is returned separately astransactionLogIndexbyeth_getLogs.
Expected behavior
I expect logIndex for a specific log to return the same index regardless of whether it's coming back from eth_subscribe or eth_getLogs, ideally in compliance with the Ethereum JSON RPC.
Example
From eth_subscribe, I received this log event among others:
{
"address": "0x72002129a3834d63c57d157ddf069dee37b08f24",
"topics": [
"0xf6a97944f31ea060dfde0566e4167c1a1082551e64b60ecb14d599a9d023d451",
"0x0000000000000000000000000000000000000000000000000000000000000507"
],
"data": "0x000000000000000000000000000000000000000000000000000f608e8bef54000000000000000000000000003ae9d0b74e3968cfcf89a4de4f0d8b2a326a1dfd00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000faf898512abd68ebb95c5f0aa8200bbb000142bb020000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000f5e487852ac00000000000000000000000000000000000000000000000000000f5e4e60d770f6000000000000000000000000000000000000000000000000000f5e4e60d770f6000000000000000000000000000000000000000000000000000f5e4e60d770f6000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f63ee592ac000000000000000000000000000000000000000000000000000000f648ae50c4e66000000000000000000000000000000000000000000000000000f64d30eb9a13e000000000000000000000000000000000000000000000000000f652770eddccd000000000000000000000000000000000000000000000000000f652770eddccd000000000000000000000000000000000000000000000000000f652770eddccd00000000000000000000000000000000000000000000000000000000000000100f0109020c040e060d0308070b0a050000000000000000000000000000000000",
"blockNumber": "0xee0408",
"transactionHash": "0x2db52a9f5884253fc2d9f8953fe425deb1b7ff16120a74bf5a71daa948ebece9",
"transactionIndex": "0x1d",
"blockHash": "0xa5d7fe6e81f8b1af30aeee397c30db5a50f9f7d98e9bd71d45e70b0bd9e4c762",
"logIndex": "0x0",
"removed": false
}
Using eth_getLogs to fetch it after the fact gives me the correct logIndex (0x61):
{
"jsonrpc": "2.0",
"result": [
{
"address": "0x72002129a3834d63c57d157ddf069dee37b08f24",
"blockHash": "0xa5d7fe6e81f8b1af30aeee397c30db5a50f9f7d98e9bd71d45e70b0bd9e4c762",
"blockNumber": "0xee0408",
"data": "0x000000000000000000000000000000000000000000000000000f608e8bef54000000000000000000000000003ae9d0b74e3968cfcf89a4de4f0d8b2a326a1dfd00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000faf898512abd68ebb95c5f0aa8200bbb000142bb020000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000f5e487852ac00000000000000000000000000000000000000000000000000000f5e4e60d770f6000000000000000000000000000000000000000000000000000f5e4e60d770f6000000000000000000000000000000000000000000000000000f5e4e60d770f6000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f608e8bef5400000000000000000000000000000000000000000000000000000f63ee592ac000000000000000000000000000000000000000000000000000000f648ae50c4e66000000000000000000000000000000000000000000000000000f64d30eb9a13e000000000000000000000000000000000000000000000000000f652770eddccd000000000000000000000000000000000000000000000000000f652770eddccd000000000000000000000000000000000000000000000000000f652770eddccd00000000000000000000000000000000000000000000000000000000000000100f0109020c040e060d0308070b0a050000000000000000000000000000000000",
"logIndex": "0x61",
"removed": false,
"topics": [
"0xf6a97944f31ea060dfde0566e4167c1a1082551e64b60ecb14d599a9d023d451",
"0x0000000000000000000000000000000000000000000000000000000000000507"
],
"transactionHash": "0x2db52a9f5884253fc2d9f8953fe425deb1b7ff16120a74bf5a71daa948ebece9",
"transactionIndex": "0x1d",
"transactionLogIndex": "0x0"
}
These results came from a getblock rpc server running:
{"jsonrpc":"2.0","result":"Nethermind/v1.14.1-0-1a32d4541-20220914/X64-Linux/6.0.8","id":"1"}