Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get_TransactionReceipt logIndex and transactionIndex is not correct #2028

Closed
tgerring opened this issue Dec 1, 2015 · 17 comments
Closed

get_TransactionReceipt logIndex and transactionIndex is not correct #2028

tgerring opened this issue Dec 1, 2015 · 17 comments

Comments

@tgerring
Copy link
Contributor

tgerring commented Dec 1, 2015

Working on a private chain, I noticed that logIndex seems to follow be the order of a transaction and transactionIndex not set to what it should be. For example, note the below block with 2 transactions, each containing 1 log. The "position" of these logs in the chain should be 7494.0.0 and 7494.1.0 where the format is BlockIndex.TransactionIndex.LogIndex, each as a subset of the other. Instead, go-ethereum reports the position as 7494.0.1 and 7494.0/1.1. The second receipt actually has conflicting information, with the transactionIndex being reported at "1" on the transaction itself but "0" on the composed log.

The positional values should be defined as follows:
BlockHeight (in main chain)
Transaction index (within the block)
Log index (within the transaction)

{
  "number": 7494,
  "hash": "0xf40e42e96dd65293fec0c964949c7fb0714950ad68f5dbc149976373863cb706",
  "parentHash": "0x64aade970cb55d33dac4de99fdfe586b33c273bd01aa9d2c5130891398ee7337",
  "nonce": "0x62ebcb509371bfa9",
  "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  "logsBloom": "0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000400000000000000000000000000000000000040000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000440000000000000000",
  "transactionsRoot": "0xabbadcac389e791d49707038e786e16b1f95133b476fbf89c170e675a58b19c3",
  "stateRoot": "0x1edf9403b6d46043e88c1df1135c27fc689503d18b2cdd1804a04197d4645c24",
  "receiptRoot": "0x0fd029c2da92e37cbb396d1fee0287c9804d8cc72cbb7c8cad81ebbbb68b1e29",
  "miner": "0x392af429f1b9537f28d97b8467e4b4e3498d5108",
  "difficulty": "2260665",
  "totalDifficulty": "6628082686",
  "size": 788,
  "extraData": "0xd883010301844765746887676f312e352e318664617277696e",
  "gasLimit": 3141592,
  "gasUsed": 97110,
  "timestamp": 1448536345,
  "transactions": [
    "0x350fb0718093692501fc33dec42b5a4e55860747b4224a3ee0625d1336923854",
    "0xdce4c53b4572f4f87a6a65ae149bbdf283f7517242696e5af7bfa48d4d9ea343"
  ],
  "uncles": []
}

Receipt 350fb0:

{
  "transactionHash": "0x350fb0718093692501fc33dec42b5a4e55860747b4224a3ee0625d1336923854",
  "transactionIndex": 0,
  "blockNumber": 7494,
  "blockHash": "0xf40e42e96dd65293fec0c964949c7fb0714950ad68f5dbc149976373863cb706",
  "cumulativeGasUsed": 22444,
  "gasUsed": 22444,
  "contractAddress": null,
  "logs": [
    {
      "address": "0x63f33b08404987648ce2dde79715e14e8b69e4d8",
      "topics": [
        "0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c"
      ],
      "data": "0x000000000000000000000000392af429f1b9537f28d97b8467e4b4e3498d51080000000000000000000000000000000000000000000000000000000000000001",
      "blockNumber": 7494,
      "logIndex": 0,
      "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "transactionHash": "0x350fb0718093692501fc33dec42b5a4e55860747b4224a3ee0625d1336923854",
      "transactionIndex": 0
    }
  ]
}

Receipt dce4c5:

{
  "transactionHash": "0xdce4c53b4572f4f87a6a65ae149bbdf283f7517242696e5af7bfa48d4d9ea343",
  "transactionIndex": 1,
  "blockNumber": 7494,
  "blockHash": "0xf40e42e96dd65293fec0c964949c7fb0714950ad68f5dbc149976373863cb706",
  "cumulativeGasUsed": 97110,
  "gasUsed": 74666,
  "contractAddress": null,
  "logs": [
    {
      "address": "0x63f33b08404987648ce2dde79715e14e8b69e4d8",
      "topics": [
        "0xe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda"
      ],
      "data": "0x000000000000000000000000392af429f1b9537f28d97b8467e4b4e3498d51081e170c489308caf0fe6d059b7da016bf187ec33420b8144a4db938a6e0a22c8d",
      "blockNumber": 7494,
      "logIndex": 1,
      "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
      "transactionHash": "0xdce4c53b4572f4f87a6a65ae149bbdf283f7517242696e5af7bfa48d4d9ea343",
      "transactionIndex": 0
    }
  ]
}
@bas-vk
Copy link
Member

bas-vk commented Dec 1, 2015

@tgerring, according to the official json docs the logIndex is the index of the log in the block and not in the transaction.

Could you try PR #2030?

@tgerring
Copy link
Contributor Author

tgerring commented Dec 1, 2015

The problem is that this definition is impractical. If the logIndex is based on the log position in the block, then it is impossible to identify a specific log without fetching all transactions in a block and looping to count the number of logs preceding the particular log. In fact, this is the point of having a transactionIndex. The logIndex should instead be the index of within the particular transaction.

Given a txhash and logIndex, here's the difference:
logIndex as position within block

  1. Given txhash, fetch transaction with eth_getTransaction
  2. From transaction, use blockHash to fetch Block with eth_getBlock
  3. From block, loop through transactions, calling eth_getTransactionReciept on each, counting the number of logs
    4 .When the total log count == logIndex, you have located the correct log

logIndex as position within transaction

  1. Given txhash, fetch transaction receipt with eth_getTransactionReceipt
  2. The log is located at logs[logIndex]

In summary, when logIndex tracks the position of the log within the block, it actually combines the txIndex and logIndex into a single confusing parameter. Instead, the bias of txIndex should be removed, so logIndex doesn't need to know anything about its containing block, only the transaction

@tgerring
Copy link
Contributor Author

tgerring commented Dec 1, 2015

Pinging @frozeman for his input

@frozeman
Copy link
Contributor

frozeman commented Dec 1, 2015

I agree with @tgerring here, it doesn't make real sense to make it block specific, as this makes the log index rather useless.
The only benefit it gives is to give an indication in which order they were processed. (Which can also be found out by checking the tx index too)

Im not sure how this is implemented in cpp @debris

@tjayrush
Copy link

tjayrush commented Nov 20, 2016

I've been looking into this carefully between geth and parity. Geth and parity both report transactionIndexes starting from '0' within a block. Parity (at least its latest version) reports logIndexes per transaction starting with '0'. Geth (prior to 1.5.x) reports logIndexes per block starting with '1'

So there's more than one different inconsistencies. The docs say that each item is an 'integer of the [item]'s index position in the block. null when its pending'.

I agree with tgerring, that the transactionIndex should be per block (because transactions are data members of blocks), and the logIndex should be per transaction (because logs are conceptually part of a transaction). Both should index starting with '0' not '1', but in either case, both should index starting with the same number.

Fixing this will be a breaking change for existing apps using either transactionIndex or logIndex (whichever gets changed), and the docs will have to be fixed.

I think it's also important to track that this gets made consistent between Parity and geth so as to make switching RPC providers painless.

@dpyro
Copy link

dpyro commented Mar 4, 2018

Fixing this would be a breaking change. However, this would make logIndex:

  • consistent with transactionIndex and blockNumber
  • useful
  • far less compute and bandwidth to fetch a specific class of events

Perhaps it could be done for the next major version?

@coderNeos
Copy link

+1 I think, that logIndex should be transaction specific. It is really useful in many cases.

@jmooo
Copy link

jmooo commented Aug 2, 2018

I just ran into this because it seemed strange geth indexed the logs as a position within the block, but I had to call client.ImportReceipt on each Txn to actually count how many logs are within the block total. Also confusing was this code comment stating logIndex is based on the position in the Receipt, but is actually based on the position in the Block currently.

(Incidentally what I was trying to do with create a buffered channel of len(logs) because as geth currently stands max(log_index) would be the appropriate channel size, but there's no way to find out what max is without iterating each receipt.)

@adamschmideg
Copy link
Contributor

@bas-vk are you still working on this? I'm going to remove the in-progress label.

@karalabe
Copy link
Member

karalabe commented Jan 8, 2019

We can do a similar fix to Parity. Then the API doesn't break, but the functionality gets shipped openethereum/parity-ethereum#3995

@adamschmideg
Copy link
Contributor

Feature request added: #18407

@sammy007
Copy link
Contributor

OMG can somebody take care of this finally?

@karalabe
Copy link
Member

karalabe commented Jan 27, 2020 via email

@sammy007
Copy link
Contributor

But I am not premine beneficiary...

@karalabe
Copy link
Member

karalabe commented Jan 27, 2020 via email

@karalabe
Copy link
Member

Ok, so we don't get what the issue here is.

The receipt returned an array of logs. If you access logs[5], then that's... "index 5 within the transaction". I don't see why we'd need a special field to spill this out.

@holiman holiman closed this as completed Sep 10, 2020
@jmooo
Copy link

jmooo commented Sep 15, 2020

@karalabe right, but I think that's incorrect because logs need to be indexed to the block not indexed to the transaction?

return values from eth_getFilterChanges:
logIndex: QUANTITY - integer of the log index position in the block. null when its pending log.

So if txn[0] has 2 logs, and txn[1] has 3 logs the proper logIndex values should be:

txn[0].logs[0] = 0
txn[0].logs[1] = 1
txn[1].logs[0] = 2
txn[1].logs[1] = 3
txn[1].logs[2] = 4

but instead geth returns:

txn[0].logs[0] = 0
txn[0].logs[1] = 1
txn[1].logs[0] = 0
txn[1].logs[1] = 1
txn[1].logs[2] = 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests