cosmos-sdk/store/multistoreproof.go
Dev Ojha 358b48771c Merge PR #2308: Remove ripemd160 entirely
* Remove ripemd160 entirely

We already made this decision awhile ago, and have had tendermint switched
for awhile. I was surprised to find ripemd still used within the storeinfo.
This actually leads me to think the new "byter" API change in the tendermint
PR RFC compliance is better, as it avoids things like this from ever happening.

* Get ripemd160 removed from the gopkg imports
2018-09-12 15:13:14 +08:00

92 lines
2.6 KiB
Go

package store
import (
"bytes"
"github.com/pkg/errors"
"github.com/tendermint/iavl"
cmn "github.com/tendermint/tendermint/libs/common"
)
// MultiStoreProof defines a collection of store proofs in a multi-store
type MultiStoreProof struct {
StoreInfos []storeInfo
StoreName string
RangeProof iavl.RangeProof
}
// buildMultiStoreProof build MultiStoreProof based on iavl proof and storeInfos
func buildMultiStoreProof(iavlProof []byte, storeName string, storeInfos []storeInfo) []byte {
var rangeProof iavl.RangeProof
cdc.MustUnmarshalBinary(iavlProof, &rangeProof)
msp := MultiStoreProof{
StoreInfos: storeInfos,
StoreName: storeName,
RangeProof: rangeProof,
}
proof := cdc.MustMarshalBinary(msp)
return proof
}
// VerifyMultiStoreCommitInfo verify multiStoreCommitInfo against appHash
func VerifyMultiStoreCommitInfo(storeName string, storeInfos []storeInfo, appHash []byte) ([]byte, error) {
var substoreCommitHash []byte
var height int64
for _, storeInfo := range storeInfos {
if storeInfo.Name == storeName {
substoreCommitHash = storeInfo.Core.CommitID.Hash
height = storeInfo.Core.CommitID.Version
}
}
if len(substoreCommitHash) == 0 {
return nil, cmn.NewError("failed to get substore root commit hash by store name")
}
ci := commitInfo{
Version: height,
StoreInfos: storeInfos,
}
if !bytes.Equal(appHash, ci.Hash()) {
return nil, cmn.NewError("the merkle root of multiStoreCommitInfo doesn't equal to appHash")
}
return substoreCommitHash, nil
}
// VerifyRangeProof verify iavl RangeProof
func VerifyRangeProof(key, value []byte, substoreCommitHash []byte, rangeProof *iavl.RangeProof) error {
// verify the proof to ensure data integrity.
err := rangeProof.Verify(substoreCommitHash)
if err != nil {
return errors.Wrap(err, "proof root hash doesn't equal to substore commit root hash")
}
if len(value) != 0 {
// verify existence proof
err = rangeProof.VerifyItem(key, value)
if err != nil {
return errors.Wrap(err, "failed in existence verification")
}
} else {
// verify absence proof
err = rangeProof.VerifyAbsence(key)
if err != nil {
return errors.Wrap(err, "failed in absence verification")
}
}
return nil
}
// RequireProof return whether proof is require for the subpath
func RequireProof(subpath string) bool {
// Currently, only when query subpath is "/store" or "/key", will proof be included in response.
// If there are some changes about proof building in iavlstore.go, we must change code here to keep consistency with iavlstore.go:212
if subpath == "/store" || subpath == "/key" {
return true
}
return false
}