123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- package mps
- import (
- "math/big"
- "sync"
- "testing"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/privatecache"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/stretchr/testify/assert"
- )
- //TestMultiplePSRCopy tests that copying a the PSR object indeed makes the original and
- // the copy and their corresponding managed states independent of each other.
- func TestMultiplePSRCopy(t *testing.T) {
- testdb := rawdb.NewMemoryDatabase()
- testCache := state.NewDatabase(testdb)
- privateCacheProvider := privatecache.NewPrivateCacheProvider(testdb, nil, testCache, false)
- psr, _ := NewMultiplePrivateStateRepository(testdb, testCache, common.Hash{}, privateCacheProvider)
- testState, _ := psr.StatePSI(types.PrivateStateIdentifier("test"))
- privState, _ := psr.StatePSI(types.DefaultPrivateStateIdentifier)
- for i := byte(0); i < 255; i++ {
- addr := common.BytesToAddress([]byte{i})
- testState.AddBalance(addr, big.NewInt(int64(i)))
- }
- testState.Finalise(false)
- for i := byte(0); i < 255; i++ {
- addr := common.BytesToAddress([]byte{i})
- privState.AddBalance(addr, big.NewInt(int64(i)))
- }
- privState.Finalise(false)
- psrCopy := psr.Copy().(*MultiplePrivateStateRepository)
- testStateCopy, _ := psrCopy.StatePSI(types.PrivateStateIdentifier("test"))
- privStateCopy, _ := psrCopy.StatePSI(types.DefaultPrivateStateIdentifier)
- addedState, _ := psrCopy.StatePSI(types.PrivateStateIdentifier("added"))
- // modify all in memory
- for i := byte(0); i < 255; i++ {
- testState.AddBalance(common.BytesToAddress([]byte{i}), big.NewInt(2*int64(i)))
- privState.AddBalance(common.BytesToAddress([]byte{i}), big.NewInt(2*int64(i)))
- testStateCopy.AddBalance(common.BytesToAddress([]byte{i}), big.NewInt(3*int64(i)))
- privStateCopy.AddBalance(common.BytesToAddress([]byte{i}), big.NewInt(3*int64(i)))
- addedState.AddBalance(common.BytesToAddress([]byte{i}), big.NewInt(3*int64(i)))
- }
- // Finalise the changes on all concurrently
- finalise := func(wg *sync.WaitGroup, db *state.StateDB) {
- defer wg.Done()
- db.Finalise(true)
- }
- var wg sync.WaitGroup
- wg.Add(5)
- go finalise(&wg, testState)
- go finalise(&wg, testStateCopy)
- go finalise(&wg, privState)
- go finalise(&wg, privStateCopy)
- go finalise(&wg, addedState)
- wg.Wait()
- //copies contain correct managed states
- assert.Contains(t, psr.managedStates, types.EmptyPrivateStateIdentifier)
- assert.Contains(t, psr.managedStates, types.DefaultPrivateStateIdentifier)
- assert.Contains(t, psr.managedStates, types.PrivateStateIdentifier("test"))
- assert.NotContains(t, psr.managedStates, types.PrivateStateIdentifier("added"))
- assert.Contains(t, psrCopy.managedStates, types.EmptyPrivateStateIdentifier)
- assert.Contains(t, psrCopy.managedStates, types.DefaultPrivateStateIdentifier)
- assert.Contains(t, psrCopy.managedStates, types.PrivateStateIdentifier("test"))
- assert.Contains(t, psrCopy.managedStates, types.PrivateStateIdentifier("added"))
- assert.Equal(t, psr.db, psrCopy.db)
- assert.Equal(t, psr.repoCache, psrCopy.repoCache)
- assert.NotEqual(t, psr.trie, psrCopy.trie)
- // Verify that the all states have been updated independently
- for i := byte(0); i < 255; i++ {
- addr := common.BytesToAddress([]byte{i})
- testObj := testState.GetOrNewStateObject(addr)
- testCopyObj := testStateCopy.GetOrNewStateObject(addr)
- privObj := privState.GetOrNewStateObject(addr)
- privCopyObj := privStateCopy.GetOrNewStateObject(addr)
- addedObj := addedState.GetOrNewStateObject(addr)
- if want := big.NewInt(3 * int64(i)); testObj.Balance().Cmp(want) != 0 {
- t.Errorf("empty obj %d: balance mismatch: have %v, want %v", i, testObj.Balance(), want)
- }
- if want := big.NewInt(3 * int64(i)); privObj.Balance().Cmp(want) != 0 {
- t.Errorf("priv obj %d: balance mismatch: have %v, want %v", i, privObj.Balance(), want)
- }
- if want := big.NewInt(4 * int64(i)); testCopyObj.Balance().Cmp(want) != 0 {
- t.Errorf("empty copy obj %d: balance mismatch: have %v, want %v", i, testCopyObj.Balance(), want)
- }
- if want := big.NewInt(4 * int64(i)); privCopyObj.Balance().Cmp(want) != 0 {
- t.Errorf("priv copy obj %d: balance mismatch: have %v, want %v", i, privCopyObj.Balance(), want)
- }
- if want := big.NewInt(3 * int64(i)); addedObj.Balance().Cmp(want) != 0 {
- t.Errorf("added obj %d: balance mismatch: have %v, want %v", i, addedObj.Balance(), want)
- }
- }
- }
- //TestMultiplePSRReset tests that state objects are cleared from all managedState statedbs after reset call
- //Any updated stateObjects not committed to statedbs before reset will be cleared
- func TestMultiplePSRReset(t *testing.T) {
- testdb := rawdb.NewMemoryDatabase()
- testCache := state.NewDatabase(testdb)
- privateCacheProvider := privatecache.NewPrivateCacheProvider(testdb, nil, testCache, false)
- psr, _ := NewMultiplePrivateStateRepository(testdb, testCache, common.Hash{}, privateCacheProvider)
- testState, _ := psr.StatePSI(types.PrivateStateIdentifier("test"))
- emptyState, _ := psr.StatePSI(types.EmptyPrivateStateIdentifier)
- addr := common.BytesToAddress([]byte{254})
- testState.AddBalance(addr, big.NewInt(int64(254)))
- emptyState.AddBalance(addr, big.NewInt(int64(254)))
- // have something to revert to (rather than the empty trie of private states)
- psr.CommitAndWrite(false, types.NewBlockWithHeader(&types.Header{Root: common.Hash{}}))
- // testState2 should branch from the emptyState - so it should contain the contract with address 254...
- testState2, _ := psr.StatePSI(types.PrivateStateIdentifier("test2"))
- for i := byte(0); i < 254; i++ {
- addr := common.BytesToAddress([]byte{i})
- testState.AddBalance(addr, big.NewInt(int64(i)))
- testState2.AddBalance(addr, big.NewInt(int64(i)))
- emptyState.AddBalance(addr, big.NewInt(int64(i)))
- }
- testState.Finalise(false)
- testState2.Finalise(false)
- emptyState.Finalise(false)
- for i := byte(0); i < 255; i++ {
- addr := common.BytesToAddress([]byte{i})
- assert.True(t, testState.Exist(addr))
- assert.True(t, testState2.Exist(addr))
- assert.True(t, emptyState.Exist(addr))
- }
- psr.Reset()
- // test2 is no longer there in the managed states after reset
- assert.Contains(t, psr.managedStates, types.PrivateStateIdentifier("test"))
- assert.NotContains(t, psr.managedStates, types.PrivateStateIdentifier("test2"))
- assert.Contains(t, psr.managedStates, types.EmptyPrivateStateIdentifier)
- for i := byte(0); i < 254; i++ {
- addr := common.BytesToAddress([]byte{i})
- assert.False(t, testState.Exist(addr))
- assert.False(t, emptyState.Exist(addr))
- }
- addr = common.BytesToAddress([]byte{254})
- assert.True(t, testState.Exist(addr))
- assert.True(t, emptyState.Exist(addr))
- }
- //TestCreatingManagedStates tests that managed states are created and added to managedState map
- func TestCreatingManagedStates(t *testing.T) {
- testdb := rawdb.NewMemoryDatabase()
- testCache := state.NewDatabase(testdb)
- privateCacheProvider := privatecache.NewPrivateCacheProvider(testdb, nil, testCache, false)
- psr, _ := NewMultiplePrivateStateRepository(testdb, testCache, common.Hash{}, privateCacheProvider)
- //create some managed states
- psr.DefaultState()
- psr.StatePSI(types.PrivateStateIdentifier("test"))
- psr.StatePSI(types.DefaultPrivateStateIdentifier)
- //check if they exist in managedStates map
- assert.Contains(t, psr.managedStates, types.EmptyPrivateStateIdentifier)
- assert.Contains(t, psr.managedStates, types.DefaultPrivateStateIdentifier)
- assert.Contains(t, psr.managedStates, types.PrivateStateIdentifier("test"))
- assert.NotContains(t, psr.managedStates, types.PrivateStateIdentifier("added"))
- }
- //TestMultiplePSRCommit tests that managedStates are updated, trie of states is updated but not written to db
- func TestMultiplePSRCommit(t *testing.T) {
- testdb := rawdb.NewMemoryDatabase()
- testCache := state.NewDatabase(testdb)
- privateCacheProvider := privatecache.NewPrivateCacheProvider(testdb, nil, testCache, false)
- psr, _ := NewMultiplePrivateStateRepository(testdb, testCache, common.Hash{}, privateCacheProvider)
- header := &types.Header{Number: big.NewInt(int64(1)), Root: common.Hash{123}}
- block := types.NewBlockWithHeader(header)
- testState, _ := psr.StatePSI(types.PrivateStateIdentifier("test"))
- privState, _ := psr.StatePSI(types.DefaultPrivateStateIdentifier)
- //states have empty tries first
- testRoot := testState.IntermediateRoot(false)
- privRoot := privState.IntermediateRoot(false)
- assert.Equal(t, testRoot, emptyRoot)
- assert.Equal(t, privRoot, emptyRoot)
- //make updates to states
- for i := byte(0); i < 255; i++ {
- addr := common.BytesToAddress([]byte{i})
- testState.AddBalance(addr, big.NewInt(int64(i)))
- privState.AddBalance(addr, big.NewInt(int64(i)))
- }
- assert.Equal(t, rawdb.GetPrivateStatesTrieRoot(testdb, block.Root()), common.Hash{})
- psr.Commit(false, block)
- //trie root updated but not committed to db
- assert.NotEqual(t, psr.trie.Hash(), common.Hash{})
- assert.Equal(t, rawdb.GetPrivateStatesTrieRoot(testdb, block.Root()), common.Hash{})
- privateKey, _ := psr.trie.TryGet([]byte(types.DefaultPrivateStateIdentifier))
- assert.NotEqual(t, len(privateKey), 0)
- testKey, _ := psr.trie.TryGet([]byte(types.PrivateStateIdentifier("test")))
- assert.NotEqual(t, len(testKey), 0)
- emptyKey, _ := psr.trie.TryGet([]byte(types.EmptyPrivateStateIdentifier))
- assert.NotEqual(t, len(emptyKey), 0)
- notKey, _ := psr.trie.TryGet([]byte(types.PrivateStateIdentifier("notKey")))
- assert.Equal(t, len(notKey), 0)
- //managed state tries updated
- testRoot = testState.IntermediateRoot(false)
- privRoot = privState.IntermediateRoot(false)
- assert.NotEqual(t, testRoot, emptyRoot)
- assert.NotEqual(t, privRoot, emptyRoot)
- }
- //TestMultiplePSRCommitAndWrite tests that managedStates are updated, trie of states is updated and written to db
- func TestMultiplePSRCommitAndWrite(t *testing.T) {
- testdb := rawdb.NewMemoryDatabase()
- testCache := state.NewDatabase(testdb)
- privateCacheProvider := privatecache.NewPrivateCacheProvider(testdb, nil, testCache, false)
- psr, _ := NewMultiplePrivateStateRepository(testdb, testCache, common.Hash{}, privateCacheProvider)
- header := &types.Header{Number: big.NewInt(int64(1)), Root: common.Hash{123}}
- block := types.NewBlockWithHeader(header)
- testState, _ := psr.StatePSI(types.PrivateStateIdentifier("test"))
- privState, _ := psr.StatePSI(types.DefaultPrivateStateIdentifier)
- //states have empty tries first
- testRoot := testState.IntermediateRoot(false)
- privRoot := privState.IntermediateRoot(false)
- assert.Equal(t, testRoot, emptyRoot)
- assert.Equal(t, privRoot, emptyRoot)
- //make updates to states
- for i := byte(0); i < 255; i++ {
- addr := common.BytesToAddress([]byte{i})
- testState.AddBalance(addr, big.NewInt(int64(i)))
- privState.AddBalance(addr, big.NewInt(int64(i)))
- }
- assert.Equal(t, rawdb.GetPrivateStatesTrieRoot(testdb, block.Root()), common.Hash{})
- psr.CommitAndWrite(false, block)
- //trie root updated and committed to db
- assert.NotEqual(t, psr.trie.Hash(), common.Hash{})
- assert.NotEqual(t, rawdb.GetPrivateStatesTrieRoot(testdb, block.Root()), common.Hash{})
- privateKey, _ := psr.trie.TryGet([]byte(types.DefaultPrivateStateIdentifier))
- assert.NotEqual(t, len(privateKey), 0)
- testKey, _ := psr.trie.TryGet([]byte(types.PrivateStateIdentifier("test")))
- assert.NotEqual(t, len(testKey), 0)
- emptyKey, _ := psr.trie.TryGet([]byte(types.EmptyPrivateStateIdentifier))
- assert.NotEqual(t, len(emptyKey), 0)
- notKey, _ := psr.trie.TryGet([]byte(types.PrivateStateIdentifier("notKey")))
- assert.Equal(t, len(notKey), 0)
- //managed state tries updated
- testRoot = testState.IntermediateRoot(false)
- privRoot = privState.IntermediateRoot(false)
- assert.NotEqual(t, testRoot, emptyRoot)
- assert.NotEqual(t, privRoot, emptyRoot)
- }
- //TestMultiplePSRIntroduceNewPrivateState tests that a newly introduced private state is branched from the empty state and maintained accordingly
- func TestMultiplePSRIntroduceNewPrivateState(t *testing.T) {
- testPS1 := types.PrivateStateIdentifier("PS1")
- testPS2 := types.PrivateStateIdentifier("PS2")
- testdb := rawdb.NewMemoryDatabase()
- testCache := state.NewDatabase(testdb)
- privateCacheProvider := privatecache.NewPrivateCacheProvider(testdb, nil, testCache, false)
- psr, _ := NewMultiplePrivateStateRepository(testdb, testCache, common.Hash{}, privateCacheProvider)
- header1 := &types.Header{Number: big.NewInt(int64(1)), Root: common.Hash{123}}
- block1 := types.NewBlockWithHeader(header1)
- header2 := &types.Header{Number: big.NewInt(int64(2)), Root: common.Hash{124}}
- block2 := types.NewBlockWithHeader(header2)
- testState1, _ := psr.StatePSI(testPS1)
- emptyState, _ := psr.StatePSI(types.EmptyPrivateStateIdentifier)
- //states have empty tries first
- testState1Root := testState1.IntermediateRoot(false)
- emptyStateRoot := emptyState.IntermediateRoot(false)
- assert.Equal(t, testState1Root, emptyRoot)
- assert.Equal(t, emptyStateRoot, emptyRoot)
- //make updates to states
- for i := byte(0); i < 10; i++ {
- addr := common.BytesToAddress([]byte{i})
- testState1.AddBalance(addr, big.NewInt(int64(i)))
- emptyState.AddBalance(addr, big.NewInt(int64(i)))
- }
- assert.Equal(t, rawdb.GetPrivateStatesTrieRoot(testdb, block1.Root()), common.Hash{})
- psr.CommitAndWrite(false, block1)
- //trie root updated and committed to db
- psrRootHash1 := psr.trie.Hash()
- assert.NotEqual(t, psrRootHash1, emptyRoot)
- assert.Equal(t, rawdb.GetPrivateStatesTrieRoot(testdb, block1.Root()), psrRootHash1)
- emptyStateRootHash, _ := psr.trie.TryGet([]byte(types.EmptyPrivateStateIdentifier))
- assert.NotEqual(t, len(emptyStateRootHash), 0)
- ps1RootHash, _ := psr.trie.TryGet([]byte(testPS1))
- assert.NotEqual(t, len(ps1RootHash), 0)
- notKeyRootHash, _ := psr.trie.TryGet([]byte(types.PrivateStateIdentifier("notKey")))
- assert.Equal(t, len(notKeyRootHash), 0)
- //managed state tries updated
- testState1Root = testState1.IntermediateRoot(false)
- emptyStateRoot = emptyState.IntermediateRoot(false)
- assert.NotEqual(t, testState1Root, emptyRoot)
- assert.NotEqual(t, emptyStateRoot, emptyRoot)
- // begin adding state at block2
- psr, _ = NewMultiplePrivateStateRepository(testdb, testCache, rawdb.GetPrivateStatesTrieRoot(testdb, block1.Root()), privateCacheProvider)
- testState1, _ = psr.StatePSI(testPS1)
- testState2, _ := psr.StatePSI(testPS2)
- emptyState, _ = psr.StatePSI(types.EmptyPrivateStateIdentifier)
- //make updates to states
- for i := byte(10); i < 20; i++ {
- addr := common.BytesToAddress([]byte{i})
- testState1.AddBalance(addr, big.NewInt(int64(i)))
- testState2.AddBalance(addr, big.NewInt(int64(i)))
- emptyState.AddBalance(addr, big.NewInt(int64(i)))
- }
- psr.CommitAndWrite(false, block2)
- psr, _ = NewMultiplePrivateStateRepository(testdb, testCache, rawdb.GetPrivateStatesTrieRoot(testdb, block2.Root()), privateCacheProvider)
- testState1, _ = psr.StatePSI(testPS1)
- testState2, _ = psr.StatePSI(testPS2)
- emptyState, _ = psr.StatePSI(types.EmptyPrivateStateIdentifier)
- // we've only added addresses from 10 to 20 to testState2 but since it branched from emptyState it should also contain addresses from 0 to 10
- for i := byte(0); i < 20; i++ {
- addr := common.BytesToAddress([]byte{i})
- assert.True(t, testState1.Exist(addr))
- assert.True(t, testState2.Exist(addr))
- assert.True(t, emptyState.Exist(addr))
- }
- // check that PS2 does not exist in the PSR at block1 height
- psr, _ = NewMultiplePrivateStateRepository(testdb, testCache, rawdb.GetPrivateStatesTrieRoot(testdb, block1.Root()), privateCacheProvider)
- emptyStateRootHash, _ = psr.trie.TryGet([]byte(types.EmptyPrivateStateIdentifier))
- assert.NotEqual(t, len(emptyStateRootHash), 0)
- ps1RootHash, _ = psr.trie.TryGet([]byte(testPS1))
- assert.NotEqual(t, len(ps1RootHash), 0)
- ps2RootHash, _ := psr.trie.TryGet([]byte(testPS2))
- assert.Equal(t, len(ps2RootHash), 0)
- // check that PS2 does exist in the PSR at block2 height
- psr, _ = NewMultiplePrivateStateRepository(testdb, testCache, rawdb.GetPrivateStatesTrieRoot(testdb, block2.Root()), privateCacheProvider)
- emptyStateRootHash, _ = psr.trie.TryGet([]byte(types.EmptyPrivateStateIdentifier))
- assert.NotEqual(t, len(emptyStateRootHash), 0)
- ps1RootHash, _ = psr.trie.TryGet([]byte(testPS1))
- assert.NotEqual(t, len(ps1RootHash), 0)
- ps2RootHash, _ = psr.trie.TryGet([]byte(testPS2))
- assert.NotEqual(t, len(ps2RootHash), 0)
- }
- //TestMultiplePSRRemovalFromPrivateState tests that exist no longer picks suicided accounts
- func TestMultiplePSRRemovalFromPrivateState(t *testing.T) {
- testPS1 := types.PrivateStateIdentifier("PS1")
- testdb := rawdb.NewMemoryDatabase()
- testCache := state.NewDatabase(testdb)
- privateCacheProvider := privatecache.NewPrivateCacheProvider(testdb, nil, testCache, false)
- psr, _ := NewMultiplePrivateStateRepository(testdb, testCache, common.Hash{}, privateCacheProvider)
- header1 := &types.Header{Number: big.NewInt(int64(1)), Root: common.Hash{123}}
- block1 := types.NewBlockWithHeader(header1)
- header2 := &types.Header{Number: big.NewInt(int64(2)), Root: common.Hash{124}}
- block2 := types.NewBlockWithHeader(header2)
- testState1, _ := psr.StatePSI(testPS1)
- emptyState, _ := psr.StatePSI(types.EmptyPrivateStateIdentifier)
- //make updates to states
- for i := byte(0); i < 10; i++ {
- addr := common.BytesToAddress([]byte{i})
- testState1.AddBalance(addr, big.NewInt(int64(i)))
- emptyState.AddBalance(addr, big.NewInt(int64(i)))
- }
- assert.Equal(t, rawdb.GetPrivateStatesTrieRoot(testdb, block1.Root()), common.Hash{})
- psr.CommitAndWrite(false, block1)
- psr, _ = NewMultiplePrivateStateRepository(testdb, testCache, rawdb.GetPrivateStatesTrieRoot(testdb, block1.Root()), privateCacheProvider)
- testState1, _ = psr.StatePSI(testPS1)
- emptyState, _ = psr.StatePSI(types.EmptyPrivateStateIdentifier)
- removedAddress := common.BytesToAddress([]byte{1})
- testState1.Suicide(removedAddress)
- psr.CommitAndWrite(false, block2)
- psr, _ = NewMultiplePrivateStateRepository(testdb, testCache, rawdb.GetPrivateStatesTrieRoot(testdb, block2.Root()), privateCacheProvider)
- testState1, _ = psr.StatePSI(testPS1)
- emptyState, _ = psr.StatePSI(types.EmptyPrivateStateIdentifier)
- assert.False(t, testState1.Exist(removedAddress))
- assert.True(t, emptyState.Exist(removedAddress))
- }
|