You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

322 lines
8.8 KiB

  1. package arbo
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "math/big"
  6. "testing"
  7. "time"
  8. qt "github.com/frankban/quicktest"
  9. "github.com/iden3/go-merkletree/db/memory"
  10. )
  11. func TestAddBatchCaseA(t *testing.T) {
  12. c := qt.New(t)
  13. nLeafs := 1024
  14. tree, err := NewTree(memory.NewMemoryStorage(), 100, HashFunctionPoseidon)
  15. c.Assert(err, qt.IsNil)
  16. defer tree.db.Close()
  17. start := time.Now()
  18. for i := 0; i < nLeafs; i++ {
  19. k := BigIntToBytes(big.NewInt(int64(i)))
  20. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  21. if err := tree.Add(k, v); err != nil {
  22. t.Fatal(err)
  23. }
  24. }
  25. fmt.Println(time.Since(start))
  26. tree2, err := NewTree(memory.NewMemoryStorage(), 100, HashFunctionPoseidon)
  27. c.Assert(err, qt.IsNil)
  28. defer tree2.db.Close()
  29. var keys, values [][]byte
  30. for i := 0; i < nLeafs; i++ {
  31. k := BigIntToBytes(big.NewInt(int64(i)))
  32. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  33. keys = append(keys, k)
  34. values = append(values, v)
  35. }
  36. start = time.Now()
  37. indexes, err := tree2.AddBatchOpt(keys, values)
  38. c.Assert(err, qt.IsNil)
  39. fmt.Println(time.Since(start))
  40. c.Check(len(indexes), qt.Equals, 0)
  41. // check that both trees roots are equal
  42. c.Check(tree2.Root(), qt.DeepEquals, tree.Root())
  43. }
  44. func TestAddBatchCaseB(t *testing.T) {
  45. c := qt.New(t)
  46. nLeafs := 1024
  47. tree, err := NewTree(memory.NewMemoryStorage(), 100, HashFunctionPoseidon)
  48. c.Assert(err, qt.IsNil)
  49. defer tree.db.Close()
  50. start := time.Now()
  51. for i := 0; i < nLeafs; i++ {
  52. k := BigIntToBytes(big.NewInt(int64(i)))
  53. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  54. if err := tree.Add(k, v); err != nil {
  55. t.Fatal(err)
  56. }
  57. }
  58. fmt.Println(time.Since(start))
  59. tree2, err := NewTree(memory.NewMemoryStorage(), 100, HashFunctionPoseidon)
  60. c.Assert(err, qt.IsNil)
  61. defer tree2.db.Close()
  62. // add the initial leafs to fill a bit the tree before calling the
  63. // AddBatch method
  64. for i := 0; i < 99; i++ { // TMP TODO use const minLeafsThreshold-1 once ready
  65. k := BigIntToBytes(big.NewInt(int64(i)))
  66. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  67. if err := tree2.Add(k, v); err != nil {
  68. t.Fatal(err)
  69. }
  70. }
  71. var keys, values [][]byte
  72. for i := 99; i < nLeafs; i++ {
  73. k := BigIntToBytes(big.NewInt(int64(i)))
  74. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  75. keys = append(keys, k)
  76. values = append(values, v)
  77. }
  78. start = time.Now()
  79. indexes, err := tree2.AddBatchOpt(keys, values)
  80. c.Assert(err, qt.IsNil)
  81. fmt.Println(time.Since(start))
  82. c.Check(len(indexes), qt.Equals, 0)
  83. // check that both trees roots are equal
  84. c.Check(tree2.Root(), qt.DeepEquals, tree.Root())
  85. }
  86. func TestGetKeysAtLevel(t *testing.T) {
  87. c := qt.New(t)
  88. tree, err := NewTree(memory.NewMemoryStorage(), 100, HashFunctionPoseidon)
  89. c.Assert(err, qt.IsNil)
  90. defer tree.db.Close()
  91. for i := 0; i < 32; i++ {
  92. k := BigIntToBytes(big.NewInt(int64(i)))
  93. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  94. if err := tree.Add(k, v); err != nil {
  95. t.Fatal(err)
  96. }
  97. }
  98. keys, err := tree.getKeysAtLevel(2)
  99. c.Assert(err, qt.IsNil)
  100. expected := []string{
  101. "a5d5f14fce7348e40751496cf25d107d91b0bd043435b9577d778a01f8aa6111",
  102. "e9e8dd9b28a7f81d1ff34cb5cefc0146dd848b31031a427b79bdadb62e7f6910",
  103. }
  104. for i := 0; i < len(keys); i++ {
  105. c.Assert(hex.EncodeToString(keys[i]), qt.Equals, expected[i])
  106. }
  107. keys, err = tree.getKeysAtLevel(3)
  108. c.Assert(err, qt.IsNil)
  109. expected = []string{
  110. "9f12c13e52bca96ad4882a26558e48ab67ddd63e062b839207e893d961390f01",
  111. "16d246dd6826ec7346c7328f11c4261facf82d4689f33263ff6e207956a77f21",
  112. "4a22cc901c6337daa17a431fa20170684b710e5f551509511492ec24e81a8f2f",
  113. "470d61abcbd154977bffc9a9ec5a8daff0caabcf2a25e8441f604c79daa0f82d",
  114. }
  115. for i := 0; i < len(keys); i++ {
  116. c.Assert(hex.EncodeToString(keys[i]), qt.Equals, expected[i])
  117. }
  118. keys, err = tree.getKeysAtLevel(4)
  119. c.Assert(err, qt.IsNil)
  120. expected = []string{
  121. "7a5d1c81f7b96318012de3417e53d4f13df5b1337718651cd29d0cb0a66edd20",
  122. "3408213e4e844bdf3355eb8781c74e31626812898c2dbe141ed6d2c92256fc1c",
  123. "dfd8a4d0b6954a3e9f3892e655b58d456eeedf9367f27dfdd9bc2dd6a5577312",
  124. "9e99fbec06fb2a6725997c12c4995f62725eb4cce4808523a5a5e80cca64b007",
  125. "0befa1e070231dbf4e8ff841c05878cdec823e0c09594c24910a248b3ff5a628",
  126. "b7131b0a15c772a57005a4dc5d0d6dd4b3414f5d9ee7408ce5e86c5ab3520e04",
  127. "6d1abe0364077846a56bab1deb1a04883eb796b74fe531a7676a9a370f83ab21",
  128. "4270116394bede69cf9cd72069eca018238080380bef5de75be8dcbbe968e105",
  129. }
  130. for i := 0; i < len(keys); i++ {
  131. c.Assert(hex.EncodeToString(keys[i]), qt.Equals, expected[i])
  132. }
  133. }
  134. func TestSplitInBuckets(t *testing.T) {
  135. c := qt.New(t)
  136. nLeafs := 16
  137. kvs := make([]kv, nLeafs)
  138. for i := 0; i < nLeafs; i++ {
  139. k := BigIntToBytes(big.NewInt(int64(i)))
  140. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  141. keyPath := make([]byte, 32)
  142. copy(keyPath[:], k)
  143. kvs[i].pos = i
  144. kvs[i].keyPath = k
  145. kvs[i].k = k
  146. kvs[i].v = v
  147. }
  148. // check keyToBucket results for 4 buckets & 8 keys
  149. c.Assert(keyToBucket(kvs[0].k, 4), qt.Equals, 0)
  150. c.Assert(keyToBucket(kvs[1].k, 4), qt.Equals, 2)
  151. c.Assert(keyToBucket(kvs[2].k, 4), qt.Equals, 1)
  152. c.Assert(keyToBucket(kvs[3].k, 4), qt.Equals, 3)
  153. c.Assert(keyToBucket(kvs[4].k, 4), qt.Equals, 0)
  154. c.Assert(keyToBucket(kvs[5].k, 4), qt.Equals, 2)
  155. c.Assert(keyToBucket(kvs[6].k, 4), qt.Equals, 1)
  156. c.Assert(keyToBucket(kvs[7].k, 4), qt.Equals, 3)
  157. // check keyToBucket results for 8 buckets & 8 keys
  158. c.Assert(keyToBucket(kvs[0].k, 8), qt.Equals, 0)
  159. c.Assert(keyToBucket(kvs[1].k, 8), qt.Equals, 4)
  160. c.Assert(keyToBucket(kvs[2].k, 8), qt.Equals, 2)
  161. c.Assert(keyToBucket(kvs[3].k, 8), qt.Equals, 6)
  162. c.Assert(keyToBucket(kvs[4].k, 8), qt.Equals, 1)
  163. c.Assert(keyToBucket(kvs[5].k, 8), qt.Equals, 5)
  164. c.Assert(keyToBucket(kvs[6].k, 8), qt.Equals, 3)
  165. c.Assert(keyToBucket(kvs[7].k, 8), qt.Equals, 7)
  166. buckets := splitInBuckets(kvs, 4)
  167. expected := [][]string{
  168. {
  169. "00000000", // bucket 0
  170. "08000000",
  171. "04000000",
  172. "0c000000",
  173. },
  174. {
  175. "02000000", // bucket 1
  176. "0a000000",
  177. "06000000",
  178. "0e000000",
  179. },
  180. {
  181. "01000000", // bucket 2
  182. "09000000",
  183. "05000000",
  184. "0d000000",
  185. },
  186. {
  187. "03000000", // bucket 3
  188. "0b000000",
  189. "07000000",
  190. "0f000000",
  191. },
  192. }
  193. for i := 0; i < len(buckets); i++ {
  194. sortKvs(buckets[i])
  195. c.Assert(len(buckets[i]), qt.Equals, len(expected[i]))
  196. for j := 0; j < len(buckets[i]); j++ {
  197. c.Check(hex.EncodeToString(buckets[i][j].k[:4]), qt.Equals, expected[i][j])
  198. }
  199. }
  200. }
  201. func TestAddBatchCaseC(t *testing.T) {
  202. c := qt.New(t)
  203. nLeafs := 1024
  204. tree, err := NewTree(memory.NewMemoryStorage(), 100, HashFunctionPoseidon)
  205. c.Assert(err, qt.IsNil)
  206. defer tree.db.Close()
  207. start := time.Now()
  208. for i := 0; i < nLeafs; i++ {
  209. k := BigIntToBytes(big.NewInt(int64(i)))
  210. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  211. if err := tree.Add(k, v); err != nil {
  212. t.Fatal(err)
  213. }
  214. }
  215. fmt.Println(time.Since(start))
  216. tree2, err := NewTree(memory.NewMemoryStorage(), 100, HashFunctionPoseidon)
  217. c.Assert(err, qt.IsNil)
  218. defer tree2.db.Close()
  219. // add the initial leafs to fill a bit the tree before calling the
  220. // AddBatch method
  221. for i := 0; i < 101; i++ { // TMP TODO use const minLeafsThreshold-1 once ready
  222. k := BigIntToBytes(big.NewInt(int64(i)))
  223. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  224. if err := tree2.Add(k, v); err != nil {
  225. t.Fatal(err)
  226. }
  227. }
  228. // tree2.PrintGraphviz(nil)
  229. var keys, values [][]byte
  230. for i := 101; i < nLeafs; i++ {
  231. k := BigIntToBytes(big.NewInt(int64(i)))
  232. v := BigIntToBytes(big.NewInt(int64(i * 2)))
  233. keys = append(keys, k)
  234. values = append(values, v)
  235. }
  236. start = time.Now()
  237. indexes, err := tree2.AddBatchOpt(keys, values)
  238. c.Assert(err, qt.IsNil)
  239. fmt.Println(time.Since(start))
  240. c.Check(len(indexes), qt.Equals, 0)
  241. // check that both trees roots are equal
  242. c.Check(tree2.Root(), qt.DeepEquals, tree.Root())
  243. // tree.PrintGraphviz(nil)
  244. // tree2.PrintGraphviz(nil)
  245. // // tree.PrintGraphvizFirstNLevels(nil, 4)
  246. // // tree2.PrintGraphvizFirstNLevels(nil, 4)
  247. // fmt.Println("TREE")
  248. // printLeafs("t1.txt", tree)
  249. // fmt.Println("TREE2")
  250. // printLeafs("t2.txt", tree2)
  251. }
  252. // func printLeafs(name string, t *Tree) {
  253. // w := bytes.NewBufferString("")
  254. //
  255. // err := t.Iterate(func(k, v []byte) {
  256. // if v[0] != PrefixValueLeaf {
  257. // return
  258. // }
  259. // leafK, _ := readLeafValue(v)
  260. // fmt.Fprintf(w, hex.EncodeToString(leafK[:4])+"\n")
  261. // })
  262. // if err != nil {
  263. // panic(err)
  264. // }
  265. // err = ioutil.WriteFile(name, w.Bytes(), 0644)
  266. // if err != nil {
  267. // panic(err)
  268. // }
  269. //
  270. // }
  271. // func TestComputeCosts(t *testing.T) {
  272. // fmt.Println(computeSimpleAddCost(10))
  273. // fmt.Println(computeBottomUpAddCost(10))
  274. //
  275. // fmt.Println(computeSimpleAddCost(1024))
  276. // fmt.Println(computeBottomUpAddCost(1024))
  277. // }
  278. // TODO test tree with nLeafs > minLeafsThreshold, but that at level L, there is
  279. // less keys than nBuckets (so CASE C could be applied if first few leafs are
  280. // added to balance the tree)