trie_test.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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. package trie
  17. import (
  18. "bytes"
  19. "encoding/binary"
  20. "fmt"
  21. "io/ioutil"
  22. "os"
  23. "testing"
  24. "github.com/davecgh/go-spew/spew"
  25. "github.com/ethereum/go-ethereum/common"
  26. "github.com/ethereum/go-ethereum/ethdb"
  27. )
  28. func init() {
  29. spew.Config.Indent = " "
  30. spew.Config.DisableMethods = true
  31. }
  32. // Used for testing
  33. func newEmpty() *Trie {
  34. db, _ := ethdb.NewMemDatabase()
  35. trie, _ := New(common.Hash{}, db)
  36. return trie
  37. }
  38. func TestEmptyTrie(t *testing.T) {
  39. var trie Trie
  40. res := trie.Hash()
  41. exp := emptyRoot
  42. if res != common.Hash(exp) {
  43. t.Errorf("expected %x got %x", exp, res)
  44. }
  45. }
  46. func TestNull(t *testing.T) {
  47. var trie Trie
  48. key := make([]byte, 32)
  49. value := common.FromHex("0x823140710bf13990e4500136726d8b55")
  50. trie.Update(key, value)
  51. value = trie.Get(key)
  52. }
  53. func TestMissingRoot(t *testing.T) {
  54. db, _ := ethdb.NewMemDatabase()
  55. trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), db)
  56. if trie != nil {
  57. t.Error("New returned non-nil trie for invalid root")
  58. }
  59. if err != ErrMissingRoot {
  60. t.Error("New returned wrong error: %v", err)
  61. }
  62. }
  63. func TestInsert(t *testing.T) {
  64. trie := newEmpty()
  65. updateString(trie, "doe", "reindeer")
  66. updateString(trie, "dog", "puppy")
  67. updateString(trie, "dogglesworth", "cat")
  68. exp := common.HexToHash("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3")
  69. root := trie.Hash()
  70. if root != exp {
  71. t.Errorf("exp %x got %x", exp, root)
  72. }
  73. trie = newEmpty()
  74. updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
  75. exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
  76. root, err := trie.Commit()
  77. if err != nil {
  78. t.Fatalf("commit error: %v", err)
  79. }
  80. if root != exp {
  81. t.Errorf("exp %x got %x", exp, root)
  82. }
  83. }
  84. func TestGet(t *testing.T) {
  85. trie := newEmpty()
  86. updateString(trie, "doe", "reindeer")
  87. updateString(trie, "dog", "puppy")
  88. updateString(trie, "dogglesworth", "cat")
  89. for i := 0; i < 2; i++ {
  90. res := getString(trie, "dog")
  91. if !bytes.Equal(res, []byte("puppy")) {
  92. t.Errorf("expected puppy got %x", res)
  93. }
  94. unknown := getString(trie, "unknown")
  95. if unknown != nil {
  96. t.Errorf("expected nil got %x", unknown)
  97. }
  98. if i == 1 {
  99. return
  100. }
  101. trie.Commit()
  102. }
  103. }
  104. func TestDelete(t *testing.T) {
  105. trie := newEmpty()
  106. vals := []struct{ k, v string }{
  107. {"do", "verb"},
  108. {"ether", "wookiedoo"},
  109. {"horse", "stallion"},
  110. {"shaman", "horse"},
  111. {"doge", "coin"},
  112. {"ether", ""},
  113. {"dog", "puppy"},
  114. {"shaman", ""},
  115. }
  116. for _, val := range vals {
  117. if val.v != "" {
  118. updateString(trie, val.k, val.v)
  119. } else {
  120. deleteString(trie, val.k)
  121. }
  122. }
  123. hash := trie.Hash()
  124. exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
  125. if hash != exp {
  126. t.Errorf("expected %x got %x", exp, hash)
  127. }
  128. }
  129. func TestEmptyValues(t *testing.T) {
  130. trie := newEmpty()
  131. vals := []struct{ k, v string }{
  132. {"do", "verb"},
  133. {"ether", "wookiedoo"},
  134. {"horse", "stallion"},
  135. {"shaman", "horse"},
  136. {"doge", "coin"},
  137. {"ether", ""},
  138. {"dog", "puppy"},
  139. {"shaman", ""},
  140. }
  141. for _, val := range vals {
  142. updateString(trie, val.k, val.v)
  143. }
  144. hash := trie.Hash()
  145. exp := common.HexToHash("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
  146. if hash != exp {
  147. t.Errorf("expected %x got %x", exp, hash)
  148. }
  149. }
  150. func TestReplication(t *testing.T) {
  151. trie := newEmpty()
  152. vals := []struct{ k, v string }{
  153. {"do", "verb"},
  154. {"ether", "wookiedoo"},
  155. {"horse", "stallion"},
  156. {"shaman", "horse"},
  157. {"doge", "coin"},
  158. {"dog", "puppy"},
  159. {"somethingveryoddindeedthis is", "myothernodedata"},
  160. }
  161. for _, val := range vals {
  162. updateString(trie, val.k, val.v)
  163. }
  164. exp, err := trie.Commit()
  165. if err != nil {
  166. t.Fatalf("commit error: %v", err)
  167. }
  168. // create a new trie on top of the database and check that lookups work.
  169. trie2, err := New(exp, trie.db)
  170. if err != nil {
  171. t.Fatalf("can't recreate trie at %x: %v", exp, err)
  172. }
  173. for _, kv := range vals {
  174. if string(getString(trie2, kv.k)) != kv.v {
  175. t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
  176. }
  177. }
  178. hash, err := trie2.Commit()
  179. if err != nil {
  180. t.Fatalf("commit error: %v", err)
  181. }
  182. if hash != exp {
  183. t.Errorf("root failure. expected %x got %x", exp, hash)
  184. }
  185. // perform some insertions on the new trie.
  186. vals2 := []struct{ k, v string }{
  187. {"do", "verb"},
  188. {"ether", "wookiedoo"},
  189. {"horse", "stallion"},
  190. // {"shaman", "horse"},
  191. // {"doge", "coin"},
  192. // {"ether", ""},
  193. // {"dog", "puppy"},
  194. // {"somethingveryoddindeedthis is", "myothernodedata"},
  195. // {"shaman", ""},
  196. }
  197. for _, val := range vals2 {
  198. updateString(trie2, val.k, val.v)
  199. }
  200. if trie2.Hash() != exp {
  201. t.Errorf("root failure. expected %x got %x", exp, hash)
  202. }
  203. }
  204. func paranoiaCheck(t1 *Trie) (bool, *Trie) {
  205. t2 := new(Trie)
  206. it := NewIterator(t1)
  207. for it.Next() {
  208. t2.Update(it.Key, it.Value)
  209. }
  210. return t2.Hash() == t1.Hash(), t2
  211. }
  212. func TestParanoia(t *testing.T) {
  213. t.Skip()
  214. trie := newEmpty()
  215. vals := []struct{ k, v string }{
  216. {"do", "verb"},
  217. {"ether", "wookiedoo"},
  218. {"horse", "stallion"},
  219. {"shaman", "horse"},
  220. {"doge", "coin"},
  221. {"ether", ""},
  222. {"dog", "puppy"},
  223. {"shaman", ""},
  224. {"somethingveryoddindeedthis is", "myothernodedata"},
  225. }
  226. for _, val := range vals {
  227. updateString(trie, val.k, val.v)
  228. }
  229. trie.Commit()
  230. ok, t2 := paranoiaCheck(trie)
  231. if !ok {
  232. t.Errorf("trie paranoia check failed %x %x", trie.Hash(), t2.Hash())
  233. }
  234. }
  235. // Not an actual test
  236. func TestOutput(t *testing.T) {
  237. t.Skip()
  238. base := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  239. trie := newEmpty()
  240. for i := 0; i < 50; i++ {
  241. updateString(trie, fmt.Sprintf("%s%d", base, i), "valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
  242. }
  243. fmt.Println("############################## FULL ################################")
  244. fmt.Println(trie.root)
  245. trie.Commit()
  246. fmt.Println("############################## SMALL ################################")
  247. trie2, _ := New(trie.Hash(), trie.db)
  248. getString(trie2, base+"20")
  249. fmt.Println(trie2.root)
  250. }
  251. func TestLargeValue(t *testing.T) {
  252. trie := newEmpty()
  253. trie.Update([]byte("key1"), []byte{99, 99, 99, 99})
  254. trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32))
  255. trie.Hash()
  256. }
  257. type kv struct {
  258. k, v []byte
  259. t bool
  260. }
  261. func TestLargeData(t *testing.T) {
  262. trie := newEmpty()
  263. vals := make(map[string]*kv)
  264. for i := byte(0); i < 255; i++ {
  265. value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false}
  266. value2 := &kv{common.LeftPadBytes([]byte{10, i}, 32), []byte{i}, false}
  267. trie.Update(value.k, value.v)
  268. trie.Update(value2.k, value2.v)
  269. vals[string(value.k)] = value
  270. vals[string(value2.k)] = value2
  271. }
  272. it := NewIterator(trie)
  273. for it.Next() {
  274. vals[string(it.Key)].t = true
  275. }
  276. var untouched []*kv
  277. for _, value := range vals {
  278. if !value.t {
  279. untouched = append(untouched, value)
  280. }
  281. }
  282. if len(untouched) > 0 {
  283. t.Errorf("Missed %d nodes", len(untouched))
  284. for _, value := range untouched {
  285. t.Error(value)
  286. }
  287. }
  288. }
  289. func BenchmarkGet(b *testing.B) { benchGet(b, false) }
  290. func BenchmarkGetDB(b *testing.B) { benchGet(b, true) }
  291. func BenchmarkUpdateBE(b *testing.B) { benchUpdate(b, binary.BigEndian) }
  292. func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
  293. func BenchmarkHashBE(b *testing.B) { benchHash(b, binary.BigEndian) }
  294. func BenchmarkHashLE(b *testing.B) { benchHash(b, binary.LittleEndian) }
  295. const benchElemCount = 20000
  296. func benchGet(b *testing.B, commit bool) {
  297. trie := new(Trie)
  298. if commit {
  299. dir, tmpdb := tempDB()
  300. defer os.RemoveAll(dir)
  301. trie, _ = New(common.Hash{}, tmpdb)
  302. }
  303. k := make([]byte, 32)
  304. for i := 0; i < benchElemCount; i++ {
  305. binary.LittleEndian.PutUint64(k, uint64(i))
  306. trie.Update(k, k)
  307. }
  308. binary.LittleEndian.PutUint64(k, benchElemCount/2)
  309. if commit {
  310. trie.Commit()
  311. }
  312. b.ResetTimer()
  313. for i := 0; i < b.N; i++ {
  314. trie.Get(k)
  315. }
  316. }
  317. func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
  318. trie := newEmpty()
  319. k := make([]byte, 32)
  320. for i := 0; i < b.N; i++ {
  321. e.PutUint64(k, uint64(i))
  322. trie.Update(k, k)
  323. }
  324. return trie
  325. }
  326. func benchHash(b *testing.B, e binary.ByteOrder) {
  327. trie := newEmpty()
  328. k := make([]byte, 32)
  329. for i := 0; i < benchElemCount; i++ {
  330. e.PutUint64(k, uint64(i))
  331. trie.Update(k, k)
  332. }
  333. b.ResetTimer()
  334. for i := 0; i < b.N; i++ {
  335. trie.Hash()
  336. }
  337. }
  338. func tempDB() (string, Database) {
  339. dir, err := ioutil.TempDir("", "trie-bench")
  340. if err != nil {
  341. panic(fmt.Sprintf("can't create temporary directory: %v", err))
  342. }
  343. db, err := ethdb.NewLDBDatabase(dir, 300*1024)
  344. if err != nil {
  345. panic(fmt.Sprintf("can't create temporary database: %v", err))
  346. }
  347. return dir, db
  348. }
  349. func getString(trie *Trie, k string) []byte {
  350. return trie.Get([]byte(k))
  351. }
  352. func updateString(trie *Trie, k, v string) {
  353. trie.Update([]byte(k), []byte(v))
  354. }
  355. func deleteString(trie *Trie, k string) {
  356. trie.Delete([]byte(k))
  357. }