mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-17 12:21:38 +00:00
core/state: handle *bintrie.BinaryTrie in mustCopyTrie
mustCopyTrie panics on any trie type not in its type switch. On UBT-backed databases the state trie is a *bintrie.BinaryTrie, so every StateDB.Copy() call crashes with 'unknown trie type *bintrie.BinaryTrie'. BinaryTrie.Copy already exists and produces a correct deep copy; this just wires the case into the switch. Add TestStateDBCopyUBT as a regression guard: constructs a UBT StateDB, mutates an account, calls Copy, and verifies the copy is independent of the original.
This commit is contained in:
parent
61bfacc52f
commit
fa47f069d6
2 changed files with 38 additions and 0 deletions
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
"github.com/ethereum/go-ethereum/trie/bintrie"
|
||||||
"github.com/ethereum/go-ethereum/trie/transitiontrie"
|
"github.com/ethereum/go-ethereum/trie/transitiontrie"
|
||||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
|
|
@ -181,6 +182,8 @@ func mustCopyTrie(t Trie) Trie {
|
||||||
return t.Copy()
|
return t.Copy()
|
||||||
case *transitiontrie.TransitionTrie:
|
case *transitiontrie.TransitionTrie:
|
||||||
return t.Copy()
|
return t.Copy()
|
||||||
|
case *bintrie.BinaryTrie:
|
||||||
|
return t.Copy()
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("unknown trie type %T", t))
|
panic(fmt.Errorf("unknown trie type %T", t))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1366,3 +1366,38 @@ func TestStorageDirtiness(t *testing.T) {
|
||||||
state.RevertToSnapshot(snap)
|
state.RevertToSnapshot(snap)
|
||||||
checkDirty(common.Hash{0x1}, common.Hash{0x1}, true)
|
checkDirty(common.Hash{0x1}, common.Hash{0x1}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestStateDBCopyUBT exercises StateDB.Copy on a UBT-backed state database.
|
||||||
|
// Before the mustCopyTrie fix, this panicked with "unknown trie type
|
||||||
|
// *bintrie.BinaryTrie" because the type switch in mustCopyTrie only covered
|
||||||
|
// *trie.StateTrie and *transitiontrie.TransitionTrie.
|
||||||
|
func TestStateDBCopyUBT(t *testing.T) {
|
||||||
|
disk := rawdb.NewMemoryDatabase()
|
||||||
|
tdb := triedb.NewDatabase(disk, triedb.UBTDefaults)
|
||||||
|
sdb := NewDatabase(tdb, nil)
|
||||||
|
|
||||||
|
orig, err := New(types.EmptyRootHash, sdb)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("New: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Touch the trie so StateDB.Copy actually has to copy it.
|
||||||
|
addr := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
||||||
|
orig.SetBalance(addr, uint256.NewInt(1_000), tracing.BalanceChangeUnspecified)
|
||||||
|
|
||||||
|
// Must not panic.
|
||||||
|
cpy := orig.Copy()
|
||||||
|
if cpy == nil {
|
||||||
|
t.Fatal("Copy returned nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The copy must be independent: mutating the copy does not affect the
|
||||||
|
// original. Use balance as an observable.
|
||||||
|
cpy.SetBalance(addr, uint256.NewInt(2_000), tracing.BalanceChangeUnspecified)
|
||||||
|
if got, want := orig.GetBalance(addr), uint256.NewInt(1_000); got.Cmp(want) != 0 {
|
||||||
|
t.Fatalf("original balance mutated through copy: got %s, want %s", got, want)
|
||||||
|
}
|
||||||
|
if got, want := cpy.GetBalance(addr), uint256.NewInt(2_000); got.Cmp(want) != 0 {
|
||||||
|
t.Fatalf("copy balance did not update: got %s, want %s", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue