github.com/ethereum/go-ethereum@v1.16.1/triedb/pathdb/states_test.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package pathdb
    18  
    19  import (
    20  	"bytes"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/rlp"
    26  )
    27  
    28  func TestStatesMerge(t *testing.T) {
    29  	a := newStates(
    30  		map[common.Hash][]byte{
    31  			{0xa}: {0xa0},
    32  			{0xb}: {0xb0},
    33  			{0xc}: {0xc0},
    34  		},
    35  		map[common.Hash]map[common.Hash][]byte{
    36  			{0xa}: {
    37  				common.Hash{0x1}: {0x10},
    38  				common.Hash{0x2}: {0x20},
    39  			},
    40  			{0xb}: {
    41  				common.Hash{0x1}: {0x10},
    42  			},
    43  			{0xc}: {
    44  				common.Hash{0x1}: {0x10},
    45  			},
    46  		},
    47  		false,
    48  	)
    49  	b := newStates(
    50  		map[common.Hash][]byte{
    51  			{0xa}: {0xa1},
    52  			{0xb}: {0xb1},
    53  			{0xc}: nil, // delete account
    54  		},
    55  		map[common.Hash]map[common.Hash][]byte{
    56  			{0xa}: {
    57  				common.Hash{0x1}: {0x11},
    58  				common.Hash{0x2}: nil, // delete slot
    59  				common.Hash{0x3}: {0x31},
    60  			},
    61  			{0xb}: {
    62  				common.Hash{0x1}: {0x11},
    63  			},
    64  			{0xc}: {
    65  				common.Hash{0x1}: nil, // delete slot
    66  			},
    67  		},
    68  		false,
    69  	)
    70  	a.merge(b)
    71  
    72  	blob, exist := a.account(common.Hash{0xa})
    73  	if !exist || !bytes.Equal(blob, []byte{0xa1}) {
    74  		t.Error("Unexpected value for account a")
    75  	}
    76  	blob, exist = a.account(common.Hash{0xb})
    77  	if !exist || !bytes.Equal(blob, []byte{0xb1}) {
    78  		t.Error("Unexpected value for account b")
    79  	}
    80  	blob, exist = a.account(common.Hash{0xc})
    81  	if !exist || len(blob) != 0 {
    82  		t.Error("Unexpected value for account c")
    83  	}
    84  	// unknown account
    85  	blob, exist = a.account(common.Hash{0xd})
    86  	if exist || len(blob) != 0 {
    87  		t.Error("Unexpected value for account d")
    88  	}
    89  
    90  	blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x1})
    91  	if !exist || !bytes.Equal(blob, []byte{0x11}) {
    92  		t.Error("Unexpected value for a's storage")
    93  	}
    94  	blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x2})
    95  	if !exist || len(blob) != 0 {
    96  		t.Error("Unexpected value for a's storage")
    97  	}
    98  	blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x3})
    99  	if !exist || !bytes.Equal(blob, []byte{0x31}) {
   100  		t.Error("Unexpected value for a's storage")
   101  	}
   102  	blob, exist = a.storage(common.Hash{0xb}, common.Hash{0x1})
   103  	if !exist || !bytes.Equal(blob, []byte{0x11}) {
   104  		t.Error("Unexpected value for b's storage")
   105  	}
   106  	blob, exist = a.storage(common.Hash{0xc}, common.Hash{0x1})
   107  	if !exist || len(blob) != 0 {
   108  		t.Error("Unexpected value for c's storage")
   109  	}
   110  
   111  	// unknown storage slots
   112  	blob, exist = a.storage(common.Hash{0xd}, common.Hash{0x1})
   113  	if exist || len(blob) != 0 {
   114  		t.Error("Unexpected value for d's storage")
   115  	}
   116  }
   117  
   118  func TestStatesRevert(t *testing.T) {
   119  	a := newStates(
   120  		map[common.Hash][]byte{
   121  			{0xa}: {0xa0},
   122  			{0xb}: {0xb0},
   123  			{0xc}: {0xc0},
   124  		},
   125  		map[common.Hash]map[common.Hash][]byte{
   126  			{0xa}: {
   127  				common.Hash{0x1}: {0x10},
   128  				common.Hash{0x2}: {0x20},
   129  			},
   130  			{0xb}: {
   131  				common.Hash{0x1}: {0x10},
   132  			},
   133  			{0xc}: {
   134  				common.Hash{0x1}: {0x10},
   135  			},
   136  		},
   137  		false,
   138  	)
   139  	b := newStates(
   140  		map[common.Hash][]byte{
   141  			{0xa}: {0xa1},
   142  			{0xb}: {0xb1},
   143  			{0xc}: nil,
   144  		},
   145  		map[common.Hash]map[common.Hash][]byte{
   146  			{0xa}: {
   147  				common.Hash{0x1}: {0x11},
   148  				common.Hash{0x2}: nil,
   149  				common.Hash{0x3}: {0x31},
   150  			},
   151  			{0xb}: {
   152  				common.Hash{0x1}: {0x11},
   153  			},
   154  			{0xc}: {
   155  				common.Hash{0x1}: nil,
   156  			},
   157  		},
   158  		false,
   159  	)
   160  	a.merge(b)
   161  	a.revertTo(
   162  		map[common.Hash][]byte{
   163  			{0xa}: {0xa0},
   164  			{0xb}: {0xb0},
   165  			{0xc}: {0xc0},
   166  		},
   167  		map[common.Hash]map[common.Hash][]byte{
   168  			{0xa}: {
   169  				common.Hash{0x1}: {0x10},
   170  				common.Hash{0x2}: {0x20},
   171  				common.Hash{0x3}: nil,
   172  			},
   173  			{0xb}: {
   174  				common.Hash{0x1}: {0x10},
   175  			},
   176  			{0xc}: {
   177  				common.Hash{0x1}: {0x10},
   178  			},
   179  		},
   180  	)
   181  
   182  	blob, exist := a.account(common.Hash{0xa})
   183  	if !exist || !bytes.Equal(blob, []byte{0xa0}) {
   184  		t.Error("Unexpected value for account a")
   185  	}
   186  	blob, exist = a.account(common.Hash{0xb})
   187  	if !exist || !bytes.Equal(blob, []byte{0xb0}) {
   188  		t.Error("Unexpected value for account b")
   189  	}
   190  	blob, exist = a.account(common.Hash{0xc})
   191  	if !exist || !bytes.Equal(blob, []byte{0xc0}) {
   192  		t.Error("Unexpected value for account c")
   193  	}
   194  	// unknown account
   195  	blob, exist = a.account(common.Hash{0xd})
   196  	if exist || len(blob) != 0 {
   197  		t.Error("Unexpected value for account d")
   198  	}
   199  
   200  	blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x1})
   201  	if !exist || !bytes.Equal(blob, []byte{0x10}) {
   202  		t.Error("Unexpected value for a's storage")
   203  	}
   204  	blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x2})
   205  	if !exist || !bytes.Equal(blob, []byte{0x20}) {
   206  		t.Error("Unexpected value for a's storage")
   207  	}
   208  	blob, exist = a.storage(common.Hash{0xa}, common.Hash{0x3})
   209  	if !exist || len(blob) != 0 {
   210  		t.Error("Unexpected value for a's storage")
   211  	}
   212  	blob, exist = a.storage(common.Hash{0xb}, common.Hash{0x1})
   213  	if !exist || !bytes.Equal(blob, []byte{0x10}) {
   214  		t.Error("Unexpected value for b's storage")
   215  	}
   216  	blob, exist = a.storage(common.Hash{0xc}, common.Hash{0x1})
   217  	if !exist || !bytes.Equal(blob, []byte{0x10}) {
   218  		t.Error("Unexpected value for c's storage")
   219  	}
   220  	// unknown storage slots
   221  	blob, exist = a.storage(common.Hash{0xd}, common.Hash{0x1})
   222  	if exist || len(blob) != 0 {
   223  		t.Error("Unexpected value for d's storage")
   224  	}
   225  }
   226  
   227  // TestStateRevertAccountNullMarker tests the scenario that account x did not exist
   228  // before and was created during transition w, reverting w will retain an x=nil
   229  // entry in the set.
   230  func TestStateRevertAccountNullMarker(t *testing.T) {
   231  	a := newStates(nil, nil, false) // empty initial state
   232  	b := newStates(
   233  		map[common.Hash][]byte{
   234  			{0xa}: {0xa},
   235  		},
   236  		nil,
   237  		false,
   238  	)
   239  	a.merge(b) // create account 0xa
   240  	a.revertTo(
   241  		map[common.Hash][]byte{
   242  			{0xa}: nil,
   243  		},
   244  		nil,
   245  	) // revert the transition b
   246  
   247  	blob, exist := a.account(common.Hash{0xa})
   248  	if !exist {
   249  		t.Fatal("null marker is not found")
   250  	}
   251  	if len(blob) != 0 {
   252  		t.Fatalf("Unexpected value for account, %v", blob)
   253  	}
   254  }
   255  
   256  // TestStateRevertStorageNullMarker tests the scenario that slot x did not exist
   257  // before and was created during transition w, reverting w will retain an x=nil
   258  // entry in the set.
   259  func TestStateRevertStorageNullMarker(t *testing.T) {
   260  	a := newStates(map[common.Hash][]byte{
   261  		{0xa}: {0xa},
   262  	}, nil, false) // initial state with account 0xa
   263  
   264  	b := newStates(
   265  		nil,
   266  		map[common.Hash]map[common.Hash][]byte{
   267  			{0xa}: {
   268  				common.Hash{0x1}: {0x1},
   269  			},
   270  		},
   271  		false,
   272  	)
   273  	a.merge(b) // create slot 0x1
   274  	a.revertTo(
   275  		nil,
   276  		map[common.Hash]map[common.Hash][]byte{
   277  			{0xa}: {
   278  				common.Hash{0x1}: nil,
   279  			},
   280  		},
   281  	) // revert the transition b
   282  
   283  	blob, exist := a.storage(common.Hash{0xa}, common.Hash{0x1})
   284  	if !exist {
   285  		t.Fatal("null marker is not found")
   286  	}
   287  	if len(blob) != 0 {
   288  		t.Fatalf("Unexpected value for storage slot, %v", blob)
   289  	}
   290  }
   291  
   292  func TestStatesEncode(t *testing.T) {
   293  	testStatesEncode(t, false)
   294  	testStatesEncode(t, true)
   295  }
   296  
   297  func testStatesEncode(t *testing.T, rawStorageKey bool) {
   298  	s := newStates(
   299  		map[common.Hash][]byte{
   300  			{0x1}: {0x1},
   301  		},
   302  		map[common.Hash]map[common.Hash][]byte{
   303  			{0x1}: {
   304  				common.Hash{0x1}: {0x1},
   305  			},
   306  		},
   307  		rawStorageKey,
   308  	)
   309  	buf := bytes.NewBuffer(nil)
   310  	if err := s.encode(buf); err != nil {
   311  		t.Fatalf("Failed to encode states, %v", err)
   312  	}
   313  	var dec stateSet
   314  	if err := dec.decode(rlp.NewStream(buf, 0)); err != nil {
   315  		t.Fatalf("Failed to decode states, %v", err)
   316  	}
   317  	if !reflect.DeepEqual(s.accountData, dec.accountData) {
   318  		t.Fatal("Unexpected account data")
   319  	}
   320  	if !reflect.DeepEqual(s.storageData, dec.storageData) {
   321  		t.Fatal("Unexpected storage data")
   322  	}
   323  	if s.rawStorageKey != dec.rawStorageKey {
   324  		t.Fatal("Unexpected rawStorageKey flag")
   325  	}
   326  }
   327  
   328  func TestStateWithOriginEncode(t *testing.T) {
   329  	testStateWithOriginEncode(t, false)
   330  	testStateWithOriginEncode(t, true)
   331  }
   332  
   333  func testStateWithOriginEncode(t *testing.T, rawStorageKey bool) {
   334  	s := NewStateSetWithOrigin(
   335  		map[common.Hash][]byte{
   336  			{0x1}: {0x1},
   337  		},
   338  		map[common.Hash]map[common.Hash][]byte{
   339  			{0x1}: {
   340  				common.Hash{0x1}: {0x1},
   341  			},
   342  		},
   343  		map[common.Address][]byte{
   344  			{0x1}: {0x1},
   345  		},
   346  		map[common.Address]map[common.Hash][]byte{
   347  			{0x1}: {
   348  				common.Hash{0x1}: {0x1},
   349  			},
   350  		},
   351  		rawStorageKey,
   352  	)
   353  	buf := bytes.NewBuffer(nil)
   354  	if err := s.encode(buf); err != nil {
   355  		t.Fatalf("Failed to encode states, %v", err)
   356  	}
   357  	var dec StateSetWithOrigin
   358  	if err := dec.decode(rlp.NewStream(buf, 0)); err != nil {
   359  		t.Fatalf("Failed to decode states, %v", err)
   360  	}
   361  	if !reflect.DeepEqual(s.accountData, dec.accountData) {
   362  		t.Fatal("Unexpected account data")
   363  	}
   364  	if !reflect.DeepEqual(s.storageData, dec.storageData) {
   365  		t.Fatal("Unexpected storage data")
   366  	}
   367  	if !reflect.DeepEqual(s.accountOrigin, dec.accountOrigin) {
   368  		t.Fatal("Unexpected account origin data")
   369  	}
   370  	if !reflect.DeepEqual(s.storageOrigin, dec.storageOrigin) {
   371  		t.Fatal("Unexpected storage origin data")
   372  	}
   373  	if s.rawStorageKey != dec.rawStorageKey {
   374  		t.Fatal("Unexpected rawStorageKey flag")
   375  	}
   376  }
   377  
   378  func TestStateSizeTracking(t *testing.T) {
   379  	expSizeA := 3*(common.HashLength+1) + /* account data */
   380  		2*(2*common.HashLength+1) + /* storage data of 0xa */
   381  		2*common.HashLength + 3 + /* storage data of 0xb */
   382  		2*common.HashLength + 1 /* storage data of 0xc */
   383  
   384  	a := newStates(
   385  		map[common.Hash][]byte{
   386  			{0xa}: {0xa0}, // common.HashLength+1
   387  			{0xb}: {0xb0}, // common.HashLength+1
   388  			{0xc}: {0xc0}, // common.HashLength+1
   389  		},
   390  		map[common.Hash]map[common.Hash][]byte{
   391  			{0xa}: {
   392  				common.Hash{0x1}: {0x10}, // 2*common.HashLength+1
   393  				common.Hash{0x2}: {0x20}, // 2*common.HashLength+1
   394  			},
   395  			{0xb}: {
   396  				common.Hash{0x1}: {0x10, 0x11, 0x12}, // 2*common.HashLength+3
   397  			},
   398  			{0xc}: {
   399  				common.Hash{0x1}: {0x10}, // 2*common.HashLength+1
   400  			},
   401  		},
   402  		false,
   403  	)
   404  	if a.size != uint64(expSizeA) {
   405  		t.Fatalf("Unexpected size, want: %d, got: %d", expSizeA, a.size)
   406  	}
   407  
   408  	expSizeB := common.HashLength + 2 + common.HashLength + 3 + common.HashLength + /* account data */
   409  		2*common.HashLength + 3 + 2*common.HashLength + 2 + /* storage data of 0xa */
   410  		2*common.HashLength + 2 + 2*common.HashLength + 2 + /* storage data of 0xb */
   411  		3*2*common.HashLength /* storage data of 0xc */
   412  	b := newStates(
   413  		map[common.Hash][]byte{
   414  			{0xa}: {0xa1, 0xa1},       // common.HashLength+2
   415  			{0xb}: {0xb1, 0xb1, 0xb1}, // common.HashLength+3
   416  			{0xc}: nil,                // common.HashLength, account deletion
   417  		},
   418  		map[common.Hash]map[common.Hash][]byte{
   419  			{0xa}: {
   420  				common.Hash{0x1}: {0x11, 0x11, 0x11}, // 2*common.HashLength+3
   421  				common.Hash{0x3}: {0x31, 0x31},       // 2*common.HashLength+2, slot creation
   422  			},
   423  			{0xb}: {
   424  				common.Hash{0x1}: {0x11, 0x11}, // 2*common.HashLength+2
   425  				common.Hash{0x2}: {0x22, 0x22}, // 2*common.HashLength+2, slot creation
   426  			},
   427  			// The storage of 0xc is entirely removed
   428  			{0xc}: {
   429  				common.Hash{0x1}: nil, // 2*common.HashLength, slot deletion
   430  				common.Hash{0x2}: nil, // 2*common.HashLength, slot deletion
   431  				common.Hash{0x3}: nil, // 2*common.HashLength, slot deletion
   432  			},
   433  		},
   434  		false,
   435  	)
   436  	if b.size != uint64(expSizeB) {
   437  		t.Fatalf("Unexpected size, want: %d, got: %d", expSizeB, b.size)
   438  	}
   439  
   440  	a.merge(b)
   441  	mergeSize := expSizeA + 1 /* account a data change */ + 2 /* account b data change */ - 1 /* account c data change */
   442  	mergeSize += 2*common.HashLength + 2 + 2                                                  /* storage a change */
   443  	mergeSize += 2*common.HashLength + 2 - 1                                                  /* storage b change */
   444  	mergeSize += 2*2*common.HashLength - 1                                                    /* storage data removal of 0xc */
   445  
   446  	if a.size != uint64(mergeSize) {
   447  		t.Fatalf("Unexpected size, want: %d, got: %d", mergeSize, a.size)
   448  	}
   449  
   450  	// Revert the set to original status
   451  	a.revertTo(
   452  		map[common.Hash][]byte{
   453  			{0xa}: {0xa0},
   454  			{0xb}: {0xb0},
   455  			{0xc}: {0xc0},
   456  		},
   457  		map[common.Hash]map[common.Hash][]byte{
   458  			{0xa}: {
   459  				common.Hash{0x1}: {0x10},
   460  				common.Hash{0x2}: {0x20},
   461  				common.Hash{0x3}: nil, // revert slot creation
   462  			},
   463  			{0xb}: {
   464  				common.Hash{0x1}: {0x10, 0x11, 0x12},
   465  				common.Hash{0x2}: nil, // revert slot creation
   466  			},
   467  			{0xc}: {
   468  				common.Hash{0x1}: {0x10},
   469  				common.Hash{0x2}: {0x20}, // resurrected slot
   470  				common.Hash{0x3}: {0x30}, // resurrected slot
   471  			},
   472  		},
   473  	)
   474  	revertSize := expSizeA + 2*common.HashLength + 2*common.HashLength // delete-marker of a.3 and b.2 slot
   475  	revertSize += 2 * (2*common.HashLength + 1)                        // resurrected slot, c.2, c.3
   476  	if a.size != uint64(revertSize) {
   477  		t.Fatalf("Unexpected size, want: %d, got: %d", revertSize, a.size)
   478  	}
   479  }