package merkletree import ( "errors" "math/big" "sync" "github.com/iden3/go-iden3-core/common" "github.com/iden3/go-iden3-core/db" ) const ( // proofFlagsLen is the byte length of the flags in the proof header (first 32 // bytes). proofFlagsLen = 2 // ElemBytesLen is the length of the Hash byte array ElemBytesLen = 32 ) var ( // ErrNodeKeyAlreadyExists is used when a node key already exists. ErrNodeKeyAlreadyExists = errors.New("node already exists") // ErrEntryIndexNotFound is used when no entry is found for an index. ErrEntryIndexNotFound = errors.New("node index not found in the DB") // ErrNodeDataBadSize is used when the data of a node has an incorrect // size and can't be parsed. ErrNodeDataBadSize = errors.New("node data has incorrect size in the DB") // ErrReachedMaxLevel is used when a traversal of the MT reaches the // maximum level. ErrReachedMaxLevel = errors.New("reached maximum level of the merkle tree") // ErrInvalidNodeFound is used when an invalid node is found and can't // be parsed. ErrInvalidNodeFound = errors.New("found an invalid node in the DB") // ErrInvalidProofBytes is used when a serialized proof is invalid. ErrInvalidProofBytes = errors.New("the serialized proof is invalid") // ErrInvalidDBValue is used when a value in the key value DB is // invalid (for example, it doen't contain a byte header and a []byte // body of at least len=1. ErrInvalidDBValue = errors.New("the value in the DB is invalid") // ErrEntryIndexAlreadyExists is used when the entry index already // exists in the tree. ErrEntryIndexAlreadyExists = errors.New("the entry index already exists in the tree") // ErrNotWritable is used when the MerkleTree is not writable and a write function is called ErrNotWritable = errors.New("Merkle Tree not writable") rootNodeValue = []byte("currentroot") HashZero = Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} ) type Hash [32]byte func (h Hash) String() string { return new(big.Int).SetBytes(h[:]).String() } func (h *Hash) BigInt() *big.Int { return new(big.Int).SetBytes(common.SwapEndianness(h[:])) } func NewHashFromBigInt(b *big.Int) *Hash { r := &Hash{} copy(r[:], common.SwapEndianness(b.Bytes())) return r } type MerkleTree struct { sync.RWMutex db db.Storage rootKey *Hash writable bool maxLevels int } func NewMerkleTree(storage db.Storage, maxLevels int) (*MerkleTree, error) { mt := MerkleTree{db: storage, maxLevels: maxLevels, writable: true} v, err := mt.db.Get(rootNodeValue) if err != nil { tx, err := mt.db.NewTx() if err != nil { return nil, err } mt.rootKey = &HashZero tx.Put(rootNodeValue, mt.rootKey[:]) err = tx.Commit() if err != nil { return nil, err } return &mt, nil } mt.rootKey = &Hash{} copy(mt.rootKey[:], v) return &mt, nil } func (mt *MerkleTree) Root() *Hash { return mt.rootKey }