mirror of
https://github.com/arnaucube/arbo.git
synced 2026-01-09 07:21:28 +01:00
Merge pull request #21 from vocdoni/feature/keyPath-key-len-check
Update keyPath to ceil(maxLvl/8), add checks that len(key)<=maxKeyLen
This commit is contained in:
@@ -39,12 +39,12 @@ func debugTime(descr string, time1, time2 time.Duration) {
|
|||||||
func testInit(c *qt.C, n int) (*Tree, *Tree) {
|
func testInit(c *qt.C, n int) (*Tree, *Tree) {
|
||||||
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err := NewTree(database1, 100, HashFunctionPoseidon)
|
tree1, err := NewTree(database1, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
bLen := HashFunctionPoseidon.Len()
|
bLen := HashFunctionPoseidon.Len()
|
||||||
@@ -70,11 +70,11 @@ func TestAddBatchTreeEmpty(t *testing.T) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
var keys, values [][]byte
|
var keys, values [][]byte
|
||||||
for i := 0; i < nLeafs; i++ {
|
for i := 0; i < nLeafs; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
@@ -93,7 +93,7 @@ func TestAddBatchTreeEmpty(t *testing.T) {
|
|||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
tree2.dbgInit()
|
tree2.dbgInit()
|
||||||
@@ -120,11 +120,11 @@ func TestAddBatchTreeEmptyNotPowerOf2(t *testing.T) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
for i := 0; i < nLeafs; i++ {
|
for i := 0; i < nLeafs; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
|
v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
|
||||||
@@ -135,7 +135,7 @@ func TestAddBatchTreeEmptyNotPowerOf2(t *testing.T) {
|
|||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -167,13 +167,13 @@ func TestAddBatchTestVector1(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err := NewTree(database1, 100, HashFunctionBlake2b)
|
tree1, err := NewTree(database1, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree1.db.Close() //nolint:errcheck
|
defer tree1.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionBlake2b)
|
tree2, err := NewTree(database2, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -207,13 +207,13 @@ func TestAddBatchTestVector1(t *testing.T) {
|
|||||||
// 2nd test vectors
|
// 2nd test vectors
|
||||||
database1, err = badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database1, err = badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err = NewTree(database1, 100, HashFunctionBlake2b)
|
tree1, err = NewTree(database1, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree1.db.Close() //nolint:errcheck
|
defer tree1.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
database2, err = badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err = badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err = NewTree(database2, 100, HashFunctionBlake2b)
|
tree2, err = NewTree(database2, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -255,13 +255,13 @@ func TestAddBatchTestVector2(t *testing.T) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree1, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree1.db.Close() //nolint:errcheck
|
defer tree1.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -300,13 +300,13 @@ func TestAddBatchTestVector3(t *testing.T) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree1, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree1.db.Close() //nolint:errcheck
|
defer tree1.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -349,13 +349,13 @@ func TestAddBatchTreeEmptyRandomKeys(t *testing.T) {
|
|||||||
|
|
||||||
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err := NewTree(database1, 100, HashFunctionBlake2b)
|
tree1, err := NewTree(database1, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree1.db.Close() //nolint:errcheck
|
defer tree1.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionBlake2b)
|
tree2, err := NewTree(database2, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -699,7 +699,7 @@ func TestAddBatchNotEmptyUnbalanced(t *testing.T) {
|
|||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
tree2.dbgInit()
|
tree2.dbgInit()
|
||||||
@@ -776,7 +776,7 @@ func benchAdd(t *testing.T, ks, vs [][]byte) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 140, HashFunctionBlake2b)
|
tree, err := NewTree(database, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -796,7 +796,7 @@ func benchAddBatch(t *testing.T, ks, vs [][]byte) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 140, HashFunctionBlake2b)
|
tree, err := NewTree(database, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -829,7 +829,7 @@ func TestDbgStats(t *testing.T) {
|
|||||||
// 1
|
// 1
|
||||||
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err := NewTree(database1, 100, HashFunctionBlake2b)
|
tree1, err := NewTree(database1, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree1.db.Close() //nolint:errcheck
|
defer tree1.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -843,7 +843,7 @@ func TestDbgStats(t *testing.T) {
|
|||||||
// 2
|
// 2
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionBlake2b)
|
tree2, err := NewTree(database2, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -856,7 +856,7 @@ func TestDbgStats(t *testing.T) {
|
|||||||
// 3
|
// 3
|
||||||
database3, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database3, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree3, err := NewTree(database3, 100, HashFunctionBlake2b)
|
tree3, err := NewTree(database3, 256, HashFunctionBlake2b)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree3.db.Close() //nolint:errcheck
|
defer tree3.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -891,7 +891,7 @@ func TestLoadVT(t *testing.T) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -927,11 +927,11 @@ func TestAddKeysWithEmptyValues(t *testing.T) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
var keys, values [][]byte
|
var keys, values [][]byte
|
||||||
for i := 0; i < nLeafs; i++ {
|
for i := 0; i < nLeafs; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
@@ -948,7 +948,7 @@ func TestAddKeysWithEmptyValues(t *testing.T) {
|
|||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
tree2.dbgInit()
|
tree2.dbgInit()
|
||||||
@@ -962,7 +962,7 @@ func TestAddKeysWithEmptyValues(t *testing.T) {
|
|||||||
// use tree3 to add nil value array
|
// use tree3 to add nil value array
|
||||||
database3, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database3, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree3, err := NewTree(database3, 100, HashFunctionPoseidon)
|
tree3, err := NewTree(database3, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree3.db.Close() //nolint:errcheck
|
defer tree3.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
|||||||
@@ -17,14 +17,13 @@ func TestCircomVerifierProof(t *testing.T) {
|
|||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
|
||||||
|
|
||||||
testVector := [][]int64{
|
testVector := [][]int64{
|
||||||
{1, 11},
|
{1, 11},
|
||||||
{2, 22},
|
{2, 22},
|
||||||
{3, 33},
|
{3, 33},
|
||||||
{4, 44},
|
{4, 44},
|
||||||
}
|
}
|
||||||
|
bLen := 1
|
||||||
for i := 0; i < len(testVector); i++ {
|
for i := 0; i < len(testVector); i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(testVector[i][0]))
|
k := BigIntToBytes(bLen, big.NewInt(testVector[i][0]))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(testVector[i][1]))
|
v := BigIntToBytes(bLen, big.NewInt(testVector[i][1]))
|
||||||
|
|||||||
@@ -18,14 +18,13 @@ func TestGenerator(t *testing.T) {
|
|||||||
tree, err := arbo.NewTree(database, 4, arbo.HashFunctionPoseidon)
|
tree, err := arbo.NewTree(database, 4, arbo.HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
|
||||||
|
|
||||||
testVector := [][]int64{
|
testVector := [][]int64{
|
||||||
{1, 11},
|
{1, 11},
|
||||||
{2, 22},
|
{2, 22},
|
||||||
{3, 33},
|
{3, 33},
|
||||||
{4, 44},
|
{4, 44},
|
||||||
}
|
}
|
||||||
|
bLen := 1
|
||||||
for i := 0; i < len(testVector); i++ {
|
for i := 0; i < len(testVector); i++ {
|
||||||
k := arbo.BigIntToBytes(bLen, big.NewInt(testVector[i][0]))
|
k := arbo.BigIntToBytes(bLen, big.NewInt(testVector[i][0]))
|
||||||
v := arbo.BigIntToBytes(bLen, big.NewInt(testVector[i][1]))
|
v := arbo.BigIntToBytes(bLen, big.NewInt(testVector[i][1]))
|
||||||
|
|||||||
80
tree.go
80
tree.go
@@ -229,8 +229,10 @@ func (t *Tree) AddBatchWithTx(wTx db.WriteTx, keys, values [][]byte) ([]int, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// store root (from the vt) to db
|
// store root (from the vt) to db
|
||||||
if err := wTx.Set(dbKeyRoot, vt.root.h); err != nil {
|
if vt.root != nil {
|
||||||
return nil, err
|
if err := wTx.Set(dbKeyRoot, vt.root.h); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update nLeafs
|
// update nLeafs
|
||||||
@@ -310,17 +312,34 @@ func (t *Tree) AddWithTx(wTx db.WriteTx, k, v []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tree) add(wTx db.WriteTx, root []byte, fromLvl int, k, v []byte) ([]byte, error) {
|
// keyPathFromKey returns the keyPath and checks that the key is not bigger
|
||||||
keyPath := make([]byte, t.hashFunction.Len())
|
// than maximum key length for the tree maxLevels size.
|
||||||
// if len(k) > t.hashFunction.Len() { // WIP
|
// This is because if the key bits length is bigger than the maxLevels of the
|
||||||
// return nil, fmt.Errorf("len(k) > hashFunction.Len()")
|
// tree, two different keys that their difference is at the end, will collision
|
||||||
// }
|
// in the same leaf of the tree (at the max depth).
|
||||||
|
func keyPathFromKey(maxLevels int, k []byte) ([]byte, error) {
|
||||||
|
maxKeyLen := int(math.Ceil(float64(maxLevels) / float64(8))) //nolint:gomnd
|
||||||
|
if len(k) > maxKeyLen {
|
||||||
|
return nil, fmt.Errorf("len(k) can not be bigger than ceil(maxLevels/8), where"+
|
||||||
|
" len(k): %d, maxLevels: %d, max key len=ceil(maxLevels/8): %d. Might need"+
|
||||||
|
" a bigger tree depth (maxLevels>=%d) in order to input keys of length %d",
|
||||||
|
len(k), maxLevels, maxKeyLen, len(k)*8, len(k)) //nolint:gomnd
|
||||||
|
}
|
||||||
|
keyPath := make([]byte, maxKeyLen) //nolint:gomnd
|
||||||
copy(keyPath[:], k)
|
copy(keyPath[:], k)
|
||||||
|
return keyPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tree) add(wTx db.WriteTx, root []byte, fromLvl int, k, v []byte) ([]byte, error) {
|
||||||
|
keyPath, err := keyPathFromKey(t.maxLevels, k)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
path := getPath(t.maxLevels, keyPath)
|
path := getPath(t.maxLevels, keyPath)
|
||||||
|
|
||||||
// go down to the leaf
|
// go down to the leaf
|
||||||
var siblings [][]byte
|
var siblings [][]byte
|
||||||
_, _, siblings, err := t.down(wTx, k, root, siblings, path, fromLvl, false)
|
_, _, siblings, err = t.down(wTx, k, root, siblings, path, fromLvl, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -386,12 +405,10 @@ func (t *Tree) down(rTx db.ReadTx, newKey, currKey []byte, siblings [][]byte,
|
|||||||
return nil, nil, nil, ErrKeyAlreadyExists
|
return nil, nil, nil, ErrKeyAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
oldLeafKeyFull := make([]byte, t.hashFunction.Len())
|
oldLeafKeyFull, err := keyPathFromKey(t.maxLevels, oldLeafKey)
|
||||||
// if len(oldLeafKey) > t.hashFunction.Len() { // WIP
|
if err != nil {
|
||||||
// return nil, nil, nil,
|
return nil, nil, nil, err
|
||||||
// fmt.Errorf("len(oldLeafKey) > hashFunction.Len()")
|
}
|
||||||
// }
|
|
||||||
copy(oldLeafKeyFull[:], oldLeafKey)
|
|
||||||
|
|
||||||
// if currKey is already used, go down until paths diverge
|
// if currKey is already used, go down until paths diverge
|
||||||
oldPath := getPath(t.maxLevels, oldLeafKeyFull)
|
oldPath := getPath(t.maxLevels, oldLeafKeyFull)
|
||||||
@@ -593,13 +610,10 @@ func (t *Tree) UpdateWithTx(wTx db.WriteTx, k, v []byte) error {
|
|||||||
return ErrSnapshotNotEditable
|
return ErrSnapshotNotEditable
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
keyPath, err := keyPathFromKey(t.maxLevels, k)
|
||||||
|
if err != nil {
|
||||||
keyPath := make([]byte, t.hashFunction.Len())
|
return err
|
||||||
// if len(k) > t.hashFunction.Len() { // WIP
|
}
|
||||||
// return fmt.Errorf("len(k) > hashFunction.Len()")
|
|
||||||
// }
|
|
||||||
copy(keyPath[:], k)
|
|
||||||
path := getPath(t.maxLevels, keyPath)
|
path := getPath(t.maxLevels, keyPath)
|
||||||
|
|
||||||
root, err := t.RootWithTx(wTx)
|
root, err := t.RootWithTx(wTx)
|
||||||
@@ -655,18 +669,17 @@ func (t *Tree) GenProof(k []byte) ([]byte, []byte, []byte, bool, error) {
|
|||||||
// GenProofWithTx does the same than the GenProof method, but allowing to pass
|
// GenProofWithTx does the same than the GenProof method, but allowing to pass
|
||||||
// the db.ReadTx that is used.
|
// the db.ReadTx that is used.
|
||||||
func (t *Tree) GenProofWithTx(rTx db.ReadTx, k []byte) ([]byte, []byte, []byte, bool, error) {
|
func (t *Tree) GenProofWithTx(rTx db.ReadTx, k []byte) ([]byte, []byte, []byte, bool, error) {
|
||||||
keyPath := make([]byte, t.hashFunction.Len())
|
keyPath, err := keyPathFromKey(t.maxLevels, k)
|
||||||
// if len(k) > t.hashFunction.Len() { // WIP
|
if err != nil {
|
||||||
// return nil, nil, nil, false, fmt.Errorf("len(k) > hashFunction.Len()")
|
return nil, nil, nil, false, err
|
||||||
// }
|
}
|
||||||
copy(keyPath[:], k)
|
path := getPath(t.maxLevels, keyPath)
|
||||||
|
|
||||||
root, err := t.RootWithTx(rTx)
|
root, err := t.RootWithTx(rTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, false, err
|
return nil, nil, nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
path := getPath(t.maxLevels, keyPath)
|
|
||||||
// go down to the leaf
|
// go down to the leaf
|
||||||
var siblings [][]byte
|
var siblings [][]byte
|
||||||
_, value, siblings, err := t.down(rTx, k, root, siblings, path, 0, true)
|
_, value, siblings, err := t.down(rTx, k, root, siblings, path, 0, true)
|
||||||
@@ -793,18 +806,17 @@ func (t *Tree) Get(k []byte) ([]byte, []byte, error) {
|
|||||||
// ErrKeyNotFound, and in the leafK & leafV parameters will be placed the data
|
// ErrKeyNotFound, and in the leafK & leafV parameters will be placed the data
|
||||||
// found in the tree in the leaf that was on the path going to the input key.
|
// found in the tree in the leaf that was on the path going to the input key.
|
||||||
func (t *Tree) GetWithTx(rTx db.ReadTx, k []byte) ([]byte, []byte, error) {
|
func (t *Tree) GetWithTx(rTx db.ReadTx, k []byte) ([]byte, []byte, error) {
|
||||||
keyPath := make([]byte, t.hashFunction.Len())
|
keyPath, err := keyPathFromKey(t.maxLevels, k)
|
||||||
// if len(k) > t.hashFunction.Len() { // WIP
|
if err != nil {
|
||||||
// return nil, nil, fmt.Errorf("len(k) > hashFunction.Len()")
|
return nil, nil, err
|
||||||
// }
|
}
|
||||||
copy(keyPath[:], k)
|
path := getPath(t.maxLevels, keyPath)
|
||||||
|
|
||||||
root, err := t.RootWithTx(rTx)
|
root, err := t.RootWithTx(rTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
path := getPath(t.maxLevels, keyPath)
|
|
||||||
// go down to the leaf
|
// go down to the leaf
|
||||||
var siblings [][]byte
|
var siblings [][]byte
|
||||||
_, value, _, err := t.down(rTx, k, root, siblings, path, 0, true)
|
_, value, _, err := t.down(rTx, k, root, siblings, path, 0, true)
|
||||||
@@ -827,7 +839,7 @@ func CheckProof(hashFunc HashFunction, k, v, root, packedSiblings []byte) (bool,
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
keyPath := make([]byte, hashFunc.Len())
|
keyPath := make([]byte, int(math.Ceil(float64(len(siblings))/float64(8)))) //nolint:gomnd
|
||||||
copy(keyPath[:], k)
|
copy(keyPath[:], k)
|
||||||
|
|
||||||
key, _, err := newLeafValue(hashFunc, k, v)
|
key, _, err := newLeafValue(hashFunc, k, v)
|
||||||
|
|||||||
195
tree_test.go
195
tree_test.go
@@ -2,7 +2,9 @@ package arbo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ func TestAddTestVectors(t *testing.T) {
|
|||||||
func testAdd(c *qt.C, hashFunc HashFunction, testVectors []string) {
|
func testAdd(c *qt.C, hashFunc HashFunction, testVectors []string) {
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 10, hashFunc)
|
tree, err := NewTree(database, 256, hashFunc)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -68,7 +70,7 @@ func testAdd(c *qt.C, hashFunc HashFunction, testVectors []string) {
|
|||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
c.Check(hex.EncodeToString(root), qt.Equals, testVectors[0])
|
c.Check(hex.EncodeToString(root), qt.Equals, testVectors[0])
|
||||||
|
|
||||||
bLen := hashFunc.Len()
|
bLen := 32
|
||||||
err = tree.Add(
|
err = tree.Add(
|
||||||
BigIntToBytes(bLen, big.NewInt(1)),
|
BigIntToBytes(bLen, big.NewInt(1)),
|
||||||
BigIntToBytes(bLen, big.NewInt(2)))
|
BigIntToBytes(bLen, big.NewInt(2)))
|
||||||
@@ -92,11 +94,11 @@ func TestAddBatch(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(0))
|
v := BigIntToBytes(bLen, big.NewInt(0))
|
||||||
@@ -110,7 +112,7 @@ func TestAddBatch(t *testing.T) {
|
|||||||
|
|
||||||
database, err = badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err = badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -133,11 +135,11 @@ func TestAddDifferentOrder(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err := NewTree(database1, 100, HashFunctionPoseidon)
|
tree1, err := NewTree(database1, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree1.db.Close() //nolint:errcheck
|
defer tree1.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree1.HashFunction().Len()
|
bLen := 32
|
||||||
for i := 0; i < 16; i++ {
|
for i := 0; i < 16; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(0))
|
v := BigIntToBytes(bLen, big.NewInt(0))
|
||||||
@@ -148,7 +150,7 @@ func TestAddDifferentOrder(t *testing.T) {
|
|||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
@@ -173,11 +175,11 @@ func TestAddRepeatedIndex(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(3)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(3)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(int64(12)))
|
v := BigIntToBytes(bLen, big.NewInt(int64(12)))
|
||||||
|
|
||||||
@@ -191,11 +193,11 @@ func TestUpdate(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(20)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(20)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(int64(12)))
|
v := BigIntToBytes(bLen, big.NewInt(int64(12)))
|
||||||
if err := tree.Add(k, v); err != nil {
|
if err := tree.Add(k, v); err != nil {
|
||||||
@@ -244,11 +246,11 @@ func TestAux(t *testing.T) { // TODO split in proper tests
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(1)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(1)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(int64(0)))
|
v := BigIntToBytes(bLen, big.NewInt(int64(0)))
|
||||||
err = tree.Add(k, v)
|
err = tree.Add(k, v)
|
||||||
@@ -283,11 +285,11 @@ func TestGet(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
|
v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
|
||||||
@@ -307,11 +309,11 @@ func TestGenProofAndVerify(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len() - 1
|
bLen := 32
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
|
v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
|
||||||
@@ -339,11 +341,11 @@ func TestDumpAndImportDump(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database1, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree1, err := NewTree(database1, 100, HashFunctionPoseidon)
|
tree1, err := NewTree(database1, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree1.db.Close() //nolint:errcheck
|
defer tree1.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree1.HashFunction().Len()
|
bLen := 32
|
||||||
for i := 0; i < 16; i++ {
|
for i := 0; i < 16; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
|
v := BigIntToBytes(bLen, big.NewInt(int64(i*2)))
|
||||||
@@ -357,7 +359,7 @@ func TestDumpAndImportDump(t *testing.T) {
|
|||||||
|
|
||||||
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database2, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree2, err := NewTree(database2, 100, HashFunctionPoseidon)
|
tree2, err := NewTree(database2, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree2.db.Close() //nolint:errcheck
|
defer tree2.db.Close() //nolint:errcheck
|
||||||
err = tree2.ImportDump(e)
|
err = tree2.ImportDump(e)
|
||||||
@@ -376,11 +378,11 @@ func TestRWMutex(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
var keys, values [][]byte
|
var keys, values [][]byte
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
@@ -469,7 +471,7 @@ func TestAddBatchFullyUsed(t *testing.T) {
|
|||||||
|
|
||||||
var keys, values [][]byte
|
var keys, values [][]byte
|
||||||
for i := 0; i < 16; i++ {
|
for i := 0; i < 16; i++ {
|
||||||
k := BigIntToBytes(32, big.NewInt(int64(i)))
|
k := BigIntToBytes(1, big.NewInt(int64(i)))
|
||||||
v := k
|
v := k
|
||||||
|
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
@@ -492,10 +494,10 @@ func TestAddBatchFullyUsed(t *testing.T) {
|
|||||||
|
|
||||||
// get all key-values and check that are equal between both trees
|
// get all key-values and check that are equal between both trees
|
||||||
for i := 0; i < 16; i++ {
|
for i := 0; i < 16; i++ {
|
||||||
auxK1, auxV1, err := tree1.Get(BigIntToBytes(32, big.NewInt(int64(i))))
|
auxK1, auxV1, err := tree1.Get(BigIntToBytes(1, big.NewInt(int64(i))))
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
auxK2, auxV2, err := tree2.Get(BigIntToBytes(32, big.NewInt(int64(i))))
|
auxK2, auxV2, err := tree2.Get(BigIntToBytes(1, big.NewInt(int64(i))))
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
c.Assert(auxK1, qt.DeepEquals, auxK2)
|
c.Assert(auxK1, qt.DeepEquals, auxK2)
|
||||||
@@ -504,7 +506,7 @@ func TestAddBatchFullyUsed(t *testing.T) {
|
|||||||
|
|
||||||
// try adding one more key to both trees (through Add & AddBatch) and
|
// try adding one more key to both trees (through Add & AddBatch) and
|
||||||
// expect not being added due the tree is already full
|
// expect not being added due the tree is already full
|
||||||
k := BigIntToBytes(32, big.NewInt(int64(16)))
|
k := BigIntToBytes(1, big.NewInt(int64(16)))
|
||||||
v := k
|
v := k
|
||||||
err = tree1.Add(k, v)
|
err = tree1.Add(k, v)
|
||||||
c.Assert(err, qt.Equals, ErrMaxVirtualLevel)
|
c.Assert(err, qt.Equals, ErrMaxVirtualLevel)
|
||||||
@@ -518,13 +520,13 @@ func TestSetRoot(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
expectedRoot := "13742386369878513332697380582061714160370929283209286127733983161245560237407"
|
expectedRoot := "13742386369878513332697380582061714160370929283209286127733983161245560237407"
|
||||||
|
|
||||||
// fill the tree
|
// fill the tree
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
var keys, values [][]byte
|
var keys, values [][]byte
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
@@ -574,11 +576,11 @@ func TestSnapshot(t *testing.T) {
|
|||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
// fill the tree
|
// fill the tree
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
var keys, values [][]byte
|
var keys, values [][]byte
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(i)))
|
||||||
@@ -624,11 +626,11 @@ func TestGetFromSnapshotExpectArboErrKeyNotFound(t *testing.T) {
|
|||||||
|
|
||||||
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
tree, err := NewTree(database, 100, HashFunctionPoseidon)
|
tree, err := NewTree(database, 256, HashFunctionPoseidon)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
defer tree.db.Close() //nolint:errcheck
|
defer tree.db.Close() //nolint:errcheck
|
||||||
|
|
||||||
bLen := tree.HashFunction().Len()
|
bLen := 32
|
||||||
k := BigIntToBytes(bLen, big.NewInt(int64(3)))
|
k := BigIntToBytes(bLen, big.NewInt(int64(3)))
|
||||||
|
|
||||||
root, err := tree.Root()
|
root, err := tree.Root()
|
||||||
@@ -640,6 +642,133 @@ func TestGetFromSnapshotExpectArboErrKeyNotFound(t *testing.T) {
|
|||||||
c.Assert(err, qt.Equals, ErrKeyNotFound) // and not equal to db.ErrKeyNotFound
|
c.Assert(err, qt.Equals, ErrKeyNotFound) // and not equal to db.ErrKeyNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeyLen(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
// maxLevels is 100, keyPath length = ceil(maxLevels/8) = 13
|
||||||
|
maxLevels := 100
|
||||||
|
tree, err := NewTree(database, maxLevels, HashFunctionBlake2b)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
// expect no errors when adding a key of only 4 bytes (when the
|
||||||
|
// required length of keyPath for 100 levels would be 13 bytes)
|
||||||
|
bLen := 4
|
||||||
|
k := BigIntToBytes(bLen, big.NewInt(1))
|
||||||
|
v := BigIntToBytes(bLen, big.NewInt(1))
|
||||||
|
|
||||||
|
err = tree.Add(k, v)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
err = tree.Update(k, v)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
_, _, _, _, err = tree.GenProof(k)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
_, _, err = tree.Get(k)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
k = BigIntToBytes(bLen, big.NewInt(2))
|
||||||
|
v = BigIntToBytes(bLen, big.NewInt(2))
|
||||||
|
invalids, err := tree.AddBatch([][]byte{k}, [][]byte{v})
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
c.Assert(len(invalids), qt.Equals, 0)
|
||||||
|
|
||||||
|
// expect errors when adding a key bigger than maximum capacity of the
|
||||||
|
// tree: ceil(maxLevels/8)
|
||||||
|
maxLevels = 32
|
||||||
|
database, err = badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
tree, err = NewTree(database, maxLevels, HashFunctionBlake2b)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
maxKeyLen := int(math.Ceil(float64(maxLevels) / float64(8))) //nolint:gomnd
|
||||||
|
k = BigIntToBytes(maxKeyLen+1, big.NewInt(1))
|
||||||
|
v = BigIntToBytes(maxKeyLen+1, big.NewInt(1))
|
||||||
|
|
||||||
|
expectedErrMsg := "len(k) can not be bigger than ceil(maxLevels/8)," +
|
||||||
|
" where len(k): 5, maxLevels: 32, max key len=ceil(maxLevels/8): 4." +
|
||||||
|
" Might need a bigger tree depth (maxLevels>=40) in order to input" +
|
||||||
|
" keys of length 5"
|
||||||
|
|
||||||
|
err = tree.Add(k, v)
|
||||||
|
c.Assert(err.Error(), qt.Equals, expectedErrMsg)
|
||||||
|
|
||||||
|
err = tree.Update(k, v)
|
||||||
|
c.Assert(err.Error(), qt.Equals, expectedErrMsg)
|
||||||
|
|
||||||
|
_, _, _, _, err = tree.GenProof(k)
|
||||||
|
c.Assert(err.Error(), qt.Equals, expectedErrMsg)
|
||||||
|
|
||||||
|
_, _, err = tree.Get(k)
|
||||||
|
c.Assert(err.Error(), qt.Equals, expectedErrMsg)
|
||||||
|
|
||||||
|
// check AddBatch with few key-values
|
||||||
|
invalids, err = tree.AddBatch([][]byte{k}, [][]byte{v})
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
c.Assert(len(invalids), qt.Equals, 1)
|
||||||
|
|
||||||
|
// check AddBatch with many key-values
|
||||||
|
nCPU := flp2(runtime.NumCPU())
|
||||||
|
nKVs := nCPU + 1
|
||||||
|
var ks, vs [][]byte
|
||||||
|
for i := 0; i < nKVs; i++ {
|
||||||
|
ks = append(ks, BigIntToBytes(maxKeyLen+1, big.NewInt(1)))
|
||||||
|
vs = append(vs, BigIntToBytes(maxKeyLen+1, big.NewInt(1)))
|
||||||
|
}
|
||||||
|
invalids, err = tree.AddBatch(ks, vs)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
c.Assert(len(invalids), qt.Equals, nKVs)
|
||||||
|
|
||||||
|
// check that with maxKeyLen it can be added
|
||||||
|
k = BigIntToBytes(maxKeyLen, big.NewInt(1))
|
||||||
|
err = tree.Add(k, v)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
// check CheckProof check with key longer
|
||||||
|
kAux, vAux, packedSiblings, existence, err := tree.GenProof(k)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
c.Assert(existence, qt.IsTrue)
|
||||||
|
|
||||||
|
root, err := tree.Root()
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
verif, err := CheckProof(tree.HashFunction(), kAux, vAux, root, packedSiblings)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
c.Assert(verif, qt.IsTrue)
|
||||||
|
|
||||||
|
// use a similar key but with one zero, expect that CheckProof fails on
|
||||||
|
// the verification
|
||||||
|
kAux = append(kAux, 0)
|
||||||
|
verif, err = CheckProof(tree.HashFunction(), kAux, vAux, root, packedSiblings)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
c.Assert(verif, qt.IsFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKeyLenBiggerThan32(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
maxLevels := 264
|
||||||
|
database, err := badgerdb.New(badgerdb.Options{Path: c.TempDir()})
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
tree, err := NewTree(database, maxLevels, HashFunctionBlake2b)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
bLen := 33
|
||||||
|
err = tree.Add(
|
||||||
|
randomBytes(bLen),
|
||||||
|
randomBytes(bLen))
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
// 2nd key that we add, will find a node with len(key)==32 (due the
|
||||||
|
// hash output size, expect that next Add does not give any error, as
|
||||||
|
// internally it will use a keyPath of size corresponent to the
|
||||||
|
// maxLevels size of the tree
|
||||||
|
err = tree.Add(
|
||||||
|
randomBytes(bLen),
|
||||||
|
randomBytes(bLen))
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkAdd(b *testing.B) {
|
func BenchmarkAdd(b *testing.B) {
|
||||||
bLen := 32 // for both Poseidon & Sha256
|
bLen := 32 // for both Poseidon & Sha256
|
||||||
// prepare inputs
|
// prepare inputs
|
||||||
|
|||||||
4
utils.go
4
utils.go
@@ -1,6 +1,8 @@
|
|||||||
package arbo
|
package arbo
|
||||||
|
|
||||||
import "math/big"
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
// SwapEndianness swaps the order of the bytes in the byte slice.
|
// SwapEndianness swaps the order of the bytes in the byte slice.
|
||||||
func SwapEndianness(b []byte) []byte {
|
func SwapEndianness(b []byte) []byte {
|
||||||
|
|||||||
50
vt.go
50
vt.go
@@ -37,22 +37,32 @@ type kv struct {
|
|||||||
v []byte
|
v []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *params) keysValuesToKvs(ks, vs [][]byte) ([]kv, error) {
|
func (p *params) keysValuesToKvs(ks, vs [][]byte) ([]kv, []int, error) {
|
||||||
if len(ks) != len(vs) {
|
if len(ks) != len(vs) {
|
||||||
return nil, fmt.Errorf("len(keys)!=len(values) (%d!=%d)",
|
return nil, nil, fmt.Errorf("len(keys)!=len(values) (%d!=%d)",
|
||||||
len(ks), len(vs))
|
len(ks), len(vs))
|
||||||
}
|
}
|
||||||
kvs := make([]kv, len(ks))
|
var invalids []int
|
||||||
|
var kvs []kv
|
||||||
for i := 0; i < len(ks); i++ {
|
for i := 0; i < len(ks); i++ {
|
||||||
keyPath := make([]byte, p.hashFunction.Len())
|
keyPath, err := keyPathFromKey(p.maxLevels, ks[i])
|
||||||
copy(keyPath[:], ks[i])
|
if err != nil {
|
||||||
kvs[i].pos = i
|
// TODO in a future iteration, invalids will contain
|
||||||
kvs[i].keyPath = keyPath
|
// the reason of the error of why each index is
|
||||||
kvs[i].k = ks[i]
|
// invalid.
|
||||||
kvs[i].v = vs[i]
|
invalids = append(invalids, i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var kvsI kv
|
||||||
|
kvsI.pos = i
|
||||||
|
kvsI.keyPath = keyPath
|
||||||
|
kvsI.k = ks[i]
|
||||||
|
kvsI.v = vs[i]
|
||||||
|
kvs = append(kvs, kvsI)
|
||||||
}
|
}
|
||||||
|
|
||||||
return kvs, nil
|
return kvs, invalids, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// vt stands for virtual tree. It's a tree that does not have any computed hash
|
// vt stands for virtual tree. It's a tree that does not have any computed hash
|
||||||
@@ -94,9 +104,9 @@ func (t *vt) addBatch(ks, vs [][]byte) ([]int, error) {
|
|||||||
|
|
||||||
l := int(math.Log2(float64(nCPU)))
|
l := int(math.Log2(float64(nCPU)))
|
||||||
|
|
||||||
kvs, err := t.params.keysValuesToKvs(ks, vs)
|
kvs, invalids, err := t.params.keysValuesToKvs(ks, vs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return invalids, err
|
||||||
}
|
}
|
||||||
|
|
||||||
buckets := splitInBuckets(kvs, nCPU)
|
buckets := splitInBuckets(kvs, nCPU)
|
||||||
@@ -186,7 +196,6 @@ func (t *vt) addBatch(ks, vs [][]byte) ([]int, error) {
|
|||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
var invalids []int
|
|
||||||
for i := 0; i < len(invalidsInBucket); i++ {
|
for i := 0; i < len(invalidsInBucket); i++ {
|
||||||
invalids = append(invalids, invalidsInBucket[i]...)
|
invalids = append(invalids, invalidsInBucket[i]...)
|
||||||
}
|
}
|
||||||
@@ -284,7 +293,10 @@ func upFromNodes(ns []*node) (*node, error) {
|
|||||||
|
|
||||||
// add adds a key&value as a leaf in the VirtualTree
|
// add adds a key&value as a leaf in the VirtualTree
|
||||||
func (t *vt) add(fromLvl int, k, v []byte) error {
|
func (t *vt) add(fromLvl int, k, v []byte) error {
|
||||||
leaf := newLeafNode(t.params, k, v)
|
leaf, err := newLeafNode(t.params, k, v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if t.root == nil {
|
if t.root == nil {
|
||||||
t.root = leaf
|
t.root = leaf
|
||||||
return nil
|
return nil
|
||||||
@@ -366,16 +378,18 @@ func (t *vt) computeHashes() ([][2][]byte, error) {
|
|||||||
return pairs, nil
|
return pairs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLeafNode(p *params, k, v []byte) *node {
|
func newLeafNode(p *params, k, v []byte) (*node, error) {
|
||||||
keyPath := make([]byte, p.hashFunction.Len())
|
keyPath, err := keyPathFromKey(p.maxLevels, k)
|
||||||
copy(keyPath[:], k)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
path := getPath(p.maxLevels, keyPath)
|
path := getPath(p.maxLevels, keyPath)
|
||||||
n := &node{
|
n := &node{
|
||||||
k: k,
|
k: k,
|
||||||
v: v,
|
v: v,
|
||||||
path: path,
|
path: path,
|
||||||
}
|
}
|
||||||
return n
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type virtualNodeType int
|
type virtualNodeType int
|
||||||
|
|||||||
134
vt_test.go
134
vt_test.go
@@ -2,6 +2,7 @@ package arbo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -9,69 +10,8 @@ import (
|
|||||||
"go.vocdoni.io/dvote/db/badgerdb"
|
"go.vocdoni.io/dvote/db/badgerdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVirtualTreeTestVectors(t *testing.T) {
|
// testVirtualTree adds the given key-values and tests the vt root against the
|
||||||
c := qt.New(t)
|
// Tree
|
||||||
|
|
||||||
bLen := 32
|
|
||||||
keys := [][]byte{
|
|
||||||
BigIntToBytes(bLen, big.NewInt(1)),
|
|
||||||
BigIntToBytes(bLen, big.NewInt(33)),
|
|
||||||
BigIntToBytes(bLen, big.NewInt(1234)),
|
|
||||||
BigIntToBytes(bLen, big.NewInt(123456789)),
|
|
||||||
}
|
|
||||||
values := [][]byte{
|
|
||||||
BigIntToBytes(bLen, big.NewInt(2)),
|
|
||||||
BigIntToBytes(bLen, big.NewInt(44)),
|
|
||||||
BigIntToBytes(bLen, big.NewInt(9876)),
|
|
||||||
BigIntToBytes(bLen, big.NewInt(987654321)),
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the root for different batches of leafs
|
|
||||||
testVirtualTree(c, 10, keys[:1], values[:1])
|
|
||||||
testVirtualTree(c, 10, keys[:2], values[:2])
|
|
||||||
testVirtualTree(c, 10, keys[:3], values[:3])
|
|
||||||
testVirtualTree(c, 10, 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})
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the root for different batches of leafs
|
|
||||||
testVirtualTree(c, 10, keys[:1], values[:1])
|
|
||||||
testVirtualTree(c, 10, keys, values)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
testVirtualTree(c, 100, keys, values)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testVirtualTree(c *qt.C, maxLevels int, keys, values [][]byte) {
|
func testVirtualTree(c *qt.C, maxLevels int, keys, values [][]byte) {
|
||||||
c.Assert(len(keys), qt.Equals, len(values))
|
c.Assert(len(keys), qt.Equals, len(values))
|
||||||
|
|
||||||
@@ -103,11 +43,75 @@ func testVirtualTree(c *qt.C, maxLevels int, keys, values [][]byte) {
|
|||||||
c.Assert(vTree.root.h, qt.DeepEquals, root)
|
c.Assert(vTree.root.h, qt.DeepEquals, root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
func TestVirtualTreeAddBatch(t *testing.T) {
|
func TestVirtualTreeAddBatch(t *testing.T) {
|
||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
|
|
||||||
nLeafs := 2000
|
nLeafs := 2000
|
||||||
maxLevels := 100
|
maxLevels := 256
|
||||||
|
|
||||||
keys := make([][]byte, nLeafs)
|
keys := make([][]byte, nLeafs)
|
||||||
values := make([][]byte, nLeafs)
|
values := make([][]byte, nLeafs)
|
||||||
@@ -151,7 +155,7 @@ func TestVirtualTreeAddBatchFullyUsed(t *testing.T) {
|
|||||||
|
|
||||||
var keys, values [][]byte
|
var keys, values [][]byte
|
||||||
for i := 0; i < 128; i++ {
|
for i := 0; i < 128; i++ {
|
||||||
k := BigIntToBytes(32, big.NewInt(int64(i)))
|
k := BigIntToBytes(1, big.NewInt(int64(i)))
|
||||||
v := k
|
v := k
|
||||||
|
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
|
|||||||
Reference in New Issue
Block a user