github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/trie/trie_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:45</date>
    10  //</624450123639820288>
    11  
    12  
    13  package trie
    14  
    15  import (
    16  	"bytes"
    17  	"encoding/binary"
    18  	"errors"
    19  	"fmt"
    20  	"io/ioutil"
    21  	"math/big"
    22  	"math/rand"
    23  	"os"
    24  	"reflect"
    25  	"testing"
    26  	"testing/quick"
    27  
    28  	"github.com/davecgh/go-spew/spew"
    29  	"github.com/ethereum/go-ethereum/common"
    30  	"github.com/ethereum/go-ethereum/crypto"
    31  	"github.com/ethereum/go-ethereum/ethdb"
    32  	"github.com/ethereum/go-ethereum/rlp"
    33  )
    34  
    35  func init() {
    36  	spew.Config.Indent = "    "
    37  	spew.Config.DisableMethods = false
    38  }
    39  
    40  //用于测试
    41  func newEmpty() *Trie {
    42  	trie, _ := New(common.Hash{}, NewDatabase(ethdb.NewMemDatabase()))
    43  	return trie
    44  }
    45  
    46  func TestEmptyTrie(t *testing.T) {
    47  	var trie Trie
    48  	res := trie.Hash()
    49  	exp := emptyRoot
    50  	if res != common.Hash(exp) {
    51  		t.Errorf("expected %x got %x", exp, res)
    52  	}
    53  }
    54  
    55  func TestNull(t *testing.T) {
    56  	var trie Trie
    57  	key := make([]byte, 32)
    58  	value := []byte("test")
    59  	trie.Update(key, value)
    60  	if !bytes.Equal(trie.Get(key), value) {
    61  		t.Fatal("wrong value")
    62  	}
    63  }
    64  
    65  func TestMissingRoot(t *testing.T) {
    66  	trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), NewDatabase(ethdb.NewMemDatabase()))
    67  	if trie != nil {
    68  		t.Error("New returned non-nil trie for invalid root")
    69  	}
    70  	if _, ok := err.(*MissingNodeError); !ok {
    71  		t.Errorf("New returned wrong error: %v", err)
    72  	}
    73  }
    74  
    75  func TestMissingNodeDisk(t *testing.T)    { testMissingNode(t, false) }
    76  func TestMissingNodeMemonly(t *testing.T) { testMissingNode(t, true) }
    77  
    78  func testMissingNode(t *testing.T, memonly bool) {
    79  	diskdb := ethdb.NewMemDatabase()
    80  	triedb := NewDatabase(diskdb)
    81  
    82  	trie, _ := New(common.Hash{}, triedb)
    83  	updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
    84  	updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
    85  	root, _ := trie.Commit(nil)
    86  	if !memonly {
    87  		triedb.Commit(root, true)
    88  	}
    89  
    90  	trie, _ = New(root, triedb)
    91  	_, err := trie.TryGet([]byte("120000"))
    92  	if err != nil {
    93  		t.Errorf("Unexpected error: %v", err)
    94  	}
    95  	trie, _ = New(root, triedb)
    96  	_, err = trie.TryGet([]byte("120099"))
    97  	if err != nil {
    98  		t.Errorf("Unexpected error: %v", err)
    99  	}
   100  	trie, _ = New(root, triedb)
   101  	_, err = trie.TryGet([]byte("123456"))
   102  	if err != nil {
   103  		t.Errorf("Unexpected error: %v", err)
   104  	}
   105  	trie, _ = New(root, triedb)
   106  	err = trie.TryUpdate([]byte("120099"), []byte("zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv"))
   107  	if err != nil {
   108  		t.Errorf("Unexpected error: %v", err)
   109  	}
   110  	trie, _ = New(root, triedb)
   111  	err = trie.TryDelete([]byte("123456"))
   112  	if err != nil {
   113  		t.Errorf("Unexpected error: %v", err)
   114  	}
   115  
   116  	hash := common.HexToHash("0xe1d943cc8f061a0c0b98162830b970395ac9315654824bf21b73b891365262f9")
   117  	if memonly {
   118  		delete(triedb.dirties, hash)
   119  	} else {
   120  		diskdb.Delete(hash[:])
   121  	}
   122  
   123  	trie, _ = New(root, triedb)
   124  	_, err = trie.TryGet([]byte("120000"))
   125  	if _, ok := err.(*MissingNodeError); !ok {
   126  		t.Errorf("Wrong error: %v", err)
   127  	}
   128  	trie, _ = New(root, triedb)
   129  	_, err = trie.TryGet([]byte("120099"))
   130  	if _, ok := err.(*MissingNodeError); !ok {
   131  		t.Errorf("Wrong error: %v", err)
   132  	}
   133  	trie, _ = New(root, triedb)
   134  	_, err = trie.TryGet([]byte("123456"))
   135  	if err != nil {
   136  		t.Errorf("Unexpected error: %v", err)
   137  	}
   138  	trie, _ = New(root, triedb)
   139  	err = trie.TryUpdate([]byte("120099"), []byte("zxcv"))
   140  	if _, ok := err.(*MissingNodeError); !ok {
   141  		t.Errorf("Wrong error: %v", err)
   142  	}
   143  	trie, _ = New(root, triedb)
   144  	err = trie.TryDelete([]byte("123456"))
   145  	if _, ok := err.(*MissingNodeError); !ok {
   146  		t.Errorf("Wrong error: %v", err)
   147  	}
   148  }
   149  
   150  func TestInsert(t *testing.T) {
   151  	trie := newEmpty()
   152  
   153  	updateString(trie, "doe", "reindeer")
   154  	updateString(trie, "dog", "puppy")
   155  	updateString(trie, "dogglesworth", "cat")
   156  
   157  	exp := common.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3")
   158  	root := trie.Hash()
   159  	if root != exp {
   160  		t.Errorf("exp %x got %x", exp, root)
   161  	}
   162  
   163  	trie = newEmpty()
   164  	updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
   165  
   166  	exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
   167  	root, err := trie.Commit(nil)
   168  	if err != nil {
   169  		t.Fatalf("commit error: %v", err)
   170  	}
   171  	if root != exp {
   172  		t.Errorf("exp %x got %x", exp, root)
   173  	}
   174  }
   175  
   176  func TestGet(t *testing.T) {
   177  	trie := newEmpty()
   178  	updateString(trie, "doe", "reindeer")
   179  	updateString(trie, "dog", "puppy")
   180  	updateString(trie, "dogglesworth", "cat")
   181  
   182  	for i := 0; i < 2; i++ {
   183  		res := getString(trie, "dog")
   184  		if !bytes.Equal(res, []byte("puppy")) {
   185  			t.Errorf("expected puppy got %x", res)
   186  		}
   187  
   188  		unknown := getString(trie, "unknown")
   189  		if unknown != nil {
   190  			t.Errorf("expected nil got %x", unknown)
   191  		}
   192  
   193  		if i == 1 {
   194  			return
   195  		}
   196  		trie.Commit(nil)
   197  	}
   198  }
   199  
   200  func TestDelete(t *testing.T) {
   201  	trie := newEmpty()
   202  	vals := []struct{ k, v string }{
   203  		{"do", "verb"},
   204  		{"ether", "wookiedoo"},
   205  		{"horse", "stallion"},
   206  		{"shaman", "horse"},
   207  		{"doge", "coin"},
   208  		{"ether", ""},
   209  		{"dog", "puppy"},
   210  		{"shaman", ""},
   211  	}
   212  	for _, val := range vals {
   213  		if val.v != "" {
   214  			updateString(trie, val.k, val.v)
   215  		} else {
   216  			deleteString(trie, val.k)
   217  		}
   218  	}
   219  
   220  	hash := trie.Hash()
   221  	exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   222  	if hash != exp {
   223  		t.Errorf("expected %x got %x", exp, hash)
   224  	}
   225  }
   226  
   227  func TestEmptyValues(t *testing.T) {
   228  	trie := newEmpty()
   229  
   230  	vals := []struct{ k, v string }{
   231  		{"do", "verb"},
   232  		{"ether", "wookiedoo"},
   233  		{"horse", "stallion"},
   234  		{"shaman", "horse"},
   235  		{"doge", "coin"},
   236  		{"ether", ""},
   237  		{"dog", "puppy"},
   238  		{"shaman", ""},
   239  	}
   240  	for _, val := range vals {
   241  		updateString(trie, val.k, val.v)
   242  	}
   243  
   244  	hash := trie.Hash()
   245  	exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   246  	if hash != exp {
   247  		t.Errorf("expected %x got %x", exp, hash)
   248  	}
   249  }
   250  
   251  func TestReplication(t *testing.T) {
   252  	trie := newEmpty()
   253  	vals := []struct{ k, v string }{
   254  		{"do", "verb"},
   255  		{"ether", "wookiedoo"},
   256  		{"horse", "stallion"},
   257  		{"shaman", "horse"},
   258  		{"doge", "coin"},
   259  		{"dog", "puppy"},
   260  		{"somethingveryoddindeedthis is", "myothernodedata"},
   261  	}
   262  	for _, val := range vals {
   263  		updateString(trie, val.k, val.v)
   264  	}
   265  	exp, err := trie.Commit(nil)
   266  	if err != nil {
   267  		t.Fatalf("commit error: %v", err)
   268  	}
   269  
   270  //在数据库顶部创建一个新的trie,并检查查找是否有效。
   271  	trie2, err := New(exp, trie.db)
   272  	if err != nil {
   273  		t.Fatalf("can't recreate trie at %x: %v", exp, err)
   274  	}
   275  	for _, kv := range vals {
   276  		if string(getString(trie2, kv.k)) != kv.v {
   277  			t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
   278  		}
   279  	}
   280  	hash, err := trie2.Commit(nil)
   281  	if err != nil {
   282  		t.Fatalf("commit error: %v", err)
   283  	}
   284  	if hash != exp {
   285  		t.Errorf("root failure. expected %x got %x", exp, hash)
   286  	}
   287  
   288  //对新的trie执行一些插入操作。
   289  	vals2 := []struct{ k, v string }{
   290  		{"do", "verb"},
   291  		{"ether", "wookiedoo"},
   292  		{"horse", "stallion"},
   293  //“萨满”、“马”,
   294  //“狗”,“硬币”,
   295  //{“醚”、“}”
   296  //“狗”,“小狗”,
   297  //“有什么特别的地方是”,“我的孩子”,
   298  //{“萨满”、“}”
   299  	}
   300  	for _, val := range vals2 {
   301  		updateString(trie2, val.k, val.v)
   302  	}
   303  	if hash := trie2.Hash(); hash != exp {
   304  		t.Errorf("root failure. expected %x got %x", exp, hash)
   305  	}
   306  }
   307  
   308  func TestLargeValue(t *testing.T) {
   309  	trie := newEmpty()
   310  	trie.Update([]byte("key1"), []byte{99, 99, 99, 99})
   311  	trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32))
   312  	trie.Hash()
   313  }
   314  
   315  type countingDB struct {
   316  	ethdb.Database
   317  	gets map[string]int
   318  }
   319  
   320  func (db *countingDB) Get(key []byte) ([]byte, error) {
   321  	db.gets[string(key)]++
   322  	return db.Database.Get(key)
   323  }
   324  
   325  //testcacheUnload检查解码后的节点是否在
   326  //一定数量的提交操作。
   327  func TestCacheUnload(t *testing.T) {
   328  //用两个分支创建测试trie。
   329  	trie := newEmpty()
   330  	key1 := "---------------------------------"
   331  	key2 := "---some other branch"
   332  	updateString(trie, key1, "this is the branch of key1.")
   333  	updateString(trie, key2, "this is the branch of key2.")
   334  
   335  	root, _ := trie.Commit(nil)
   336  	trie.db.Commit(root, true)
   337  
   338  //重复提交trie并访问key1。
   339  //包含它的分支从数据库加载两次:
   340  //在第0次和第6次迭代中。
   341  	diskdb := &countingDB{Database: trie.db.diskdb, gets: make(map[string]int)}
   342  	triedb := NewDatabase(diskdb)
   343  	trie, _ = New(root, triedb)
   344  	trie.SetCacheLimit(5)
   345  	for i := 0; i < 12; i++ {
   346  		getString(trie, key1)
   347  		trie.Commit(nil)
   348  	}
   349  //检查它是否装了两次。
   350  	for dbkey, count := range diskdb.gets {
   351  		if count != 2 {
   352  			t.Errorf("db key %x loaded %d times, want %d times", []byte(dbkey), count, 2)
   353  		}
   354  	}
   355  }
   356  
   357  //randtest执行随机trie操作。
   358  //此测试的实例由generate创建。
   359  type randTest []randTestStep
   360  
   361  type randTestStep struct {
   362  	op    int
   363  key   []byte //对于opupdate、opdelete、opget
   364  value []byte //为了更新
   365  err   error  //用于调试
   366  }
   367  
   368  const (
   369  	opUpdate = iota
   370  	opDelete
   371  	opGet
   372  	opCommit
   373  	opHash
   374  	opReset
   375  	opItercheckhash
   376  	opCheckCacheInvariant
   377  opMax //边界值,不是实际操作
   378  )
   379  
   380  func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
   381  	var allKeys [][]byte
   382  	genKey := func() []byte {
   383  		if len(allKeys) < 2 || r.Intn(100) < 10 {
   384  //新密钥
   385  			key := make([]byte, r.Intn(50))
   386  			r.Read(key)
   387  			allKeys = append(allKeys, key)
   388  			return key
   389  		}
   390  //使用现有密钥
   391  		return allKeys[r.Intn(len(allKeys))]
   392  	}
   393  
   394  	var steps randTest
   395  	for i := 0; i < size; i++ {
   396  		step := randTestStep{op: r.Intn(opMax)}
   397  		switch step.op {
   398  		case opUpdate:
   399  			step.key = genKey()
   400  			step.value = make([]byte, 8)
   401  			binary.BigEndian.PutUint64(step.value, uint64(i))
   402  		case opGet, opDelete:
   403  			step.key = genKey()
   404  		}
   405  		steps = append(steps, step)
   406  	}
   407  	return reflect.ValueOf(steps)
   408  }
   409  
   410  func runRandTest(rt randTest) bool {
   411  	triedb := NewDatabase(ethdb.NewMemDatabase())
   412  
   413  	tr, _ := New(common.Hash{}, triedb)
   414  values := make(map[string]string) //跟踪trie的内容
   415  
   416  	for i, step := range rt {
   417  		switch step.op {
   418  		case opUpdate:
   419  			tr.Update(step.key, step.value)
   420  			values[string(step.key)] = string(step.value)
   421  		case opDelete:
   422  			tr.Delete(step.key)
   423  			delete(values, string(step.key))
   424  		case opGet:
   425  			v := tr.Get(step.key)
   426  			want := values[string(step.key)]
   427  			if string(v) != want {
   428  				rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
   429  			}
   430  		case opCommit:
   431  			_, rt[i].err = tr.Commit(nil)
   432  		case opHash:
   433  			tr.Hash()
   434  		case opReset:
   435  			hash, err := tr.Commit(nil)
   436  			if err != nil {
   437  				rt[i].err = err
   438  				return false
   439  			}
   440  			newtr, err := New(hash, triedb)
   441  			if err != nil {
   442  				rt[i].err = err
   443  				return false
   444  			}
   445  			tr = newtr
   446  		case opItercheckhash:
   447  			checktr, _ := New(common.Hash{}, triedb)
   448  			it := NewIterator(tr.NodeIterator(nil))
   449  			for it.Next() {
   450  				checktr.Update(it.Key, it.Value)
   451  			}
   452  			if tr.Hash() != checktr.Hash() {
   453  				rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash")
   454  			}
   455  		case opCheckCacheInvariant:
   456  			rt[i].err = checkCacheInvariant(tr.root, nil, tr.cachegen, false, 0)
   457  		}
   458  //出错时中止测试。
   459  		if rt[i].err != nil {
   460  			return false
   461  		}
   462  	}
   463  	return true
   464  }
   465  
   466  func checkCacheInvariant(n, parent node, parentCachegen uint16, parentDirty bool, depth int) error {
   467  	var children []node
   468  	var flag nodeFlag
   469  	switch n := n.(type) {
   470  	case *shortNode:
   471  		flag = n.flags
   472  		children = []node{n.Val}
   473  	case *fullNode:
   474  		flag = n.flags
   475  		children = n.Children[:]
   476  	default:
   477  		return nil
   478  	}
   479  
   480  	errorf := func(format string, args ...interface{}) error {
   481  		msg := fmt.Sprintf(format, args...)
   482  		msg += fmt.Sprintf("\nat depth %d node %s", depth, spew.Sdump(n))
   483  		msg += fmt.Sprintf("parent: %s", spew.Sdump(parent))
   484  		return errors.New(msg)
   485  	}
   486  	if flag.gen > parentCachegen {
   487  		return errorf("cache invariant violation: %d > %d\n", flag.gen, parentCachegen)
   488  	}
   489  	if depth > 0 && !parentDirty && flag.dirty {
   490  		return errorf("cache invariant violation: %d > %d\n", flag.gen, parentCachegen)
   491  	}
   492  	for _, child := range children {
   493  		if err := checkCacheInvariant(child, n, flag.gen, flag.dirty, depth+1); err != nil {
   494  			return err
   495  		}
   496  	}
   497  	return nil
   498  }
   499  
   500  func TestRandom(t *testing.T) {
   501  	if err := quick.Check(runRandTest, nil); err != nil {
   502  		if cerr, ok := err.(*quick.CheckError); ok {
   503  			t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
   504  		}
   505  		t.Fatal(err)
   506  	}
   507  }
   508  
   509  func BenchmarkGet(b *testing.B)      { benchGet(b, false) }
   510  func BenchmarkGetDB(b *testing.B)    { benchGet(b, true) }
   511  func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) }
   512  func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
   513  
   514  const benchElemCount = 20000
   515  
   516  func benchGet(b *testing.B, commit bool) {
   517  	trie := new(Trie)
   518  	if commit {
   519  		_, tmpdb := tempDB()
   520  		trie, _ = New(common.Hash{}, tmpdb)
   521  	}
   522  	k := make([]byte, 32)
   523  	for i := 0; i < benchElemCount; i++ {
   524  		binary.LittleEndian.PutUint64(k, uint64(i))
   525  		trie.Update(k, k)
   526  	}
   527  	binary.LittleEndian.PutUint64(k, benchElemCount/2)
   528  	if commit {
   529  		trie.Commit(nil)
   530  	}
   531  
   532  	b.ResetTimer()
   533  	for i := 0; i < b.N; i++ {
   534  		trie.Get(k)
   535  	}
   536  	b.StopTimer()
   537  
   538  	if commit {
   539  		ldb := trie.db.diskdb.(*ethdb.LDBDatabase)
   540  		ldb.Close()
   541  		os.RemoveAll(ldb.Path())
   542  	}
   543  }
   544  
   545  func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
   546  	trie := newEmpty()
   547  	k := make([]byte, 32)
   548  	for i := 0; i < b.N; i++ {
   549  		e.PutUint64(k, uint64(i))
   550  		trie.Update(k, k)
   551  	}
   552  	return trie
   553  }
   554  
   555  //测试trie散列。由于trie缓存任何操作的结果,
   556  //我们不能用b.n作为散列rouns的数目,因为除了
   557  //第一个将是noop。因此,我们将使用B.N作为
   558  //在测量散列之前插入trie。
   559  func BenchmarkHash(b *testing.B) {
   560  //使随机基准具有确定性
   561  	random := rand.New(rand.NewSource(0))
   562  
   563  //创建一个真实的帐户trie to hash
   564  	addresses := make([][20]byte, b.N)
   565  	for i := 0; i < len(addresses); i++ {
   566  		for j := 0; j < len(addresses[i]); j++ {
   567  			addresses[i][j] = byte(random.Intn(256))
   568  		}
   569  	}
   570  	accounts := make([][]byte, len(addresses))
   571  	for i := 0; i < len(accounts); i++ {
   572  		var (
   573  			nonce   = uint64(random.Int63())
   574  			balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
   575  			root    = emptyRoot
   576  			code    = crypto.Keccak256(nil)
   577  		)
   578  		accounts[i], _ = rlp.EncodeToBytes([]interface{}{nonce, balance, root, code})
   579  	}
   580  //将帐户插入trie并散列它
   581  	trie := newEmpty()
   582  	for i := 0; i < len(addresses); i++ {
   583  		trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
   584  	}
   585  	b.ResetTimer()
   586  	b.ReportAllocs()
   587  	trie.Hash()
   588  }
   589  
   590  func tempDB() (string, *Database) {
   591  	dir, err := ioutil.TempDir("", "trie-bench")
   592  	if err != nil {
   593  		panic(fmt.Sprintf("can't create temporary directory: %v", err))
   594  	}
   595  	diskdb, err := ethdb.NewLDBDatabase(dir, 256, 0)
   596  	if err != nil {
   597  		panic(fmt.Sprintf("can't create temporary database: %v", err))
   598  	}
   599  	return dir, NewDatabase(diskdb)
   600  }
   601  
   602  func getString(trie *Trie, k string) []byte {
   603  	return trie.Get([]byte(k))
   604  }
   605  
   606  func updateString(trie *Trie, k, v string) {
   607  	trie.Update([]byte(k), []byte(v))
   608  }
   609  
   610  func deleteString(trie *Trie, k string) {
   611  	trie.Delete([]byte(k))
   612  }
   613