func (proof MerkleProof) BatchVerifyNonMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, items [][]byte) error {
	return sdkerrors.Wrap(ErrInvalidProof, "batch proofs are currently unsupported")
}
BatchVerifyNonMembership verifies absence of a group of keys against the given root
NOTE: Currently left unimplemented as it is unused
package types
import (
	"bytes"
	"fmt"
	"net/url"
	ics23 "github.com/confio/ics23/go"
	"github.com/gogo/protobuf/proto"
	tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	"github.com/bianjieai/tibc-go/modules/tibc/core/exported"
)
var sdkSpecs = []*ics23.ProofSpec{ics23.IavlSpec, ics23.TendermintSpec}
var _ exported.Root = (*MerkleRoot)(nil)
func GetSDKSpecs() []*ics23.ProofSpec {
	return sdkSpecs
}
func NewMerkleRoot(hash []byte) MerkleRoot {
	return MerkleRoot{
		Hash: hash,
	}
}
func (mr MerkleRoot) GetHash() []byte {
	return mr.Hash
}
func (mr MerkleRoot) Empty() bool {
	return len(mr.GetHash()) == 0
}
var _ exported.Prefix = (*MerklePrefix)(nil)
func NewMerklePrefix(keyPrefix []byte) MerklePrefix {
	return MerklePrefix{
		KeyPrefix: keyPrefix,
	}
}
func (mp MerklePrefix) Bytes() []byte {
	return mp.KeyPrefix
}
func (mp MerklePrefix) Empty() bool {
	return len(mp.Bytes()) == 0
}
var _ exported.Path = (*MerklePath)(nil)
func NewMerklePath(keyPath ...string) MerklePath {
	return MerklePath{
		KeyPath: keyPath,
	}
}
func (mp MerklePath) String() string {
	pathStr := ""
	for _, k := range mp.KeyPath {
		pathStr += "/" + url.PathEscape(k)
	}
	return pathStr
}
func (mp MerklePath) Pretty() string {
	path, err := url.PathUnescape(mp.String())
	if err != nil {
		panic(err)
	}
	return path
}
func (mp MerklePath) GetKey(i uint64) ([]byte, error) {
	if i >= uint64(len(mp.KeyPath)) {
		return nil, fmt.Errorf("index out of range. %d (index) >= %d (len)", i, len(mp.KeyPath))
	}
	key, err := url.PathUnescape(mp.KeyPath[i])
	if err != nil {
		return nil, err
	}
	return []byte(key), nil
}
func (mp MerklePath) Empty() bool {
	return len(mp.KeyPath) == 0
}
func ApplyPrefix(prefix exported.Prefix, path MerklePath) (MerklePath, error) {
	if prefix == nil || prefix.Empty() {
		return MerklePath{}, sdkerrors.Wrap(ErrInvalidPrefix, "prefix can't be empty")
	}
	return NewMerklePath(append([]string{string(prefix.Bytes())}, path.KeyPath...)...), nil
}
var _ exported.Proof = (*MerkleProof)(nil)
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
	}
	mpath, ok := path.(MerklePath)
	if !ok {
		return sdkerrors.Wrapf(ErrInvalidProof, "path %v is not of type MerklePath", path)
	}
	if len(mpath.KeyPath) != len(specs) {
		return sdkerrors.Wrapf(
			ErrInvalidProof,
			"path length %d not same as proof %d",
			len(mpath.KeyPath), len(specs),
		)
	}
	if len(value) == 0 {
		return sdkerrors.Wrap(ErrInvalidProof, "empty value in membership proof")
	}
	if err := verifyChainedMembershipProof(root.GetHash(), specs, proof.Proofs, mpath, value, 0); err != nil {
		return err
	}
	return nil
}
func (proof MerkleProof) VerifyNonMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path) error {
	if err := proof.validateVerificationArgs(specs, root); err != nil {
		return err
	}
	mpath, ok := path.(MerklePath)
	if !ok {
		return sdkerrors.Wrapf(ErrInvalidProof, "path %v is not of type MerkleProof", path)
	}
	if len(mpath.KeyPath) != len(specs) {
		return sdkerrors.Wrapf(
			ErrInvalidProof, "path length %d not same as proof %d",
			len(mpath.KeyPath), len(specs),
		)
	}
	switch proof.Proofs[0].Proof.(type) {
	case *ics23.CommitmentProof_Nonexist:
		subroot, err := proof.Proofs[0].Calculate()
		if err != nil {
			return sdkerrors.Wrapf(ErrInvalidProof, "could not calculate root for proof index 0, merkle tree is likely empty. %v", err)
		}
		key, err := mpath.GetKey(uint64(len(mpath.KeyPath) - 1))
		if err != nil {
			return sdkerrors.Wrapf(ErrInvalidProof, "could not retrieve key bytes for key: %s", mpath.KeyPath[len(mpath.KeyPath)-1])
		}
		if ok := ics23.VerifyNonMembership(specs[0], subroot, proof.Proofs[0], key); !ok {
			return sdkerrors.Wrapf(ErrInvalidProof, "could not verify absence of key %s. Please ensure that the path is correct.", string(key))
		}
		if err := verifyChainedMembershipProof(root.GetHash(), specs, proof.Proofs, mpath, subroot, 1); err != nil {
			return err
		}
	case *ics23.CommitmentProof_Exist:
		return sdkerrors.Wrapf(
			ErrInvalidProof,
			"got ExistenceProof in VerifyNonMembership. If this is unexpected, please ensure that proof was queried with the correct key.",
		)
	default:
		return sdkerrors.Wrapf(
			ErrInvalidProof,
			"expected proof type: %T, got: %T",
			&ics23.CommitmentProof_Exist{}, proof.Proofs[0].Proof,
		)
	}
	return nil
}
func (proof MerkleProof) BatchVerifyMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, items map[string][]byte) error {
	return sdkerrors.Wrap(ErrInvalidProof, "batch proofs are currently unsupported")
}