github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/trie/trie_test.go (about)

     1  package trie
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"math/big"
     9  	"math/rand"
    10  	"os"
    11  	"reflect"
    12  	"testing"
    13  	"testing/quick"
    14  
    15  	"github.com/davecgh/go-spew/spew"
    16  	"github.com/neatlab/neatio/neatdb"
    17  	"github.com/neatlab/neatio/neatdb/leveldb"
    18  	"github.com/neatlab/neatio/neatdb/memorydb"
    19  	"github.com/neatlab/neatio/utilities/common"
    20  	"github.com/neatlab/neatio/utilities/crypto"
    21  	"github.com/neatlab/neatio/utilities/rlp"
    22  )
    23  
    24  func init() {
    25  	spew.Config.Indent = "    "
    26  	spew.Config.DisableMethods = false
    27  }
    28  
    29  func newEmpty() *Trie {
    30  	trie, _ := New(common.Hash{}, NewDatabase(memorydb.New()))
    31  	return trie
    32  }
    33  
    34  func TestEmptyTrie(t *testing.T) {
    35  	var trie Trie
    36  	res := trie.Hash()
    37  	exp := emptyRoot
    38  	if res != common.Hash(exp) {
    39  		t.Errorf("expected %x got %x", exp, res)
    40  	}
    41  }
    42  
    43  func TestNull(t *testing.T) {
    44  	var trie Trie
    45  	key := make([]byte, 32)
    46  	value := []byte("test")
    47  	trie.Update(key, value)
    48  	if !bytes.Equal(trie.Get(key), value) {
    49  		t.Fatal("wrong value")
    50  	}
    51  }
    52  
    53  func TestMissingRoot(t *testing.T) {
    54  	trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), NewDatabase(memorydb.New()))
    55  	if trie != nil {
    56  		t.Error("New returned non-nil trie for invalid root")
    57  	}
    58  	if _, ok := err.(*MissingNodeError); !ok {
    59  		t.Errorf("New returned wrong error: %v", err)
    60  	}
    61  }
    62  
    63  func TestMissingNodeDisk(t *testing.T)    { testMissingNode(t, false) }
    64  func TestMissingNodeMemonly(t *testing.T) { testMissingNode(t, true) }
    65  
    66  func testMissingNode(t *testing.T, memonly bool) {
    67  	diskdb := memorydb.New()
    68  	triedb := NewDatabase(diskdb)
    69  
    70  	trie, _ := New(common.Hash{}, triedb)
    71  	updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
    72  	updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
    73  	root, _ := trie.Commit(nil)
    74  	if !memonly {
    75  		triedb.Commit(root, true)
    76  	}
    77  
    78  	trie, _ = New(root, triedb)
    79  	_, err := trie.TryGet([]byte("120000"))
    80  	if err != nil {
    81  		t.Errorf("Unexpected error: %v", err)
    82  	}
    83  	trie, _ = New(root, triedb)
    84  	_, err = trie.TryGet([]byte("120099"))
    85  	if err != nil {
    86  		t.Errorf("Unexpected error: %v", err)
    87  	}
    88  	trie, _ = New(root, triedb)
    89  	_, err = trie.TryGet([]byte("123456"))
    90  	if err != nil {
    91  		t.Errorf("Unexpected error: %v", err)
    92  	}
    93  	trie, _ = New(root, triedb)
    94  	err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv"))
    95  	if err != nil {
    96  		t.Errorf("Unexpected error: %v", err)
    97  	}
    98  	trie, _ = New(root, triedb)
    99  	err = trie.TryDelete([]byte("123456"))
   100  	if err != nil {
   101  		t.Errorf("Unexpected error: %v", err)
   102  	}
   103  
   104  	hash := common.HexToHash("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9")
   105  	if memonly {
   106  		delete(triedb.dirties, hash)
   107  	} else {
   108  		diskdb.Delete(hash[:])
   109  	}
   110  
   111  	trie, _ = New(root, triedb)
   112  	_, err = trie.TryGet([]byte("120000"))
   113  	if _, ok := err.(*MissingNodeError); !ok {
   114  		t.Errorf("Wrong error: %v", err)
   115  	}
   116  	trie, _ = New(root, triedb)
   117  	_, err = trie.TryGet([]byte("120099"))
   118  	if _, ok := err.(*MissingNodeError); !ok {
   119  		t.Errorf("Wrong error: %v", err)
   120  	}
   121  	trie, _ = New(root, triedb)
   122  	_, err = trie.TryGet([]byte("123456"))
   123  	if err != nil {
   124  		t.Errorf("Unexpected error: %v", err)
   125  	}
   126  	trie, _ = New(root, triedb)
   127  	err = trie.TryUpdate([]byte("120099"), []byte("zxcv"))
   128  	if _, ok := err.(*MissingNodeError); !ok {
   129  		t.Errorf("Wrong error: %v", err)
   130  	}
   131  	trie, _ = New(root, triedb)
   132  	err = trie.TryDelete([]byte("123456"))
   133  	if _, ok := err.(*MissingNodeError); !ok {
   134  		t.Errorf("Wrong error: %v", err)
   135  	}
   136  }
   137  
   138  func TestInsert(t *testing.T) {
   139  	trie := newEmpty()
   140  
   141  	updateString(trie, "doe", "reindeer")
   142  	updateString(trie, "dog", "puppy")
   143  	updateString(trie, "dogglesworth", "cat")
   144  
   145  	exp := common.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3")
   146  	root := trie.Hash()
   147  	if root != exp {
   148  		t.Errorf("exp %x got %x", exp, root)
   149  	}
   150  
   151  	trie = newEmpty()
   152  	updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
   153  
   154  	exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
   155  	root, err := trie.Commit(nil)
   156  	if err != nil {
   157  		t.Fatalf("commit error: %v", err)
   158  	}
   159  	if root != exp {
   160  		t.Errorf("exp %x got %x", exp, root)
   161  	}
   162  }
   163  
   164  func TestGet(t *testing.T) {
   165  	trie := newEmpty()
   166  	updateString(trie, "doe", "reindeer")
   167  	updateString(trie, "dog", "puppy")
   168  	updateString(trie, "dogglesworth", "cat")
   169  
   170  	for i := 0; i < 2; i++ {
   171  		res := getString(trie, "dog")
   172  		if !bytes.Equal(res, []byte("puppy")) {
   173  			t.Errorf("expected puppy got %x", res)
   174  		}
   175  
   176  		unknown := getString(trie, "unknown")
   177  		if unknown != nil {
   178  			t.Errorf("expected nil got %x", unknown)
   179  		}
   180  
   181  		if i == 1 {
   182  			return
   183  		}
   184  		trie.Commit(nil)
   185  	}
   186  }
   187  
   188  func TestDelete(t *testing.T) {
   189  	trie := newEmpty()
   190  	vals := []struct{ k, v string }{
   191  		{"do", "verb"},
   192  		{"ether", "wookiedoo"},
   193  		{"horse", "stallion"},
   194  		{"shaman", "horse"},
   195  		{"doge", "coin"},
   196  		{"ether", ""},
   197  		{"dog", "puppy"},
   198  		{"shaman", ""},
   199  	}
   200  	for _, val := range vals {
   201  		if val.v != "" {
   202  			updateString(trie, val.k, val.v)
   203  		} else {
   204  			deleteString(trie, val.k)
   205  		}
   206  	}
   207  
   208  	hash := trie.Hash()
   209  	exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   210  	if hash != exp {
   211  		t.Errorf("expected %x got %x", exp, hash)
   212  	}
   213  }
   214  
   215  func TestEmptyValues(t *testing.T) {
   216  	trie := newEmpty()
   217  
   218  	vals := []struct{ k, v string }{
   219  		{"do", "verb"},
   220  		{"ether", "wookiedoo"},
   221  		{"horse", "stallion"},
   222  		{"shaman", "horse"},
   223  		{"doge", "coin"},
   224  		{"ether", ""},
   225  		{"dog", "puppy"},
   226  		{"shaman", ""},
   227  	}
   228  	for _, val := range vals {
   229  		updateString(trie, val.k, val.v)
   230  	}
   231  
   232  	hash := trie.Hash()
   233  	exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   234  	if hash != exp {
   235  		t.Errorf("expected %x got %x", exp, hash)
   236  	}
   237  }
   238  
   239  func TestReplication(t *testing.T) {
   240  	trie := newEmpty()
   241  	vals := []struct{ k, v string }{
   242  		{"do", "verb"},
   243  		{"ether", "wookiedoo"},
   244  		{"horse", "stallion"},
   245  		{"shaman", "horse"},
   246  		{"doge", "coin"},
   247  		{"dog", "puppy"},
   248  		{"somethingveryoddindeedthis is", "myothernodedata"},
   249  	}
   250  	for _, val := range vals {
   251  		updateString(trie, val.k, val.v)
   252  	}
   253  	exp, err := trie.Commit(nil)
   254  	if err != nil {
   255  		t.Fatalf("commit error: %v", err)
   256  	}
   257  
   258  	trie2, err := New(exp, trie.db)
   259  	if err != nil {
   260  		t.Fatalf("can't recreate trie at %x: %v", exp, err)
   261  	}
   262  	for _, kv := range vals {
   263  		if string(getString(trie2, kv.k)) != kv.v {
   264  			t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
   265  		}
   266  	}
   267  	hash, err := trie2.Commit(nil)
   268  	if err != nil {
   269  		t.Fatalf("commit error: %v", err)
   270  	}
   271  	if hash != exp {
   272  		t.Errorf("root failure. expected %x got %x", exp, hash)
   273  	}
   274  
   275  	vals2 := []struct{ k, v string }{
   276  		{"do", "verb"},
   277  		{"ether", "wookiedoo"},
   278  		{"horse", "stallion"},
   279  	}
   280  	for _, val := range vals2 {
   281  		updateString(trie2, val.k, val.v)
   282  	}
   283  	if hash := trie2.Hash(); hash != exp {
   284  		t.Errorf("root failure. expected %x got %x", exp, hash)
   285  	}
   286  }
   287  
   288  func TestLargeValue(t *testing.T) {
   289  	trie := newEmpty()
   290  	trie.Update([]byte("key1"), []byte{99, 99, 99, 99})
   291  	trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32))
   292  	trie.Hash()
   293  }
   294  
   295  type countingDB struct {
   296  	neatdb.KeyValueStore
   297  	gets map[string]int
   298  }
   299  
   300  func (db *countingDB) Get(key []byte) ([]byte, error) {
   301  	db.gets[string(key)]++
   302  	return db.KeyValueStore.Get(key)
   303  }
   304  
   305  type randTest []randTestStep
   306  
   307  type randTestStep struct {
   308  	op    int
   309  	key   []byte
   310  	value []byte
   311  	err   error
   312  }
   313  
   314  const (
   315  	opUpdate = iota
   316  	opDelete
   317  	opGet
   318  	opCommit
   319  	opHash
   320  	opReset
   321  	opItercheckhash
   322  	opMax
   323  )
   324  
   325  func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
   326  	var allKeys [][]byte
   327  	genKey := func() []byte {
   328  		if len(allKeys) < 2 || r.Intn(100) < 10 {
   329  
   330  			key := make([]byte, r.Intn(50))
   331  			r.Read(key)
   332  			allKeys = append(allKeys, key)
   333  			return key
   334  		}
   335  
   336  		return allKeys[r.Intn(len(allKeys))]
   337  	}
   338  
   339  	var steps randTest
   340  	for i := 0; i < size; i++ {
   341  		step := randTestStep{op: r.Intn(opMax)}
   342  		switch step.op {
   343  		case opUpdate:
   344  			step.key = genKey()
   345  			step.value = make([]byte, 8)
   346  			binary.BigEndian.PutUint64(step.value, uint64(i))
   347  		case opGet, opDelete:
   348  			step.key = genKey()
   349  		}
   350  		steps = append(steps, step)
   351  	}
   352  	return reflect.ValueOf(steps)
   353  }
   354  
   355  func runRandTest(rt randTest) bool {
   356  	triedb := NewDatabase(memorydb.New())
   357  
   358  	tr, _ := New(common.Hash{}, triedb)
   359  	values := make(map[string]string)
   360  
   361  	for i, step := range rt {
   362  		switch step.op {
   363  		case opUpdate:
   364  			tr.Update(step.key, step.value)
   365  			values[string(step.key)] = string(step.value)
   366  		case opDelete:
   367  			tr.Delete(step.key)
   368  			delete(values, string(step.key))
   369  		case opGet:
   370  			v := tr.Get(step.key)
   371  			want := values[string(step.key)]
   372  			if string(v) != want {
   373  				rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
   374  			}
   375  		case opCommit:
   376  			_, rt[i].err = tr.Commit(nil)
   377  		case opHash:
   378  			tr.Hash()
   379  		case opReset:
   380  			hash, err := tr.Commit(nil)
   381  			if err != nil {
   382  				rt[i].err = err
   383  				return false
   384  			}
   385  			newtr, err := New(hash, triedb)
   386  			if err != nil {
   387  				rt[i].err = err
   388  				return false
   389  			}
   390  			tr = newtr
   391  		case opItercheckhash:
   392  			checktr, _ := New(common.Hash{}, triedb)
   393  			it := NewIterator(tr.NodeIterator(nil))
   394  			for it.Next() {
   395  				checktr.Update(it.Key, it.Value)
   396  			}
   397  			if tr.Hash() != checktr.Hash() {
   398  				rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash")
   399  			}
   400  		}
   401  
   402  		if rt[i].err != nil {
   403  			return false
   404  		}
   405  	}
   406  	return true
   407  }
   408  
   409  func TestRandom(t *testing.T) {
   410  	if err := quick.Check(runRandTest, nil); err != nil {
   411  		if cerr, ok := err.(*quick.CheckError); ok {
   412  			t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
   413  		}
   414  		t.Fatal(err)
   415  	}
   416  }
   417  
   418  func BenchmarkGet(b *testing.B)      { benchGet(b, false) }
   419  func BenchmarkGetDB(b *testing.B)    { benchGet(b, true) }
   420  func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) }
   421  func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
   422  
   423  const benchElemCount = 20000
   424  
   425  func benchGet(b *testing.B, commit bool) {
   426  	trie := new(Trie)
   427  	if commit {
   428  		_, tmpdb := tempDB()
   429  		trie, _ = New(common.Hash{}, tmpdb)
   430  	}
   431  	k := make([]byte, 32)
   432  	for i := 0; i < benchElemCount; i++ {
   433  		binary.LittleEndian.PutUint64(k, uint64(i))
   434  		trie.Update(k, k)
   435  	}
   436  	binary.LittleEndian.PutUint64(k, benchElemCount/2)
   437  	if commit {
   438  		trie.Commit(nil)
   439  	}
   440  
   441  	b.ResetTimer()
   442  	for i := 0; i < b.N; i++ {
   443  		trie.Get(k)
   444  	}
   445  	b.StopTimer()
   446  
   447  	if commit {
   448  		ldb := trie.db.diskdb.(*leveldb.Database)
   449  		ldb.Close()
   450  		os.RemoveAll(ldb.Path())
   451  	}
   452  }
   453  
   454  func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
   455  	trie := newEmpty()
   456  	k := make([]byte, 32)
   457  	for i := 0; i < b.N; i++ {
   458  		e.PutUint64(k, uint64(i))
   459  		trie.Update(k, k)
   460  	}
   461  	return trie
   462  }
   463  
   464  func BenchmarkHash(b *testing.B) {
   465  
   466  	random := rand.New(rand.NewSource(0))
   467  
   468  	addresses := make([][20]byte, b.N)
   469  	for i := 0; i < len(addresses); i++ {
   470  		for j := 0; j < len(addresses[i]); j++ {
   471  			addresses[i][j] = byte(random.Intn(256))
   472  		}
   473  	}
   474  	accounts := make([][]byte, len(addresses))
   475  	for i := 0; i < len(accounts); i++ {
   476  		var (
   477  			nonce   = uint64(random.Int63())
   478  			balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
   479  			root    = emptyRoot
   480  			code    = crypto.Keccak256(nil)
   481  		)
   482  		accounts[i], _ = rlp.EncodeToBytes([]interface{}{nonce, balance, root, code})
   483  	}
   484  
   485  	trie := newEmpty()
   486  	for i := 0; i < len(addresses); i++ {
   487  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   488  	}
   489  	b.ResetTimer()
   490  	b.ReportAllocs()
   491  	trie.Hash()
   492  }
   493  
   494  func tempDB() (string, *Database) {
   495  	dir, err := ioutil.TempDir("", "trie-bench")
   496  	if err != nil {
   497  		panic(fmt.Sprintf("can't create temporary directory: %v", err))
   498  	}
   499  	diskdb, err := leveldb.New(dir, 256, 0, "")
   500  	if err != nil {
   501  		panic(fmt.Sprintf("can't create temporary database: %v", err))
   502  	}
   503  	return dir, NewDatabase(diskdb)
   504  }
   505  
   506  func getString(trie *Trie, k string) []byte {
   507  	return trie.Get([]byte(k))
   508  }
   509  
   510  func updateString(trie *Trie, k, v string) {
   511  	trie.Update([]byte(k), []byte(v))
   512  }
   513  
   514  func deleteString(trie *Trie, k string) {
   515  	trie.Delete([]byte(k))
   516  }
   517  
   518  func TestDecodeNode(t *testing.T) {
   519  	t.Parallel()
   520  	var (
   521  		hash  = make([]byte, 20)
   522  		elems = make([]byte, 20)
   523  	)
   524  	for i := 0; i < 5000000; i++ {
   525  		rand.Read(hash)
   526  		rand.Read(elems)
   527  		decodeNode(hash, elems)
   528  	}
   529  }