2020-08-11 03:09:16 -07:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
fmt "fmt"
|
|
|
|
|
|
|
|
ics23 "github.com/confio/ics23/go"
|
2020-08-14 10:58:53 -07:00
|
|
|
tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
|
2020-08-11 03:09:16 -07:00
|
|
|
|
|
|
|
sdkmaps "github.com/cosmos/cosmos-sdk/store/internal/maps"
|
|
|
|
sdkproofs "github.com/cosmos/cosmos-sdk/store/internal/proofs"
|
|
|
|
)
|
|
|
|
|
|
|
|
// GetHash returns the GetHash from the CommitID.
|
|
|
|
// This is used in CommitInfo.Hash()
|
|
|
|
//
|
|
|
|
// When we commit to this in a merkle proof, we create a map of storeInfo.Name -> storeInfo.GetHash()
|
|
|
|
// and build a merkle proof from that.
|
|
|
|
// This is then chained with the substore proof, so we prove the root hash from the substore before this
|
|
|
|
// and need to pass that (unmodified) as the leaf value of the multistore proof.
|
|
|
|
func (si StoreInfo) GetHash() []byte {
|
2020-08-14 01:55:54 -07:00
|
|
|
return si.CommitId.Hash
|
2020-08-11 03:09:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ci CommitInfo) toMap() map[string][]byte {
|
|
|
|
m := make(map[string][]byte, len(ci.StoreInfos))
|
|
|
|
for _, storeInfo := range ci.StoreInfos {
|
|
|
|
m[storeInfo.Name] = storeInfo.GetHash()
|
|
|
|
}
|
|
|
|
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash returns the simple merkle root hash of the stores sorted by name.
|
|
|
|
func (ci CommitInfo) Hash() []byte {
|
|
|
|
// we need a special case for empty set, as SimpleProofsFromMap requires at least one entry
|
|
|
|
if len(ci.StoreInfos) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-08-14 10:58:53 -07:00
|
|
|
rootHash, _, _ := sdkmaps.ProofsFromMap(ci.toMap())
|
2020-08-11 03:09:16 -07:00
|
|
|
return rootHash
|
|
|
|
}
|
|
|
|
|
2020-08-14 10:58:53 -07:00
|
|
|
func (ci CommitInfo) ProofOp(storeName string) tmcrypto.ProofOp {
|
2020-08-11 03:09:16 -07:00
|
|
|
cmap := ci.toMap()
|
2020-08-14 10:58:53 -07:00
|
|
|
_, proofs, _ := sdkmaps.ProofsFromMap(cmap)
|
2020-08-11 03:09:16 -07:00
|
|
|
|
|
|
|
proof := proofs[storeName]
|
|
|
|
if proof == nil {
|
|
|
|
panic(fmt.Sprintf("ProofOp for %s but not registered store name", storeName))
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert merkle.SimpleProof to CommitmentProof
|
|
|
|
existProof, err := sdkproofs.ConvertExistenceProof(proof, []byte(storeName), cmap[storeName])
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Errorf("could not convert simple proof to existence proof: %w", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
commitmentProof := &ics23.CommitmentProof{
|
|
|
|
Proof: &ics23.CommitmentProof_Exist{
|
|
|
|
Exist: existProof,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return NewSimpleMerkleCommitmentOp([]byte(storeName), commitmentProof).ProofOp()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ci CommitInfo) CommitID() CommitID {
|
|
|
|
return CommitID{
|
|
|
|
Version: ci.Version,
|
|
|
|
Hash: ci.Hash(),
|
|
|
|
}
|
|
|
|
}
|