-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does this library support Openzeppelin MerkleProof? #39
Comments
I see, Openzeppelin merkle tree (https://github.com/OpenZeppelin/merkle-tree) uses an opinionated double leaf hash algorithm. |
Hi, thanks for using this library and providing feedbacks. Yes. This library supports OpenZeppelin Merkle proof. The support was added after #21. Since in OpenZeppelin's implementation, the hashes are sorted pair-wise during the Merkle tree construction process, you need to set Supporting iteration and streaming is a good proposal and I will consider adding such feature to the library in the future. Thanks. |
This will generate the identical root result as https://github.com/FantasyJony/openzeppelin-merkle-tree-go/blob/main/main.go: package main
import (
"bytes"
"fmt"
"sort"
smt "github.com/FantasyJony/openzeppelin-merkle-tree-go/standard_merkle_tree"
"github.com/ethereum/go-ethereum/common/hexutil"
mt "github.com/txaty/go-merkletree"
)
type dataBlock struct {
value []interface{}
}
var leafEncodings = []string{
smt.SOL_ADDRESS,
smt.SOL_UINT256,
}
func (d *dataBlock) Serialize() ([]byte, error) {
data, err := smt.AbiPack(leafEncodings, d.value...)
if err != nil {
return nil, err
}
return smt.Keccak256(data)
}
func main() {
dataBlocks := []mt.DataBlock{
&dataBlock{
value: []interface{}{
smt.SolAddress("0x1111111111111111111111111111111111111111"),
smt.SolNumber("5000000000000000000"),
},
},
&dataBlock{
value: []interface{}{
smt.SolAddress("0x2222222222222222222222222222222222222222"),
smt.SolNumber("2500000000000000000"),
},
},
&dataBlock{
value: []interface{}{
smt.SolAddress("0x3333333333333333333333333333333333333333"),
smt.SolNumber("1500000000000000000"),
},
},
&dataBlock{
value: []interface{}{
smt.SolAddress("0x4444444444444444444444444444444444444444"),
smt.SolNumber("1000000000000000000"),
},
},
}
sort.Slice(dataBlocks, func(i, j int) bool {
inputBytesI, err := dataBlocks[i].Serialize()
handleError(err)
inputBytesJ, err := dataBlocks[j].Serialize()
handleError(err)
return bytes.Compare(inputBytesI, inputBytesJ) == 1
})
tree, err := mt.New(&mt.Config{
HashFunc: smt.Keccak256,
SortSiblingPairs: true,
}, dataBlocks)
handleError(err)
fmt.Println("MakeTree Root: ", hexutil.Encode(tree.Root))
}
func handleError(err error) {
if err != nil {
panic(err)
}
} |
I set to 3 leaves, the root value is different since the different handle of odd leaf: copied or left to the next level. and I changed to 6 leaves:
why the root is different? |
When calculating the second layer, there will be 3 nodes in total again. Thus the different handles of odd leaf lead to different results. In fact, any leaf numbers that are not Odd leaf handling in this library is the same as Bitcoin's: https://bitcoin.stackexchange.com/questions/79364/are-number-of-transactions-in-merkle-tree-always-even. The last node in an odd node array is duplicated and hashed with itself. |
you are right. thanks! |
I find this library sort the hashed leafs two pairs only:
While this library(github.com/FantasyJony/openzeppelin-merkle-tree-go) sort all the leaves and generate the same root as this js library (https://github.com/OpenZeppelin/merkle-tree)
I tried to use customer hash function as FantasyJony one by using this config:
I think it's the sorting difference makes the different root value, am I right? (But I tried only two leaves and no sorting, still get different root value.)
If I'm wrong, could you please give me an example code to generate the same result. Thank you.
BTW: It seems your library is fast, but API is not that convenient. If there is an AddLeaf or something like to make it possible to use it in 'iteratoring or streaming style' rather than collect all the data to an array in the first place and pass to this library which allocate arrays inside to waste redundant memory.
The text was updated successfully, but these errors were encountered: