You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
arnaucube a8c7ea9808 Add circom test w/ circuit for CircomVerifierProof 2 years ago
.github/workflows Add circom test w/ circuit for CircomVerifierProof 2 years ago
testvectors/circom Add circom test w/ circuit for CircomVerifierProof 2 years ago
.gitignore Update upFromNodes function for unbalanced tree 2 years ago
.golangci.yml Simplify cyclomatic complexity of AddBatch 3 years ago
LICENSE Init: README.md & LICENSE 3 years ago
README.md Migrate repository to github.com/vocdoni/arbo 2 years ago
addbatch_test.go Update upFromNodes function for unbalanced tree 2 years ago
circomproofs.go Add Tree Circom Verifier Proofs 2 years ago
circomproofs_test.go Add Tree Circom Verifier Proofs 2 years ago
dbg.go Add dbgStats metrics 2 years ago
go.mod Migrate repository to github.com/vocdoni/arbo 2 years ago
go.sum Migrate kv db to go.vocdoni.io/dvote/db interface 2 years ago
hash.go Update public methods signatures 2 years ago
hash_test.go Update public methods signatures 2 years ago
helpers_test.go Update upFromNodes function for unbalanced tree 2 years ago
tree.go Add Tree Circom Verifier Proofs 2 years ago
tree_test.go Add Tree Circom Verifier Proofs 2 years ago
utils.go Update public methods signatures 2 years ago
vt.go Update upFromNodes function for unbalanced tree 2 years ago
vt_test.go Migrate kv db to go.vocdoni.io/dvote/db interface 2 years ago

README.md

arbo GoDoc Go Report Card Test

arbo: tree in Esperanto.

MerkleTree implementation in Go. Compatible with the circomlib implementation of the MerkleTree, following the specification from https://docs.iden3.io/publications/pdfs/Merkle-Tree.pdf and https://eprint.iacr.org/2018/955.

Allows to define which hash function to use. So for example, when working with zkSnarks the Poseidon hash function can be used, but when not, it can be used the Blake2b hash function, which has much faster computation time.

Usage

// create new database
database, err := db.NewBadgerDB(c.TempDir())

// create new Tree with maxLevels=100 and Blake2b hash function
tree, err := arbo.NewTree(database, 100, arbo.HashFunctionBlake2b)

key := []byte("hello")
value := []byte("world")
// Add a key & value into the merkle tree
err = tree.Add(key, value)

// There are cases where multiple key-values (leafs) are going to be added to a
// Tree, for these cases is more efficient to use:
invalids, err := tree.AddBatch(keys, values)

// generate the merkle proof of a leaf by it's key
value, siblings, err := tree.GenProof(key)

// verify the proof
verified, err := arbo.CheckProof(tree.hashFunction, key, value, tree.Root(), siblings)
if !verified {
	fmt.Println("proof could not be verified")
}

// get the value of a leaf assigned to a key
gettedKey, gettedValue, err := tree.Get(key)

// update the value of a leaf assigned to a key
err = tree.Update(key, value)

// dump the tree (the leafs)
dump, err := tree.Dump(nil) // instead of nil, a root to start from can be used

// import the dump into a tree
err = tree.ImportDump(dump)

// print graphviz diagram of the tree
err = tree.PrintGraphviz(nil) // instead of nil, a root to start from can be used

Usage with SNARKs compatibility

Arbo is designed to be compatible with circom merkle tree's snark-friendly merkletree. The only change needed is the hash function used for the Tree, for example using the Poseidon hash function:

tree, err := arbo.NewTree(database, 100, arbo.HashFunctionPoseidon)

Be aware of the characteristics of this kind of hashes, such as using values inside the finite field used by the hash, and also the computation time.

The interface of arbo uses byte arrays, and for the case of these kind of hashes (that usually work directly with finite field elements), arbo expects those values to be represented by little-endian byte arrays. There is a helper method to convert a *big.Int to []byte using little-endian:

bLen := tree.HashFunction().Len()
kBigInt := big.NewInt(100)

// convert *big.Int to byte array
kBytes := arbo.BigIntToBytes(bLen, kBigInt)

// convert byte array to *big.Int
kBigInt2 := arbo.BytesToBigInt(kBytes)