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

miner: only fill the pending block pre-merge #28440

Conversation

MariusVanDerWijden
Copy link
Member

@MariusVanDerWijden MariusVanDerWijden commented Oct 31, 2023

This PR changes the way the pending block is constructed.
It will leave the pending block empty after the merge.

The pending block still behaves correctly (e.g. increased block number etc), but it is just constructed as if the node has no transactions available.

The only issue I see with this approach is that some people might rely on the pending state for nonce tracking. However you can track the pending nonces via eth_getTransactionCount which uses the pendingNoncer in the txpool instead of the pending state.

@@ -1068,35 +1068,39 @@ func (w *worker) commitWork(interrupt *atomic.Int32, timestamp int64) {
if err != nil {
return
}
// Fill pending transactions from the txpool into the block.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, this change will break the subscription(pending transactions and pending logs)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, didn't think about that

Copy link
Member Author

@MariusVanDerWijden MariusVanDerWijden Oct 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm from what I can tell the pending transaction subscription goes via the txpool not the miner
Only the pending logs are retrieved via the miner

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. It might be a breaking change imo, I guess some MEV guys rely on the pending logs. Just want to mention here, not to block the pull request.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting point about pending logs. I think it's fair to remove them since they will be able to get this on demand via multicall.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can we obtain the pending logs via multicall though?

Originally people can subscribe the pending logs with or without filter criteria. The target is the pending transactions in the txpool which will have very high chance to be included in the next block.

But for multicall, the transactions/calls are constructed by the users themselves, the target is different right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can fetch list of pending transactions and pass them to multicall. Tho yes there will be no filtering on the server-side. But to your point, yes they will not know which txes are more likely to be mined. Because we simply return a flat list of transactions as opposed to a weighted list. Perhaps that's something that can be changed?

@MariusVanDerWijden
Copy link
Member Author

It would be good to benchmark this to see the impact of prefetching done by creating the pending block

@MariusVanDerWijden
Copy link
Member Author

Some stats:

Looks like CPU went down significantly
Screenshot_2023-11-24_12-06-05

Block processing is not impacted significantly
Screenshot_2023-11-24_12-06-49

The prefetcher stats, the miner drops from ~30 ops/s, most of them duplicates, and most of them wastes down to 0.
Screenshot_2023-11-24_12-07-09

@MariusVanDerWijden
Copy link
Member Author

One thing that changed between this PR and master is that snapshot storage read went from 5.9ms to 12.9ms. All other metrics stayed the same, execution actually went down from 45ms to 38ms

if pending != 1 {
t.Fatalf("unexpected pending, wanted 1 got: %v", pending)
// After nerfing the pending block, pending transaction count will be 0
if pending != 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the pending nonce changed here? I thought that's fetched through txpool.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the pending nonce, but the pending transaction count. The pending nonce does not change because its fetched through the txpool. The pending transaction count returns the number of transactions in a block. I don't think it is a useful metric at all for the pending block

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argh I thought this is a call to eth_getTransactionCount. That method name is confusing.

@s1na
Copy link
Contributor

s1na commented Nov 28, 2023

Some eth protocol tests are failing. If they are flaky I haven't seem them fail before:

--- FAIL: TestEthSuite (11.07s)
    --- FAIL: TestEthSuite/TestBroadcast (10.01s)
        suite_test.go:53: 
    --- FAIL: TestEthSuite/TestLargeAnnounce (0.06s)
        suite_test.go:53: 
    --- FAIL: TestEthSuite/TestOldAnnounce (0.00s)
        suite_test.go:53: 
    --- FAIL: TestEthSuite/TestBlockHashAnnounce (0.00s)
        suite_test.go:53: 
    --- FAIL: TestEthSuite/TestMaliciousStatus (0.01s)
        suite_test.go:53: 
    --- FAIL: TestEthSuite/TestTransaction (0.00s)
        suite_test.go:53: 
    --- FAIL: TestEthSuite/TestMaliciousTx (0.06s)
        suite_test.go:53: 
    --- FAIL: TestEthSuite/TestLargeTxRequest (0.01s)
        suite_test.go:53: 
    --- FAIL: TestEthSuite/TestNewPooledTxs (0.00s)
        suite_test.go:53: 
FAIL
FAIL	github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest	11.100s

@MariusVanDerWijden
Copy link
Member Author

MariusVanDerWijden commented Nov 28, 2023

Weird, it works on my AMD64 Linux machine, I think these might be flaky and if the first one fails, all subsequent ones fail as well

@MariusVanDerWijden
Copy link
Member Author

During the refactor of the miner package I kinda came to the conclusion that it would be possible to just create the pending block (with transactions) on the fly when requested. This is kind-of a costly operation but it would not break any users

@holiman
Copy link
Contributor

holiman commented Nov 28, 2023

If they are flaky I haven't seem them fail before:

I've seen those fail from time to time, they're flaky

@@ -598,8 +598,9 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if pending != 1 {
t.Fatalf("unexpected pending, wanted 1 got: %v", pending)
// After nerfing the pending block, pending transaction count will be 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2023-11-28 at 13-59-11 verb nerf at DuckDuckGo

Is this what you mean? Or do you mean 'yeet'?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant nerf as in weaken. The pending block is still constructed, just without any transactions

@MariusVanDerWijden
Copy link
Member Author

I'm going to close this for now. During the bigger refactor of the miner I noticed that we could just produce the pending block on demand. This will be a bit heavier for people depending on it, but it won't bork people depending on the behavior. And it has the same benefit as this PR as most users will not have to compute the pending block at all.

A good learning from this PR though is that the block processing is not impacted much by the prefetching done during construction of the pending block. And not computing the pending block will save a lot of CPU

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

Successfully merging this pull request may close these issues.

4 participants