-
Notifications
You must be signed in to change notification settings - Fork 20.3k
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
api: Fetch pending state from txpool #15963
Conversation
This is the related Quorum (Istanbul BFT) issue that made this issue come up: Consensys/quorum#247 |
There was never such definition. The pending block was always the next block containing as many transactions as fits is. Also I don't see what this PR supposed to do. The transaction pool only tracks virtual nonces, but otherwise does not have a state db. You attempt to operate on it as if it was a true state database containing all transactions. Also the reason we had
The miner is the one creating the pending state. Whether your node tries to find PoW is irrelevant, but if it requires the pending state, it needs the same logic as mining itself. Also this part of the code is being reworked currently. |
The rationale of the specific issue can be found here: ethereum/EIPs#650 (comment) Namely, all applications that rely on abigen rely on
Regarding that, let me rephrase. I did realize the issue of getting the state and header from different sources. Only one method does that, though: I would suggest following this up with a change that totally kills the miner when As an alternative to this PR, we could introduce a different endpoint in the API backend that is purely used for accessing "an account's next nonce", i.e. using the txpool for that. |
The miner just takes the pending state from the txpool (here) and filters the result, f.e. to fill the block only up to the max gas limit. |
This commit changes the source of the state when asking for the *pending* state. Instead of consulting the miner of the node, it uses teh pending state of the transaction pool. Two reasons for this change: 1. Introduction of the consensus package + BFT algorithms With the introduction of the consensus package and the potential BFT algorithms being built with it, the concept of the "pending block/state" changes its definition. In some of these algorithms, pending block can mean a block that is in the process of validation, but that can no longer be updated. This conflicts with the traditional meaning of "pending state", being the latest block plus all known pending transactions. Most notably, the Istanbul implementation has this problem. This also results in the values for the pending state being different for a node that has the miner enabled and the miner disabled. 2. General principle that the miner package should be disabled for non-mining nodes So considering the previous point, the use of the miner package for something else than mining should be evaluated. I think it makes sense to try working towards not using it at all when a node does not participate in the mining/validating process. Currently, the miner's pending state is used (a.o.) for executing new incoming transactions (because the EVM needs a "current block" for the global getters). I think this should be fairly easy to work around and this is a first step.
I think the thing 'closest' to what you want, is an additional api-method which would be "give me the nonce that the transaction-pending-pool considers the next available nonce for account x". This could be added to the txpool namespace imo. Note, though, that relying on such a method to provide nonces in concurrent requests would be dangerous, since there would always be gaps between getting it and submitting a signed transaction into the pending-pool. |
Considering that abigen and So either the bind package is broken because it uses the pending block instead of the pending state which potentially returns a sequence number that is already used, or either that method is ambiguous like I assumed. So yes, if a |
Apparently, there is |
If I may quote. This literally confirms how I interpreted PendingNonceAt as opposed to @karalabe's interpretation. // A PendingStateReader provides access to the pending state, which is the result of all
// known executable transactions which have not yet been included in the blockchain. It is
// commonly used to display the result of ’unconfirmed’ actions (e.g. wallet value
// transfers) initiated by the user. The PendingNonceAt operation is a good way to
// retrieve the next available transaction nonce for a specific account.
type PendingStateReader interface {
PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error)
PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error)
PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error)
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
PendingTransactionCount(ctx context.Context) (uint, error)
} ~ // The transaction must be signed and have a valid nonce to be included. Consumers of the
// API can use package accounts to maintain local private keys and need can retrieve the
// next available nonce using PendingNonceAt. |
Oh most definitely. You're not the first to stumble upon that, it's been the cause of many bug reports. So, I know there's been talk about removing the pending state in it's current form -- since it's kind of useless for anyone not mining; and most callers actually care about all the pending transactions, not just the ones who happen to be selected for inclusion in a potential next block. I agree that the documentation you find is erroneous, and misleading. @karalabe @fjl what would you propose to be the right path forward to make our API less confusing and error-prone? |
I would think a miner-independent "pending state" (as opposed to "pending block") would be ideal. All the global variables the EVM exposes for the current block can be "dummied" by just creating a dummy header and use that header for all pending txs. (Difficulty will be the hardest, but can be extracted from some block validation logic, I suppose.) |
Can you pls port this PR to quorum and i can test? Currently i try to modify code in quorum, but build was failed because the param in quorum and go-ethereum is difference updated: i ported to quorum, running -> the result is not good, we still can't send parallel transactions |
header, err := s.b.HeaderByNumber(ctx, blockNr) | ||
if header == nil || err != nil { | ||
return nil, 0, false, err | ||
} |
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 is racey. The whole reason behind retrieving the header and the state at the same time is because the pending state can and will change very frequently, often between these two calls (retrieving the state and the header separately). This was our original solution too btw that we needed to fix, took quite a lot to detect and figure out the issue.
// Pending state is only known by the miner | ||
if blockNr == rpc.PendingBlockNumber { | ||
block, state := b.eth.miner.Pending() | ||
return state, block.Header(), nil | ||
return b.eth.TxPool().State().StateDB, nil |
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.
AFAIK the transaction pool does not have a meaningful state, it just tracks pending nonces. Won't this break everything?
I don't really think this PR makes sense in it's current form. We updated the nonce retrieval in 1.9.0 to retrieve the nonce from the pool, so that's fixed. The txpool does not have a state otherwise, so this PR doesn't do what you think it does. |
The issue is that the txpool's state is just a fake thing to track nonces, it doesn't track any real state (balances, contracts, whatnot). I could imagine some consensus engine needs perhaps some specifics, but we should discuss those in the context of relevant PRs, not standalone, because it's hard to follow. |
I think that was the major problem we were having at the time, so that seems to be a good fix. |
This commit changes the source of the state when asking for the
pending state. Instead of consulting the miner of the node, it uses
teh pending state of the transaction pool.
Two reasons for this change:
With the introduction of the consensus package and the potential BFT
algorithms being built with it, the concept of the "pending block/state"
changes its definition. In some of these algorithms, pending block can
mean a block that is in the process of validation, but that can no
longer be updated. This conflicts with the traditional meaning of
"pending state", being the latest block plus all known pending
transactions.
Most notably, the Istanbul implementation has this problem. This also
results in the values for the pending state being different for a node
that has the miner enabled and the miner disabled.
non-mining nodes
So considering the previous point, the use of the miner package for
something else than mining should be evaluated. I think it makes sense
to try working towards not using it at all when a node does not
participate in the mining/validating process.
Currently, the miner's pending state is used (a.o.) for executing new
incoming transactions (because the EVM needs a "current block" for the
global getters). I think this should be fairly easy to work around and
this is a first step.