* 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
92 lines
2.6 KiB
Go
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
|
|
}
|