github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/trie/secure_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  //</624450123396550656>
    11  
    12  
    13  package trie
    14  
    15  import (
    16  	"bytes"
    17  	"runtime"
    18  	"sync"
    19  	"testing"
    20  
    21  	"github.com/ethereum/go-ethereum/common"
    22  	"github.com/ethereum/go-ethereum/crypto"
    23  	"github.com/ethereum/go-ethereum/ethdb"
    24  )
    25  
    26  func newEmptySecure() *SecureTrie {
    27  	trie, _ := NewSecure(common.Hash{}, NewDatabase(ethdb.NewMemDatabase()), 0)
    28  	return trie
    29  }
    30  
    31  //maketestsecuretrie为测试创建足够大的安全trie。
    32  func makeTestSecureTrie() (*Database, *SecureTrie, map[string][]byte) {
    33  //创建空的trie
    34  	triedb := NewDatabase(ethdb.NewMemDatabase())
    35  
    36  	trie, _ := NewSecure(common.Hash{}, triedb, 0)
    37  
    38  //用任意数据填充它
    39  	content := make(map[string][]byte)
    40  	for i := byte(0); i < 255; i++ {
    41  //在多个键下映射相同的数据
    42  		key, val := common.LeftPadBytes([]byte{1, i}, 32), []byte{i}
    43  		content[string(key)] = val
    44  		trie.Update(key, val)
    45  
    46  		key, val = common.LeftPadBytes([]byte{2, i}, 32), []byte{i}
    47  		content[string(key)] = val
    48  		trie.Update(key, val)
    49  
    50  //添加一些其他数据来填充trie
    51  		for j := byte(3); j < 13; j++ {
    52  			key, val = common.LeftPadBytes([]byte{j, i}, 32), []byte{j, i}
    53  			content[string(key)] = val
    54  			trie.Update(key, val)
    55  		}
    56  	}
    57  	trie.Commit(nil)
    58  
    59  //返回生成的trie
    60  	return triedb, trie, content
    61  }
    62  
    63  func TestSecureDelete(t *testing.T) {
    64  	trie := newEmptySecure()
    65  	vals := []struct{ k, v string }{
    66  		{"do", "verb"},
    67  		{"ether", "wookiedoo"},
    68  		{"horse", "stallion"},
    69  		{"shaman", "horse"},
    70  		{"doge", "coin"},
    71  		{"ether", ""},
    72  		{"dog", "puppy"},
    73  		{"shaman", ""},
    74  	}
    75  	for _, val := range vals {
    76  		if val.v != "" {
    77  			trie.Update([]byte(val.k), []byte(val.v))
    78  		} else {
    79  			trie.Delete([]byte(val.k))
    80  		}
    81  	}
    82  	hash := trie.Hash()
    83  	exp := common.HexToHash("29b235a58c3c25ab83010c327d5932bcf05324b7d6b1185e650798034783ca9d")
    84  	if hash != exp {
    85  		t.Errorf("expected %x got %x", exp, hash)
    86  	}
    87  }
    88  
    89  func TestSecureGetKey(t *testing.T) {
    90  	trie := newEmptySecure()
    91  	trie.Update([]byte("foo"), []byte("bar"))
    92  
    93  	key := []byte("foo")
    94  	value := []byte("bar")
    95  	seckey := crypto.Keccak256(key)
    96  
    97  	if !bytes.Equal(trie.Get(key), value) {
    98  		t.Errorf("Get did not return bar")
    99  	}
   100  	if k := trie.GetKey(seckey); !bytes.Equal(k, key) {
   101  		t.Errorf("GetKey returned %q, want %q", k, key)
   102  	}
   103  }
   104  
   105  func TestSecureTrieConcurrency(t *testing.T) {
   106  //为并发访问创建初始trie和copy if
   107  	_, trie, _ := makeTestSecureTrie()
   108  
   109  	threads := runtime.NumCPU()
   110  	tries := make([]*SecureTrie, threads)
   111  	for i := 0; i < threads; i++ {
   112  		cpy := *trie
   113  		tries[i] = &cpy
   114  	}
   115  //启动一批Goroutines与Trie交互
   116  	pend := new(sync.WaitGroup)
   117  	pend.Add(threads)
   118  	for i := 0; i < threads; i++ {
   119  		go func(index int) {
   120  			defer pend.Done()
   121  
   122  			for j := byte(0); j < 255; j++ {
   123  //在多个键下映射相同的数据
   124  				key, val := common.LeftPadBytes([]byte{byte(index), 1, j}, 32), []byte{j}
   125  				tries[index].Update(key, val)
   126  
   127  				key, val = common.LeftPadBytes([]byte{byte(index), 2, j}, 32), []byte{j}
   128  				tries[index].Update(key, val)
   129  
   130  //添加一些其他数据来填充trie
   131  				for k := byte(3); k < 13; k++ {
   132  					key, val = common.LeftPadBytes([]byte{byte(index), k, j}, 32), []byte{k, j}
   133  					tries[index].Update(key, val)
   134  				}
   135  			}
   136  			tries[index].Commit(nil)
   137  		}(i)
   138  	}
   139  //等待所有线程完成
   140  	pend.Wait()
   141  }
   142