@@ -28,6 +28,7 @@ import (
28
28
"sync"
29
29
"testing"
30
30
"testing/quick"
31
+ "time"
31
32
32
33
"github.com/ethereum/go-ethereum/common"
33
34
"github.com/ethereum/go-ethereum/core/rawdb"
@@ -915,3 +916,78 @@ func TestStateDBAccessList(t *testing.T) {
915
916
t .Fatalf ("expected empty, got %d" , got )
916
917
}
917
918
}
919
+
920
+ func TestIntermediateUpdateConcurrently (t * testing.T ) {
921
+ rng := rand .New (rand .NewSource (time .Now ().Unix ()))
922
+ // Create an empty state
923
+ db1 := rawdb .NewMemoryDatabase ()
924
+ db2 := rawdb .NewMemoryDatabase ()
925
+ state1 , _ := New (common.Hash {}, NewDatabase (db1 ), nil )
926
+ state2 , _ := New (common.Hash {}, NewDatabase (db2 ), nil )
927
+
928
+ // Update it with random data
929
+ for i := int64 (0 ); i < 1000 ; i ++ {
930
+ addr := common .BigToAddress (big .NewInt (i ))
931
+ balance := big .NewInt (int64 (rng .Int63 ()))
932
+ nonce := rng .Uint64 ()
933
+ key := common .BigToHash (big .NewInt (int64 (rng .Int63 ())))
934
+ value := common .BigToHash (big .NewInt (int64 (rng .Int63 ())))
935
+ code := []byte {byte (rng .Uint64 ()), byte (rng .Uint64 ()), byte (rng .Uint64 ())}
936
+ state1 .SetBalance (addr , balance )
937
+ state2 .SetBalance (addr , balance )
938
+ state1 .SetNonce (addr , nonce )
939
+ state2 .SetNonce (addr , nonce )
940
+ state1 .SetState (addr , key , value )
941
+ state2 .SetState (addr , key , value )
942
+ state1 .SetCode (addr , code )
943
+ state2 .SetCode (addr , code )
944
+ }
945
+
946
+ state1 .ConcurrentUpdateThreshold = 0
947
+ state2 .ConcurrentUpdateThreshold = 1
948
+
949
+ state1 .IntermediateRoot (false ) // sequential
950
+ state2 .IntermediateRoot (false ) // concurrent
951
+
952
+ root1 , err1 := state1 .Commit (false )
953
+ root2 , err2 := state2 .Commit (false )
954
+
955
+ if err1 != nil {
956
+ t .Fatalf ("sequential commit failed: %v" , err1 )
957
+ }
958
+ if err1 = state1 .Database ().TrieDB ().Commit (root1 , false , nil ); err1 != nil {
959
+ t .Errorf ("cannot commit trie %v to persistent database" , root1 .Hex ())
960
+ }
961
+ if err2 != nil {
962
+ t .Fatalf ("concurrent commit failed: %v" , err2 )
963
+ }
964
+ if err2 = state2 .Database ().TrieDB ().Commit (root2 , false , nil ); err2 != nil {
965
+ t .Errorf ("cannot commit trie %v to persistent database" , root2 .Hex ())
966
+ }
967
+
968
+ it1 := db1 .NewIterator (nil , nil )
969
+ it2 := db2 .NewIterator (nil , nil )
970
+ for it1 .Next () {
971
+ if ! it2 .Next () {
972
+ t .Fatalf ("concurrent iterator ended prematurely" )
973
+ }
974
+ if ! bytes .Equal (it1 .Key (), it2 .Key ()) {
975
+ t .Fatalf ("concurrent iterator key mismatch: " + string (it1 .Key ()) + " != " + string (it2 .Key ()))
976
+ }
977
+ if ! bytes .Equal (it1 .Value (), it2 .Value ()) {
978
+ t .Fatalf ("concurrent iterator value mismatch: " + string (it1 .Value ()) + " != " + string (it2 .Value ()))
979
+ }
980
+ }
981
+ if it1 .Error () != nil {
982
+ t .Fatalf ("sequential iterator error: %v" , it1 .Error ())
983
+ }
984
+ if it2 .Error () != nil {
985
+ t .Fatalf ("concurrent iterator error: %v" , it2 .Error ())
986
+ }
987
+ if it1 .Next () {
988
+ t .Fatalf ("sequential iterator has extra data" )
989
+ }
990
+ if it2 .Next () {
991
+ t .Fatalf ("concurrent iterator has extra data" )
992
+ }
993
+ }
0 commit comments