-
Notifications
You must be signed in to change notification settings - Fork 20.5k
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
types, rawdb, core, miner: add block location fields to receipt #17662
types, rawdb, core, miner: add block location fields to receipt #17662
Conversation
@bmperrea probably they just had no time to do a review yet. |
@karalabe any chance for a review on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
core/types/gen_receipt_json.go
Outdated
@@ -47,6 +54,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { | |||
TxHash *common.Hash `json:"transactionHash" gencodec:"required"` | |||
ContractAddress *common.Address `json:"contractAddress"` | |||
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` | |||
BlockHash *common.Hash `json:"blockHash"` | |||
BlockNumber *hexutil.Big `json:"blockNumber"` | |||
TransactionIndex *hexutil.Big `json:"transactionIndex"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps good to have omitEmpty
on the json-part?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea. Adding it now.
5d00090
to
444dd6f
Compare
That would be good, yes, ping @fjl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR adds a few fields to the receipt which only ever get initialized when read from the database. What happens when we receive a receipt from the network? The fields will be empty. What happens if we mine and generate a receipt ourselves? The fields will be empty.
These incomplete receipts will end up in various caches and will be returned on our APIs. Unless you ensure all paths that ever create a receipt also correctly initializes these fields, it's not possible to accept with PR.
You also updated the JSON output with extra fields, but the JSON is adhering to the standard Ethereum JSON RPC spec. Adding anything only in Geth will fragment the ecosystem because all of a sudden we have information other clients don't report. Or alternatively, our ethclient
expects fields that other clients don't provide. The correct way here is to open an EIP that chnges the RPC spec so all clients implement it and we can also enforce it properly.
thanks @karalabe 👍. Is the rpc spec you're referring to documented somewhere? I see block location fields are included here https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt |
444dd6f
to
9b2bbe8
Compare
Great point about mined and downloaded receipts @karalabe . I'm excited to improve the geth go-client interface to make sure we keep consistent with the rpc spec which includes these location fields. I've updated the PR to add code to take care of these cases in This pr makes the receipt object in the go-client interface more consistent with the rpc spec while also keeping consistent with how location fields are set for log entries. |
In general there are significant differences between the rpc api and the @karalabe is right that these missing block location fields, as well as the differences between This PR is only the beginning of fixing the broad issue. |
@karalabe it's your call, please decide on how to move forward |
Hi, actually I don't think we need to add these additional fields into the And actually what we are doing now is "try to cut some unnecessary fields" to save disk usage. Like in your PR you add three new fields which occupy 48bytes for each receipt. It can abuse the disk storage. For more information check #17106 |
We'll add this after #17106 is in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In core/state_processor.go we are creating new receipts when applying a transaction. You need to add these computed fields there too.
9b2bbe8
to
d797d25
Compare
Thanks @holiman @karalabe . I rebased and added the block location fields in To add the transaction index in Good work @rjl493456442 on #17106 . The separation of Receipt struct from the corresponding rlp and db objects allows for storage optimization while still allowing us to add context that a client would expect to have available when a Receipt object is returned, and the same goes for other types returned by ethclient. |
This change is going to help with ethclient because it will make it possible to fetch inclusion info through TransactionReceipt |
core/types/receipt.go
Outdated
// Block location fields - not part of the rlp | ||
BlockHash common.Hash `json:"blockHash,omitempty"` | ||
BlockNumber *big.Int `json:"blockNumber,omitempty"` | ||
TransactionIndex *big.Int `json:"transactionIndex,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TransactionIndex
can just be a regular uint
. Maybe it should be called BlockIndex
to make it clear that it's the index in the block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change the type Thanks for changing the type 👍
I got the name TransactionIndex
from this RPC spec. I'm hoping we can continue toward ethclient
implementing that entire spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it can be called TransactionIndex, it's fine. ethclient will never implement the full RPC API because it is based on core/types and some of the concepts in the web3 RPC API cannot be represented using the types. One example is transaction sender and inclusion info: the RPC API returns inclusion info and sender in the transaction object, but it would be silly to add those fields to types.Transaction
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather see us separate the interface struct from the storage struct than compromise the interface. ethclient
could return everything in rpcTransaction
. Otherwise it's dropping fields that are returned by the geth server.
It would be good to have a go client that is as functional as rpc clients in other languages and I think ethclient
should be that interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to explain the motivation for the current API in a different way: when making ethclient I wanted an API that could be implemented on the server side as well as the client side. The interfaces in the root directory should be general enough to allow efficient implementation on both sides. From that PoV the web3 RPC interface is stupid: it requires us to dig up receipts when transactions are queried to add inclusion info, etc. If you are building an app in Go, you should just be able to embed the light client in your app and access the blockchain using efficient operations. ethclient was supposed to be the drop-in replacement for the light client in cases where you want to get the same info from an RPC provider like Infura.
Unfortunately we never got around to implementing the interfaces natively, without RPC in the middle. That's why we're stuck with an API that doesn't match the RPC API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still want to get to the native implementation done. If you're seriously interested in improving Go developer experience using go-ethereum as a library, I'd be super happy if you could help us make that happen by implementing the existing interfaces on the server side.
@@ -121,6 +121,9 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo | |||
// Set the receipt logs and create a bloom for filtering | |||
receipt.Logs = statedb.GetLogs(tx.Hash()) | |||
receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) | |||
receipt.BlockHash = header.Hash() | |||
receipt.BlockNumber = header.Number | |||
receipt.TransactionIndex = uint(statedb.TxIndex()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better solution might be to set them in Process, since you can reuse the hash instead of recalculating the header hash for every tx.
The drawback, I guess, is that direct usage of ApplytTransaction
won't get it, which I guess applies to the miner, the txpool (?) and various users of chain_makers in tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@holiman fixed it now by adding an accessor for block hash to StateDB. The PR already adds an accessor for TxIndex, one more can't hurt.
Lgtm! |
Finally. Thank you guys! |
Solves ethereum#15210 without changing consensus, in a backwards compatible way, by adding tx inclusion information to the Receipt struct.
Solves #15210 without changing consensus, in a backwards compatible way, by adding the block location fields from ReadReceipt to the Receipt struct.
Update: In particular this improves consistency between the go client interface and the json rpc spec and allows go clients to use transaction receipts to watch for block confirmations for particular transactions - see #15210.