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.

462 lines
13 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package arbo
  2. import (
  3. "encoding/hex"
  4. "math/big"
  5. "testing"
  6. "time"
  7. qt "github.com/frankban/quicktest"
  8. "go.vocdoni.io/dvote/db"
  9. )
  10. func TestDBBatch(t *testing.T) {
  11. c := qt.New(t)
  12. database, err := db.NewBadgerDB(c.TempDir())
  13. c.Assert(err, qt.IsNil)
  14. b := database.NewBatch()
  15. err = b.Put([]byte("a"), []byte("b"))
  16. c.Assert(err, qt.IsNil)
  17. }
  18. func TestAddTestVectors(t *testing.T) {
  19. c := qt.New(t)
  20. // Poseidon test vectors generated using https://github.com/iden3/circomlib smt.js
  21. testVectorsPoseidon := []string{
  22. "0000000000000000000000000000000000000000000000000000000000000000",
  23. "13578938674299138072471463694055224830892726234048532520316387704878000008795",
  24. "5412393676474193513566895793055462193090331607895808993925969873307089394741",
  25. "14204494359367183802864593755198662203838502594566452929175967972147978322084",
  26. }
  27. testAdd(c, HashFunctionPoseidon, testVectorsPoseidon)
  28. testVectorsSha256 := []string{
  29. "0000000000000000000000000000000000000000000000000000000000000000",
  30. "46910109172468462938850740851377282682950237270676610513794735904325820156367",
  31. "59481735341404520835410489183267411392292882901306595567679529387376287440550",
  32. "20573794434149960984975763118181266662429997821552560184909083010514790081771",
  33. }
  34. testAdd(c, HashFunctionSha256, testVectorsSha256)
  35. }
  36. func testAdd(c *qt.C, hashFunc HashFunction, testVectors []string) {
  37. database, err := db.NewBadgerDB(c.TempDir())
  38. c.Assert(err, qt.IsNil)
  39. tree, err := NewTree(database, 10, hashFunc)
  40. c.Assert(err, qt.IsNil)
  41. defer tree.db.Close() //nolint:errcheck
  42. c.Check(hex.EncodeToString(tree.Root()), qt.Equals, testVectors[0])
  43. bLen := hashFunc.Len()
  44. err = tree.Add(
  45. BigIntToBytes(bLen, big.NewInt(1)),
  46. BigIntToBytes(bLen, big.NewInt(2)))
  47. c.Assert(err, qt.IsNil)
  48. rootBI := BytesToBigInt(tree.Root())
  49. c.Check(rootBI.String(), qt.Equals, testVectors[1])
  50. err = tree.Add(
  51. BigIntToBytes(bLen, big.NewInt(33)),
  52. BigIntToBytes(bLen, big.NewInt(44)))
  53. c.Assert(err, qt.IsNil)
  54. rootBI = BytesToBigInt(tree.Root())
  55. c.Check(rootBI.String(), qt.Equals, testVectors[2])
  56. err = tree.Add(
  57. BigIntToBytes(bLen, big.NewInt(1234)),
  58. BigIntToBytes(bLen, big.NewInt(9876)))
  59. c.Assert(err, qt.IsNil)
  60. rootBI = BytesToBigInt(tree.Root())
  61. c.Check(rootBI.String(), qt.Equals, testVectors[3])
  62. }
  63. func TestAddBatch(t *testing.T) {
  64. c := qt.New(t)
  65. database, err := db.NewBadgerDB(c.TempDir())
  66. c.Assert(err, qt.IsNil)
  67. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  68. c.Assert(err, qt.IsNil)
  69. defer tree.db.Close() //nolint:errcheck
  70. bLen := tree.HashFunction().Len()
  71. for i := 0; i < 1000; i++ {
  72. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  73. v := BigIntToBytes(bLen, big.NewInt(0))
  74. if err := tree.Add(k, v); err != nil {
  75. t.Fatal(err)
  76. }
  77. }
  78. rootBI := BytesToBigInt(tree.Root())
  79. c.Check(rootBI.String(), qt.Equals,
  80. "296519252211642170490407814696803112091039265640052570497930797516015811235")
  81. database, err = db.NewBadgerDB(c.TempDir())
  82. c.Assert(err, qt.IsNil)
  83. tree2, err := NewTree(database, 100, HashFunctionPoseidon)
  84. c.Assert(err, qt.IsNil)
  85. defer tree2.db.Close() //nolint:errcheck
  86. var keys, values [][]byte
  87. for i := 0; i < 1000; i++ {
  88. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  89. v := BigIntToBytes(bLen, big.NewInt(0))
  90. keys = append(keys, k)
  91. values = append(values, v)
  92. }
  93. indexes, err := tree2.AddBatch(keys, values)
  94. c.Assert(err, qt.IsNil)
  95. c.Check(len(indexes), qt.Equals, 0)
  96. rootBI = BytesToBigInt(tree2.Root())
  97. c.Check(rootBI.String(), qt.Equals,
  98. "296519252211642170490407814696803112091039265640052570497930797516015811235")
  99. }
  100. func TestAddDifferentOrder(t *testing.T) {
  101. c := qt.New(t)
  102. database1, err := db.NewBadgerDB(c.TempDir())
  103. c.Assert(err, qt.IsNil)
  104. tree1, err := NewTree(database1, 100, HashFunctionPoseidon)
  105. c.Assert(err, qt.IsNil)
  106. defer tree1.db.Close() //nolint:errcheck
  107. bLen := tree1.HashFunction().Len()
  108. for i := 0; i < 16; i++ {
  109. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  110. v := BigIntToBytes(bLen, big.NewInt(0))
  111. if err := tree1.Add(k, v); err != nil {
  112. t.Fatal(err)
  113. }
  114. }
  115. database2, err := db.NewBadgerDB(c.TempDir())
  116. c.Assert(err, qt.IsNil)
  117. tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
  118. c.Assert(err, qt.IsNil)
  119. defer tree2.db.Close() //nolint:errcheck
  120. for i := 16 - 1; i >= 0; i-- {
  121. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  122. v := BigIntToBytes(bLen, big.NewInt(0))
  123. if err := tree2.Add(k, v); err != nil {
  124. t.Fatal(err)
  125. }
  126. }
  127. c.Check(hex.EncodeToString(tree2.Root()), qt.Equals, hex.EncodeToString(tree1.Root()))
  128. c.Check(hex.EncodeToString(tree1.Root()), qt.Equals,
  129. "3b89100bec24da9275c87bc188740389e1d5accfc7d88ba5688d7fa96a00d82f")
  130. }
  131. func TestAddRepeatedIndex(t *testing.T) {
  132. c := qt.New(t)
  133. database, err := db.NewBadgerDB(c.TempDir())
  134. c.Assert(err, qt.IsNil)
  135. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  136. c.Assert(err, qt.IsNil)
  137. defer tree.db.Close() //nolint:errcheck
  138. bLen := tree.HashFunction().Len()
  139. k := BigIntToBytes(bLen, big.NewInt(int64(3)))
  140. v := BigIntToBytes(bLen, big.NewInt(int64(12)))
  141. err = tree.Add(k, v)
  142. c.Assert(err, qt.IsNil)
  143. err = tree.Add(k, v) // repeating same key-value
  144. c.Check(err, qt.Equals, ErrKeyAlreadyExists)
  145. }
  146. func TestUpdate(t *testing.T) {
  147. c := qt.New(t)
  148. database, err := db.NewBadgerDB(c.TempDir())
  149. c.Assert(err, qt.IsNil)
  150. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  151. c.Assert(err, qt.IsNil)
  152. defer tree.db.Close() //nolint:errcheck
  153. bLen := tree.HashFunction().Len()
  154. k := BigIntToBytes(bLen, big.NewInt(int64(20)))
  155. v := BigIntToBytes(bLen, big.NewInt(int64(12)))
  156. if err := tree.Add(k, v); err != nil {
  157. t.Fatal(err)
  158. }
  159. v = BigIntToBytes(bLen, big.NewInt(int64(11)))
  160. err = tree.Update(k, v)
  161. c.Assert(err, qt.IsNil)
  162. gettedKey, gettedValue, err := tree.Get(k)
  163. c.Assert(err, qt.IsNil)
  164. c.Check(gettedKey, qt.DeepEquals, k)
  165. c.Check(gettedValue, qt.DeepEquals, v)
  166. // add more leafs to the tree to do another test
  167. for i := 0; i < 16; i++ {
  168. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  169. v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
  170. if err := tree.Add(k, v); err != nil {
  171. t.Fatal(err)
  172. }
  173. }
  174. k = BigIntToBytes(bLen, big.NewInt(int64(3)))
  175. v = BigIntToBytes(bLen, big.NewInt(int64(11)))
  176. // check that before the Update, value for 3 is !=11
  177. gettedKey, gettedValue, err = tree.Get(k)
  178. c.Assert(err, qt.IsNil)
  179. c.Check(gettedKey, qt.DeepEquals, k)
  180. c.Check(gettedValue, qt.Not(qt.DeepEquals), v)
  181. c.Check(gettedValue, qt.DeepEquals, BigIntToBytes(bLen, big.NewInt(6)))
  182. err = tree.Update(k, v)
  183. c.Assert(err, qt.IsNil)
  184. // check that after Update, the value for 3 is ==11
  185. gettedKey, gettedValue, err = tree.Get(k)
  186. c.Assert(err, qt.IsNil)
  187. c.Check(gettedKey, qt.DeepEquals, k)
  188. c.Check(gettedValue, qt.DeepEquals, v)
  189. c.Check(gettedValue, qt.DeepEquals, BigIntToBytes(bLen, big.NewInt(11)))
  190. }
  191. func TestAux(t *testing.T) { // TODO split in proper tests
  192. c := qt.New(t)
  193. database, err := db.NewBadgerDB(c.TempDir())
  194. c.Assert(err, qt.IsNil)
  195. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  196. c.Assert(err, qt.IsNil)
  197. defer tree.db.Close() //nolint:errcheck
  198. bLen := tree.HashFunction().Len()
  199. k := BigIntToBytes(bLen, big.NewInt(int64(1)))
  200. v := BigIntToBytes(bLen, big.NewInt(int64(0)))
  201. err = tree.Add(k, v)
  202. c.Assert(err, qt.IsNil)
  203. k = BigIntToBytes(bLen, big.NewInt(int64(256)))
  204. err = tree.Add(k, v)
  205. c.Assert(err, qt.IsNil)
  206. k = BigIntToBytes(bLen, big.NewInt(int64(257)))
  207. err = tree.Add(k, v)
  208. c.Assert(err, qt.IsNil)
  209. k = BigIntToBytes(bLen, big.NewInt(int64(515)))
  210. err = tree.Add(k, v)
  211. c.Assert(err, qt.IsNil)
  212. k = BigIntToBytes(bLen, big.NewInt(int64(770)))
  213. err = tree.Add(k, v)
  214. c.Assert(err, qt.IsNil)
  215. k = BigIntToBytes(bLen, big.NewInt(int64(388)))
  216. err = tree.Add(k, v)
  217. c.Assert(err, qt.IsNil)
  218. k = BigIntToBytes(bLen, big.NewInt(int64(900)))
  219. err = tree.Add(k, v)
  220. c.Assert(err, qt.IsNil)
  221. //
  222. // err = tree.PrintGraphviz(nil)
  223. // c.Assert(err, qt.IsNil)
  224. }
  225. func TestGet(t *testing.T) {
  226. c := qt.New(t)
  227. database, err := db.NewBadgerDB(c.TempDir())
  228. c.Assert(err, qt.IsNil)
  229. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  230. c.Assert(err, qt.IsNil)
  231. defer tree.db.Close() //nolint:errcheck
  232. bLen := tree.HashFunction().Len()
  233. for i := 0; i < 10; i++ {
  234. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  235. v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
  236. if err := tree.Add(k, v); err != nil {
  237. t.Fatal(err)
  238. }
  239. }
  240. k := BigIntToBytes(bLen, big.NewInt(int64(7)))
  241. gettedKey, gettedValue, err := tree.Get(k)
  242. c.Assert(err, qt.IsNil)
  243. c.Check(gettedKey, qt.DeepEquals, k)
  244. c.Check(gettedValue, qt.DeepEquals, BigIntToBytes(bLen, big.NewInt(int64(7*2))))
  245. }
  246. func TestGenProofAndVerify(t *testing.T) {
  247. c := qt.New(t)
  248. database, err := db.NewBadgerDB(c.TempDir())
  249. c.Assert(err, qt.IsNil)
  250. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  251. c.Assert(err, qt.IsNil)
  252. defer tree.db.Close() //nolint:errcheck
  253. bLen := tree.HashFunction().Len()
  254. for i := 0; i < 10; i++ {
  255. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  256. v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
  257. if err := tree.Add(k, v); err != nil {
  258. t.Fatal(err)
  259. }
  260. }
  261. k := BigIntToBytes(bLen, big.NewInt(int64(7)))
  262. v := BigIntToBytes(bLen, big.NewInt(int64(14)))
  263. proofV, siblings, err := tree.GenProof(k)
  264. c.Assert(err, qt.IsNil)
  265. c.Assert(proofV, qt.DeepEquals, v)
  266. verif, err := CheckProof(tree.hashFunction, k, v, tree.Root(), siblings)
  267. c.Assert(err, qt.IsNil)
  268. c.Check(verif, qt.IsTrue)
  269. }
  270. func TestDumpAndImportDump(t *testing.T) {
  271. c := qt.New(t)
  272. database1, err := db.NewBadgerDB(c.TempDir())
  273. c.Assert(err, qt.IsNil)
  274. tree1, err := NewTree(database1, 100, HashFunctionPoseidon)
  275. c.Assert(err, qt.IsNil)
  276. defer tree1.db.Close() //nolint:errcheck
  277. bLen := tree1.HashFunction().Len()
  278. for i := 0; i < 16; i++ {
  279. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  280. v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
  281. if err := tree1.Add(k, v); err != nil {
  282. t.Fatal(err)
  283. }
  284. }
  285. e, err := tree1.Dump(nil)
  286. c.Assert(err, qt.IsNil)
  287. database2, err := db.NewBadgerDB(c.TempDir())
  288. c.Assert(err, qt.IsNil)
  289. tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
  290. c.Assert(err, qt.IsNil)
  291. defer tree2.db.Close() //nolint:errcheck
  292. err = tree2.ImportDump(e)
  293. c.Assert(err, qt.IsNil)
  294. c.Check(tree2.Root(), qt.DeepEquals, tree1.Root())
  295. c.Check(hex.EncodeToString(tree2.Root()), qt.Equals,
  296. "0d93aaa3362b2f999f15e15728f123087c2eee716f01c01f56e23aae07f09f08")
  297. }
  298. func TestRWMutex(t *testing.T) {
  299. c := qt.New(t)
  300. database, err := db.NewBadgerDB(c.TempDir())
  301. c.Assert(err, qt.IsNil)
  302. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  303. c.Assert(err, qt.IsNil)
  304. defer tree.db.Close() //nolint:errcheck
  305. bLen := tree.HashFunction().Len()
  306. var keys, values [][]byte
  307. for i := 0; i < 1000; i++ {
  308. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  309. v := BigIntToBytes(bLen, big.NewInt(0))
  310. keys = append(keys, k)
  311. values = append(values, v)
  312. }
  313. go func() {
  314. _, err = tree.AddBatch(keys, values)
  315. if err != nil {
  316. panic(err)
  317. }
  318. }()
  319. time.Sleep(500 * time.Millisecond)
  320. k := BigIntToBytes(bLen, big.NewInt(int64(99999)))
  321. v := BigIntToBytes(bLen, big.NewInt(int64(99999)))
  322. if err := tree.Add(k, v); err != nil {
  323. t.Fatal(err)
  324. }
  325. }
  326. func TestSetGetNLeafs(t *testing.T) {
  327. c := qt.New(t)
  328. database, err := db.NewBadgerDB(c.TempDir())
  329. c.Assert(err, qt.IsNil)
  330. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  331. c.Assert(err, qt.IsNil)
  332. // 0
  333. tree.dbBatch = tree.db.NewBatch()
  334. err = tree.setNLeafs(0)
  335. c.Assert(err, qt.IsNil)
  336. err = tree.dbBatch.Write()
  337. c.Assert(err, qt.IsNil)
  338. n, err := tree.GetNLeafs()
  339. c.Assert(err, qt.IsNil)
  340. c.Assert(n, qt.Equals, 0)
  341. // 1024
  342. tree.dbBatch = tree.db.NewBatch()
  343. err = tree.setNLeafs(1024)
  344. c.Assert(err, qt.IsNil)
  345. err = tree.dbBatch.Write()
  346. c.Assert(err, qt.IsNil)
  347. n, err = tree.GetNLeafs()
  348. c.Assert(err, qt.IsNil)
  349. c.Assert(n, qt.Equals, 1024)
  350. // 2**64 -1
  351. tree.dbBatch = tree.db.NewBatch()
  352. maxUint := ^uint(0)
  353. maxInt := int(maxUint >> 1)
  354. err = tree.setNLeafs(maxInt)
  355. c.Assert(err, qt.IsNil)
  356. err = tree.dbBatch.Write()
  357. c.Assert(err, qt.IsNil)
  358. n, err = tree.GetNLeafs()
  359. c.Assert(err, qt.IsNil)
  360. c.Assert(n, qt.Equals, maxInt)
  361. }
  362. func BenchmarkAdd(b *testing.B) {
  363. bLen := 32 // for both Poseidon & Sha256
  364. // prepare inputs
  365. var ks, vs [][]byte
  366. for i := 0; i < 1000; i++ {
  367. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  368. v := BigIntToBytes(bLen, big.NewInt(int64(i)))
  369. ks = append(ks, k)
  370. vs = append(vs, v)
  371. }
  372. b.Run("Poseidon", func(b *testing.B) {
  373. benchmarkAdd(b, HashFunctionPoseidon, ks, vs)
  374. })
  375. b.Run("Sha256", func(b *testing.B) {
  376. benchmarkAdd(b, HashFunctionSha256, ks, vs)
  377. })
  378. }
  379. func benchmarkAdd(b *testing.B, hashFunc HashFunction, ks, vs [][]byte) {
  380. c := qt.New(b)
  381. database, err := db.NewBadgerDB(c.TempDir())
  382. c.Assert(err, qt.IsNil)
  383. tree, err := NewTree(database, 140, hashFunc)
  384. c.Assert(err, qt.IsNil)
  385. defer tree.db.Close() //nolint:errcheck
  386. for i := 0; i < len(ks); i++ {
  387. if err := tree.Add(ks[i], vs[i]); err != nil {
  388. b.Fatal(err)
  389. }
  390. }
  391. }