Why you didn't add BlockNumber to a Transaction struct?
How can I get Block number by Transaction?
A transaction doesn't have a block number, because it may be included in any block. A transaction receipt on the other hand does have a block number. eth.getTransactionReceipt(hash).
E.g. on Rinkeby:
> eth.getTransaction("0xc1c1eaeb8a9ca522bf49f3021da354a13947d9fde5f9bd934886713161e5b234")
{
blockHash: "0xfa85deb625c9f4279cc0e5e2f9fd08324ff70a0239f23a2f313702d5ce92dd7f",
blockNumber: 926794,
from: "0x2cf93add1b823d8bfd4723ab846041899b193ebc",
gas: 400000,
gasPrice: 20000000000,
hash: "0xc1c1eaeb8a9ca522bf49f3021da354a13947d9fde5f9bd934886713161e5b234",
input: "0x4dbf27cc000000000000000000000000551df15db6f9f834c6b5795183190582452cb10c",
nonce: 0,
r: "0xe2ced21d50e8810cdec93cc18f2575ec00c10cc5609bfbe1e27e4ce61556cfb9",
s: "0x2e17a1390ca6ade9ed23f4bdfdbaedf6f4d34a11f6784a6385c92ea85977c0ad",
to: "0x38621f898b7552a7982a5c5670e9d74c4adc8714",
transactionIndex: 1,
v: "0x2b",
value: 0
}
Ah, lookie, it actually does have the block number in.
But Go's structure types.Transaction doesn't contain BlockNumber while BlockNumber uses internally:
An Ethereum transaction has no associated block number. It is a set of fields that represent an order for a state transition. The block is only relevant when the transaction is executed. The RPC spec dictates that the result of retrieving a transaction should include block information. You can see here that this information is fetched separate and combined into a special rpc transaction.
ethapi is designed to work on the core types that go-ethereum internally uses. This was a deliberated decision. As such it doesn't include the block number. As already suggested, the best way to get block information is by receiving the receipt.
@bas-vk Actually, this might be an interesting problem. The types.Receipt struct as is doesn't contain block information either.
I just stumbled across this as well. To my knowledge there is no way to get a transaction's block number using ethclient. The receipt struct has no block number in it, and I can't go randomly trying blocks with TransactionInBlock because that's a bit silly.
Is there a workaround?
In the Javascript API, a Transaction Receipt has a blockNumber member https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethgettransactionreceipt
I'm rewriting some of my JS code in Go, and I'm going to need this in the Go API.
I'm still interested
If we find a way to access the rpc.Client from ethclient, we can workaround by calling CallContext(ctx, &raw, "eth_getTransactionByHash", hash) and get the blockNumber from there.
So far to have the BlockNumber returned we have to copy the TransactionByHash and all its internal dependencies. Is there a more elegant way to achieve that?
I created a PR to add BlockNumber to transaction receipt: #16912
@kivutar your changes look good why no PR?
Is there any strong arguments to not change the way ethclient: TransactionByHash works?
My proposal:
// TransactionByHashModified returns the transaction with the given hash, and the txExtraInfo
func (ec *Client) TransactionByHashModified(ctx context.Context, hash common.Hash) (tx *types.Transaction, blockNumber *string, isPending bool, err error) {
var json *rpcTransaction
err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash)
if err != nil {
return nil, nil, false, err
} else if json == nil {
return nil, nil, false, ethereum.NotFound
} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
return nil, nil, false, fmt.Errorf("server returned transaction without signature")
}
setSenderFromServer(json.tx, json.From, json.BlockHash)
return json.tx, json.BlockNumber, json.BlockNumber == nil, nil
}
else could we not simply add the blockhash or number to the *types.Transaction struct?
Edit: That is bad, we need to get it from the receipt but my point remains, is there a reason why we cannot/shouldn't edit the receipt call?
@maxrobot I think this whole thing is not needed because:
Event.Raw.BlockNumber@kivutar what should you do if you are building something with Go-Ethereum and you want to trace back which block a transaction belongs to by txHash?
You need to have been following the whole block generaiton with the Filter API? Or iterate through all the blocks until you find your specific transaction?
It seems a bee intensive to do :(
Checkout my pr #17662. It solves this issue without changing consensus, in a backwards compatible way, by adding the block location fields from ReadReceipt to the Receipt struct.
Let's get a review on #17662 so we can close out this issue. @karalabe @holiman
Can this be reviewed and merged, please? Or rpc client exposed directly so we can make custom calls?
@karalabe Just coming across this today while writing a simple API. Seems kind of strange that blocknumber isnt returned from TransactionReceipt() and types.Receipt, whats the best workaround for getting this info
@karalabe @kvutar
BlockNumber seems wrong for BlockNumberByTransactionHash but BlockHash is OK like code below:
(I don't know why)
// BlockHashByTransactionHash returns block hash for the transaction with the given hash.
func (ec *Client) BlockHashByTransactionHash(ctx context.Context, hash common.Hash) (blockHash *common.Hash, err error) {
var json *rpcTransaction
err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash)
if err != nil {
return nil, err
} else if json == nil {
return nil, ethereum.NotFound
} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
return nil, fmt.Errorf("server returned transaction without signature")
}
setSenderFromServer(json.tx, *json.From, *json.BlockHash)
return json.BlockHash, nil
}
This was solved by #17662, which added tx inclusion information to receipts. You can use TransactionReceipt to get the block number, hash and index in block.
@fjl Looks like it has been reverted https://github.com/paxosglobal/go-ethereum/blob/master/core/types/receipt.go#L46-L58
@kivutar wrong repo, here's the relevant link: https://github.com/ethereum/go-ethereum/blob/master/core/types/receipt.go#L64-L68
@holiman Hi, I'm looking at the same file in the most recent release (v1.8.27). I don't see this change. I do see it on master though.
https://github.com/ethereum/go-ethereum/blob/v1.8.27/core/types/receipt.go#L82
@karalabe Was this reverted?
Most helpful comment
@kivutar what should you do if you are building something with Go-Ethereum and you want to trace back which block a transaction belongs to by txHash?
You need to have been following the whole block generaiton with the Filter API? Or iterate through all the blocks until you find your specific transaction?
It seems a bee intensive to do :(