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