Skip to content

Commit

Permalink
simplify single-leaf merklearray proofs
Browse files Browse the repository at this point in the history
No need to explicitly specify tree depth for merklearray proofs of
a single leaf node, because the tree depth is exactly the number of
sibling hashes in the proof.

This allows simplifying the format for sending single-leaf merklearray
proofs, sending just the proofBytes []byte, and not having to send along
an extra treeDepth.

The current algod API for fetching a proof still sends the tree depth
along, for any clients that might care about it, but future APIs won't
need to pass treeDepth.
  • Loading branch information
zeldovich committed Aug 30, 2023
1 parent b86d0ff commit 8dac888
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 9 deletions.
5 changes: 3 additions & 2 deletions crypto/merklearray/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func (p *SingleLeafProof) GetConcatenatedProof() []byte {
}

// ProofDataToSingleLeafProof receives serialized proof data and uses it to construct a proof object.
func ProofDataToSingleLeafProof(hashTypeData string, treeDepth uint64, proofBytes []byte) (SingleLeafProof, error) {
func ProofDataToSingleLeafProof(hashTypeData string, proofBytes []byte) (SingleLeafProof, error) {
hashType, err := crypto.UnmarshalHashType(hashTypeData)
if err != nil {
return SingleLeafProof{}, err
Expand All @@ -158,7 +158,7 @@ func ProofDataToSingleLeafProof(hashTypeData string, treeDepth uint64, proofByte
var proof SingleLeafProof

proof.HashFactory = crypto.HashFactory{HashType: hashType}
proof.TreeDepth = uint8(treeDepth)
proof.TreeDepth = 0

digestSize := proof.HashFactory.NewHash().Size()
if len(proofBytes)%digestSize != 0 {
Expand All @@ -172,6 +172,7 @@ func ProofDataToSingleLeafProof(hashTypeData string, treeDepth uint64, proofByte
copy(d[:], proofBytes)
proofPath = append(proofPath, d[:])
proofBytes = proofBytes[len(d):]
proof.TreeDepth++
}

proof.Path = proofPath
Expand Down
8 changes: 4 additions & 4 deletions crypto/merklearray/proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func TestConcatenatedProofsMissingChild(t *testing.T) {
err = Verify(tree.Root(), map[uint64]crypto.Hashable{6: array[6]}, newP.ToProof())
a.NoError(err)

recomputedProof, err := ProofDataToSingleLeafProof(p.HashFactory.HashType.String(), uint64(p.TreeDepth), concatenatedProof)
recomputedProof, err := ProofDataToSingleLeafProof(p.HashFactory.HashType.String(), concatenatedProof)
a.NoError(err)

// verify that we can reconstruct the original singleLeafProof from the concatenated proof
Expand Down Expand Up @@ -189,7 +189,7 @@ func TestConcatenatedProofsFullTree(t *testing.T) {
err = Verify(tree.Root(), map[uint64]crypto.Hashable{6: array[6]}, newP.ToProof())
a.NoError(err)

recomputedProof, err := ProofDataToSingleLeafProof(p.HashFactory.HashType.String(), uint64(p.TreeDepth), concatenatedProof)
recomputedProof, err := ProofDataToSingleLeafProof(p.HashFactory.HashType.String(), concatenatedProof)
a.NoError(err)

// verify that we can reconstruct the original singleLeafProof from the concatenated proof
Expand Down Expand Up @@ -218,7 +218,7 @@ func TestConcatenatedProofsOneLeaf(t *testing.T) {
err = Verify(tree.Root(), map[uint64]crypto.Hashable{0: array[0]}, newP.ToProof())
a.NoError(err)

recomputedProof, err := ProofDataToSingleLeafProof(p.HashFactory.HashType.String(), uint64(p.TreeDepth), concatenatedProof)
recomputedProof, err := ProofDataToSingleLeafProof(p.HashFactory.HashType.String(), concatenatedProof)
a.NoError(err)

// verify that we can reconstruct the original singleLeafProof from the concatenated proof
Expand All @@ -230,7 +230,7 @@ func TestProofDeserializationError(t *testing.T) {
partitiontest.PartitionTest(t)
a := require.New(t)

_, err := ProofDataToSingleLeafProof(crypto.Sha256.String(), 1, []byte{1})
_, err := ProofDataToSingleLeafProof(crypto.Sha256.String(), []byte{1})
a.ErrorIs(err, ErrProofLengthDigestSizeMismatch)
}

Expand Down
4 changes: 3 additions & 1 deletion daemon/algod/api/server/v2/test/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1810,9 +1810,11 @@ func TestGetProofDefault(t *testing.T) {
blkHdr, err := l.BlockHdr(1)
a.NoError(err)

singleLeafProof, err := merklearray.ProofDataToSingleLeafProof(string(resp.Hashtype), resp.Treedepth, resp.Proof)
singleLeafProof, err := merklearray.ProofDataToSingleLeafProof(string(resp.Hashtype), resp.Proof)
a.NoError(err)

a.Equal(uint64(singleLeafProof.TreeDepth), resp.Treedepth)

element := TxnMerkleElemRaw{Txn: crypto.Digest(txid)}
copy(element.Stib[:], resp.Stibhash[:])
elems := make(map[uint64]crypto.Hashable)
Expand Down
4 changes: 2 additions & 2 deletions test/framework/fixtures/libgoalFixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ func (f *LibGoalFixture) TransactionProof(txid string, round uint64, hashType cr
return model.TransactionProofResponse{}, merklearray.SingleLeafProof{}, err
}

proof, err := merklearray.ProofDataToSingleLeafProof(string(proofResp.Hashtype), proofResp.Treedepth, proofResp.Proof)
proof, err := merklearray.ProofDataToSingleLeafProof(string(proofResp.Hashtype), proofResp.Proof)
if err != nil {
return model.TransactionProofResponse{}, merklearray.SingleLeafProof{}, err
}
Expand All @@ -550,7 +550,7 @@ func (f *LibGoalFixture) LightBlockHeaderProof(round uint64) (model.LightBlockHe
return model.LightBlockHeaderProofResponse{}, merklearray.SingleLeafProof{}, err
}

proof, err := merklearray.ProofDataToSingleLeafProof(crypto.Sha256.String(), proofResp.Treedepth, proofResp.Proof)
proof, err := merklearray.ProofDataToSingleLeafProof(crypto.Sha256.String(), proofResp.Proof)
if err != nil {
return model.LightBlockHeaderProofResponse{}, merklearray.SingleLeafProof{}, err
}
Expand Down

0 comments on commit 8dac888

Please sign in to comment.