github.com/annchain/OG@v0.0.9/trie/trie_test.go (about)

     1  // Copyright 2014 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  	"encoding/binary"
    22  	"errors"
    23  	"fmt"
    24  	"github.com/annchain/OG/arefactor/common/math"
    25  	"github.com/annchain/OG/arefactor/og/types"
    26  	ogcrypto2 "github.com/annchain/OG/deprecated/ogcrypto"
    27  	"io/ioutil"
    28  	"math/big"
    29  	"math/rand"
    30  	"os"
    31  	"reflect"
    32  	"testing"
    33  	"testing/quick"
    34  
    35  	"github.com/annchain/OG/common"
    36  	"github.com/annchain/OG/ogdb"
    37  	"github.com/davecgh/go-spew/spew"
    38  	// "github.com/ethereum/go-ethereum/common"
    39  	// "github.com/ethereum/go-ethereum/ogcrypto"
    40  	// "github.com/ethereum/go-ethereum/ethdb"
    41  	// "github.com/ethereum/go-ethereum/rlp"
    42  )
    43  
    44  func init() {
    45  	spew.Config.Indent = "    "
    46  	spew.Config.DisableMethods = false
    47  }
    48  
    49  // Used for testing
    50  func newEmpty() *Trie {
    51  	trie, _ := New(types.Hash{}, NewDatabase(ogdb.NewMemDatabase()))
    52  	return trie
    53  }
    54  
    55  func TestEmptyTrie(t *testing.T) {
    56  	var trie Trie
    57  	res := trie.Hash()
    58  	exp := emptyRoot
    59  	if res != types.Hash(exp) {
    60  		t.Errorf("expected %x got %x", exp, res)
    61  	}
    62  }
    63  
    64  func TestNull(t *testing.T) {
    65  	var trie Trie
    66  	key := make([]byte, 32)
    67  	value := []byte("test")
    68  	trie.Update(key, value)
    69  	if !bytes.Equal(trie.Get(key), value) {
    70  		t.Fatal("wrong value")
    71  	}
    72  }
    73  
    74  func TestMissingRoot(t *testing.T) {
    75  	trie, err := New(types.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), NewDatabase(ogdb.NewMemDatabase()))
    76  	if trie != nil {
    77  		t.Error("New returned non-nil trie for invalid root")
    78  	}
    79  	if _, ok := err.(*MissingNodeError); !ok {
    80  		t.Errorf("New returned wrong error: %v", err)
    81  	}
    82  }
    83  
    84  func TestMissingNodeDisk(t *testing.T)    { testMissingNode(t, false) }
    85  func TestMissingNodeMemonly(t *testing.T) { testMissingNode(t, true) }
    86  
    87  func testMissingNode(t *testing.T, memonly bool) {
    88  	diskdb := ogdb.NewMemDatabase()
    89  	triedb := NewDatabase(diskdb)
    90  
    91  	trie, _ := New(types.Hash{}, triedb)
    92  	updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
    93  	updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
    94  	root, _ := trie.Commit(nil)
    95  	if !memonly {
    96  		triedb.Commit(root, true)
    97  	}
    98  
    99  	trie, _ = New(root, triedb)
   100  	_, err := trie.TryGet([]byte("120000"))
   101  	if err != nil {
   102  		t.Errorf("Unexpected error: %v", err)
   103  	}
   104  	trie, _ = New(root, triedb)
   105  	_, err = trie.TryGet([]byte("120099"))
   106  	if err != nil {
   107  		t.Errorf("Unexpected error: %v", err)
   108  	}
   109  	trie, _ = New(root, triedb)
   110  	_, err = trie.TryGet([]byte("123456"))
   111  	if err != nil {
   112  		t.Errorf("Unexpected error: %v", err)
   113  	}
   114  	trie, _ = New(root, triedb)
   115  	err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv"))
   116  	if err != nil {
   117  		t.Errorf("Unexpected error: %v", err)
   118  	}
   119  	trie, _ = New(root, triedb)
   120  	err = trie.TryDelete([]byte("123456"))
   121  	if err != nil {
   122  		t.Errorf("Unexpected error: %v", err)
   123  	}
   124  
   125  	hash := types.HexToHash("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9")
   126  	if memonly {
   127  		delete(triedb.nodes, hash)
   128  	} else {
   129  		diskdb.Delete(hash.ToBytes())
   130  	}
   131  
   132  	trie, _ = New(root, triedb)
   133  	_, err = trie.TryGet([]byte("120000"))
   134  	if _, ok := err.(*MissingNodeError); !ok {
   135  		t.Errorf("Wrong error: %v", err)
   136  	}
   137  	trie, _ = New(root, triedb)
   138  	_, err = trie.TryGet([]byte("120099"))
   139  	if _, ok := err.(*MissingNodeError); !ok {
   140  		t.Errorf("Wrong error: %v", err)
   141  	}
   142  	trie, _ = New(root, triedb)
   143  	_, err = trie.TryGet([]byte("123456"))
   144  	if err != nil {
   145  		t.Errorf("Unexpected error: %v", err)
   146  	}
   147  	trie, _ = New(root, triedb)
   148  	err = trie.TryUpdate([]byte("120099"), []byte("zxcv"))
   149  	if _, ok := err.(*MissingNodeError); !ok {
   150  		t.Errorf("Wrong error: %v", err)
   151  	}
   152  	trie, _ = New(root, triedb)
   153  	err = trie.TryDelete([]byte("123456"))
   154  	if _, ok := err.(*MissingNodeError); !ok {
   155  		t.Errorf("Wrong error: %v", err)
   156  	}
   157  }
   158  
   159  func TestInsert(t *testing.T) {
   160  	trie := newEmpty()
   161  
   162  	updateString(trie, "doe", "reindeer")
   163  	updateString(trie, "dog", "puppy")
   164  	updateString(trie, "dogglesworth", "cat")
   165  
   166  	exp := types.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3")
   167  	root := trie.Hash()
   168  	if root != exp {
   169  		t.Errorf("exp %x got %x", exp, root)
   170  	}
   171  
   172  	trie = newEmpty()
   173  	updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
   174  
   175  	exp = types.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
   176  	root, err := trie.Commit(nil)
   177  	if err != nil {
   178  		t.Fatalf("commit error: %v", err)
   179  	}
   180  	if root != exp {
   181  		t.Errorf("exp %x got %x", exp, root)
   182  	}
   183  }
   184  
   185  func TestGet(t *testing.T) {
   186  	trie := newEmpty()
   187  	updateString(trie, "doe", "reindeer")
   188  	updateString(trie, "dog", "puppy")
   189  	updateString(trie, "dogglesworth", "cat")
   190  
   191  	for i := 0; i < 2; i++ {
   192  		res := getString(trie, "dog")
   193  		if !bytes.Equal(res, []byte("puppy")) {
   194  			t.Errorf("expected puppy got %x", res)
   195  		}
   196  
   197  		unknown := getString(trie, "unknown")
   198  		if unknown != nil {
   199  			t.Errorf("expected nil got %x", unknown)
   200  		}
   201  
   202  		if i == 1 {
   203  			return
   204  		}
   205  		trie.Commit(nil)
   206  	}
   207  }
   208  
   209  func TestDelete(t *testing.T) {
   210  	trie := newEmpty()
   211  	vals := []struct{ k, v string }{
   212  		{"do", "verb"},
   213  		{"ether", "wookiedoo"},
   214  		{"horse", "stallion"},
   215  		{"shaman", "horse"},
   216  		{"doge", "coin"},
   217  		{"ether", ""},
   218  		{"dog", "puppy"},
   219  		{"shaman", ""},
   220  	}
   221  	for _, val := range vals {
   222  		if val.v != "" {
   223  			updateString(trie, val.k, val.v)
   224  		} else {
   225  			deleteString(trie, val.k)
   226  		}
   227  	}
   228  
   229  	hash := trie.Hash()
   230  	exp := types.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   231  	if hash != exp {
   232  		t.Errorf("expected %x got %x", exp, hash)
   233  	}
   234  }
   235  
   236  func TestEmptyValues(t *testing.T) {
   237  	trie := newEmpty()
   238  
   239  	vals := []struct{ k, v string }{
   240  		{"do", "verb"},
   241  		{"ether", "wookiedoo"},
   242  		{"horse", "stallion"},
   243  		{"shaman", "horse"},
   244  		{"doge", "coin"},
   245  		{"ether", ""},
   246  		{"dog", "puppy"},
   247  		{"shaman", ""},
   248  	}
   249  	for _, val := range vals {
   250  		updateString(trie, val.k, val.v)
   251  	}
   252  
   253  	hash := trie.Hash()
   254  	exp := types.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   255  	if hash != exp {
   256  		t.Errorf("expected %x got %x", exp, hash)
   257  	}
   258  }
   259  
   260  func TestReplication(t *testing.T) {
   261  	trie := newEmpty()
   262  	vals := []struct{ k, v string }{
   263  		{"do", "verb"},
   264  		{"ether", "wookiedoo"},
   265  		{"horse", "stallion"},
   266  		{"shaman", "horse"},
   267  		{"doge", "coin"},
   268  		{"dog", "puppy"},
   269  		{"somethingveryoddindeedthis is", "myothernodedata"},
   270  	}
   271  	for _, val := range vals {
   272  		updateString(trie, val.k, val.v)
   273  	}
   274  	exp, err := trie.Commit(nil)
   275  	if err != nil {
   276  		t.Fatalf("commit error: %v", err)
   277  	}
   278  
   279  	// create a new trie on top of the database and check that lookups work.
   280  	trie2, err := New(exp, trie.db)
   281  	if err != nil {
   282  		t.Fatalf("can't recreate trie at %x: %v", exp, err)
   283  	}
   284  	for _, kv := range vals {
   285  		if string(getString(trie2, kv.k)) != kv.v {
   286  			t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
   287  		}
   288  	}
   289  	hash, err := trie2.Commit(nil)
   290  	if err != nil {
   291  		t.Fatalf("commit error: %v", err)
   292  	}
   293  	if hash != exp {
   294  		t.Errorf("root failure. expected %x got %x", exp, hash)
   295  	}
   296  
   297  	// perform some insertions on the new trie.
   298  	vals2 := []struct{ k, v string }{
   299  		{"do", "verb"},
   300  		{"ether", "wookiedoo"},
   301  		{"horse", "stallion"},
   302  		// {"shaman", "horse"},
   303  		// {"doge", "coin"},
   304  		// {"ether", ""},
   305  		// {"dog", "puppy"},
   306  		// {"somethingveryoddindeedthis is", "myothernodedata"},
   307  		// {"shaman", ""},
   308  	}
   309  	for _, val := range vals2 {
   310  		updateString(trie2, val.k, val.v)
   311  	}
   312  	if hash := trie2.Hash(); hash != exp {
   313  		t.Errorf("root failure. expected %x got %x", exp, hash)
   314  	}
   315  }
   316  
   317  func TestLargeValue(t *testing.T) {
   318  	trie := newEmpty()
   319  	trie.Update([]byte("key1"), []byte{99, 99, 99, 99})
   320  	trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32))
   321  	trie.Hash()
   322  }
   323  
   324  type countingDB struct {
   325  	ogdb.Database
   326  	gets map[string]int
   327  }
   328  
   329  func (db *countingDB) Get(key []byte) ([]byte, error) {
   330  	db.gets[string(key)]++
   331  	return db.Database.Get(key)
   332  }
   333  
   334  // TestCacheUnload checks that decoded nodes are unloaded after a
   335  // certain number of commit operations.
   336  func TestCacheUnload(t *testing.T) {
   337  	// Create test trie with two branches.
   338  	trie := newEmpty()
   339  	key1 := "---------------------------------"
   340  	key2 := "---some other branch"
   341  	updateString(trie, key1, "this is the branch of key1.")
   342  	updateString(trie, key2, "this is the branch of key2.")
   343  
   344  	root, _ := trie.Commit(nil)
   345  	trie.db.Commit(root, true)
   346  
   347  	// Commit the trie repeatedly and access key1.
   348  	// The branch containing it is loaded from DB exactly two times:
   349  	// in the 0th and 6th iteration.
   350  	db := &countingDB{Database: trie.db.diskdb, gets: make(map[string]int)}
   351  	trie, _ = New(root, NewDatabase(db))
   352  	trie.SetCacheLimit(5)
   353  	for i := 0; i < 12; i++ {
   354  		getString(trie, key1)
   355  		trie.Commit(nil)
   356  	}
   357  	// Check that it got loaded two times.
   358  	for dbkey, count := range db.gets {
   359  		if count != 2 {
   360  			t.Errorf("db key %x loaded %d times, want %d times", []byte(dbkey), count, 2)
   361  		}
   362  	}
   363  }
   364  
   365  // randTest performs random trie operations.
   366  // Instances of this test are created by Generate.
   367  type randTest []randTestStep
   368  
   369  type randTestStep struct {
   370  	op    int
   371  	key   []byte // for opUpdate, opDelete, opGet
   372  	value []byte // for opUpdate
   373  	err   error  // for debugging
   374  }
   375  
   376  const (
   377  	opUpdate = iota
   378  	opDelete
   379  	opGet
   380  	opCommit
   381  	opHash
   382  	opReset
   383  	opItercheckhash
   384  	opCheckCacheInvariant
   385  	opMax // boundary value, not an actual op
   386  )
   387  
   388  func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
   389  	var allKeys [][]byte
   390  	genKey := func() []byte {
   391  		if len(allKeys) < 2 || r.Intn(100) < 10 {
   392  			// new key
   393  			key := make([]byte, r.Intn(50))
   394  			r.Read(key)
   395  			allKeys = append(allKeys, key)
   396  			return key
   397  		}
   398  		// use existing key
   399  		return allKeys[r.Intn(len(allKeys))]
   400  	}
   401  
   402  	var steps randTest
   403  	for i := 0; i < size; i++ {
   404  		step := randTestStep{op: r.Intn(opMax)}
   405  		switch step.op {
   406  		case opUpdate:
   407  			step.key = genKey()
   408  			step.value = make([]byte, 8)
   409  			binary.BigEndian.PutUint64(step.value, uint64(i))
   410  		case opGet, opDelete:
   411  			step.key = genKey()
   412  		}
   413  		steps = append(steps, step)
   414  	}
   415  	return reflect.ValueOf(steps)
   416  }
   417  
   418  func runRandTest(rt randTest) bool {
   419  	triedb := NewDatabase(ogdb.NewMemDatabase())
   420  
   421  	tr, _ := New(types.Hash{}, triedb)
   422  	values := make(map[string]string) // tracks content of the trie
   423  
   424  	for i, step := range rt {
   425  		switch step.op {
   426  		case opUpdate:
   427  			tr.Update(step.key, step.value)
   428  			values[string(step.key)] = string(step.value)
   429  		case opDelete:
   430  			tr.Delete(step.key)
   431  			delete(values, string(step.key))
   432  		case opGet:
   433  			v := tr.Get(step.key)
   434  			want := values[string(step.key)]
   435  			if string(v) != want {
   436  				rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
   437  			}
   438  		case opCommit:
   439  			_, rt[i].err = tr.Commit(nil)
   440  		case opHash:
   441  			tr.Hash()
   442  		case opReset:
   443  			hash, err := tr.Commit(nil)
   444  			if err != nil {
   445  				rt[i].err = err
   446  				return false
   447  			}
   448  			newtr, err := New(hash, triedb)
   449  			if err != nil {
   450  				rt[i].err = err
   451  				return false
   452  			}
   453  			tr = newtr
   454  		case opItercheckhash:
   455  			checktr, _ := New(types.Hash{}, triedb)
   456  			it := NewIterator(tr.NodeIterator(nil))
   457  			for it.Next() {
   458  				checktr.Update(it.Key, it.Value)
   459  			}
   460  			if tr.Hash() != checktr.Hash() {
   461  				rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash")
   462  			}
   463  		case opCheckCacheInvariant:
   464  			rt[i].err = checkCacheInvariant(tr.root, nil, tr.cachegen, false, 0)
   465  		}
   466  		// Abort the test on error.
   467  		if rt[i].err != nil {
   468  			return false
   469  		}
   470  	}
   471  	return true
   472  }
   473  
   474  func checkCacheInvariant(n, parent Node, parentCachegen uint16, parentDirty bool, depth int) error {
   475  	var children []Node
   476  	var flag nodeFlag
   477  	switch n := n.(type) {
   478  	case *ShortNode:
   479  		flag = n.flags
   480  		children = []Node{n.Val}
   481  	case *FullNode:
   482  		flag = n.flags
   483  		children = n.Children[:]
   484  	default:
   485  		return nil
   486  	}
   487  
   488  	errorf := func(format string, args ...interface{}) error {
   489  		msg := fmt.Sprintf(format, args...)
   490  		msg += fmt.Sprintf("\nat depth %d node %s", depth, spew.Sdump(n))
   491  		msg += fmt.Sprintf("parent: %s", spew.Sdump(parent))
   492  		return errors.New(msg)
   493  	}
   494  	if flag.gen > parentCachegen {
   495  		return errorf("cache invariant violation: %d > %d\n", flag.gen, parentCachegen)
   496  	}
   497  	if depth > 0 && !parentDirty && flag.dirty {
   498  		return errorf("cache invariant violation: %d > %d\n", flag.gen, parentCachegen)
   499  	}
   500  	for _, child := range children {
   501  		if err := checkCacheInvariant(child, n, flag.gen, flag.dirty, depth+1); err != nil {
   502  			return err
   503  		}
   504  	}
   505  	return nil
   506  }
   507  
   508  func TestRandom(t *testing.T) {
   509  	if err := quick.Check(runRandTest, nil); err != nil {
   510  		if cerr, ok := err.(*quick.CheckError); ok {
   511  			t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
   512  		}
   513  		t.Fatal(err)
   514  	}
   515  }
   516  
   517  func BenchmarkGet(b *testing.B)      { benchGet(b, false) }
   518  func BenchmarkGetDB(b *testing.B)    { benchGet(b, true) }
   519  func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) }
   520  func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
   521  
   522  const benchElemCount = 20000
   523  
   524  func benchGet(b *testing.B, commit bool) {
   525  	trie := new(Trie)
   526  	if commit {
   527  		_, tmpdb := tempDB()
   528  		trie, _ = New(types.Hash{}, tmpdb)
   529  	}
   530  	k := make([]byte, 32)
   531  	for i := 0; i < benchElemCount; i++ {
   532  		binary.LittleEndian.PutUint64(k, uint64(i))
   533  		trie.Update(k, k)
   534  	}
   535  	binary.LittleEndian.PutUint64(k, benchElemCount/2)
   536  	if commit {
   537  		trie.Commit(nil)
   538  	}
   539  
   540  	b.ResetTimer()
   541  	for i := 0; i < b.N; i++ {
   542  		trie.Get(k)
   543  	}
   544  	b.StopTimer()
   545  
   546  	if commit {
   547  		ldb := trie.db.diskdb.(*ogdb.LevelDB)
   548  		ldb.Close()
   549  		os.RemoveAll(ldb.Path())
   550  	}
   551  }
   552  
   553  func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
   554  	trie := newEmpty()
   555  	k := make([]byte, 32)
   556  	for i := 0; i < b.N; i++ {
   557  		e.PutUint64(k, uint64(i))
   558  		trie.Update(k, k)
   559  	}
   560  	return trie
   561  }
   562  
   563  // Benchmarks the trie hashing. Since the trie caches the result of any operation,
   564  // we cannot use b.N as the number of hashing rouns, since all rounds apart from
   565  // the first one will be NOOP. As such, we'll use b.N as the number of account to
   566  // insert into the trie before measuring the hashing.
   567  func BenchmarkHash(b *testing.B) {
   568  	// Make the random benchmark deterministic
   569  	random := rand.New(rand.NewSource(0))
   570  
   571  	// Create a realistic account trie to hash
   572  	addresses := make([][20]byte, b.N)
   573  	for i := 0; i < len(addresses); i++ {
   574  		for j := 0; j < len(addresses[i]); j++ {
   575  			addresses[i][j] = byte(random.Intn(256))
   576  		}
   577  	}
   578  	accounts := make([][]byte, len(addresses))
   579  	for i := 0; i < len(accounts); i++ {
   580  		var (
   581  			nonce   = uint64(random.Int63())
   582  			balance = new(big.Int).Rand(random, new(big.Int).Exp(math.Big2, math.Big256, nil))
   583  			root    = emptyRoot
   584  			code    = ogcrypto2.Keccak256(nil)
   585  		)
   586  		accstr := fmt.Sprintf("%d %v %s %v", nonce, balance.Bytes(), root.String(), code)
   587  		accounts[i] = common.Hex2BytesNoError(accstr)
   588  	}
   589  	// Insert the accounts into the trie and hash it
   590  	trie := newEmpty()
   591  	for i := 0; i < len(addresses); i++ {
   592  		trie.Update(ogcrypto2.Keccak256(addresses[i][:]), accounts[i])
   593  	}
   594  	b.ResetTimer()
   595  	b.ReportAllocs()
   596  	trie.Hash()
   597  }
   598  
   599  func tempDB() (string, *Database) {
   600  	dir, err := ioutil.TempDir("", "trie-bench")
   601  	if err != nil {
   602  		panic(fmt.Sprintf("can't create temporary directory: %v", err))
   603  	}
   604  	diskdb, err := ogdb.NewLevelDB(dir, 256, 0)
   605  	if err != nil {
   606  		panic(fmt.Sprintf("can't create temporary database: %v", err))
   607  	}
   608  	return dir, NewDatabase(diskdb)
   609  }
   610  
   611  func getString(trie *Trie, k string) []byte {
   612  	return trie.Get([]byte(k))
   613  }
   614  
   615  func updateString(trie *Trie, k, v string) {
   616  	trie.Update([]byte(k), []byte(v))
   617  }
   618  
   619  func deleteString(trie *Trie, k string) {
   620  	trie.Delete([]byte(k))
   621  }