dirty commit

This commit is contained in:
Lucas Menendez
2025-03-25 16:34:14 +01:00
parent a7c0c5f8c3
commit f5d41490b8
6 changed files with 213 additions and 71 deletions

View File

@@ -76,7 +76,7 @@ func TestAddBatchTreeEmpty(t *testing.T) {
tree, err := NewTree(Config{database, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
var keys, values [][]byte
@@ -100,7 +100,7 @@ func TestAddBatchTreeEmpty(t *testing.T) {
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
tree2.dbgInit()
start = time.Now()
@@ -128,7 +128,7 @@ func TestAddBatchTreeEmptyNotPowerOf2(t *testing.T) {
tree, err := NewTree(Config{database, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
for i := 0; i < nLeafs; i++ {
@@ -144,7 +144,7 @@ func TestAddBatchTreeEmptyNotPowerOf2(t *testing.T) {
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
var keys, values [][]byte
for i := 0; i < nLeafs; i++ {
@@ -177,14 +177,14 @@ func TestAddBatchTestVector1(t *testing.T) {
tree1, err := NewTree(Config{database1, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
database2, err := pebbledb.New(db.Options{Path: c.TempDir()})
c.Assert(err, qt.IsNil)
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
// leafs in 2nd level subtrees: [ 6, 0, 1, 1]
testvectorKeys := []string{
@@ -219,14 +219,14 @@ func TestAddBatchTestVector1(t *testing.T) {
tree1, err = NewTree(Config{database1, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
database2, err = pebbledb.New(db.Options{Path: c.TempDir()})
c.Assert(err, qt.IsNil)
tree2, err = NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
testvectorKeys = []string{
"1c7c2265e368314ca58ed2e1f33a326f1220e234a566d55c3605439dbe411642",
@@ -269,14 +269,14 @@ func TestAddBatchTestVector2(t *testing.T) {
tree1, err := NewTree(Config{database, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
database2, err := pebbledb.New(db.Options{Path: c.TempDir()})
c.Assert(err, qt.IsNil)
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
bLen := tree1.HashFunction().Len()
var keys, values [][]byte
@@ -316,14 +316,14 @@ func TestAddBatchTestVector3(t *testing.T) {
tree1, err := NewTree(Config{database, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
database2, err := pebbledb.New(db.Options{Path: c.TempDir()})
c.Assert(err, qt.IsNil)
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
bLen := tree1.HashFunction().Len()
var keys, values [][]byte
@@ -367,14 +367,14 @@ func TestAddBatchTreeEmptyRandomKeys(t *testing.T) {
tree1, err := NewTree(Config{database1, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
database2, err := pebbledb.New(db.Options{Path: c.TempDir()})
c.Assert(err, qt.IsNil)
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
var keys, values [][]byte
for i := 0; i < nLeafs; i++ {
@@ -719,7 +719,7 @@ func TestAddBatchNotEmptyUnbalanced(t *testing.T) {
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
tree2.dbgInit()
var keys, values [][]byte
@@ -797,7 +797,7 @@ func benchAdd(t *testing.T, ks, vs [][]byte) {
tree, err := NewTree(Config{database, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
start := time.Now()
for i := 0; i < len(ks); i++ {
@@ -818,7 +818,7 @@ func benchAddBatch(t *testing.T, ks, vs [][]byte) {
tree, err := NewTree(Config{database, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
tree.dbgInit()
@@ -852,7 +852,7 @@ func TestDbgStats(t *testing.T) {
tree1, err := NewTree(Config{database1, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
tree1.dbgInit()
@@ -867,7 +867,7 @@ func TestDbgStats(t *testing.T) {
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
tree2.dbgInit()
@@ -881,7 +881,7 @@ func TestDbgStats(t *testing.T) {
tree3, err := NewTree(Config{database3, 256, DefaultThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree3.db.Close() //nolint:errcheck
defer tree3.treedb.Close() //nolint:errcheck
tree3.dbgInit()
@@ -916,7 +916,7 @@ func TestLoadVT(t *testing.T) {
tree, err := NewTree(Config{database, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
var keys, values [][]byte
for i := 0; i < nLeafs; i++ {
@@ -951,7 +951,7 @@ func TestAddKeysWithEmptyValues(t *testing.T) {
tree, err := NewTree(Config{database, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
var keys, values [][]byte
@@ -973,7 +973,7 @@ func TestAddKeysWithEmptyValues(t *testing.T) {
tree2, err := NewTree(Config{database2, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
tree2.dbgInit()
invalids, err := tree2.AddBatch(keys, values)
@@ -988,7 +988,7 @@ func TestAddKeysWithEmptyValues(t *testing.T) {
tree3, err := NewTree(Config{database3, 256, DefaultThresholdNLeafs,
HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree3.db.Close() //nolint:errcheck
defer tree3.treedb.Close() //nolint:errcheck
invalids, err = tree3.AddBatch(keys, nil)
c.Assert(err, qt.IsNil)
@@ -1038,21 +1038,21 @@ func TestAddBatchThresholdInDisk(t *testing.T) {
tree1, err := NewTree(Config{database1, 256, testThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
database2, err := pebbledb.New(db.Options{Path: c.TempDir()})
c.Assert(err, qt.IsNil)
tree2, err := NewTree(Config{database2, 256, testThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
database3, err := pebbledb.New(db.Options{Path: c.TempDir()})
c.Assert(err, qt.IsNil)
tree3, err := NewTree(Config{database3, 256, testThresholdNLeafs,
HashFunctionBlake2b})
c.Assert(err, qt.IsNil)
defer tree3.db.Close() //nolint:errcheck
defer tree3.treedb.Close() //nolint:errcheck
var keys, values [][]byte
for i := 0; i < 3*testThresholdNLeafs; i++ {
@@ -1078,7 +1078,7 @@ func TestAddBatchThresholdInDisk(t *testing.T) {
checkRoots(c, tree1, tree2)
// call directly the tree3.addBatchInDisk to ensure that is tested
wTx := tree3.db.WriteTx()
wTx := tree3.treedb.WriteTx()
defer wTx.Discard()
invalids, err = tree3.addBatchInDisk(wTx, keys, values)
c.Assert(err, qt.IsNil)
@@ -1127,7 +1127,7 @@ func testUpFromSubRoots(c *qt.C, tree1, tree2 *Tree, preSubRoots [][]byte) {
root1, err := tree1.Root()
c.Assert(err, qt.IsNil)
wTx := tree2.db.WriteTx()
wTx := tree2.treedb.WriteTx()
subRoots := make([][]byte, len(preSubRoots))
for i := 0; i < len(preSubRoots); i++ {
if preSubRoots[i] == nil || bytes.Equal(preSubRoots[i], tree1.emptyHash) {
@@ -1159,8 +1159,8 @@ func testUpFromSubRoots(c *qt.C, tree1, tree2 *Tree, preSubRoots [][]byte) {
func testUpFromSubRootsWithEmpties(c *qt.C, preSubRoots [][]byte, indexEmpties []int) {
tree1, tree2 := initTestUpFromSubRoots(c)
defer tree1.db.Close() //nolint:errcheck
defer tree2.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
testPreSubRoots := make([][]byte, len(preSubRoots))
copy(testPreSubRoots[:], preSubRoots[:])

View File

@@ -17,7 +17,7 @@ func TestCircomVerifierProof(t *testing.T) {
tree, err := NewTree(Config{Database: database, MaxLevels: 4,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
testVector := [][]int64{
{1, 11},

63
tree.go
View File

@@ -22,6 +22,7 @@ import (
"sync"
"go.vocdoni.io/dvote/db"
"go.vocdoni.io/dvote/db/prefixeddb"
)
const (
@@ -55,9 +56,11 @@ var (
// in disk.
DefaultThresholdNLeafs = 65536
dbKeyRoot = []byte("root")
dbKeyNLeafs = []byte("nleafs")
emptyValue = []byte{0}
dbTreePrefix = []byte("tree")
dbValuesPrefix = []byte("values")
dbKeyRoot = []byte("root")
dbKeyNLeafs = []byte("nleafs")
emptyValue = []byte{0}
// ErrKeyNotFound is used when a key is not found in the db neither in
// the current db Batch.
@@ -88,7 +91,8 @@ var (
type Tree struct {
sync.Mutex
db db.Database
treedb db.Database
valuesdb db.Database
maxLevels int
// thresholdNLeafs defines the threshold number of leafs in the tree
// that determines if AddBatch will work in memory or in disk. It is
@@ -138,9 +142,16 @@ 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 = make([]byte, t.hashFunction.Len()) // empty
treedb := prefixeddb.NewPrefixedDatabase(cfg.Database, dbTreePrefix)
valuesdb := prefixeddb.NewPrefixedDatabase(cfg.Database, dbValuesPrefix)
t := Tree{
treedb: treedb,
valuesdb: valuesdb,
maxLevels: cfg.MaxLevels,
thresholdNLeafs: cfg.ThresholdNLeafs,
hashFunction: cfg.HashFunction,
emptyHash: make([]byte, cfg.HashFunction.Len()),
}
_, err := wTx.Get(dbKeyRoot)
if err == db.ErrKeyNotFound {
@@ -160,7 +171,7 @@ func NewTreeWithTx(wTx db.WriteTx, cfg Config) (*Tree, error) {
// Root returns the root of the Tree
func (t *Tree) Root() ([]byte, error) {
return t.RootWithTx(t.db)
return t.RootWithTx(t.treedb)
}
// RootWithTx returns the root of the Tree using the given db.ReadTx
@@ -201,7 +212,7 @@ type Invalid struct {
// the indexes of the keys failed to add. Supports empty values as input
// parameters, which is equivalent to 0 valued byte array.
func (t *Tree) AddBatch(keys, values [][]byte) ([]Invalid, error) {
wTx := t.db.WriteTx()
wTx := t.treedb.WriteTx()
defer wTx.Discard()
invalids, err := t.AddBatchWithTx(wTx, keys, values)
@@ -312,7 +323,7 @@ func (t *Tree) addBatchInDisk(wTx db.WriteTx, keys, values [][]byte) ([]Invalid,
invalidsInBucket := make([][]Invalid, nCPU)
txs := make([]db.WriteTx, nCPU)
for i := 0; i < nCPU; i++ {
txs[i] = t.db.WriteTx()
txs[i] = t.treedb.WriteTx()
err := txs[i].Apply(wTx)
if err != nil {
return nil, err
@@ -493,7 +504,7 @@ func (t *Tree) loadVT() (vt, error) {
vt := newVT(t.maxLevels, t.hashFunction)
vt.params.dbg = t.dbg
var callbackErr error
err := t.IterateWithStopWithTx(t.db, nil, func(_ int, k, v []byte) bool {
err := t.IterateWithStopWithTx(t.treedb, nil, func(_ int, k, v []byte) bool {
if v[0] != PrefixValueLeaf {
return false
}
@@ -515,7 +526,7 @@ func (t *Tree) loadVT() (vt, error) {
// *big.Int, is expected that are represented by a Little-Endian byte array
// (for circom compatibility).
func (t *Tree) Add(k, v []byte) error {
wTx := t.db.WriteTx()
wTx := t.treedb.WriteTx()
defer wTx.Discard()
if err := t.AddWithTx(wTx, k, v); err != nil {
@@ -860,7 +871,7 @@ func getPath(numLevels int, k []byte) []bool {
// Update updates the value for a given existing key. If the given key does not
// exist, returns an error.
func (t *Tree) Update(k, v []byte) error {
wTx := t.db.WriteTx()
wTx := t.treedb.WriteTx()
defer wTx.Discard()
if err := t.UpdateWithTx(wTx, k, v); err != nil {
@@ -930,7 +941,7 @@ func (t *Tree) UpdateWithTx(wTx db.WriteTx, k, v []byte) error {
// returned, together with the packed siblings of the proof, and a boolean
// parameter that indicates if the proof is of existence (true) or not (false).
func (t *Tree) GenProof(k []byte) ([]byte, []byte, []byte, bool, error) {
return t.GenProofWithTx(t.db, k)
return t.GenProofWithTx(t.treedb, k)
}
// GenProofWithTx does the same than the GenProof method, but allowing to pass
@@ -1062,7 +1073,7 @@ func bytesToBitmap(b []byte) []bool {
// will be placed the data found in the tree in the leaf that was on the path
// going to the input key.
func (t *Tree) Get(k []byte) ([]byte, []byte, error) {
return t.GetWithTx(t.db, k)
return t.GetWithTx(t.treedb, k)
}
// GetWithTx does the same than the Get method, but allowing to pass the
@@ -1151,7 +1162,7 @@ func (t *Tree) setNLeafs(wTx db.WriteTx, nLeafs int) error {
// GetNLeafs returns the number of Leafs of the Tree.
func (t *Tree) GetNLeafs() (int, error) {
return t.GetNLeafsWithTx(t.db)
return t.GetNLeafsWithTx(t.treedb)
}
// GetNLeafsWithTx does the same than the GetNLeafs method, but allowing to
@@ -1167,7 +1178,7 @@ func (t *Tree) GetNLeafsWithTx(rTx db.Reader) (int, error) {
// SetRoot sets the root to the given root
func (t *Tree) SetRoot(root []byte) error {
wTx := t.db.WriteTx()
wTx := t.treedb.WriteTx()
defer wTx.Discard()
if err := t.SetRootWithTx(wTx, root); err != nil {
@@ -1209,7 +1220,7 @@ func (t *Tree) Snapshot(fromRoot []byte) (*Tree, error) {
return nil, err
}
}
rTx := t.db
rTx := t.treedb
// check that the root exists in the db
if !bytes.Equal(fromRoot, t.emptyHash) {
if _, err := rTx.Get(fromRoot); err == ErrKeyNotFound {
@@ -1222,7 +1233,7 @@ func (t *Tree) Snapshot(fromRoot []byte) (*Tree, error) {
}
return &Tree{
db: t.db,
treedb: t.treedb,
maxLevels: t.maxLevels,
snapshotRoot: fromRoot,
emptyHash: t.emptyHash,
@@ -1234,7 +1245,7 @@ func (t *Tree) Snapshot(fromRoot []byte) (*Tree, error) {
// Iterate iterates through the full Tree, executing the given function on each
// node of the Tree.
func (t *Tree) Iterate(fromRoot []byte, f func([]byte, []byte)) error {
return t.IterateWithTx(t.db, fromRoot, f)
return t.IterateWithTx(t.treedb, fromRoot, f)
}
// IterateWithTx does the same than the Iterate method, but allowing to pass
@@ -1258,12 +1269,12 @@ func (t *Tree) IterateWithStop(fromRoot []byte, f func(int, []byte, []byte) bool
// allow to define which root to use
if fromRoot == nil {
var err error
fromRoot, err = t.RootWithTx(t.db)
fromRoot, err = t.RootWithTx(t.treedb)
if err != nil {
return err
}
}
return t.iterWithStop(t.db, fromRoot, 0, f)
return t.iterWithStop(t.treedb, fromRoot, 0, f)
}
// IterateWithStopWithTx does the same than the IterateWithStop method, but
@@ -1470,14 +1481,14 @@ node [fontname=Monospace,fontsize=10,shape=box]
}
if fromRoot == nil {
var err error
fromRoot, err = t.RootWithTx(t.db)
fromRoot, err = t.RootWithTx(t.treedb)
if err != nil {
return err
}
}
nEmpties := 0
err := t.iterWithStop(t.db, fromRoot, 0, func(currLvl int, k, v []byte) bool {
err := t.iterWithStop(t.treedb, fromRoot, 0, func(currLvl int, k, v []byte) bool {
if currLvl == untilLvl {
return true // to stop the iter from going down
}
@@ -1575,3 +1586,7 @@ func (t *Tree) PrintGraphvizFirstNLevels(fromRoot []byte, untilLvl int) error {
// TODO circom proofs
// TODO data structure for proofs (including root, key, value, siblings,
// hashFunction) + method to verify that data structure
func (t *Tree) MaxKeyLen() int {
return min(int(math.Ceil(float64(t.maxLevels)/8)), t.HashFunction().Len())
}

122
tree_big.go Normal file
View File

@@ -0,0 +1,122 @@
package arbo
import (
"bytes"
"fmt"
"math/big"
"slices"
)
func (t *Tree) AddBigInt(k *big.Int, v ...*big.Int) error {
bk, bv, fbv, err := bigIntLeaf(t.HashFunction(), k, v)
if err != nil {
return err
}
if err := t.Add(bk, bv); err != nil {
return err
}
wTx := t.valuesdb.WriteTx()
defer wTx.Discard()
if err := wTx.Set(bk, fbv); err != nil {
return err
}
return wTx.Commit()
}
func (t *Tree) GetBigInt(k *big.Int) (*big.Int, []*big.Int, error) {
bk, bv, err := t.Get(bigIntToKey(t.HashFunction(), k))
if err != nil {
return nil, nil, err
}
return t.leafToBigInts(bk, bv)
}
func (t *Tree) GenProofBigInts(k *big.Int) (*big.Int, []*big.Int, []byte, bool, error) {
bk, bv, siblings, exists, err := t.GenProof(bigIntToKey(t.HashFunction(), k))
if err != nil {
return nil, nil, nil, false, err
}
k, v, err := t.leafToBigInts(bk, bv)
if err != nil {
return nil, nil, nil, false, err
}
return k, v, siblings, exists, nil
}
func CheckProofBigInts(hFn HashFunction, root, packedSiblings []byte, k *big.Int, v ...*big.Int) (bool, error) {
bk, bv, _, err := bigIntLeaf(hFn, k, v)
if err != nil {
return false, err
}
return CheckProof(hFn, bk, bv, root, packedSiblings)
}
func bigIntToKey(hFn HashFunction, b *big.Int) []byte {
return BigIntToBytes(hFn.Len(), b)
}
func bigIntLeaf(hFn HashFunction, key *big.Int, values []*big.Int) ([]byte, []byte, []byte, error) {
// calculate the bytes of the key
bKey := bigIntToKey(hFn, key)
// calculate the bytes of the full values (should be reversible)
bFullValue := []byte{}
for _, v := range values {
val := append([]byte{byte(len(v.Bytes()))}, v.Bytes()...)
bFullValue = append(bFullValue, val...)
}
// calculate the value used to build the tree
bValue, err := bigIntToLeafValue(hFn, bFullValue)
if err != nil {
return nil, nil, nil, err
}
return bKey, bValue, bFullValue, nil
}
func bigIntToLeafValue(hFn HashFunction, bFullValue []byte) ([]byte, error) {
// split the full value in chunks of the size of the hash function output
chunks := [][]byte{}
chunk := []byte{}
for i := range bFullValue {
chunk = append(chunk, bFullValue[i])
if len(chunk) == hFn.Len() {
chunks = append(chunks, chunk)
chunk = []byte{}
}
}
// if there is a chunk left, add it to the chunks
if len(chunk) > 0 {
chunks = append(chunks, chunk)
}
// hash the chunks
bValue, err := hFn.Hash(chunks...)
if err != nil {
return nil, err
}
return bValue, nil
}
func (t *Tree) leafToBigInts(key, value []byte) (*big.Int, []*big.Int, error) {
bFullValue, err := t.valuesdb.Get(key)
if err != nil {
return nil, nil, err
}
// recalculate the value to check if it matches the stored value
expectedFullValue, err := bigIntToLeafValue(t.HashFunction(), bFullValue)
if err != nil {
return nil, nil, err
}
if !bytes.Equal(expectedFullValue, value) {
return nil, nil, fmt.Errorf("LeafToBigInt: expectedFullValue != value")
}
// reverse the process of values encoding
values := []*big.Int{}
for iter := slices.Clone(bFullValue); len(iter) > 0; {
lenV := int(bFullValue[0])
values = append(values, new(big.Int).SetBytes(bFullValue[1:1+lenV]))
iter = iter[1+lenV:]
}
return BytesToBigInt(key), values, nil
}

5
tree_big_test.go Normal file
View File

@@ -0,0 +1,5 @@
package arbo
import "testing"
func TestGenCheckProofBigInt(t *testing.T) {}

View File

@@ -76,7 +76,7 @@ func testAdd(c *qt.C, hashFunc HashFunction, testVectors []string) {
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: hashFunc})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
root, err := tree.Root()
c.Assert(err, qt.IsNil)
@@ -109,7 +109,7 @@ func TestAddBatch(t *testing.T) {
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
for i := 0; i < 1000; i++ {
@@ -128,7 +128,7 @@ func TestAddBatch(t *testing.T) {
tree2, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
var keys, values [][]byte
for i := 0; i < 1000; i++ {
@@ -152,7 +152,7 @@ func TestAddDifferentOrder(t *testing.T) {
tree1, err := NewTree(Config{Database: database1, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
bLen := 32
for i := 0; i < 16; i++ {
@@ -168,7 +168,7 @@ func TestAddDifferentOrder(t *testing.T) {
tree2, err := NewTree(Config{Database: database2, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
for i := 16 - 1; i >= 0; i-- {
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
@@ -194,7 +194,7 @@ func TestAddRepeatedIndex(t *testing.T) {
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
k := BigIntToBytes(bLen, big.NewInt(int64(3)))
@@ -213,7 +213,7 @@ func TestUpdate(t *testing.T) {
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
k := BigIntToBytes(bLen, big.NewInt(int64(20)))
@@ -267,7 +267,7 @@ func TestAux(t *testing.T) { // TODO split in proper tests
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
k := BigIntToBytes(bLen, big.NewInt(int64(1)))
@@ -307,7 +307,7 @@ func TestGet(t *testing.T) {
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
for i := 0; i < 10; i++ {
@@ -432,7 +432,7 @@ func TestGenProofAndVerify(t *testing.T) {
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
for i := 0; i < 10; i++ {
@@ -473,7 +473,7 @@ func testDumpAndImportDump(t *testing.T, inFile bool) {
tree1, err := NewTree(Config{Database: database1, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree1.db.Close() //nolint:errcheck
defer tree1.treedb.Close() //nolint:errcheck
bLen := 32
for i := 0; i < 16; i++ {
@@ -502,7 +502,7 @@ func testDumpAndImportDump(t *testing.T, inFile bool) {
tree2, err := NewTree(Config{Database: database2, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree2.db.Close() //nolint:errcheck
defer tree2.treedb.Close() //nolint:errcheck
if inFile {
f, err := os.Open(filepath.Clean(fileName))
@@ -530,7 +530,7 @@ func TestRWMutex(t *testing.T) {
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
var keys, values [][]byte
@@ -783,7 +783,7 @@ func TestGetFromSnapshotExpectArboErrKeyNotFound(t *testing.T) {
tree, err := NewTree(Config{Database: database, MaxLevels: 256,
HashFunction: HashFunctionPoseidon})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
bLen := 32
k := BigIntToBytes(bLen, big.NewInt(int64(3)))
@@ -953,7 +953,7 @@ func benchmarkAdd(b *testing.B, hashFunc HashFunction, ks, vs [][]byte) {
tree, err := NewTree(Config{Database: database, MaxLevels: 140,
HashFunction: hashFunc})
c.Assert(err, qt.IsNil)
defer tree.db.Close() //nolint:errcheck
defer tree.treedb.Close() //nolint:errcheck
for i := 0; i < len(ks); i++ {
if err := tree.Add(ks[i], vs[i]); err != nil {