Browse Source

Merge pull request #5 from iden3/feature/update

Add mt.Update(key, value) method
circomproofs
arnau 3 years ago
committed by GitHub
parent
commit
cdad1f2608
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 123 additions and 1 deletions
  1. +68
    -1
      merkletree.go
  2. +55
    -0
      merkletree_test.go

+ 68
- 1
merkletree.go

@ -342,6 +342,73 @@ func (mt *MerkleTree) Get(k *big.Int) (*big.Int, error) {
return nil, ErrKeyNotFound
}
// Update updates the value of a specified key in the MerkleTree, and updates
// the path from the leaf to the Root with the new values.
func (mt *MerkleTree) Update(k, v *big.Int) error {
// verify that the MerkleTree is writable
if !mt.writable {
return ErrNotWritable
}
// verfy that k & are valid and fit inside the Finite Field.
if !cryptoUtils.CheckBigIntInField(k) {
return errors.New("Key not inside the Finite Field")
}
if !cryptoUtils.CheckBigIntInField(v) {
return errors.New("Key not inside the Finite Field")
}
tx, err := mt.db.NewTx()
if err != nil {
return err
}
mt.Lock()
defer mt.Unlock()
kHash := NewHashFromBigInt(k)
vHash := NewHashFromBigInt(v)
path := getPath(mt.maxLevels, kHash[:])
nextKey := mt.rootKey
var siblings []*Hash
for i := 0; i < mt.maxLevels; i++ {
n, err := mt.GetNode(nextKey)
if err != nil {
return err
}
switch n.Type {
case NodeTypeEmpty:
return ErrKeyNotFound
case NodeTypeLeaf:
if bytes.Equal(kHash[:], n.Entry[0][:]) {
// update leaf and upload to the root
newNodeLeaf := NewNodeLeaf(kHash, vHash)
_, err := mt.addNode(tx, newNodeLeaf)
newRootKey, err := mt.recalculatePathUntilRoot(tx, path, newNodeLeaf, siblings)
if err != nil {
return err
}
mt.rootKey = newRootKey
mt.dbInsert(tx, rootNodeValue, DBEntryTypeRoot, mt.rootKey[:])
return tx.Commit()
} else {
return ErrKeyNotFound
}
case NodeTypeMiddle:
if path[i] {
nextKey = n.ChildR
siblings = append(siblings, n.ChildL)
} else {
nextKey = n.ChildL
siblings = append(siblings, n.ChildR)
}
default:
return ErrInvalidNodeFound
}
}
return ErrKeyNotFound
}
// Delete removes the specified Key from the MerkleTree and updates the path
// from the deleted key to the Root with the new values. This method removes
// the key from the MerkleTree, but does not remove the old nodes from the
@ -403,7 +470,7 @@ func (mt *MerkleTree) Delete(k *big.Int) error {
}
}
return nil
return ErrKeyNotFound
}
// rmAndUpload removes the key, and goes up until the root updating all the nodes with the new values.

+ 55
- 0
merkletree_test.go

@ -136,6 +136,60 @@ func TestGet(t *testing.T) {
assert.Nil(t, v)
}
func TestUpdate(t *testing.T) {
mt := newTestingMerkle(t, 140)
defer mt.db.Close()
for i := 0; i < 16; i++ {
k := big.NewInt(int64(i))
v := big.NewInt(int64(i * 2))
if err := mt.Add(k, v); err != nil {
t.Fatal(err)
}
}
v, err := mt.Get(big.NewInt(10))
assert.Nil(t, err)
assert.Equal(t, big.NewInt(20), v)
err = mt.Update(big.NewInt(10), big.NewInt(1024))
v, err = mt.Get(big.NewInt(10))
assert.Nil(t, err)
assert.Equal(t, big.NewInt(1024), v)
err = mt.Update(big.NewInt(1000), big.NewInt(1024))
assert.Equal(t, ErrKeyNotFound, err)
}
func TestUpdate2(t *testing.T) {
mt1 := newTestingMerkle(t, 140)
defer mt1.db.Close()
mt2 := newTestingMerkle(t, 140)
defer mt2.db.Close()
err := mt1.Add(big.NewInt(1), big.NewInt(119))
assert.Nil(t, err)
err = mt1.Add(big.NewInt(2), big.NewInt(229))
assert.Nil(t, err)
err = mt1.Add(big.NewInt(9876), big.NewInt(6789))
assert.Nil(t, err)
err = mt2.Add(big.NewInt(1), big.NewInt(11))
assert.Nil(t, err)
err = mt2.Add(big.NewInt(2), big.NewInt(22))
assert.Nil(t, err)
err = mt2.Add(big.NewInt(9876), big.NewInt(10))
assert.Nil(t, err)
err = mt1.Update(big.NewInt(1), big.NewInt(11))
assert.Nil(t, err)
err = mt1.Update(big.NewInt(2), big.NewInt(22))
assert.Nil(t, err)
err = mt2.Update(big.NewInt(9876), big.NewInt(6789))
assert.Nil(t, err)
assert.Equal(t, mt1.Root(), mt2.Root())
}
func TestGenerateAndVerifyProof128(t *testing.T) {
mt, err := NewMerkleTree(memory.NewMemoryStorage(), 140)
require.Nil(t, err)
@ -346,6 +400,7 @@ func TestDelete(t *testing.T) {
err = mt.Delete(big.NewInt(1))
assert.Nil(t, err)
assert.Equal(t, "0", mt.Root().String())
}
func TestDelete2(t *testing.T) {

Loading…
Cancel
Save