mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
core/state: Track block-hash to base-state-root mapping for Verkle transition
This commit is contained in:
parent
a7f24c26c0
commit
a8240e46ea
5 changed files with 432 additions and 0 deletions
|
|
@ -274,6 +274,10 @@ type BlockChain struct {
|
||||||
processor Processor // Block transaction processor interface
|
processor Processor // Block transaction processor interface
|
||||||
vmConfig vm.Config
|
vmConfig vm.Config
|
||||||
logger *tracing.Hooks
|
logger *tracing.Hooks
|
||||||
|
|
||||||
|
// Verkle transition fields
|
||||||
|
blockToBaseStateRoot *state.BlockToBaseStateRoot
|
||||||
|
verkleTransitionBlock uint64 // Block number when Verkle transition begins
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
|
|
@ -486,6 +490,21 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
if txLookupLimit != nil {
|
if txLookupLimit != nil {
|
||||||
bc.txIndexer = newTxIndexer(*txLookupLimit, bc)
|
bc.txIndexer = newTxIndexer(*txLookupLimit, bc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize verkle transition mapping if needed
|
||||||
|
if chainConfig.IsVerkleActive(0) || (chainConfig.VerkleBlock != nil && chainConfig.VerkleBlock.Uint64() > 0) {
|
||||||
|
bc.verkleTransitionBlock = chainConfig.VerkleBlock.Uint64()
|
||||||
|
|
||||||
|
mapping, err := state.LoadBlockToBaseStateRoot(db)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bc.blockToBaseStateRoot = mapping
|
||||||
|
log.Info("Initialized Verkle transition mapping", "verkleBlock", bc.verkleTransitionBlock)
|
||||||
|
} else {
|
||||||
|
bc.blockToBaseStateRoot = state.NewBlockToBaseStateRootMapping()
|
||||||
|
}
|
||||||
|
|
||||||
return bc, nil
|
return bc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
150
core/blockchain_verkle_test.go
Normal file
150
core/blockchain_verkle_test.go
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestVerkleTransitionWithReorg tests the mapping during a reorg at the verkle transition
|
||||||
|
func TestVerkleTransitionWithReorg(t *testing.T) {
|
||||||
|
// Configure Verkle transition at block 10
|
||||||
|
var (
|
||||||
|
db = rawdb.NewMemoryDatabase()
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: ¶ms.ChainConfig{
|
||||||
|
ChainID: big.NewInt(1337),
|
||||||
|
VerkleBlock: big.NewInt(10),
|
||||||
|
HomesteadBlock: big.NewInt(0),
|
||||||
|
EIP150Block: big.NewInt(0),
|
||||||
|
EIP155Block: big.NewInt(0),
|
||||||
|
EIP158Block: big.NewInt(0),
|
||||||
|
},
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): {Balance: big.NewInt(1000000000000000000)},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
genesis = gspec.MustCommit(db)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create our blockchain instance
|
||||||
|
blockchain, err := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create blockchain: %v", err)
|
||||||
|
}
|
||||||
|
defer blockchain.Stop()
|
||||||
|
|
||||||
|
// Create a chain up to the fork block (block 9)
|
||||||
|
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 9, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetCoinbase(common.HexToAddress("0x" + string(i+'0')))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Insert blocks up to block 9
|
||||||
|
if _, err := blockchain.InsertChain(blocks); err != nil {
|
||||||
|
t.Fatalf("Failed to insert initial chain: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create two competing forks from block 9 (both are at the Verkle transition height)
|
||||||
|
// Fork 1 with account A1
|
||||||
|
fork1Block10, _ := GenerateChain(gspec.Config, blocks[len(blocks)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetCoinbase(common.HexToAddress("0xA1"))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Fork 2 with account A2
|
||||||
|
fork2Block10, _ := GenerateChain(gspec.Config, blocks[len(blocks)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {
|
||||||
|
gen.SetCoinbase(common.HexToAddress("0xA2"))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Insert fork 1 (blocks 10-A1)
|
||||||
|
if _, err := blockchain.InsertChain(fork1Block10); err != nil {
|
||||||
|
t.Fatalf("Failed to insert fork 1: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both forks add a new account A3
|
||||||
|
addr3 := common.HexToAddress("0xA3")
|
||||||
|
|
||||||
|
// Create block 11 on fork 1 (adding account A3)
|
||||||
|
fork1Block11, _ := GenerateChain(gspec.Config, fork1Block10[0], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {
|
||||||
|
// Add account A3
|
||||||
|
tx, _ := types.SignTx(
|
||||||
|
types.NewTransaction(0, addr3, big.NewInt(100), 21000, big.NewInt(1), nil),
|
||||||
|
types.HomesteadSigner{},
|
||||||
|
testKey,
|
||||||
|
)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Insert block 11 on fork 1
|
||||||
|
if _, err := blockchain.InsertChain(fork1Block11); err != nil {
|
||||||
|
t.Fatalf("Failed to insert fork 1 block 11: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the mapping for fork 1's block 10
|
||||||
|
baseRoot1, exists := blockchain.blockToBaseStateRoot.Get(fork1Block10[0].Hash())
|
||||||
|
if !exists {
|
||||||
|
t.Fatalf("Expected mapping to exist for fork 1 block 10")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now simulate a reorg by inserting fork 2 (with higher total difficulty)
|
||||||
|
for i := range fork2Block10 {
|
||||||
|
fork2Block10[i].Header().Difficulty = new(big.Int).Add(fork2Block10[i].Header().Difficulty, big.NewInt(1000))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert fork 2 (blocks 10-A2)
|
||||||
|
if _, err := blockchain.InsertChain(fork2Block10); err != nil {
|
||||||
|
t.Fatalf("Failed to insert fork 2: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create block 11 on fork 2 (also adding account A3)
|
||||||
|
fork2Block11, _ := GenerateChain(gspec.Config, fork2Block10[0], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {
|
||||||
|
// Add same account A3
|
||||||
|
tx, _ := types.SignTx(
|
||||||
|
types.NewTransaction(0, addr3, big.NewInt(100), 21000, big.NewInt(1), nil),
|
||||||
|
types.HomesteadSigner{},
|
||||||
|
testKey,
|
||||||
|
)
|
||||||
|
gen.AddTx(tx)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Ensure fork 2 has higher total difficulty
|
||||||
|
for i := range fork2Block11 {
|
||||||
|
fork2Block11[i].Header().Difficulty = new(big.Int).Add(fork2Block11[i].Header().Difficulty, big.NewInt(1000))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert block 11 on fork 2
|
||||||
|
if _, err := blockchain.InsertChain(fork2Block11); err != nil {
|
||||||
|
t.Fatalf("Failed to insert fork 2 block 11: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the mapping for fork 2's block 10
|
||||||
|
baseRoot2, exists := blockchain.blockToBaseStateRoot.Get(fork2Block10[0].Hash())
|
||||||
|
if !exists {
|
||||||
|
t.Fatalf("Expected mapping to exist for fork 2 block 10")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The base roots should be different
|
||||||
|
if baseRoot1 == baseRoot2 {
|
||||||
|
t.Fatalf("Expected different base roots for different forks")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current chain head should be fork 2 block 11
|
||||||
|
if blockchain.CurrentBlock().Hash() != fork2Block11[0].Hash() {
|
||||||
|
t.Fatalf("Expected chain head to be fork 2 block 11")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify we can correctly get state for fork 2 block 11
|
||||||
|
state, err := blockchain.StateAt(fork2Block11[0].Root())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get state: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check A3 is present in the state
|
||||||
|
if balance := state.GetBalance(addr3); balance.Cmp(big.NewInt(100)) != 0 {
|
||||||
|
t.Fatalf("Expected A3 balance of 100, got %v", balance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -86,6 +86,11 @@ type StateDB struct {
|
||||||
// It will be updated when the Commit is called.
|
// It will be updated when the Commit is called.
|
||||||
originalRoot common.Hash
|
originalRoot common.Hash
|
||||||
|
|
||||||
|
// Verkle transition fields for identifying state
|
||||||
|
verkleTransitionActive bool
|
||||||
|
baseStateRoot common.Hash
|
||||||
|
blockHash common.Hash
|
||||||
|
|
||||||
// This map holds 'live' objects, which will get modified while
|
// This map holds 'live' objects, which will get modified while
|
||||||
// processing a state transition.
|
// processing a state transition.
|
||||||
stateObjects map[common.Address]*stateObject
|
stateObjects map[common.Address]*stateObject
|
||||||
|
|
@ -1434,3 +1439,52 @@ func (s *StateDB) Witness() *stateless.Witness {
|
||||||
func (s *StateDB) AccessEvents() *AccessEvents {
|
func (s *StateDB) AccessEvents() *AccessEvents {
|
||||||
return s.accessEvents
|
return s.accessEvents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add new methods for Verkle transition
|
||||||
|
func (s *StateDB) SetVerkleTransitionData(blockHash, baseStateRoot common.Hash) {
|
||||||
|
s.verkleTransitionActive = true
|
||||||
|
s.baseStateRoot = baseStateRoot
|
||||||
|
s.blockHash = blockHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVerkleTransitionActive returns whether the state is in Verkle transition
|
||||||
|
func (s *StateDB) IsVerkleTransitionActive() bool {
|
||||||
|
return s.verkleTransitionActive
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseStateRoot returns the Merkle state root used as base during transition
|
||||||
|
func (s *StateDB) BaseStateRoot() common.Hash {
|
||||||
|
return s.baseStateRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
|
||||||
|
// Try current state first
|
||||||
|
value := s.GetState(addr, hash) // This is wrong - would cause recursion
|
||||||
|
|
||||||
|
// Instead, check how GetState is currently implemented
|
||||||
|
// Likely something like:
|
||||||
|
stateObject := s.getStateObject(addr)
|
||||||
|
if stateObject != nil {
|
||||||
|
value = stateObject.GetState(hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If in verkle transition and value not found, fallback to base state
|
||||||
|
if s.verkleTransitionActive && value == (common.Hash{}) {
|
||||||
|
return s.getStateFromBase(addr, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add method to access base state
|
||||||
|
func (s *StateDB) getStateFromBase(addr common.Address, hash common.Hash) common.Hash {
|
||||||
|
// Implementation depends on how Merkle states are accessed
|
||||||
|
// This is a simplified implementation for the PR
|
||||||
|
baseState, err := New(s.baseStateRoot, s.db)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to access base state", "error", err)
|
||||||
|
return common.Hash{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseState.GetState(addr, hash)
|
||||||
|
}
|
||||||
99
core/state/verkle_transition.go
Normal file
99
core/state/verkle_transition.go
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BlockToBaseStateRoot maps block hashes to their corresponding base Merkle state roots
|
||||||
|
// during the Verkle transition period to uniquely identify states
|
||||||
|
type BlockToBaseStateRoot struct {
|
||||||
|
blockHashToStateRoot map[common.Hash]common.Hash
|
||||||
|
mutex sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBlockToBaseStateRootMapping creates a new mapping instance
|
||||||
|
func NewBlockToBaseStateRootMapping() *BlockToBaseStateRoot {
|
||||||
|
return &BlockToBaseStateRoot{
|
||||||
|
blockHashToStateRoot: make(map[common.Hash]common.Hash),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add associates a block hash with its base state root
|
||||||
|
func (m *BlockToBaseStateRoot) Add(blockHash common.Hash, stateRoot common.Hash) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
m.blockHashToStateRoot[blockHash] = stateRoot
|
||||||
|
log.Debug("Added verkle transition mapping", "blockHash", blockHash, "baseStateRoot", stateRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves the base state root for a given block hash
|
||||||
|
func (m *BlockToBaseStateRoot) Get(blockHash common.Hash) (common.Hash, bool) {
|
||||||
|
m.mutex.RLock()
|
||||||
|
defer m.mutex.RUnlock()
|
||||||
|
|
||||||
|
root, exists := m.blockHashToStateRoot[blockHash]
|
||||||
|
return root, exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has checks if mapping exists for the given block hash
|
||||||
|
func (m *BlockToBaseStateRoot) Has(blockHash common.Hash) bool {
|
||||||
|
m.mutex.RLock()
|
||||||
|
defer m.mutex.RUnlock()
|
||||||
|
|
||||||
|
_, exists := m.blockHashToStateRoot[blockHash]
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store persists the mapping to the database
|
||||||
|
func (m *BlockToBaseStateRoot) Store(db ethdb.Database) error {
|
||||||
|
m.mutex.RLock()
|
||||||
|
defer m.mutex.RUnlock()
|
||||||
|
|
||||||
|
batch := db.NewBatch()
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
for blockHash, stateRoot := range m.blockHashToStateRoot {
|
||||||
|
key := append([]byte("verkle-base-state:"), blockHash.Bytes()...)
|
||||||
|
if err := batch.Put(key, stateRoot.Bytes()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := batch.Write(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Stored verkle transition mappings", "count", count)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load loads the mapping from the database
|
||||||
|
func LoadBlockToBaseStateRoot(db ethdb.Database) (*BlockToBaseStateRoot, error) {
|
||||||
|
mapping := NewBlockToBaseStateRootMapping()
|
||||||
|
|
||||||
|
it := db.NewIterator([]byte("verkle-base-state:"), nil)
|
||||||
|
defer it.Release()
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
for it.Next() {
|
||||||
|
key := it.Key()
|
||||||
|
blockHash := common.BytesToHash(key[len("verkle-base-state:"):])
|
||||||
|
stateRoot := common.BytesToHash(it.Value())
|
||||||
|
mapping.Add(blockHash, stateRoot)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := it.Error(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Loaded verkle transition mappings", "count", count)
|
||||||
|
return mapping, nil
|
||||||
|
}
|
||||||
110
core/state/verkle_transition_test.go
Normal file
110
core/state/verkle_transition_test.go
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBlockToBaseStateRootMapping(t *testing.T) {
|
||||||
|
// Create a new mapping
|
||||||
|
mapping := NewBlockToBaseStateRootMapping()
|
||||||
|
|
||||||
|
// Test data
|
||||||
|
blockHash1 := common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
|
||||||
|
stateRoot1 := common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
||||||
|
blockHash2 := common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222")
|
||||||
|
stateRoot2 := common.HexToHash("0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
|
||||||
|
|
||||||
|
// Test Add and Get
|
||||||
|
mapping.Add(blockHash1, stateRoot1)
|
||||||
|
mapping.Add(blockHash2, stateRoot2)
|
||||||
|
|
||||||
|
root, exists := mapping.Get(blockHash1)
|
||||||
|
if !exists {
|
||||||
|
t.Fatalf("Expected mapping to exist for blockHash1")
|
||||||
|
}
|
||||||
|
if root != stateRoot1 {
|
||||||
|
t.Fatalf("Expected stateRoot1, got %x", root)
|
||||||
|
}
|
||||||
|
|
||||||
|
root, exists = mapping.Get(blockHash2)
|
||||||
|
if !exists {
|
||||||
|
t.Fatalf("Expected mapping to exist for blockHash2")
|
||||||
|
}
|
||||||
|
if root != stateRoot2 {
|
||||||
|
t.Fatalf("Expected stateRoot2, got %x", root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Has
|
||||||
|
if !mapping.Has(blockHash1) {
|
||||||
|
t.Fatalf("Expected Has to return true for blockHash1")
|
||||||
|
}
|
||||||
|
if mapping.Has(common.HexToHash("0x3333")) {
|
||||||
|
t.Fatalf("Expected Has to return false for unknown hash")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Store and Load
|
||||||
|
db := memorydb.New()
|
||||||
|
err := mapping.Store(db)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to store mapping: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
loadedMapping, err := LoadBlockToBaseStateRoot(db)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to load mapping: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
root, exists = loadedMapping.Get(blockHash1)
|
||||||
|
if !exists {
|
||||||
|
t.Fatalf("Expected loaded mapping to contain blockHash1")
|
||||||
|
}
|
||||||
|
if root != stateRoot1 {
|
||||||
|
t.Fatalf("Expected stateRoot1 after loading, got %x", root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStateDBVerkleTransition(t *testing.T) {
|
||||||
|
// Create a test state
|
||||||
|
db := NewDatabase(memorydb.New())
|
||||||
|
baseState, _ := New(common.Hash{}, db, nil)
|
||||||
|
|
||||||
|
// Create base state with account1
|
||||||
|
addr1 := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
||||||
|
key1 := common.HexToHash("0xaaaa")
|
||||||
|
value1 := common.HexToHash("0xbbbb")
|
||||||
|
baseState.SetState(addr1, key1, value1)
|
||||||
|
baseRoot, _ := baseState.Commit(false)
|
||||||
|
|
||||||
|
// Create new verkle state with account2
|
||||||
|
statedb, _ := New(common.Hash{}, db, nil)
|
||||||
|
statedb.SetVerkleTransitionData(common.HexToHash("0xblock"), baseRoot)
|
||||||
|
|
||||||
|
addr2 := common.HexToAddress("0x2222222222222222222222222222222222222222")
|
||||||
|
key2 := common.HexToHash("0xcccc")
|
||||||
|
value2 := common.HexToHash("0xdddd")
|
||||||
|
statedb.SetState(addr2, key2, value2)
|
||||||
|
|
||||||
|
// Test fallback to base state
|
||||||
|
retrievedValue1 := statedb.GetState(addr1, key1)
|
||||||
|
if retrievedValue1 != value1 {
|
||||||
|
t.Fatalf("Expected fallback to base state to return correct value, got %x", retrievedValue1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test current state access
|
||||||
|
retrievedValue2 := statedb.GetState(addr2, key2)
|
||||||
|
if retrievedValue2 != value2 {
|
||||||
|
t.Fatalf("Expected current state access to return correct value, got %x", retrievedValue2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check state properties
|
||||||
|
if !statedb.IsVerkleTransitionActive() {
|
||||||
|
t.Fatalf("Expected IsVerkleTransitionActive to return true")
|
||||||
|
}
|
||||||
|
|
||||||
|
if statedb.BaseStateRoot() != baseRoot {
|
||||||
|
t.Fatalf("Expected BaseStateRoot to return correct root")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue