Enforce ProofSpecs in 23-Commitment (#6374)

* enforce spec ordering

* modify clients to pass in specs to verify functions

* start fixing tests

* Apply suggestions from code review

* enforce spec length and proof length match

* fix all tests

* add argument to constructor:

* fixed msg client and tests

* appease linter

* Apply suggestions from code review

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* finish fixes from review

* add back proof-specific checks

* Apply suggestions from code review

* more robust proof spec checks

* add CHANGELOG entries

* do not hardcode proofspecs in 23-commitment

* fix client modules

* fix tests

* appease linter

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
Aditya 2020-06-12 06:45:40 -04:00 committed by GitHub
parent 9048ffa8d3
commit d82c2e6a94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 514 additions and 230 deletions

View File

@ -46,6 +46,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
balances or a single balance by denom when the `denom` query parameter is present. balances or a single balance by denom when the `denom` query parameter is present.
* (client) [\#5640](https://github.com/cosmos/cosmos-sdk/pull/5640) The rest server endpoint `/swagger-ui/` is replaced by ´/´. * (client) [\#5640](https://github.com/cosmos/cosmos-sdk/pull/5640) The rest server endpoint `/swagger-ui/` is replaced by ´/´.
* (x/auth) [\#5702](https://github.com/cosmos/cosmos-sdk/pull/5702) The `x/auth` querier route has changed from `"acc"` to `"auth"`. * (x/auth) [\#5702](https://github.com/cosmos/cosmos-sdk/pull/5702) The `x/auth` querier route has changed from `"acc"` to `"auth"`.
* (store/rootmulti) [\#6390](https://github.com/cosmos/cosmos-sdk/pull/6390) Proofs of empty stores are no longer supported.
* (store/types) [\#5730](https://github.com/cosmos/cosmos-sdk/pull/5730) store.types.Cp() is removed in favour of types.CopyBytes(). * (store/types) [\#5730](https://github.com/cosmos/cosmos-sdk/pull/5730) store.types.Cp() is removed in favour of types.CopyBytes().
* (client) [\#5640](https://github.com/cosmos/cosmos-sdk/issues/5783) Unify all coins representations on JSON client requests for governance proposals. * (client) [\#5640](https://github.com/cosmos/cosmos-sdk/issues/5783) Unify all coins representations on JSON client requests for governance proposals.
* [\#5785](https://github.com/cosmos/cosmos-sdk/issues/5785) JSON strings coerced to valid UTF-8 bytes at JSON marshalling time * [\#5785](https://github.com/cosmos/cosmos-sdk/issues/5785) JSON strings coerced to valid UTF-8 bytes at JSON marshalling time
@ -135,6 +136,7 @@ be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposa
* (client/lcd) [\#6290](https://github.com/cosmos/cosmos-sdk/pull/6290) `CliCtx` of struct `RestServer` in package client/lcd has been renamed to `ClientCtx`. * (client/lcd) [\#6290](https://github.com/cosmos/cosmos-sdk/pull/6290) `CliCtx` of struct `RestServer` in package client/lcd has been renamed to `ClientCtx`.
* (types) [\#6327](https://github.com/cosmos/cosmos-sdk/pull/6327) `sdk.Msg` now inherits `proto.Message`, as a result all `sdk.Msg` types now use pointer semantics. * (types) [\#6327](https://github.com/cosmos/cosmos-sdk/pull/6327) `sdk.Msg` now inherits `proto.Message`, as a result all `sdk.Msg` types now use pointer semantics.
* (codec) [\#6330](https://github.com/cosmos/cosmos-sdk/pull/6330) `codec.RegisterCrypto` has been moved to the `crypto/codec` package and the global `codec.Cdc` Amino instance has been deprecated and moved to the `codec/legacy_global` package. * (codec) [\#6330](https://github.com/cosmos/cosmos-sdk/pull/6330) `codec.RegisterCrypto` has been moved to the `crypto/codec` package and the global `codec.Cdc` Amino instance has been deprecated and moved to the `codec/legacy_global` package.
* (x/ibc) [\#6374](https://github.com/cosmos/cosmos-sdk/pull/6374) `VerifyMembership` and `VerifyNonMembership` now take a `specs []string` argument to specify the proof format used for verification. Most SDK chains can simply use `commitmenttypes.GetSDKSpecs()` for this argument.
### Features ### Features
@ -153,6 +155,7 @@ be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposa
* (x/capability) [\#5828](https://github.com/cosmos/cosmos-sdk/pull/5828) Capability module integration as outlined in [ADR 3 - Dynamic Capability Store](https://github.com/cosmos/tree/master/docs/architecture/adr-003-dynamic-capability-store.md). * (x/capability) [\#5828](https://github.com/cosmos/cosmos-sdk/pull/5828) Capability module integration as outlined in [ADR 3 - Dynamic Capability Store](https://github.com/cosmos/tree/master/docs/architecture/adr-003-dynamic-capability-store.md).
* (x/params) [\#6005](https://github.com/cosmos/cosmos-sdk/pull/6005) Add new CLI command for querying raw x/params parameters by subspace and key. * (x/params) [\#6005](https://github.com/cosmos/cosmos-sdk/pull/6005) Add new CLI command for querying raw x/params parameters by subspace and key.
* (x/ibc) [\#5769](https://github.com/cosmos/cosmos-sdk/pull/5769) [ICS 009 - Loopback Client](https://github.com/cosmos/ics/tree/master/spec/ics-009-loopback-client) subpackage * (x/ibc) [\#5769](https://github.com/cosmos/cosmos-sdk/pull/5769) [ICS 009 - Loopback Client](https://github.com/cosmos/ics/tree/master/spec/ics-009-loopback-client) subpackage
* (x/ibc) [\#6374](https://github.com/cosmos/cosmos-sdk/pull/6374) ICS-23 Verify functions will now accept and verify ics23 CommitmentProofs exclusively
* (store) [\#6324](https://github.com/cosmos/cosmos-sdk/pull/6324) IAVL store query proofs now return CommitmentOp which wraps an ics23 CommitmentProof * (store) [\#6324](https://github.com/cosmos/cosmos-sdk/pull/6324) IAVL store query proofs now return CommitmentOp which wraps an ics23 CommitmentProof
* (store) [\#6390](https://github.com/cosmos/cosmos-sdk/pull/6390) `RootMulti` store query proofs now return `CommitmentOp` which wraps `CommitmentProofs` * (store) [\#6390](https://github.com/cosmos/cosmos-sdk/pull/6390) `RootMulti` store query proofs now return `CommitmentOp` which wraps `CommitmentProofs`
* `store.Query` now only returns chained `ics23.CommitmentProof` wrapped in `merkle.Proof` * `store.Query` now only returns chained `ics23.CommitmentProof` wrapped in `merkle.Proof`

View File

@ -190,7 +190,7 @@ func (chain *TestChain) CreateClient(client *TestChain) error {
ctxTarget := chain.GetContext() ctxTarget := chain.GetContext()
// create client // create client
clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header) clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -259,7 +259,7 @@ func (chain *TestChain) updateClient(client *TestChain) {
ctxTarget, client.ClientID, uint64(client.Header.SignedHeader.Header.Height), consensusState, ctxTarget, client.ClientID, uint64(client.Header.SignedHeader.Header.Height), consensusState,
) )
chain.App.IBCKeeper.ClientKeeper.SetClientState( chain.App.IBCKeeper.ClientKeeper.SetClientState(
ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header), ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs()),
) )
// _, _, err := simapp.SignCheckDeliver( // _, _, err := simapp.SignCheckDeliver(

View File

@ -165,7 +165,7 @@ func (chain *TestChain) CreateClient(client *TestChain) error {
ctxTarget := chain.GetContext() ctxTarget := chain.GetContext()
// create client // create client
clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header) clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -234,7 +234,7 @@ func (chain *TestChain) updateClient(client *TestChain) {
ctxTarget, client.ClientID, client.Header.GetHeight(), consensusState, ctxTarget, client.ClientID, client.Header.GetHeight(), consensusState,
) )
chain.App.IBCKeeper.ClientKeeper.SetClientState( chain.App.IBCKeeper.ClientKeeper.SetClientState(
ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header), ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs()),
) )
// _, _, err := simapp.SignCheckDeliver( // _, _, err := simapp.SignCheckDeliver(

View File

@ -3,6 +3,7 @@ package exported
import ( import (
"encoding/json" "encoding/json"
ics23 "github.com/confio/ics23/go"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -21,6 +22,7 @@ type ClientState interface {
GetLatestHeight() uint64 GetLatestHeight() uint64
IsFrozen() bool IsFrozen() bool
Validate() error Validate() error
GetProofSpecs() []*ics23.ProofSpec
// State verification functions // State verification functions

View File

@ -38,12 +38,12 @@ func (suite *KeeperTestSuite) TestCreateClient() {
i := i i := i
if tc.expPanic { if tc.expPanic {
suite.Require().Panics(func() { suite.Require().Panics(func() {
clientState, err := ibctmtypes.Initialize(tc.clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState, err := ibctmtypes.Initialize(tc.clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
suite.Require().NoError(err, "err on client state initialization") suite.Require().NoError(err, "err on client state initialization")
suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState)
}, "Msg %d didn't panic: %s", i, tc.msg) }, "Msg %d didn't panic: %s", i, tc.msg)
} else { } else {
clientState, err := ibctmtypes.Initialize(tc.clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState, err := ibctmtypes.Initialize(tc.clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
if tc.expPass { if tc.expPass {
suite.Require().NoError(err, "errored on initialization") suite.Require().NoError(err, "errored on initialization")
suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.msg) suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.msg)
@ -80,7 +80,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
expPass bool expPass bool
}{ }{
{"valid update", func() error { {"valid update", func() error {
clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -114,7 +114,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
return nil return nil
}, false}, }, false},
{"invalid header", func() error { {"invalid header", func() error {
clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -229,7 +229,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
}, },
func() error { func() error {
suite.consensusState.ValidatorSet = bothValSet suite.consensusState.ValidatorSet = bothValSet
clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -249,7 +249,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
}, },
func() error { func() error {
suite.consensusState.ValidatorSet = bothValSet suite.consensusState.ValidatorSet = bothValSet
clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -304,7 +304,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
ClientID: testClientID, ClientID: testClientID,
}, },
func() error { func() error {
clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }

View File

@ -23,7 +23,7 @@ import (
) )
const ( const (
testClientID = "gaia" testClientID = "gaiachain"
testClientID2 = "ethbridge" testClientID2 = "ethbridge"
testClientID3 = "ethermint" testClientID3 = "ethermint"
@ -90,7 +90,7 @@ func TestKeeperTestSuite(t *testing.T) {
} }
func (suite *KeeperTestSuite) TestSetClientState() { func (suite *KeeperTestSuite) TestSetClientState() {
clientState := ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}) clientState := ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs())
suite.keeper.SetClientState(suite.ctx, clientState) suite.keeper.SetClientState(suite.ctx, clientState)
retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID) retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID)
@ -121,9 +121,9 @@ func (suite *KeeperTestSuite) TestSetClientConsensusState() {
func (suite KeeperTestSuite) TestGetAllClients() { func (suite KeeperTestSuite) TestGetAllClients() {
expClients := []exported.ClientState{ expClients := []exported.ClientState{
ibctmtypes.NewClientState(testClientID2, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}), ibctmtypes.NewClientState(testClientID2, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testClientID3, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}), ibctmtypes.NewClientState(testClientID3, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}), ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
} }
for i := range expClients { for i := range expClients {
@ -168,7 +168,7 @@ func (suite KeeperTestSuite) TestGetConsensusState() {
func (suite KeeperTestSuite) TestConsensusStateHelpers() { func (suite KeeperTestSuite) TestConsensusStateHelpers() {
// initial setup // initial setup
clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState, err := ibctmtypes.Initialize(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
suite.Require().NoError(err) suite.Require().NoError(err)
suite.keeper.SetClientState(suite.ctx, clientState) suite.keeper.SetClientState(suite.ctx, clientState)

View File

@ -50,7 +50,7 @@ func TestValidateGenesis(t *testing.T) {
name: "valid genesis", name: "valid genesis",
genState: types.NewGenesisState( genState: types.NewGenesisState(
[]exported.ClientState{ []exported.ClientState{
ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header), ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
localhosttypes.NewClientState("chaindID", 10), localhosttypes.NewClientState("chaindID", 10),
}, },
[]types.ClientConsensusStates{ []types.ClientConsensusStates{
@ -71,7 +71,7 @@ func TestValidateGenesis(t *testing.T) {
name: "invalid client", name: "invalid client",
genState: types.NewGenesisState( genState: types.NewGenesisState(
[]exported.ClientState{ []exported.ClientState{
ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header), ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
localhosttypes.NewClientState("chaindID", 0), localhosttypes.NewClientState("chaindID", 0),
}, },
nil, nil,
@ -83,7 +83,7 @@ func TestValidateGenesis(t *testing.T) {
name: "invalid consensus state", name: "invalid consensus state",
genState: types.NewGenesisState( genState: types.NewGenesisState(
[]exported.ClientState{ []exported.ClientState{
ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header), ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
localhosttypes.NewClientState("chaindID", 10), localhosttypes.NewClientState("chaindID", 10),
}, },
[]types.ClientConsensusStates{ []types.ClientConsensusStates{
@ -104,7 +104,7 @@ func TestValidateGenesis(t *testing.T) {
name: "invalid consensus state", name: "invalid consensus state",
genState: types.NewGenesisState( genState: types.NewGenesisState(
[]exported.ClientState{ []exported.ClientState{
ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header), ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
localhosttypes.NewClientState("chaindID", 10), localhosttypes.NewClientState("chaindID", 10),
}, },
[]types.ClientConsensusStates{ []types.ClientConsensusStates{

View File

@ -132,9 +132,9 @@ func (suite KeeperTestSuite) TestGetAllConnections() {
func (suite KeeperTestSuite) TestGetAllClientConnectionPaths() { func (suite KeeperTestSuite) TestGetAllClientConnectionPaths() {
clients := []clientexported.ClientState{ clients := []clientexported.ClientState{
ibctmtypes.NewClientState(testClientIDA, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}), ibctmtypes.NewClientState(testClientIDA, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testClientIDB, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}), ibctmtypes.NewClientState(testClientIDB, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testClientID3, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}), ibctmtypes.NewClientState(testClientID3, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
} }
for i := range clients { for i := range clients {
@ -264,7 +264,7 @@ func (chain *TestChain) CreateClient(client *TestChain) error {
ctxTarget := chain.GetContext() ctxTarget := chain.GetContext()
// create client // create client
clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header) clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -340,7 +340,7 @@ func (chain *TestChain) updateClient(client *TestChain) {
ctxTarget, client.ClientID, client.Header.GetHeight(), consensusState, ctxTarget, client.ClientID, client.Header.GetHeight(), consensusState,
) )
chain.App.IBCKeeper.ClientKeeper.SetClientState( chain.App.IBCKeeper.ClientKeeper.SetClientState(
ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header), ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs()),
) )
// _, _, err := simapp.SignCheckDeliver( // _, _, err := simapp.SignCheckDeliver(

View File

@ -381,7 +381,7 @@ func (chain *TestChain) CreateClient(client *TestChain) error {
ctxTarget := chain.GetContext() ctxTarget := chain.GetContext()
// create client // create client
clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header) clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -449,7 +449,7 @@ func (chain *TestChain) updateClient(client *TestChain) {
ctxTarget, client.ClientID, client.Header.GetHeight(), consensusState, ctxTarget, client.ClientID, client.Header.GetHeight(), consensusState,
) )
chain.App.IBCKeeper.ClientKeeper.SetClientState( chain.App.IBCKeeper.ClientKeeper.SetClientState(
ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header), ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs()),
) )
// _, _, err := simapp.SignCheckDeliver( // _, _, err := simapp.SignCheckDeliver(

View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
"time" "time"
ics23 "github.com/confio/ics23/go"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -25,17 +26,23 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
) )
const flagTrustLevel = "trust-level" const (
flagTrustLevel = "trust-level"
flagProofSpecs = "proof-specs"
)
// GetCmdCreateClient defines the command to create a new IBC Client as defined // GetCmdCreateClient defines the command to create a new IBC Client as defined
// in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create // in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create
func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command { func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift]", Use: "create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift]",
Short: "create new tendermint client", Short: "create new tendermint client",
Long: "create new tendermint client. Trust level can be a fraction (eg: '1/3') or 'default'", Long: `Create a new tendermint IBC client.
- 'trust-level' flag can be a fraction (eg: '1/3') or 'default'
- 'proof-specs' flag can be a comma-separated list of strings (eg: 'ics23:simple,ics23:iavl') or 'default'`,
Example: fmt.Sprintf("%s tx ibc %s create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift] --trust-level default --from node0 --home ../node0/<app>cli --chain-id $CID", version.ClientName, ibctmtypes.SubModuleName), Example: fmt.Sprintf("%s tx ibc %s create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift] --trust-level default --from node0 --home ../node0/<app>cli --chain-id $CID", version.ClientName, ibctmtypes.SubModuleName),
Args: cobra.ExactArgs(5), Args: cobra.ExactArgs(5),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
@ -59,6 +66,7 @@ func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command {
var ( var (
trustLevel tmmath.Fraction trustLevel tmmath.Fraction
specs []*ics23.ProofSpec
err error err error
) )
@ -88,8 +96,20 @@ func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command {
return err return err
} }
spc := viper.GetString(flagProofSpecs)
// Currently supports SDK chain or simple kvstore tendermint chain
switch spc {
case "default":
specs = commitmenttypes.GetSDKSpecs()
case "simple":
specs = []*ics23.ProofSpec{ics23.TendermintSpec}
default:
return fmt.Errorf("proof Spec: %s not supported", spc)
}
msg := ibctmtypes.NewMsgCreateClient( msg := ibctmtypes.NewMsgCreateClient(
clientID, header, trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clientCtx.GetFromAddress(), clientID, header, trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, specs, clientCtx.GetFromAddress(),
) )
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {
@ -100,6 +120,7 @@ func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command {
}, },
} }
cmd.Flags().String(flagTrustLevel, "default", "light client trust level fraction for header updates") cmd.Flags().String(flagTrustLevel, "default", "light client trust level fraction for header updates")
cmd.Flags().String(flagProofSpecs, "default", "proof specs format to be used for verification")
return cmd return cmd
} }

View File

@ -3,6 +3,7 @@ package rest
import ( import (
"time" "time"
ics23 "github.com/confio/ics23/go"
"github.com/gorilla/mux" "github.com/gorilla/mux"
tmmath "github.com/tendermint/tendermint/libs/math" tmmath "github.com/tendermint/tendermint/libs/math"
@ -26,14 +27,15 @@ func RegisterRoutes(clientCtx client.Context, r *mux.Router, queryRoute string)
// CreateClientReq defines the properties of a create client request's body. // CreateClientReq defines the properties of a create client request's body.
type CreateClientReq struct { type CreateClientReq struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`
ClientID string `json:"client_id" yaml:"client_id"` ClientID string `json:"client_id" yaml:"client_id"`
ChainID string `json:"chain_id" yaml:"chain_id"` ChainID string `json:"chain_id" yaml:"chain_id"`
Header ibctmtypes.Header `json:"header" yaml:"header"` Header ibctmtypes.Header `json:"header" yaml:"header"`
TrustLevel tmmath.Fraction `json:"trust_level" yaml:"trust_level"` TrustLevel tmmath.Fraction `json:"trust_level" yaml:"trust_level"`
TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"`
UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"` UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"`
MaxClockDrift time.Duration `json:"max_clock_drift" yaml:"max_clock_drift"` MaxClockDrift time.Duration `json:"max_clock_drift" yaml:"max_clock_drift"`
ProofSpecs []*ics23.ProofSpec `json:"proof_specs" yaml:"proof_specs"`
} }
// UpdateClientReq defines the properties of a update client request's body. // UpdateClientReq defines the properties of a update client request's body.

View File

@ -52,7 +52,7 @@ func createClientHandlerFn(clientCtx client.Context) http.HandlerFunc {
msg := ibctmtypes.NewMsgCreateClient( msg := ibctmtypes.NewMsgCreateClient(
req.ClientID, req.Header, req.TrustLevel, req.ClientID, req.Header, req.TrustLevel,
req.TrustingPeriod, req.UnbondingPeriod, req.MaxClockDrift, req.TrustingPeriod, req.UnbondingPeriod, req.MaxClockDrift,
fromAddr, req.ProofSpecs, fromAddr,
) )
if err := msg.ValidateBasic(); err != nil { if err := msg.ValidateBasic(); err != nil {

View File

@ -49,7 +49,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
}{ }{
{ {
"valid misbehavior evidence", "valid misbehavior evidence",
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
ibctmtypes.Evidence{ ibctmtypes.Evidence{
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners), Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
@ -62,7 +62,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
}, },
{ {
"valid misbehavior at height greater than last consensusState", "valid misbehavior at height greater than last consensusState",
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
ibctmtypes.Evidence{ ibctmtypes.Evidence{
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners), Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
@ -75,7 +75,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
}, },
{ {
"consensus state's valset hash different from evidence should still pass", "consensus state's valset hash different from evidence should still pass",
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: suite.valSet}, ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: suite.valSet},
ibctmtypes.Evidence{ ibctmtypes.Evidence{
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners), Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
@ -88,7 +88,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
}, },
{ {
"first valset has too much change", "first valset has too much change",
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
ibctmtypes.Evidence{ ibctmtypes.Evidence{
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altSigners), Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altSigners),
@ -101,7 +101,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
}, },
{ {
"second valset has too much change", "second valset has too much change",
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
ibctmtypes.Evidence{ ibctmtypes.Evidence{
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners), Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
@ -114,7 +114,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
}, },
{ {
"both valsets have too much change", "both valsets have too much change",
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
ibctmtypes.Evidence{ ibctmtypes.Evidence{
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altSigners), Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altSigners),

View File

@ -3,6 +3,7 @@ package types
import ( import (
"time" "time"
ics23 "github.com/confio/ics23/go"
tmmath "github.com/tendermint/tendermint/libs/math" tmmath "github.com/tendermint/tendermint/libs/math"
lite "github.com/tendermint/tendermint/lite2" lite "github.com/tendermint/tendermint/lite2"
@ -46,6 +47,8 @@ type ClientState struct {
// Last Header that was stored by client // Last Header that was stored by client
LastHeader Header `json:"last_header" yaml:"last_header"` LastHeader Header `json:"last_header" yaml:"last_header"`
ProofSpecs []*ics23.ProofSpec `json:"proof_specs" yaml:"proof_specs"`
} }
// InitializeFromMsg creates a tendermint client state from a CreateClientMsg // InitializeFromMsg creates a tendermint client state from a CreateClientMsg
@ -53,7 +56,7 @@ func InitializeFromMsg(msg MsgCreateClient) (ClientState, error) {
return Initialize( return Initialize(
msg.GetClientID(), msg.TrustLevel, msg.GetClientID(), msg.TrustLevel,
msg.TrustingPeriod, msg.UnbondingPeriod, msg.MaxClockDrift, msg.TrustingPeriod, msg.UnbondingPeriod, msg.MaxClockDrift,
msg.Header, msg.Header, msg.ProofSpecs,
) )
} }
@ -62,17 +65,10 @@ func InitializeFromMsg(msg MsgCreateClient) (ClientState, error) {
func Initialize( func Initialize(
id string, trustLevel tmmath.Fraction, id string, trustLevel tmmath.Fraction,
trustingPeriod, ubdPeriod, maxClockDrift time.Duration, trustingPeriod, ubdPeriod, maxClockDrift time.Duration,
header Header, header Header, specs []*ics23.ProofSpec,
) (ClientState, error) { ) (ClientState, error) {
clientState := NewClientState(id, trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, specs)
if trustingPeriod >= ubdPeriod {
return ClientState{}, sdkerrors.Wrapf(
ErrInvalidTrustingPeriod,
"trusting period (%s) should be < unbonding period (%s)", trustingPeriod, ubdPeriod,
)
}
clientState := NewClientState(id, trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header)
return clientState, nil return clientState, nil
} }
@ -80,7 +76,7 @@ func Initialize(
func NewClientState( func NewClientState(
id string, trustLevel tmmath.Fraction, id string, trustLevel tmmath.Fraction,
trustingPeriod, ubdPeriod, maxClockDrift time.Duration, trustingPeriod, ubdPeriod, maxClockDrift time.Duration,
header Header, header Header, specs []*ics23.ProofSpec,
) ClientState { ) ClientState {
return ClientState{ return ClientState{
ID: id, ID: id,
@ -90,6 +86,7 @@ func NewClientState(
MaxClockDrift: maxClockDrift, MaxClockDrift: maxClockDrift,
LastHeader: header, LastHeader: header,
FrozenHeight: 0, FrozenHeight: 0,
ProofSpecs: specs,
} }
} }
@ -143,9 +140,31 @@ func (cs ClientState) Validate() error {
if cs.MaxClockDrift == 0 { if cs.MaxClockDrift == 0 {
return sdkerrors.Wrap(ErrInvalidMaxClockDrift, "max clock drift cannot be zero") return sdkerrors.Wrap(ErrInvalidMaxClockDrift, "max clock drift cannot be zero")
} }
if cs.TrustingPeriod >= cs.UnbondingPeriod {
return sdkerrors.Wrapf(
ErrInvalidTrustingPeriod,
"trusting period (%s) should be < unbonding period (%s)", cs.TrustingPeriod, cs.UnbondingPeriod,
)
}
// Validate ProofSpecs
if cs.ProofSpecs == nil {
return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof specs cannot be nil for tm client")
}
for _, spec := range cs.ProofSpecs {
if spec == nil {
return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof spec cannot be nil")
}
}
return cs.LastHeader.ValidateBasic(cs.GetChainID()) return cs.LastHeader.ValidateBasic(cs.GetChainID())
} }
// GetProofSpecs returns the format the client expects for proof verification
// as a string array specifying the proof type for each position in chained proof
func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec {
return cs.ProofSpecs
}
// VerifyClientConsensusState verifies a proof of the consensus state of the // VerifyClientConsensusState verifies a proof of the consensus state of the
// Tendermint client stored on the target machine. // Tendermint client stored on the target machine.
func (cs ClientState) VerifyClientConsensusState( func (cs ClientState) VerifyClientConsensusState(
@ -176,7 +195,7 @@ func (cs ClientState) VerifyClientConsensusState(
return err return err
} }
if err := merkleProof.VerifyMembership(provingRoot, path, bz); err != nil { if err := merkleProof.VerifyMembership(cs.ProofSpecs, provingRoot, path, bz); err != nil {
return sdkerrors.Wrap(clienttypes.ErrFailedClientConsensusStateVerification, err.Error()) return sdkerrors.Wrap(clienttypes.ErrFailedClientConsensusStateVerification, err.Error())
} }
@ -215,7 +234,7 @@ func (cs ClientState) VerifyConnectionState(
return err return err
} }
if err := merkleProof.VerifyMembership(consensusState.GetRoot(), path, bz); err != nil { if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil {
return sdkerrors.Wrap(clienttypes.ErrFailedConnectionStateVerification, err.Error()) return sdkerrors.Wrap(clienttypes.ErrFailedConnectionStateVerification, err.Error())
} }
@ -255,7 +274,7 @@ func (cs ClientState) VerifyChannelState(
return err return err
} }
if err := merkleProof.VerifyMembership(consensusState.GetRoot(), path, bz); err != nil { if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil {
return sdkerrors.Wrap(clienttypes.ErrFailedChannelStateVerification, err.Error()) return sdkerrors.Wrap(clienttypes.ErrFailedChannelStateVerification, err.Error())
} }
@ -286,7 +305,7 @@ func (cs ClientState) VerifyPacketCommitment(
return err return err
} }
if err := merkleProof.VerifyMembership(consensusState.GetRoot(), path, commitmentBytes); err != nil { if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, commitmentBytes); err != nil {
return sdkerrors.Wrap(clienttypes.ErrFailedPacketCommitmentVerification, err.Error()) return sdkerrors.Wrap(clienttypes.ErrFailedPacketCommitmentVerification, err.Error())
} }
@ -317,7 +336,7 @@ func (cs ClientState) VerifyPacketAcknowledgement(
return err return err
} }
if err := merkleProof.VerifyMembership(consensusState.GetRoot(), path, channeltypes.CommitAcknowledgement(acknowledgement)); err != nil { if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, channeltypes.CommitAcknowledgement(acknowledgement)); err != nil {
return sdkerrors.Wrap(clienttypes.ErrFailedPacketAckVerification, err.Error()) return sdkerrors.Wrap(clienttypes.ErrFailedPacketAckVerification, err.Error())
} }
@ -348,7 +367,7 @@ func (cs ClientState) VerifyPacketAcknowledgementAbsence(
return err return err
} }
if err := merkleProof.VerifyNonMembership(consensusState.GetRoot(), path); err != nil { if err := merkleProof.VerifyNonMembership(cs.ProofSpecs, consensusState.GetRoot(), path); err != nil {
return sdkerrors.Wrap(clienttypes.ErrFailedPacketAckAbsenceVerification, err.Error()) return sdkerrors.Wrap(clienttypes.ErrFailedPacketAckAbsenceVerification, err.Error())
} }
@ -380,7 +399,7 @@ func (cs ClientState) VerifyNextSequenceRecv(
bz := sdk.Uint64ToBigEndian(nextSequenceRecv) bz := sdk.Uint64ToBigEndian(nextSequenceRecv)
if err := merkleProof.VerifyMembership(consensusState.GetRoot(), path, bz); err != nil { if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil {
return sdkerrors.Wrap(clienttypes.ErrFailedNextSeqRecvVerification, err.Error()) return sdkerrors.Wrap(clienttypes.ErrFailedNextSeqRecvVerification, err.Error())
} }

View File

@ -27,37 +27,37 @@ func (suite *TendermintTestSuite) TestValidate() {
}{ }{
{ {
name: "valid client", name: "valid client",
clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
expPass: true, expPass: true,
}, },
{ {
name: "invalid client id", name: "invalid client id",
clientState: ibctmtypes.NewClientState("(testClientID)", lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState("(testClientID)", lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
expPass: false, expPass: false,
}, },
{ {
name: "invalid trust level", name: "invalid trust level",
clientState: ibctmtypes.NewClientState(testClientID, tmmath.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(testClientID, tmmath.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
expPass: false, expPass: false,
}, },
{ {
name: "invalid trusting period", name: "invalid trusting period",
clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
expPass: false, expPass: false,
}, },
{ {
name: "invalid unbonding period", name: "invalid unbonding period",
clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
expPass: false, expPass: false,
}, },
{ {
name: "invalid max clock drift", name: "invalid max clock drift",
clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, suite.header), clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, suite.header, commitmenttypes.GetSDKSpecs()),
expPass: false, expPass: false,
}, },
{ {
name: "invalid header", name: "invalid header",
clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}), clientState: ibctmtypes.NewClientState(testClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
expPass: false, expPass: false,
}, },
} }
@ -84,7 +84,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
// FIXME: uncomment // FIXME: uncomment
// { // {
// name: "successful verification", // name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, chainID, height), // clientState: ibctmtypes.NewClientState(chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
// consensusState: ibctmtypes.ConsensusState{ // consensusState: ibctmtypes.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), // Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
// }, // },
@ -93,7 +93,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
// }, // },
{ {
name: "ApplyPrefix failed", name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
}, },
@ -102,7 +102,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
}, },
{ {
name: "latest client height < height", name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
}, },
@ -120,7 +120,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
}, },
{ {
name: "proof verification failed", name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
ValidatorSet: suite.valSet, ValidatorSet: suite.valSet,
@ -162,7 +162,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
// FIXME: uncomment // FIXME: uncomment
// { // {
// name: "successful verification", // name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, chainID, height), // clientState: ibctmtypes.NewClientState(chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
// connection: conn, // connection: conn,
// consensusState: ibctmtypes.ConsensusState{ // consensusState: ibctmtypes.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), // Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -172,7 +172,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
// }, // },
{ {
name: "ApplyPrefix failed", name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
connection: conn, connection: conn,
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -182,7 +182,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
}, },
{ {
name: "latest client height < height", name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
connection: conn, connection: conn,
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -202,7 +202,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
}, },
{ {
name: "proof verification failed", name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
connection: conn, connection: conn,
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -245,7 +245,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
// FIXME: uncomment // FIXME: uncomment
// { // {
// name: "successful verification", // name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, height), // clientState: ibctmtypes.NewClientState(chainID, height, commitmenttypes.GetSDKSpecs()),
// connection: conn, // connection: conn,
// consensusState: ibctmtypes.ConsensusState{ // consensusState: ibctmtypes.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), // Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -255,7 +255,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
// }, // },
{ {
name: "ApplyPrefix failed", name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
channel: ch, channel: ch,
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -265,7 +265,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
}, },
{ {
name: "latest client height < height", name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
channel: ch, channel: ch,
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -285,7 +285,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
}, },
{ {
name: "proof verification failed", name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
channel: ch, channel: ch,
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -325,7 +325,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
// FIXME: uncomment // FIXME: uncomment
// { // {
// name: "successful verification", // name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, height), // clientState: ibctmtypes.NewClientState(chainID, height, commitmenttypes.GetSDKSpecs()),
// connection: conn, // connection: conn,
// consensusState: ibctmtypes.ConsensusState{ // consensusState: ibctmtypes.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), // Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -335,7 +335,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
// }, // },
{ {
name: "ApplyPrefix failed", name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
commitment: []byte{}, commitment: []byte{},
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -345,7 +345,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
}, },
{ {
name: "latest client height < height", name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
commitment: []byte{}, commitment: []byte{},
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -365,7 +365,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
}, },
{ {
name: "proof verification failed", name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
commitment: []byte{}, commitment: []byte{},
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -405,7 +405,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
// FIXME: uncomment // FIXME: uncomment
// { // {
// name: "successful verification", // name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, chainID, height), // clientState: ibctmtypes.NewClientState(chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
// connection: conn, // connection: conn,
// consensusState: ibctmtypes.ConsensusState{ // consensusState: ibctmtypes.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), // Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -415,7 +415,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
// }, // },
{ {
name: "ApplyPrefix failed", name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ack: []byte{}, ack: []byte{},
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -425,7 +425,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
}, },
{ {
name: "latest client height < height", name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ack: []byte{}, ack: []byte{},
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -445,7 +445,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
}, },
{ {
name: "proof verification failed", name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
ack: []byte{}, ack: []byte{},
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -484,7 +484,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
// FIXME: uncomment // FIXME: uncomment
// { // {
// name: "successful verification", // name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, chainID, height), // clientState: ibctmtypes.NewClientState(chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
// connection: conn, // connection: conn,
// consensusState: ibctmtypes.ConsensusState{ // consensusState: ibctmtypes.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), // Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -494,7 +494,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
// }, // },
{ {
name: "ApplyPrefix failed", name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
}, },
@ -503,7 +503,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
}, },
{ {
name: "latest client height < height", name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
}, },
@ -521,7 +521,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
}, },
{ {
name: "proof verification failed", name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
ValidatorSet: suite.valSet, ValidatorSet: suite.valSet,
@ -559,7 +559,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
// FIXME: uncomment // FIXME: uncomment
// { // {
// name: "successful verification", // name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, chainID, height), // clientState: ibctmtypes.NewClientState(chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
// connection: conn, // connection: conn,
// consensusState: ibctmtypes.ConsensusState{ // consensusState: ibctmtypes.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), // Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
@ -569,7 +569,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
// }, // },
{ {
name: "ApplyPrefix failed", name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
}, },
@ -578,7 +578,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
}, },
{ {
name: "latest client height < height", name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
}, },
@ -596,7 +596,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
}, },
{ {
name: "proof verification failed", name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{ consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash), Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
ValidatorSet: suite.valSet, ValidatorSet: suite.valSet,

View File

@ -16,4 +16,5 @@ var (
ErrInvalidMaxClockDrift = sdkerrors.Register(SubModuleName, 5, "invalid max clock drift") ErrInvalidMaxClockDrift = sdkerrors.Register(SubModuleName, 5, "invalid max clock drift")
ErrTrustingPeriodExpired = sdkerrors.Register(SubModuleName, 6, "time since latest trusted state has passed the trusting period") ErrTrustingPeriodExpired = sdkerrors.Register(SubModuleName, 6, "time since latest trusted state has passed the trusting period")
ErrUnbondingPeriodExpired = sdkerrors.Register(SubModuleName, 7, "time since latest trusted state has passed the unbonding period") ErrUnbondingPeriodExpired = sdkerrors.Register(SubModuleName, 7, "time since latest trusted state has passed the unbonding period")
ErrInvalidProofSpecs = sdkerrors.Register(SubModuleName, 8, "invalid proof specs")
) )

View File

@ -3,6 +3,7 @@ package types
import ( import (
"time" "time"
ics23 "github.com/confio/ics23/go"
tmmath "github.com/tendermint/tendermint/libs/math" tmmath "github.com/tendermint/tendermint/libs/math"
lite "github.com/tendermint/tendermint/lite2" lite "github.com/tendermint/tendermint/lite2"
@ -30,13 +31,14 @@ var (
// MsgCreateClient defines a message to create an IBC client // MsgCreateClient defines a message to create an IBC client
type MsgCreateClient struct { type MsgCreateClient struct {
ClientID string `json:"client_id" yaml:"client_id"` ClientID string `json:"client_id" yaml:"client_id"`
Header Header `json:"header" yaml:"header"` Header Header `json:"header" yaml:"header"`
TrustLevel tmmath.Fraction `json:"trust_level" yaml:"trust_level"` TrustLevel tmmath.Fraction `json:"trust_level" yaml:"trust_level"`
TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"`
UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"` UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"`
MaxClockDrift time.Duration `json:"max_clock_drift" yaml:"max_clock_drift"` MaxClockDrift time.Duration `json:"max_clock_drift" yaml:"max_clock_drift"`
Signer sdk.AccAddress `json:"address" yaml:"address"` ProofSpecs []*ics23.ProofSpec `json:"proof_specs" yaml:"proof_specs"`
Signer sdk.AccAddress `json:"address" yaml:"address"`
} }
// this is a constant to satisfy the linter // this is a constant to satisfy the linter
@ -50,7 +52,8 @@ func (msg MsgCreateClient) ProtoMessage() {}
// NewMsgCreateClient creates a new MsgCreateClient instance // NewMsgCreateClient creates a new MsgCreateClient instance
func NewMsgCreateClient( func NewMsgCreateClient(
id string, header Header, trustLevel tmmath.Fraction, id string, header Header, trustLevel tmmath.Fraction,
trustingPeriod, unbondingPeriod, maxClockDrift time.Duration, signer sdk.AccAddress, trustingPeriod, unbondingPeriod, maxClockDrift time.Duration,
specs []*ics23.ProofSpec, signer sdk.AccAddress,
) MsgCreateClient { ) MsgCreateClient {
return MsgCreateClient{ return MsgCreateClient{
@ -60,6 +63,7 @@ func NewMsgCreateClient(
TrustingPeriod: trustingPeriod, TrustingPeriod: trustingPeriod,
UnbondingPeriod: unbondingPeriod, UnbondingPeriod: unbondingPeriod,
MaxClockDrift: maxClockDrift, MaxClockDrift: maxClockDrift,
ProofSpecs: specs,
Signer: signer, Signer: signer,
} }
} }
@ -95,6 +99,21 @@ func (msg MsgCreateClient) ValidateBasic() error {
if err := msg.Header.ValidateBasic(msg.Header.ChainID); err != nil { if err := msg.Header.ValidateBasic(msg.Header.ChainID); err != nil {
return sdkerrors.Wrapf(ErrInvalidHeader, "header failed validatebasic with its own chain-id: %v", err) return sdkerrors.Wrapf(ErrInvalidHeader, "header failed validatebasic with its own chain-id: %v", err)
} }
if msg.TrustingPeriod >= msg.UnbondingPeriod {
return sdkerrors.Wrapf(
ErrInvalidTrustingPeriod,
"trusting period (%s) should be < unbonding period (%s)", msg.TrustingPeriod, msg.UnbondingPeriod,
)
}
// Validate ProofSpecs
if msg.ProofSpecs == nil {
return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof specs cannot be nil")
}
for _, spec := range msg.ProofSpecs {
if spec == nil {
return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof spec cannot be nil")
}
}
return host.ClientIdentifierValidator(msg.ClientID) return host.ClientIdentifierValidator(msg.ClientID)
} }

View File

@ -1,6 +1,7 @@
package types_test package types_test
import ( import (
ics23 "github.com/confio/ics23/go"
"github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/libs/math" "github.com/tendermint/tendermint/libs/math"
lite "github.com/tendermint/tendermint/lite2" lite "github.com/tendermint/tendermint/lite2"
@ -9,6 +10,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
) )
func (suite *TendermintTestSuite) TestMsgCreateClientValidateBasic() { func (suite *TendermintTestSuite) TestMsgCreateClientValidateBasic() {
@ -22,14 +24,15 @@ func (suite *TendermintTestSuite) TestMsgCreateClientValidateBasic() {
expPass bool expPass bool
errMsg string errMsg string
}{ }{
{ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, signer), true, "success msg should pass"}, {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, commitmenttypes.GetSDKSpecs(), signer), true, "success msg should pass"},
{ibctmtypes.NewMsgCreateClient("(BADCHAIN)", suite.header, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, signer), false, "invalid client id passed"}, {ibctmtypes.NewMsgCreateClient("(BADCHAIN)", suite.header, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, commitmenttypes.GetSDKSpecs(), signer), false, "invalid client id passed"},
{ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, math.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, signer), false, "invalid trust level"}, {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, math.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, commitmenttypes.GetSDKSpecs(), signer), false, "invalid trust level"},
{ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, signer), false, "zero trusting period passed"}, {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, commitmenttypes.GetSDKSpecs(), signer), false, "zero trusting period passed"},
{ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, signer), false, "zero unbonding period passed"}, {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, commitmenttypes.GetSDKSpecs(), signer), false, "zero unbonding period passed"},
{ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, nil), false, "Empty address passed"}, {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, commitmenttypes.GetSDKSpecs(), nil), false, "Empty address passed"},
{ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, ibctmtypes.Header{}, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, signer), false, "nil header"}, {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, ibctmtypes.Header{}, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, commitmenttypes.GetSDKSpecs(), signer), false, "nil header"},
{ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, invalidHeader, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, signer), false, "invalid header"}, {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, invalidHeader, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, commitmenttypes.GetSDKSpecs(), signer), false, "invalid header"},
{ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, suite.header, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, []*ics23.ProofSpec{nil}, signer), false, "invalid proof specs"},
} }
for i, tc := range cases { for i, tc := range cases {

View File

@ -54,7 +54,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "successful update with next height and same validator set", name: "successful update with next height and same validator set",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers) newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers)
currentTime = suite.now currentTime = suite.now
}, },
@ -63,7 +63,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "successful update with future height and different validator set", name: "successful update with future height and different validator set",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
newHeader = ibctmtypes.CreateTestHeader(chainID, height+5, suite.headerTime, bothValSet, bothSigners) newHeader = ibctmtypes.CreateTestHeader(chainID, height+5, suite.headerTime, bothValSet, bothSigners)
currentTime = suite.now currentTime = suite.now
}, },
@ -72,7 +72,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "unsuccessful update with next height: update header mismatches nextValSetHash", name: "unsuccessful update with next height: update header mismatches nextValSetHash",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, bothValSet, bothSigners) newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, bothValSet, bothSigners)
currentTime = suite.now currentTime = suite.now
}, },
@ -81,7 +81,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "unsuccessful update with future height: too much change in validator set", name: "unsuccessful update with future height: too much change in validator set",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
newHeader = ibctmtypes.CreateTestHeader(chainID, height+5, suite.headerTime, altValSet, altSigners) newHeader = ibctmtypes.CreateTestHeader(chainID, height+5, suite.headerTime, altValSet, altSigners)
currentTime = suite.now currentTime = suite.now
}, },
@ -90,7 +90,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "unsuccessful update: trusting period has passed since last client timestamp", name: "unsuccessful update: trusting period has passed since last client timestamp",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers) newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers)
// make current time pass trusting period from last timestamp on clientstate // make current time pass trusting period from last timestamp on clientstate
currentTime = suite.now.Add(ubdPeriod) currentTime = suite.now.Add(ubdPeriod)
@ -100,7 +100,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "unsuccessful update: header timestamp is past current timestamp", name: "unsuccessful update: header timestamp is past current timestamp",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.now.Add(time.Minute), suite.valSet, signers) newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.now.Add(time.Minute), suite.valSet, signers)
currentTime = suite.now currentTime = suite.now
}, },
@ -109,7 +109,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "unsuccessful update: header timestamp is not past last client timestamp", name: "unsuccessful update: header timestamp is not past last client timestamp",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.clientTime, suite.valSet, signers) newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.clientTime, suite.valSet, signers)
currentTime = suite.now currentTime = suite.now
}, },
@ -118,7 +118,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "header basic validation failed", name: "header basic validation failed",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers) newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers)
// cause new header to fail validatebasic by changing commit height to mismatch header height // cause new header to fail validatebasic by changing commit height to mismatch header height
newHeader.SignedHeader.Commit.Height = height - 1 newHeader.SignedHeader.Commit.Height = height - 1
@ -129,7 +129,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
{ {
name: "header height < latest client height", name: "header height < latest client height",
setup: func() { setup: func() {
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header) clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
// Make new header at height less than latest client state // Make new header at height less than latest client state
newHeader = ibctmtypes.CreateTestHeader(chainID, height-1, suite.headerTime, suite.valSet, signers) newHeader = ibctmtypes.CreateTestHeader(chainID, height-1, suite.headerTime, suite.valSet, signers)
currentTime = suite.now currentTime = suite.now

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"strings" "strings"
ics23 "github.com/confio/ics23/go"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -74,6 +75,11 @@ func (cs ClientState) Validate() error {
return host.ClientIdentifierValidator(cs.ID) return host.ClientIdentifierValidator(cs.ID)
} }
// GetProofSpecs returns nil since localhost does not have to verify proofs
func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec {
return nil
}
// VerifyClientConsensusState verifies a proof of the consensus // VerifyClientConsensusState verifies a proof of the consensus
// state of the loop-back client. // state of the loop-back client.
// VerifyClientConsensusState verifies a proof of the consensus state of the // VerifyClientConsensusState verifies a proof of the consensus state of the

View File

@ -1,5 +1,7 @@
package exported package exported
import ics23 "github.com/confio/ics23/go"
// ICS 023 Types Implementation // ICS 023 Types Implementation
// //
// This file includes types defined under // This file includes types defined under
@ -39,8 +41,8 @@ type Path interface {
// Proofs includes key but value is provided dynamically at the verification time. // Proofs includes key but value is provided dynamically at the verification time.
type Proof interface { type Proof interface {
GetCommitmentType() Type GetCommitmentType() Type
VerifyMembership(Root, Path, []byte) error VerifyMembership([]*ics23.ProofSpec, Root, Path, []byte) error
VerifyNonMembership(Root, Path) error VerifyNonMembership([]*ics23.ProofSpec, Root, Path) error
Empty() bool Empty() bool
ValidateBasic() error ValidateBasic() error

View File

@ -26,3 +26,15 @@ func (pth *KeyPath) String() string {
} }
return res return res
} }
// GetKey returns the bytes representation of key at given index
// Passing in a positive index return the key at index in forward order
// from the highest key to the lowest key
// Passing in a negative index will return the key at index in reverse order
// from the lowest key to the highest key. This is the order for proof verification,
// since we prove lowest key first before moving to key of higher subtrees
func (pth *KeyPath) GetKey(i int) []byte {
total := len(pth.Keys)
index := (total + i) % total
return pth.Keys[index].name
}

View File

@ -1,9 +1,10 @@
package types package types
import ( import (
"bytes"
"net/url" "net/url"
"github.com/cosmos/cosmos-sdk/store/rootmulti" ics23 "github.com/confio/ics23/go"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/exported" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/exported"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
@ -11,6 +12,9 @@ import (
"github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/merkle"
) )
// var representing the proofspecs for a SDK chain
var sdkSpecs = []*ics23.ProofSpec{ics23.IavlSpec, ics23.TendermintSpec}
// ICS 023 Merkle Types Implementation // ICS 023 Merkle Types Implementation
// //
// This file defines Merkle commitment types that implements ICS 023. // This file defines Merkle commitment types that implements ICS 023.
@ -19,6 +23,11 @@ import (
// Applied on SDK-based IBC implementation // Applied on SDK-based IBC implementation
var _ exported.Root = (*MerkleRoot)(nil) var _ exported.Root = (*MerkleRoot)(nil)
// GetSDKSpecs is a getter function for the proofspecs of an sdk chain
func GetSDKSpecs() []*ics23.ProofSpec {
return sdkSpecs
}
// NewMerkleRoot constructs a new MerkleRoot // NewMerkleRoot constructs a new MerkleRoot
func NewMerkleRoot(hash []byte) MerkleRoot { func NewMerkleRoot(hash []byte) MerkleRoot {
return MerkleRoot{ return MerkleRoot{
@ -128,23 +137,230 @@ func (MerkleProof) GetCommitmentType() exported.Type {
} }
// VerifyMembership verifies the membership pf a merkle proof against the given root, path, and value. // VerifyMembership verifies the membership pf a merkle proof against the given root, path, and value.
func (proof MerkleProof) VerifyMembership(root exported.Root, path exported.Path, value []byte) error { func (proof MerkleProof) VerifyMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, value []byte) error {
if proof.Empty() || root == nil || root.Empty() || path == nil || path.Empty() || len(value) == 0 { if err := proof.validateVerificationArgs(specs, root); err != nil {
return sdkerrors.Wrap(ErrInvalidMerkleProof, "empty params or proof") return err
} }
runtime := rootmulti.DefaultProofRuntime() // VerifyMembership specific argument validation
return runtime.VerifyValue(proof.Proof, root.GetHash(), path.String(), value) mpath, ok := path.(MerklePath)
if !ok {
return sdkerrors.Wrapf(ErrInvalidProof, "path %v is not of type MerkleProof", path)
}
if len(mpath.KeyPath.Keys) != len(specs) {
return sdkerrors.Wrapf(ErrInvalidProof, "path length %d not same as proof %d",
len(mpath.KeyPath.Keys), len(specs))
}
if len(value) == 0 {
return sdkerrors.Wrap(ErrInvalidProof, "empty value in membership proof")
}
// Convert Proof to []CommitmentProof
proofs, err := convertProofs(proof)
if err != nil {
return err
}
// Since every proof in chain is a membership proof we can chain from index 0
if err := verifyChainedMembershipProof(root.GetHash(), specs, proofs, mpath.KeyPath, value, 0); err != nil {
return err
}
return nil
} }
// VerifyNonMembership verifies the absence of a merkle proof against the given root and path. // VerifyNonMembership verifies the absence of a merkle proof against the given root and path.
func (proof MerkleProof) VerifyNonMembership(root exported.Root, path exported.Path) error { // VerifyNonMembership verifies a chained proof where the absence of a given path is proven
if proof.Empty() || root == nil || root.Empty() || path == nil || path.Empty() { // at the lowest subtree and then each subtree's inclusion is proved up to the final root.
return sdkerrors.Wrap(ErrInvalidMerkleProof, "empty params or proof") func (proof MerkleProof) VerifyNonMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path) error {
if err := proof.validateVerificationArgs(specs, root); err != nil {
return err
} }
runtime := rootmulti.DefaultProofRuntime() // VerifyNonMembership specific argument validation
return runtime.VerifyAbsence(proof.Proof, root.GetHash(), path.String()) mpath, ok := path.(MerklePath)
if !ok {
return sdkerrors.Wrapf(ErrInvalidProof, "path %v is not of type MerkleProof", path)
}
if len(mpath.KeyPath.Keys) != len(specs) {
return sdkerrors.Wrapf(ErrInvalidProof, "path length %d not same as proof %d",
len(mpath.KeyPath.Keys), len(specs))
}
// Convert Proof to []CommitmentProof
proofs, err := convertProofs(proof)
if err != nil {
return err
}
// VerifyNonMembership will verify the absence of key in lowest subtree, and then chain inclusion proofs
// of all subroots up to final root
subroot, err := proofs[0].Calculate()
if err != nil {
sdkerrors.Wrapf(ErrInvalidProof, "could not calculate root for proof index 0. %v", err)
}
key := mpath.KeyPath.GetKey(-1)
if ok := ics23.VerifyNonMembership(specs[0], subroot, proofs[0], key); !ok {
return sdkerrors.Wrapf(ErrInvalidProof, "could not verify absence of key %s", string(key))
}
// Verify chained membership proof starting from index 1 with value = subroot
if err := verifyChainedMembershipProof(root.GetHash(), specs, proofs, mpath.KeyPath, subroot, 1); err != nil {
return err
}
return nil
}
// BatchVerifyMembership verifies a group of key value pairs against the given root
// NOTE: All items must be part of a batch proof in the first chained proof, i.e. items must all be part of smallest subtree in the chained proof
// NOTE: The path passed in must be the path from the root to the smallest subtree in the chained proof
// NOTE: Untested
func (proof MerkleProof) BatchVerifyMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, items map[string][]byte) error {
if err := proof.validateVerificationArgs(specs, root); err != nil {
return err
}
// Convert Proof to []CommitmentProof
proofs, err := convertProofs(proof)
if err != nil {
return err
}
// VerifyNonMembership will verify the absence of key in lowest subtree, and then chain inclusion proofs
// of all subroots up to final root
subroot, err := proofs[0].Calculate()
if err != nil {
sdkerrors.Wrapf(ErrInvalidProof, "could not calculate root for proof index 0. %v", err)
}
if ok := ics23.BatchVerifyMembership(specs[0], subroot, proofs[0], items); !ok {
return sdkerrors.Wrapf(ErrInvalidProof, "could not verify batch items")
}
// BatchVerifyMembership specific argument validation
// Path must only be defined if this is a chained proof
if len(specs) > 1 {
mpath, ok := path.(MerklePath)
if !ok {
return sdkerrors.Wrapf(ErrInvalidProof, "path %v is not of type MerkleProof", path)
}
// path length should be one less than specs, since lowest proof keys are in items
if len(mpath.KeyPath.Keys) != len(specs)-1 {
return sdkerrors.Wrapf(ErrInvalidProof, "path length %d not same as proof %d",
len(mpath.KeyPath.Keys), len(specs))
}
// Since BatchedProof path does not include lowest subtree, exclude first proof from specs and proofs and start
// chaining at index 0
if err := verifyChainedMembershipProof(root.GetHash(), specs[1:], proofs[1:], mpath.KeyPath, subroot, 0); err != nil {
return err
}
} else if !bytes.Equal(root.GetHash(), subroot) {
// Since we are not chaining proofs, we must check first subroot equals given root
return sdkerrors.Wrapf(ErrInvalidProof, "batched proof did not commit to expected root: %X, got: %X", root.GetHash(), subroot)
}
return nil
}
// BatchVerifyNonMembership verifies absence of a group of keys against the given root
// NOTE: All items must be part of a batch proof in the first chained proof, i.e. items must all be part of smallest subtree in the chained proof
// NOTE: The path passed in must be the path from the root to the smallest subtree in the chained proof
// NOTE: Untested
func (proof MerkleProof) BatchVerifyNonMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, items [][]byte) error {
if err := proof.validateVerificationArgs(specs, root); err != nil {
return err
}
// Convert Proof to []CommitmentProof
proofs, err := convertProofs(proof)
if err != nil {
return err
}
// VerifyNonMembership will verify the absence of key in lowest subtree, and then chain inclusion proofs
// of all subroots up to final root
subroot, err := proofs[0].Calculate()
if err != nil {
sdkerrors.Wrapf(ErrInvalidProof, "could not calculate root for proof index 0. %v", err)
}
if ok := ics23.BatchVerifyNonMembership(specs[0], subroot, proofs[0], items); !ok {
return sdkerrors.Wrapf(ErrInvalidProof, "could not verify batch items")
}
// BatchVerifyNonMembership specific argument validation
// Path must only be defined if this is a chained proof
if len(specs) > 1 {
mpath, ok := path.(MerklePath)
if !ok {
return sdkerrors.Wrapf(ErrInvalidProof, "path %v is not of type MerkleProof", path)
}
// path length should be one less than specs, since lowest proof keys are in items
if len(mpath.KeyPath.Keys) != len(specs)-1 {
return sdkerrors.Wrapf(ErrInvalidProof, "path length %d not same as proof %d",
len(mpath.KeyPath.Keys), len(specs))
}
// Since BatchedProof path does not include lowest subtree, exclude first proof from specs and proofs and start
// chaining at index 0
if err := verifyChainedMembershipProof(root.GetHash(), specs[1:], proofs[1:], mpath.KeyPath, subroot, 0); err != nil {
return err
}
} else if !bytes.Equal(root.GetHash(), subroot) {
// Since we are not chaining proofs, we must check first subroot equals given root
return sdkerrors.Wrapf(ErrInvalidProof, "batched proof did not commit to expected root: %X, got: %X", root.GetHash(), subroot)
}
return nil
}
// verifyChainedMembershipProof takes a list of proofs and specs and verifies each proof sequentially ensuring that the value is committed to
// by first proof and each subsequent subroot is committed to by the next subroot and checking that the final calculated root is equal to the given roothash.
// The proofs and specs are passed in from lowest subtree to the highest subtree, but the keys are passed in from highest subtree to lowest.
// The index specifies what index to start chaining the membership proofs, this is useful since the lowest proof may not be a membership proof, thus we
// will want to start the membership proof chaining from index 1 with value being the lowest subroot
func verifyChainedMembershipProof(root []byte, specs []*ics23.ProofSpec, proofs []*ics23.CommitmentProof, keys KeyPath, value []byte, index int) error {
var (
subroot []byte
err error
)
// Initialize subroot to value since the proofs list may be empty.
// This may happen if this call is verifying intermediate proofs after the lowest proof has been executed.
// In this case, there may be no intermediate proofs to verify and we just check that lowest proof root equals final root
subroot = value
for i := index; i < len(proofs); i++ {
subroot, err = proofs[i].Calculate()
if err != nil {
return sdkerrors.Wrapf(ErrInvalidProof, "could not calculate proof root at index %d. %v", i, err)
}
// Since keys are passed in from highest to lowest, we must grab their indices in reverse order
// from the proofs and specs which are lowest to highest
key := keys.GetKey(-1 * (i + 1))
if ok := ics23.VerifyMembership(specs[i], subroot, proofs[i], key, value); !ok {
return sdkerrors.Wrapf(ErrInvalidProof, "chained membership proof failed to verify membership of value: %X in subroot %X at index %d",
value, subroot, i)
}
// Set value to subroot so that we verify next proof in chain commits to this subroot
value = subroot
}
// Check that chained proof root equals passed-in root
if !bytes.Equal(root, subroot) {
return sdkerrors.Wrapf(ErrInvalidProof, "proof did not commit to expected root: %X, got: %X", root, subroot)
}
return nil
}
// convertProofs converts a MerkleProof into []*ics23.CommitmentProof
func convertProofs(mproof MerkleProof) ([]*ics23.CommitmentProof, error) {
// Unmarshal all proof ops to CommitmentProof
proofs := make([]*ics23.CommitmentProof, len(mproof.Proof.Ops))
for i, op := range mproof.Proof.Ops {
var p ics23.CommitmentProof
err := p.Unmarshal(op.Data)
if err != nil {
return nil, sdkerrors.Wrapf(ErrInvalidMerkleProof, "could not unmarshal proof op into CommitmentProof at index: %d", i)
}
proofs[i] = &p
}
return proofs, nil
} }
// Empty returns true if the root is empty // Empty returns true if the root is empty
@ -159,3 +375,23 @@ func (proof MerkleProof) ValidateBasic() error {
} }
return nil return nil
} }
// validateVerificationArgs verifies the proof arguments are valid
func (proof MerkleProof) validateVerificationArgs(specs []*ics23.ProofSpec, root exported.Root) error {
if proof.Empty() || root == nil || root.Empty() {
return sdkerrors.Wrap(ErrInvalidMerkleProof, "empty params or proof")
}
if len(specs) != len(proof.Proof.Ops) {
return sdkerrors.Wrapf(ErrInvalidMerkleProof,
"length of specs: %d not equal to length of proof: %d",
len(specs), len(proof.Proof.Ops))
}
for i, spec := range specs {
if spec == nil {
return sdkerrors.Wrapf(ErrInvalidProof, "spec at position %d is nil", i)
}
}
return nil
}

View File

@ -9,6 +9,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/merkle"
) )
func (suite *MerkleTestSuite) TestVerifyMembership() { func (suite *MerkleTestSuite) TestVerifyMembership() {
@ -33,27 +34,38 @@ func (suite *MerkleTestSuite) TestVerifyMembership() {
root []byte root []byte
pathArr []string pathArr []string
value []byte value []byte
malleate func()
shouldPass bool shouldPass bool
}{ }{
{"valid proof", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), true}, // valid proof {"valid proof", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, true}, // valid proof
{"wrong value", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("WRONGVALUE"), false}, // invalid proof with wrong value {"wrong value", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("WRONGVALUE"), func() {}, false}, // invalid proof with wrong value
{"nil value", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte(nil), false}, // invalid proof with nil value {"nil value", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte(nil), func() {}, false}, // invalid proof with nil value
{"wrong key", cid.Hash, []string{suite.storeKey.Name(), "NOTMYKEY"}, []byte("MYVALUE"), false}, // invalid proof with wrong key {"wrong key", cid.Hash, []string{suite.storeKey.Name(), "NOTMYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong key
{"wrong path 1", cid.Hash, []string{suite.storeKey.Name(), "MYKEY", "MYKEY"}, []byte("MYVALUE"), false}, // invalid proof with wrong path {"wrong path 1", cid.Hash, []string{suite.storeKey.Name(), "MYKEY", "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path
{"wrong path 2", cid.Hash, []string{suite.storeKey.Name()}, []byte("MYVALUE"), false}, // invalid proof with wrong path {"wrong path 2", cid.Hash, []string{suite.storeKey.Name()}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path
{"wrong path 3", cid.Hash, []string{"MYKEY"}, []byte("MYVALUE"), false}, // invalid proof with wrong path {"wrong path 3", cid.Hash, []string{"MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path
{"wrong storekey", cid.Hash, []string{"otherStoreKey", "MYKEY"}, []byte("MYVALUE"), false}, // invalid proof with wrong store prefix {"wrong storekey", cid.Hash, []string{"otherStoreKey", "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong store prefix
{"wrong root", []byte("WRONGROOT"), []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), false}, // invalid proof with wrong root {"wrong root", []byte("WRONGROOT"), []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong root
{"nil root", []byte(nil), []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), false}, // invalid proof with nil root {"nil root", []byte(nil), []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with nil root
{"proof is wrong length", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {
proof = types.MerkleProof{
Proof: &merkle.Proof{
Ops: res.Proof.Ops[1:],
},
}
}, false}, // invalid proof with wrong length
} }
for i, tc := range cases { for i, tc := range cases {
tc := tc tc := tc
suite.Run(tc.name, func() { suite.Run(tc.name, func() {
tc.malleate()
root := types.NewMerkleRoot(tc.root) root := types.NewMerkleRoot(tc.root)
path := types.NewMerklePath(tc.pathArr) path := types.NewMerklePath(tc.pathArr)
err := proof.VerifyMembership(&root, path, tc.value) err := proof.VerifyMembership(types.GetSDKSpecs(), &root, path, tc.value)
if tc.shouldPass { if tc.shouldPass {
// nolint: scopelint // nolint: scopelint
@ -88,27 +100,38 @@ func (suite *MerkleTestSuite) TestVerifyNonMembership() {
name string name string
root []byte root []byte
pathArr []string pathArr []string
malleate func()
shouldPass bool shouldPass bool
}{ }{
{"valid proof", cid.Hash, []string{suite.storeKey.Name(), "MYABSENTKEY"}, true}, // valid proof {"valid proof", cid.Hash, []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, true}, // valid proof
{"wrong key", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, false}, // invalid proof with existent key {"wrong key", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, func() {}, false}, // invalid proof with existent key
{"wrong path 1", cid.Hash, []string{suite.storeKey.Name(), "MYKEY", "MYABSENTKEY"}, false}, // invalid proof with wrong path {"wrong path 1", cid.Hash, []string{suite.storeKey.Name(), "MYKEY", "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong path
{"wrong path 2", cid.Hash, []string{suite.storeKey.Name(), "MYABSENTKEY", "MYKEY"}, false}, // invalid proof with wrong path {"wrong path 2", cid.Hash, []string{suite.storeKey.Name(), "MYABSENTKEY", "MYKEY"}, func() {}, false}, // invalid proof with wrong path
{"wrong path 3", cid.Hash, []string{suite.storeKey.Name()}, false}, // invalid proof with wrong path {"wrong path 3", cid.Hash, []string{suite.storeKey.Name()}, func() {}, false}, // invalid proof with wrong path
{"wrong path 4", cid.Hash, []string{"MYABSENTKEY"}, false}, // invalid proof with wrong path {"wrong path 4", cid.Hash, []string{"MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong path
{"wrong storeKey", cid.Hash, []string{"otherStoreKey", "MYABSENTKEY"}, false}, // invalid proof with wrong store prefix {"wrong storeKey", cid.Hash, []string{"otherStoreKey", "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong store prefix
{"wrong root", []byte("WRONGROOT"), []string{suite.storeKey.Name(), "MYABSENTKEY"}, false}, // invalid proof with wrong root {"wrong root", []byte("WRONGROOT"), []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong root
{"nil root", []byte(nil), []string{suite.storeKey.Name(), "MYABSENTKEY"}, false}, // invalid proof with nil root {"nil root", []byte(nil), []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, false}, // invalid proof with nil root
{"proof is wrong length", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, func() {
proof = types.MerkleProof{
Proof: &merkle.Proof{
Ops: res.Proof.Ops[1:],
},
}
}, false}, // invalid proof with wrong length
} }
for i, tc := range cases { for i, tc := range cases {
tc := tc tc := tc
suite.Run(tc.name, func() { suite.Run(tc.name, func() {
tc.malleate()
root := types.NewMerkleRoot(tc.root) root := types.NewMerkleRoot(tc.root)
path := types.NewMerklePath(tc.pathArr) path := types.NewMerklePath(tc.pathArr)
err := proof.VerifyNonMembership(&root, path) err := proof.VerifyNonMembership(types.GetSDKSpecs(), &root, path)
if tc.shouldPass { if tc.shouldPass {
// nolint: scopelint // nolint: scopelint

View File

@ -1,65 +0,0 @@
package commitment
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
)
// CalculateRoot returns the application Hash at the curretn block height as a commitment
// root for proof verification.
func CalculateRoot(ctx sdk.Context) exported.Root {
root := types.NewMerkleRoot(ctx.BlockHeader().AppHash)
return &root
}
// BatchVerifyMembership verifies a proof that many paths have been set to
// specific values in a commitment. It calls the proof's VerifyMembership method
// with the calculated root and the provided paths.
// Returns false on the first failed membership verification.
func BatchVerifyMembership(
ctx sdk.Context,
proof exported.Proof,
prefix exported.Prefix,
items map[string][]byte,
) error {
root := CalculateRoot(ctx)
for pathStr, value := range items {
path, err := types.ApplyPrefix(prefix, pathStr)
if err != nil {
return err
}
if err := proof.VerifyMembership(root, path, value); err != nil {
return err
}
}
return nil
}
// BatchVerifyNonMembership verifies a proof that many paths have not been set
// to any value in a commitment. It calls the proof's VerifyNonMembership method
// with the calculated root and the provided paths.
// Returns false on the first failed non-membership verification.
func BatchVerifyNonMembership(
ctx sdk.Context,
proof exported.Proof,
prefix exported.Prefix,
paths []string,
) error {
root := CalculateRoot(ctx)
for _, pathStr := range paths {
path, err := types.ApplyPrefix(prefix, pathStr)
if err != nil {
return err
}
if err := proof.VerifyNonMembership(root, path); err != nil {
return err
}
}
return nil
}

View File

@ -243,7 +243,7 @@ func (chain *TestChain) CreateClient(client *TestChain) error {
ctxTarget := chain.GetContext() ctxTarget := chain.GetContext()
// create client // create client
clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header) clientState, err := ibctmtypes.Initialize(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs())
if err != nil { if err != nil {
return err return err
} }
@ -311,7 +311,7 @@ func (chain *TestChain) updateClient(client *TestChain) {
ctxTarget, client.ClientID, uint64(client.Header.Height-1), consensusState, ctxTarget, client.ClientID, uint64(client.Header.Height-1), consensusState,
) )
chain.App.IBCKeeper.ClientKeeper.SetClientState( chain.App.IBCKeeper.ClientKeeper.SetClientState(
ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header), ctxTarget, ibctmtypes.NewClientState(client.ClientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, client.Header, commitmenttypes.GetSDKSpecs()),
) )
// _, _, err := simapp.SignCheckDeliver( // _, _, err := simapp.SignCheckDeliver(

View File

@ -30,7 +30,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
genState: ibc.GenesisState{ genState: ibc.GenesisState{
ClientGenesis: client.NewGenesisState( ClientGenesis: client.NewGenesisState(
[]exported.ClientState{ []exported.ClientState{
ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
localhosttypes.NewClientState("chaindID", 10), localhosttypes.NewClientState("chaindID", 10),
}, },
[]client.ConsensusStates{ []client.ConsensusStates{
@ -86,7 +86,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
genState: ibc.GenesisState{ genState: ibc.GenesisState{
ClientGenesis: client.NewGenesisState( ClientGenesis: client.NewGenesisState(
[]exported.ClientState{ []exported.ClientState{
ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header), ibctmtypes.NewClientState(clientID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
localhosttypes.NewClientState("(chaindID)", 0), localhosttypes.NewClientState("(chaindID)", 0),
}, },
nil, nil,

View File

@ -246,7 +246,7 @@ func (chain *TestChain) CreateTMClient(counterparty *TestChain, clientID string)
msg := ibctmtypes.NewMsgCreateClient( msg := ibctmtypes.NewMsgCreateClient(
clientID, counterparty.LastHeader, clientID, counterparty.LastHeader,
DefaultTrustLevel, TrustingPeriod, UnbondingPeriod, MaxClockDrift, DefaultTrustLevel, TrustingPeriod, UnbondingPeriod, MaxClockDrift,
chain.SenderAccount.GetAddress(), commitmenttypes.GetSDKSpecs(), chain.SenderAccount.GetAddress(),
) )
return chain.SendMsg(msg) return chain.SendMsg(msg)