@@ -715,3 +715,160 @@ func TestCopyOfCopy(t *testing.T) {
715715 t .Fatalf ("2nd copy fail, expected 42, got %v" , got )
716716 }
717717}
718+
719+ // Tests a regression where committing a copy lost some internal meta information,
720+ // leading to corrupted subsequent copies.
721+ //
722+ // See https://github.com/ethereum/go-ethereum/issues/20106.
723+ func TestCopyCommitCopy (t * testing.T ) {
724+ state , _ := New (common.Hash {}, NewDatabase (rawdb .NewMemoryDatabase ()))
725+
726+ // Create an account and check if the retrieved balance is correct
727+ addr := common .HexToAddress ("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe" )
728+ skey := common .HexToHash ("aaa" )
729+ sval := common .HexToHash ("bbb" )
730+
731+ state .SetBalance (addr , big .NewInt (42 )) // Change the account trie
732+ state .SetCode (addr , []byte ("hello" )) // Change an external metadata
733+ state .SetState (addr , skey , sval ) // Change the storage trie
734+
735+ if balance := state .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
736+ t .Fatalf ("initial balance mismatch: have %v, want %v" , balance , 42 )
737+ }
738+ if code := state .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
739+ t .Fatalf ("initial code mismatch: have %x, want %x" , code , []byte ("hello" ))
740+ }
741+ if val := state .GetState (addr , skey ); val != sval {
742+ t .Fatalf ("initial non-committed storage slot mismatch: have %x, want %x" , val , sval )
743+ }
744+ if val := state .GetCommittedState (addr , skey ); val != (common.Hash {}) {
745+ t .Fatalf ("initial committed storage slot mismatch: have %x, want %x" , val , common.Hash {})
746+ }
747+ // Copy the non-committed state database and check pre/post commit balance
748+ copyOne := state .Copy ()
749+ if balance := copyOne .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
750+ t .Fatalf ("first copy pre-commit balance mismatch: have %v, want %v" , balance , 42 )
751+ }
752+ if code := copyOne .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
753+ t .Fatalf ("first copy pre-commit code mismatch: have %x, want %x" , code , []byte ("hello" ))
754+ }
755+ if val := copyOne .GetState (addr , skey ); val != sval {
756+ t .Fatalf ("first copy pre-commit non-committed storage slot mismatch: have %x, want %x" , val , sval )
757+ }
758+ if val := copyOne .GetCommittedState (addr , skey ); val != (common.Hash {}) {
759+ t .Fatalf ("first copy pre-commit committed storage slot mismatch: have %x, want %x" , val , common.Hash {})
760+ }
761+
762+ copyOne .Commit (false )
763+ if balance := copyOne .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
764+ t .Fatalf ("first copy post-commit balance mismatch: have %v, want %v" , balance , 42 )
765+ }
766+ if code := copyOne .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
767+ t .Fatalf ("first copy post-commit code mismatch: have %x, want %x" , code , []byte ("hello" ))
768+ }
769+ if val := copyOne .GetState (addr , skey ); val != sval {
770+ t .Fatalf ("first copy post-commit non-committed storage slot mismatch: have %x, want %x" , val , sval )
771+ }
772+ if val := copyOne .GetCommittedState (addr , skey ); val != sval {
773+ t .Fatalf ("first copy post-commit committed storage slot mismatch: have %x, want %x" , val , sval )
774+ }
775+ // Copy the copy and check the balance once more
776+ copyTwo := copyOne .Copy ()
777+ if balance := copyTwo .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
778+ t .Fatalf ("second copy balance mismatch: have %v, want %v" , balance , 42 )
779+ }
780+ if code := copyTwo .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
781+ t .Fatalf ("second copy code mismatch: have %x, want %x" , code , []byte ("hello" ))
782+ }
783+ if val := copyTwo .GetState (addr , skey ); val != sval {
784+ t .Fatalf ("second copy non-committed storage slot mismatch: have %x, want %x" , val , sval )
785+ }
786+ if val := copyTwo .GetCommittedState (addr , skey ); val != sval {
787+ t .Fatalf ("second copy post-commit committed storage slot mismatch: have %x, want %x" , val , sval )
788+ }
789+ }
790+
791+ // Tests a regression where committing a copy lost some internal meta information,
792+ // leading to corrupted subsequent copies.
793+ //
794+ // See https://github.com/ethereum/go-ethereum/issues/20106.
795+ func TestCopyCopyCommitCopy (t * testing.T ) {
796+ state , _ := New (common.Hash {}, NewDatabase (rawdb .NewMemoryDatabase ()))
797+
798+ // Create an account and check if the retrieved balance is correct
799+ addr := common .HexToAddress ("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe" )
800+ skey := common .HexToHash ("aaa" )
801+ sval := common .HexToHash ("bbb" )
802+
803+ state .SetBalance (addr , big .NewInt (42 )) // Change the account trie
804+ state .SetCode (addr , []byte ("hello" )) // Change an external metadata
805+ state .SetState (addr , skey , sval ) // Change the storage trie
806+
807+ if balance := state .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
808+ t .Fatalf ("initial balance mismatch: have %v, want %v" , balance , 42 )
809+ }
810+ if code := state .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
811+ t .Fatalf ("initial code mismatch: have %x, want %x" , code , []byte ("hello" ))
812+ }
813+ if val := state .GetState (addr , skey ); val != sval {
814+ t .Fatalf ("initial non-committed storage slot mismatch: have %x, want %x" , val , sval )
815+ }
816+ if val := state .GetCommittedState (addr , skey ); val != (common.Hash {}) {
817+ t .Fatalf ("initial committed storage slot mismatch: have %x, want %x" , val , common.Hash {})
818+ }
819+ // Copy the non-committed state database and check pre/post commit balance
820+ copyOne := state .Copy ()
821+ if balance := copyOne .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
822+ t .Fatalf ("first copy balance mismatch: have %v, want %v" , balance , 42 )
823+ }
824+ if code := copyOne .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
825+ t .Fatalf ("first copy code mismatch: have %x, want %x" , code , []byte ("hello" ))
826+ }
827+ if val := copyOne .GetState (addr , skey ); val != sval {
828+ t .Fatalf ("first copy non-committed storage slot mismatch: have %x, want %x" , val , sval )
829+ }
830+ if val := copyOne .GetCommittedState (addr , skey ); val != (common.Hash {}) {
831+ t .Fatalf ("first copy committed storage slot mismatch: have %x, want %x" , val , common.Hash {})
832+ }
833+ // Copy the copy and check the balance once more
834+ copyTwo := copyOne .Copy ()
835+ if balance := copyTwo .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
836+ t .Fatalf ("second copy pre-commit balance mismatch: have %v, want %v" , balance , 42 )
837+ }
838+ if code := copyTwo .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
839+ t .Fatalf ("second copy pre-commit code mismatch: have %x, want %x" , code , []byte ("hello" ))
840+ }
841+ if val := copyTwo .GetState (addr , skey ); val != sval {
842+ t .Fatalf ("second copy pre-commit non-committed storage slot mismatch: have %x, want %x" , val , sval )
843+ }
844+ if val := copyTwo .GetCommittedState (addr , skey ); val != (common.Hash {}) {
845+ t .Fatalf ("second copy pre-commit committed storage slot mismatch: have %x, want %x" , val , common.Hash {})
846+ }
847+ copyTwo .Commit (false )
848+ if balance := copyTwo .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
849+ t .Fatalf ("second copy post-commit balance mismatch: have %v, want %v" , balance , 42 )
850+ }
851+ if code := copyTwo .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
852+ t .Fatalf ("second copy post-commit code mismatch: have %x, want %x" , code , []byte ("hello" ))
853+ }
854+ if val := copyTwo .GetState (addr , skey ); val != sval {
855+ t .Fatalf ("second copy post-commit non-committed storage slot mismatch: have %x, want %x" , val , sval )
856+ }
857+ if val := copyTwo .GetCommittedState (addr , skey ); val != sval {
858+ t .Fatalf ("second copy post-commit committed storage slot mismatch: have %x, want %x" , val , sval )
859+ }
860+ // Copy the copy-copy and check the balance once more
861+ copyThree := copyTwo .Copy ()
862+ if balance := copyThree .GetBalance (addr ); balance .Cmp (big .NewInt (42 )) != 0 {
863+ t .Fatalf ("third copy balance mismatch: have %v, want %v" , balance , 42 )
864+ }
865+ if code := copyThree .GetCode (addr ); ! bytes .Equal (code , []byte ("hello" )) {
866+ t .Fatalf ("third copy code mismatch: have %x, want %x" , code , []byte ("hello" ))
867+ }
868+ if val := copyThree .GetState (addr , skey ); val != sval {
869+ t .Fatalf ("third copy non-committed storage slot mismatch: have %x, want %x" , val , sval )
870+ }
871+ if val := copyThree .GetCommittedState (addr , skey ); val != sval {
872+ t .Fatalf ("third copy committed storage slot mismatch: have %x, want %x" , val , sval )
873+ }
874+ }
0 commit comments