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

[wip] combined coreth mods #3

Draft
wants to merge 17 commits into
base: branch-v1.13.8
Choose a base branch
from

Conversation

darioush
Copy link
Owner

@darioush darioush commented Jun 14, 2024

This pull request introduces several changes to the core/state package, focusing on adding support for multi-coin accounts, enhancing snapshot functionality, and improving error handling and logging. The most significant changes include the addition of multi-coin account support, the introduction of new snapshot interfaces, and various improvements to the StateDB struct and its methods.

Multi-coin Account Support:

  • Added IsMultiCoin field to the DumpAccount struct and updated relevant functions to handle this new field. (core/state/dump.go) [1] [2] [3]
  • Introduced new methods in state_object_coreth.go to manage multi-coin balances, including AddBalanceMultiCoin, SubBalanceMultiCoin, and SetBalanceMultiCoin. (core/state/state_object_coreth.go)

Snapshot Enhancements:

  • Added new SnapshotTree interface to manage snapshots and updated the StateDB struct to use this new interface. (core/state/interfaces.go, core/state/statedb.go) [1] [2] [3]
  • Enhanced the snapshot interface with AccountIterator and StorageIterator methods, and updated the Tree struct to include UpdateWithBlockHash method. (core/state/snapshot/snapshot.go) [1] [2] [3]

Error Handling and Logging:

  • Improved error handling in the StateDB methods, such as SubRefund, GetBalance, and getDeletedStateObject, to provide more informative logs and prevent panics. (core/state/statedb.go) [1] [2] [3]
  • Updated test cases to reflect changes in error messages and logging. (core/state/snapshot/snapshot_test.go) [1] [2] [3] [4]

Additional Changes:

  • Modified the empty method in stateObject to account for the IsMultiCoin field. (core/state/state_object.go)
  • Refactored the Commit method in StateDB to include a new CommitWithBlockHash method for better snapshot management. (core/state/statedb.go) [1] [2] [3]

Comment on lines -118 to -125
func (db *Database) Reader(blockRoot common.Hash) (Reader, error) {
switch b := db.backend.(type) {
case *hashdb.Database:
return b.Reader(blockRoot)
case *pathdb.Database:
return b.Reader(blockRoot)
}
return nil, errors.New("unknown backend")
Copy link

Choose a reason for hiding this comment

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

why did we remove dual support for this?

Copy link
Owner Author

Choose a reason for hiding this comment

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

it is not needed to fork on the concrete type of the db backend since the interface supports it. I also applied this upstream.
There has also been some refactoring upstream here, which I partially applied to make things a bit more simple (provides a place for the interfaces)

UpdateSameRoot(common.Hash) error
}
if u, ok := db.backend.(withUpdateSameRoot); ok {
return u.UpdateSameRoot(root)
Copy link

Choose a reason for hiding this comment

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

I could not see where this was actually implemented in coreth. I guess we cannot handle this in atomic trie itself right?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Probably a bug that it's not referenced from coreth, (seems I only referenced it in subnet-evm's hashdb).
We should review the path that ensures blocks with the same state root are processed correctly.

// NewWithSnapshot creates a new state from a given trie with the specified [snap]
// If [snap] doesn't have the same root as [root], then NewWithSnapshot will return
// an error.
func NewWithSnapshot(root common.Hash, db Database, snaps SnapshotTree, snap snapshot.Snapshot) (*StateDB, error) {
Copy link

Choose a reason for hiding this comment

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

I think we can either unexport or remove this. It seems we use this only here and we already check if the snap == nil we can also check if root != snap.Root().

Copy link
Owner Author

Choose a reason for hiding this comment

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

I'm not sure if this is possible due to differences in nil, but definitely if possible I agree to not add it.

@@ -285,7 +300,7 @@ func (s *StateDB) GetBalance(addr common.Address) *big.Int {
if stateObject != nil {
return stateObject.Balance()
}
return common.Big0
return new(big.Int).Set(common.Big0)
Copy link

Choose a reason for hiding this comment

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

I wonder where/if we violate this. This is probably safer but again we should not ever modify returned bigint here.

Copy link
Owner Author

Choose a reason for hiding this comment

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

seems some diff we have from upstream for a long time, didn't notice anything failing without this patch

Comment on lines -574 to 596
if acc == nil {
if len(acc) == 0 {
return nil
}
data = &types.StateAccount{
Nonce: acc.Nonce,
Balance: acc.Balance,
CodeHash: acc.CodeHash,
Root: common.BytesToHash(acc.Root),
data, err = types.FullAccount(acc)
if err != nil {
s.setError(fmt.Errorf("could not unmarshal account (%x) error: %w", addr.Bytes(), err))
return nil
}
Copy link

Choose a reason for hiding this comment

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

aren't these (before/after changes) doing essentialy the same thing? If we use FullAccount we don't need below data.CodeHash/data.Root checks, but again it looks like we don't need these changes at all.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I use the rlp serialization here to avoid having to explicitly set the IsMulticoin field

@@ -1274,7 +1289,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
if origin == (common.Hash{}) {
origin = types.EmptyRootHash
}
if root != origin {
Copy link

Choose a reason for hiding this comment

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

why did we remove this?

Copy link
Owner Author

@darioush darioush Jul 10, 2024

Choose a reason for hiding this comment

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

Due to some consecutive blocks having the same root, I agree that we can probably hoist this to the caller instead, and probably drop the UpdateSameRoot. (Instead, the caller (blockchain.go) should know how to handle it, not sure that makes it super cleaner)

Copy link

Choose a reason for hiding this comment

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

I wonder if we move the stateDB interface here from coreth

Copy link
Owner Author

Choose a reason for hiding this comment

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

which one?

Copy link

Choose a reason for hiding this comment

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

the one in core/interface.go

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.

3 participants