trie_test.go 10 KB

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