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

use StateAtBlock and reference states when recreating missing state #277

Merged
merged 30 commits into from
Mar 13, 2024

Conversation

magicxyyz
Copy link
Contributor

@magicxyyz magicxyyz commented Dec 7, 2023

This PR is addressing following issues:

  1. When getting state for RPCs (in the upstream code), the state getter is called first and after that the state root is referenced in hashdb dirties cache if at all. It means that the state could potentially be garbage collected in another thread and further operations on state would fail.
    That is fine for normal archive node that keeps all the state and doesn't use dirties cache. It is also ok for a full node as we don't require it to keep all the state but only some recent, so RPCs are expected to fail when requesting too old state.
    However, that is an issue for "hybrid" node that persists only some states and keeps recent states in dirties cache - we expect it to always be able to process RPC for any state (to emulate normal archive node functionality).
  2. Previous implementation of recreating missing state (AdvanceStateUpToBlock), which we use for some RPCs (e.g. eth_call, etc_getBalance), accumulated changes to state in one StateDB object, what may cause some issues i.a. excessive memory usage by caches inside StateDB.

This PR:

  1. reorders referencing and getting state, adds referencing and adds a release method to state.StateDB
  2. changes the recreation of state to use eth.StateAtBlock which is upstream implementation for recreation of state for tracers and should be a more robust solution

@magicxyyz magicxyyz marked this pull request as ready for review December 8, 2023 16:18
Copy link
Contributor

@tsahee tsahee left a comment

Choose a reason for hiding this comment

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

Generally looking good. Some comments.
Also - I'd like to have a test for our partial-archive-node config that will try at least some of these APIs.

eth/state_accessor.go Outdated Show resolved Hide resolved
eth/state_accessor.go Outdated Show resolved Hide resolved
arbitrum/apibackend.go Outdated Show resolved Hide resolved
@magicxyyz
Copy link
Contributor Author

Also - I'd like to have a test for our partial-archive-node config that will try at least some of these APIs.

There already is a system test on nitro side, that runs this partial-archive-node, stops it, restarts it and then checks if eth_getBalance can be called for some blocks.
https://github.com/OffchainLabs/nitro/blob/a40f8f1e9ba0975452d3dc1da602f4e20142b608/system_tests/recreatestate_rpc_test.go#L429-L429

If needed, I can add some more specific tests for the changes, also in geth repo.

@magicxyyz
Copy link
Contributor Author

Also - I'd like to have a test for our partial-archive-node config that will try at least some of these APIs.

There already is a system test on nitro side, that runs this partial-archive-node, stops it, restarts it and then checks if eth_getBalance can be called for some blocks. https://github.com/OffchainLabs/nitro/blob/a40f8f1e9ba0975452d3dc1da602f4e20142b608/system_tests/recreatestate_rpc_test.go#L429-L429

If needed, I can add some more specific tests for the changes, also in geth rep

As suggested, I added a specific test on nitro side for getting state for RPCs:
https://github.com/OffchainLabs/nitro/blob/bb5c908d7c16e103130e2d80c7f5fc01e4dbef2e/system_tests/recreatestate_rpc_test.go#L514C1-L557

arbitrum/apibackend.go Outdated Show resolved Hide resolved
@magicxyyz
Copy link
Contributor Author

I am still doing some testing with nitro-testnode. I have to yet confirm that, but it seems that finalizers are not good solution.

core/state/statedb.go Outdated Show resolved Hide resolved
core/state/statedb.go Outdated Show resolved Hide resolved
@@ -70,7 +80,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
database = state.NewDatabaseWithConfig(eth.chainDb, trie.HashDefaults)
if statedb, err = state.New(block.Root(), database, nil); err == nil {
log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
return statedb, func() { database.TrieDB().Close() }, nil
return statedb, noopReleaser, nil
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 that changed to noop? where will that temporarye stateDatabase be released?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. Referencing here is not needed, as if the state is available it was read from disk.

  2. I've removed some of our changes here to minimize the diff to upstream, ia. we went with how upstream solved cleans cache memory leak by just disabling the cleans cache for the temporary dbs (trie.HashDefaults has cleans = 0) => we don't need to close the db here. If there will be need for cleans cache for better performance, we can enable cleans cache - we can do that in separate PR, but if needed I can enable it in this PR.

@@ -93,7 +103,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
if !readOnly {
statedb, err = state.New(current.Root(), database, nil)
if err == nil {
return statedb, func() { database.TrieDB().Close() }, nil
return statedb, noopReleaser, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

same question

Copy link
Contributor Author

Choose a reason for hiding this comment

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

here also if state is available then it was read from disk + same as above we don't need to close the triedb so we can remove the diff.

tsahee
tsahee previously approved these changes Mar 8, 2024
Copy link
Contributor

@tsahee tsahee left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@tsahee tsahee left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@tsahee tsahee left a comment

Choose a reason for hiding this comment

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

I meant approve, LGTM:)

@tsahee tsahee merged commit e5d8587 into master Mar 13, 2024
3 checks passed
@tsahee tsahee deleted the better-recreate-state-for-rpc branch March 13, 2024 01:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants