github.com/ethereum/go-ethereum@v1.10.9/trie/stacktrie_test.go (about)

     1  // Copyright 2021 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 trie
    18  
    19  import (
    20  	"bytes"
    21  	"math/big"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  	"github.com/ethereum/go-ethereum/ethdb/memorydb"
    27  )
    28  
    29  func TestSizeBug(t *testing.T) {
    30  	st := NewStackTrie(nil)
    31  	nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
    32  
    33  	leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
    34  	value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
    35  
    36  	nt.TryUpdate(leaf, value)
    37  	st.TryUpdate(leaf, value)
    38  
    39  	if nt.Hash() != st.Hash() {
    40  		t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
    41  	}
    42  }
    43  
    44  func TestEmptyBug(t *testing.T) {
    45  	st := NewStackTrie(nil)
    46  	nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
    47  
    48  	//leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
    49  	//value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
    50  	kvs := []struct {
    51  		K string
    52  		V string
    53  	}{
    54  		{K: "405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace", V: "9496f4ec2bf9dab484cac6be589e8417d84781be08"},
    55  		{K: "40edb63a35fcf86c08022722aa3287cdd36440d671b4918131b2514795fefa9c", V: "01"},
    56  		{K: "b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", V: "947a30f7736e48d6599356464ba4c150d8da0302ff"},
    57  		{K: "c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b", V: "02"},
    58  	}
    59  
    60  	for _, kv := range kvs {
    61  		nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
    62  		st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
    63  	}
    64  
    65  	if nt.Hash() != st.Hash() {
    66  		t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
    67  	}
    68  }
    69  
    70  func TestValLength56(t *testing.T) {
    71  	st := NewStackTrie(nil)
    72  	nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
    73  
    74  	//leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
    75  	//value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
    76  	kvs := []struct {
    77  		K string
    78  		V string
    79  	}{
    80  		{K: "405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace", V: "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"},
    81  	}
    82  
    83  	for _, kv := range kvs {
    84  		nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
    85  		st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
    86  	}
    87  
    88  	if nt.Hash() != st.Hash() {
    89  		t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
    90  	}
    91  }
    92  
    93  // TestUpdateSmallNodes tests a case where the leaves are small (both key and value),
    94  // which causes a lot of node-within-node. This case was found via fuzzing.
    95  func TestUpdateSmallNodes(t *testing.T) {
    96  	st := NewStackTrie(nil)
    97  	nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
    98  	kvs := []struct {
    99  		K string
   100  		V string
   101  	}{
   102  		{"63303030", "3041"}, // stacktrie.Update
   103  		{"65", "3000"},       // stacktrie.Update
   104  	}
   105  	for _, kv := range kvs {
   106  		nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
   107  		st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
   108  	}
   109  	if nt.Hash() != st.Hash() {
   110  		t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
   111  	}
   112  }
   113  
   114  // TestUpdateVariableKeys contains a case which stacktrie fails: when keys of different
   115  // sizes are used, and the second one has the same prefix as the first, then the
   116  // stacktrie fails, since it's unable to 'expand' on an already added leaf.
   117  // For all practical purposes, this is fine, since keys are fixed-size length
   118  // in account and storage tries.
   119  //
   120  // The test is marked as 'skipped', and exists just to have the behaviour documented.
   121  // This case was found via fuzzing.
   122  func TestUpdateVariableKeys(t *testing.T) {
   123  	t.SkipNow()
   124  	st := NewStackTrie(nil)
   125  	nt, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
   126  	kvs := []struct {
   127  		K string
   128  		V string
   129  	}{
   130  		{"0x33303534636532393561313031676174", "303030"},
   131  		{"0x3330353463653239356131303167617430", "313131"},
   132  	}
   133  	for _, kv := range kvs {
   134  		nt.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
   135  		st.TryUpdate(common.FromHex(kv.K), common.FromHex(kv.V))
   136  	}
   137  	if nt.Hash() != st.Hash() {
   138  		t.Fatalf("error %x != %x", st.Hash(), nt.Hash())
   139  	}
   140  }
   141  
   142  // TestStacktrieNotModifyValues checks that inserting blobs of data into the
   143  // stacktrie does not mutate the blobs
   144  func TestStacktrieNotModifyValues(t *testing.T) {
   145  	st := NewStackTrie(nil)
   146  	{ // Test a very small trie
   147  		// Give it the value as a slice with large backing alloc,
   148  		// so if the stacktrie tries to append, it won't have to realloc
   149  		value := make([]byte, 1, 100)
   150  		value[0] = 0x2
   151  		want := common.CopyBytes(value)
   152  		st.TryUpdate([]byte{0x01}, value)
   153  		st.Hash()
   154  		if have := value; !bytes.Equal(have, want) {
   155  			t.Fatalf("tiny trie: have %#x want %#x", have, want)
   156  		}
   157  		st = NewStackTrie(nil)
   158  	}
   159  	// Test with a larger trie
   160  	keyB := big.NewInt(1)
   161  	keyDelta := big.NewInt(1)
   162  	var vals [][]byte
   163  	getValue := func(i int) []byte {
   164  		if i%2 == 0 { // large
   165  			return crypto.Keccak256(big.NewInt(int64(i)).Bytes())
   166  		} else { //small
   167  			return big.NewInt(int64(i)).Bytes()
   168  		}
   169  	}
   170  	for i := 0; i < 1000; i++ {
   171  		key := common.BigToHash(keyB)
   172  		value := getValue(i)
   173  		st.TryUpdate(key.Bytes(), value)
   174  		vals = append(vals, value)
   175  		keyB = keyB.Add(keyB, keyDelta)
   176  		keyDelta.Add(keyDelta, common.Big1)
   177  	}
   178  	st.Hash()
   179  	for i := 0; i < 1000; i++ {
   180  		want := getValue(i)
   181  
   182  		have := vals[i]
   183  		if !bytes.Equal(have, want) {
   184  			t.Fatalf("item %d, have %#x want %#x", i, have, want)
   185  		}
   186  
   187  	}
   188  }
   189  
   190  // TestStacktrieSerialization tests that the stacktrie works well if we
   191  // serialize/unserialize it a lot
   192  func TestStacktrieSerialization(t *testing.T) {
   193  	var (
   194  		st       = NewStackTrie(nil)
   195  		nt, _    = New(common.Hash{}, NewDatabase(memorydb.New()))
   196  		keyB     = big.NewInt(1)
   197  		keyDelta = big.NewInt(1)
   198  		vals     [][]byte
   199  		keys     [][]byte
   200  	)
   201  	getValue := func(i int) []byte {
   202  		if i%2 == 0 { // large
   203  			return crypto.Keccak256(big.NewInt(int64(i)).Bytes())
   204  		} else { //small
   205  			return big.NewInt(int64(i)).Bytes()
   206  		}
   207  	}
   208  	for i := 0; i < 10; i++ {
   209  		vals = append(vals, getValue(i))
   210  		keys = append(keys, common.BigToHash(keyB).Bytes())
   211  		keyB = keyB.Add(keyB, keyDelta)
   212  		keyDelta.Add(keyDelta, common.Big1)
   213  	}
   214  	for i, k := range keys {
   215  		nt.TryUpdate(k, common.CopyBytes(vals[i]))
   216  	}
   217  
   218  	for i, k := range keys {
   219  		blob, err := st.MarshalBinary()
   220  		if err != nil {
   221  			t.Fatal(err)
   222  		}
   223  		newSt, err := NewFromBinary(blob, nil)
   224  		if err != nil {
   225  			t.Fatal(err)
   226  		}
   227  		st = newSt
   228  		st.TryUpdate(k, common.CopyBytes(vals[i]))
   229  	}
   230  	if have, want := st.Hash(), nt.Hash(); have != want {
   231  		t.Fatalf("have %#x want %#x", have, want)
   232  	}
   233  }