Skip to content
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

imp: cleanup verifcation arg code for 23-commitment #7493

Merged
merged 10 commits into from
Nov 19, 2024
15 changes: 0 additions & 15 deletions modules/core/23-commitment/types/bench_test.go

This file was deleted.

65 changes: 20 additions & 45 deletions modules/core/23-commitment/types/merkle.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@ package types
import (
"bytes"

"github.com/cosmos/gogoproto/proto"
ics23 "github.com/cosmos/ics23/go"

errorsmod "cosmossdk.io/errors"

cmtcrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"

"github.com/cosmos/ibc-go/v9/modules/core/23-commitment/types/v2"
"github.com/cosmos/ibc-go/v9/modules/core/exported"
)
Expand Down Expand Up @@ -86,19 +83,16 @@ func ApplyPrefix(prefix exported.Prefix, path v2.MerklePath) (v2.MerklePath, err
// VerifyMembership verifies the membership of a merkle proof against the given root, path, and value.
// Note that the path is expected as []string{<store key of module>, <key corresponding to requested value>}.
func (proof MerkleProof) VerifyMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, value []byte) error {
if err := proof.validateVerificationArgs(specs, root); err != nil {
return err
}

// VerifyMembership specific argument validation
mpath, ok := path.(v2.MerklePath)
if !ok {
return errorsmod.Wrapf(ErrInvalidProof, "path %v is not of type MerklePath", path)
}
if len(mpath.KeyPath) != len(specs) {
return errorsmod.Wrapf(ErrInvalidProof, "path length %d not same as proof %d",
len(mpath.KeyPath), len(specs))

if err := validateVerificationArgs(proof, mpath, specs, root); err != nil {
return err
}

// VerifyMembership specific argument validation
if len(value) == 0 {
return errorsmod.Wrap(ErrInvalidProof, "empty value in membership proof")
}
Expand All @@ -112,17 +106,13 @@ func (proof MerkleProof) VerifyMembership(specs []*ics23.ProofSpec, root exporte
// VerifyNonMembership verifies a chained proof where the absence of a given path is proven
// at the lowest subtree and then each subtree's inclusion is proved up to the final root.
func (proof MerkleProof) VerifyNonMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path) error {
if err := proof.validateVerificationArgs(specs, root); err != nil {
return err
}

// VerifyNonMembership specific argument validation
mpath, ok := path.(v2.MerklePath)
if !ok {
return errorsmod.Wrapf(ErrInvalidProof, "path %v is not of type MerkleProof", path)
}
if len(mpath.KeyPath) != len(specs) {
return errorsmod.Wrapf(ErrInvalidProof, "path length %d not same as proof %d", len(mpath.KeyPath), len(specs))

if err := validateVerificationArgs(proof, mpath, specs, root); err != nil {
return err
}

// VerifyNonMembership will verify the absence of key in lowest subtree, and then chain inclusion proofs
Expand Down Expand Up @@ -198,40 +188,25 @@ func verifyChainedMembershipProof(root []byte, specs []*ics23.ProofSpec, proofs
return nil
}

// blankMerkleProof and blankProofOps will be used to compare against their zero values,
// and are declared as globals to avoid having to unnecessarily re-allocate on every comparison.
var (
blankMerkleProof = &MerkleProof{}
blankProofOps = &cmtcrypto.ProofOps{}
)

// Empty returns true if the root is empty
func (proof *MerkleProof) Empty() bool {
return proof == nil || proto.Equal(proof, blankMerkleProof) || proto.Equal(proof, blankProofOps)
}

// ValidateBasic checks if the proof is empty.
func (proof MerkleProof) ValidateBasic() error {
if proof.Empty() {
return ErrInvalidProof
}
return nil
}

// validateVerificationArgs verifies the proof arguments are valid
func (proof MerkleProof) validateVerificationArgs(specs []*ics23.ProofSpec, root exported.Root) error {
if proof.Empty() {
return errorsmod.Wrap(ErrInvalidMerkleProof, "proof cannot be empty")
// validateVerificationArgs verifies the proof arguments are valid.
// The merkle path and merkle proof contain a list of keys and their proofs
// which correspond to individual trees. The length of these keys and their proofs
// must equal the length of the given specs. All arguments must be non-empty.
func validateVerificationArgs(proof MerkleProof, path v2.MerklePath, specs []*ics23.ProofSpec, root exported.Root) error {
if proof.GetProofs() == nil {
return errorsmod.Wrap(ErrInvalidMerkleProof, "proof must not be empty")
}

if root == nil || root.Empty() {
return errorsmod.Wrap(ErrInvalidMerkleProof, "root cannot be empty")
}

if len(specs) != len(proof.Proofs) {
return errorsmod.Wrapf(ErrInvalidMerkleProof,
"length of specs: %d not equal to length of proof: %d",
len(specs), len(proof.Proofs))
return errorsmod.Wrapf(ErrInvalidMerkleProof, "length of specs: %d not equal to length of proof: %d", len(specs), len(proof.Proofs))
}

if len(path.KeyPath) != len(specs) {
return errorsmod.Wrapf(ErrInvalidProof, "path length %d not same as proof %d", len(path.KeyPath), len(specs))
damiannolan marked this conversation as resolved.
Show resolved Hide resolved
}

for i, spec := range specs {
Expand Down
5 changes: 0 additions & 5 deletions modules/core/23-commitment/types/merkle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ func (suite *MerkleTestSuite) TestVerifyMembership() {
proof, err := types.ConvertProofs(res.ProofOps)
require.NoError(suite.T(), err)

suite.Require().NoError(proof.ValidateBasic())
DimitrisJim marked this conversation as resolved.
Show resolved Hide resolved
suite.Require().Error(types.MerkleProof{}.ValidateBasic())

cases := []struct {
name string
root []byte
Expand Down Expand Up @@ -93,8 +90,6 @@ func (suite *MerkleTestSuite) TestVerifyNonMembership() {
proof, err := types.ConvertProofs(res.ProofOps)
require.NoError(suite.T(), err)

suite.Require().NoError(proof.ValidateBasic())

cases := []struct {
name string
root []byte
Expand Down
Loading