mirror of
https://github.com/vocdoni/arbo.git
synced 2026-01-09 13:57:54 -05:00
simple test fails going down in the tree
This commit is contained in:
2410
addbatch_test.go
2410
addbatch_test.go
File diff suppressed because it is too large
Load Diff
@@ -1,64 +1,64 @@
|
||||
package arbo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"testing"
|
||||
// import (
|
||||
// "encoding/json"
|
||||
// "math/big"
|
||||
// "testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"go.vocdoni.io/dvote/db"
|
||||
"go.vocdoni.io/dvote/db/pebbledb"
|
||||
)
|
||||
// qt "github.com/frankban/quicktest"
|
||||
// "go.vocdoni.io/dvote/db"
|
||||
// "go.vocdoni.io/dvote/db/pebbledb"
|
||||
// )
|
||||
|
||||
func TestCircomVerifierProof(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
database, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
c.Assert(err, qt.IsNil)
|
||||
tree, err := NewTree(Config{Database: database, MaxLevels: 4,
|
||||
HashFunction: HashFunctionPoseidon})
|
||||
c.Assert(err, qt.IsNil)
|
||||
defer tree.db.Close() //nolint:errcheck
|
||||
// func TestCircomVerifierProof(t *testing.T) {
|
||||
// c := qt.New(t)
|
||||
// database, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// tree, err := NewTree(Config{Database: database, MaxLevels: 4,
|
||||
// HashFunction: HashFunctionPoseidon})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// defer tree.db.Close() //nolint:errcheck
|
||||
|
||||
testVector := [][]int64{
|
||||
{1, 11},
|
||||
{2, 22},
|
||||
{3, 33},
|
||||
{4, 44},
|
||||
}
|
||||
bLen := 1
|
||||
for i := 0; i < len(testVector); i++ {
|
||||
k := BigIntToBytes(bLen, big.NewInt(testVector[i][0]))
|
||||
v := BigIntToBytes(bLen, big.NewInt(testVector[i][1]))
|
||||
if err := tree.Add(k, v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
// testVector := [][]int64{
|
||||
// {1, 11},
|
||||
// {2, 22},
|
||||
// {3, 33},
|
||||
// {4, 44},
|
||||
// }
|
||||
// bLen := 1
|
||||
// for i := 0; i < len(testVector); i++ {
|
||||
// k := BigIntToBytes(bLen, big.NewInt(testVector[i][0]))
|
||||
// v := BigIntToBytes(bLen, big.NewInt(testVector[i][1]))
|
||||
// if err := tree.Add(k, v); err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// proof of existence
|
||||
k := BigIntToBytes(bLen, big.NewInt(int64(2)))
|
||||
cvp, err := tree.GenerateCircomVerifierProof(k)
|
||||
c.Assert(err, qt.IsNil)
|
||||
jCvp, err := json.Marshal(cvp)
|
||||
c.Assert(err, qt.IsNil)
|
||||
// test vector checked with a circom circuit (arbo/testvectors/circom)
|
||||
c.Assert(string(jCvp), qt.Equals, `{"fnc":0,"isOld0":"0","key":"2","oldK`+
|
||||
`ey":"0","oldValue":"0","root":"1355816845522055904274785395894906304622`+
|
||||
`6645447188878859760119761585093422436","siblings":["1162013050763544193`+
|
||||
`2056895853942898236773847390796721536119314875877874016518","5158240518`+
|
||||
`874928563648144881543092238925265313977134167935552944620041388700","0"`+
|
||||
`,"0"],"value":"22"}`)
|
||||
// // proof of existence
|
||||
// k := BigIntToBytes(bLen, big.NewInt(int64(2)))
|
||||
// cvp, err := tree.GenerateCircomVerifierProof(k)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// jCvp, err := json.Marshal(cvp)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// // test vector checked with a circom circuit (arbo/testvectors/circom)
|
||||
// c.Assert(string(jCvp), qt.Equals, `{"fnc":0,"isOld0":"0","key":"2","oldK`+
|
||||
// `ey":"0","oldValue":"0","root":"1355816845522055904274785395894906304622`+
|
||||
// `6645447188878859760119761585093422436","siblings":["1162013050763544193`+
|
||||
// `2056895853942898236773847390796721536119314875877874016518","5158240518`+
|
||||
// `874928563648144881543092238925265313977134167935552944620041388700","0"`+
|
||||
// `,"0"],"value":"22"}`)
|
||||
|
||||
// proof of non-existence
|
||||
k = BigIntToBytes(bLen, big.NewInt(int64(5)))
|
||||
cvp, err = tree.GenerateCircomVerifierProof(k)
|
||||
c.Assert(err, qt.IsNil)
|
||||
jCvp, err = json.Marshal(cvp)
|
||||
c.Assert(err, qt.IsNil)
|
||||
// test vector checked with a circom circuit (arbo/testvectors/circom)
|
||||
c.Assert(string(jCvp), qt.Equals, `{"fnc":1,"isOld0":"0","key":"5","oldK`+
|
||||
`ey":"1","oldValue":"11","root":"135581684552205590427478539589490630462`+
|
||||
`26645447188878859760119761585093422436","siblings":["756056982086999933`+
|
||||
`1905412009838015295115276841209205575174464206730109811365","1276103081`+
|
||||
`3800436751877086580591648324911598798716611088294049841213649313596","0`+
|
||||
`","0"],"value":"11"}`)
|
||||
}
|
||||
// // proof of non-existence
|
||||
// k = BigIntToBytes(bLen, big.NewInt(int64(5)))
|
||||
// cvp, err = tree.GenerateCircomVerifierProof(k)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// jCvp, err = json.Marshal(cvp)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// // test vector checked with a circom circuit (arbo/testvectors/circom)
|
||||
// c.Assert(string(jCvp), qt.Equals, `{"fnc":1,"isOld0":"0","key":"5","oldK`+
|
||||
// `ey":"1","oldValue":"11","root":"135581684552205590427478539589490630462`+
|
||||
// `26645447188878859760119761585093422436","siblings":["756056982086999933`+
|
||||
// `1905412009838015295115276841209205575174464206730109811365","1276103081`+
|
||||
// `3800436751877086580591648324911598798716611088294049841213649313596","0`+
|
||||
// `","0"],"value":"11"}`)
|
||||
// }
|
||||
|
||||
6
hash.go
6
hash.go
@@ -64,7 +64,11 @@ func (f HashPoseidon) Len() int {
|
||||
// expects the byte arrays to be little-endian representations of big.Int
|
||||
// values.
|
||||
func (f HashPoseidon) Hash(b ...*big.Int) (*big.Int, error) {
|
||||
return poseidon.Hash(b)
|
||||
var toHash []*big.Int
|
||||
for _, i := range b {
|
||||
toHash = append(toHash, BigToFF(BN254BaseField, BytesToBigInt(i.Bytes())))
|
||||
}
|
||||
return poseidon.Hash(toHash)
|
||||
}
|
||||
|
||||
type HashMiMC7 struct{}
|
||||
|
||||
208
helpers_test.go
208
helpers_test.go
@@ -1,121 +1,121 @@
|
||||
package arbo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
// import (
|
||||
// "bytes"
|
||||
// "io"
|
||||
// "os"
|
||||
// "testing"
|
||||
// "time"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"go.vocdoni.io/dvote/db"
|
||||
"go.vocdoni.io/dvote/db/pebbledb"
|
||||
)
|
||||
// qt "github.com/frankban/quicktest"
|
||||
// "go.vocdoni.io/dvote/db"
|
||||
// "go.vocdoni.io/dvote/db/pebbledb"
|
||||
// )
|
||||
|
||||
func checkRoots(c *qt.C, tree1, tree2 *Tree) {
|
||||
root1, err := tree1.Root()
|
||||
c.Assert(err, qt.IsNil)
|
||||
root2, err := tree2.Root()
|
||||
c.Assert(err, qt.IsNil)
|
||||
if !bytes.Equal(root2, root1) {
|
||||
dir := "err-dump"
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
err := os.Mkdir(dir, os.ModePerm)
|
||||
c.Assert(err, qt.IsNil)
|
||||
}
|
||||
// store tree1
|
||||
storeTree(c, tree1, dir+"/tree1")
|
||||
// func checkRoots(c *qt.C, tree1, tree2 *Tree) {
|
||||
// root1, err := tree1.Root()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// root2, err := tree2.Root()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// if !bytes.Equal(root2, root1) {
|
||||
// dir := "err-dump"
|
||||
// if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
// err := os.Mkdir(dir, os.ModePerm)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// }
|
||||
// // store tree1
|
||||
// storeTree(c, tree1, dir+"/tree1")
|
||||
|
||||
// store tree2
|
||||
storeTree(c, tree2, dir+"/tree2")
|
||||
// // store tree2
|
||||
// storeTree(c, tree2, dir+"/tree2")
|
||||
|
||||
root1, err := tree1.Root()
|
||||
c.Assert(err, qt.IsNil)
|
||||
root2, err := tree2.Root()
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Check(root2, qt.DeepEquals, root1)
|
||||
}
|
||||
}
|
||||
// root1, err := tree1.Root()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// root2, err := tree2.Root()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Check(root2, qt.DeepEquals, root1)
|
||||
// }
|
||||
// }
|
||||
|
||||
func storeTree(c *qt.C, tree *Tree, path string) {
|
||||
dump, err := tree.Dump(nil)
|
||||
c.Assert(err, qt.IsNil)
|
||||
err = os.WriteFile(path+"-"+time.Now().String()+".debug", dump, 0600)
|
||||
c.Assert(err, qt.IsNil)
|
||||
}
|
||||
// func storeTree(c *qt.C, tree *Tree, path string) {
|
||||
// dump, err := tree.Dump(nil)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// err = os.WriteFile(path+"-"+time.Now().String()+".debug", dump, 0600)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// }
|
||||
|
||||
// nolint:unused
|
||||
func readTree(c *qt.C, tree *Tree, path string) {
|
||||
b, err := os.ReadFile(path) //nolint:gosec
|
||||
c.Assert(err, qt.IsNil)
|
||||
err = tree.ImportDump(b)
|
||||
c.Assert(err, qt.IsNil)
|
||||
}
|
||||
// // nolint:unused
|
||||
// func readTree(c *qt.C, tree *Tree, path string) {
|
||||
// b, err := os.ReadFile(path) //nolint:gosec
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// err = tree.ImportDump(b)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// }
|
||||
|
||||
// nolint:unused
|
||||
func importDumpLoopAdd(tree *Tree, b []byte) error {
|
||||
r := bytes.NewReader(b)
|
||||
var err error
|
||||
for {
|
||||
l := make([]byte, 2)
|
||||
_, err = io.ReadFull(r, l)
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
k := make([]byte, l[0])
|
||||
_, err = io.ReadFull(r, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v := make([]byte, l[1])
|
||||
_, err = io.ReadFull(r, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tree.Add(k, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// // nolint:unused
|
||||
// func importDumpLoopAdd(tree *Tree, b []byte) error {
|
||||
// r := bytes.NewReader(b)
|
||||
// var err error
|
||||
// for {
|
||||
// l := make([]byte, 2)
|
||||
// _, err = io.ReadFull(r, l)
|
||||
// if err == io.EOF {
|
||||
// break
|
||||
// } else if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// k := make([]byte, l[0])
|
||||
// _, err = io.ReadFull(r, k)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// v := make([]byte, l[1])
|
||||
// _, err = io.ReadFull(r, v)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// err = tree.Add(k, v)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func TestReadTreeDBG(t *testing.T) {
|
||||
t.Skip() // test just for debugging purposes, disabled by default
|
||||
// func TestReadTreeDBG(t *testing.T) {
|
||||
// t.Skip() // test just for debugging purposes, disabled by default
|
||||
|
||||
c := qt.New(t)
|
||||
// c := qt.New(t)
|
||||
|
||||
database1, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
c.Assert(err, qt.IsNil)
|
||||
tree1, err := NewTree(Config{Database: database1, MaxLevels: 100,
|
||||
HashFunction: HashFunctionMiMC_BN254})
|
||||
c.Assert(err, qt.IsNil)
|
||||
// database1, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// tree1, err := NewTree(Config{Database: database1, MaxLevels: 100,
|
||||
// HashFunction: HashFunctionMiMC_BN254})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
|
||||
database2, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
c.Assert(err, qt.IsNil)
|
||||
tree2, err := NewTree(Config{Database: database2, MaxLevels: 100,
|
||||
HashFunction: HashFunctionMiMC_BN254})
|
||||
c.Assert(err, qt.IsNil)
|
||||
// database2, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// tree2, err := NewTree(Config{Database: database2, MaxLevels: 100,
|
||||
// HashFunction: HashFunctionMiMC_BN254})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
|
||||
// tree1 is generated by a loop of .Add
|
||||
path := "err-dump/tree1-2021-06-03 16:45:54.104449306 +0200 CEST m=+0.073874545.debug"
|
||||
b, err := os.ReadFile(path)
|
||||
c.Assert(err, qt.IsNil)
|
||||
err = importDumpLoopAdd(tree1, b)
|
||||
c.Assert(err, qt.IsNil)
|
||||
// // tree1 is generated by a loop of .Add
|
||||
// path := "err-dump/tree1-2021-06-03 16:45:54.104449306 +0200 CEST m=+0.073874545.debug"
|
||||
// b, err := os.ReadFile(path)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// err = importDumpLoopAdd(tree1, b)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
|
||||
// tree2 is generated by .AddBatch
|
||||
path = "err-dump/tree2-2021-06-03 16:45:54.104525519 +0200 CEST m=+0.073950756.debug"
|
||||
readTree(c, tree2, path)
|
||||
// // tree2 is generated by .AddBatch
|
||||
// path = "err-dump/tree2-2021-06-03 16:45:54.104525519 +0200 CEST m=+0.073950756.debug"
|
||||
// readTree(c, tree2, path)
|
||||
|
||||
// tree1.PrintGraphvizFirstNLevels(nil, 6)
|
||||
// tree2.PrintGraphvizFirstNLevels(nil, 6)
|
||||
// // tree1.PrintGraphvizFirstNLevels(nil, 6)
|
||||
// // tree2.PrintGraphvizFirstNLevels(nil, 6)
|
||||
|
||||
root1, err := tree1.Root()
|
||||
c.Assert(err, qt.IsNil)
|
||||
root2, err := tree2.Root()
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Check(root2, qt.DeepEquals, root1)
|
||||
}
|
||||
// root1, err := tree1.Root()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// root2, err := tree2.Root()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Check(root2, qt.DeepEquals, root1)
|
||||
// }
|
||||
|
||||
@@ -8,16 +8,16 @@ import (
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"github.com/vocdoni/arbo"
|
||||
"go.vocdoni.io/dvote/db"
|
||||
"go.vocdoni.io/dvote/db/pebbledb"
|
||||
"github.com/vocdoni/arbo/memdb"
|
||||
)
|
||||
|
||||
func TestGenerator(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
database, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
c.Assert(err, qt.IsNil)
|
||||
tree, err := arbo.NewTree(arbo.Config{Database: database, MaxLevels: 4,
|
||||
HashFunction: arbo.HashFunctionPoseidon})
|
||||
tree, err := arbo.NewTree(arbo.Config{
|
||||
Database: memdb.New(),
|
||||
MaxLevels: 4,
|
||||
HashFunction: arbo.HashFunctionPoseidon,
|
||||
})
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
testVector := [][]int64{
|
||||
@@ -26,17 +26,12 @@ func TestGenerator(t *testing.T) {
|
||||
{3, 33},
|
||||
{4, 44},
|
||||
}
|
||||
bLen := 1
|
||||
for i := 0; i < len(testVector); i++ {
|
||||
k := arbo.BigIntToBytes(bLen, big.NewInt(testVector[i][0]))
|
||||
v := arbo.BigIntToBytes(bLen, big.NewInt(testVector[i][1]))
|
||||
if err := tree.Add(k, v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := range testVector {
|
||||
c.Assert(tree.Add(big.NewInt(testVector[i][0]), big.NewInt(testVector[i][1])), qt.IsNil)
|
||||
}
|
||||
|
||||
// proof of existence
|
||||
k := arbo.BigIntToBytes(bLen, big.NewInt(int64(2)))
|
||||
k := big.NewInt(int64(2))
|
||||
cvp, err := tree.GenerateCircomVerifierProof(k)
|
||||
c.Assert(err, qt.IsNil)
|
||||
jCvp, err := json.Marshal(cvp)
|
||||
@@ -46,7 +41,7 @@ func TestGenerator(t *testing.T) {
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
// proof of non-existence
|
||||
k = arbo.BigIntToBytes(bLen, big.NewInt(int64(5)))
|
||||
k = big.NewInt(int64(5))
|
||||
cvp, err = tree.GenerateCircomVerifierProof(k)
|
||||
c.Assert(err, qt.IsNil)
|
||||
jCvp, err = json.Marshal(cvp)
|
||||
|
||||
69
tree.go
69
tree.go
@@ -15,6 +15,7 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"math/big"
|
||||
"runtime"
|
||||
@@ -138,12 +139,14 @@ func NewTreeWithTx(wTx db.WriteTx, cfg Config) (*Tree, error) {
|
||||
if cfg.ThresholdNLeafs == 0 {
|
||||
cfg.ThresholdNLeafs = DefaultThresholdNLeafs
|
||||
}
|
||||
t := Tree{db: cfg.Database, maxLevels: cfg.MaxLevels,
|
||||
thresholdNLeafs: cfg.ThresholdNLeafs, hashFunction: cfg.HashFunction}
|
||||
t.emptyHash = big.NewInt(0) // empty
|
||||
|
||||
_, err := wTx.Get(dbKeyRoot)
|
||||
if err == db.ErrKeyNotFound {
|
||||
t := Tree{
|
||||
db: cfg.Database,
|
||||
maxLevels: cfg.MaxLevels,
|
||||
thresholdNLeafs: cfg.ThresholdNLeafs,
|
||||
hashFunction: cfg.HashFunction,
|
||||
emptyHash: zero, // empty
|
||||
}
|
||||
if _, err := wTx.Get(dbKeyRoot); err == db.ErrKeyNotFound {
|
||||
// store new root 0 (empty)
|
||||
if err = wTx.Set(dbKeyRoot, t.emptyHash.Bytes()); err != nil {
|
||||
return nil, err
|
||||
@@ -226,12 +229,11 @@ func (t *Tree) AddBatchWithTx(wTx db.WriteTx, keys []*big.Int, values [][]*big.I
|
||||
return nil, ErrSnapshotNotEditable
|
||||
}
|
||||
|
||||
e := big.NewInt(0)
|
||||
// equal the number of keys & values
|
||||
if len(keys) > len(values) {
|
||||
// add missing values
|
||||
for i := len(values); i < len(keys); i++ {
|
||||
values = append(values, []*big.Int{e})
|
||||
values = append(values, []*big.Int{zero})
|
||||
}
|
||||
} else if len(keys) < len(values) {
|
||||
// crop extra values
|
||||
@@ -252,7 +254,7 @@ func (t *Tree) addBatchInDisk(wTx db.WriteTx, keys []*big.Int, values [][]*big.I
|
||||
nCPU := flp2(runtime.NumCPU())
|
||||
if nCPU == 1 || len(keys) < nCPU {
|
||||
var invalids []Invalid
|
||||
for i := 0; i < len(keys); i++ {
|
||||
for i := range keys {
|
||||
if err := t.addWithTx(wTx, keys[i], values[i]...); err != nil {
|
||||
invalids = append(invalids, Invalid{i, err})
|
||||
}
|
||||
@@ -281,12 +283,12 @@ func (t *Tree) addBatchInDisk(wTx db.WriteTx, keys []*big.Int, values [][]*big.I
|
||||
// Already populated Tree but Unbalanced.
|
||||
|
||||
// add one key at each bucket, and then continue with the flow
|
||||
for i := 0; i < len(buckets); i++ {
|
||||
for i := range buckets {
|
||||
// add one leaf of the bucket, if there is an error when
|
||||
// adding the k-v, try to add the next one of the bucket
|
||||
// (until one is added)
|
||||
inserted := -1
|
||||
for j := 0; j < len(buckets[i]); j++ {
|
||||
for j := range buckets[i] {
|
||||
if newRoot, err := t.add(wTx, root, 0,
|
||||
buckets[i][j].k, buckets[i][j].v...); err == nil {
|
||||
inserted = j
|
||||
@@ -315,7 +317,7 @@ func (t *Tree) addBatchInDisk(wTx db.WriteTx, keys []*big.Int, values [][]*big.I
|
||||
|
||||
invalidsInBucket := make([][]Invalid, nCPU)
|
||||
txs := make([]db.WriteTx, nCPU)
|
||||
for i := 0; i < nCPU; i++ {
|
||||
for i := range nCPU {
|
||||
txs[i] = t.db.WriteTx()
|
||||
err := txs[i].Apply(wTx)
|
||||
if err != nil {
|
||||
@@ -325,7 +327,7 @@ func (t *Tree) addBatchInDisk(wTx db.WriteTx, keys []*big.Int, values [][]*big.I
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(nCPU)
|
||||
for i := 0; i < nCPU; i++ {
|
||||
for i := range nCPU {
|
||||
go func(cpu int) {
|
||||
// use different wTx for each cpu, after once all
|
||||
// are done, iter over the cpuWTxs and copy their
|
||||
@@ -346,14 +348,14 @@ func (t *Tree) addBatchInDisk(wTx db.WriteTx, keys []*big.Int, values [][]*big.I
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for i := 0; i < nCPU; i++ {
|
||||
for i := range nCPU {
|
||||
if err := wTx.Apply(txs[i]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txs[i].Discard()
|
||||
}
|
||||
|
||||
for i := 0; i < len(invalidsInBucket); i++ {
|
||||
for i := range invalidsInBucket {
|
||||
invalids = append(invalids, invalidsInBucket[i]...)
|
||||
}
|
||||
|
||||
@@ -386,7 +388,7 @@ func (t *Tree) upFromSubRoots(wTx db.WriteTx, subRoots []*big.Int) (*big.Int, er
|
||||
}
|
||||
// get the subRoots values to know the node types of each subRoot
|
||||
nodeTypes := make([]byte, len(subRoots))
|
||||
for i := 0; i < len(subRoots); i++ {
|
||||
for i := range subRoots {
|
||||
if subRoots[i].Cmp(t.emptyHash) == 0 {
|
||||
nodeTypes[i] = PrefixValueEmpty
|
||||
continue
|
||||
@@ -470,7 +472,7 @@ func (t *Tree) addBatchInMemory(wTx db.WriteTx, keys []*big.Int, values [][]*big
|
||||
}
|
||||
|
||||
// store pairs in db
|
||||
for i := 0; i < len(pairs); i++ {
|
||||
for i := range pairs {
|
||||
if err := wTx.Set(pairs[i][0], pairs[i][1]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -604,28 +606,34 @@ func checkKeyValueLen(k *big.Int, v ...*big.Int) error {
|
||||
|
||||
func (t *Tree) add(wTx db.WriteTx, root *big.Int, fromLvl int, k *big.Int, v ...*big.Int) (*big.Int, error) {
|
||||
if err := checkKeyValueLen(k, v...); err != nil {
|
||||
log.Println("checkKeyValueLen error:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyPath, err := keyPathFromKey(t.maxLevels, k)
|
||||
if err != nil {
|
||||
log.Println("keyPathFromKey error:", err)
|
||||
return nil, err
|
||||
}
|
||||
path := getPath(t.maxLevels, keyPath)
|
||||
|
||||
// go down to the leaf
|
||||
var siblings []*big.Int
|
||||
log.Println("down", k.String(), root.String())
|
||||
_, _, siblings, err = t.down(wTx, k, root, siblings, path, fromLvl, false)
|
||||
if err != nil {
|
||||
log.Println("down error:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
leafKey, leafValue, err := t.newLeafValue(k, v...)
|
||||
if err != nil {
|
||||
log.Println("newLeafValue error:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := wTx.Set(leafKey.Bytes(), leafValue); err != nil {
|
||||
log.Println("wTx.Set error:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -636,9 +644,10 @@ func (t *Tree) add(wTx db.WriteTx, root *big.Int, fromLvl int, k *big.Int, v ...
|
||||
}
|
||||
root, err = t.up(wTx, leafKey, siblings, path, len(siblings)-1, fromLvl)
|
||||
if err != nil {
|
||||
log.Println("up error:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Println("new root", root.String())
|
||||
return root, nil
|
||||
}
|
||||
|
||||
@@ -660,6 +669,7 @@ func (t *Tree) down(rTx db.Reader, newKey, currKey *big.Int, siblings []*big.Int
|
||||
}
|
||||
currValue, err = rTx.Get(currKey.Bytes())
|
||||
if err != nil {
|
||||
log.Println("rTx.Get error:", err)
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
@@ -685,6 +695,7 @@ func (t *Tree) down(rTx db.Reader, newKey, currKey *big.Int, siblings []*big.Int
|
||||
|
||||
oldLeafKeyFull, err := keyPathFromKey(t.maxLevels, oldLeafKey)
|
||||
if err != nil {
|
||||
log.Println("keyPathFromKey error:", err)
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
@@ -692,6 +703,7 @@ func (t *Tree) down(rTx db.Reader, newKey, currKey *big.Int, siblings []*big.Int
|
||||
oldPath := getPath(t.maxLevels, oldLeafKeyFull)
|
||||
siblings, err = t.downVirtually(siblings, currKey, newKey, oldPath, path, currLvl)
|
||||
if err != nil {
|
||||
log.Println("downVirtually error:", err)
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
@@ -811,7 +823,7 @@ func WriteLeafValue(k *big.Int, v ...*big.Int) ([]byte, error) {
|
||||
leafValue = append(leafValue, byte(PrefixValueLeaf))
|
||||
leafValue = append(leafValue, byte(len(k.Bytes())))
|
||||
leafValue = append(leafValue, k.Bytes()...)
|
||||
for i := 0; i < len(v); i++ {
|
||||
for i := range v {
|
||||
leafValue = append(leafValue, byte(len(v[i].Bytes())))
|
||||
leafValue = append(leafValue, v[i].Bytes()...)
|
||||
}
|
||||
@@ -892,7 +904,7 @@ func ReadIntermediateChilds(b []byte) (*big.Int, *big.Int) {
|
||||
|
||||
func getPath(numLevels int, k []byte) []bool {
|
||||
path := make([]bool, numLevels)
|
||||
for n := 0; n < numLevels; n++ {
|
||||
for n := range numLevels {
|
||||
path[n] = k[n/8]&(1<<(n%8)) != 0
|
||||
}
|
||||
return path
|
||||
@@ -1019,7 +1031,7 @@ func (t *Tree) GenProofWithTx(rTx db.Reader, k *big.Int) (*big.Int, []*big.Int,
|
||||
func PackSiblings(hashFunc HashFunction, siblings []*big.Int) ([]byte, error) {
|
||||
var b []byte
|
||||
var bitmap []bool
|
||||
for i := 0; i < len(siblings); i++ {
|
||||
for i := range siblings {
|
||||
if siblings[i].Cmp(zero) == 0 {
|
||||
bitmap = append(bitmap, false)
|
||||
} else {
|
||||
@@ -1062,7 +1074,7 @@ func UnpackSiblings(hashFunc HashFunction, b []byte) ([]*big.Int, error) {
|
||||
iSibl := 0
|
||||
emptySibl := big.NewInt(0)
|
||||
var siblings []*big.Int
|
||||
for i := 0; i < len(bitmap); i++ {
|
||||
for i := range bitmap {
|
||||
if iSibl >= len(siblingsBytes) {
|
||||
break
|
||||
}
|
||||
@@ -1080,7 +1092,7 @@ func UnpackSiblings(hashFunc HashFunction, b []byte) ([]*big.Int, error) {
|
||||
func bitmapToBytes(bitmap []bool) []byte {
|
||||
bitmapBytesLen := int(math.Ceil(float64(len(bitmap)) / 8)) //nolint:gomnd
|
||||
b := make([]byte, bitmapBytesLen)
|
||||
for i := 0; i < len(bitmap); i++ {
|
||||
for i := range bitmap {
|
||||
if bitmap[i] {
|
||||
b[i/8] |= 1 << (i % 8)
|
||||
}
|
||||
@@ -1090,8 +1102,8 @@ func bitmapToBytes(bitmap []bool) []byte {
|
||||
|
||||
func bytesToBitmap(b []byte) []bool {
|
||||
var bitmap []bool
|
||||
for i := 0; i < len(b); i++ {
|
||||
for j := 0; j < 8; j++ {
|
||||
for i := range b {
|
||||
for j := range 8 {
|
||||
bitmap = append(bitmap, b[i]&(1<<j) > 0)
|
||||
}
|
||||
}
|
||||
@@ -1138,7 +1150,7 @@ func (t *Tree) GetWithTx(rTx db.Reader, k *big.Int) (*big.Int, []*big.Int, error
|
||||
|
||||
// CheckProof verifies the given proof. The proof verification depends on the
|
||||
// HashFunction passed as parameter.
|
||||
func CheckProof(hashFunc HashFunction, root, packedSiblings []byte, k *big.Int, v ...*big.Int) (bool, error) {
|
||||
func CheckProof(hashFunc HashFunction, root *big.Int, packedSiblings []byte, k *big.Int, v ...*big.Int) (bool, error) {
|
||||
siblings, err := UnpackSiblings(hashFunc, packedSiblings)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -1166,10 +1178,7 @@ func CheckProof(hashFunc HashFunction, root, packedSiblings []byte, k *big.Int,
|
||||
}
|
||||
}
|
||||
}
|
||||
if bytes.Equal(key.Bytes(), root) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
return key.Cmp(root) == 0, nil
|
||||
}
|
||||
|
||||
func (t *Tree) incNLeafs(wTx db.WriteTx, nLeafs int) error {
|
||||
|
||||
1413
tree_test.go
1413
tree_test.go
File diff suppressed because it is too large
Load Diff
582
vt_test.go
582
vt_test.go
@@ -1,336 +1,336 @@
|
||||
package arbo
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math"
|
||||
"math/big"
|
||||
"testing"
|
||||
// import (
|
||||
// "encoding/hex"
|
||||
// "math"
|
||||
// "math/big"
|
||||
// "testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
"go.vocdoni.io/dvote/db"
|
||||
"go.vocdoni.io/dvote/db/pebbledb"
|
||||
)
|
||||
// qt "github.com/frankban/quicktest"
|
||||
// "go.vocdoni.io/dvote/db"
|
||||
// "go.vocdoni.io/dvote/db/pebbledb"
|
||||
// )
|
||||
|
||||
// testVirtualTree adds the given key-values and tests the vt root against the
|
||||
// Tree
|
||||
func testVirtualTree(c *qt.C, maxLevels int, keys, values [][]byte) {
|
||||
c.Assert(len(keys), qt.Equals, len(values))
|
||||
// // testVirtualTree adds the given key-values and tests the vt root against the
|
||||
// // Tree
|
||||
// func testVirtualTree(c *qt.C, maxLevels int, keys, values [][]byte) {
|
||||
// c.Assert(len(keys), qt.Equals, len(values))
|
||||
|
||||
// normal tree, to have an expected root value
|
||||
database, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
c.Assert(err, qt.IsNil)
|
||||
tree, err := NewTree(Config{Database: database, MaxLevels: maxLevels,
|
||||
HashFunction: HashFunctionPoseidon})
|
||||
c.Assert(err, qt.IsNil)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
err := tree.Add(keys[i], values[i])
|
||||
c.Assert(err, qt.IsNil)
|
||||
}
|
||||
// // normal tree, to have an expected root value
|
||||
// database, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// tree, err := NewTree(Config{Database: database, MaxLevels: maxLevels,
|
||||
// HashFunction: HashFunctionPoseidon})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// for i := 0; i < len(keys); i++ {
|
||||
// err := tree.Add(keys[i], values[i])
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// }
|
||||
|
||||
// virtual tree
|
||||
vTree := newVT(maxLevels, HashFunctionPoseidon)
|
||||
// // virtual tree
|
||||
// vTree := newVT(maxLevels, HashFunctionPoseidon)
|
||||
|
||||
c.Assert(vTree.root, qt.IsNil)
|
||||
// c.Assert(vTree.root, qt.IsNil)
|
||||
|
||||
for i := 0; i < len(keys); i++ {
|
||||
err := vTree.add(0, keys[i], values[i])
|
||||
c.Assert(err, qt.IsNil)
|
||||
}
|
||||
// for i := 0; i < len(keys); i++ {
|
||||
// err := vTree.add(0, keys[i], values[i])
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// }
|
||||
|
||||
// compute hashes, and check Root
|
||||
_, err = vTree.computeHashes()
|
||||
c.Assert(err, qt.IsNil)
|
||||
root, err := tree.Root()
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(vTree.root.h, qt.DeepEquals, root)
|
||||
}
|
||||
// // compute hashes, and check Root
|
||||
// _, err = vTree.computeHashes()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// root, err := tree.Root()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(vTree.root.h, qt.DeepEquals, root)
|
||||
// }
|
||||
|
||||
func TestVirtualTreeTestVectors(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
// func TestVirtualTreeTestVectors(t *testing.T) {
|
||||
// c := qt.New(t)
|
||||
|
||||
maxLevels := 32
|
||||
keyLen := int(math.Ceil(float64(maxLevels) / float64(8))) //nolint:gomnd
|
||||
keys := [][]byte{
|
||||
BigIntToBytes(keyLen, big.NewInt(1)),
|
||||
BigIntToBytes(keyLen, big.NewInt(33)),
|
||||
BigIntToBytes(keyLen, big.NewInt(1234)),
|
||||
BigIntToBytes(keyLen, big.NewInt(123456789)),
|
||||
}
|
||||
values := [][]byte{
|
||||
BigIntToBytes(keyLen, big.NewInt(2)),
|
||||
BigIntToBytes(keyLen, big.NewInt(44)),
|
||||
BigIntToBytes(keyLen, big.NewInt(9876)),
|
||||
BigIntToBytes(keyLen, big.NewInt(987654321)),
|
||||
}
|
||||
// maxLevels := 32
|
||||
// keyLen := int(math.Ceil(float64(maxLevels) / float64(8))) //nolint:gomnd
|
||||
// keys := [][]byte{
|
||||
// BigIntToBytes(keyLen, big.NewInt(1)),
|
||||
// BigIntToBytes(keyLen, big.NewInt(33)),
|
||||
// BigIntToBytes(keyLen, big.NewInt(1234)),
|
||||
// BigIntToBytes(keyLen, big.NewInt(123456789)),
|
||||
// }
|
||||
// values := [][]byte{
|
||||
// BigIntToBytes(keyLen, big.NewInt(2)),
|
||||
// BigIntToBytes(keyLen, big.NewInt(44)),
|
||||
// BigIntToBytes(keyLen, big.NewInt(9876)),
|
||||
// BigIntToBytes(keyLen, big.NewInt(987654321)),
|
||||
// }
|
||||
|
||||
// check the root for different batches of leafs
|
||||
testVirtualTree(c, maxLevels, keys[:1], values[:1])
|
||||
testVirtualTree(c, maxLevels, keys[:2], values[:2])
|
||||
testVirtualTree(c, maxLevels, keys[:3], values[:3])
|
||||
testVirtualTree(c, maxLevels, keys[:4], values[:4])
|
||||
// // check the root for different batches of leafs
|
||||
// testVirtualTree(c, maxLevels, keys[:1], values[:1])
|
||||
// testVirtualTree(c, maxLevels, keys[:2], values[:2])
|
||||
// testVirtualTree(c, maxLevels, keys[:3], values[:3])
|
||||
// testVirtualTree(c, maxLevels, keys[:4], values[:4])
|
||||
|
||||
// test with hardcoded values
|
||||
testvectorKeys := []string{
|
||||
"1c7c2265e368314ca58ed2e1f33a326f1220e234a566d55c3605439dbe411642",
|
||||
"2c9f0a578afff5bfa4e0992a43066460faaab9e8e500db0b16647c701cdb16bf",
|
||||
"9cb87ec67e875c61390edcd1ab517f443591047709a4d4e45b0f9ed980857b8e",
|
||||
"9b4e9e92e974a589f426ceeb4cb291dc24893513fecf8e8460992dcf52621d4d",
|
||||
"1c45cb31f2fa39ec7b9ebf0fad40e0b8296016b5ce8844ae06ff77226379d9a5",
|
||||
"d8af98bbbb585129798ae54d5eabbc9d0561d583faf1663b3a3724d15bda4ec7",
|
||||
"3cd55dbfb8f975f20a0925dfbdabe79fa2d51dd0268afbb8ba6b01de9dfcdd3c",
|
||||
"5d0a9d6d9f197c091bf054fac9cb60e11ec723d6610ed8578e617b4d46cb43d5",
|
||||
}
|
||||
keys = [][]byte{}
|
||||
values = [][]byte{}
|
||||
for i := 0; i < len(testvectorKeys); i++ {
|
||||
key, err := hex.DecodeString(testvectorKeys[i])
|
||||
c.Assert(err, qt.IsNil)
|
||||
keys = append(keys, key)
|
||||
values = append(values, []byte{0})
|
||||
}
|
||||
// // test with hardcoded values
|
||||
// testvectorKeys := []string{
|
||||
// "1c7c2265e368314ca58ed2e1f33a326f1220e234a566d55c3605439dbe411642",
|
||||
// "2c9f0a578afff5bfa4e0992a43066460faaab9e8e500db0b16647c701cdb16bf",
|
||||
// "9cb87ec67e875c61390edcd1ab517f443591047709a4d4e45b0f9ed980857b8e",
|
||||
// "9b4e9e92e974a589f426ceeb4cb291dc24893513fecf8e8460992dcf52621d4d",
|
||||
// "1c45cb31f2fa39ec7b9ebf0fad40e0b8296016b5ce8844ae06ff77226379d9a5",
|
||||
// "d8af98bbbb585129798ae54d5eabbc9d0561d583faf1663b3a3724d15bda4ec7",
|
||||
// "3cd55dbfb8f975f20a0925dfbdabe79fa2d51dd0268afbb8ba6b01de9dfcdd3c",
|
||||
// "5d0a9d6d9f197c091bf054fac9cb60e11ec723d6610ed8578e617b4d46cb43d5",
|
||||
// }
|
||||
// keys = [][]byte{}
|
||||
// values = [][]byte{}
|
||||
// for i := 0; i < len(testvectorKeys); i++ {
|
||||
// key, err := hex.DecodeString(testvectorKeys[i])
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// keys = append(keys, key)
|
||||
// values = append(values, []byte{0})
|
||||
// }
|
||||
|
||||
// check the root for different batches of leafs
|
||||
testVirtualTree(c, 256, keys[:1], values[:1])
|
||||
testVirtualTree(c, 256, keys, values)
|
||||
}
|
||||
// // check the root for different batches of leafs
|
||||
// testVirtualTree(c, 256, keys[:1], values[:1])
|
||||
// testVirtualTree(c, 256, keys, values)
|
||||
// }
|
||||
|
||||
func TestVirtualTreeRandomKeys(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
// func TestVirtualTreeRandomKeys(t *testing.T) {
|
||||
// c := qt.New(t)
|
||||
|
||||
// test with random values
|
||||
nLeafs := 1024
|
||||
keys := make([][]byte, nLeafs)
|
||||
values := make([][]byte, nLeafs)
|
||||
for i := 0; i < nLeafs; i++ {
|
||||
keys[i] = randomBytes(32)
|
||||
values[i] = randomBytes(32)
|
||||
}
|
||||
// // test with random values
|
||||
// nLeafs := 1024
|
||||
// keys := make([][]byte, nLeafs)
|
||||
// values := make([][]byte, nLeafs)
|
||||
// for i := 0; i < nLeafs; i++ {
|
||||
// keys[i] = randomBytes(32)
|
||||
// values[i] = randomBytes(32)
|
||||
// }
|
||||
|
||||
testVirtualTree(c, 256, keys, values)
|
||||
}
|
||||
// testVirtualTree(c, 256, keys, values)
|
||||
// }
|
||||
|
||||
func TestVirtualTreeAddBatch(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
// func TestVirtualTreeAddBatch(t *testing.T) {
|
||||
// c := qt.New(t)
|
||||
|
||||
nLeafs := 2000
|
||||
maxLevels := 256
|
||||
// nLeafs := 2000
|
||||
// maxLevels := 256
|
||||
|
||||
keys := make([][]byte, nLeafs)
|
||||
values := make([][]byte, nLeafs)
|
||||
for i := 0; i < nLeafs; i++ {
|
||||
keys[i] = randomBytes(32)
|
||||
values[i] = randomBytes(32)
|
||||
}
|
||||
// keys := make([][]byte, nLeafs)
|
||||
// values := make([][]byte, nLeafs)
|
||||
// for i := 0; i < nLeafs; i++ {
|
||||
// keys[i] = randomBytes(32)
|
||||
// values[i] = randomBytes(32)
|
||||
// }
|
||||
|
||||
// normal tree, to have an expected root value
|
||||
database, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
c.Assert(err, qt.IsNil)
|
||||
tree, err := NewTree(Config{Database: database, MaxLevels: maxLevels,
|
||||
HashFunction: HashFunctionPoseidon})
|
||||
c.Assert(err, qt.IsNil)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
err := tree.Add(keys[i], values[i])
|
||||
c.Assert(err, qt.IsNil)
|
||||
}
|
||||
// // normal tree, to have an expected root value
|
||||
// database, err := pebbledb.New(db.Options{Path: c.TempDir()})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// tree, err := NewTree(Config{Database: database, MaxLevels: maxLevels,
|
||||
// HashFunction: HashFunctionPoseidon})
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// for i := 0; i < len(keys); i++ {
|
||||
// err := tree.Add(keys[i], values[i])
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// }
|
||||
|
||||
// virtual tree
|
||||
vTree := newVT(maxLevels, HashFunctionPoseidon)
|
||||
// // virtual tree
|
||||
// vTree := newVT(maxLevels, HashFunctionPoseidon)
|
||||
|
||||
c.Assert(vTree.root, qt.IsNil)
|
||||
// c.Assert(vTree.root, qt.IsNil)
|
||||
|
||||
invalids, err := vTree.addBatch(keys, values)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(invalids), qt.Equals, 0)
|
||||
// invalids, err := vTree.addBatch(keys, values)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(invalids), qt.Equals, 0)
|
||||
|
||||
// compute hashes, and check Root
|
||||
_, err = vTree.computeHashes()
|
||||
c.Assert(err, qt.IsNil)
|
||||
root, err := tree.Root()
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(vTree.root.h, qt.DeepEquals, root)
|
||||
}
|
||||
// // compute hashes, and check Root
|
||||
// _, err = vTree.computeHashes()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// root, err := tree.Root()
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(vTree.root.h, qt.DeepEquals, root)
|
||||
// }
|
||||
|
||||
func TestVirtualTreeAddBatchFullyUsed(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
// func TestVirtualTreeAddBatchFullyUsed(t *testing.T) {
|
||||
// c := qt.New(t)
|
||||
|
||||
vTree1 := newVT(7, HashFunctionPoseidon) // used for add one by one
|
||||
vTree2 := newVT(7, HashFunctionPoseidon) // used for addBatch
|
||||
// vTree1 := newVT(7, HashFunctionPoseidon) // used for add one by one
|
||||
// vTree2 := newVT(7, HashFunctionPoseidon) // used for addBatch
|
||||
|
||||
var keys, values [][]byte
|
||||
for i := 0; i < 128; i++ {
|
||||
k := BigIntToBytes(1, big.NewInt(int64(i)))
|
||||
v := k
|
||||
// var keys, values [][]byte
|
||||
// for i := 0; i < 128; i++ {
|
||||
// k := BigIntToBytes(1, big.NewInt(int64(i)))
|
||||
// v := k
|
||||
|
||||
keys = append(keys, k)
|
||||
values = append(values, v)
|
||||
// keys = append(keys, k)
|
||||
// values = append(values, v)
|
||||
|
||||
// add one by one expecting no error
|
||||
err := vTree1.add(0, k, v)
|
||||
c.Assert(err, qt.IsNil)
|
||||
}
|
||||
// // add one by one expecting no error
|
||||
// err := vTree1.add(0, k, v)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// }
|
||||
|
||||
invalids, err := vTree2.addBatch(keys, values)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(0, qt.Equals, len(invalids))
|
||||
}
|
||||
// invalids, err := vTree2.addBatch(keys, values)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(0, qt.Equals, len(invalids))
|
||||
// }
|
||||
|
||||
func TestGetNodesAtLevel(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
// func TestGetNodesAtLevel(t *testing.T) {
|
||||
// c := qt.New(t)
|
||||
|
||||
tree0 := vt{
|
||||
params: ¶ms{
|
||||
maxLevels: 100,
|
||||
hashFunction: HashFunctionPoseidon,
|
||||
emptyHash: make([]byte, HashFunctionPoseidon.Len()),
|
||||
},
|
||||
root: nil,
|
||||
}
|
||||
// tree0 := vt{
|
||||
// params: ¶ms{
|
||||
// maxLevels: 100,
|
||||
// hashFunction: HashFunctionPoseidon,
|
||||
// emptyHash: make([]byte, HashFunctionPoseidon.Len()),
|
||||
// },
|
||||
// root: nil,
|
||||
// }
|
||||
|
||||
tree1 := vt{
|
||||
params: ¶ms{
|
||||
maxLevels: 100,
|
||||
hashFunction: HashFunctionPoseidon,
|
||||
emptyHash: make([]byte, HashFunctionPoseidon.Len()),
|
||||
},
|
||||
root: &node{
|
||||
l: &node{
|
||||
l: &node{
|
||||
k: []byte{0, 0, 0, 0},
|
||||
v: []byte{0, 0, 0, 0},
|
||||
},
|
||||
r: &node{
|
||||
k: []byte{0, 0, 0, 1},
|
||||
v: []byte{0, 0, 0, 1},
|
||||
},
|
||||
},
|
||||
r: &node{
|
||||
l: &node{
|
||||
k: []byte{0, 0, 0, 2},
|
||||
v: []byte{0, 0, 0, 2},
|
||||
},
|
||||
r: &node{
|
||||
k: []byte{0, 0, 0, 3},
|
||||
v: []byte{0, 0, 0, 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
// tree1.printGraphviz()
|
||||
// tree1 := vt{
|
||||
// params: ¶ms{
|
||||
// maxLevels: 100,
|
||||
// hashFunction: HashFunctionPoseidon,
|
||||
// emptyHash: make([]byte, HashFunctionPoseidon.Len()),
|
||||
// },
|
||||
// root: &node{
|
||||
// l: &node{
|
||||
// l: &node{
|
||||
// k: []byte{0, 0, 0, 0},
|
||||
// v: []byte{0, 0, 0, 0},
|
||||
// },
|
||||
// r: &node{
|
||||
// k: []byte{0, 0, 0, 1},
|
||||
// v: []byte{0, 0, 0, 1},
|
||||
// },
|
||||
// },
|
||||
// r: &node{
|
||||
// l: &node{
|
||||
// k: []byte{0, 0, 0, 2},
|
||||
// v: []byte{0, 0, 0, 2},
|
||||
// },
|
||||
// r: &node{
|
||||
// k: []byte{0, 0, 0, 3},
|
||||
// v: []byte{0, 0, 0, 3},
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// // tree1.printGraphviz()
|
||||
|
||||
tree2 := vt{
|
||||
params: ¶ms{
|
||||
maxLevels: 100,
|
||||
hashFunction: HashFunctionPoseidon,
|
||||
emptyHash: make([]byte, HashFunctionPoseidon.Len()),
|
||||
},
|
||||
root: &node{
|
||||
l: nil,
|
||||
r: &node{
|
||||
l: &node{
|
||||
l: &node{
|
||||
l: &node{
|
||||
k: []byte{0, 0, 0, 0},
|
||||
v: []byte{0, 0, 0, 0},
|
||||
},
|
||||
r: &node{
|
||||
k: []byte{0, 0, 0, 1},
|
||||
v: []byte{0, 0, 0, 1},
|
||||
},
|
||||
},
|
||||
r: &node{
|
||||
k: []byte{0, 0, 0, 2},
|
||||
v: []byte{0, 0, 0, 2},
|
||||
},
|
||||
},
|
||||
r: &node{
|
||||
k: []byte{0, 0, 0, 3},
|
||||
v: []byte{0, 0, 0, 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
// tree2.printGraphviz()
|
||||
// tree2 := vt{
|
||||
// params: ¶ms{
|
||||
// maxLevels: 100,
|
||||
// hashFunction: HashFunctionPoseidon,
|
||||
// emptyHash: make([]byte, HashFunctionPoseidon.Len()),
|
||||
// },
|
||||
// root: &node{
|
||||
// l: nil,
|
||||
// r: &node{
|
||||
// l: &node{
|
||||
// l: &node{
|
||||
// l: &node{
|
||||
// k: []byte{0, 0, 0, 0},
|
||||
// v: []byte{0, 0, 0, 0},
|
||||
// },
|
||||
// r: &node{
|
||||
// k: []byte{0, 0, 0, 1},
|
||||
// v: []byte{0, 0, 0, 1},
|
||||
// },
|
||||
// },
|
||||
// r: &node{
|
||||
// k: []byte{0, 0, 0, 2},
|
||||
// v: []byte{0, 0, 0, 2},
|
||||
// },
|
||||
// },
|
||||
// r: &node{
|
||||
// k: []byte{0, 0, 0, 3},
|
||||
// v: []byte{0, 0, 0, 3},
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// // tree2.printGraphviz()
|
||||
|
||||
tree3 := vt{
|
||||
params: ¶ms{
|
||||
maxLevels: 100,
|
||||
hashFunction: HashFunctionPoseidon,
|
||||
emptyHash: make([]byte, HashFunctionPoseidon.Len()),
|
||||
},
|
||||
root: &node{
|
||||
l: nil,
|
||||
r: &node{
|
||||
l: &node{
|
||||
l: &node{
|
||||
l: &node{
|
||||
k: []byte{0, 0, 0, 0},
|
||||
v: []byte{0, 0, 0, 0},
|
||||
},
|
||||
r: &node{
|
||||
k: []byte{0, 0, 0, 1},
|
||||
v: []byte{0, 0, 0, 1},
|
||||
},
|
||||
},
|
||||
r: &node{
|
||||
k: []byte{0, 0, 0, 2},
|
||||
v: []byte{0, 0, 0, 2},
|
||||
},
|
||||
},
|
||||
r: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
// tree3.printGraphviz()
|
||||
// tree3 := vt{
|
||||
// params: ¶ms{
|
||||
// maxLevels: 100,
|
||||
// hashFunction: HashFunctionPoseidon,
|
||||
// emptyHash: make([]byte, HashFunctionPoseidon.Len()),
|
||||
// },
|
||||
// root: &node{
|
||||
// l: nil,
|
||||
// r: &node{
|
||||
// l: &node{
|
||||
// l: &node{
|
||||
// l: &node{
|
||||
// k: []byte{0, 0, 0, 0},
|
||||
// v: []byte{0, 0, 0, 0},
|
||||
// },
|
||||
// r: &node{
|
||||
// k: []byte{0, 0, 0, 1},
|
||||
// v: []byte{0, 0, 0, 1},
|
||||
// },
|
||||
// },
|
||||
// r: &node{
|
||||
// k: []byte{0, 0, 0, 2},
|
||||
// v: []byte{0, 0, 0, 2},
|
||||
// },
|
||||
// },
|
||||
// r: nil,
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// // tree3.printGraphviz()
|
||||
|
||||
nodes0, err := tree0.getNodesAtLevel(2)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(nodes0), qt.DeepEquals, 4)
|
||||
c.Assert("0000", qt.DeepEquals, getNotNils(nodes0))
|
||||
// nodes0, err := tree0.getNodesAtLevel(2)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(nodes0), qt.DeepEquals, 4)
|
||||
// c.Assert("0000", qt.DeepEquals, getNotNils(nodes0))
|
||||
|
||||
nodes1, err := tree1.getNodesAtLevel(2)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(nodes1), qt.DeepEquals, 4)
|
||||
c.Assert("1111", qt.DeepEquals, getNotNils(nodes1))
|
||||
// nodes1, err := tree1.getNodesAtLevel(2)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(nodes1), qt.DeepEquals, 4)
|
||||
// c.Assert("1111", qt.DeepEquals, getNotNils(nodes1))
|
||||
|
||||
nodes1, err = tree1.getNodesAtLevel(3)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(nodes1), qt.DeepEquals, 8)
|
||||
c.Assert("00000000", qt.DeepEquals, getNotNils(nodes1))
|
||||
// nodes1, err = tree1.getNodesAtLevel(3)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(nodes1), qt.DeepEquals, 8)
|
||||
// c.Assert("00000000", qt.DeepEquals, getNotNils(nodes1))
|
||||
|
||||
nodes2, err := tree2.getNodesAtLevel(2)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(nodes2), qt.DeepEquals, 4)
|
||||
c.Assert("0011", qt.DeepEquals, getNotNils(nodes2))
|
||||
// nodes2, err := tree2.getNodesAtLevel(2)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(nodes2), qt.DeepEquals, 4)
|
||||
// c.Assert("0011", qt.DeepEquals, getNotNils(nodes2))
|
||||
|
||||
nodes2, err = tree2.getNodesAtLevel(3)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(nodes2), qt.DeepEquals, 8)
|
||||
c.Assert("00001100", qt.DeepEquals, getNotNils(nodes2))
|
||||
// nodes2, err = tree2.getNodesAtLevel(3)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(nodes2), qt.DeepEquals, 8)
|
||||
// c.Assert("00001100", qt.DeepEquals, getNotNils(nodes2))
|
||||
|
||||
nodes3, err := tree3.getNodesAtLevel(2)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(nodes3), qt.DeepEquals, 4)
|
||||
c.Assert("0010", qt.DeepEquals, getNotNils(nodes3))
|
||||
// nodes3, err := tree3.getNodesAtLevel(2)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(nodes3), qt.DeepEquals, 4)
|
||||
// c.Assert("0010", qt.DeepEquals, getNotNils(nodes3))
|
||||
|
||||
nodes3, err = tree3.getNodesAtLevel(3)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(nodes3), qt.DeepEquals, 8)
|
||||
c.Assert("00001100", qt.DeepEquals, getNotNils(nodes3))
|
||||
// nodes3, err = tree3.getNodesAtLevel(3)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(nodes3), qt.DeepEquals, 8)
|
||||
// c.Assert("00001100", qt.DeepEquals, getNotNils(nodes3))
|
||||
|
||||
nodes3, err = tree3.getNodesAtLevel(4)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(len(nodes3), qt.DeepEquals, 16)
|
||||
c.Assert("0000000011000000", qt.DeepEquals, getNotNils(nodes3))
|
||||
}
|
||||
// nodes3, err = tree3.getNodesAtLevel(4)
|
||||
// c.Assert(err, qt.IsNil)
|
||||
// c.Assert(len(nodes3), qt.DeepEquals, 16)
|
||||
// c.Assert("0000000011000000", qt.DeepEquals, getNotNils(nodes3))
|
||||
// }
|
||||
|
||||
func getNotNils(nodes []*node) string {
|
||||
s := ""
|
||||
for i := 0; i < len(nodes); i++ {
|
||||
if nodes[i] == nil {
|
||||
s += "0"
|
||||
} else {
|
||||
s += "1"
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
// func getNotNils(nodes []*node) string {
|
||||
// s := ""
|
||||
// for i := 0; i < len(nodes); i++ {
|
||||
// if nodes[i] == nil {
|
||||
// s += "0"
|
||||
// } else {
|
||||
// s += "1"
|
||||
// }
|
||||
// }
|
||||
// return s
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user