Skip to content

Commit

Permalink
Merkle proof
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksej-paschenko committed Sep 13, 2024
1 parent 38b0f76 commit 98dc84a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 25 deletions.
16 changes: 7 additions & 9 deletions boc/merkle_proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,27 @@ package boc

type MerkleProver struct {
root *immutableCell

pruned map[*immutableCell]struct{}
}

func NewMerkleProver(root *Cell) (*MerkleProver, error) {
immRoot, err := newImmutableCell(root, make(map[*Cell]*immutableCell))
if err != nil {
return nil, err
}
return &MerkleProver{root: immRoot, pruned: make(map[*immutableCell]struct{})}, nil
return &MerkleProver{root: immRoot}, nil
}

type Cursor struct {
cell *immutableCell
prover *MerkleProver
pruned map[*immutableCell]struct{}
}

func (p *MerkleProver) Cursor() *Cursor {
return &Cursor{cell: p.root, prover: p}
return &Cursor{cell: p.root, pruned: make(map[*immutableCell]struct{})}
}

func (p *MerkleProver) CreateProof() ([]byte, error) {
immRoot, err := p.root.pruneCells(p.pruned)
func (p *MerkleProver) CreateProof(cursor *Cursor) ([]byte, error) {
immRoot, err := p.root.pruneCells(cursor.pruned)
if err != nil {
return nil, err
}
Expand All @@ -47,9 +45,9 @@ func (p *MerkleProver) CreateProof() ([]byte, error) {
}

func (c *Cursor) Prune() {
c.prover.pruned[c.cell] = struct{}{}
c.pruned[c.cell] = struct{}{}
}

func (c *Cursor) Ref(ref int) *Cursor {
return &Cursor{cell: c.cell.refs[ref], prover: c.prover}
return &Cursor{cell: c.cell.refs[ref], pruned: c.pruned}
}
49 changes: 33 additions & 16 deletions tlb/hashmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,52 +171,69 @@ func countLeafs(keySize, leftKeySize int, c *boc.Cell) (int, error) {
return 1, nil
}

func ProveKeyInHashmap(cell *boc.Cell, key boc.BitString) ([]byte, error) {
func ProveKeyInHashmap[T any](prover *boc.MerkleProver, cell *boc.Cell, key boc.BitString) (T, []byte, error) {
keySize := key.BitsAvailableForRead()
prover, err := boc.NewMerkleProver(cell)
if err != nil {
return nil, err
}
cursor := prover.Cursor()
bitString := boc.NewBitString(keySize)
prefix := &bitString
cursor := prover.Cursor()
var t T
remaining := keySize
for {
var err error
var size int
size, prefix, err = loadLabel(keySize, cell, prefix)
size, prefix, err = loadLabel(remaining, cell, prefix)
if err != nil {
return nil, err
return t, nil, err
}
if keySize <= size {
_ = prefix
if remaining <= size {
break
}
if _, err = key.ReadBits(size); err != nil {
return nil, err
return t, nil, err
}

isRight, err := key.ReadBit()
if err != nil {
return nil, err
return t, nil, err
}
if err := prefix.WriteBit(isRight); err != nil {
return t, nil, err
}
keySize = keySize - size - 1
remaining = remaining - size - 1
next, err := cell.NextRef()
if err != nil {
return nil, err
return t, nil, err
}
if isRight {
cursor.Ref(0).Prune()
next, err = cell.NextRef()
if err != nil {
return nil, err
return t, nil, err
}
cursor = cursor.Ref(1)
} else {
cursor.Ref(1).Prune()
cursor = cursor.Ref(0)
}
cell = next
cell.ResetCounters()
}
if err := Unmarshal(cell, &t); err != nil {
return t, nil, err
}
constructedKey, err := prefix.ReadBits(keySize)
if err != nil {
return t, nil, err
}
return prover.CreateProof()
if constructedKey.ToFiftHex() != key.ToFiftHex() {
return t, nil, errors.New("key is not found")
}
proof, err := prover.CreateProof(cursor)
if err != nil {
return t, nil, err
}
return t, proof, nil

}

func (h *Hashmap[keyT, T]) mapInner(keySize, leftKeySize int, c *boc.Cell, keyPrefix *boc.BitString, decoder *Decoder) error {
Expand Down

0 comments on commit 98dc84a

Please sign in to comment.