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.

519 lines
15 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. kAux, proofV, siblings, existence, err := tree.GenProof(k)
  264. c.Assert(err, qt.IsNil)
  265. c.Assert(proofV, qt.DeepEquals, v)
  266. c.Assert(k, qt.DeepEquals, kAux)
  267. c.Assert(existence, qt.IsTrue)
  268. verif, err := CheckProof(tree.hashFunction, k, v, tree.Root(), siblings)
  269. c.Assert(err, qt.IsNil)
  270. c.Check(verif, qt.IsTrue)
  271. }
  272. func TestDumpAndImportDump(t *testing.T) {
  273. c := qt.New(t)
  274. database1, err := db.NewBadgerDB(c.TempDir())
  275. c.Assert(err, qt.IsNil)
  276. tree1, err := NewTree(database1, 100, HashFunctionPoseidon)
  277. c.Assert(err, qt.IsNil)
  278. defer tree1.db.Close() //nolint:errcheck
  279. bLen := tree1.HashFunction().Len()
  280. for i := 0; i < 16; i++ {
  281. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  282. v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
  283. if err := tree1.Add(k, v); err != nil {
  284. t.Fatal(err)
  285. }
  286. }
  287. e, err := tree1.Dump(nil)
  288. c.Assert(err, qt.IsNil)
  289. database2, err := db.NewBadgerDB(c.TempDir())
  290. c.Assert(err, qt.IsNil)
  291. tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
  292. c.Assert(err, qt.IsNil)
  293. defer tree2.db.Close() //nolint:errcheck
  294. err = tree2.ImportDump(e)
  295. c.Assert(err, qt.IsNil)
  296. c.Check(tree2.Root(), qt.DeepEquals, tree1.Root())
  297. c.Check(hex.EncodeToString(tree2.Root()), qt.Equals,
  298. "0d93aaa3362b2f999f15e15728f123087c2eee716f01c01f56e23aae07f09f08")
  299. }
  300. func TestRWMutex(t *testing.T) {
  301. c := qt.New(t)
  302. database, err := db.NewBadgerDB(c.TempDir())
  303. c.Assert(err, qt.IsNil)
  304. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  305. c.Assert(err, qt.IsNil)
  306. defer tree.db.Close() //nolint:errcheck
  307. bLen := tree.HashFunction().Len()
  308. var keys, values [][]byte
  309. for i := 0; i < 1000; i++ {
  310. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  311. v := BigIntToBytes(bLen, big.NewInt(0))
  312. keys = append(keys, k)
  313. values = append(values, v)
  314. }
  315. go func() {
  316. _, err = tree.AddBatch(keys, values)
  317. if err != nil {
  318. panic(err)
  319. }
  320. }()
  321. time.Sleep(500 * time.Millisecond)
  322. k := BigIntToBytes(bLen, big.NewInt(int64(99999)))
  323. v := BigIntToBytes(bLen, big.NewInt(int64(99999)))
  324. if err := tree.Add(k, v); err != nil {
  325. t.Fatal(err)
  326. }
  327. }
  328. func TestSetGetNLeafs(t *testing.T) {
  329. c := qt.New(t)
  330. database, err := db.NewBadgerDB(c.TempDir())
  331. c.Assert(err, qt.IsNil)
  332. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  333. c.Assert(err, qt.IsNil)
  334. // 0
  335. tree.dbBatch = tree.db.NewBatch()
  336. err = tree.setNLeafs(0)
  337. c.Assert(err, qt.IsNil)
  338. err = tree.dbBatch.Write()
  339. c.Assert(err, qt.IsNil)
  340. n, err := tree.GetNLeafs()
  341. c.Assert(err, qt.IsNil)
  342. c.Assert(n, qt.Equals, 0)
  343. // 1024
  344. tree.dbBatch = tree.db.NewBatch()
  345. err = tree.setNLeafs(1024)
  346. c.Assert(err, qt.IsNil)
  347. err = tree.dbBatch.Write()
  348. c.Assert(err, qt.IsNil)
  349. n, err = tree.GetNLeafs()
  350. c.Assert(err, qt.IsNil)
  351. c.Assert(n, qt.Equals, 1024)
  352. // 2**64 -1
  353. tree.dbBatch = tree.db.NewBatch()
  354. maxUint := ^uint(0)
  355. maxInt := int(maxUint >> 1)
  356. err = tree.setNLeafs(maxInt)
  357. c.Assert(err, qt.IsNil)
  358. err = tree.dbBatch.Write()
  359. c.Assert(err, qt.IsNil)
  360. n, err = tree.GetNLeafs()
  361. c.Assert(err, qt.IsNil)
  362. c.Assert(n, qt.Equals, maxInt)
  363. }
  364. func TestSnapshot(t *testing.T) {
  365. c := qt.New(t)
  366. database, err := db.NewBadgerDB(c.TempDir())
  367. c.Assert(err, qt.IsNil)
  368. tree, err := NewTree(database, 100, HashFunctionPoseidon)
  369. c.Assert(err, qt.IsNil)
  370. // fill the tree
  371. bLen := tree.HashFunction().Len()
  372. var keys, values [][]byte
  373. for i := 0; i < 1000; i++ {
  374. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  375. v := BigIntToBytes(bLen, big.NewInt(int64(i)))
  376. keys = append(keys, k)
  377. values = append(values, v)
  378. }
  379. indexes, err := tree.AddBatch(keys, values)
  380. c.Assert(err, qt.IsNil)
  381. c.Check(len(indexes), qt.Equals, 0)
  382. rootBI := BytesToBigInt(tree.Root())
  383. c.Check(rootBI.String(), qt.Equals,
  384. "13742386369878513332697380582061714160370929283209286127733983161245560237407")
  385. tree2, err := tree.Snapshot(nil)
  386. c.Assert(err, qt.IsNil)
  387. rootBI = BytesToBigInt(tree2.Root())
  388. c.Check(rootBI.String(), qt.Equals,
  389. "13742386369878513332697380582061714160370929283209286127733983161245560237407")
  390. // add k-v to original tree
  391. k := BigIntToBytes(bLen, big.NewInt(int64(1000)))
  392. v := BigIntToBytes(bLen, big.NewInt(int64(1000)))
  393. err = tree.Add(k, v)
  394. c.Assert(err, qt.IsNil)
  395. // expect original tree to have new root
  396. rootBI = BytesToBigInt(tree.Root())
  397. c.Check(rootBI.String(), qt.Equals,
  398. "10747149055773881257049574592162159501044114324358186833013814735296193179713")
  399. // expect snapshot tree to have the old root
  400. rootBI = BytesToBigInt(tree2.Root())
  401. c.Check(rootBI.String(), qt.Equals,
  402. "13742386369878513332697380582061714160370929283209286127733983161245560237407")
  403. err = tree2.Add(k, v)
  404. c.Assert(err, qt.IsNil)
  405. // after adding also the k-v into the snapshot tree, expect original
  406. // tree to have new root
  407. rootBI = BytesToBigInt(tree.Root())
  408. c.Check(rootBI.String(), qt.Equals,
  409. "10747149055773881257049574592162159501044114324358186833013814735296193179713")
  410. }
  411. func BenchmarkAdd(b *testing.B) {
  412. bLen := 32 // for both Poseidon & Sha256
  413. // prepare inputs
  414. var ks, vs [][]byte
  415. for i := 0; i < 1000; i++ {
  416. k := BigIntToBytes(bLen, big.NewInt(int64(i)))
  417. v := BigIntToBytes(bLen, big.NewInt(int64(i)))
  418. ks = append(ks, k)
  419. vs = append(vs, v)
  420. }
  421. b.Run("Poseidon", func(b *testing.B) {
  422. benchmarkAdd(b, HashFunctionPoseidon, ks, vs)
  423. })
  424. b.Run("Sha256", func(b *testing.B) {
  425. benchmarkAdd(b, HashFunctionSha256, ks, vs)
  426. })
  427. }
  428. func benchmarkAdd(b *testing.B, hashFunc HashFunction, ks, vs [][]byte) {
  429. c := qt.New(b)
  430. database, err := db.NewBadgerDB(c.TempDir())
  431. c.Assert(err, qt.IsNil)
  432. tree, err := NewTree(database, 140, hashFunc)
  433. c.Assert(err, qt.IsNil)
  434. defer tree.db.Close() //nolint:errcheck
  435. for i := 0; i < len(ks); i++ {
  436. if err := tree.Add(ks[i], vs[i]); err != nil {
  437. b.Fatal(err)
  438. }
  439. }
  440. }