Skip to content

Commit

Permalink
add a verify fn
Browse files Browse the repository at this point in the history
  • Loading branch information
n8wb committed Nov 15, 2023
1 parent f4009ef commit e3e8a59
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 182 deletions.
36 changes: 36 additions & 0 deletions base_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,42 @@ func (bt *BaseTree) Path(index int) (ProofPath, error) {
PathRoot: bt.layers[bt.levels][0]}, nil
}

/*
*
VerifyProof
*
*/
func (bt *BaseTree) VerifyProof(elem Element, proof ProofPath) error {
index := IndexOfElement(bt.layers[0], elem, 0, nil)

var (
elIndex = index
)

for level := 0; level < bt.levels; level++ {
if proof.PathIndices[level] != elIndex%2 {
return fmt.Errorf("invalid proof")
}
leafIndex := elIndex ^ 1
if leafIndex < len(bt.layers[level]) {
if !bytes.Equal(proof.PathElements[level], bt.layers[level][leafIndex]) {
return fmt.Errorf("invalid proof")
}
if proof.PathPositions[level] != leafIndex {
return fmt.Errorf("invalid proof")
}
} else {
if !bytes.Equal(proof.PathElements[level], bt.zeros[level]) {
return fmt.Errorf("invalid proof")
}
if proof.PathPositions[level] != 0 {
return fmt.Errorf("invalid proof")
}
}
elIndex >>= 1
}
return nil
}
func (bt *BaseTree) buildZeros() {
bt.zeros = make([]Element, bt.levels+1)
bt.zeros[0] = bt.zeroElement
Expand Down
200 changes: 18 additions & 182 deletions fixed_merkle_tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ func Test_MerkleTree_Path(t *testing.T) {
path, err := tree.Path(3)
require.NoError(t, err)
require.ElementsMatch(t, path.PathIndices, []int{1, 1, 0, 0, 0, 0, 0, 0, 0, 0})
require.ElementsMatch(t, path.PathPositions, []int{2, 0, 1, 0, 0, 0, 0, 0, 0, 0})

expected := []string{
"03",
"6b51d431df5d7f141cbececcf79edf3dd861c3b4069f0b11661a3eefacbba918",
Expand Down Expand Up @@ -179,187 +181,21 @@ func Test_MerkleTree_Path(t *testing.T) {
require.Error(t, err)

})
}

//68f30f28e64ca789f80b0108d36f38deae22764b485ba57cbb1b486bb1711ff7
// import { MerkleTree, PartialMerkleTree, TreeEdge } from '../src'
// import { assert, should } from 'chai'
// import { createHash } from 'crypto'
// import { it } from 'mocha'

// const sha256Hash = (left, right) => createHash('sha256').update(`${left}${right}`).digest('hex')
// const ZERO_ELEMENT = '21663839004416932945382355908790599225266501822907911457504978515578255421292'

// describe('MerkleTree', () => {

// describe('#constructor', () => {

// describe('#proof', () => {
// it('should return proof for leaf', () => {
// const tree = new MerkleTree(10, [1, 2, 3, 4, 5])
// assert.deepEqual(tree.proof(4), tree.path(3))
// })
// })

// describe('#getTreeEdge', () => {
// it('should return correct treeEdge', () => {
// const expectedEdge: TreeEdge = {
// edgePath: {
// pathElements: [
// 5,
// '1390935134112885103361924701261056180224',
// '1952916572242076545231119328171167580160',
// '938972308169430750202858820582946897920',
// ],
// pathIndices: [0, 0, 1, 0],
// pathPositions: [5, 0, 0, 0],
// pathRoot: '3283298202329284319899364273680487022592',
// },
// edgeElement: 4,
// edgeIndex: 4,
// edgeElementsCount: 6,
// }
// const tree = new MerkleTree(4, [0, 1, 2, 3, 4, 5])
// assert.deepEqual(tree.getTreeEdge(4), expectedEdge)
// })
// it('should fail if element not found', () => {
// const tree = new MerkleTree(4, [0, 1, 2, 3, 4, 5])
// const call = () => tree.getTreeEdge(6)
// should().throw(call, 'Element not found')
// })
// })
// describe('#getTreeSlices', () => {
// let fullTree: MerkleTree
// before(async () => {
// const elements = Array.from({ length: 2 ** 10 }, (_, i) => i)
// fullTree = new MerkleTree(10, elements)
// return Promise.resolve()
// })
// it('should return correct slices count', () => {
// const count = 4
// const slicesCount = fullTree.getTreeSlices(4).length
// should().equal(count, slicesCount)
// }).timeout(10000)

// it('should be able to create partial tree from last slice', () => {
// const [, , , lastSlice] = fullTree.getTreeSlices()
// const partialTree = new PartialMerkleTree(10, lastSlice.edge, lastSlice.elements)
// assert.deepEqual(fullTree.root, partialTree.root)
// }).timeout(10000)

// it('should be able to build full tree from slices', () => {
// const slices = fullTree.getTreeSlices()
// const lastSlice = slices.pop()
// const partialTree = new PartialMerkleTree(10, lastSlice.edge, lastSlice.elements)
// slices.reverse().forEach(({ edge, elements }) => {
// partialTree.shiftEdge(edge, elements)
// })
// assert.deepEqual(fullTree.layers, partialTree.layers)
// }).timeout(10000)

// it('should return same path', () => {
// const slices = fullTree.getTreeSlices()
// const lastSlice = slices.pop()
// const partialTree = new PartialMerkleTree(10, lastSlice.edge, lastSlice.elements)
// slices.reverse().forEach(({ edge, elements }) => {
// partialTree.shiftEdge(edge, elements)
// })
// assert.deepEqual(fullTree.path(100), partialTree.path(100))
// }).timeout(10000)

// it('should throw if invalid number of elements', () => {
// const [firstSlice] = fullTree.getTreeSlices()
// const call = () => new PartialMerkleTree(10, firstSlice.edge, firstSlice.elements)
// should().throw(call, 'Invalid number of elements')
// }).timeout(10000)
// })
// describe('#getters', () => {
// const elements = [1, 2, 3, 4, 5]
// const layers = [
// [1, 2, 3, 4, 5],
// [
// '4027992409016347597424110157229339967488',
// '923221781152860005594997320673730232320',
// '752191049236692618445397735417537626112',

// ],
// [
// '81822854828781486047086122479545722339328',
// '3591172241203040147397382471352592629760',

// ],
// ['2729943778107054496417267081388406865920'],
// ['4562739390655416913642128116127918718976'],
// ]

// it('should return same elements in array', () => {
// const tree = new MerkleTree(10, elements)
// assert.deepEqual(tree.elements, elements)
// })
// it('should return copy of elements array', () => {
// const tree = new MerkleTree(10, elements)
// const elements1 = tree.elements
// tree.insert(6)
// const elements2 = tree.elements
// should().not.equal(elements1, elements2)
// })

// it('should return same layers in array', () => {
// const tree = new MerkleTree(4, elements)
// assert.deepEqual(tree.layers, layers)
// })
// it('should return copy of elements array', () => {
// const tree = new MerkleTree(4, elements)
// const layers1 = tree.layers
// tree.insert(6)
// const layers2 = tree.layers
// should().not.equal(layers1, layers2)
// })
// it('should return correct zeros array', () => {
// const zeros = [
// 0,
// '1390935134112885103361924701261056180224',
// '3223901263414086620636498663535535980544',
// '938972308169430750202858820582946897920',
// '3743880566844110745576746962917825445888',
// ]
// const tree = new MerkleTree(4, [])
// assert.deepEqual(tree.zeros, zeros, 'Not equal')
// })
// it('should return copy of zeros array', () => {
// const tree = new MerkleTree(4, [])
// const zeros1 = tree.zeros
// tree.insert(6)
// const zeros2 = tree.zeros
// should().not.equal(zeros1, zeros2)
// })
// })

// describe('#serialize', () => {
// it('should work', () => {
// const src = new MerkleTree(10, [1, 2, 3, 4, 5, 6, 7, 8, 9])
// const data = src.serialize()
// const dst = MerkleTree.deserialize(data)
// should().equal(src.root, dst.root)

// src.insert(10)
// dst.insert(10)

// should().equal(src.root, dst.root)
// })
// })
// describe('#toString', () => {
// it('should return correct stringified representation', () => {
// const src = new MerkleTree(10, [1, 2, 3, 4, 5, 6, 7, 8, 9])
// const str = src.toString()
// const dst = MerkleTree.deserialize(JSON.parse(str))
// should().equal(src.root, dst.root)

// src.insert(10)
// dst.insert(10)

// should().equal(src.root, dst.root)
t.Run("proof", func(t *testing.T) {
tree, err := NewMerkleTree(10, []Element{{1}, {2}, {3}, {4}, {5}}, Element{0}, SHA256Hash)
require.NoError(t, err)
proof, err := tree.Proof(Element{4})
require.NoError(t, err)
path, err := tree.Path(3)
require.NoError(t, err)
require.ElementsMatch(t, path.PathElements, proof.PathElements)
})

// })
// })
// })
t.Run("proof is valid", func(t *testing.T) {
tree, err := NewMerkleTree(10, []Element{{1}, {2}, {3}, {4}, {5}}, Element{0}, SHA256Hash)
require.NoError(t, err)
proof, _ := tree.Proof(Element{4})
require.NoError(t, tree.VerifyProof(Element{4}, proof))
})
}

0 comments on commit e3e8a59

Please sign in to comment.