From 46d228a8f3e86d250b3031134e70e120932b3c68 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 7 Jun 2019 23:47:01 +0200 Subject: [PATCH 001/182] add client --- x/ibc/02-client/manager.go | 146 ++++++++++++++++++++++++++++ x/ibc/02-client/tendermint/types.go | 79 +++++++++++++++ x/ibc/02-client/types.go | 46 +++++++++ 3 files changed, 271 insertions(+) create mode 100644 x/ibc/02-client/manager.go create mode 100644 x/ibc/02-client/tendermint/types.go create mode 100644 x/ibc/02-client/types.go diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go new file mode 100644 index 000000000000..89a8a878df49 --- /dev/null +++ b/x/ibc/02-client/manager.go @@ -0,0 +1,146 @@ +package client + +import ( + "errors" + "strconv" + + "github.com/cosmos/cosmos-sdk/store/mapping" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string + +func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { + id := mapping.NewInteger(v, mapping.Dec).Incr(ctx) + return strconv.FormatUint(id, 10) +} + +type Manager struct { + protocol mapping.Mapping + + idval mapping.Value + idgen IDGenerator +} + +func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { + return Manager{ + protocol: mapping.NewMapping(protocol, []byte("/")), + idval: mapping.NewValue(free, []byte("/id")), + idgen: idgen, + } +} + +/* +func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { + if _, ok := man.pred[kind]; ok { + panic("Kind already registered") + } + man.pred[kind] = pred + return man +} +*/ +func (man Manager) object(id string) Object { + return Object{ + id: id, + client: man.protocol.Value([]byte(id)), + freeze: mapping.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + } +} + +func (man Manager) Create(ctx sdk.Context, cs Client) string { + id := man.idgen(ctx, man.idval) + err := man.object(id).create(ctx, cs) + if err != nil { + panic(err) + } + return id +} + +func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { + res := man.object(id) + if !res.exists(ctx) { + return Object{}, errors.New("client not exists") + } + return res, nil +} + +type Object struct { + id string + client mapping.Value + freeze mapping.Boolean +} + +func (obj Object) create(ctx sdk.Context, st Client) error { + if obj.exists(ctx) { + return errors.New("Create client on already existing id") + } + obj.client.Set(ctx, st) + return nil +} + +func (obj Object) exists(ctx sdk.Context) bool { + return obj.client.Exists(ctx) +} + +func (obj Object) ID() string { + return obj.id +} + +func (obj Object) Value(ctx sdk.Context) (res Client) { + obj.client.Get(ctx, &res) + return +} + +func (obj Object) Is(ctx sdk.Context, client Client) bool { + return obj.client.Is(ctx, client) +} + +func (obj Object) Update(ctx sdk.Context, header Header) error { + if !obj.exists(ctx) { + panic("should not update nonexisting client") + } + + if obj.freeze.Get(ctx) { + return errors.New("client is frozen") + } + + var stored Client + obj.client.GetIfExists(ctx, &stored) + updated, err := stored.Validate(header) + if err != nil { + return err + } + + obj.client.Set(ctx, updated) + + return nil +} + +func (obj Object) Freeze(ctx sdk.Context) error { + if !obj.exists(ctx) { + panic("should not freeze nonexisting client") + } + + if obj.freeze.Get(ctx) { + return errors.New("client is already frozen") + } + + obj.freeze.Set(ctx, true) + + return nil +} + +func (obj Object) Delete(ctx sdk.Context) error { + if !obj.exists(ctx) { + panic("should not delete nonexisting client") + } + + if !obj.freeze.Get(ctx) { + return errors.New("client is not frozen") + } + + obj.client.Delete(ctx) + obj.freeze.Delete(ctx) + + return nil +} diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go new file mode 100644 index 000000000000..54655cf702d4 --- /dev/null +++ b/x/ibc/02-client/tendermint/types.go @@ -0,0 +1,79 @@ +package tendermint + +import ( + "bytes" + + "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +// Ref tendermint/lite/base_verifier.go + +var _ client.ValidityPredicateBase = ValidityPredicateBase{} + +type ValidityPredicateBase struct { + Height int64 + NextValidatorSet *types.ValidatorSet +} + +func (ValidityPredicateBase) Kind() client.Kind { + return client.Tendermint +} + +func (base ValidityPredicateBase) GetHeight() int64 { + return base.Height +} + +func (base ValidityPredicateBase) Equal(cbase client.ValidityPredicateBase) bool { + base0, ok := cbase.(ValidityPredicateBase) + if !ok { + return false + } + return base.Height == base0.Height && + bytes.Equal(base.NextValidatorSet.Hash(), base0.NextValidatorSet.Hash()) +} + +var _ client.Client = Client{} + +type Client struct { + Base ValidityPredicateBase + Root commitment.Root +} + +func (Client) Kind() client.Kind { + return client.Tendermint +} + +func (client Client) GetBase() client.ValidityPredicateBase { + return client.Base +} + +func (client Client) GetRoot() commitment.Root { + return client.Root +} + +func (client Client) Validate(header client.Header) (client.Client, error) { + return client, nil // XXX +} + +var _ client.Header = Header{} + +type Header struct { + Base ValidityPredicateBase + Root commitment.Root + Votes []*types.CommitSig +} + +func (header Header) Kind() client.Kind { + return client.Tendermint +} + +func (header Header) GetBase() client.ValidityPredicateBase { + return header.Base +} + +func (header Header) GetRoot() commitment.Root { + return header.Root +} diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go new file mode 100644 index 000000000000..7b9f81ec7789 --- /dev/null +++ b/x/ibc/02-client/types.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +// TODO: types in this file should be (de/)serialized with proto in the future + +type AminoMarshaler interface { + MarshalAmino() (string, error) + UnmarshalAmino(string) error +} + +type ValidityPredicateBase interface { + Kind() Kind + GetHeight() int64 + Equal(ValidityPredicateBase) bool +} + +// ConsensusState +type Client interface { + Kind() Kind + GetBase() ValidityPredicateBase + GetRoot() commitment.Root + Validate(Header) (Client, error) // ValidityPredicate +} + +func Equal(client1, client2 Client) bool { + return client1.Kind() == client2.Kind() && + client1.GetBase().Equal(client2.GetBase()) +} + +type Header interface { + Kind() Kind + // Proof() HeaderProof + GetBase() ValidityPredicateBase // can be nil + GetRoot() commitment.Root +} + +// XXX: Kind should be enum? + +type Kind byte + +const ( + Tendermint Kind = iota +) From 65a904a80964500bc127606c96df68fd6365c838 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:14:19 +0200 Subject: [PATCH 002/182] add counterpartymanager --- x/ibc/02-client/manager.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 89a8a878df49..97f281cc9596 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -6,6 +6,8 @@ import ( "github.com/cosmos/cosmos-sdk/store/mapping" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string @@ -24,12 +26,22 @@ type Manager struct { func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/")), - idval: mapping.NewValue(free, []byte("/id")), + protocol: mapping.NewMapping(protocol, []byte("/client")), + idval: mapping.NewValue(free, []byte("/client/id")), idgen: idgen, } } +type CounterpartyManager struct { + protocol commitment.Mapping +} + +func NewCounterpartyManager(protocol commitment.Base) CounterpartyManager { + return CounterpartyManager{ + protocol: commitment.NewMapping(protocol, []byte("/client")), + } +} + /* func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { if _, ok := man.pred[kind]; ok { From 070e7d0df3574292c9913bafb9dab8e39043f5c6 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:29:24 +0200 Subject: [PATCH 003/182] fix manager --- x/ibc/02-client/manager.go | 16 ++++++++++++++++ x/ibc/23-commitment/value.go | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 97f281cc9596..c22576b18cd2 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -76,12 +76,28 @@ func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { return res, nil } +func (man CounterpartyManager) object(id string) CounterObject { + return CounterObject{ + id: id, + client: man.protocol.Value([]byte(id)), + } +} + +func (man CounterpartyManager) Query(id string) CounterObject { + return man.object(id) +} + type Object struct { id string client mapping.Value freeze mapping.Boolean } +type CounterObject struct { + id string + client commitment.Value +} + func (obj Object) create(ctx sdk.Context, st Client) error { if obj.exists(ctx) { return errors.New("Create client on already existing id") diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index 70b8502a44e6..10b409b28b99 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -45,6 +45,13 @@ func NewMapping(base Base, prefix []byte) Mapping { } } +func (m Mapping) Value(key []byte) Value { + return Value{ + base: m.base, + key: key, + } +} + type Value struct { base Base key []byte From 99ad6d48153f93774da37ffdb2f57c8742d96545 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:44:25 +0200 Subject: [PATCH 004/182] add Is() to counterobject --- x/ibc/02-client/manager.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index c22576b18cd2..502478104757 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -123,6 +123,10 @@ func (obj Object) Is(ctx sdk.Context, client Client) bool { return obj.client.Is(ctx, client) } +func (obj CounterObject) Is(ctx sdk.Context, client Client) bool { + return obj.client.Is(ctx, client) +} + func (obj Object) Update(ctx sdk.Context, header Header) error { if !obj.exists(ctx) { panic("should not update nonexisting client") From 9956f0e310375b73e68e0e16c3404b156c38a090 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 12 Jun 2019 00:08:04 +0200 Subject: [PATCH 005/182] add readme, reflect ICS02 revision --- x/ibc/02-client/README.md | 49 ++++++++++++++++++++++++++++++++++++++ x/ibc/02-client/manager.go | 31 ++++++++++-------------- x/ibc/02-client/types.go | 26 ++++++++------------ 3 files changed, 72 insertions(+), 34 deletions(-) create mode 100644 x/ibc/02-client/README.md diff --git a/x/ibc/02-client/README.md b/x/ibc/02-client/README.md new file mode 100644 index 000000000000..a9bd6892771b --- /dev/null +++ b/x/ibc/02-client/README.md @@ -0,0 +1,49 @@ +# ICS 02: Client + +Package `client` defines types and method to store and update light clients which tracks on other chain's state. +The main type is `Client`, which provides `commitment.Root` to verify state proofs and `ConsensusState` to +verify header proofs. + +## Spec + +```typescript +interface ConsensusState { + height: uint64 + root: CommitmentRoot + validityPredicate: ValidityPredicate + eqivocationPredicate: EquivocationPredicate +} + +interface ClientState { + consensusState: ConsensusState + verifiedRoots: Map + frozen: bool +} + +interface Header { + height: uint64 + proof: HeaderProof + state: Maybe[ConsensusState] + root: CommitmentRoot +} + +type ValidityPredicate = (ConsensusState, Header) => Error | ConsensusState + +type EquivocationPredicate = (ConsensusState, Header, Header) => bool +``` + +## Impl + +### types.go + +`spec: interface ConsensusState` is implemented by `type ConsensusState`. `ConsensusState.{GetHeight(), GetRoot(), +Validate(), Equivocation()}` each corresponds to `spec: ConsensusState.{height, root, validityPredicate, +equivocationPredicate}`. `ConsensusState.Kind()` returns `Kind`, which is an enum indicating the type of the +consensus algorithm. + +`spec: interface Header` is implemented by `type Header`. `Header{GetHeight(), Proof(), State(), GetRoot()}` +each corresponds to `spec: Header.{height, proof, state, root}`. + +### manager.go + +`spec: interface ClientState` is implemented by `type Object`. // TODO diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 502478104757..0134d8340d55 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -10,6 +10,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) +// XXX: implement spec: ClientState.verifiedRoots + type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { @@ -59,13 +61,14 @@ func (man Manager) object(id string) Object { } } -func (man Manager) Create(ctx sdk.Context, cs Client) string { +func (man Manager) Create(ctx sdk.Context, cs ConsensusState) (Object, error) { id := man.idgen(ctx, man.idval) - err := man.object(id).create(ctx, cs) - if err != nil { - panic(err) + obj := man.object(id) + if obj.exists(ctx) { + return Object{}, errors.New("Create client on already existing id") } - return id + obj.client.Set(ctx, cs) + return obj, nil } func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { @@ -89,7 +92,7 @@ func (man CounterpartyManager) Query(id string) CounterObject { type Object struct { id string - client mapping.Value + client mapping.Value // ConsensusState freeze mapping.Boolean } @@ -98,14 +101,6 @@ type CounterObject struct { client commitment.Value } -func (obj Object) create(ctx sdk.Context, st Client) error { - if obj.exists(ctx) { - return errors.New("Create client on already existing id") - } - obj.client.Set(ctx, st) - return nil -} - func (obj Object) exists(ctx sdk.Context) bool { return obj.client.Exists(ctx) } @@ -114,16 +109,16 @@ func (obj Object) ID() string { return obj.id } -func (obj Object) Value(ctx sdk.Context) (res Client) { +func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { obj.client.Get(ctx, &res) return } -func (obj Object) Is(ctx sdk.Context, client Client) bool { +func (obj Object) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } -func (obj CounterObject) Is(ctx sdk.Context, client Client) bool { +func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } @@ -136,7 +131,7 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { return errors.New("client is frozen") } - var stored Client + var stored ConsensusState obj.client.GetIfExists(ctx, &stored) updated, err := stored.Validate(header) if err != nil { diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go index 7b9f81ec7789..2ae484853354 100644 --- a/x/ibc/02-client/types.go +++ b/x/ibc/02-client/types.go @@ -5,35 +5,29 @@ import ( ) // TODO: types in this file should be (de/)serialized with proto in the future - -type AminoMarshaler interface { - MarshalAmino() (string, error) - UnmarshalAmino(string) error -} - -type ValidityPredicateBase interface { - Kind() Kind - GetHeight() int64 - Equal(ValidityPredicateBase) bool -} +// currently amkno codec handles it // ConsensusState -type Client interface { +type ConsensusState interface { Kind() Kind - GetBase() ValidityPredicateBase + GetHeight() uint64 GetRoot() commitment.Root - Validate(Header) (Client, error) // ValidityPredicate + Validate(Header) (ConsensusState, error) // ValidityPredicate + Equivocation(Header, Header) bool // EquivocationPredicate } -func Equal(client1, client2 Client) bool { +/* +func Equal(client1, client2 ConsensusState) bool { return client1.Kind() == client2.Kind() && client1.GetBase().Equal(client2.GetBase()) } +*/ type Header interface { Kind() Kind + GetHeight() uint64 // Proof() HeaderProof - GetBase() ValidityPredicateBase // can be nil + State() ConsensusState // can be nil GetRoot() commitment.Root } From 5f6391876a476f1d1beb75d8677716cfc67ee1e2 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 12 Jun 2019 00:28:13 +0200 Subject: [PATCH 006/182] reflect downstream ics --- x/ibc/02-client/manager.go | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 0134d8340d55..196d62e62fdc 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -4,7 +4,7 @@ import ( "errors" "strconv" - "github.com/cosmos/cosmos-sdk/store/mapping" + "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" @@ -12,24 +12,24 @@ import ( // XXX: implement spec: ClientState.verifiedRoots -type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string +type IDGenerator func(sdk.Context /*Header,*/, state.Value) string -func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { - id := mapping.NewInteger(v, mapping.Dec).Incr(ctx) +func IntegerIDGenerator(ctx sdk.Context, v state.Value) string { + id := state.NewInteger(v, state.Dec).Incr(ctx) return strconv.FormatUint(id, 10) } type Manager struct { - protocol mapping.Mapping + protocol state.Mapping - idval mapping.Value + idval state.Value idgen IDGenerator } -func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { +func NewManager(protocol, free state.Base, idgen IDGenerator) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/client")), - idval: mapping.NewValue(free, []byte("/client/id")), + protocol: state.NewMapping(protocol, []byte("/client")), + idval: state.NewValue(free, []byte("/client/id")), idgen: idgen, } } @@ -57,7 +57,7 @@ func (man Manager) object(id string) Object { return Object{ id: id, client: man.protocol.Value([]byte(id)), - freeze: mapping.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + freeze: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), } } @@ -92,8 +92,8 @@ func (man CounterpartyManager) Query(id string) CounterObject { type Object struct { id string - client mapping.Value // ConsensusState - freeze mapping.Boolean + client state.Value // ConsensusState + freeze state.Boolean } type CounterObject struct { @@ -114,10 +114,6 @@ func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { return } -func (obj Object) Is(ctx sdk.Context, client ConsensusState) bool { - return obj.client.Is(ctx, client) -} - func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } From ab3e4e6412a32f71e2a4a41e55a86adf324cd111 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 13 Jun 2019 16:00:18 +0200 Subject: [PATCH 007/182] test in progress --- x/ibc/02-client/tendermint/types.go | 96 ++++++----- x/ibc/02-client/tendermint/types_test.go | 131 ++++++++++++++ x/ibc/02-client/tendermint/valset_test.go | 197 ++++++++++++++++++++++ x/ibc/02-client/types.go | 3 - 4 files changed, 386 insertions(+), 41 deletions(-) create mode 100644 x/ibc/02-client/tendermint/types_test.go create mode 100644 x/ibc/02-client/tendermint/valset_test.go diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 54655cf702d4..1442d91d6c99 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -2,78 +2,98 @@ package tendermint import ( "bytes" + "errors" + "fmt" + lerr "github.com/tendermint/tendermint/lite/errors" "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -// Ref tendermint/lite/base_verifier.go - -var _ client.ValidityPredicateBase = ValidityPredicateBase{} +var _ client.ConsensusState = ConsensusState{} -type ValidityPredicateBase struct { - Height int64 +// Ref tendermint/lite/base_verifier.go +type ConsensusState struct { + ChainID string + Height uint64 + Root commitment.Root NextValidatorSet *types.ValidatorSet } -func (ValidityPredicateBase) Kind() client.Kind { +func (ConsensusState) Kind() client.Kind { return client.Tendermint } -func (base ValidityPredicateBase) GetHeight() int64 { - return base.Height +func (cs ConsensusState) GetHeight() uint64 { + return cs.Height } -func (base ValidityPredicateBase) Equal(cbase client.ValidityPredicateBase) bool { - base0, ok := cbase.(ValidityPredicateBase) - if !ok { - return false +func (cs ConsensusState) GetRoot() commitment.Root { + return cs.Root +} + +func (cs ConsensusState) update(header Header) ConsensusState { + return ConsensusState{ + ChainID: cs.ChainID, + Height: uint64(header.Height), + Root: header.AppHash, + NextValidatorSet: header.NextValidatorSet, } - return base.Height == base0.Height && - bytes.Equal(base.NextValidatorSet.Hash(), base0.NextValidatorSet.Hash()) } -var _ client.Client = Client{} +func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, error) { + header, ok := cheader.(Header) + if !ok { + return nil, errors.New("invalid type") + } -type Client struct { - Base ValidityPredicateBase - Root commitment.Root -} + nextvalset := cs.NextValidatorSet + nexthash := nextvalset.Hash() -func (Client) Kind() client.Kind { - return client.Tendermint -} + if cs.Height == uint64(header.Height-1) { + nexthash = cs.NextValidatorSet.Hash() + if !bytes.Equal(header.ValidatorsHash, nexthash) { + fmt.Println(111) + return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) + } + } -func (client Client) GetBase() client.ValidityPredicateBase { - return client.Base -} + if !bytes.Equal(header.NextValidatorsHash, header.NextValidatorSet.Hash()) { + fmt.Println(header) + return nil, lerr.ErrUnexpectedValidators(header.NextValidatorsHash, header.NextValidatorSet.Hash()) + } + + err := header.ValidateBasic(cs.ChainID) + if err != nil { + return nil, err + } -func (client Client) GetRoot() commitment.Root { - return client.Root + err = cs.NextValidatorSet.VerifyCommit(cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) + if err != nil { + return nil, err + } + + return cs.update(header), nil } -func (client Client) Validate(header client.Header) (client.Client, error) { - return client, nil // XXX +func (cs ConsensusState) Equivocation(header1, header2 client.Header) bool { + return false // XXX } var _ client.Header = Header{} type Header struct { - Base ValidityPredicateBase - Root commitment.Root - Votes []*types.CommitSig + // XXX: don't take the entire struct + types.SignedHeader + NextValidatorSet *types.ValidatorSet } func (header Header) Kind() client.Kind { return client.Tendermint } -func (header Header) GetBase() client.ValidityPredicateBase { - return header.Base -} - -func (header Header) GetRoot() commitment.Root { - return header.Root +func (header Header) GetHeight() uint64 { + return uint64(header.Height) } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go new file mode 100644 index 000000000000..44dc0fc9aba9 --- /dev/null +++ b/x/ibc/02-client/tendermint/types_test.go @@ -0,0 +1,131 @@ +package tendermint + +import ( + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/tendermint/tendermint/abci/types" + dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/libs/log" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store" + stypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const chainid = "testchain" + +func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { + key := sdk.NewKVStoreKey("ibc") + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) + err := cms.LoadLatestVersion() + if err != nil { + panic(err) + } + ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger()) + cdc := codec.New() + return key, ctx, cms, cdc +} + +type node struct { + valset MockValidators + + cms sdk.CommitMultiStore + store sdk.KVStore + + commits []tmtypes.SignedHeader +} + +func NewNode(valset MockValidators) *node { + key, ctx, cms, _ := defaultComponents() + return &node{ + valset: valset, + cms: cms, + store: ctx.KVStore(key), + commits: nil, + } +} + +func (node *node) last() tmtypes.SignedHeader { + if len(node.commits) == 0 { + return tmtypes.SignedHeader{} + } + return node.commits[len(node.commits)-1] +} + +func (node *node) Commit() tmtypes.SignedHeader { + valsethash := node.valset.ValidatorSet().Hash() + nextvalset := node.valset.Mutate(false) + nextvalsethash := nextvalset.ValidatorSet().Hash() + commitid := node.cms.Commit() + + header := tmtypes.Header{ + ChainID: chainid, + Height: int64(len(node.commits) + 1), + LastBlockID: tmtypes.BlockID{ + Hash: node.last().Header.Hash(), + }, + + ValidatorsHash: valsethash, + NextValidatorsHash: nextvalsethash, + AppHash: commitid.Hash, + } + + commit := node.valset.Sign(header) + + node.commits = append(node.commits, commit) + + return commit +} + +func (node *node) Set(key, value string) { + node.store.Set(append([]byte{0x00}, []byte(key)...), []byte(value)) +} + +type Verifier struct { + ConsensusState +} + +func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifier { + return &Verifier{ + ConsensusState{ + ChainID: chainid, + Height: uint64(header.Height), + Root: header.AppHash, + NextValidatorSet: nextvalset.ValidatorSet(), + }, + } +} + +func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidators) error { + newcs, err := v.ConsensusState.Validate( + Header{ + SignedHeader: header, + NextValidatorSet: nextvalset.ValidatorSet(), + }, + ) + if err != nil { + return err + } + v.ConsensusState = newcs.(ConsensusState) + + return nil +} + +func TestUpdate(t *testing.T) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + verifier := NewVerifier(node.last(), node.valset) + + header := node.Commit() + + err := verifier.Validate(header, node.valset) + require.NoError(t, err) +} diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/valset_test.go new file mode 100644 index 000000000000..10aa5dc0eae7 --- /dev/null +++ b/x/ibc/02-client/tendermint/valset_test.go @@ -0,0 +1,197 @@ +package tendermint + +import ( + "bytes" + "fmt" + "sort" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + tmtypes "github.com/tendermint/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// reimplementing tmtypes.MockPV to make it marshallable +type mockPV struct { + PrivKey crypto.PrivKey +} + +var _ tmtypes.PrivValidator = (*mockPV)(nil) + +func newMockPV() *mockPV { + return &mockPV{ed25519.GenPrivKey()} +} + +func (pv *mockPV) GetAddress() tmtypes.Address { + return pv.PrivKey.PubKey().Address() +} + +func (pv *mockPV) GetPubKey() crypto.PubKey { + return pv.PrivKey.PubKey() +} + +func (pv *mockPV) SignVote(chainID string, vote *tmtypes.Vote) error { + signBytes := vote.SignBytes(chainID) + sig, err := pv.PrivKey.Sign(signBytes) + if err != nil { + return err + } + vote.Signature = sig + return nil +} + +func (pv *mockPV) SignProposal(string, *tmtypes.Proposal) error { + panic("not needed") +} + +// MockValset +type MockValidator struct { + MockPV *mockPV + Power sdk.Dec +} + +func NewMockValidator(power sdk.Dec) MockValidator { + return MockValidator{ + MockPV: newMockPV(), + Power: power, + } +} + +func (val MockValidator) GetOperator() sdk.ValAddress { + return sdk.ValAddress(val.MockPV.GetAddress()) +} + +func (val MockValidator) GetConsAddr() sdk.ConsAddress { + return sdk.GetConsAddress(val.MockPV.GetPubKey()) +} + +func (val MockValidator) GetConsPubKey() crypto.PubKey { + return val.MockPV.GetPubKey() +} + +func (val MockValidator) GetPower() sdk.Dec { + return val.Power +} + +func (val MockValidator) Validator() *tmtypes.Validator { + return tmtypes.NewValidator( + val.GetConsPubKey(), + val.GetPower().RoundInt64(), + ) +} + +type MockValidators []MockValidator + +var _ sort.Interface = MockValidators{} + +func NewMockValidators(num int, power int64) MockValidators { + res := make(MockValidators, num) + for i := range res { + res[i] = NewMockValidator(sdk.NewDec(power)) + } + + // ddd + fmt.Println(333) + for _, val := range res { + fmt.Println(val) + } + + // ddd + return res +} + +func (vals MockValidators) Len() int { + return len(vals) +} + +func (vals MockValidators) Less(i, j int) bool { + return bytes.Compare([]byte(vals[i].GetConsAddr()), []byte(vals[j].GetConsAddr())) == -1 +} + +func (vals MockValidators) Swap(i, j int) { + it := vals[j] + vals[j] = vals[i] + vals[i] = it +} + +func (vals MockValidators) TotalPower() sdk.Dec { + res := sdk.ZeroDec() + for _, val := range vals { + res = res.Add(val.Power) + } + return res +} + +func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { + precommits := make([]*tmtypes.CommitSig, len(vals)) + for i, val := range vals { + precommits[i] = (&tmtypes.Vote{ + BlockID: tmtypes.BlockID{ + Hash: header.Hash(), + }, + ValidatorAddress: val.MockPV.GetAddress(), + ValidatorIndex: i, + Height: header.Height, + Type: tmtypes.PrecommitType, + }).CommitSig() + val.MockPV.SignVote("", (*tmtypes.Vote)(precommits[i])) + } + + return tmtypes.SignedHeader{ + Header: &header, + Commit: &tmtypes.Commit{ + BlockID: tmtypes.BlockID{ + Hash: header.Hash(), + }, + Precommits: precommits, + }, + } +} + +// Mutate valset +func (vals MockValidators) Mutate(majority bool) MockValidators { + var num int + if majority { + num = len(vals) * 2 / 3 + } else { + num = len(vals) * 1 / 6 + } + + res := make(MockValidators, len(vals)) + + for i := 0; i < len(vals)-num; i++ { + res[i] = vals[num:][i] + } + + for i := len(vals) - num; i < len(vals); i++ { + res[i] = NewMockValidator(vals[0].Power) + } + + // ddd + fmt.Println(333) + for _, val := range res { + fmt.Println(val) + } + + // ddd + + return res +} + +func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { + tmvals := make([]*tmtypes.Validator, len(vals)) + + for i, val := range vals { + tmvals[i] = val.Validator() + } + + // ddd + fmt.Println(333444) + for _, val := range tmvals { + fmt.Println(val) + } + + // ddd + return tmtypes.NewValidatorSet(tmvals) +} diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go index 2ae484853354..2a34855085b9 100644 --- a/x/ibc/02-client/types.go +++ b/x/ibc/02-client/types.go @@ -26,9 +26,6 @@ func Equal(client1, client2 ConsensusState) bool { type Header interface { Kind() Kind GetHeight() uint64 - // Proof() HeaderProof - State() ConsensusState // can be nil - GetRoot() commitment.Root } // XXX: Kind should be enum? From e7dde7881baf8bef52661b3260b03f50019ed363 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 13 Jun 2019 19:08:13 +0200 Subject: [PATCH 008/182] add test --- x/ibc/02-client/tendermint/types.go | 6 +- x/ibc/02-client/tendermint/types_test.go | 108 +++++++++++++++++++--- x/ibc/02-client/tendermint/valset_test.go | 46 +++------ 3 files changed, 114 insertions(+), 46 deletions(-) diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 1442d91d6c99..8dd3cfca7294 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -3,7 +3,6 @@ package tendermint import ( "bytes" "errors" - "fmt" lerr "github.com/tendermint/tendermint/lite/errors" "github.com/tendermint/tendermint/types" @@ -55,13 +54,11 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, if cs.Height == uint64(header.Height-1) { nexthash = cs.NextValidatorSet.Hash() if !bytes.Equal(header.ValidatorsHash, nexthash) { - fmt.Println(111) return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) } } if !bytes.Equal(header.NextValidatorsHash, header.NextValidatorSet.Hash()) { - fmt.Println(header) return nil, lerr.ErrUnexpectedValidators(header.NextValidatorsHash, header.NextValidatorSet.Hash()) } @@ -70,7 +67,7 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, return nil, err } - err = cs.NextValidatorSet.VerifyCommit(cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) + err = cs.NextValidatorSet.VerifyFutureCommit(header.ValidatorSet, cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) if err != nil { return nil, err } @@ -87,6 +84,7 @@ var _ client.Header = Header{} type Header struct { // XXX: don't take the entire struct types.SignedHeader + ValidatorSet *types.ValidatorSet NextValidatorSet *types.ValidatorSet } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 44dc0fc9aba9..14ca7adad0ea 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -1,11 +1,13 @@ package tendermint import ( + "math/rand" "testing" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" tmtypes "github.com/tendermint/tendermint/types" @@ -14,6 +16,9 @@ import ( "github.com/cosmos/cosmos-sdk/store" stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) const chainid = "testchain" @@ -33,7 +38,8 @@ func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *c } type node struct { - valset MockValidators + prevvalset MockValidators + valset MockValidators cms sdk.CommitMultiStore store sdk.KVStore @@ -60,7 +66,7 @@ func (node *node) last() tmtypes.SignedHeader { func (node *node) Commit() tmtypes.SignedHeader { valsethash := node.valset.ValidatorSet().Hash() - nextvalset := node.valset.Mutate(false) + nextvalset := node.valset.Mutate() nextvalsethash := nextvalset.ValidatorSet().Hash() commitid := node.cms.Commit() @@ -78,15 +84,13 @@ func (node *node) Commit() tmtypes.SignedHeader { commit := node.valset.Sign(header) + node.prevvalset = node.valset + node.valset = nextvalset node.commits = append(node.commits, commit) return commit } -func (node *node) Set(key, value string) { - node.store.Set(append([]byte{0x00}, []byte(key)...), []byte(value)) -} - type Verifier struct { ConsensusState } @@ -102,10 +106,11 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifi } } -func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidators) error { +func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset MockValidators) error { newcs, err := v.ConsensusState.Validate( Header{ SignedHeader: header, + ValidatorSet: valset.ValidatorSet(), NextValidatorSet: nextvalset.ValidatorSet(), }, ) @@ -117,15 +122,96 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidato return nil } -func TestUpdate(t *testing.T) { +func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10)) node.Commit() verifier := NewVerifier(node.last(), node.valset) - header := node.Commit() + for i := 0; i < 100; i++ { + header := node.Commit() + + if i%interval == 0 { + err := verifier.Validate(header, node.prevvalset, node.valset) + if ok { + require.NoError(t, err) + } else { + require.Error(t, err) + } + } + } +} + +func TestEveryBlockUpdate(t *testing.T) { + testUpdate(t, 1, true) +} + +func TestEvenBlockUpdate(t *testing.T) { + testUpdate(t, 2, true) +} + +func TestSixthBlockUpdate(t *testing.T) { + testUpdate(t, 6, true) +} + +/* +// This should fail, since the amount of mutation is so large +// Commented out because it sometimes success +func TestTenthBlockUpdate(t *testing.T) { + testUpdate(t, 10, false) +} +*/ + +func key(str []byte) []byte { + return append([]byte{0x00}, str...) +} + +func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { + qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/ibc/key", Data: key(k), Prove: true}) + require.Equal(t, uint32(0), qres.Code, qres.Log) + proof := merkle.Proof{ + Key: []byte(k), + Proof: qres.Proof, + } + return qres.Value, proof +} + +func (node *node) Set(k, value []byte) { + node.store.Set(key(k), value) +} + +func testProof(t *testing.T) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + kvps := cmn.KVPairs{} + for h := 0; h < 20; h++ { + for i := 0; i < 100; i++ { + k := make([]byte, 32) + v := make([]byte, 32) + rand.Read(k) + rand.Read(v) + kvps = append(kvps, cmn.KVPair{Key: k, Value: v}) + node.Set(k, v) + } + header := node.Commit() + proofs := []commitment.Proof{} + for _, kvp := range kvps { + v, p := node.query(t, []byte(kvp.Key)) + require.Equal(t, kvp.Value, v) + proofs = append(proofs, p) + } + cstore, err := commitment.NewStore([]byte(header.AppHash), proofs) + require.NoError(t, err) + + for _, kvp := range kvps { + require.True(t, cstore.Prove(kvp.Key, kvp.Value)) + } + } +} - err := verifier.Validate(header, node.valset) - require.NoError(t, err) +func TestProofs(t *testing.T) { + testProof(t) } diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/valset_test.go index 10aa5dc0eae7..5649a3533273 100644 --- a/x/ibc/02-client/tendermint/valset_test.go +++ b/x/ibc/02-client/tendermint/valset_test.go @@ -2,7 +2,6 @@ package tendermint import ( "bytes" - "fmt" "sort" "github.com/tendermint/tendermint/crypto" @@ -91,13 +90,8 @@ func NewMockValidators(num int, power int64) MockValidators { res[i] = NewMockValidator(sdk.NewDec(power)) } - // ddd - fmt.Println(333) - for _, val := range res { - fmt.Println(val) - } + sort.Sort(res) - // ddd return res } @@ -124,9 +118,10 @@ func (vals MockValidators) TotalPower() sdk.Dec { } func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { + precommits := make([]*tmtypes.CommitSig, len(vals)) for i, val := range vals { - precommits[i] = (&tmtypes.Vote{ + vote := &tmtypes.Vote{ BlockID: tmtypes.BlockID{ Hash: header.Hash(), }, @@ -134,8 +129,9 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { ValidatorIndex: i, Height: header.Height, Type: tmtypes.PrecommitType, - }).CommitSig() - val.MockPV.SignVote("", (*tmtypes.Vote)(precommits[i])) + } + val.MockPV.SignVote(chainid, vote) + precommits[i] = vote.CommitSig() } return tmtypes.SignedHeader{ @@ -150,13 +146,8 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { } // Mutate valset -func (vals MockValidators) Mutate(majority bool) MockValidators { - var num int - if majority { - num = len(vals) * 2 / 3 - } else { - num = len(vals) * 1 / 6 - } +func (vals MockValidators) Mutate() MockValidators { + num := len(vals) / 20 // 5% change each block res := make(MockValidators, len(vals)) @@ -168,15 +159,15 @@ func (vals MockValidators) Mutate(majority bool) MockValidators { res[i] = NewMockValidator(vals[0].Power) } - // ddd - fmt.Println(333) - for _, val := range res { - fmt.Println(val) - } + sort.Sort(res) - // ddd + for i, val := range vals { + if val != res[i] { + return res + } + } - return res + panic("not mutated") } func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { @@ -186,12 +177,5 @@ func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { tmvals[i] = val.Validator() } - // ddd - fmt.Println(333444) - for _, val := range tmvals { - fmt.Println(val) - } - - // ddd return tmtypes.NewValidatorSet(tmvals) } From 579060f5cd03cb95ed05e8727a166f07c1a4f21f Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 19 Jun 2019 13:07:06 +0100 Subject: [PATCH 009/182] in progres --- x/ibc/client/cli/query.go | 216 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 x/ibc/client/cli/query.go diff --git a/x/ibc/client/cli/query.go b/x/ibc/client/cli/query.go new file mode 100644 index 000000000000..ca979151c499 --- /dev/null +++ b/x/ibc/client/cli/query.go @@ -0,0 +1,216 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" + ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" +) + +func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcQueryCmd := &cobra.Command{ + Use: "ibc", + Short: "IBC query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcQueryCmd.AddCommand(client.GetCommands( + GetCmdQueryConsensusState(cdc), + GetCmdQueryHeader(cdc), + GetCmdQueryClient(cdc), + GetCmdQueryConnection(cdc), + GetCmdQueryChannel(cdc), + )...) + return ibcQueryCmd +} + +func GetCmdQueryClient(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "client", + Short: "Query stored client", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var state ibc.ConsensusState + statebz, _, err := query(ctx, keeper.Client.Object(args[0]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(statebz, &state) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryConsensusState(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "consensus-state", + Short: "Query the latest consensus state of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + state := tendermint.ConsensusState{ + ChainID: commit.ChainID, + Height: uint64(commit.Height), + Root: []byte(commit.AppHash), + NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "header", + Short: "Query the latest header of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + nextvalidators, err := node.Validators(&height) + if err != nil { + return err + } + + header := tendermint.Header{ + SignedHeader: commit.SignedHeader, + ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) + + return nil + }, + } +} + +func GetCmdQueryConnection(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "connection", + Short: "Query an existing connection", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var conn ibc.Connection + connbz, _, err := query(ctx, keeper.Connection.Object(args[0]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(connbz, &conn) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) + + return nil + }, + } +} + +func GetCmdQueryChannel(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "channel", + Short: "Query an existing channel", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var conn ibc.Channel + connbz, _, err := query(ctx, keeper.Channel.Object(args[0], args[1]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(connbz, &conn) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) + + return nil + }, + } +} + +func GetCmdQuerySendSequence(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "send-sequence", + Short: "Query the send sequence of a channel", + Args: cobra.ExactArgs(), + RunE: func(cmd *cobra.Command, args []string) error { + + }, + } +} + +func GetCmdQueryReceiveSequence(cdc *codec.Codec) *cobra.Command { + +} + +func GetCmdQueryPacket(cdc *codec.Codec) *cobra.Command { +} From b3f4ef5b4216cf587c8cb7f9acc637b24243b35e Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 12:20:15 +0200 Subject: [PATCH 010/182] fin rebase --- x/ibc/02-client/tendermint/types.go | 2 +- x/ibc/02-client/tendermint/types_test.go | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 8dd3cfca7294..26a4c35370e6 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -37,7 +37,7 @@ func (cs ConsensusState) update(header Header) ConsensusState { return ConsensusState{ ChainID: cs.ChainID, Height: uint64(header.Height), - Root: header.AppHash, + Root: cs.GetRoot().Update(header.AppHash), NextValidatorSet: header.NextValidatorSet, } } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 14ca7adad0ea..8bde76d10302 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -24,7 +24,7 @@ import ( const chainid = "testchain" func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { - key := sdk.NewKVStoreKey("ibc") + key := sdk.NewKVStoreKey("test") db := dbm.NewMemDB() cms := store.NewCommitMultiStore(db) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) @@ -91,6 +91,13 @@ func (node *node) Commit() tmtypes.SignedHeader { return commit } +func keyPrefix() [][]byte { + return [][]byte{ + []byte("test"), + []byte{0x00}, + } +} + type Verifier struct { ConsensusState } @@ -100,7 +107,7 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifi ConsensusState{ ChainID: chainid, Height: uint64(header.Height), - Root: header.AppHash, + Root: merkle.NewRoot(header.AppHash, keyPrefix()), NextValidatorSet: nextvalset.ValidatorSet(), }, } @@ -168,7 +175,7 @@ func key(str []byte) []byte { } func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { - qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/ibc/key", Data: key(k), Prove: true}) + qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/test/key", Data: key(k), Prove: true}) require.Equal(t, uint32(0), qres.Code, qres.Log) proof := merkle.Proof{ Key: []byte(k), @@ -203,7 +210,7 @@ func testProof(t *testing.T) { require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore([]byte(header.AppHash), proofs) + cstore, err := commitment.NewStore(merkle.NewRoot([]byte(header.AppHash), keyPrefix()), proofs) require.NoError(t, err) for _, kvp := range kvps { From 7b745573c0eebb8692830b01e87fd8a5389ece8d Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 16:07:00 +0200 Subject: [PATCH 011/182] in progress --- x/ibc/02-client/cli.go | 18 ++++++++++ x/ibc/02-client/manager.go | 34 ++++++++++--------- x/ibc/02-client/tendermint/types_test.go | 42 ++++++++++-------------- 3 files changed, 54 insertions(+), 40 deletions(-) create mode 100644 x/ibc/02-client/cli.go diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go new file mode 100644 index 000000000000..5c245ba0378e --- /dev/null +++ b/x/ibc/02-client/cli.go @@ -0,0 +1,18 @@ +package client + +import () + +// CLIObject stores the key for each object fields +type CLIObject struct { + ID string + ConsensusState []byte + Frozen []byte +} + +func (object Object) CLI() CLIObject { + return CLIObject{ + ID: object.id, + ConsensusState: object.consensusState.Key(), + Frozen: object.frozen.Key(), + } +} diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 196d62e62fdc..a99a4bcc785c 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -55,9 +55,9 @@ func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { */ func (man Manager) object(id string) Object { return Object{ - id: id, - client: man.protocol.Value([]byte(id)), - freeze: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + id: id, + consensusState: man.protocol.Value([]byte(id)), + frozen: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), } } @@ -67,7 +67,7 @@ func (man Manager) Create(ctx sdk.Context, cs ConsensusState) (Object, error) { if obj.exists(ctx) { return Object{}, errors.New("Create client on already existing id") } - obj.client.Set(ctx, cs) + obj.consensusState.Set(ctx, cs) return obj, nil } @@ -91,9 +91,9 @@ func (man CounterpartyManager) Query(id string) CounterObject { } type Object struct { - id string - client state.Value // ConsensusState - freeze state.Boolean + id string + consensusState state.Value // ConsensusState + frozen state.Boolean } type CounterObject struct { @@ -101,34 +101,38 @@ type CounterObject struct { client commitment.Value } -func (obj Object) exists(ctx sdk.Context) bool { - return obj.client.Exists(ctx) -} - func (obj Object) ID() string { return obj.id } -func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { - obj.client.Get(ctx, &res) +func (obj Object) ConsensusState(ctx sdk.Context) (res ConsensusState) { + obj.consensusState.Get(ctx, &res) return } +func (obj Object) Frozen(ctx sdk.Context) bool { + return obj.frozen.Get(ctx) +} + func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } +func (obj Object) exists(ctx sdk.Context) bool { + return obj.consensusState.Exists(ctx) +} + func (obj Object) Update(ctx sdk.Context, header Header) error { if !obj.exists(ctx) { panic("should not update nonexisting client") } - if obj.freeze.Get(ctx) { + if obj.Frozen(ctx) { return errors.New("client is frozen") } var stored ConsensusState - obj.client.GetIfExists(ctx, &stored) + obj.client.Get(ctx, &stored) updated, err := stored.Validate(header) if err != nil { return err diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 8bde76d10302..3cb99f52b549 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -91,23 +91,16 @@ func (node *node) Commit() tmtypes.SignedHeader { return commit } -func keyPrefix() [][]byte { - return [][]byte{ - []byte("test"), - []byte{0x00}, - } -} - type Verifier struct { ConsensusState } -func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifier { +func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root merkle.Root) *Verifier { return &Verifier{ ConsensusState{ ChainID: chainid, Height: uint64(header.Height), - Root: merkle.NewRoot(header.AppHash, keyPrefix()), + Root: root.Update(header.AppHash), NextValidatorSet: nextvalset.ValidatorSet(), }, } @@ -129,12 +122,18 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock return nil } +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10)) node.Commit() - verifier := NewVerifier(node.last(), node.valset) + root := newRoot() + + verifier := NewVerifier(node.last(), node.valset, root) for i := 0; i < 100; i++ { header := node.Commit() @@ -170,22 +169,14 @@ func TestTenthBlockUpdate(t *testing.T) { } */ -func key(str []byte) []byte { - return append([]byte{0x00}, str...) -} - -func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { - qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/test/key", Data: key(k), Prove: true}) - require.Equal(t, uint32(0), qres.Code, qres.Log) - proof := merkle.Proof{ - Key: []byte(k), - Proof: qres.Proof, - } - return qres.Value, proof +func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { + code, value, proof := root.Query(node.cms, k) + require.Equal(t, uint32(0), code) + return value, proof } func (node *node) Set(k, value []byte) { - node.store.Set(key(k), value) + node.store.Set(newRoot().Key(k), value) } func testProof(t *testing.T) { @@ -205,12 +196,13 @@ func testProof(t *testing.T) { } header := node.Commit() proofs := []commitment.Proof{} + root := newRoot().Update(header.AppHash) for _, kvp := range kvps { - v, p := node.query(t, []byte(kvp.Key)) + v, p := node.query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore(merkle.NewRoot([]byte(header.AppHash), keyPrefix()), proofs) + cstore, err := commitment.NewStore(root, proofs) require.NoError(t, err) for _, kvp := range kvps { From b596fe1f5f3b967a2f02266220299f4bd21b4ff3 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 16:15:17 +0200 Subject: [PATCH 012/182] fin rebase --- x/ibc/02-client/manager.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index a99a4bcc785c..e94d14702b72 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -81,8 +81,8 @@ func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { func (man CounterpartyManager) object(id string) CounterObject { return CounterObject{ - id: id, - client: man.protocol.Value([]byte(id)), + id: id, + consensusState: man.protocol.Value([]byte(id)), } } @@ -97,8 +97,8 @@ type Object struct { } type CounterObject struct { - id string - client commitment.Value + id string + consensusState commitment.Value } func (obj Object) ID() string { @@ -115,7 +115,7 @@ func (obj Object) Frozen(ctx sdk.Context) bool { } func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { - return obj.client.Is(ctx, client) + return obj.consensusState.Is(ctx, client) } func (obj Object) exists(ctx sdk.Context) bool { @@ -132,13 +132,13 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { } var stored ConsensusState - obj.client.Get(ctx, &stored) + obj.consensusState.Get(ctx, &stored) updated, err := stored.Validate(header) if err != nil { return err } - obj.client.Set(ctx, updated) + obj.consensusState.Set(ctx, updated) return nil } @@ -148,11 +148,11 @@ func (obj Object) Freeze(ctx sdk.Context) error { panic("should not freeze nonexisting client") } - if obj.freeze.Get(ctx) { + if obj.Frozen(ctx) { return errors.New("client is already frozen") } - obj.freeze.Set(ctx, true) + obj.frozen.Set(ctx, true) return nil } @@ -162,12 +162,12 @@ func (obj Object) Delete(ctx sdk.Context) error { panic("should not delete nonexisting client") } - if !obj.freeze.Get(ctx) { + if !obj.Frozen(ctx) { return errors.New("client is not frozen") } - obj.client.Delete(ctx) - obj.freeze.Delete(ctx) + obj.consensusState.Delete(ctx) + obj.frozen.Delete(ctx) return nil } From d41b9844738b743cedba55e7a6a132e33a279e39 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 17:10:21 +0200 Subject: [PATCH 013/182] add CLIObject in progress --- client/context/query.go | 38 ++++++++++++++++++----------- x/ibc/02-client/cli.go | 24 ++++++++++++------ x/ibc/23-commitment/merkle/utils.go | 6 ++++- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 87f96aece166..1e52442c6c61 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,21 +31,31 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) ([]byte, int64, error) { - return ctx.query(path, nil) +func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { + val, _, height, err = ctx.query(path, nil) + return } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { - return ctx.query(path, data) +func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { + val, _, height, err = ctx.query(path, data) + return } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { + val, _, height, err = ctx.queryStore(key, storeName, "key") + return +} + +// QueryProof performs a query to a Tendermint node with the provided key and +// store name. It returns the result, the proof, and height of the query +// upon success or an error if the query fails. +func (ctx CLIContext) QueryProof(key cmn.HexBytes, storeName string) (val []byte, proof *merkle.Proof, height int64, err error) { return ctx.queryStore(key, storeName, "key") } @@ -53,7 +63,7 @@ func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, in // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, height int64, err error) { - resRaw, height, err := ctx.queryStore(subspace, storeName, "subspace") + resRaw, _, height, err := ctx.queryStore(subspace, storeName, "subspace") if err != nil { return res, height, err } @@ -75,10 +85,10 @@ func (ctx CLIContext) GetFromName() string { // query performs a query to a Tendermint node with the provided store name // and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height int64, err error) { +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *merkle.Proof, height int64, err error) { node, err := ctx.GetNode() if err != nil { - return res, height, err + return res, proof, height, err } opts := rpcclient.ABCIQueryOptions{ @@ -88,25 +98,25 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height i result, err := node.ABCIQueryWithOptions(path, key, opts) if err != nil { - return res, height, err + return res, proof, height, err } resp := result.Response if !resp.IsOK() { - return res, height, errors.New(resp.Log) + return res, proof, height, errors.New(resp.Log) } // data from trusted node or subspace query doesn't need verification if ctx.TrustNode || !isQueryStoreWithProof(path) { - return resp.Value, resp.Height, nil + return resp.Value, resp.Proof, resp.Height, nil } err = ctx.verifyProof(path, resp) if err != nil { - return res, height, err + return res, proof, height, err } - return resp.Value, resp.Height, nil + return resp.Value, resp.Proof, resp.Height, nil } // Verify verifies the consensus proof at given height. @@ -165,7 +175,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) { +func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, *merkle.Proof, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 5c245ba0378e..8767c3032724 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -1,18 +1,26 @@ package client -import () +import ( + "github.com/cosmos/cosmos-sdk/client/context" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) // CLIObject stores the key for each object fields type CLIObject struct { - ID string - ConsensusState []byte - Frozen []byte + ID string + ConsensusStateKey []byte + FrozenKey []byte } -func (object Object) CLI() CLIObject { +func (obj Object) CLI() CLIObject { return CLIObject{ - ID: object.id, - ConsensusState: object.consensusState.Key(), - Frozen: object.frozen.Key(), + ID: obj.id, + ConsensusStateKey: obj.consensusState.Key(), + FrozenKey: obj.frozen.Key(), } } + +func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle..Proof) { + val, proof, _, err := ctx.QueryProof(obj.ConsensusStateKey) +} diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index 1fa13f6a3d32..71650d987f22 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -23,6 +23,10 @@ func (root Root) Query(cms types.CommitMultiStore, key []byte) (uint32, []byte, return qres.Code, qres.Value, Proof{Key: key, Proof: qres.Proof} } -func (root Root) Key(key []byte) []byte { +func (root Root) QueryKey(key []byte) []byte { return append(root.KeyPrefix, key...) // XXX: cloneAppend } + +func (root Root) QueryPath() []byte { + +} From 4ed87ef649ea163b6295509f37f6c9334d74a544 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:19:42 +0200 Subject: [PATCH 014/182] cli in progress --- client/context/query.go | 69 ++++++++++++++++------------- store/state/types.go | 5 +++ x/ibc/02-client/cli.go | 34 +++++++++++++- x/ibc/23-commitment/merkle/utils.go | 6 +++ 4 files changed, 82 insertions(+), 32 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 1e52442c6c61..4738808ba4fe 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,39 +31,35 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { - val, _, height, err = ctx.query(path, nil) - return +func (ctx CLIContext) Query(path string) ([]byte, int64, error) { + return ctx.query(path, nil) } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { - val, _, height, err = ctx.query(path, data) - return +func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { + return ctx.query(path, data) } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { - val, _, height, err = ctx.queryStore(key, storeName, "key") - return +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { + return ctx.queryStore(key, storeName, "key") } -// QueryProof performs a query to a Tendermint node with the provided key and -// store name. It returns the result, the proof, and height of the query -// upon success or an error if the query fails. -func (ctx CLIContext) QueryProof(key cmn.HexBytes, storeName string) (val []byte, proof *merkle.Proof, height int64, err error) { - return ctx.queryStore(key, storeName, "key") +// QueryABCI performs a query to a Tendermint node with the provide RequestQuery. +// It returns the ResultQuery obtained from the query. +func (ctx CLIContext) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { + return ctx.queryABCI(req) } // QuerySubspace performs a query to a Tendermint node with the provided // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, height int64, err error) { - resRaw, _, height, err := ctx.queryStore(subspace, storeName, "subspace") + resRaw, height, err := ctx.queryStore(subspace, storeName, "subspace") if err != nil { return res, height, err } @@ -82,13 +78,10 @@ func (ctx CLIContext) GetFromName() string { return ctx.FromName } -// query performs a query to a Tendermint node with the provided store name -// and path. It returns the result and height of the query upon success -// or an error if the query fails. -func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *merkle.Proof, height int64, err error) { +func (ctx CLIContext) queryABCI(req abci.RequestQuery) (resp abci.ResponseQuery, err error) { node, err := ctx.GetNode() if err != nil { - return res, proof, height, err + return } opts := rpcclient.ABCIQueryOptions{ @@ -96,27 +89,43 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *m Prove: !ctx.TrustNode, } - result, err := node.ABCIQueryWithOptions(path, key, opts) + result, err := node.ABCIQueryWithOptions(req.Path, req.Data, opts) if err != nil { - return res, proof, height, err + return } - resp := result.Response + resp = result.Response if !resp.IsOK() { - return res, proof, height, errors.New(resp.Log) + err = errors.New(resp.Log) + return } // data from trusted node or subspace query doesn't need verification - if ctx.TrustNode || !isQueryStoreWithProof(path) { - return resp.Value, resp.Proof, resp.Height, nil + if ctx.TrustNode || !isQueryStoreWithProof(req.Path) { + return resp, nil } - err = ctx.verifyProof(path, resp) + err = ctx.verifyProof(req.Path, resp) + if err != nil { + return + } + + return +} + +// query performs a query to a Tendermint node with the provided store name +// and path. It returns the result and height of the query upon success +// or an error if the query fails. +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height int64, err error) { + resp, err := ctx.queryABCI(abci.RequestQuery{ + Path: path, + Data: key, + }) if err != nil { - return res, proof, height, err + return } - return resp.Value, resp.Proof, resp.Height, nil + return resp.Value, resp.Height, nil } // Verify verifies the consensus proof at given height. @@ -175,7 +184,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, *merkle.Proof, int64, error) { +func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/store/state/types.go b/store/state/types.go index a8d34d582a82..f5dbb4dc8648 100644 --- a/store/state/types.go +++ b/store/state/types.go @@ -1,8 +1,13 @@ package state import ( + "github.com/tendermint/tendermint/crypto/merkle" + + "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" ) type KVStore = sdk.KVStore type Context = sdk.Context +type CLIContext = context.CLIContext +type Proof = merkle.Proof diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 8767c3032724..f51b882e7725 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -2,6 +2,7 @@ package client import ( "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -11,6 +12,7 @@ type CLIObject struct { ID string ConsensusStateKey []byte FrozenKey []byte + Cdc *codec.Codec } func (obj Object) CLI() CLIObject { @@ -21,6 +23,34 @@ func (obj Object) CLI() CLIObject { } } -func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle..Proof) { - val, proof, _, err := ctx.QueryProof(obj.ConsensusStateKey) +func query(ctx context.CLIContext, root merkle.Root, key []byte) ([]byte, merkle.Proof, error) { + resp, err := ctx.QueryABCI(root.RequestQuery(key)) + if err != nil { + return nil, merkle.Proof{}, err + } + proof := merkle.Proof{ + Key: key, + Proof: resp.Proof, + } + return resp.Value, proof, nil + +} + +func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { + val, proof, err := query(ctx, root, obj.ConsensusStateKey) + obj.Cdc.MustUnmarshalBinaryBare(val, &res) + return +} + +func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { + val, tmproof, _, err := ctx.QueryProof(obj.FrozenKey, "ibc") // TODO + if err != nil { + return + } + proof = merkle.Proof{ + Key: obj.FrozenKey, + Proof: tmproof, + } + obj.Cdc.MustUnmarshalBinaryBare(val, &res) + return } diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index 71650d987f22..2b5e3ab87ca6 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -28,5 +28,11 @@ func (root Root) QueryKey(key []byte) []byte { } func (root Root) QueryPath() []byte { + path := "" + for _, inter := range root.KeyPath { + path = path + "/" + string(inter) + } + path = path + "/key" + return []byte(path) } From 276f18cbc4a2c9a049c9ad37849784d871e77e30 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:40:30 +0200 Subject: [PATCH 015/182] add CLIObject --- x/ibc/02-client/cli.go | 31 ++++++++++------------- x/ibc/02-client/tendermint/types_test.go | 2 +- x/ibc/23-commitment/merkle/merkle_test.go | 12 ++++----- x/ibc/23-commitment/merkle/utils.go | 25 ++++++++---------- 4 files changed, 32 insertions(+), 38 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index f51b882e7725..2592e697573c 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -12,45 +12,42 @@ type CLIObject struct { ID string ConsensusStateKey []byte FrozenKey []byte - Cdc *codec.Codec + + Root merkle.Root + Cdc *codec.Codec } -func (obj Object) CLI() CLIObject { +func (obj Object) CLI(root merkle.Root) CLIObject { return CLIObject{ ID: obj.id, ConsensusStateKey: obj.consensusState.Key(), FrozenKey: obj.frozen.Key(), + + Root: root, + Cdc: obj.consensusState.Cdc(), } } -func query(ctx context.CLIContext, root merkle.Root, key []byte) ([]byte, merkle.Proof, error) { - resp, err := ctx.QueryABCI(root.RequestQuery(key)) +func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { + resp, err := ctx.QueryABCI(obj.Root.RequestQuery(key)) if err != nil { - return nil, merkle.Proof{}, err + return merkle.Proof{}, err } proof := merkle.Proof{ Key: key, Proof: resp.Proof, } - return resp.Value, proof, nil + err = obj.Cdc.UnmarshalBinaryBare(resp.Value, ptr) + return proof, err } func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { - val, proof, err := query(ctx, root, obj.ConsensusStateKey) - obj.Cdc.MustUnmarshalBinaryBare(val, &res) + proof, err = obj.query(ctx, obj.ConsensusStateKey, &res) return } func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { - val, tmproof, _, err := ctx.QueryProof(obj.FrozenKey, "ibc") // TODO - if err != nil { - return - } - proof = merkle.Proof{ - Key: obj.FrozenKey, - Proof: tmproof, - } - obj.Cdc.MustUnmarshalBinaryBare(val, &res) + proof, err = obj.query(ctx, obj.FrozenKey, &res) return } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 3cb99f52b549..2b89f9be11c8 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -170,7 +170,7 @@ func TestTenthBlockUpdate(t *testing.T) { */ func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.Query(node.cms, k) + code, value, proof := root.QueryMultiStore(node.cms, k) require.Equal(t, uint32(0), code) return value, proof } diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index 487e9496163e..a1886519eafc 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -47,13 +47,13 @@ func TestStore(t *testing.T) { root = commit(cms, root) - c1, v1, p1 := root.Query(cms, []byte("hello")) + c1, v1, p1 := root.QueryMultiStore(cms, []byte("hello")) require.Equal(t, uint32(0), c1) require.Equal(t, []byte("world"), v1) - c2, v2, p2 := root.Query(cms, []byte("merkle")) + c2, v2, p2 := root.QueryMultiStore(cms, []byte("merkle")) require.Equal(t, uint32(0), c2) require.Equal(t, []byte("tree"), v2) - c3, v3, p3 := root.Query(cms, []byte("block")) + c3, v3, p3 := root.QueryMultiStore(cms, []byte("block")) require.Equal(t, uint32(0), c3) require.Equal(t, []byte("chain"), v3) @@ -70,13 +70,13 @@ func TestStore(t *testing.T) { root = commit(cms, root) - c1, v1, p1 = root.Query(cms, []byte("12345")) + c1, v1, p1 = root.QueryMultiStore(cms, []byte("12345")) require.Equal(t, uint32(0), c1) require.Equal(t, []byte("67890"), v1) - c2, v2, p2 = root.Query(cms, []byte("qwerty")) + c2, v2, p2 = root.QueryMultiStore(cms, []byte("qwerty")) require.Equal(t, uint32(0), c2) require.Equal(t, []byte("zxcv"), v2) - c3, v3, p3 = root.Query(cms, []byte("hello")) + c3, v3, p3 = root.QueryMultiStore(cms, []byte("hello")) require.Equal(t, uint32(0), c3) require.Equal(t, []byte("dlrow"), v3) diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index 2b5e3ab87ca6..daf4c36b171b 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -7,32 +7,29 @@ import ( ) func (root Root) RequestQuery(key []byte) abci.RequestQuery { - path := "" - for _, inter := range root.KeyPath { - path = path + "/" + string(inter) - } - path = path + "/key" - - data := append(root.KeyPrefix, key...) + req := root.RequestQueryMultiStore(key) + req.Path = "/store" + req.Path + return req +} - return abci.RequestQuery{Path: path, Data: data, Prove: true} +func (root Root) RequestQueryMultiStore(key []byte) abci.RequestQuery { + return abci.RequestQuery{Path: root.Path() + "/key", Data: root.Key(key), Prove: true} } -func (root Root) Query(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { - qres := cms.(types.Queryable).Query(root.RequestQuery(key)) +func (root Root) QueryMultiStore(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { + qres := cms.(types.Queryable).Query(root.RequestQueryMultiStore(key)) return qres.Code, qres.Value, Proof{Key: key, Proof: qres.Proof} } -func (root Root) QueryKey(key []byte) []byte { +func (root Root) Key(key []byte) []byte { return append(root.KeyPrefix, key...) // XXX: cloneAppend } -func (root Root) QueryPath() []byte { +func (root Root) Path() string { path := "" for _, inter := range root.KeyPath { path = path + "/" + string(inter) } - path = path + "/key" - return []byte(path) + return path } From 1078211fa7de89ff39fe4b541b775b242b4726b0 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:58:28 +0200 Subject: [PATCH 016/182] separate testing from tendermint --- .../tendermint/tests/tendermint_test.go | 58 ++++++++ .../{types_test.go => tests/types.go} | 125 ++++++------------ .../{valset_test.go => tests/valset.go} | 0 3 files changed, 98 insertions(+), 85 deletions(-) create mode 100644 x/ibc/02-client/tendermint/tests/tendermint_test.go rename x/ibc/02-client/tendermint/{types_test.go => tests/types.go} (57%) rename x/ibc/02-client/tendermint/{valset_test.go => tests/valset.go} (100%) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go new file mode 100644 index 000000000000..29581e718e4c --- /dev/null +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -0,0 +1,58 @@ +package tendermint + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + +func testUpdate(t *testing.T, interval int, ok bool) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + verifier := node.LastStateVerifier(newRoot()) + + for i := 0; i < 100; i++ { + header := node.Commit() + + if i%interval == 0 { + err := verifier.Validate(header, node.PrevValset, node.Valset) + if ok { + require.NoError(t, err) + } else { + require.Error(t, err) + } + } + } +} + +func TestEveryBlockUpdate(t *testing.T) { + testUpdate(t, 1, true) +} + +func TestEvenBlockUpdate(t *testing.T) { + testUpdate(t, 2, true) +} + +func TestSixthBlockUpdate(t *testing.T) { + testUpdate(t, 6, true) +} + +/* +// This should fail, since the amount of mutation is so large +// Commented out because it sometimes success +func TestTenthBlockUpdate(t *testing.T) { + testUpdate(t, 10, false) +} +*/ + +func TestProofs(t *testing.T) { + testProof(t) +} diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/tests/types.go similarity index 57% rename from x/ibc/02-client/tendermint/types_test.go rename to x/ibc/02-client/tendermint/tests/types.go index 2b89f9be11c8..f32cae8efc9d 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -17,6 +17,8 @@ import ( stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -37,44 +39,44 @@ func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *c return key, ctx, cms, cdc } -type node struct { - prevvalset MockValidators - valset MockValidators +type Node struct { + PrevValset MockValidators + Valset MockValidators - cms sdk.CommitMultiStore - store sdk.KVStore + Cms sdk.CommitMultiStore + Store sdk.KVStore - commits []tmtypes.SignedHeader + Commits []tmtypes.SignedHeader } -func NewNode(valset MockValidators) *node { +func NewNode(valset MockValidators) *Node { key, ctx, cms, _ := defaultComponents() - return &node{ - valset: valset, - cms: cms, - store: ctx.KVStore(key), - commits: nil, + return &Node{ + Valset: valset, + Cms: cms, + Store: ctx.KVStore(key), + Commits: nil, } } -func (node *node) last() tmtypes.SignedHeader { - if len(node.commits) == 0 { +func (node *Node) Last() tmtypes.SignedHeader { + if len(node.Commits) == 0 { return tmtypes.SignedHeader{} } - return node.commits[len(node.commits)-1] + return node.Commits[len(node.Commits)-1] } -func (node *node) Commit() tmtypes.SignedHeader { - valsethash := node.valset.ValidatorSet().Hash() - nextvalset := node.valset.Mutate() +func (node *Node) Commit() tmtypes.SignedHeader { + valsethash := node.Valset.ValidatorSet().Hash() + nextvalset := node.Valset.Mutate() nextvalsethash := nextvalset.ValidatorSet().Hash() - commitid := node.cms.Commit() + commitid := node.Cms.Commit() header := tmtypes.Header{ ChainID: chainid, - Height: int64(len(node.commits) + 1), + Height: int64(len(node.Commits) + 1), LastBlockID: tmtypes.BlockID{ - Hash: node.last().Header.Hash(), + Hash: node.Last().Header.Hash(), }, ValidatorsHash: valsethash, @@ -82,22 +84,26 @@ func (node *node) Commit() tmtypes.SignedHeader { AppHash: commitid.Hash, } - commit := node.valset.Sign(header) + commit := node.Valset.Sign(header) - node.prevvalset = node.valset - node.valset = nextvalset - node.commits = append(node.commits, commit) + node.PrevValset = node.Valset + node.Valset = nextvalset + node.Commits = append(node.Commits, commit) return commit } +func (node *Node) LastStateVerifier(root merkle.Root) *Verifier { + return NewVerifier(node.Last(), node.Valset, root) +} + type Verifier struct { - ConsensusState + client.ConsensusState } func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root merkle.Root) *Verifier { return &Verifier{ - ConsensusState{ + tendermint.ConsensusState{ ChainID: chainid, Height: uint64(header.Height), Root: root.Update(header.AppHash), @@ -108,7 +114,7 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root me func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset MockValidators) error { newcs, err := v.ConsensusState.Validate( - Header{ + tendermint.Header{ SignedHeader: header, ValidatorSet: valset.ValidatorSet(), NextValidatorSet: nextvalset.ValidatorSet(), @@ -117,66 +123,19 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock if err != nil { return err } - v.ConsensusState = newcs.(ConsensusState) + v.ConsensusState = newcs.(tendermint.ConsensusState) return nil } -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - -func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10)) - - node.Commit() - - root := newRoot() - - verifier := NewVerifier(node.last(), node.valset, root) - - for i := 0; i < 100; i++ { - header := node.Commit() - - if i%interval == 0 { - err := verifier.Validate(header, node.prevvalset, node.valset) - if ok { - require.NoError(t, err) - } else { - require.Error(t, err) - } - } - } -} - -func TestEveryBlockUpdate(t *testing.T) { - testUpdate(t, 1, true) -} - -func TestEvenBlockUpdate(t *testing.T) { - testUpdate(t, 2, true) -} - -func TestSixthBlockUpdate(t *testing.T) { - testUpdate(t, 6, true) -} - -/* -// This should fail, since the amount of mutation is so large -// Commented out because it sometimes success -func TestTenthBlockUpdate(t *testing.T) { - testUpdate(t, 10, false) -} -*/ - -func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.QueryMultiStore(node.cms, k) +func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { + code, value, proof := root.QueryMultiStore(node.Cms, k) require.Equal(t, uint32(0), code) return value, proof } -func (node *node) Set(k, value []byte) { - node.store.Set(newRoot().Key(k), value) +func (node *Node) Set(k, value []byte) { + node.Store.Set(newRoot().Key(k), value) } func testProof(t *testing.T) { @@ -198,7 +157,7 @@ func testProof(t *testing.T) { proofs := []commitment.Proof{} root := newRoot().Update(header.AppHash) for _, kvp := range kvps { - v, p := node.query(t, root.(merkle.Root), []byte(kvp.Key)) + v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } @@ -210,7 +169,3 @@ func testProof(t *testing.T) { } } } - -func TestProofs(t *testing.T) { - testProof(t) -} diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/tests/valset.go similarity index 100% rename from x/ibc/02-client/tendermint/valset_test.go rename to x/ibc/02-client/tendermint/tests/valset.go From e64a0d21c84ebd92838bc2fc0b8cb2d9f947d79e Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 16:10:21 +0200 Subject: [PATCH 017/182] add key to node --- x/ibc/02-client/tendermint/tests/types.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index f32cae8efc9d..cc6d73592504 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -44,9 +44,12 @@ type Node struct { Valset MockValidators Cms sdk.CommitMultiStore + Key sdk.StoreKey Store sdk.KVStore Commits []tmtypes.SignedHeader + + Root merkle.Root } func NewNode(valset MockValidators) *Node { @@ -54,6 +57,7 @@ func NewNode(valset MockValidators) *Node { return &Node{ Valset: valset, Cms: cms, + Key: key, Store: ctx.KVStore(key), Commits: nil, } From e2a61ac70d0508b2a85a1df4c094d2ae907509da Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 18:58:29 +0200 Subject: [PATCH 018/182] add root and storekey to tests/node, add codec --- x/ibc/02-client/codec.go | 10 ++++++++++ x/ibc/02-client/tendermint/codec.go | 11 +++++++++++ x/ibc/02-client/tendermint/tests/types.go | 8 ++++++-- x/ibc/02-client/tendermint/tests/valset.go | 1 + 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 x/ibc/02-client/codec.go create mode 100644 x/ibc/02-client/tendermint/codec.go diff --git a/x/ibc/02-client/codec.go b/x/ibc/02-client/codec.go new file mode 100644 index 000000000000..fa194562e4f1 --- /dev/null +++ b/x/ibc/02-client/codec.go @@ -0,0 +1,10 @@ +package client + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterInterface((*ConsensusState)(nil), nil) + cdc.RegisterInterface((*Header)(nil), nil) +} diff --git a/x/ibc/02-client/tendermint/codec.go b/x/ibc/02-client/tendermint/codec.go new file mode 100644 index 000000000000..d8308a3e7ec8 --- /dev/null +++ b/x/ibc/02-client/tendermint/codec.go @@ -0,0 +1,11 @@ +package tendermint + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterConcrete(ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil) + cdc.RegisterConcrete(Header{}, "ibc/client/tendermint/Header", nil) + +} diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index cc6d73592504..88a27fd69f51 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -101,6 +101,10 @@ func (node *Node) LastStateVerifier(root merkle.Root) *Verifier { return NewVerifier(node.Last(), node.Valset, root) } +func (node *Node) Context() sdk.Context { + return sdk.NewContext(node.Cms, abci.Header{}, false, log.NewNopLogger()) +} + type Verifier struct { client.ConsensusState } @@ -139,7 +143,7 @@ func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commi } func (node *Node) Set(k, value []byte) { - node.Store.Set(newRoot().Key(k), value) + node.Store.Set(node.Root.Key(k), value) } func testProof(t *testing.T) { @@ -159,7 +163,7 @@ func testProof(t *testing.T) { } header := node.Commit() proofs := []commitment.Proof{} - root := newRoot().Update(header.AppHash) + root := node.Root.Update(header.AppHash) for _, kvp := range kvps { v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 5649a3533273..0d97a5427c9b 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -84,6 +84,7 @@ type MockValidators []MockValidator var _ sort.Interface = MockValidators{} +// TODO: differenciate power between the vals func NewMockValidators(num int, power int64) MockValidators { res := make(MockValidators, num) for i := range res { From c6c4c045c82cee09d3b22f2a7c7aecf104afce03 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 12:22:46 +0200 Subject: [PATCH 019/182] rm cli/query.go --- x/ibc/client/cli/query.go | 216 -------------------------------------- 1 file changed, 216 deletions(-) delete mode 100644 x/ibc/client/cli/query.go diff --git a/x/ibc/client/cli/query.go b/x/ibc/client/cli/query.go deleted file mode 100644 index ca979151c499..000000000000 --- a/x/ibc/client/cli/query.go +++ /dev/null @@ -1,216 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/spf13/cobra" - - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" -) - -func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { - ibcQueryCmd := &cobra.Command{ - Use: "ibc", - Short: "IBC query subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - } - - ibcQueryCmd.AddCommand(client.GetCommands( - GetCmdQueryConsensusState(cdc), - GetCmdQueryHeader(cdc), - GetCmdQueryClient(cdc), - GetCmdQueryConnection(cdc), - GetCmdQueryChannel(cdc), - )...) - return ibcQueryCmd -} - -func GetCmdQueryClient(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "client", - Short: "Query stored client", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var state ibc.ConsensusState - statebz, _, err := query(ctx, keeper.Client.Object(args[0]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(statebz, &state) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) - - return nil - }, - } -} - -func GetCmdQueryConsensusState(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "consensus-state", - Short: "Query the latest consensus state of the running chain", - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - node, err := ctx.GetNode() - if err != nil { - return err - } - - info, err := node.ABCIInfo() - if err != nil { - return err - } - - height := info.Response.LastBlockHeight - prevheight := height - 1 - - commit, err := node.Commit(&height) - if err != nil { - return err - } - - validators, err := node.Validators(&prevheight) - if err != nil { - return err - } - - state := tendermint.ConsensusState{ - ChainID: commit.ChainID, - Height: uint64(commit.Height), - Root: []byte(commit.AppHash), - NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) - - return nil - }, - } -} - -func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "header", - Short: "Query the latest header of the running chain", - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - node, err := ctx.GetNode() - if err != nil { - return err - } - - info, err := node.ABCIInfo() - if err != nil { - return err - } - - height := info.Response.LastBlockHeight - prevheight := height - 1 - - commit, err := node.Commit(&height) - if err != nil { - return err - } - - validators, err := node.Validators(&prevheight) - if err != nil { - return err - } - - nextvalidators, err := node.Validators(&height) - if err != nil { - return err - } - - header := tendermint.Header{ - SignedHeader: commit.SignedHeader, - ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) - - return nil - }, - } -} - -func GetCmdQueryConnection(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "connection", - Short: "Query an existing connection", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var conn ibc.Connection - connbz, _, err := query(ctx, keeper.Connection.Object(args[0]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(connbz, &conn) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) - - return nil - }, - } -} - -func GetCmdQueryChannel(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "channel", - Short: "Query an existing channel", - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var conn ibc.Channel - connbz, _, err := query(ctx, keeper.Channel.Object(args[0], args[1]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(connbz, &conn) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) - - return nil - }, - } -} - -func GetCmdQuerySendSequence(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "send-sequence", - Short: "Query the send sequence of a channel", - Args: cobra.ExactArgs(), - RunE: func(cmd *cobra.Command, args []string) error { - - }, - } -} - -func GetCmdQueryReceiveSequence(cdc *codec.Codec) *cobra.Command { - -} - -func GetCmdQueryPacket(cdc *codec.Codec) *cobra.Command { -} From 83afdaf2808019c17359fdb5261577871e3971b3 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 18:21:20 +0200 Subject: [PATCH 020/182] fix test --- x/ibc/02-client/tendermint/tests/tendermint_test.go | 2 +- x/ibc/02-client/tendermint/tests/types.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index 29581e718e4c..caf866337c47 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -13,7 +13,7 @@ func newRoot() merkle.Root { } func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10)) + node := NewNode(NewMockValidators(100, 10), newRoot()) node.Commit() diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 88a27fd69f51..d0b7b488db39 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -52,7 +52,7 @@ type Node struct { Root merkle.Root } -func NewNode(valset MockValidators) *Node { +func NewNode(valset MockValidators, root merkle.Root) *Node { key, ctx, cms, _ := defaultComponents() return &Node{ Valset: valset, @@ -60,6 +60,7 @@ func NewNode(valset MockValidators) *Node { Key: key, Store: ctx.KVStore(key), Commits: nil, + Root: root, } } @@ -147,7 +148,7 @@ func (node *Node) Set(k, value []byte) { } func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10)) + node := NewNode(NewMockValidators(100, 10), newRoot()) node.Commit() From 21e0b15698f20924740711a07069c98054a5ec7a Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 18:26:23 +0200 Subject: [PATCH 021/182] fix lint --- x/ibc/02-client/tendermint/tests/valset.go | 2 +- x/ibc/02-client/tendermint/types.go | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 0d97a5427c9b..1b5f88aa949b 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -84,7 +84,7 @@ type MockValidators []MockValidator var _ sort.Interface = MockValidators{} -// TODO: differenciate power between the vals +// TODO: differentiate power between the vals func NewMockValidators(num int, power int64) MockValidators { res := make(MockValidators, num) for i := range res { diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 26a4c35370e6..6bb1bb1f18dd 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -48,11 +48,8 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, return nil, errors.New("invalid type") } - nextvalset := cs.NextValidatorSet - nexthash := nextvalset.Hash() - if cs.Height == uint64(header.Height-1) { - nexthash = cs.NextValidatorSet.Hash() + nexthash := cs.NextValidatorSet.Hash() if !bytes.Equal(header.ValidatorsHash, nexthash) { return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) } From 203eaf3c659aedc4b8f7985ad8c33c0f07187658 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 19:12:36 +0200 Subject: [PATCH 022/182] fix lint --- .../tendermint/tests/tendermint_test.go | 6 ------ x/ibc/02-client/tendermint/tests/types.go | 16 ++++++++++++---- x/ibc/02-client/tendermint/tests/valset.go | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index caf866337c47..8a1c764f50f2 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -4,14 +4,8 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10), newRoot()) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index d0b7b488db39..5e0af44f3806 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -1,7 +1,7 @@ package tendermint import ( - "math/rand" + "crypto/rand" "testing" "github.com/stretchr/testify/require" @@ -23,6 +23,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) +// nolint: unused +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + const chainid = "testchain" func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { @@ -147,6 +152,7 @@ func (node *Node) Set(k, value []byte) { node.Store.Set(node.Root.Key(k), value) } +// nolint:deadcode,unused func testProof(t *testing.T) { node := NewNode(NewMockValidators(100, 10), newRoot()) @@ -157,8 +163,10 @@ func testProof(t *testing.T) { for i := 0; i < 100; i++ { k := make([]byte, 32) v := make([]byte, 32) - rand.Read(k) - rand.Read(v) + _, err := rand.Read(k) + require.NoError(t, err) + _, err = rand.Read(v) + require.NoError(t, err) kvps = append(kvps, cmn.KVPair{Key: k, Value: v}) node.Set(k, v) } @@ -166,7 +174,7 @@ func testProof(t *testing.T) { proofs := []commitment.Proof{} root := node.Root.Update(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) + v, p := node.Query(t, root.(merkle.Root), kvp.Key) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 1b5f88aa949b..30bd194682c8 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -131,7 +131,7 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { Height: header.Height, Type: tmtypes.PrecommitType, } - val.MockPV.SignVote(chainid, vote) + _ = val.MockPV.SignVote(chainid, vote) precommits[i] = vote.CommitSig() } From 0872511e91fa865059e16172cca2d1a2bd2393ee Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 17:10:21 +0200 Subject: [PATCH 023/182] add CLIObject in progress --- client/context/query.go | 28 +++++++++++++++++++--------- x/ibc/02-client/cli.go | 4 ++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 4738808ba4fe..b04527f07740 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,21 +31,31 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) ([]byte, int64, error) { - return ctx.query(path, nil) +func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { + val, _, height, err = ctx.query(path, nil) + return } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { - return ctx.query(path, data) +func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { + val, _, height, err = ctx.query(path, data) + return } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { + val, _, height, err = ctx.queryStore(key, storeName, "key") + return +} + +// QueryProof performs a query to a Tendermint node with the provided key and +// store name. It returns the result, the proof, and height of the query +// upon success or an error if the query fails. +func (ctx CLIContext) QueryProof(key cmn.HexBytes, storeName string) (val []byte, proof *merkle.Proof, height int64, err error) { return ctx.queryStore(key, storeName, "key") } @@ -59,7 +69,7 @@ func (ctx CLIContext) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, erro // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, height int64, err error) { - resRaw, height, err := ctx.queryStore(subspace, storeName, "subspace") + resRaw, _, height, err := ctx.queryStore(subspace, storeName, "subspace") if err != nil { return res, height, err } @@ -116,7 +126,7 @@ func (ctx CLIContext) queryABCI(req abci.RequestQuery) (resp abci.ResponseQuery, // query performs a query to a Tendermint node with the provided store name // and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height int64, err error) { +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *merkle.Proof, height int64, err error) { resp, err := ctx.queryABCI(abci.RequestQuery{ Path: path, Data: key, @@ -125,7 +135,7 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height i return } - return resp.Value, resp.Height, nil + return resp.Value, resp.Proof, resp.Height, nil } // Verify verifies the consensus proof at given height. @@ -184,7 +194,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) { +func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, *merkle.Proof, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 2592e697573c..6390bf5ccb8c 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -51,3 +51,7 @@ func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof, err = obj.query(ctx, obj.FrozenKey, &res) return } + +func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle..Proof) { + val, proof, _, err := ctx.QueryProof(obj.ConsensusStateKey) +} From fdf09cc5f526517beb987e27d97467b0ba905b0b Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:19:42 +0200 Subject: [PATCH 024/182] cli in progress --- client/context/query.go | 27 ++++++++++++------------ x/ibc/02-client/cli.go | 32 +++++++++++++++++++++++++++-- x/ibc/23-commitment/merkle/utils.go | 1 - 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index b04527f07740..237a628bf4e8 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,32 +31,31 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { - val, _, height, err = ctx.query(path, nil) - return +func (ctx CLIContext) Query(path string) ([]byte, int64, error) { + return ctx.query(path, nil) } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { - val, _, height, err = ctx.query(path, data) - return +func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { + return ctx.query(path, data) } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { - val, _, height, err = ctx.queryStore(key, storeName, "key") - return +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { + return ctx.queryStore(key, storeName, "key") } // QueryProof performs a query to a Tendermint node with the provided key and // store name. It returns the result, the proof, and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QueryProof(key cmn.HexBytes, storeName string) (val []byte, proof *merkle.Proof, height int64, err error) { - return ctx.queryStore(key, storeName, "key") + path := fmt.Sprintf("/store/%s/%s", storeName, "key") + resp, err := ctx.queryABCI(abci.RequestQuery{Data: key, Path: path}) + return resp.Value, resp.Proof, resp.Height, err } // QueryABCI performs a query to a Tendermint node with the provide RequestQuery. @@ -69,7 +68,7 @@ func (ctx CLIContext) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, erro // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, height int64, err error) { - resRaw, _, height, err := ctx.queryStore(subspace, storeName, "subspace") + resRaw, height, err := ctx.queryStore(subspace, storeName, "subspace") if err != nil { return res, height, err } @@ -126,7 +125,7 @@ func (ctx CLIContext) queryABCI(req abci.RequestQuery) (resp abci.ResponseQuery, // query performs a query to a Tendermint node with the provided store name // and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *merkle.Proof, height int64, err error) { +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height int64, err error) { resp, err := ctx.queryABCI(abci.RequestQuery{ Path: path, Data: key, @@ -135,7 +134,7 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *m return } - return resp.Value, resp.Proof, resp.Height, nil + return resp.Value, resp.Height, nil } // Verify verifies the consensus proof at given height. @@ -194,7 +193,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, *merkle.Proof, int64, error) { +func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 6390bf5ccb8c..47302294efcc 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -52,6 +52,34 @@ func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, return } -func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle..Proof) { - val, proof, _, err := ctx.QueryProof(obj.ConsensusStateKey) +func query(ctx context.CLIContext, root merkle.Root, key []byte) ([]byte, merkle.Proof, error) { + resp, err := ctx.QueryABCI(root.RequestQuery(key)) + if err != nil { + return nil, merkle.Proof{}, err + } + proof := merkle.Proof{ + Key: key, + Proof: resp.Proof, + } + return resp.Value, proof, nil + +} + +func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { + val, proof, err := query(ctx, root, obj.ConsensusStateKey) + obj.Cdc.MustUnmarshalBinaryBare(val, &res) + return +} + +func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { + val, tmproof, _, err := ctx.QueryProof(obj.FrozenKey, "ibc") // TODO + if err != nil { + return + } + proof = merkle.Proof{ + Key: obj.FrozenKey, + Proof: tmproof, + } + obj.Cdc.MustUnmarshalBinaryBare(val, &res) + return } diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index daf4c36b171b..b16d0854e2af 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -30,6 +30,5 @@ func (root Root) Path() string { for _, inter := range root.KeyPath { path = path + "/" + string(inter) } - return path } From ae663575c50586cbf4cea5747babea72e52130cf Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 7 Jun 2019 23:47:41 +0200 Subject: [PATCH 025/182] add connection --- x/ibc/03-connection/manager.go | 387 +++++++++++++++++++++++++++++++++ x/ibc/03-connection/types.go | 37 ++++ 2 files changed, 424 insertions(+) create mode 100644 x/ibc/03-connection/manager.go create mode 100644 x/ibc/03-connection/types.go diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go new file mode 100644 index 000000000000..5317078f3796 --- /dev/null +++ b/x/ibc/03-connection/manager.go @@ -0,0 +1,387 @@ +package connection + +import ( + "errors" + + "github.com/cosmos/cosmos-sdk/store/mapping" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +// XXX: rename remote to something else +// XXX: all code using external KVStore should be defer-recovered in case of missing proofs + +type Manager struct { + protocol mapping.Mapping + + client client.Manager + + // CONTRACT: remote/self should not be used when remote + remote *Manager + self mapping.Indexer +} + +func NewManager(protocol, free mapping.Base, client client.Manager) Manager { + return Manager{ + protocol: mapping.NewMapping(protocol, []byte("/")), + + client: client, + + self: mapping.NewIndexer(free, []byte("/self"), mapping.Dec), + } +} + +// TODO: return newtyped manager +func NewRemoteManager(protocol mapping.Base, client client.Manager) Manager { + return NewManager(protocol, mapping.EmptyBase(), client) +} + +func (man Manager) Exec(remote Manager, fn func(Manager)) { + fn(Manager{ + protocol: man.protocol, + client: man.client, + self: man.self, + remote: &remote, + }) +} + +// CONTRACT: client and remote must be filled by the caller +func (man Manager) object(id string) Object { + return Object{ + id: id, + connection: man.protocol.Value([]byte(id)), + state: mapping.NewEnum(man.protocol.Value([]byte(id + "/state"))), + nexttimeout: mapping.NewInteger(man.protocol.Value([]byte(id+"/timeout")), mapping.Dec), + + self: man.self, + } +} + +func (man Manager) remoteobject(id string) Object { + return Object{ + id: id, + connection: man.remote.protocol.Value([]byte(id), commitment.Value), + state: commitment.Enum(man.protocol.Value([]byte(id+"/state"), commitment.Value)), + nexttimeout: commitment.Integer(man.protocol.Value([]byte(id+"/timeout"), commitment.Value), mapping.Dec), + } +} + +func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (nobj NihiloObject, err error) { + obj := man.object(id) + if obj.exists(ctx) { + err = errors.New("connection already exists for the provided id") + return + } + obj.connection.Set(ctx, connection) + obj.client, err = man.client.Query(ctx, connection.Client) + if err != nil { + return + } + remote := man.remote.object(connection.Counterparty) + obj.remote = &remote + return NihiloObject(obj), nil +} + +func (man Manager) Query(ctx sdk.Context, key string) (obj Object, err error) { + obj = man.object(key) + if !obj.exists(ctx) { + return Object{}, errors.New("connection not exists for the provided id") + } + conn := obj.Value(ctx) + obj.client, err = man.client.Query(ctx, conn.Client) + if err != nil { + return + } + remote := man.remote.object(conn.Counterparty) + obj.remote = &remote + return +} + +type NihiloObject Object + +type Object struct { + id string + connection mapping.Value + state mapping.Enum + nexttimeout mapping.Integer + + client client.Object + + // CONTRACT: remote/self should not be used when remote + remote *Object + self mapping.Indexer +} + +func (obj Object) ID() string { + return obj.id +} + +func (obj Object) ClientID() string { + return obj.client.ID() +} + +func (obj Object) exists(ctx sdk.Context) bool { + return obj.connection.Exists(ctx) +} + +func (obj Object) remove(ctx sdk.Context) { + obj.connection.Delete(ctx) + obj.state.Delete(ctx) + obj.nexttimeout.Delete(ctx) +} + +func (obj Object) assertSymmetric(ctx sdk.Context) error { + if !obj.Value(ctx).Symmetric(obj.id, obj.remote.Value(ctx)) { + return errors.New("unexpected counterparty connection value") + } + + return nil +} + +func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { + if uint64(ctx.BlockHeight()) > timeoutHeight { + return errors.New("timeout") + } + + return nil +} + +func (obj Object) Value(ctx sdk.Context) (res Connection) { + obj.connection.Get(ctx, &res) + return +} + +func (nobj NihiloObject) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) error { + + obj := Object(nobj) + if obj.exists(ctx) { + return errors.New("init on existing connection") + } + + if !obj.state.Transit(ctx, Idle, Init) { + return errors.New("init on non-idle connection") + } + + // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), + // which will ensure + // assert(get("connections/{identifier}") === null) and + // set("connections{identifier}", connection) + + obj.nexttimeout.Set(ctx, nextTimeoutHeight) + + return nil +} + +func (nobj NihiloObject) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { + + obj := Object(nobj) + if !obj.state.Transit(ctx, Idle, OpenTry) { + return errors.New("invalid state") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.remote.state.Is(ctx, Init) { + return errors.New("counterparty state not init") + } + + err = obj.assertSymmetric(ctx) + if err != nil { + return err + } + + if !obj.remote.nexttimeout.Is(ctx, uint64(timeoutHeight)) { + return errors.New("unexpected counterparty timeout value") + } + + var expected client.Client + obj.self.Get(ctx, expheight, &expected) + if !obj.remote.client.Is(ctx, expected) { + return errors.New("unexpected counterparty client value") + } + + // CONTRACT: OpenTry() should be called after man.Create(), not man.Query(), + // which will ensure + // assert(get("connections/{desiredIdentifier}") === null) and + // set("connections{identifier}", connection) + + obj.nexttimeout.Set(ctx, nextTimeoutHeight) + + return nil +} + +func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { + + if !obj.state.Transit(ctx, Init, Open) { + return errors.New("ack on non-init connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.remote.state.Is(ctx, OpenTry) { + return errors.New("counterparty state not try") + } + + err = obj.assertSymmetric(ctx) + if err != nil { + return err + } + + if !obj.remote.nexttimeout.Is(ctx, uint64(timeoutHeight)) { + return errors.New("unexpected counterparty timeout value") + } + + var expected client.Client + obj.self.Get(ctx, expheight, &expected) + if !obj.remote.client.Is(ctx, expected) { + return errors.New("unexpected counterparty client value") + } + + obj.nexttimeout.Set(ctx, uint64(nextTimeoutHeight)) + + return nil +} + +func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { + if !obj.state.Transit(ctx, OpenTry, Open) { + return errors.New("confirm on non-try connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.remote.state.Is(ctx, Open) { + return errors.New("counterparty state not open") + } + + err = obj.assertSymmetric(ctx) + if err != nil { + return err + } + + if !obj.remote.nexttimeout.Is(ctx, timeoutHeight) { + return errors.New("unexpected counterparty timeout value") + } + + obj.nexttimeout.Set(ctx, 0) + + return nil +} + +func (obj Object) OpenTimeout(ctx sdk.Context) error { + if !(uint64(obj.client.Value(ctx).GetBase().GetHeight()) > obj.nexttimeout.Get(ctx)) { + return errors.New("timeout height not yet reached") + } + + // XXX: double check if a user can bypass the verification logic somehow + switch obj.state.Get(ctx) { + case Init: + if !obj.remote.connection.Is(ctx, nil) { + return errors.New("counterparty connection exists") + } + case OpenTry: + if !(obj.remote.state.Is(ctx, Init) || + obj.remote.exists(ctx)) { + return errors.New("counterparty connection state not init") + } + // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) + case Open: + if obj.remote.state.Is(ctx, OpenTry) { + return errors.New("counterparty connection state not tryopen") + } + } + + obj.remove(ctx) + + return nil +} + +func (obj Object) CloseInit(ctx sdk.Context, nextTimeout uint64) error { + if !obj.state.Transit(ctx, Open, CloseTry) { + return errors.New("closeinit on non-open connection") + } + + obj.nexttimeout.Set(ctx, nextTimeout) + + return nil +} + +func (obj Object) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { + if !obj.state.Transit(ctx, Open, Closed) { + return errors.New("closetry on non-open connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.remote.state.Is(ctx, CloseTry) { + return errors.New("unexpected counterparty state value") + } + + if !obj.remote.nexttimeout.Is(ctx, timeoutHeight) { + return errors.New("unexpected counterparty timeout value") + } + + obj.nexttimeout.Set(ctx, nextTimeoutHeight) + + return nil +} + +func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { + if !obj.state.Transit(ctx, CloseTry, Closed) { + return errors.New("closeack on non-closetry connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.remote.state.Is(ctx, Closed) { + return errors.New("unexpected counterparty state value") + } + + if !obj.remote.nexttimeout.Is(ctx, timeoutHeight) { + return errors.New("unexpected counterparty timeout value") + } + + obj.nexttimeout.Set(ctx, 0) + + return nil +} + +func (obj Object) CloseTimeout(ctx sdk.Context) error { + if !(uint64(obj.client.Value(ctx).GetBase().GetHeight()) > obj.nexttimeout.Get(ctx)) { + return errors.New("timeout height not yet reached") + } + + // XXX: double check if the user can bypass the verification logic somehow + switch obj.state.Get(ctx) { + case CloseTry: + if !obj.remote.state.Is(ctx, Open) { + return errors.New("counterparty connection state not open") + } + case Closed: + if !obj.remote.state.Is(ctx, CloseTry) { + return errors.New("counterparty connection state not closetry") + } + } + + obj.state.Set(ctx, Open) + obj.nexttimeout.Set(ctx, 0) + + return nil + +} diff --git a/x/ibc/03-connection/types.go b/x/ibc/03-connection/types.go new file mode 100644 index 000000000000..50df047a6b21 --- /dev/null +++ b/x/ibc/03-connection/types.go @@ -0,0 +1,37 @@ +package connection + +type State = byte + +const ( + Idle State = iota + Init + OpenTry + Open + CloseTry + Closed +) + +// TODO: Connection is amino marshaled currently, need to implement MarshalBinary manually +type Connection struct { + Counterparty string + Client string + CounterpartyClient string +} + +func (conn Connection) Equal(conn0 Connection) bool { + return conn.Counterparty == conn0.Counterparty && + conn.Client == conn0.Client && + conn.CounterpartyClient == conn0.CounterpartyClient +} + +func (conn Connection) Symmetric(id string, conn0 Connection) bool { + return conn0.Equal(conn.Symmetry(id)) +} + +func (conn Connection) Symmetry(id string) Connection { + return Connection{ + Counterparty: id, + Client: conn.CounterpartyClient, + CounterpartyClient: conn.Client, + } +} From 7c44da1f4e0cec7bc88c8a4d902bc8db6128bb0a Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 8 Jun 2019 00:01:26 +0200 Subject: [PATCH 026/182] fix assertSymmetry --- x/ibc/03-connection/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 5317078f3796..e08ba97eb809 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -133,7 +133,7 @@ func (obj Object) remove(ctx sdk.Context) { } func (obj Object) assertSymmetric(ctx sdk.Context) error { - if !obj.Value(ctx).Symmetric(obj.id, obj.remote.Value(ctx)) { + if !obj.remote.connection.Is(ctx, obj.Value(ctx).Symmetry(obj.id)) { return errors.New("unexpected counterparty connection value") } From 043de514fef05a7a7abf604739a79f9e14a952ef Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 01:02:15 +0200 Subject: [PATCH 027/182] fix remote in progress in progress in progress --- x/ibc/03-connection/manager.go | 110 +++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index e08ba97eb809..09025ad5919f 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -3,6 +3,7 @@ package connection import ( "errors" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/mapping" sdk "github.com/cosmos/cosmos-sdk/types" @@ -18,33 +19,37 @@ type Manager struct { client client.Manager - // CONTRACT: remote/self should not be used when remote - remote *Manager - self mapping.Indexer + self mapping.Indexer + + counterparty CounterpartyManager } -func NewManager(protocol, free mapping.Base, client client.Manager) Manager { +func NewManager(protocol, free mapping.Base, clientman client.Manager) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/")), + protocol: mapping.NewMapping(protocol, []byte("/connection/")), + + client: clientman, - client: client, + self: mapping.NewIndexer(free, []byte("/connection/self/"), mapping.Dec), - self: mapping.NewIndexer(free, []byte("/self"), mapping.Dec), + counterparty: NewCounterpartyManager(protocol.Cdc()), } } -// TODO: return newtyped manager -func NewRemoteManager(protocol mapping.Base, client client.Manager) Manager { - return NewManager(protocol, mapping.EmptyBase(), client) +type CounterpartyManager struct { + protocol commitment.Mapping + + client client.CounterpartyManager } -func (man Manager) Exec(remote Manager, fn func(Manager)) { - fn(Manager{ - protocol: man.protocol, - client: man.client, - self: man.self, - remote: &remote, - }) +func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { + protocol := commitment.NewBase(cdc) + + return CounterpartyManager{ + protocol: commitment.NewMapping(protocol, []byte("/connection/")), + + client: client.NewCounterpartyManager(protocol), + } } // CONTRACT: client and remote must be filled by the caller @@ -59,12 +64,13 @@ func (man Manager) object(id string) Object { } } -func (man Manager) remoteobject(id string) Object { - return Object{ +// CONTRACT: client must be filled by the caller +func (man CounterpartyManager) object(id string) CounterObject { + return CounterObject{ id: id, - connection: man.remote.protocol.Value([]byte(id), commitment.Value), - state: commitment.Enum(man.protocol.Value([]byte(id+"/state"), commitment.Value)), - nexttimeout: commitment.Integer(man.protocol.Value([]byte(id+"/timeout"), commitment.Value), mapping.Dec), + connection: man.protocol.Value([]byte(id)), + state: commitment.NewEnum(man.protocol.Value([]byte(id + "/state"))), + nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(id+"/timeout")), mapping.Dec), } } @@ -79,8 +85,8 @@ func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (no if err != nil { return } - remote := man.remote.object(connection.Counterparty) - obj.remote = &remote + obj.counterparty = man.counterparty.object(connection.Counterparty) + obj.counterparty.client = man.counterparty.client.Query(connection.CounterpartyClient) return NihiloObject(obj), nil } @@ -94,8 +100,8 @@ func (man Manager) Query(ctx sdk.Context, key string) (obj Object, err error) { if err != nil { return } - remote := man.remote.object(conn.Counterparty) - obj.remote = &remote + obj.counterparty = man.counterparty.object(conn.Counterparty) + obj.counterparty.client = man.counterparty.client.Query(conn.CounterpartyClient) return } @@ -109,9 +115,17 @@ type Object struct { client client.Object - // CONTRACT: remote/self should not be used when remote - remote *Object - self mapping.Indexer + counterparty CounterObject + self mapping.Indexer +} + +type CounterObject struct { + id string + connection commitment.Value + state commitment.Enum + nexttimeout commitment.Integer + + client client.CounterObject } func (obj Object) ID() string { @@ -133,7 +147,7 @@ func (obj Object) remove(ctx sdk.Context) { } func (obj Object) assertSymmetric(ctx sdk.Context) error { - if !obj.remote.connection.Is(ctx, obj.Value(ctx).Symmetry(obj.id)) { + if !obj.counterparty.connection.Is(ctx, obj.Value(ctx).Symmetry(obj.id)) { return errors.New("unexpected counterparty connection value") } @@ -186,7 +200,7 @@ func (nobj NihiloObject) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeigh return err } - if !obj.remote.state.Is(ctx, Init) { + if !obj.counterparty.state.Is(ctx, Init) { return errors.New("counterparty state not init") } @@ -195,13 +209,13 @@ func (nobj NihiloObject) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeigh return err } - if !obj.remote.nexttimeout.Is(ctx, uint64(timeoutHeight)) { + if !obj.counterparty.nexttimeout.Is(ctx, uint64(timeoutHeight)) { return errors.New("unexpected counterparty timeout value") } var expected client.Client obj.self.Get(ctx, expheight, &expected) - if !obj.remote.client.Is(ctx, expected) { + if !obj.counterparty.client.Is(ctx, expected) { return errors.New("unexpected counterparty client value") } @@ -226,7 +240,7 @@ func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, next return err } - if !obj.remote.state.Is(ctx, OpenTry) { + if !obj.counterparty.state.Is(ctx, OpenTry) { return errors.New("counterparty state not try") } @@ -235,13 +249,13 @@ func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, next return err } - if !obj.remote.nexttimeout.Is(ctx, uint64(timeoutHeight)) { + if !obj.counterparty.nexttimeout.Is(ctx, uint64(timeoutHeight)) { return errors.New("unexpected counterparty timeout value") } var expected client.Client obj.self.Get(ctx, expheight, &expected) - if !obj.remote.client.Is(ctx, expected) { + if !obj.counterparty.client.Is(ctx, expected) { return errors.New("unexpected counterparty client value") } @@ -260,7 +274,7 @@ func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { return err } - if !obj.remote.state.Is(ctx, Open) { + if !obj.counterparty.state.Is(ctx, Open) { return errors.New("counterparty state not open") } @@ -269,7 +283,7 @@ func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { return err } - if !obj.remote.nexttimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.nexttimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } @@ -286,17 +300,17 @@ func (obj Object) OpenTimeout(ctx sdk.Context) error { // XXX: double check if a user can bypass the verification logic somehow switch obj.state.Get(ctx) { case Init: - if !obj.remote.connection.Is(ctx, nil) { + if !obj.counterparty.connection.Is(ctx, nil) { return errors.New("counterparty connection exists") } case OpenTry: - if !(obj.remote.state.Is(ctx, Init) || - obj.remote.exists(ctx)) { + if !(obj.counterparty.state.Is(ctx, Init) || + obj.counterparty.exists(ctx)) { return errors.New("counterparty connection state not init") } // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) case Open: - if obj.remote.state.Is(ctx, OpenTry) { + if obj.counterparty.state.Is(ctx, OpenTry) { return errors.New("counterparty connection state not tryopen") } } @@ -326,11 +340,11 @@ func (obj Object) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uin return err } - if !obj.remote.state.Is(ctx, CloseTry) { + if !obj.counterparty.state.Is(ctx, CloseTry) { return errors.New("unexpected counterparty state value") } - if !obj.remote.nexttimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.nexttimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } @@ -349,11 +363,11 @@ func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { return err } - if !obj.remote.state.Is(ctx, Closed) { + if !obj.counterparty.state.Is(ctx, Closed) { return errors.New("unexpected counterparty state value") } - if !obj.remote.nexttimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.nexttimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } @@ -370,11 +384,11 @@ func (obj Object) CloseTimeout(ctx sdk.Context) error { // XXX: double check if the user can bypass the verification logic somehow switch obj.state.Get(ctx) { case CloseTry: - if !obj.remote.state.Is(ctx, Open) { + if !obj.counterparty.state.Is(ctx, Open) { return errors.New("counterparty connection state not open") } case Closed: - if !obj.remote.state.Is(ctx, CloseTry) { + if !obj.counterparty.state.Is(ctx, CloseTry) { return errors.New("counterparty connection state not closetry") } } From b2841199b6031f0239b7aab36a6563672c9efd33 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:49:11 +0200 Subject: [PATCH 028/182] reformat over dependent icss --- x/ibc/03-connection/manager.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 09025ad5919f..d741d9f21977 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -140,6 +140,20 @@ func (obj Object) exists(ctx sdk.Context) bool { return obj.connection.Exists(ctx) } +// If there is no proof provided, assume not exists +func (obj CounterObject) exists(ctx sdk.Context) bool { + /* + // XXX + if !obj.connection.Proven(ctx) { + return false + } + + return obj.connection.Exists(ctx) + */ + + return false +} + func (obj Object) remove(ctx sdk.Context) { obj.connection.Delete(ctx) obj.state.Delete(ctx) From 33b3b2de594762a7f97453a955eabcf53d8aaaef Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 19:11:21 +0200 Subject: [PATCH 029/182] add CounterManager.Query/90 --- x/ibc/03-connection/manager.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index d741d9f21977..fd5e4a7ed78d 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -105,6 +105,11 @@ func (man Manager) Query(ctx sdk.Context, key string) (obj Object, err error) { return } +// XXX: add HasProof() method to commitment.Store, and check it here +func (man CounterpartyManager) Query(id string) CounterObject { + return man.object(id) +} + type NihiloObject Object type Object struct { From f835bab6ca55ad4d010fc2483020fbbe3ef158b7 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 12 Jun 2019 00:29:39 +0200 Subject: [PATCH 030/182] reflect downstream ics --- x/ibc/03-connection/manager.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index fd5e4a7ed78d..71009a7cb27b 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -4,7 +4,7 @@ import ( "errors" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/mapping" + "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" @@ -15,22 +15,22 @@ import ( // XXX: all code using external KVStore should be defer-recovered in case of missing proofs type Manager struct { - protocol mapping.Mapping + protocol state.Mapping client client.Manager - self mapping.Indexer + self state.Indexer counterparty CounterpartyManager } -func NewManager(protocol, free mapping.Base, clientman client.Manager) Manager { +func NewManager(protocol, free state.Base, clientman client.Manager) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/connection/")), + protocol: state.NewMapping(protocol, []byte("/connection/")), client: clientman, - self: mapping.NewIndexer(free, []byte("/connection/self/"), mapping.Dec), + self: state.NewIndexer(free, []byte("/connection/self/"), state.Dec), counterparty: NewCounterpartyManager(protocol.Cdc()), } @@ -57,8 +57,8 @@ func (man Manager) object(id string) Object { return Object{ id: id, connection: man.protocol.Value([]byte(id)), - state: mapping.NewEnum(man.protocol.Value([]byte(id + "/state"))), - nexttimeout: mapping.NewInteger(man.protocol.Value([]byte(id+"/timeout")), mapping.Dec), + state: state.NewEnum(man.protocol.Value([]byte(id + "/state"))), + nexttimeout: state.NewInteger(man.protocol.Value([]byte(id+"/timeout")), state.Dec), self: man.self, } @@ -70,7 +70,7 @@ func (man CounterpartyManager) object(id string) CounterObject { id: id, connection: man.protocol.Value([]byte(id)), state: commitment.NewEnum(man.protocol.Value([]byte(id + "/state"))), - nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(id+"/timeout")), mapping.Dec), + nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(id+"/timeout")), state.Dec), } } @@ -114,14 +114,14 @@ type NihiloObject Object type Object struct { id string - connection mapping.Value - state mapping.Enum - nexttimeout mapping.Integer + connection state.Value + state state.Enum + nexttimeout state.Integer client client.Object counterparty CounterObject - self mapping.Indexer + self state.Indexer } type CounterObject struct { @@ -232,7 +232,7 @@ func (nobj NihiloObject) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeigh return errors.New("unexpected counterparty timeout value") } - var expected client.Client + var expected client.ConsensusState obj.self.Get(ctx, expheight, &expected) if !obj.counterparty.client.Is(ctx, expected) { return errors.New("unexpected counterparty client value") @@ -272,7 +272,7 @@ func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, next return errors.New("unexpected counterparty timeout value") } - var expected client.Client + var expected client.ConsensusState obj.self.Get(ctx, expheight, &expected) if !obj.counterparty.client.Is(ctx, expected) { return errors.New("unexpected counterparty client value") @@ -312,7 +312,7 @@ func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { } func (obj Object) OpenTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.Value(ctx).GetBase().GetHeight()) > obj.nexttimeout.Get(ctx)) { + if !(uint64(obj.client.Value(ctx).GetHeight()) > obj.nexttimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } @@ -396,7 +396,7 @@ func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { } func (obj Object) CloseTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.Value(ctx).GetBase().GetHeight()) > obj.nexttimeout.Get(ctx)) { + if !(uint64(obj.client.Value(ctx).GetHeight()) > obj.nexttimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } From 6437f5928c773b78916ec69aaf8aadfd3a44f3a1 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:48:52 +0200 Subject: [PATCH 031/182] fix --- x/ibc/03-connection/manager.go | 12 ++---------- x/ibc/23-commitment/store.go | 10 ++++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 71009a7cb27b..4f876c326cfa 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -11,9 +11,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -// XXX: rename remote to something else -// XXX: all code using external KVStore should be defer-recovered in case of missing proofs - type Manager struct { protocol state.Mapping @@ -105,11 +102,6 @@ func (man Manager) Query(ctx sdk.Context, key string) (obj Object, err error) { return } -// XXX: add HasProof() method to commitment.Store, and check it here -func (man CounterpartyManager) Query(id string) CounterObject { - return man.object(id) -} - type NihiloObject Object type Object struct { @@ -312,7 +304,7 @@ func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { } func (obj Object) OpenTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.Value(ctx).GetHeight()) > obj.nexttimeout.Get(ctx)) { + if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nexttimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } @@ -396,7 +388,7 @@ func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { } func (obj Object) CloseTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.Value(ctx).GetHeight()) > obj.nexttimeout.Get(ctx)) { + if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nexttimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index 8cfaef4baaa1..7ad593d6f9d2 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -7,6 +7,7 @@ import ( type Store interface { Prove(key, value []byte) bool + HasProof(key []byte) bool } var _ Store = prefix{} @@ -23,6 +24,10 @@ func NewPrefix(store Store, pref []byte) prefix { } } +func (prefix prefix) HasProof(key []byte) bool { + return prefix.store.HasProof(join(prefix.prefix, key)) +} + func (prefix prefix) Prove(key, value []byte) bool { return prefix.store.Prove(join(prefix.prefix, key), value) } @@ -77,6 +82,11 @@ func (store store) Prove(key, value []byte) bool { return true } +func (store store) HasProof(key []byte) bool { + _, ok := store.proofs[string(key)] + return ok +} + func (store store) Proven(key []byte) bool { _, ok := store.Get(key) return ok From 927a2d07e8bb0b4d45bfc9e2b9832858a8f402b2 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 18:54:40 +0200 Subject: [PATCH 032/182] add test in progress --- x/ibc/03-connection/manager.go | 69 ++++---- x/ibc/03-connection/tests/connection_test.go | 22 +++ x/ibc/03-connection/tests/types.go | 159 +++++++++++++++++++ 3 files changed, 217 insertions(+), 33 deletions(-) create mode 100644 x/ibc/03-connection/tests/connection_test.go create mode 100644 x/ibc/03-connection/tests/types.go diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 4f876c326cfa..f788713bd634 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -21,14 +21,12 @@ type Manager struct { counterparty CounterpartyManager } -func NewManager(protocol, free state.Base, clientman client.Manager) Manager { +func NewManager(protocol state.Base, clientman client.Manager) Manager { return Manager{ protocol: state.NewMapping(protocol, []byte("/connection/")), client: clientman, - self: state.NewIndexer(free, []byte("/connection/self/"), state.Dec), - counterparty: NewCounterpartyManager(protocol.Cdc()), } } @@ -71,8 +69,8 @@ func (man CounterpartyManager) object(id string) CounterObject { } } -func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (nobj NihiloObject, err error) { - obj := man.object(id) +func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (obj Object, err error) { + obj = man.object(id) if obj.exists(ctx) { err = errors.New("connection already exists for the provided id") return @@ -84,7 +82,7 @@ func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (no } obj.counterparty = man.counterparty.object(connection.Counterparty) obj.counterparty.client = man.counterparty.client.Query(connection.CounterpartyClient) - return NihiloObject(obj), nil + return obj, nil } func (man Manager) Query(ctx sdk.Context, key string) (obj Object, err error) { @@ -92,7 +90,7 @@ func (man Manager) Query(ctx sdk.Context, key string) (obj Object, err error) { if !obj.exists(ctx) { return Object{}, errors.New("connection not exists for the provided id") } - conn := obj.Value(ctx) + conn := obj.Connection(ctx) obj.client, err = man.client.Query(ctx, conn.Client) if err != nil { return @@ -102,8 +100,6 @@ func (man Manager) Query(ctx sdk.Context, key string) (obj Object, err error) { return } -type NihiloObject Object - type Object struct { id string connection state.Value @@ -129,8 +125,17 @@ func (obj Object) ID() string { return obj.id } -func (obj Object) ClientID() string { - return obj.client.ID() +func (obj Object) Connection(ctx sdk.Context) (res Connection) { + obj.connection.Get(ctx, &res) + return +} + +func (obj Object) State(ctx sdk.Context) byte { + return obj.state.Get(ctx) +} + +func (obj Object) Client() client.Object { + return obj.client } func (obj Object) exists(ctx sdk.Context) bool { @@ -158,7 +163,7 @@ func (obj Object) remove(ctx sdk.Context) { } func (obj Object) assertSymmetric(ctx sdk.Context) error { - if !obj.counterparty.connection.Is(ctx, obj.Value(ctx).Symmetry(obj.id)) { + if !obj.counterparty.connection.Is(ctx, obj.Connection(ctx).Symmetry(obj.id)) { return errors.New("unexpected counterparty connection value") } @@ -173,14 +178,7 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { return nil } -func (obj Object) Value(ctx sdk.Context) (res Connection) { - obj.connection.Get(ctx, &res) - return -} - -func (nobj NihiloObject) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) error { - - obj := Object(nobj) +func (obj Object) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) error { if obj.exists(ctx) { return errors.New("init on existing connection") } @@ -199,9 +197,7 @@ func (nobj NihiloObject) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) err return nil } -func (nobj NihiloObject) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { - - obj := Object(nobj) +func (obj Object) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { if !obj.state.Transit(ctx, Idle, OpenTry) { return errors.New("invalid state") } @@ -224,11 +220,15 @@ func (nobj NihiloObject) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeigh return errors.New("unexpected counterparty timeout value") } - var expected client.ConsensusState - obj.self.Get(ctx, expheight, &expected) - if !obj.counterparty.client.Is(ctx, expected) { - return errors.New("unexpected counterparty client value") - } + // TODO: commented out, need to check whether the stored client is compatible + // make a separate module that manages recent n block headers + /* + var expected client.ConsensusState + obj.self.Get(ctx, expheight, &expected) + if !obj.counterparty.client.Is(ctx, expected) { + return errors.New("unexpected counterparty client value") + } + */ // CONTRACT: OpenTry() should be called after man.Create(), not man.Query(), // which will ensure @@ -264,11 +264,14 @@ func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, next return errors.New("unexpected counterparty timeout value") } - var expected client.ConsensusState - obj.self.Get(ctx, expheight, &expected) - if !obj.counterparty.client.Is(ctx, expected) { - return errors.New("unexpected counterparty client value") - } + // TODO: commented out, implement in v1 + /* + var expected client.ConsensusState + obj.self.Get(ctx, expheight, &expected) + if !obj.counterparty.client.Is(ctx, expected) { + return errors.New("unexpected counterparty client value") + } + */ obj.nexttimeout.Set(ctx, uint64(nextTimeoutHeight)) diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go new file mode 100644 index 000000000000..cdd4699b74b5 --- /dev/null +++ b/x/ibc/03-connection/tests/connection_test.go @@ -0,0 +1,22 @@ +package connection + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" +) + +func registerCodec(cdc *codec.Codec) { + client.RegisterCodec(cdc) +} + +func TestHandshake(t *testing.T) { + cdc := codec.New() + + node := NewNode(tendermint.NewMockValidators(10), tendermint.NewMockValidators(10)) +} diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go new file mode 100644 index 000000000000..cf6faa01712f --- /dev/null +++ b/x/ibc/03-connection/tests/types.go @@ -0,0 +1,159 @@ +package connection + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" +) + +type Node struct { + Name string + *tendermint.Node + Counterparty *CounterpartyNode + + State connection.State + + Cdc *codec.Codec +} + +func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { + res := &Node{ + Name: "self", // hard coded, doesnt matter + Node: tendermint.NewNode(self), + + State: connection.Idle, + Cdc: cdc, + } + + res.Counterparty = &CounterpartyNode{ + Name: "counterparty", + Node: tendermint.NewNode(counter), + Cdc: cdc, + + SelfName: &res.Name, + State: &res.State, + } + + return res +} + +func (node *Node) Object(t *testing.T) (sdk.Context, connection.Object) { + ctx, man, conn := node.Context(), node.Manager(), node.Connection() + switch node.State { + case connection.Idle: + obj, err := man.Create(ctx, node.Name, conn) + require.NoError(t, err) + return ctx, obj + default: + obj, err := man.Query(ctx, node.Name) + require.NoError(t, err) + require.Equal(t, conn, obj.Connection(ctx)) + return ctx, obj + } +} + +func (node *Node) Manager() connection.Manager { + base := state.NewBase(node.Cdc, node.Key) + protocol := base.Prefix([]byte("protocol/")) + free := base.Prefix([]byte("free/")) + clientman := client.NewManager(protocol, free, client.IntegerIDGenerator) + return connection.NewManager(base, clientman) +} + +func (node *Node) Connection() connection.Connection { + return connection.Connection{ + Counterparty: node.Counterparty.Name, + Client: node.Name + "client", + CounterpartyClient: node.Counterparty.Name + "client", + } +} + +type CounterpartyNode struct { + Name string + *tendermint.Node + + Cdc *codec.Codec + + // pointer to self + // TODO: improve + State *connection.State + SelfName *string +} + +func (node *CounterpartyNode) Object(t *testing.T) (sdk.Context, connection.Object) { + ctx, man, conn := node.Context(), node.Manager(), node.Connection() + switch *node.State { + case connection.Idle: + obj, err := man.Create(ctx, node.Name, conn) + require.NoError(t, err) + return ctx, obj + default: + obj, err := man.Query(ctx, node.Name) + require.NoError(t, err) + require.Equal(t, conn, obj.Connection(ctx)) + return ctx, obj + } +} +func (node *CounterpartyNode) Connection() connection.Connection { + return connection.Connection{ + Counterparty: *node.SelfName, + Client: node.Name + "client", + CounterpartyClient: *node.SelfName + "client", + } +} + +func (node *CounterpartyNode) Manager() connection.Manager { + base := state.NewBase(node.Cdc, node.Key) + protocol := base.Prefix([]byte("protocol/")) + free := base.Prefix([]byte("free/")) + clientman := client.NewManager(protocol, free, client.IntegerIDGenerator) + return connection.NewManager(base, clientman) +} + +func (node *Node) Advance(t *testing.T) { + switch node.State { + case connection.Idle: // self: Idle -> Init + ctx, obj := node.Object(t) + require.Equal(t, connection.Idle, obj.State(ctx)) + err := obj.OpenInit(ctx, 100) // TODO: test timeout + require.NoError(t, err) + require.Equal(t, connection.Init, obj.State(ctx)) + require.Equal(t, node.Connection(), obj.Connection(ctx)) + node.State = connection.Init + case connection.Init: // counter: Idle -> OpenTry + ctx, obj := node.Counterparty.Object(t) + require.Equal(t, connection.Idle, obj.State(ctx)) + err := obj.OpenTry(ctx, 0 /*TODO*/, 100 /*TODO*/, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, connection.OpenTry, obj.State(ctx)) + require.Equal(t, node.Counterparty.Connection(), obj.Connection(ctx)) + node.State = connection.OpenTry + case connection.OpenTry: // self: Init -> Open + ctx, obj := node.Object(t) + require.Equal(t, connection.Init, obj.State(ctx)) + err := obj.OpenAck(ctx, 0 /*TODO*/, 100 /*TODO*/, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, connection.Open, obj.State(ctx)) + require.Equal(t, node.Connection(), obj.Connection(ctx)) + node.State = connection.Open + case connection.Open: // counter: OpenTry -> Open + ctx, obj := node.Counterparty.Object(t) + require.Equal(t, connection.OpenTry, obj.State(ctx)) + err := obj.OpenConfirm(ctx, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, connection.Open, obj.State(ctx)) + require.Equal(t, node.Counterparty.Connection(), obj.Connection(ctx)) + node.State = connection.CloseTry + // case connection.CloseTry // self: Open -> CloseTry + default: + return + } +} From c0ca538099463aeeffce5cac534c6811eff58266 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 19:09:32 +0200 Subject: [PATCH 033/182] add test in progress --- x/ibc/03-connection/tests/connection_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index cdd4699b74b5..e2b47963044e 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -8,15 +8,26 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + tmclient "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) func registerCodec(cdc *codec.Codec) { client.RegisterCodec(cdc) + tmclient.RegisterCodec(cdc) + commitment.RegisterCodec(cdc) + merkle.RegisterCodec(cdc) } func TestHandshake(t *testing.T) { cdc := codec.New() + registerCodec(cdc) - node := NewNode(tendermint.NewMockValidators(10), tendermint.NewMockValidators(10)) + node := NewNode(tendermint.NewMockValidators(10), tendermint.NewMockValidators(10), cdc) + node.Advance(t) + node.Advance(t) + node.Advance(t) + node.Advance(t) } From 67818d53d069f5f9884b62a6a1f23ff4ecf505e2 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 28 Jun 2019 17:43:53 +0200 Subject: [PATCH 034/182] add test in progress/ --- x/ibc/02-client/cli.go | 32 ----- .../tendermint/tests/tendermint_test.go | 6 +- x/ibc/02-client/tendermint/tests/types.go | 39 ++--- x/ibc/03-connection/cli.go | 69 +++++++++ x/ibc/03-connection/manager.go | 54 +++---- x/ibc/03-connection/tests/connection_test.go | 32 ++++- x/ibc/03-connection/tests/types.go | 136 +++++++++--------- x/ibc/23-commitment/store.go | 23 +-- 8 files changed, 229 insertions(+), 162 deletions(-) create mode 100644 x/ibc/03-connection/cli.go diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 47302294efcc..2592e697573c 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -51,35 +51,3 @@ func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof, err = obj.query(ctx, obj.FrozenKey, &res) return } - -func query(ctx context.CLIContext, root merkle.Root, key []byte) ([]byte, merkle.Proof, error) { - resp, err := ctx.QueryABCI(root.RequestQuery(key)) - if err != nil { - return nil, merkle.Proof{}, err - } - proof := merkle.Proof{ - Key: key, - Proof: resp.Proof, - } - return resp.Value, proof, nil - -} - -func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { - val, proof, err := query(ctx, root, obj.ConsensusStateKey) - obj.Cdc.MustUnmarshalBinaryBare(val, &res) - return -} - -func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { - val, tmproof, _, err := ctx.QueryProof(obj.FrozenKey, "ibc") // TODO - if err != nil { - return - } - proof = merkle.Proof{ - Key: obj.FrozenKey, - Proof: tmproof, - } - obj.Cdc.MustUnmarshalBinaryBare(val, &res) - return -} diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index 8a1c764f50f2..d4a0397ef06b 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -7,17 +7,17 @@ import ( ) func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10), newRoot()) + node := NewNode(NewMockValidators(100, 10), NewRoot([]byte("qwertyuiop"))) node.Commit() - verifier := node.LastStateVerifier(newRoot()) + verifier := node.LastStateVerifier() for i := 0; i < 100; i++ { header := node.Commit() if i%interval == 0 { - err := verifier.Validate(header, node.PrevValset, node.Valset) + err := verifier.Validate(header) if ok { require.NoError(t, err) } else { diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 5e0af44f3806..49b2a3a9460c 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -30,6 +30,9 @@ func newRoot() merkle.Root { const chainid = "testchain" +func NewRoot(keyPrefix []byte) merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, keyPrefix) +} func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { key := sdk.NewKVStoreKey("test") db := dbm.NewMemDB() @@ -76,7 +79,7 @@ func (node *Node) Last() tmtypes.SignedHeader { return node.Commits[len(node.Commits)-1] } -func (node *Node) Commit() tmtypes.SignedHeader { +func (node *Node) Commit() tendermint.Header { valsethash := node.Valset.ValidatorSet().Hash() nextvalset := node.Valset.Mutate() nextvalsethash := nextvalset.ValidatorSet().Hash() @@ -99,12 +102,17 @@ func (node *Node) Commit() tmtypes.SignedHeader { node.PrevValset = node.Valset node.Valset = nextvalset node.Commits = append(node.Commits, commit) + node.Root = node.Root.Update(header.AppHash).(merkle.Root) - return commit + return tendermint.Header{ + SignedHeader: commit, + ValidatorSet: node.PrevValset.ValidatorSet(), + NextValidatorSet: node.Valset.ValidatorSet(), + } } -func (node *Node) LastStateVerifier(root merkle.Root) *Verifier { - return NewVerifier(node.Last(), node.Valset, root) +func (node *Node) LastStateVerifier() *Verifier { + return NewVerifier(node.Last(), node.Valset, node.Root) } func (node *Node) Context() sdk.Context { @@ -126,14 +134,8 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root me } } -func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset MockValidators) error { - newcs, err := v.ConsensusState.Validate( - tendermint.Header{ - SignedHeader: header, - ValidatorSet: valset.ValidatorSet(), - NextValidatorSet: nextvalset.ValidatorSet(), - }, - ) +func (v *Verifier) Validate(header tendermint.Header) error { + newcs, err := v.ConsensusState.Validate(header) if err != nil { return err } @@ -142,8 +144,8 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock return nil } -func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.QueryMultiStore(node.Cms, k) +func (node *Node) Query(t *testing.T, k []byte) ([]byte, commitment.Proof) { + code, value, proof := node.Root.QueryMultiStore(node.Cms, k) require.Equal(t, uint32(0), code) return value, proof } @@ -154,7 +156,7 @@ func (node *Node) Set(k, value []byte) { // nolint:deadcode,unused func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10), newRoot()) + node := NewNode(NewMockValidators(100, 10), NewRoot([]byte{0x34, 0x90, 0xDA})) node.Commit() @@ -170,15 +172,14 @@ func testProof(t *testing.T) { kvps = append(kvps, cmn.KVPair{Key: k, Value: v}) node.Set(k, v) } - header := node.Commit() + _ = node.Commit() proofs := []commitment.Proof{} - root := node.Root.Update(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, root.(merkle.Root), kvp.Key) + v, p := node.Query(t, kvp.Key) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore(root, proofs) + cstore, err := commitment.NewStore(node.Root, proofs) require.NoError(t, err) for _, kvp := range kvps { diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go new file mode 100644 index 000000000000..3df848ffb953 --- /dev/null +++ b/x/ibc/03-connection/cli.go @@ -0,0 +1,69 @@ +package connection + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +// CLIObject stores the key for each object fields +type CLIObject struct { + ID string + ConnectionKey []byte + StateKey []byte + NextTimeoutKey []byte + + Client client.CLIObject + + Root merkle.Root + Cdc *codec.Codec +} + +func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { + obj := man.object(id) + return CLIObject{ + ID: obj.id, + ConnectionKey: obj.connection.Key(), + StateKey: obj.state.Key(), + NextTimeoutKey: obj.nextTimeout.Key(), + + // TODO: unify man.CLIObject() <=> obj.CLI() + Client: obj.client.CLI(root), + + Root: root, + Cdc: obj.connection.Cdc(), + } +} + +func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { + resp, err := ctx.QueryABCI(obj.Root.RequestQuery(key)) + if err != nil { + return merkle.Proof{}, err + } + proof := merkle.Proof{ + Key: key, + Proof: resp.Proof, + } + err = obj.Cdc.UnmarshalBinaryBare(resp.Value, ptr) + return proof, err + +} + +func (obj CLIObject) Connection(ctx context.CLIContext, root merkle.Root) (res Connection, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.ConnectionKey, &res) + return +} + +func (obj CLIObject) State(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.StateKey, &res) + return +} + +func (obj CLIObject) NextTimeout(ctx context.CLIContext, root merkle.Root) (res time.Time, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.NextTimeoutKey, &res) + return +} diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index f788713bd634..7c0668bc0dbd 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -2,6 +2,7 @@ package connection import ( "errors" + "fmt" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" @@ -53,7 +54,7 @@ func (man Manager) object(id string) Object { id: id, connection: man.protocol.Value([]byte(id)), state: state.NewEnum(man.protocol.Value([]byte(id + "/state"))), - nexttimeout: state.NewInteger(man.protocol.Value([]byte(id+"/timeout")), state.Dec), + nextTimeout: state.NewInteger(man.protocol.Value([]byte(id+"/timeout")), state.Dec), self: man.self, } @@ -65,11 +66,12 @@ func (man CounterpartyManager) object(id string) CounterObject { id: id, connection: man.protocol.Value([]byte(id)), state: commitment.NewEnum(man.protocol.Value([]byte(id + "/state"))), - nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(id+"/timeout")), state.Dec), + nextTimeout: commitment.NewInteger(man.protocol.Value([]byte(id+"/timeout")), state.Dec), } } func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (obj Object, err error) { + fmt.Println("create", id, connection) obj = man.object(id) if obj.exists(ctx) { err = errors.New("connection already exists for the provided id") @@ -104,7 +106,7 @@ type Object struct { id string connection state.Value state state.Enum - nexttimeout state.Integer + nextTimeout state.Integer client client.Object @@ -116,7 +118,7 @@ type CounterObject struct { id string connection commitment.Value state commitment.Enum - nexttimeout commitment.Integer + nextTimeout commitment.Integer client client.CounterObject } @@ -159,7 +161,7 @@ func (obj CounterObject) exists(ctx sdk.Context) bool { func (obj Object) remove(ctx sdk.Context) { obj.connection.Delete(ctx) obj.state.Delete(ctx) - obj.nexttimeout.Delete(ctx) + obj.nextTimeout.Delete(ctx) } func (obj Object) assertSymmetric(ctx sdk.Context) error { @@ -178,11 +180,8 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { return nil } +// Using proofs: none func (obj Object) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) error { - if obj.exists(ctx) { - return errors.New("init on existing connection") - } - if !obj.state.Transit(ctx, Idle, Init) { return errors.New("init on non-idle connection") } @@ -192,31 +191,36 @@ func (obj Object) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) error { // assert(get("connections/{identifier}") === null) and // set("connections{identifier}", connection) - obj.nexttimeout.Set(ctx, nextTimeoutHeight) + obj.nextTimeout.Set(ctx, nextTimeoutHeight) return nil } +// Using proofs: counterparty.{connection,state,nextTimeout,client} func (obj Object) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { if !obj.state.Transit(ctx, Idle, OpenTry) { return errors.New("invalid state") } + fmt.Println(12345) err := assertTimeout(ctx, timeoutHeight) if err != nil { return err } + fmt.Println(67890) if !obj.counterparty.state.Is(ctx, Init) { return errors.New("counterparty state not init") } + fmt.Println(97) err = obj.assertSymmetric(ctx) if err != nil { return err } - if !obj.counterparty.nexttimeout.Is(ctx, uint64(timeoutHeight)) { + fmt.Println(65) + if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { return errors.New("unexpected counterparty timeout value") } @@ -235,11 +239,12 @@ func (obj Object) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, next // assert(get("connections/{desiredIdentifier}") === null) and // set("connections{identifier}", connection) - obj.nexttimeout.Set(ctx, nextTimeoutHeight) + obj.nextTimeout.Set(ctx, nextTimeoutHeight) return nil } +// Using proofs: counterparty.{connection,state, nextTimeout} func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { if !obj.state.Transit(ctx, Init, Open) { @@ -260,7 +265,7 @@ func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, next return err } - if !obj.counterparty.nexttimeout.Is(ctx, uint64(timeoutHeight)) { + if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { return errors.New("unexpected counterparty timeout value") } @@ -273,11 +278,12 @@ func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, next } */ - obj.nexttimeout.Set(ctx, uint64(nextTimeoutHeight)) + obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) return nil } +// Using proofs: counterparty.{connection,state, nextTimeout} func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { if !obj.state.Transit(ctx, OpenTry, Open) { return errors.New("confirm on non-try connection") @@ -297,17 +303,17 @@ func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { return err } - if !obj.counterparty.nexttimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } - obj.nexttimeout.Set(ctx, 0) + obj.nextTimeout.Set(ctx, 0) return nil } func (obj Object) OpenTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nexttimeout.Get(ctx)) { + if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } @@ -339,7 +345,7 @@ func (obj Object) CloseInit(ctx sdk.Context, nextTimeout uint64) error { return errors.New("closeinit on non-open connection") } - obj.nexttimeout.Set(ctx, nextTimeout) + obj.nextTimeout.Set(ctx, nextTimeout) return nil } @@ -358,11 +364,11 @@ func (obj Object) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uin return errors.New("unexpected counterparty state value") } - if !obj.counterparty.nexttimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } - obj.nexttimeout.Set(ctx, nextTimeoutHeight) + obj.nextTimeout.Set(ctx, nextTimeoutHeight) return nil } @@ -381,17 +387,17 @@ func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { return errors.New("unexpected counterparty state value") } - if !obj.counterparty.nexttimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } - obj.nexttimeout.Set(ctx, 0) + obj.nextTimeout.Set(ctx, 0) return nil } func (obj Object) CloseTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nexttimeout.Get(ctx)) { + if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } @@ -408,7 +414,7 @@ func (obj Object) CloseTimeout(ctx sdk.Context) error { } obj.state.Set(ctx, Open) - obj.nexttimeout.Set(ctx, 0) + obj.nextTimeout.Set(ctx, 0) return nil diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index e2b47963044e..4ff890630135 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -1,10 +1,9 @@ package connection import ( + "fmt" "testing" - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" @@ -19,15 +18,40 @@ func registerCodec(cdc *codec.Codec) { tmclient.RegisterCodec(cdc) commitment.RegisterCodec(cdc) merkle.RegisterCodec(cdc) + codec.RegisterCrypto(cdc) } func TestHandshake(t *testing.T) { cdc := codec.New() registerCodec(cdc) - node := NewNode(tendermint.NewMockValidators(10), tendermint.NewMockValidators(10), cdc) - node.Advance(t) + node := NewNode(tendermint.NewMockValidators(100, 10), tendermint.NewMockValidators(100, 10), cdc) + node.Commit() + node.Counterparty.Commit() + + node.CreateClient(t) + node.Counterparty.CreateClient(t) + + // self.OpenInit node.Advance(t) + header := node.Commit() + + fmt.Printf("ddd\n\n\n\n%+v\n", node.Root) + + // counterparty.OpenTry + node.Counterparty.UpdateClient(t, header) + cliobj := node.CLIObject() + _, pconn := node.Query(t, cliobj.ConnectionKey) + fmt.Printf("\n\n\n\n%s: %+v, %s\n", cliobj.ConnectionKey, pconn.(merkle.Proof).Proof, string(pconn.(merkle.Proof).Key)) + _, pstate := node.Query(t, cliobj.StateKey) + _, ptimeout := node.Query(t, cliobj.NextTimeoutKey) + // TODO: implement consensus state checking + // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) + node.Advance(t, pconn, pstate, ptimeout) + + // self.OpenAck node.Advance(t) + + // counterparty.OpenConfirm node.Advance(t) } diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index cf6faa01712f..4a6d31a2f47e 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -12,145 +12,137 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type Node struct { Name string *tendermint.Node - Counterparty *CounterpartyNode + Counterparty *Node - State connection.State + Connection connection.Connection + State connection.State Cdc *codec.Codec } func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res := &Node{ - Name: "self", // hard coded, doesnt matter - Node: tendermint.NewNode(self), + Name: "self", // hard coded, doesnt matter + Node: tendermint.NewNode(self, tendermint.NewRoot([]byte("protocol"))), // TODO: test with key prefix State: connection.Idle, Cdc: cdc, } - res.Counterparty = &CounterpartyNode{ - Name: "counterparty", - Node: tendermint.NewNode(counter), - Cdc: cdc, + res.Counterparty = &Node{ + Name: "counterparty", + Node: tendermint.NewNode(counter, tendermint.NewRoot([]byte("protocol"))), + Counterparty: res, - SelfName: &res.Name, - State: &res.State, + State: connection.Idle, + Cdc: cdc, } - return res -} + res.Connection = connection.Connection{ + Counterparty: res.Counterparty.Name, + } -func (node *Node) Object(t *testing.T) (sdk.Context, connection.Object) { - ctx, man, conn := node.Context(), node.Manager(), node.Connection() - switch node.State { - case connection.Idle: - obj, err := man.Create(ctx, node.Name, conn) - require.NoError(t, err) - return ctx, obj - default: - obj, err := man.Query(ctx, node.Name) - require.NoError(t, err) - require.Equal(t, conn, obj.Connection(ctx)) - return ctx, obj + res.Counterparty.Connection = connection.Connection{ + Counterparty: res.Name, } -} -func (node *Node) Manager() connection.Manager { - base := state.NewBase(node.Cdc, node.Key) - protocol := base.Prefix([]byte("protocol/")) - free := base.Prefix([]byte("free/")) - clientman := client.NewManager(protocol, free, client.IntegerIDGenerator) - return connection.NewManager(base, clientman) + return res } -func (node *Node) Connection() connection.Connection { - return connection.Connection{ - Counterparty: node.Counterparty.Name, - Client: node.Name + "client", - CounterpartyClient: node.Counterparty.Name + "client", - } +func (node *Node) CreateClient(t *testing.T) { + ctx := node.Context() + climan, _ := node.Manager() + obj, err := climan.Create(ctx, node.Counterparty.LastStateVerifier().ConsensusState) + require.NoError(t, err) + node.Connection.Client = obj.ID() + node.Counterparty.Connection.CounterpartyClient = obj.ID() } -type CounterpartyNode struct { - Name string - *tendermint.Node - - Cdc *codec.Codec - - // pointer to self - // TODO: improve - State *connection.State - SelfName *string +func (node *Node) UpdateClient(t *testing.T, header client.Header) { + ctx := node.Context() + climan, _ := node.Manager() + obj, err := climan.Query(ctx, node.Connection.Client) + require.NoError(t, err) + err = obj.Update(ctx, header) + require.NoError(t, err) } -func (node *CounterpartyNode) Object(t *testing.T) (sdk.Context, connection.Object) { - ctx, man, conn := node.Context(), node.Manager(), node.Connection() - switch *node.State { +func (node *Node) Object(t *testing.T, proofs []commitment.Proof) (sdk.Context, connection.Object) { + ctx := node.Context() + store, err := commitment.NewStore(node.Counterparty.Root, proofs) + require.NoError(t, err) + ctx = commitment.WithStore(ctx, store) + _, man := node.Manager() + switch node.State { case connection.Idle: - obj, err := man.Create(ctx, node.Name, conn) + obj, err := man.Create(ctx, node.Name, node.Connection) require.NoError(t, err) return ctx, obj default: obj, err := man.Query(ctx, node.Name) require.NoError(t, err) - require.Equal(t, conn, obj.Connection(ctx)) + require.Equal(t, node.Connection, obj.Connection(ctx)) return ctx, obj } } -func (node *CounterpartyNode) Connection() connection.Connection { - return connection.Connection{ - Counterparty: *node.SelfName, - Client: node.Name + "client", - CounterpartyClient: *node.SelfName + "client", - } + +func (node *Node) CLIObject() connection.CLIObject { + _, man := node.Manager() + return man.CLIObject(node.Root, node.Name) +} + +func base(cdc *codec.Codec, key sdk.StoreKey) (state.Base, state.Base) { + base := state.NewBase(cdc, key) + protocol := base.Prefix([]byte("protocol")) + free := base.Prefix([]byte("free")) + return protocol, free } -func (node *CounterpartyNode) Manager() connection.Manager { - base := state.NewBase(node.Cdc, node.Key) - protocol := base.Prefix([]byte("protocol/")) - free := base.Prefix([]byte("free/")) +func (node *Node) Manager() (client.Manager, connection.Manager) { + protocol, free := base(node.Cdc, node.Key) clientman := client.NewManager(protocol, free, client.IntegerIDGenerator) - return connection.NewManager(base, clientman) + return clientman, connection.NewManager(protocol, clientman) } -func (node *Node) Advance(t *testing.T) { +func (node *Node) Advance(t *testing.T, proofs ...commitment.Proof) { switch node.State { case connection.Idle: // self: Idle -> Init - ctx, obj := node.Object(t) + ctx, obj := node.Object(t, proofs) require.Equal(t, connection.Idle, obj.State(ctx)) err := obj.OpenInit(ctx, 100) // TODO: test timeout require.NoError(t, err) require.Equal(t, connection.Init, obj.State(ctx)) - require.Equal(t, node.Connection(), obj.Connection(ctx)) + require.Equal(t, node.Connection, obj.Connection(ctx)) node.State = connection.Init case connection.Init: // counter: Idle -> OpenTry - ctx, obj := node.Counterparty.Object(t) + ctx, obj := node.Counterparty.Object(t, proofs) require.Equal(t, connection.Idle, obj.State(ctx)) err := obj.OpenTry(ctx, 0 /*TODO*/, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.OpenTry, obj.State(ctx)) - require.Equal(t, node.Counterparty.Connection(), obj.Connection(ctx)) + require.Equal(t, node.Counterparty.Connection, obj.Connection(ctx)) node.State = connection.OpenTry case connection.OpenTry: // self: Init -> Open - ctx, obj := node.Object(t) + ctx, obj := node.Object(t, proofs) require.Equal(t, connection.Init, obj.State(ctx)) err := obj.OpenAck(ctx, 0 /*TODO*/, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) - require.Equal(t, node.Connection(), obj.Connection(ctx)) + require.Equal(t, node.Connection, obj.Connection(ctx)) node.State = connection.Open case connection.Open: // counter: OpenTry -> Open - ctx, obj := node.Counterparty.Object(t) + ctx, obj := node.Counterparty.Object(t, proofs) require.Equal(t, connection.OpenTry, obj.State(ctx)) err := obj.OpenConfirm(ctx, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) - require.Equal(t, node.Counterparty.Connection(), obj.Connection(ctx)) + require.Equal(t, node.Counterparty.Connection, obj.Connection(ctx)) node.State = connection.CloseTry // case connection.CloseTry // self: Open -> CloseTry default: diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index 7ad593d6f9d2..4a90426defcb 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -3,6 +3,7 @@ package commitment import ( "bytes" "errors" + "fmt" ) type Store interface { @@ -10,7 +11,7 @@ type Store interface { HasProof(key []byte) bool } -var _ Store = prefix{} +var _ Store = prefix{} // TODO: pointer type prefix struct { store Store @@ -32,7 +33,7 @@ func (prefix prefix) Prove(key, value []byte) bool { return prefix.store.Prove(join(prefix.prefix, key), value) } -var _ Store = store{} +var _ Store = (*store)(nil) type store struct { root Root @@ -41,8 +42,8 @@ type store struct { } // Proofs must be provided -func NewStore(root Root, proofs []Proof) (res store, err error) { - res = store{ +func NewStore(root Root, proofs []Proof) (res *store, err error) { + res = &store{ root: root, proofs: make(map[string]Proof), verified: make(map[string][]byte), @@ -53,28 +54,34 @@ func NewStore(root Root, proofs []Proof) (res store, err error) { err = errors.New("proof type not matching with root's") return } + fmt.Println("set key", string(proof.GetKey())) res.proofs[string(proof.GetKey())] = proof } + fmt.Printf("%+v\n", res) + return } -func (store store) Get(key []byte) ([]byte, bool) { +func (store *store) Get(key []byte) ([]byte, bool) { res, ok := store.verified[string(key)] return res, ok } -func (store store) Prove(key, value []byte) bool { +func (store *store) Prove(key, value []byte) bool { stored, ok := store.Get(key) if ok && bytes.Equal(stored, value) { return true } proof, ok := store.proofs[string(key)] if !ok { + fmt.Println("no proof") + fmt.Println("get key", string(key)) return false } err := proof.Verify(store.root, value) if err != nil { + fmt.Println("invalid proof") return false } store.verified[string(key)] = value @@ -82,12 +89,12 @@ func (store store) Prove(key, value []byte) bool { return true } -func (store store) HasProof(key []byte) bool { +func (store *store) HasProof(key []byte) bool { _, ok := store.proofs[string(key)] return ok } -func (store store) Proven(key []byte) bool { +func (store *store) Proven(key []byte) bool { _, ok := store.Get(key) return ok } From d5bed425b6687ecf3c8776b4f6c25be46f71933e Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 29 Jun 2019 14:10:53 +0200 Subject: [PATCH 035/182] add test in progress 02 --- x/ibc/02-client/manager.go | 2 ++ x/ibc/02-client/tendermint/tests/types.go | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index e94d14702b72..5d52613be9df 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -2,6 +2,7 @@ package client import ( "errors" + "fmt" "strconv" "github.com/cosmos/cosmos-sdk/store/state" @@ -27,6 +28,7 @@ type Manager struct { } func NewManager(protocol, free state.Base, idgen IDGenerator) Manager { + fmt.Println(1234567890, protocol, free) return Manager{ protocol: state.NewMapping(protocol, []byte("/client")), idval: state.NewValue(free, []byte("/client/id")), diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 49b2a3a9460c..860cb424e11d 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -145,9 +145,10 @@ func (v *Verifier) Validate(header tendermint.Header) error { } func (node *Node) Query(t *testing.T, k []byte) ([]byte, commitment.Proof) { - code, value, proof := node.Root.QueryMultiStore(node.Cms, k) - require.Equal(t, uint32(0), code) - return value, proof + qres, proof, err := node.Root.QueryMultiStore(node.Cms, k) + require.NoError(t, err) + require.Equal(t, uint32(0), qres.Code) + return qres.Value, proof } func (node *Node) Set(k, value []byte) { From 93f35b8ed2f3e95591f896c53900c46005397ef4 Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 29 Jun 2019 14:11:04 +0200 Subject: [PATCH 036/182] add test in progress 23 --- x/ibc/23-commitment/merkle/merkle_test.go | 38 +++++++++++------------ x/ibc/23-commitment/merkle/utils.go | 37 ++++++++++++++++++++-- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index a1886519eafc..5e15b8384cfb 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -36,6 +36,14 @@ func commit(cms types.CommitMultiStore, root Root) Root { return root.Update(cid.Hash).(Root) } +func queryMultiStore(t *testing.T, root Root, cms types.CommitMultiStore, key, value []byte) Proof { + q, p, err := root.QueryMultiStore(cms, key) + require.Equal(t, uint32(0), q.Code) + require.NoError(t, err) + require.Equal(t, value, q.Value) + return p +} + func TestStore(t *testing.T) { k, ctx, cms, _ := defaultComponents() kvstore := ctx.KVStore(k) @@ -47,15 +55,9 @@ func TestStore(t *testing.T) { root = commit(cms, root) - c1, v1, p1 := root.QueryMultiStore(cms, []byte("hello")) - require.Equal(t, uint32(0), c1) - require.Equal(t, []byte("world"), v1) - c2, v2, p2 := root.QueryMultiStore(cms, []byte("merkle")) - require.Equal(t, uint32(0), c2) - require.Equal(t, []byte("tree"), v2) - c3, v3, p3 := root.QueryMultiStore(cms, []byte("block")) - require.Equal(t, uint32(0), c3) - require.Equal(t, []byte("chain"), v3) + p1 := queryMultiStore(t, root, cms, []byte("hello"), []byte("world")) + p2 := queryMultiStore(t, root, cms, []byte("merkle"), []byte("tree")) + p3 := queryMultiStore(t, root, cms, []byte("block"), []byte("chain")) cstore, err := commitment.NewStore(root, []commitment.Proof{p1, p2, p3}) require.NoError(t, err) @@ -70,20 +72,16 @@ func TestStore(t *testing.T) { root = commit(cms, root) - c1, v1, p1 = root.QueryMultiStore(cms, []byte("12345")) - require.Equal(t, uint32(0), c1) - require.Equal(t, []byte("67890"), v1) - c2, v2, p2 = root.QueryMultiStore(cms, []byte("qwerty")) - require.Equal(t, uint32(0), c2) - require.Equal(t, []byte("zxcv"), v2) - c3, v3, p3 = root.QueryMultiStore(cms, []byte("hello")) - require.Equal(t, uint32(0), c3) - require.Equal(t, []byte("dlrow"), v3) - - cstore, err = commitment.NewStore(root, []commitment.Proof{p1, p2, p3}) + p1 = queryMultiStore(t, root, cms, []byte("12345"), []byte("67890")) + p2 = queryMultiStore(t, root, cms, []byte("qwerty"), []byte("zxcv")) + p3 = queryMultiStore(t, root, cms, []byte("hello"), []byte("dlrow")) + p4 := queryMultiStore(t, root, cms, []byte("merkle"), []byte("tree")) + + cstore, err = commitment.NewStore(root, []commitment.Proof{p1, p2, p3, p4}) require.NoError(t, err) require.True(t, cstore.Prove([]byte("12345"), []byte("67890"))) require.True(t, cstore.Prove([]byte("qwerty"), []byte("zxcv"))) require.True(t, cstore.Prove([]byte("hello"), []byte("dlrow"))) + require.True(t, cstore.Prove([]byte("merkle"), []byte("tree"))) } diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index b16d0854e2af..8e4ec43fb021 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -1,8 +1,13 @@ package merkle import ( + "bytes" + "errors" + "fmt" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -16,9 +21,35 @@ func (root Root) RequestQueryMultiStore(key []byte) abci.RequestQuery { return abci.RequestQuery{Path: root.Path() + "/key", Data: root.Key(key), Prove: true} } -func (root Root) QueryMultiStore(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { - qres := cms.(types.Queryable).Query(root.RequestQueryMultiStore(key)) - return qres.Code, qres.Value, Proof{Key: key, Proof: qres.Proof} +// QueryMultiStore prefixes the root.KeyPrefix to the key +func (root Root) QueryMultiStore(cms types.CommitMultiStore, key []byte) (qres abci.ResponseQuery, proof Proof, err error) { + qres = cms.(types.Queryable).Query(root.RequestQueryMultiStore(key)) + proof = Proof{Key: key, Proof: qres.Proof} + return +} + +// TrimPrefix is used when the input key is generate with prefix +// so need to be trimmed +func (root Root) trimPrefix(key []byte) ([]byte, error) { + if !bytes.HasPrefix(key, root.KeyPrefix) { + fmt.Println(string(key), key, string(root.KeyPrefix), root.KeyPrefix) + return nil, errors.New("key not starting with root key prefix") + } + return bytes.TrimPrefix(key, root.KeyPrefix), nil +} + +// QueryCLI does NOT prefixes the root.KeyPrefix to the key +func (root Root) QueryCLI(ctx context.CLIContext, key []byte) (qres abci.ResponseQuery, proof Proof, err error) { + qres, err = ctx.QueryABCI(root.RequestQueryMultiStore(key)) + if err != nil { + return + } + trimkey, err := root.trimPrefix(key) + if err != nil { + return + } + proof = Proof{Key: trimkey, Proof: qres.Proof} + return } func (root Root) Key(key []byte) []byte { From 82d8a7cb9d0d60b5f86e8ea35224f791c205cd8c Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 29 Jun 2019 14:40:30 +0200 Subject: [PATCH 037/182] handshake test now working --- store/state/base.go | 12 +++++++--- x/ibc/02-client/manager.go | 2 -- x/ibc/03-connection/manager.go | 6 ----- x/ibc/03-connection/tests/connection_test.go | 22 +++++++++++++------ x/ibc/03-connection/tests/types.go | 23 ++++++++++++-------- x/ibc/23-commitment/store.go | 7 ------ 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/store/state/base.go b/store/state/base.go index f163c18b98a0..a6f429053248 100644 --- a/store/state/base.go +++ b/store/state/base.go @@ -15,13 +15,19 @@ type Base struct { } func EmptyBase() Base { - return NewBase(nil, nil) + return NewBase(nil, nil, nil) } -func NewBase(cdc *codec.Codec, key sdk.StoreKey) Base { +func NewBase(cdc *codec.Codec, key sdk.StoreKey, rootkey []byte) Base { + if len(rootkey) == 0 { + return Base{ + cdc: cdc, + storefn: func(ctx Context) KVStore { return ctx.KVStore(key) }, + } + } return Base{ cdc: cdc, - storefn: func(ctx Context) KVStore { return ctx.KVStore(key) }, + storefn: func(ctx Context) KVStore { return prefix.NewStore(ctx.KVStore(key), rootkey) }, } } diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 5d52613be9df..e94d14702b72 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -2,7 +2,6 @@ package client import ( "errors" - "fmt" "strconv" "github.com/cosmos/cosmos-sdk/store/state" @@ -28,7 +27,6 @@ type Manager struct { } func NewManager(protocol, free state.Base, idgen IDGenerator) Manager { - fmt.Println(1234567890, protocol, free) return Manager{ protocol: state.NewMapping(protocol, []byte("/client")), idval: state.NewValue(free, []byte("/client/id")), diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 7c0668bc0dbd..3c12fe5851d6 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -2,7 +2,6 @@ package connection import ( "errors" - "fmt" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" @@ -71,7 +70,6 @@ func (man CounterpartyManager) object(id string) CounterObject { } func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (obj Object, err error) { - fmt.Println("create", id, connection) obj = man.object(id) if obj.exists(ctx) { err = errors.New("connection already exists for the provided id") @@ -202,24 +200,20 @@ func (obj Object) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, next return errors.New("invalid state") } - fmt.Println(12345) err := assertTimeout(ctx, timeoutHeight) if err != nil { return err } - fmt.Println(67890) if !obj.counterparty.state.Is(ctx, Init) { return errors.New("counterparty state not init") } - fmt.Println(97) err = obj.assertSymmetric(ctx) if err != nil { return err } - fmt.Println(65) if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { return errors.New("unexpected counterparty timeout value") } diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index 4ff890630135..338218542322 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -1,7 +1,6 @@ package connection import ( - "fmt" "testing" "github.com/cosmos/cosmos-sdk/codec" @@ -36,22 +35,31 @@ func TestHandshake(t *testing.T) { node.Advance(t) header := node.Commit() - fmt.Printf("ddd\n\n\n\n%+v\n", node.Root) - // counterparty.OpenTry node.Counterparty.UpdateClient(t, header) cliobj := node.CLIObject() _, pconn := node.Query(t, cliobj.ConnectionKey) - fmt.Printf("\n\n\n\n%s: %+v, %s\n", cliobj.ConnectionKey, pconn.(merkle.Proof).Proof, string(pconn.(merkle.Proof).Key)) _, pstate := node.Query(t, cliobj.StateKey) _, ptimeout := node.Query(t, cliobj.NextTimeoutKey) // TODO: implement consensus state checking // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) - node.Advance(t, pconn, pstate, ptimeout) + node.Advance(t, pconn, pstate, ptimeout /*, pclient*/) + header = node.Counterparty.Commit() // self.OpenAck - node.Advance(t) + node.UpdateClient(t, header) + cliobj = node.Counterparty.CLIObject() + _, pconn = node.Counterparty.Query(t, cliobj.ConnectionKey) + _, pstate = node.Counterparty.Query(t, cliobj.StateKey) + _, ptimeout = node.Counterparty.Query(t, cliobj.NextTimeoutKey) + node.Advance(t, pconn, pstate, ptimeout) + header = node.Commit() // counterparty.OpenConfirm - node.Advance(t) + node.Counterparty.UpdateClient(t, header) + cliobj = node.CLIObject() + _, pconn = node.Query(t, cliobj.ConnectionKey) // TODO: check if it is needed + _, pstate = node.Query(t, cliobj.StateKey) + _, ptimeout = node.Query(t, cliobj.NextTimeoutKey) + node.Advance(t, pconn, pstate, ptimeout) } diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 4a6d31a2f47e..18d941cad038 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -73,6 +73,11 @@ func (node *Node) UpdateClient(t *testing.T, header client.Header) { require.NoError(t, err) } +func (node *Node) SetState(state connection.State) { + node.State = state + node.Counterparty.State = state +} + func (node *Node) Object(t *testing.T, proofs []commitment.Proof) (sdk.Context, connection.Object) { ctx := node.Context() store, err := commitment.NewStore(node.Counterparty.Root, proofs) @@ -80,7 +85,7 @@ func (node *Node) Object(t *testing.T, proofs []commitment.Proof) (sdk.Context, ctx = commitment.WithStore(ctx, store) _, man := node.Manager() switch node.State { - case connection.Idle: + case connection.Idle, connection.Init: obj, err := man.Create(ctx, node.Name, node.Connection) require.NoError(t, err) return ctx, obj @@ -98,9 +103,8 @@ func (node *Node) CLIObject() connection.CLIObject { } func base(cdc *codec.Codec, key sdk.StoreKey) (state.Base, state.Base) { - base := state.NewBase(cdc, key) - protocol := base.Prefix([]byte("protocol")) - free := base.Prefix([]byte("free")) + protocol := state.NewBase(cdc, key, []byte("protocol")) + free := state.NewBase(cdc, key, []byte("free")) return protocol, free } @@ -112,6 +116,7 @@ func (node *Node) Manager() (client.Manager, connection.Manager) { func (node *Node) Advance(t *testing.T, proofs ...commitment.Proof) { switch node.State { + // TODO: use different enum type for node.State case connection.Idle: // self: Idle -> Init ctx, obj := node.Object(t, proofs) require.Equal(t, connection.Idle, obj.State(ctx)) @@ -119,7 +124,7 @@ func (node *Node) Advance(t *testing.T, proofs ...commitment.Proof) { require.NoError(t, err) require.Equal(t, connection.Init, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) - node.State = connection.Init + node.SetState(connection.Init) case connection.Init: // counter: Idle -> OpenTry ctx, obj := node.Counterparty.Object(t, proofs) require.Equal(t, connection.Idle, obj.State(ctx)) @@ -127,7 +132,7 @@ func (node *Node) Advance(t *testing.T, proofs ...commitment.Proof) { require.NoError(t, err) require.Equal(t, connection.OpenTry, obj.State(ctx)) require.Equal(t, node.Counterparty.Connection, obj.Connection(ctx)) - node.State = connection.OpenTry + node.SetState(connection.OpenTry) case connection.OpenTry: // self: Init -> Open ctx, obj := node.Object(t, proofs) require.Equal(t, connection.Init, obj.State(ctx)) @@ -135,7 +140,7 @@ func (node *Node) Advance(t *testing.T, proofs ...commitment.Proof) { require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) - node.State = connection.Open + node.SetState(connection.Open) case connection.Open: // counter: OpenTry -> Open ctx, obj := node.Counterparty.Object(t, proofs) require.Equal(t, connection.OpenTry, obj.State(ctx)) @@ -143,8 +148,8 @@ func (node *Node) Advance(t *testing.T, proofs ...commitment.Proof) { require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) require.Equal(t, node.Counterparty.Connection, obj.Connection(ctx)) - node.State = connection.CloseTry - // case connection.CloseTry // self: Open -> CloseTry + node.SetState(connection.CloseTry) + // case connection.CloseTry // self: Open -> CloseTry default: return } diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index 4a90426defcb..a5640db907c3 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -3,7 +3,6 @@ package commitment import ( "bytes" "errors" - "fmt" ) type Store interface { @@ -54,12 +53,9 @@ func NewStore(root Root, proofs []Proof) (res *store, err error) { err = errors.New("proof type not matching with root's") return } - fmt.Println("set key", string(proof.GetKey())) res.proofs[string(proof.GetKey())] = proof } - fmt.Printf("%+v\n", res) - return } @@ -75,13 +71,10 @@ func (store *store) Prove(key, value []byte) bool { } proof, ok := store.proofs[string(key)] if !ok { - fmt.Println("no proof") - fmt.Println("get key", string(key)) return false } err := proof.Verify(store.root, value) if err != nil { - fmt.Println("invalid proof") return false } store.verified[string(key)] = value From 1b47501d7459efc80964ad86a909289369f22795 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 5 Jul 2019 01:18:36 +0200 Subject: [PATCH 038/182] modularize connection in progress --- store/state/mapping.go | 4 + store/state/string.go | 23 ++ store/state/types.go | 2 + x/ibc/03-connection/cli.go | 27 +- x/ibc/03-connection/handshake/manager.go | 374 ++++++++++++++++++++ x/ibc/03-connection/handshake/types.go | 60 ++++ x/ibc/03-connection/manager.go | 419 +++++------------------ x/ibc/03-connection/types.go | 38 +- x/ibc/23-commitment/value.go | 18 + 9 files changed, 595 insertions(+), 370 deletions(-) create mode 100644 store/state/string.go create mode 100644 x/ibc/03-connection/handshake/manager.go create mode 100644 x/ibc/03-connection/handshake/types.go diff --git a/store/state/mapping.go b/store/state/mapping.go index 566077a62237..0d0ae990cf5a 100644 --- a/store/state/mapping.go +++ b/store/state/mapping.go @@ -54,3 +54,7 @@ func (m Mapping) IsEmpty(ctx Context) bool { func (m Mapping) Prefix(prefix []byte) Mapping { return NewMapping(m.base, prefix) } + +func (m Mapping) Cdc() *Codec { + return m.base.Cdc() +} diff --git a/store/state/string.go b/store/state/string.go new file mode 100644 index 000000000000..38b92b16ec71 --- /dev/null +++ b/store/state/string.go @@ -0,0 +1,23 @@ +package state + +type String struct { + Value +} + +func NewString(v Value) String { + return String{v} +} + +func (v String) Get(ctx Context) (res string) { + v.Value.Get(ctx, &res) + return +} + +func (v String) GetSafe(ctx Context) (res string, err error) { + v.Value.GetSafe(ctx, &res) + return +} + +func (v String) Set(ctx Context, value string) { + v.Value.Set(ctx, value) +} diff --git a/store/state/types.go b/store/state/types.go index f5dbb4dc8648..a058cf6ddf0a 100644 --- a/store/state/types.go +++ b/store/state/types.go @@ -4,6 +4,7 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -11,3 +12,4 @@ type KVStore = sdk.KVStore type Context = sdk.Context type CLIContext = context.CLIContext type Proof = merkle.Proof +type Codec = codec.Codec diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 3df848ffb953..ffbebcb0d27e 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -1,8 +1,6 @@ package connection import ( - "time" - "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" @@ -12,10 +10,11 @@ import ( // CLIObject stores the key for each object fields type CLIObject struct { - ID string - ConnectionKey []byte - StateKey []byte - NextTimeoutKey []byte + ID string + ConnectionKey []byte + // StateKey []byte + // NextTimeoutKey []byte + PermissionKey []byte Client client.CLIObject @@ -26,10 +25,11 @@ type CLIObject struct { func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { obj := man.object(id) return CLIObject{ - ID: obj.id, - ConnectionKey: obj.connection.Key(), - StateKey: obj.state.Key(), - NextTimeoutKey: obj.nextTimeout.Key(), + ID: obj.id, + ConnectionKey: obj.connection.Key(), + // StateKey: obj.state.Key(), + // NextTimeoutKey: obj.nextTimeout.Key(), + PermissionKey: obj.permission.Key(), // TODO: unify man.CLIObject() <=> obj.CLI() Client: obj.client.CLI(root), @@ -58,6 +58,7 @@ func (obj CLIObject) Connection(ctx context.CLIContext, root merkle.Root) (res C return } +/* func (obj CLIObject) State(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.StateKey, &res) return @@ -67,3 +68,9 @@ func (obj CLIObject) NextTimeout(ctx context.CLIContext, root merkle.Root) (res proof, err = obj.query(ctx, obj.NextTimeoutKey, &res) return } +*/ + +func (obj CLIObject) Permission(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.PermissionKey, &res) + return +} diff --git a/x/ibc/03-connection/handshake/manager.go b/x/ibc/03-connection/handshake/manager.go new file mode 100644 index 000000000000..38b4816e0fd4 --- /dev/null +++ b/x/ibc/03-connection/handshake/manager.go @@ -0,0 +1,374 @@ +package handshake + +import ( + "errors" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +type Manager struct { + connection.PermissionedManager + + counterparty CounterpartyManager +} + +func NewManager(man connection.PermissionedManager) Manager { + return Manager{ + PermissionedManager: man, + + counterparty: NewCounterpartyManager(man.Cdc()), + } +} + +type CounterpartyManager struct { + protocol commitment.Mapping + + client client.CounterpartyManager +} + +func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { + protocol := commitment.NewBase(cdc) + + return CounterpartyManager{ + protocol: commitment.NewMapping(protocol, []byte("/connection/")), + + client: client.NewCounterpartyManager(protocol), + } +} + +// CONTRACT: client and remote must be filled by the caller +func (man Manager) object(parent connection.Object) Object { + return Object{ + Object: parent, + + nextTimeout: state.NewInteger(parent.Mapping().Value([]byte("/timeout")), state.Dec), + + counterparty: man.counterparty.object(parent.Counterparty()), + } +} + +func (man CounterpartyManager) object(parent connection.CounterObject) CounterObject { + return CounterObject{ + CounterObject: parent, + + nextTimeout: commitment.NewInteger(parent.Mapping.Value([]byte("/timeout")), state.Dec), + } +} + +func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (obj Object, err error) { + cobj, err := man.PermissionedManager.Create(ctx, id, connection) + if err != nil { + return + } + obj = man.object(cobj) + return obj, nil +} + +func (man Manager) query(ctx sdk.Context, id string) (obj Object, err error) { + cobj, err := man.PermissionedManager.Query(ctx, id) + if err != nil { + return + } + obj = man.object(cobj) + return +} + +type Object struct { + connection.Object + + nextTimeout state.Integer + + client client.Object + + counterparty CounterObject +} + +type CounterObject struct { + connection.CounterObject + + nextTimeout commitment.Integer + + client client.CounterObject +} + +func (obj Object) NextTimeout(ctx sdk.Context) uint64 { + return obj.nextTimeout.Get(ctx) +} + +// If there is no proof provided, assume not exists +func (obj CounterObject) exists(ctx sdk.Context) bool { + /* + // XXX + if !obj.connection.Proven(ctx) { + return false + } + + return obj.connection.Exists(ctx) + */ + + return false +} + +// TODO: make it private +func (obj Object) Delete(ctx sdk.Context) { + obj.Object.Remove(ctx) + obj.nextTimeout.Delete(ctx) +} + +func (obj Object) assertSymmetric(ctx sdk.Context) error { + if !obj.counterparty.connection.Is(ctx, obj.Connection(ctx).Symmetry(obj.id)) { + return errors.New("unexpected counterparty connection value") + } + + return nil +} + +func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { + if uint64(ctx.BlockHeight()) > timeoutHeight { + return errors.New("timeout") + } + + return nil +} + +// Using proofs: none +func (obj Object) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) error { + if !obj.state.Transit(ctx, Idle, Init) { + return errors.New("init on non-idle connection") + } + + // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), + // which will ensure + // assert(get("connections/{identifier}") === null) and + // set("connections{identifier}", connection) + + obj.nextTimeout.Set(ctx, nextTimeoutHeight) + + return nil +} + +// Using proofs: counterparty.{connection,state,nextTimeout,client} +func (obj Object) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { + if !obj.state.Transit(ctx, Idle, OpenTry) { + return errors.New("invalid state") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.counterparty.state.Is(ctx, Init) { + return errors.New("counterparty state not init") + } + + err = obj.assertSymmetric(ctx) + if err != nil { + return err + } + + if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { + return errors.New("unexpected counterparty timeout value") + } + + // TODO: commented out, need to check whether the stored client is compatible + // make a separate module that manages recent n block headers + /* + var expected client.ConsensusState + obj.self.Get(ctx, expheight, &expected) + if !obj.counterparty.client.Is(ctx, expected) { + return errors.New("unexpected counterparty client value") + } + */ + + // CONTRACT: OpenTry() should be called after man.Create(), not man.Query(), + // which will ensure + // assert(get("connections/{desiredIdentifier}") === null) and + // set("connections{identifier}", connection) + + obj.nextTimeout.Set(ctx, nextTimeoutHeight) + + return nil +} + +// Using proofs: counterparty.{connection,state, nextTimeout} +func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { + + if !obj.state.Transit(ctx, Init, Open) { + return errors.New("ack on non-init connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.counterparty.state.Is(ctx, OpenTry) { + return errors.New("counterparty state not try") + } + + err = obj.assertSymmetric(ctx) + if err != nil { + return err + } + + if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { + return errors.New("unexpected counterparty timeout value") + } + + // TODO: commented out, implement in v1 + /* + var expected client.ConsensusState + obj.self.Get(ctx, expheight, &expected) + if !obj.counterparty.client.Is(ctx, expected) { + return errors.New("unexpected counterparty client value") + } + */ + + obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) + + return nil +} + +// Using proofs: counterparty.{connection,state, nextTimeout} +func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { + if !obj.state.Transit(ctx, OpenTry, Open) { + return errors.New("confirm on non-try connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.counterparty.state.Is(ctx, Open) { + return errors.New("counterparty state not open") + } + + err = obj.assertSymmetric(ctx) + if err != nil { + return err + } + + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + return errors.New("unexpected counterparty timeout value") + } + + obj.nextTimeout.Set(ctx, 0) + + return nil +} + +func (obj Object) OpenTimeout(ctx sdk.Context) error { + if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + return errors.New("timeout height not yet reached") + } + + // XXX: double check if a user can bypass the verification logic somehow + switch obj.state.Get(ctx) { + case Init: + if !obj.counterparty.connection.Is(ctx, nil) { + return errors.New("counterparty connection exists") + } + case OpenTry: + if !(obj.counterparty.state.Is(ctx, Init) || + obj.counterparty.exists(ctx)) { + return errors.New("counterparty connection state not init") + } + // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) + case Open: + if obj.counterparty.state.Is(ctx, OpenTry) { + return errors.New("counterparty connection state not tryopen") + } + } + + obj.remove(ctx) + + return nil +} + +func (obj Object) CloseInit(ctx sdk.Context, nextTimeout uint64) error { + if !obj.state.Transit(ctx, Open, CloseTry) { + return errors.New("closeinit on non-open connection") + } + + obj.nextTimeout.Set(ctx, nextTimeout) + + return nil +} + +func (obj Object) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { + if !obj.state.Transit(ctx, Open, Closed) { + return errors.New("closetry on non-open connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.counterparty.state.Is(ctx, CloseTry) { + return errors.New("unexpected counterparty state value") + } + + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + return errors.New("unexpected counterparty timeout value") + } + + obj.nextTimeout.Set(ctx, nextTimeoutHeight) + + return nil +} + +func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { + if !obj.state.Transit(ctx, CloseTry, Closed) { + return errors.New("closeack on non-closetry connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.counterparty.state.Is(ctx, Closed) { + return errors.New("unexpected counterparty state value") + } + + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + return errors.New("unexpected counterparty timeout value") + } + + obj.nextTimeout.Set(ctx, 0) + + return nil +} + +func (obj Object) CloseTimeout(ctx sdk.Context) error { + if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + return errors.New("timeout height not yet reached") + } + + // XXX: double check if the user can bypass the verification logic somehow + switch obj.state.Get(ctx) { + case CloseTry: + if !obj.counterparty.state.Is(ctx, Open) { + return errors.New("counterparty connection state not open") + } + case Closed: + if !obj.counterparty.state.Is(ctx, CloseTry) { + return errors.New("counterparty connection state not closetry") + } + } + + obj.state.Set(ctx, Open) + obj.nextTimeout.Set(ctx, 0) + + return nil + +} diff --git a/x/ibc/03-connection/handshake/types.go b/x/ibc/03-connection/handshake/types.go new file mode 100644 index 000000000000..786948991ad1 --- /dev/null +++ b/x/ibc/03-connection/handshake/types.go @@ -0,0 +1,60 @@ +package handshake + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" +) + +type State = byte + +const ( + Idle State = iota + Init + OpenTry + Open + CloseTry + Closed +) + +var _ connection.Connection = Connection{} + +// TODO: Connection is amino marshaled currently, need to implement MarshalBinary manually +type Connection struct { + Counterparty string + Client string + CounterpartyClient string + State State +} + +func (conn Connection) GetCounterparty() string { + return conn.Counterparty +} + +func (conn Connection) GetClient() string { + return conn.Client +} + +func (conn Connection) GetCounterpartyClient() string { + return conn.CounterpartyClient +} + +func (conn Connection) Available() bool { + return conn.State == Open +} + +func (conn Connection) Equal(conn0 Connection) bool { + return conn.Counterparty == conn0.Counterparty && + conn.Client == conn0.Client && + conn.CounterpartyClient == conn0.CounterpartyClient +} + +func (conn Connection) Symmetric(id string, conn0 Connection) bool { + return conn0.Equal(conn.Symmetry(id)) +} + +func (conn Connection) Symmetry(id string) Connection { + return Connection{ + Counterparty: id, + Client: conn.CounterpartyClient, + CounterpartyClient: conn.Client, + } +} diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 3c12fe5851d6..bd74bddf142e 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -14,111 +14,118 @@ import ( type Manager struct { protocol state.Mapping - client client.Manager + table map[string]struct{} - self state.Indexer + client client.Manager counterparty CounterpartyManager } -func NewManager(protocol state.Base, clientman client.Manager) Manager { - return Manager{ - protocol: state.NewMapping(protocol, []byte("/connection/")), - - client: clientman, - - counterparty: NewCounterpartyManager(protocol.Cdc()), - } -} - type CounterpartyManager struct { protocol commitment.Mapping client client.CounterpartyManager } -func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { - protocol := commitment.NewBase(cdc) +// CONTRACT: should be called on initialization time only +func (man Manager) Register(name string) PermissionedManager { + if _, ok := man.table[name]; ok { + panic("SubManager registered for existing name") + } + man.table[name] = struct{}{} - return CounterpartyManager{ - protocol: commitment.NewMapping(protocol, []byte("/connection/")), + return PermissionedManager{man, name} +} - client: client.NewCounterpartyManager(protocol), - } +func (man Manager) mapping(id string) state.Mapping { + return man.protocol.Prefix([]byte(id)) } -// CONTRACT: client and remote must be filled by the caller func (man Manager) object(id string) Object { return Object{ - id: id, - connection: man.protocol.Value([]byte(id)), - state: state.NewEnum(man.protocol.Value([]byte(id + "/state"))), - nextTimeout: state.NewInteger(man.protocol.Value([]byte(id+"/timeout")), state.Dec), + id: id, + connection: man.protocol.Value([]byte(id)), + permission: state.NewString(man.protocol.Value([]byte(id + "/permission"))), + + mapping: man.protocol.Prefix([]byte(id)), + + // CONTRACT: client should be filled by the caller - self: man.self, + counterparty: man.counterparty.object(id), } } -// CONTRACT: client must be filled by the caller func (man CounterpartyManager) object(id string) CounterObject { return CounterObject{ - id: id, - connection: man.protocol.Value([]byte(id)), - state: commitment.NewEnum(man.protocol.Value([]byte(id + "/state"))), - nextTimeout: commitment.NewInteger(man.protocol.Value([]byte(id+"/timeout")), state.Dec), + ID: id, + Connection: man.protocol.Value([]byte(id)), + Permission: commitment.NewString(man.protocol.Value([]byte(id + "/permission"))), + + // CONTRACT: client should be filled by the caller + + Mapping: man.protocol.Prefix([]byte(id)), } } -func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (obj Object, err error) { +func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { obj = man.object(id) - if obj.exists(ctx) { - err = errors.New("connection already exists for the provided id") + if !obj.exists(ctx) { + err = errors.New("Object not exists") return } - obj.connection.Set(ctx, connection) - obj.client, err = man.client.Query(ctx, connection.Client) - if err != nil { + obj.client, err = man.client.Query(ctx, obj.Connection(ctx).GetClient()) + return +} + +type PermissionedManager struct { + man Manager + name string +} + +func (man PermissionedManager) Cdc() *codec.Codec { + return man.man.protocol.Cdc() +} + +func (man PermissionedManager) object(id string) Object { + return man.man.object(id) +} + +func (man PermissionedManager) Create(ctx sdk.Context, id string, connection Connection) (obj Object, err error) { + obj = man.object(id) + if obj.exists(ctx) { + err = errors.New("Object already exists") return } - obj.counterparty = man.counterparty.object(connection.Counterparty) - obj.counterparty.client = man.counterparty.client.Query(connection.CounterpartyClient) - return obj, nil + obj.connection.Set(ctx, connection) + obj.permission.Set(ctx, man.name) + obj.client, err = man.man.client.Query(ctx, connection.GetClient()) + return } -func (man Manager) Query(ctx sdk.Context, key string) (obj Object, err error) { - obj = man.object(key) +func (man PermissionedManager) Query(ctx sdk.Context, id string) (obj Object, err error) { + obj = man.object(id) if !obj.exists(ctx) { - return Object{}, errors.New("connection not exists for the provided id") + err = errors.New("Object not exists") + return } - conn := obj.Connection(ctx) - obj.client, err = man.client.Query(ctx, conn.Client) - if err != nil { + if obj.Permission(ctx) != man.name { + err = errors.New("Object created with different permission") return } - obj.counterparty = man.counterparty.object(conn.Counterparty) - obj.counterparty.client = man.counterparty.client.Query(conn.CounterpartyClient) + obj.client, err = man.man.client.Query(ctx, obj.Connection(ctx).GetClient()) return } type Object struct { - id string - connection state.Value - state state.Enum - nextTimeout state.Integer + id string + connection state.Value // Connection + permission state.String + + mapping state.Mapping client client.Object counterparty CounterObject - self state.Indexer -} - -type CounterObject struct { - id string - connection commitment.Value - state commitment.Enum - nextTimeout commitment.Integer - - client client.CounterObject } func (obj Object) ID() string { @@ -130,286 +137,42 @@ func (obj Object) Connection(ctx sdk.Context) (res Connection) { return } -func (obj Object) State(ctx sdk.Context) byte { - return obj.state.Get(ctx) +// TODO: it should not be exposed +func (obj Object) Permission(ctx sdk.Context) string { + return obj.permission.Get(ctx) } -func (obj Object) Client() client.Object { - return obj.client +func (obj Object) Mapping() state.Mapping { + return obj.mapping } -func (obj Object) exists(ctx sdk.Context) bool { - return obj.connection.Exists(ctx) +func (obj Object) Counterparty() CounterObject { + return obj.counterparty } -// If there is no proof provided, assume not exists -func (obj CounterObject) exists(ctx sdk.Context) bool { - /* - // XXX - if !obj.connection.Proven(ctx) { - return false - } - - return obj.connection.Exists(ctx) - */ - - return false +func (obj Object) exists(ctx sdk.Context) bool { + return obj.connection.Exists(ctx) } -func (obj Object) remove(ctx sdk.Context) { +func (obj Object) Delete(ctx sdk.Context) { obj.connection.Delete(ctx) - obj.state.Delete(ctx) - obj.nextTimeout.Delete(ctx) -} - -func (obj Object) assertSymmetric(ctx sdk.Context) error { - if !obj.counterparty.connection.Is(ctx, obj.Connection(ctx).Symmetry(obj.id)) { - return errors.New("unexpected counterparty connection value") - } - - return nil -} - -func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { - if uint64(ctx.BlockHeight()) > timeoutHeight { - return errors.New("timeout") - } - - return nil -} - -// Using proofs: none -func (obj Object) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) error { - if !obj.state.Transit(ctx, Idle, Init) { - return errors.New("init on non-idle connection") - } - - // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), - // which will ensure - // assert(get("connections/{identifier}") === null) and - // set("connections{identifier}", connection) - - obj.nextTimeout.Set(ctx, nextTimeoutHeight) - - return nil -} - -// Using proofs: counterparty.{connection,state,nextTimeout,client} -func (obj Object) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { - if !obj.state.Transit(ctx, Idle, OpenTry) { - return errors.New("invalid state") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.counterparty.state.Is(ctx, Init) { - return errors.New("counterparty state not init") - } - - err = obj.assertSymmetric(ctx) - if err != nil { - return err - } - - if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { - return errors.New("unexpected counterparty timeout value") - } - - // TODO: commented out, need to check whether the stored client is compatible - // make a separate module that manages recent n block headers - /* - var expected client.ConsensusState - obj.self.Get(ctx, expheight, &expected) - if !obj.counterparty.client.Is(ctx, expected) { - return errors.New("unexpected counterparty client value") - } - */ - - // CONTRACT: OpenTry() should be called after man.Create(), not man.Query(), - // which will ensure - // assert(get("connections/{desiredIdentifier}") === null) and - // set("connections{identifier}", connection) - - obj.nextTimeout.Set(ctx, nextTimeoutHeight) - - return nil -} - -// Using proofs: counterparty.{connection,state, nextTimeout} -func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { - - if !obj.state.Transit(ctx, Init, Open) { - return errors.New("ack on non-init connection") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.counterparty.state.Is(ctx, OpenTry) { - return errors.New("counterparty state not try") - } - - err = obj.assertSymmetric(ctx) - if err != nil { - return err - } - - if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { - return errors.New("unexpected counterparty timeout value") - } - - // TODO: commented out, implement in v1 - /* - var expected client.ConsensusState - obj.self.Get(ctx, expheight, &expected) - if !obj.counterparty.client.Is(ctx, expected) { - return errors.New("unexpected counterparty client value") - } - */ - - obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) - - return nil + obj.permission.Delete(ctx) } -// Using proofs: counterparty.{connection,state, nextTimeout} -func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { - if !obj.state.Transit(ctx, OpenTry, Open) { - return errors.New("confirm on non-try connection") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.counterparty.state.Is(ctx, Open) { - return errors.New("counterparty state not open") - } - - err = obj.assertSymmetric(ctx) - if err != nil { - return err - } - - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { - return errors.New("unexpected counterparty timeout value") - } - - obj.nextTimeout.Set(ctx, 0) - - return nil -} - -func (obj Object) OpenTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { - return errors.New("timeout height not yet reached") - } - - // XXX: double check if a user can bypass the verification logic somehow - switch obj.state.Get(ctx) { - case Init: - if !obj.counterparty.connection.Is(ctx, nil) { - return errors.New("counterparty connection exists") - } - case OpenTry: - if !(obj.counterparty.state.Is(ctx, Init) || - obj.counterparty.exists(ctx)) { - return errors.New("counterparty connection state not init") - } - // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) - case Open: - if obj.counterparty.state.Is(ctx, OpenTry) { - return errors.New("counterparty connection state not tryopen") - } - } - - obj.remove(ctx) - - return nil -} - -func (obj Object) CloseInit(ctx sdk.Context, nextTimeout uint64) error { - if !obj.state.Transit(ctx, Open, CloseTry) { - return errors.New("closeinit on non-open connection") - } - - obj.nextTimeout.Set(ctx, nextTimeout) - - return nil -} - -func (obj Object) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { - if !obj.state.Transit(ctx, Open, Closed) { - return errors.New("closetry on non-open connection") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.counterparty.state.Is(ctx, CloseTry) { - return errors.New("unexpected counterparty state value") - } - - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { - return errors.New("unexpected counterparty timeout value") - } - - obj.nextTimeout.Set(ctx, nextTimeoutHeight) - - return nil -} - -func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { - if !obj.state.Transit(ctx, CloseTry, Closed) { - return errors.New("closeack on non-closetry connection") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.counterparty.state.Is(ctx, Closed) { - return errors.New("unexpected counterparty state value") - } - - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { - return errors.New("unexpected counterparty timeout value") - } +type CounterObject struct { + ID string + Connection commitment.Value + Permission commitment.String - obj.nextTimeout.Set(ctx, 0) + Mapping commitment.Mapping - return nil + Client client.CounterObject } -func (obj Object) CloseTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { - return errors.New("timeout height not yet reached") - } - - // XXX: double check if the user can bypass the verification logic somehow - switch obj.state.Get(ctx) { - case CloseTry: - if !obj.counterparty.state.Is(ctx, Open) { - return errors.New("counterparty connection state not open") - } - case Closed: - if !obj.counterparty.state.Is(ctx, CloseTry) { - return errors.New("counterparty connection state not closetry") - } - } - - obj.state.Set(ctx, Open) - obj.nextTimeout.Set(ctx, 0) - - return nil - -} +// Flow(DEPRECATED): +// 1. a module calls SubManager.{Create, Query}() +// 2. SubManager calls StateManager.RequestBase(id string) +// 3-1. If id is not reserved, StateManager marks id as reserved and returns base +// 3-2. If id is reserved, StateManager checks if the SubManager is one who reserved +// 4. if okay, Manager return the base, which only Manager has access +// 5. SubManager returns the result of method call diff --git a/x/ibc/03-connection/types.go b/x/ibc/03-connection/types.go index 50df047a6b21..62f5de12b2a5 100644 --- a/x/ibc/03-connection/types.go +++ b/x/ibc/03-connection/types.go @@ -1,37 +1,11 @@ package connection -type State = byte +import () -const ( - Idle State = iota - Init - OpenTry - Open - CloseTry - Closed -) +type Connection interface { + GetCounterparty() string + GetClient() string + GetCounterpartyClient() string -// TODO: Connection is amino marshaled currently, need to implement MarshalBinary manually -type Connection struct { - Counterparty string - Client string - CounterpartyClient string -} - -func (conn Connection) Equal(conn0 Connection) bool { - return conn.Counterparty == conn0.Counterparty && - conn.Client == conn0.Client && - conn.CounterpartyClient == conn0.CounterpartyClient -} - -func (conn Connection) Symmetric(id string, conn0 Connection) bool { - return conn0.Equal(conn.Symmetry(id)) -} - -func (conn Connection) Symmetry(id string) Connection { - return Connection{ - Counterparty: id, - Client: conn.CounterpartyClient, - CounterpartyClient: conn.Client, - } + Available() bool } diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index 10b409b28b99..d2ef335d00e0 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -45,6 +45,12 @@ func NewMapping(base Base, prefix []byte) Mapping { } } +func (m Mapping) Prefix(prefix []byte) Mapping { + return Mapping{ + base: m.base.Prefix(prefix), + } +} + func (m Mapping) Value(key []byte) Value { return Value{ base: m.base, @@ -81,6 +87,18 @@ func (v Enum) Is(ctx sdk.Context, value byte) bool { return v.Value.IsRaw(ctx, []byte{value}) } +type String struct { + Value +} + +func NewString(v Value) String { + return String{v} +} + +func (v String) Is(ctx sdk.Context, value string) bool { + return v.Value.Is(ctx, value) +} + type Integer struct { Value From a2a0233ba1db6366dbbdbf570d42987653075d0e Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 5 Jul 2019 21:07:46 +0200 Subject: [PATCH 039/182] fix all syntax errors --- x/ibc/03-connection/cli.go | 17 +- .../{handshake/manager.go => handshake.go} | 249 +++++++++--------- x/ibc/03-connection/manager.go | 197 +++++++------- x/ibc/23-commitment/value.go | 12 + 4 files changed, 245 insertions(+), 230 deletions(-) rename x/ibc/03-connection/{handshake/manager.go => handshake.go} (52%) diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index ffbebcb0d27e..a76c89c37097 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -1,5 +1,6 @@ package connection +/* import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" @@ -8,13 +9,12 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) + // CLIObject stores the key for each object fields type CLIObject struct { - ID string - ConnectionKey []byte - // StateKey []byte - // NextTimeoutKey []byte - PermissionKey []byte + ID string + ClientIDKey []byte + AvailableKey []byte Client client.CLIObject @@ -26,6 +26,8 @@ func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { obj := man.object(id) return CLIObject{ ID: obj.id, + ClientIDKey: obj.clientid.Key(), + Available ConnectionKey: obj.connection.Key(), // StateKey: obj.state.Key(), // NextTimeoutKey: obj.nextTimeout.Key(), @@ -68,9 +70,12 @@ func (obj CLIObject) NextTimeout(ctx context.CLIContext, root merkle.Root) (res proof, err = obj.query(ctx, obj.NextTimeoutKey, &res) return } -*/ +:w +:w + func (obj CLIObject) Permission(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.PermissionKey, &res) return } +*/ diff --git a/x/ibc/03-connection/handshake/manager.go b/x/ibc/03-connection/handshake.go similarity index 52% rename from x/ibc/03-connection/handshake/manager.go rename to x/ibc/03-connection/handshake.go index 38b4816e0fd4..ed1e3bb405e0 100644 --- a/x/ibc/03-connection/handshake/manager.go +++ b/x/ibc/03-connection/handshake.go @@ -1,134 +1,138 @@ -package handshake +package connection import ( "errors" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -type Manager struct { - connection.PermissionedManager +type State = byte - counterparty CounterpartyManager +const ( + Idle State = iota + Init + OpenTry + Open + CloseTry + Closed +) + +type Handshake struct { + Counterparty string + CounterpartyClient string } -func NewManager(man connection.PermissionedManager) Manager { - return Manager{ - PermissionedManager: man, +type Handshaker struct { + man Manager - counterparty: NewCounterpartyManager(man.Cdc()), - } + counterparty CounterpartyHandshaker +} + +func (man Handshaker) Kind() string { + return "handshake" } -type CounterpartyManager struct { - protocol commitment.Mapping +// TODO: ocapify Manager; an actor who holds Manager +// should not be able to construct creaters from it +// or add Seal() method to Manager? +func NewHandshaker(man Manager) Handshaker { + return Handshaker{ + man: man, - client client.CounterpartyManager + counterparty: CounterpartyHandshaker{man.counterparty}, + } } -func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { - protocol := commitment.NewBase(cdc) +type CounterpartyHandshaker struct { + man CounterpartyManager +} - return CounterpartyManager{ - protocol: commitment.NewMapping(protocol, []byte("/connection/")), +type HandshakeObject struct { + Object - client: client.NewCounterpartyManager(protocol), - } + state state.Enum + handshake state.Value // type Handshake + nextTimeout state.Integer + + counterparty CounterHandshakeObject +} + +type CounterHandshakeObject struct { + CounterObject + + state commitment.Enum + handshake commitment.Value + nextTimeout commitment.Integer } // CONTRACT: client and remote must be filled by the caller -func (man Manager) object(parent connection.Object) Object { - return Object{ +func (man Handshaker) object(parent Object) HandshakeObject { + return HandshakeObject{ Object: parent, - nextTimeout: state.NewInteger(parent.Mapping().Value([]byte("/timeout")), state.Dec), + state: state.NewEnum(man.man.protocol.Value([]byte(parent.id + "/state"))), + handshake: man.man.protocol.Value([]byte(parent.id + "/handshake")), + nextTimeout: state.NewInteger(man.man.protocol.Value([]byte(parent.id+"/timeout")), state.Dec), - counterparty: man.counterparty.object(parent.Counterparty()), + // CONTRACT: counterparty must be filled by the caller } } -func (man CounterpartyManager) object(parent connection.CounterObject) CounterObject { - return CounterObject{ - CounterObject: parent, +func (man CounterpartyHandshaker) object(id string) CounterHandshakeObject { + return CounterHandshakeObject{ + CounterObject: man.man.object(id), - nextTimeout: commitment.NewInteger(parent.Mapping.Value([]byte("/timeout")), state.Dec), + state: commitment.NewEnum(man.man.protocol.Value([]byte(id + "/state"))), + handshake: man.man.protocol.Value([]byte(id + "/handshake")), + nextTimeout: commitment.NewInteger(man.man.protocol.Value([]byte(id+"/timeout")), state.Dec), } } -func (man Manager) Create(ctx sdk.Context, id string, connection Connection) (obj Object, err error) { - cobj, err := man.PermissionedManager.Create(ctx, id, connection) +func (man Handshaker) create(ctx sdk.Context, id, clientid string, handshake Handshake) (obj HandshakeObject, err error) { + cobj, err := man.man.create(ctx, id, clientid, man.Kind()) if err != nil { return } obj = man.object(cobj) + obj.handshake.Set(ctx, handshake) + obj.counterparty = man.counterparty.object(handshake.Counterparty) return obj, nil } -func (man Manager) query(ctx sdk.Context, id string) (obj Object, err error) { - cobj, err := man.PermissionedManager.Query(ctx, id) +func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeObject, err error) { + cobj, err := man.man.query(ctx, id, man.Kind()) if err != nil { return } obj = man.object(cobj) + handshake := obj.Handshake(ctx) + obj.counterparty = man.counterparty.object(handshake.Counterparty) return } -type Object struct { - connection.Object - - nextTimeout state.Integer - - client client.Object - - counterparty CounterObject -} - -type CounterObject struct { - connection.CounterObject - - nextTimeout commitment.Integer - - client client.CounterObject +func (obj HandshakeObject) Handshake(ctx sdk.Context) (res Handshake) { + obj.handshake.Get(ctx, &res) + return } -func (obj Object) NextTimeout(ctx sdk.Context) uint64 { +func (obj HandshakeObject) Timeout(ctx sdk.Context) uint64 { return obj.nextTimeout.Get(ctx) } -// If there is no proof provided, assume not exists -func (obj CounterObject) exists(ctx sdk.Context) bool { - /* - // XXX - if !obj.connection.Proven(ctx) { - return false - } - - return obj.connection.Exists(ctx) - */ - - return false +func (obj HandshakeObject) NextTimeout(ctx sdk.Context) uint64 { + return obj.nextTimeout.Get(ctx) } -// TODO: make it private -func (obj Object) Delete(ctx sdk.Context) { - obj.Object.Remove(ctx) +func (obj HandshakeObject) remove(ctx sdk.Context) { + obj.Object.remove(ctx) + obj.state.Delete(ctx) + obj.handshake.Delete(ctx) obj.nextTimeout.Delete(ctx) } -func (obj Object) assertSymmetric(ctx sdk.Context) error { - if !obj.counterparty.connection.Is(ctx, obj.Connection(ctx).Symmetry(obj.id)) { - return errors.New("unexpected counterparty connection value") - } - - return nil -} - func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { if uint64(ctx.BlockHeight()) > timeoutHeight { return errors.New("timeout") @@ -138,47 +142,51 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { } // Using proofs: none -func (obj Object) OpenInit(ctx sdk.Context, nextTimeoutHeight uint64) error { - if !obj.state.Transit(ctx, Idle, Init) { - return errors.New("init on non-idle connection") - } - - // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), - // which will ensure +func (man Handshaker) OpenInit(ctx sdk.Context, + id, clientid string, handshake Handshake, nextTimeoutHeight uint64, +) error { + // man.Create() will ensure // assert(get("connections/{identifier}") === null) and // set("connections{identifier}", connection) + obj, err := man.create(ctx, id, clientid, handshake) + if err != nil { + return err + } obj.nextTimeout.Set(ctx, nextTimeoutHeight) + obj.state.Set(ctx, Init) return nil } // Using proofs: counterparty.{connection,state,nextTimeout,client} -func (obj Object) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { - if !obj.state.Transit(ctx, Idle, OpenTry) { - return errors.New("invalid state") - } - - err := assertTimeout(ctx, timeoutHeight) +func (man Handshaker) OpenTry(ctx sdk.Context, + id, clientid string, handshake Handshake, timeoutHeight, nextTimeoutHeight uint64, +) error { + obj, err := man.create(ctx, id, clientid, handshake) if err != nil { return err } - if !obj.counterparty.state.Is(ctx, Init) { - return errors.New("counterparty state not init") - } - - err = obj.assertSymmetric(ctx) + err = assertTimeout(ctx, timeoutHeight) if err != nil { return err } + if !obj.counterparty.handshake.Is(ctx, Handshake{ + Counterparty: id, + CounterpartyClient: clientid, + }) { + return errors.New("wrong counterparty") + } + if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { return errors.New("unexpected counterparty timeout value") } // TODO: commented out, need to check whether the stored client is compatible // make a separate module that manages recent n block headers + // ref #4647 /* var expected client.ConsensusState obj.self.Get(ctx, expheight, &expected) @@ -192,30 +200,33 @@ func (obj Object) OpenTry(ctx sdk.Context, expheight uint64, timeoutHeight, next // assert(get("connections/{desiredIdentifier}") === null) and // set("connections{identifier}", connection) + obj.state.Set(ctx, OpenTry) obj.nextTimeout.Set(ctx, nextTimeoutHeight) return nil } -// Using proofs: counterparty.{connection,state, nextTimeout} -func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { +// Using proofs: counterparty.{handshake,nextTimeout} +func (man Handshaker) OpenAck(ctx sdk.Context, id string, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { + obj, err := man.query(ctx, id) + if err != nil { + return err + } if !obj.state.Transit(ctx, Init, Open) { return errors.New("ack on non-init connection") } - err := assertTimeout(ctx, timeoutHeight) + err = assertTimeout(ctx, timeoutHeight) if err != nil { return err } - if !obj.counterparty.state.Is(ctx, OpenTry) { - return errors.New("counterparty state not try") - } - - err = obj.assertSymmetric(ctx) - if err != nil { - return err + if !obj.counterparty.handshake.Is(ctx, Handshake{ + Counterparty: obj.ID(), + CounterpartyClient: obj.Client().ID(), + }) { + return errors.New("wrong counterparty") } if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { @@ -237,25 +248,28 @@ func (obj Object) OpenAck(ctx sdk.Context, expheight uint64, timeoutHeight, next } // Using proofs: counterparty.{connection,state, nextTimeout} -func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { - if !obj.state.Transit(ctx, OpenTry, Open) { - return errors.New("confirm on non-try connection") - } - - err := assertTimeout(ctx, timeoutHeight) +func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint64) error { + obj, err := man.query(ctx, id) if err != nil { return err } - if !obj.counterparty.state.Is(ctx, Open) { - return errors.New("counterparty state not open") + if !obj.state.Transit(ctx, OpenTry, Open) { + return errors.New("confirm on non-try connection") } - err = obj.assertSymmetric(ctx) + err = assertTimeout(ctx, timeoutHeight) if err != nil { return err } + if !obj.counterparty.handshake.Is(ctx, Handshake{ + Counterparty: obj.ID(), + CounterpartyClient: obj.Client().ID(), + }) { + return errors.New("counterparty state not open or wrong counterparty") + } + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } @@ -265,20 +279,19 @@ func (obj Object) OpenConfirm(ctx sdk.Context, timeoutHeight uint64) error { return nil } -func (obj Object) OpenTimeout(ctx sdk.Context) error { +func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } - // XXX: double check if a user can bypass the verification logic somehow switch obj.state.Get(ctx) { case Init: - if !obj.counterparty.connection.Is(ctx, nil) { + if !obj.counterparty.handshake.Is(ctx, nil) { return errors.New("counterparty connection exists") } case OpenTry: if !(obj.counterparty.state.Is(ctx, Init) || - obj.counterparty.exists(ctx)) { + obj.counterparty.clientid.Is(ctx, "")) /*FIXME: empty string does not work, it should be nil*/ { return errors.New("counterparty connection state not init") } // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) @@ -293,7 +306,7 @@ func (obj Object) OpenTimeout(ctx sdk.Context) error { return nil } -func (obj Object) CloseInit(ctx sdk.Context, nextTimeout uint64) error { +func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error { if !obj.state.Transit(ctx, Open, CloseTry) { return errors.New("closeinit on non-open connection") } @@ -303,7 +316,7 @@ func (obj Object) CloseInit(ctx sdk.Context, nextTimeout uint64) error { return nil } -func (obj Object) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { +func (obj HandshakeObject) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { if !obj.state.Transit(ctx, Open, Closed) { return errors.New("closetry on non-open connection") } @@ -326,7 +339,7 @@ func (obj Object) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uin return nil } -func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { +func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { if !obj.state.Transit(ctx, CloseTry, Closed) { return errors.New("closeack on non-closetry connection") } @@ -349,7 +362,7 @@ func (obj Object) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { return nil } -func (obj Object) CloseTimeout(ctx sdk.Context) error { +func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index bd74bddf142e..6918224e7eb7 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -14,165 +14,150 @@ import ( type Manager struct { protocol state.Mapping - table map[string]struct{} - client client.Manager counterparty CounterpartyManager } +func NewManager(protocol state.Base, client client.Manager) Manager { + return Manager{ + protocol: state.NewMapping(protocol, ([]byte("/connection/"))), + client: client, + counterparty: NewCounterpartyManager(protocol.Cdc()), + } +} + type CounterpartyManager struct { protocol commitment.Mapping client client.CounterpartyManager } -// CONTRACT: should be called on initialization time only -func (man Manager) Register(name string) PermissionedManager { - if _, ok := man.table[name]; ok { - panic("SubManager registered for existing name") - } - man.table[name] = struct{}{} +func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { + protocol := commitment.NewBase(cdc) - return PermissionedManager{man, name} + return CounterpartyManager{ + protocol: commitment.NewMapping(protocol, []byte("/connection/")), + + client: client.NewCounterpartyManager(protocol), + } } -func (man Manager) mapping(id string) state.Mapping { - return man.protocol.Prefix([]byte(id)) +type Object struct { + id string + + protocol state.Mapping + clientid state.String + available state.Boolean + + kind state.String + + client client.Object } func (man Manager) object(id string) Object { return Object{ - id: id, - connection: man.protocol.Value([]byte(id)), - permission: state.NewString(man.protocol.Value([]byte(id + "/permission"))), + id: id, - mapping: man.protocol.Prefix([]byte(id)), + protocol: man.protocol.Prefix([]byte(id + "/")), + clientid: state.NewString(man.protocol.Value([]byte(id + "/client"))), + available: state.NewBoolean(man.protocol.Value([]byte(id + "/available"))), - // CONTRACT: client should be filled by the caller + kind: state.NewString(man.protocol.Value([]byte(id + "/kind"))), - counterparty: man.counterparty.object(id), + // CONTRACT: client must be filled by the caller } } +type CounterObject struct { + id string + + protocol commitment.Mapping + clientid commitment.String + available commitment.Boolean + + kind commitment.String + + client client.CounterObject +} + func (man CounterpartyManager) object(id string) CounterObject { return CounterObject{ - ID: id, - Connection: man.protocol.Value([]byte(id)), - Permission: commitment.NewString(man.protocol.Value([]byte(id + "/permission"))), + id: id, + protocol: man.protocol.Prefix([]byte(id + "/")), + clientid: commitment.NewString(man.protocol.Value([]byte(id + "/client"))), + available: commitment.NewBoolean(man.protocol.Value([]byte(id + "/available"))), - // CONTRACT: client should be filled by the caller + kind: commitment.NewString(man.protocol.Value([]byte(id + "/kind"))), - Mapping: man.protocol.Prefix([]byte(id)), + // CONTRACT: client should be filled by the caller } } +func (obj Object) ID() string { + return obj.id +} -func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { - obj = man.object(id) - if !obj.exists(ctx) { - err = errors.New("Object not exists") - return - } - obj.client, err = man.client.Query(ctx, obj.Connection(ctx).GetClient()) - return +func (obj Object) ClientID(ctx sdk.Context) string { + return obj.clientid.Get(ctx) } -type PermissionedManager struct { - man Manager - name string +func (obj Object) Available(ctx sdk.Context) bool { + return obj.available.Get(ctx) } -func (man PermissionedManager) Cdc() *codec.Codec { - return man.man.protocol.Cdc() +func (obj Object) Client() client.Object { + return obj.client } -func (man PermissionedManager) object(id string) Object { - return man.man.object(id) +func (obj Object) remove(ctx sdk.Context) { + obj.clientid.Delete(ctx) + obj.available.Delete(ctx) + obj.kind.Delete(ctx) +} + +func (obj Object) exists(ctx sdk.Context) bool { + return obj.clientid.Exists(ctx) } -func (man PermissionedManager) Create(ctx sdk.Context, id string, connection Connection) (obj Object, err error) { +func (man Manager) Cdc() *codec.Codec { + return man.protocol.Cdc() +} + +func (man Manager) create(ctx sdk.Context, id, clientid string, kind string) (obj Object, err error) { obj = man.object(id) if obj.exists(ctx) { err = errors.New("Object already exists") return } - obj.connection.Set(ctx, connection) - obj.permission.Set(ctx, man.name) - obj.client, err = man.man.client.Query(ctx, connection.GetClient()) + obj.clientid.Set(ctx, clientid) + obj.kind.Set(ctx, kind) return } -func (man PermissionedManager) Query(ctx sdk.Context, id string) (obj Object, err error) { - obj = man.object(id) - if !obj.exists(ctx) { - err = errors.New("Object not exists") +// query() is used internally by the connection creators +// checing the connection kind +func (man Manager) query(ctx sdk.Context, id string, kind string) (obj Object, err error) { + obj, err = man.Query(ctx, id) + if err != nil { return } - if obj.Permission(ctx) != man.name { - err = errors.New("Object created with different permission") + if obj.kind.Get(ctx) != kind { + err = errors.New("kind mismatch") return } - obj.client, err = man.man.client.Query(ctx, obj.Connection(ctx).GetClient()) return } -type Object struct { - id string - connection state.Value // Connection - permission state.String - - mapping state.Mapping - - client client.Object - - counterparty CounterObject -} - -func (obj Object) ID() string { - return obj.id -} - -func (obj Object) Connection(ctx sdk.Context) (res Connection) { - obj.connection.Get(ctx, &res) +func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { + obj = man.object(id) + if !obj.exists(ctx) { + err = errors.New("Object not exists") + return + } + if !obj.Available(ctx) { + err = errors.New("object not available") + return + } + obj.client, err = man.client.Query(ctx, obj.ClientID(ctx)) return } - -// TODO: it should not be exposed -func (obj Object) Permission(ctx sdk.Context) string { - return obj.permission.Get(ctx) -} - -func (obj Object) Mapping() state.Mapping { - return obj.mapping -} - -func (obj Object) Counterparty() CounterObject { - return obj.counterparty -} - -func (obj Object) exists(ctx sdk.Context) bool { - return obj.connection.Exists(ctx) -} - -func (obj Object) Delete(ctx sdk.Context) { - obj.connection.Delete(ctx) - obj.permission.Delete(ctx) -} - -type CounterObject struct { - ID string - Connection commitment.Value - Permission commitment.String - - Mapping commitment.Mapping - - Client client.CounterObject -} - -// Flow(DEPRECATED): -// 1. a module calls SubManager.{Create, Query}() -// 2. SubManager calls StateManager.RequestBase(id string) -// 3-1. If id is not reserved, StateManager marks id as reserved and returns base -// 3-2. If id is reserved, StateManager checks if the SubManager is one who reserved -// 4. if okay, Manager return the base, which only Manager has access -// 5. SubManager returns the result of method call diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index d2ef335d00e0..8b8ec4c82941 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -99,6 +99,18 @@ func (v String) Is(ctx sdk.Context, value string) bool { return v.Value.Is(ctx, value) } +type Boolean struct { + Value +} + +func NewBoolean(v Value) Boolean { + return Boolean{v} +} + +func (v Boolean) Is(ctx sdk.Context, value bool) bool { + return v.Value.Is(ctx, value) +} + type Integer struct { Value From 2d4c7233cc56249cc4629b6ba5e1bc3a9ee24df7 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 5 Jul 2019 22:18:31 +0200 Subject: [PATCH 040/182] test reworking --- x/ibc/03-connection/cli.go | 73 +++++++++--- x/ibc/03-connection/handshake.go | 97 ++++++++++------ x/ibc/03-connection/handshake/types.go | 60 ---------- x/ibc/03-connection/manager.go | 9 +- x/ibc/03-connection/tests/connection_test.go | 21 ++-- x/ibc/03-connection/tests/types.go | 110 +++++++++---------- 6 files changed, 188 insertions(+), 182 deletions(-) delete mode 100644 x/ibc/03-connection/handshake/types.go diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index a76c89c37097..a8acda7162f6 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -1,6 +1,5 @@ package connection -/* import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" @@ -9,12 +8,12 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) - // CLIObject stores the key for each object fields type CLIObject struct { - ID string - ClientIDKey []byte - AvailableKey []byte + ID string + ClientIDKey []byte + AvailableKey []byte + KindKey []byte Client client.CLIObject @@ -25,19 +24,16 @@ type CLIObject struct { func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { obj := man.object(id) return CLIObject{ - ID: obj.id, - ClientIDKey: obj.clientid.Key(), - Available - ConnectionKey: obj.connection.Key(), - // StateKey: obj.state.Key(), - // NextTimeoutKey: obj.nextTimeout.Key(), - PermissionKey: obj.permission.Key(), + ID: obj.id, + ClientIDKey: obj.clientid.Key(), + AvailableKey: obj.available.Key(), + KindKey: obj.kind.Key(), // TODO: unify man.CLIObject() <=> obj.CLI() Client: obj.client.CLI(root), Root: root, - Cdc: obj.connection.Cdc(), + Cdc: obj.clientid.Cdc(), } } @@ -55,8 +51,52 @@ func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) } -func (obj CLIObject) Connection(ctx context.CLIContext, root merkle.Root) (res Connection, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.ConnectionKey, &res) +func (obj CLIObject) ClientID(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.ClientIDKey, &res) + return +} + +func (obj CLIObject) Available(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.AvailableKey, &res) + return +} + +func (obj CLIObject) Kind(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.KindKey, &res) + return +} + +type CLIHandshakeObject struct { + CLIObject + + StateKey []byte + HandshakeKey []byte + TimeoutKey []byte +} + +func (man Handshaker) CLIObject(root merkle.Root, id string) CLIHandshakeObject { + obj := man.object(man.man.object(id)) + return CLIHandshakeObject{ + CLIObject: man.man.CLIObject(root, id), + + StateKey: obj.state.Key(), + HandshakeKey: obj.handshake.Key(), + TimeoutKey: obj.nextTimeout.Key(), + } +} + +func (obj CLIHandshakeObject) ClientID(ctx context.CLIContext, root merkle.Root) (res byte, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.ClientIDKey, &res) + return +} + +func (obj CLIHandshakeObject) Handshake(ctx context.CLIContext, root merkle.Root) (res Handshake, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.HandshakeKey, &res) + return +} + +func (obj CLIHandshakeObject) Timeout(ctx context.CLIContext, root merkle.Root) (res uint64, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.TimeoutKey, &res) return } @@ -70,9 +110,6 @@ func (obj CLIObject) NextTimeout(ctx context.CLIContext, root merkle.Root) (res proof, err = obj.query(ctx, obj.NextTimeoutKey, &res) return } -:w -:w - func (obj CLIObject) Permission(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.PermissionKey, &res) diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index ed1e3bb405e0..d08a3209deca 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -113,6 +113,10 @@ func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeObject, er return } +func (obj HandshakeObject) State(ctx sdk.Context) byte { + return obj.state.Get(ctx) +} + func (obj HandshakeObject) Handshake(ctx sdk.Context) (res Handshake) { obj.handshake.Get(ctx, &res) return @@ -144,44 +148,56 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { // Using proofs: none func (man Handshaker) OpenInit(ctx sdk.Context, id, clientid string, handshake Handshake, nextTimeoutHeight uint64, -) error { +) (HandshakeObject, error) { // man.Create() will ensure // assert(get("connections/{identifier}") === null) and // set("connections{identifier}", connection) obj, err := man.create(ctx, id, clientid, handshake) if err != nil { - return err + return HandshakeObject{}, err } obj.nextTimeout.Set(ctx, nextTimeoutHeight) obj.state.Set(ctx, Init) - return nil + return obj, nil } -// Using proofs: counterparty.{connection,state,nextTimeout,client} +// Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenTry(ctx sdk.Context, id, clientid string, handshake Handshake, timeoutHeight, nextTimeoutHeight uint64, -) error { - obj, err := man.create(ctx, id, clientid, handshake) +) (obj HandshakeObject, err error) { + obj, err = man.create(ctx, id, clientid, handshake) if err != nil { - return err + return } err = assertTimeout(ctx, timeoutHeight) if err != nil { - return err + return + } + + if !obj.counterparty.state.Is(ctx, Init) { + err = errors.New("counterparty state not init") + return } if !obj.counterparty.handshake.Is(ctx, Handshake{ Counterparty: id, CounterpartyClient: clientid, }) { - return errors.New("wrong counterparty") + err = errors.New("wrong counterparty") + return + } + + if !obj.counterparty.clientid.Is(ctx, handshake.CounterpartyClient) { + err = errors.New("counterparty client not match") + return } if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { - return errors.New("unexpected counterparty timeout value") + err = errors.New("unexpected counterparty timeout value") + return } // TODO: commented out, need to check whether the stored client is compatible @@ -203,34 +219,49 @@ func (man Handshaker) OpenTry(ctx sdk.Context, obj.state.Set(ctx, OpenTry) obj.nextTimeout.Set(ctx, nextTimeoutHeight) - return nil + return } -// Using proofs: counterparty.{handshake,nextTimeout} -func (man Handshaker) OpenAck(ctx sdk.Context, id string, expheight uint64, timeoutHeight, nextTimeoutHeight uint64) error { - obj, err := man.query(ctx, id) +// Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} +func (man Handshaker) OpenAck(ctx sdk.Context, + id string /*expheight uint64, */, timeoutHeight, nextTimeoutHeight uint64, +) (obj HandshakeObject, err error) { + obj, err = man.query(ctx, id) if err != nil { - return err + return } if !obj.state.Transit(ctx, Init, Open) { - return errors.New("ack on non-init connection") + err = errors.New("ack on non-init connection") + return } err = assertTimeout(ctx, timeoutHeight) if err != nil { - return err + return } if !obj.counterparty.handshake.Is(ctx, Handshake{ Counterparty: obj.ID(), CounterpartyClient: obj.Client().ID(), }) { - return errors.New("wrong counterparty") + err = errors.New("wrong counterparty") + return + } + + if !obj.counterparty.state.Is(ctx, OpenTry) { + err = errors.New("counterparty state not opentry") + return + } + + if !obj.counterparty.clientid.Is(ctx, obj.Handshake(ctx).CounterpartyClient) { + err = errors.New("counterparty client not match") + return } if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { - return errors.New("unexpected counterparty timeout value") + err = errors.New("unexpected counterparty timeout value") + return } // TODO: commented out, implement in v1 @@ -242,41 +273,43 @@ func (man Handshaker) OpenAck(ctx sdk.Context, id string, expheight uint64, time } */ + obj.available.Set(ctx, true) obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) - return nil + return } // Using proofs: counterparty.{connection,state, nextTimeout} -func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint64) error { - obj, err := man.query(ctx, id) +func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint64) (obj HandshakeObject, err error) { + obj, err = man.query(ctx, id) if err != nil { - return err + return } if !obj.state.Transit(ctx, OpenTry, Open) { - return errors.New("confirm on non-try connection") + err = errors.New("confirm on non-try connection") + return } err = assertTimeout(ctx, timeoutHeight) if err != nil { - return err + return } - if !obj.counterparty.handshake.Is(ctx, Handshake{ - Counterparty: obj.ID(), - CounterpartyClient: obj.Client().ID(), - }) { - return errors.New("counterparty state not open or wrong counterparty") + if !obj.counterparty.state.Is(ctx, Open) { + err = errors.New("counterparty state not open") + return } if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { - return errors.New("unexpected counterparty timeout value") + err = errors.New("unexpected counterparty timeout value") + return } + obj.available.Set(ctx, true) obj.nextTimeout.Set(ctx, 0) - return nil + return } func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { diff --git a/x/ibc/03-connection/handshake/types.go b/x/ibc/03-connection/handshake/types.go deleted file mode 100644 index 786948991ad1..000000000000 --- a/x/ibc/03-connection/handshake/types.go +++ /dev/null @@ -1,60 +0,0 @@ -package handshake - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" -) - -type State = byte - -const ( - Idle State = iota - Init - OpenTry - Open - CloseTry - Closed -) - -var _ connection.Connection = Connection{} - -// TODO: Connection is amino marshaled currently, need to implement MarshalBinary manually -type Connection struct { - Counterparty string - Client string - CounterpartyClient string - State State -} - -func (conn Connection) GetCounterparty() string { - return conn.Counterparty -} - -func (conn Connection) GetClient() string { - return conn.Client -} - -func (conn Connection) GetCounterpartyClient() string { - return conn.CounterpartyClient -} - -func (conn Connection) Available() bool { - return conn.State == Open -} - -func (conn Connection) Equal(conn0 Connection) bool { - return conn.Counterparty == conn0.Counterparty && - conn.Client == conn0.Client && - conn.CounterpartyClient == conn0.CounterpartyClient -} - -func (conn Connection) Symmetric(id string, conn0 Connection) bool { - return conn0.Equal(conn.Symmetry(id)) -} - -func (conn Connection) Symmetry(id string) Connection { - return Connection{ - Counterparty: id, - Client: conn.CounterpartyClient, - CounterpartyClient: conn.Client, - } -} diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 6918224e7eb7..390aa3c6e54a 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -135,9 +135,14 @@ func (man Manager) create(ctx sdk.Context, id, clientid string, kind string) (ob } // query() is used internally by the connection creators -// checing the connection kind +// checks connection kind, doesn't check avilability func (man Manager) query(ctx sdk.Context, id string, kind string) (obj Object, err error) { - obj, err = man.Query(ctx, id) + obj = man.object(id) + if !obj.exists(ctx) { + err = errors.New("Object not exists") + return + } + obj.client, err = man.client.Query(ctx, obj.ClientID(ctx)) if err != nil { return } diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index 338218542322..a6c0860ff6ff 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -32,34 +32,35 @@ func TestHandshake(t *testing.T) { node.Counterparty.CreateClient(t) // self.OpenInit - node.Advance(t) + node.OpenInit(t) header := node.Commit() // counterparty.OpenTry node.Counterparty.UpdateClient(t, header) cliobj := node.CLIObject() - _, pconn := node.Query(t, cliobj.ConnectionKey) + _, phand := node.Query(t, cliobj.HandshakeKey) _, pstate := node.Query(t, cliobj.StateKey) - _, ptimeout := node.Query(t, cliobj.NextTimeoutKey) + _, ptimeout := node.Query(t, cliobj.TimeoutKey) + _, pclientid := node.Query(t, cliobj.ClientIDKey) // TODO: implement consensus state checking // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) - node.Advance(t, pconn, pstate, ptimeout /*, pclient*/) + node.Counterparty.OpenTry(t, phand, pstate, ptimeout, pclientid) header = node.Counterparty.Commit() // self.OpenAck node.UpdateClient(t, header) cliobj = node.Counterparty.CLIObject() - _, pconn = node.Counterparty.Query(t, cliobj.ConnectionKey) + _, phand = node.Counterparty.Query(t, cliobj.HandshakeKey) _, pstate = node.Counterparty.Query(t, cliobj.StateKey) - _, ptimeout = node.Counterparty.Query(t, cliobj.NextTimeoutKey) - node.Advance(t, pconn, pstate, ptimeout) + _, ptimeout = node.Counterparty.Query(t, cliobj.TimeoutKey) + _, pclientid = node.Counterparty.Query(t, cliobj.ClientIDKey) + node.OpenAck(t, phand, pstate, ptimeout, pclientid) header = node.Commit() // counterparty.OpenConfirm node.Counterparty.UpdateClient(t, header) cliobj = node.CLIObject() - _, pconn = node.Query(t, cliobj.ConnectionKey) // TODO: check if it is needed _, pstate = node.Query(t, cliobj.StateKey) - _, ptimeout = node.Query(t, cliobj.NextTimeoutKey) - node.Advance(t, pconn, pstate, ptimeout) + _, ptimeout = node.Query(t, cliobj.TimeoutKey) + node.Counterparty.OpenConfirm(t, pstate, ptimeout) } diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 18d941cad038..e1112fc43895 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -20,8 +20,9 @@ type Node struct { *tendermint.Node Counterparty *Node - Connection connection.Connection - State connection.State + Client string + Handshake connection.Handshake + State connection.State Cdc *codec.Codec } @@ -44,11 +45,11 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { Cdc: cdc, } - res.Connection = connection.Connection{ + res.Handshake = connection.Handshake{ Counterparty: res.Counterparty.Name, } - res.Counterparty.Connection = connection.Connection{ + res.Counterparty.Handshake = connection.Handshake{ Counterparty: res.Name, } @@ -60,14 +61,14 @@ func (node *Node) CreateClient(t *testing.T) { climan, _ := node.Manager() obj, err := climan.Create(ctx, node.Counterparty.LastStateVerifier().ConsensusState) require.NoError(t, err) - node.Connection.Client = obj.ID() - node.Counterparty.Connection.CounterpartyClient = obj.ID() + node.Client = obj.ID() + node.Counterparty.Handshake.CounterpartyClient = obj.ID() } func (node *Node) UpdateClient(t *testing.T, header client.Header) { ctx := node.Context() climan, _ := node.Manager() - obj, err := climan.Query(ctx, node.Connection.Client) + obj, err := climan.Query(ctx, node.Client) require.NoError(t, err) err = obj.Update(ctx, header) require.NoError(t, err) @@ -78,28 +79,18 @@ func (node *Node) SetState(state connection.State) { node.Counterparty.State = state } -func (node *Node) Object(t *testing.T, proofs []commitment.Proof) (sdk.Context, connection.Object) { +func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, connection.Handshaker) { ctx := node.Context() store, err := commitment.NewStore(node.Counterparty.Root, proofs) require.NoError(t, err) ctx = commitment.WithStore(ctx, store) _, man := node.Manager() - switch node.State { - case connection.Idle, connection.Init: - obj, err := man.Create(ctx, node.Name, node.Connection) - require.NoError(t, err) - return ctx, obj - default: - obj, err := man.Query(ctx, node.Name) - require.NoError(t, err) - require.Equal(t, node.Connection, obj.Connection(ctx)) - return ctx, obj - } + return ctx, connection.NewHandshaker(man) } -func (node *Node) CLIObject() connection.CLIObject { +func (node *Node) CLIObject() connection.CLIHandshakeObject { _, man := node.Manager() - return man.CLIObject(node.Root, node.Name) + return connection.NewHandshaker(man).CLIObject(node.Root, node.Name) } func base(cdc *codec.Codec, key sdk.StoreKey) (state.Base, state.Base) { @@ -114,43 +105,42 @@ func (node *Node) Manager() (client.Manager, connection.Manager) { return clientman, connection.NewManager(protocol, clientman) } -func (node *Node) Advance(t *testing.T, proofs ...commitment.Proof) { - switch node.State { - // TODO: use different enum type for node.State - case connection.Idle: // self: Idle -> Init - ctx, obj := node.Object(t, proofs) - require.Equal(t, connection.Idle, obj.State(ctx)) - err := obj.OpenInit(ctx, 100) // TODO: test timeout - require.NoError(t, err) - require.Equal(t, connection.Init, obj.State(ctx)) - require.Equal(t, node.Connection, obj.Connection(ctx)) - node.SetState(connection.Init) - case connection.Init: // counter: Idle -> OpenTry - ctx, obj := node.Counterparty.Object(t, proofs) - require.Equal(t, connection.Idle, obj.State(ctx)) - err := obj.OpenTry(ctx, 0 /*TODO*/, 100 /*TODO*/, 100 /*TODO*/) - require.NoError(t, err) - require.Equal(t, connection.OpenTry, obj.State(ctx)) - require.Equal(t, node.Counterparty.Connection, obj.Connection(ctx)) - node.SetState(connection.OpenTry) - case connection.OpenTry: // self: Init -> Open - ctx, obj := node.Object(t, proofs) - require.Equal(t, connection.Init, obj.State(ctx)) - err := obj.OpenAck(ctx, 0 /*TODO*/, 100 /*TODO*/, 100 /*TODO*/) - require.NoError(t, err) - require.Equal(t, connection.Open, obj.State(ctx)) - require.Equal(t, node.Connection, obj.Connection(ctx)) - node.SetState(connection.Open) - case connection.Open: // counter: OpenTry -> Open - ctx, obj := node.Counterparty.Object(t, proofs) - require.Equal(t, connection.OpenTry, obj.State(ctx)) - err := obj.OpenConfirm(ctx, 100 /*TODO*/) - require.NoError(t, err) - require.Equal(t, connection.Open, obj.State(ctx)) - require.Equal(t, node.Counterparty.Connection, obj.Connection(ctx)) - node.SetState(connection.CloseTry) - // case connection.CloseTry // self: Open -> CloseTry - default: - return - } +func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { + ctx, man := node.Handshaker(t, proofs) + obj, err := man.OpenInit(ctx, node.Name, node.Client, node.Handshake, 100) // TODO: test timeout + require.NoError(t, err) + require.Equal(t, connection.Init, obj.State(ctx)) + require.Equal(t, node.Handshake, obj.Handshake(ctx)) + require.False(t, obj.Available(ctx)) + node.SetState(connection.Init) +} + +func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { + ctx, man := node.Handshaker(t, proofs) + obj, err := man.OpenTry(ctx, node.Name, node.Client, node.Handshake, 100 /*TODO*/, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, connection.OpenTry, obj.State(ctx)) + require.Equal(t, node.Handshake, obj.Handshake(ctx)) + require.False(t, obj.Available(ctx)) + node.SetState(connection.OpenTry) +} + +func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { + ctx, man := node.Handshaker(t, proofs) + obj, err := man.OpenAck(ctx, node.Name, 100 /*TODO*/, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, connection.Open, obj.State(ctx)) + require.Equal(t, node.Handshake, obj.Handshake(ctx)) + require.True(t, obj.Available(ctx)) + node.SetState(connection.Open) +} + +func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { + ctx, man := node.Handshaker(t, proofs) + obj, err := man.OpenConfirm(ctx, node.Name, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, connection.Open, obj.State(ctx)) + require.Equal(t, node.Handshake, obj.Handshake(ctx)) + require.True(t, obj.Available(ctx)) + node.SetState(connection.CloseTry) } From 20489fb3c208165271ccef127d952e1b589c6444 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 14:40:40 +0200 Subject: [PATCH 041/182] change connection structure --- x/ibc/03-connection/cli.go | 55 +++++++------ x/ibc/03-connection/handshake.go | 83 +++++++++----------- x/ibc/03-connection/manager.go | 62 ++++++++------- x/ibc/03-connection/tests/connection_test.go | 12 +-- x/ibc/03-connection/tests/types.go | 42 +++++----- x/ibc/03-connection/types.go | 26 ++++-- 6 files changed, 154 insertions(+), 126 deletions(-) diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index a8acda7162f6..0c8e8de505b1 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -10,10 +10,11 @@ import ( // CLIObject stores the key for each object fields type CLIObject struct { - ID string - ClientIDKey []byte - AvailableKey []byte - KindKey []byte + ID string + ConnectionKey []byte + SendableKey []byte + ReceivableKey []byte + KindKey []byte Client client.CLIObject @@ -24,16 +25,17 @@ type CLIObject struct { func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { obj := man.object(id) return CLIObject{ - ID: obj.id, - ClientIDKey: obj.clientid.Key(), - AvailableKey: obj.available.Key(), - KindKey: obj.kind.Key(), + ID: obj.id, + ConnectionKey: obj.connection.Key(), + SendableKey: obj.sendable.Key(), + ReceivableKey: obj.receivable.Key(), + KindKey: obj.kind.Key(), // TODO: unify man.CLIObject() <=> obj.CLI() Client: obj.client.CLI(root), Root: root, - Cdc: obj.clientid.Cdc(), + Cdc: obj.connection.Cdc(), } } @@ -51,17 +53,22 @@ func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) } -func (obj CLIObject) ClientID(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.ClientIDKey, &res) +func (obj CLIObject) Connection(ctx context.CLIContext) (res Connection, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.ConnectionKey, &res) return } -func (obj CLIObject) Available(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.AvailableKey, &res) +func (obj CLIObject) Sendable(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.SendableKey, &res) return } -func (obj CLIObject) Kind(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { +func (obj CLIObject) Receivable(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.ReceivableKey, &res) + return +} + +func (obj CLIObject) Kind(ctx context.CLIContext) (res string, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.KindKey, &res) return } @@ -69,9 +76,9 @@ func (obj CLIObject) Kind(ctx context.CLIContext, root merkle.Root) (res string, type CLIHandshakeObject struct { CLIObject - StateKey []byte - HandshakeKey []byte - TimeoutKey []byte + StateKey []byte + CounterpartyClientKey []byte + TimeoutKey []byte } func (man Handshaker) CLIObject(root merkle.Root, id string) CLIHandshakeObject { @@ -79,19 +86,19 @@ func (man Handshaker) CLIObject(root merkle.Root, id string) CLIHandshakeObject return CLIHandshakeObject{ CLIObject: man.man.CLIObject(root, id), - StateKey: obj.state.Key(), - HandshakeKey: obj.handshake.Key(), - TimeoutKey: obj.nextTimeout.Key(), + StateKey: obj.state.Key(), + CounterpartyClientKey: obj.counterpartyClient.Key(), + TimeoutKey: obj.nextTimeout.Key(), } } -func (obj CLIHandshakeObject) ClientID(ctx context.CLIContext, root merkle.Root) (res byte, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.ClientIDKey, &res) +func (obj CLIHandshakeObject) State(ctx context.CLIContext, root merkle.Root) (res byte, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.StateKey, &res) return } -func (obj CLIHandshakeObject) Handshake(ctx context.CLIContext, root merkle.Root) (res Handshake, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.HandshakeKey, &res) +func (obj CLIHandshakeObject) CounterpartyClient(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.CounterpartyClientKey, &res) return } diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index d08a3209deca..27fd0389bd12 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -20,11 +20,6 @@ const ( Closed ) -type Handshake struct { - Counterparty string - CounterpartyClient string -} - type Handshaker struct { man Manager @@ -53,9 +48,9 @@ type CounterpartyHandshaker struct { type HandshakeObject struct { Object - state state.Enum - handshake state.Value // type Handshake - nextTimeout state.Integer + state state.Enum + counterpartyClient state.String + nextTimeout state.Integer counterparty CounterHandshakeObject } @@ -63,9 +58,9 @@ type HandshakeObject struct { type CounterHandshakeObject struct { CounterObject - state commitment.Enum - handshake commitment.Value - nextTimeout commitment.Integer + state commitment.Enum + counterpartyClient commitment.String + nextTimeout commitment.Integer } // CONTRACT: client and remote must be filled by the caller @@ -73,9 +68,9 @@ func (man Handshaker) object(parent Object) HandshakeObject { return HandshakeObject{ Object: parent, - state: state.NewEnum(man.man.protocol.Value([]byte(parent.id + "/state"))), - handshake: man.man.protocol.Value([]byte(parent.id + "/handshake")), - nextTimeout: state.NewInteger(man.man.protocol.Value([]byte(parent.id+"/timeout")), state.Dec), + state: state.NewEnum(man.man.protocol.Value([]byte(parent.id + "/state"))), + counterpartyClient: state.NewString(man.man.protocol.Value([]byte(parent.id + "/counterpartyClient"))), + nextTimeout: state.NewInteger(man.man.protocol.Value([]byte(parent.id+"/timeout")), state.Dec), // CONTRACT: counterparty must be filled by the caller } @@ -85,20 +80,20 @@ func (man CounterpartyHandshaker) object(id string) CounterHandshakeObject { return CounterHandshakeObject{ CounterObject: man.man.object(id), - state: commitment.NewEnum(man.man.protocol.Value([]byte(id + "/state"))), - handshake: man.man.protocol.Value([]byte(id + "/handshake")), - nextTimeout: commitment.NewInteger(man.man.protocol.Value([]byte(id+"/timeout")), state.Dec), + state: commitment.NewEnum(man.man.protocol.Value([]byte(id + "/state"))), + counterpartyClient: commitment.NewString(man.man.protocol.Value([]byte(id + "/counterpartyClient"))), + nextTimeout: commitment.NewInteger(man.man.protocol.Value([]byte(id+"/timeout")), state.Dec), } } -func (man Handshaker) create(ctx sdk.Context, id, clientid string, handshake Handshake) (obj HandshakeObject, err error) { - cobj, err := man.man.create(ctx, id, clientid, man.Kind()) +func (man Handshaker) create(ctx sdk.Context, id string, connection Connection, counterpartyClient string) (obj HandshakeObject, err error) { + cobj, err := man.man.create(ctx, id, connection, man.Kind()) if err != nil { return } obj = man.object(cobj) - obj.handshake.Set(ctx, handshake) - obj.counterparty = man.counterparty.object(handshake.Counterparty) + obj.counterpartyClient.Set(ctx, counterpartyClient) + obj.counterparty = man.counterparty.object(connection.Counterparty) return obj, nil } @@ -108,8 +103,7 @@ func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeObject, er return } obj = man.object(cobj) - handshake := obj.Handshake(ctx) - obj.counterparty = man.counterparty.object(handshake.Counterparty) + obj.counterparty = man.counterparty.object(obj.Connection(ctx).Counterparty) return } @@ -117,9 +111,8 @@ func (obj HandshakeObject) State(ctx sdk.Context) byte { return obj.state.Get(ctx) } -func (obj HandshakeObject) Handshake(ctx sdk.Context) (res Handshake) { - obj.handshake.Get(ctx, &res) - return +func (obj HandshakeObject) CounterpartyClient(ctx sdk.Context) string { + return obj.counterpartyClient.Get(ctx) } func (obj HandshakeObject) Timeout(ctx sdk.Context) uint64 { @@ -133,7 +126,7 @@ func (obj HandshakeObject) NextTimeout(ctx sdk.Context) uint64 { func (obj HandshakeObject) remove(ctx sdk.Context) { obj.Object.remove(ctx) obj.state.Delete(ctx) - obj.handshake.Delete(ctx) + obj.counterpartyClient.Delete(ctx) obj.nextTimeout.Delete(ctx) } @@ -147,12 +140,12 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { // Using proofs: none func (man Handshaker) OpenInit(ctx sdk.Context, - id, clientid string, handshake Handshake, nextTimeoutHeight uint64, + id string, connection Connection, counterpartyClient string, nextTimeoutHeight uint64, ) (HandshakeObject, error) { // man.Create() will ensure // assert(get("connections/{identifier}") === null) and // set("connections{identifier}", connection) - obj, err := man.create(ctx, id, clientid, handshake) + obj, err := man.create(ctx, id, connection, counterpartyClient) if err != nil { return HandshakeObject{}, err } @@ -165,9 +158,9 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenTry(ctx sdk.Context, - id, clientid string, handshake Handshake, timeoutHeight, nextTimeoutHeight uint64, + id string, connection Connection, counterpartyClient string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { - obj, err = man.create(ctx, id, clientid, handshake) + obj, err = man.create(ctx, id, connection, counterpartyClient) if err != nil { return } @@ -182,15 +175,15 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.handshake.Is(ctx, Handshake{ - Counterparty: id, - CounterpartyClient: clientid, + if !obj.counterparty.connection.Is(ctx, Connection{ + Client: counterpartyClient, + Counterparty: id, }) { - err = errors.New("wrong counterparty") + err = errors.New("wrong counterparty connection") return } - if !obj.counterparty.clientid.Is(ctx, handshake.CounterpartyClient) { + if !obj.counterparty.counterpartyClient.Is(ctx, connection.Client) { err = errors.New("counterparty client not match") return } @@ -241,9 +234,9 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.handshake.Is(ctx, Handshake{ - Counterparty: obj.ID(), - CounterpartyClient: obj.Client().ID(), + if !obj.counterparty.connection.Is(ctx, Connection{ + Client: obj.Connection(ctx).Client, + Counterparty: obj.ID(), }) { err = errors.New("wrong counterparty") return @@ -254,7 +247,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.clientid.Is(ctx, obj.Handshake(ctx).CounterpartyClient) { + if !obj.counterparty.counterpartyClient.Is(ctx, obj.Connection(ctx).Client) { err = errors.New("counterparty client not match") return } @@ -273,7 +266,8 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } */ - obj.available.Set(ctx, true) + obj.sendable.Set(ctx, true) + obj.receivable.Set(ctx, true) obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) return @@ -306,7 +300,8 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint return } - obj.available.Set(ctx, true) + obj.sendable.Set(ctx, true) + obj.receivable.Set(ctx, true) obj.nextTimeout.Set(ctx, 0) return @@ -319,12 +314,12 @@ func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { switch obj.state.Get(ctx) { case Init: - if !obj.counterparty.handshake.Is(ctx, nil) { + if !obj.counterparty.connection.Is(ctx, nil) { return errors.New("counterparty connection exists") } case OpenTry: if !(obj.counterparty.state.Is(ctx, Init) || - obj.counterparty.clientid.Is(ctx, "")) /*FIXME: empty string does not work, it should be nil*/ { + obj.counterparty.connection.Is(ctx, nil)) { return errors.New("counterparty connection state not init") } // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 390aa3c6e54a..ad28264cc594 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -46,9 +46,10 @@ func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { type Object struct { id string - protocol state.Mapping - clientid state.String - available state.Boolean + protocol state.Mapping + connection state.Value + sendable state.Boolean + receivable state.Boolean kind state.String @@ -59,9 +60,10 @@ func (man Manager) object(id string) Object { return Object{ id: id, - protocol: man.protocol.Prefix([]byte(id + "/")), - clientid: state.NewString(man.protocol.Value([]byte(id + "/client"))), - available: state.NewBoolean(man.protocol.Value([]byte(id + "/available"))), + protocol: man.protocol.Prefix([]byte(id + "/")), + connection: man.protocol.Value([]byte(id)), + sendable: state.NewBoolean(man.protocol.Value([]byte(id + "/sendable"))), + receivable: state.NewBoolean(man.protocol.Value([]byte(id + "/receivable"))), kind: state.NewString(man.protocol.Value([]byte(id + "/kind"))), @@ -72,9 +74,10 @@ func (man Manager) object(id string) Object { type CounterObject struct { id string - protocol commitment.Mapping - clientid commitment.String - available commitment.Boolean + protocol commitment.Mapping + connection commitment.Value + sendable commitment.Boolean + receivable commitment.Boolean kind commitment.String @@ -83,10 +86,11 @@ type CounterObject struct { func (man CounterpartyManager) object(id string) CounterObject { return CounterObject{ - id: id, - protocol: man.protocol.Prefix([]byte(id + "/")), - clientid: commitment.NewString(man.protocol.Value([]byte(id + "/client"))), - available: commitment.NewBoolean(man.protocol.Value([]byte(id + "/available"))), + id: id, + protocol: man.protocol.Prefix([]byte(id + "/")), + connection: man.protocol.Value([]byte(id)), + sendable: commitment.NewBoolean(man.protocol.Value([]byte(id + "/sendable"))), + receivable: commitment.NewBoolean(man.protocol.Value([]byte(id + "/receivable"))), kind: commitment.NewString(man.protocol.Value([]byte(id + "/kind"))), @@ -97,12 +101,17 @@ func (obj Object) ID() string { return obj.id } -func (obj Object) ClientID(ctx sdk.Context) string { - return obj.clientid.Get(ctx) +func (obj Object) Connection(ctx sdk.Context) (res Connection) { + obj.connection.Get(ctx, &res) + return +} + +func (obj Object) Sendable(ctx sdk.Context) bool { + return obj.sendable.Get(ctx) } -func (obj Object) Available(ctx sdk.Context) bool { - return obj.available.Get(ctx) +func (obj Object) Receivable(ctx sdk.Context) bool { + return obj.receivable.Get(ctx) } func (obj Object) Client() client.Object { @@ -110,26 +119,27 @@ func (obj Object) Client() client.Object { } func (obj Object) remove(ctx sdk.Context) { - obj.clientid.Delete(ctx) - obj.available.Delete(ctx) + obj.connection.Delete(ctx) + obj.sendable.Delete(ctx) + obj.receivable.Delete(ctx) obj.kind.Delete(ctx) } func (obj Object) exists(ctx sdk.Context) bool { - return obj.clientid.Exists(ctx) + return obj.connection.Exists(ctx) } func (man Manager) Cdc() *codec.Codec { return man.protocol.Cdc() } -func (man Manager) create(ctx sdk.Context, id, clientid string, kind string) (obj Object, err error) { +func (man Manager) create(ctx sdk.Context, id string, connection Connection, kind string) (obj Object, err error) { obj = man.object(id) if obj.exists(ctx) { err = errors.New("Object already exists") return } - obj.clientid.Set(ctx, clientid) + obj.connection.Set(ctx, connection) obj.kind.Set(ctx, kind) return } @@ -142,7 +152,7 @@ func (man Manager) query(ctx sdk.Context, id string, kind string) (obj Object, e err = errors.New("Object not exists") return } - obj.client, err = man.client.Query(ctx, obj.ClientID(ctx)) + obj.client, err = man.client.Query(ctx, obj.Connection(ctx).Client) if err != nil { return } @@ -159,10 +169,6 @@ func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { err = errors.New("Object not exists") return } - if !obj.Available(ctx) { - err = errors.New("object not available") - return - } - obj.client, err = man.client.Query(ctx, obj.ClientID(ctx)) + obj.client, err = man.client.Query(ctx, obj.Connection(ctx).Client) return } diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index a6c0860ff6ff..2edc9c3ad3cf 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -38,23 +38,23 @@ func TestHandshake(t *testing.T) { // counterparty.OpenTry node.Counterparty.UpdateClient(t, header) cliobj := node.CLIObject() - _, phand := node.Query(t, cliobj.HandshakeKey) + _, pconn := node.Query(t, cliobj.ConnectionKey) _, pstate := node.Query(t, cliobj.StateKey) _, ptimeout := node.Query(t, cliobj.TimeoutKey) - _, pclientid := node.Query(t, cliobj.ClientIDKey) + _, pcounterclient := node.Query(t, cliobj.CounterpartyClientKey) // TODO: implement consensus state checking // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) - node.Counterparty.OpenTry(t, phand, pstate, ptimeout, pclientid) + node.Counterparty.OpenTry(t, pconn, pstate, ptimeout, pcounterclient) header = node.Counterparty.Commit() // self.OpenAck node.UpdateClient(t, header) cliobj = node.Counterparty.CLIObject() - _, phand = node.Counterparty.Query(t, cliobj.HandshakeKey) + _, pconn = node.Counterparty.Query(t, cliobj.ConnectionKey) _, pstate = node.Counterparty.Query(t, cliobj.StateKey) _, ptimeout = node.Counterparty.Query(t, cliobj.TimeoutKey) - _, pclientid = node.Counterparty.Query(t, cliobj.ClientIDKey) - node.OpenAck(t, phand, pstate, ptimeout, pclientid) + _, pcounterclient = node.Counterparty.Query(t, cliobj.CounterpartyClientKey) + node.OpenAck(t, pconn, pstate, ptimeout, pcounterclient) header = node.Commit() // counterparty.OpenConfirm diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index e1112fc43895..66bf2434db80 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -20,9 +20,9 @@ type Node struct { *tendermint.Node Counterparty *Node - Client string - Handshake connection.Handshake - State connection.State + CounterpartyClient string + Connection connection.Connection + State connection.State Cdc *codec.Codec } @@ -45,11 +45,11 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { Cdc: cdc, } - res.Handshake = connection.Handshake{ + res.Connection = connection.Connection{ Counterparty: res.Counterparty.Name, } - res.Counterparty.Handshake = connection.Handshake{ + res.Counterparty.Connection = connection.Connection{ Counterparty: res.Name, } @@ -61,14 +61,14 @@ func (node *Node) CreateClient(t *testing.T) { climan, _ := node.Manager() obj, err := climan.Create(ctx, node.Counterparty.LastStateVerifier().ConsensusState) require.NoError(t, err) - node.Client = obj.ID() - node.Counterparty.Handshake.CounterpartyClient = obj.ID() + node.Connection.Client = obj.ID() + node.Counterparty.CounterpartyClient = obj.ID() } func (node *Node) UpdateClient(t *testing.T, header client.Header) { ctx := node.Context() climan, _ := node.Manager() - obj, err := climan.Query(ctx, node.Client) + obj, err := climan.Query(ctx, node.Connection.Client) require.NoError(t, err) err = obj.Update(ctx, header) require.NoError(t, err) @@ -107,21 +107,25 @@ func (node *Node) Manager() (client.Manager, connection.Manager) { func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenInit(ctx, node.Name, node.Client, node.Handshake, 100) // TODO: test timeout + obj, err := man.OpenInit(ctx, node.Name, node.Connection, node.CounterpartyClient, 100) // TODO: test timeout require.NoError(t, err) require.Equal(t, connection.Init, obj.State(ctx)) - require.Equal(t, node.Handshake, obj.Handshake(ctx)) - require.False(t, obj.Available(ctx)) + require.Equal(t, node.Connection, obj.Connection(ctx)) + require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient(ctx)) + require.False(t, obj.Sendable(ctx)) + require.False(t, obj.Receivable(ctx)) node.SetState(connection.Init) } func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, node.Name, node.Client, node.Handshake, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.OpenTry, obj.State(ctx)) - require.Equal(t, node.Handshake, obj.Handshake(ctx)) - require.False(t, obj.Available(ctx)) + require.Equal(t, node.Connection, obj.Connection(ctx)) + require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient(ctx)) + require.False(t, obj.Sendable(ctx)) + require.False(t, obj.Receivable(ctx)) node.SetState(connection.OpenTry) } @@ -130,8 +134,9 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { obj, err := man.OpenAck(ctx, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) - require.Equal(t, node.Handshake, obj.Handshake(ctx)) - require.True(t, obj.Available(ctx)) + require.Equal(t, node.Connection, obj.Connection(ctx)) + require.True(t, obj.Sendable(ctx)) + require.True(t, obj.Receivable(ctx)) node.SetState(connection.Open) } @@ -140,7 +145,8 @@ func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { obj, err := man.OpenConfirm(ctx, node.Name, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) - require.Equal(t, node.Handshake, obj.Handshake(ctx)) - require.True(t, obj.Available(ctx)) + require.Equal(t, node.Connection, obj.Connection(ctx)) + require.True(t, obj.Sendable(ctx)) + require.True(t, obj.Receivable(ctx)) node.SetState(connection.CloseTry) } diff --git a/x/ibc/03-connection/types.go b/x/ibc/03-connection/types.go index 62f5de12b2a5..4811572a5284 100644 --- a/x/ibc/03-connection/types.go +++ b/x/ibc/03-connection/types.go @@ -1,11 +1,25 @@ package connection -import () +import ( + "errors" + "strings" +) -type Connection interface { - GetCounterparty() string - GetClient() string - GetCounterpartyClient() string +type Connection struct { + Client string + Counterparty string +} + +func (conn Connection) MarshalAmino() (string, error) { + return strings.Join([]string{conn.Client, conn.Counterparty}, "/"), nil +} - Available() bool +func (conn *Connection) UnmarshalAmino(text string) (err error) { + fields := strings.Split(text, "/") + if len(fields) < 2 { + return errors.New("not enough number of fields") + } + conn.Client = fields[0] + conn.Counterparty = fields[1] + return nil } From 0b4eab02dd1ff21116293e74722c4091825d760c Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 16:31:45 +0200 Subject: [PATCH 042/182] rm sendable/receivable --- x/ibc/03-connection/cli.go | 15 ++++----------- x/ibc/03-connection/handshake.go | 16 ++++++---------- x/ibc/03-connection/manager.go | 23 +++++++---------------- x/ibc/03-connection/tests/types.go | 12 ++++-------- x/ibc/03-connection/types.go | 9 +++++++++ 5 files changed, 30 insertions(+), 45 deletions(-) diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 0c8e8de505b1..b6f3cb993749 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -12,8 +12,7 @@ import ( type CLIObject struct { ID string ConnectionKey []byte - SendableKey []byte - ReceivableKey []byte + AvailableKey []byte KindKey []byte Client client.CLIObject @@ -27,8 +26,7 @@ func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { return CLIObject{ ID: obj.id, ConnectionKey: obj.connection.Key(), - SendableKey: obj.sendable.Key(), - ReceivableKey: obj.receivable.Key(), + AvailableKey: obj.available.Key(), KindKey: obj.kind.Key(), // TODO: unify man.CLIObject() <=> obj.CLI() @@ -58,13 +56,8 @@ func (obj CLIObject) Connection(ctx context.CLIContext) (res Connection, proof m return } -func (obj CLIObject) Sendable(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.SendableKey, &res) - return -} - -func (obj CLIObject) Receivable(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.ReceivableKey, &res) +func (obj CLIObject) Available(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.AvailableKey, &res) return } diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 27fd0389bd12..1f694dbd6927 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -20,16 +20,14 @@ const ( Closed ) +const HandshakeKind = "handshake" + type Handshaker struct { man Manager counterparty CounterpartyHandshaker } -func (man Handshaker) Kind() string { - return "handshake" -} - // TODO: ocapify Manager; an actor who holds Manager // should not be able to construct creaters from it // or add Seal() method to Manager? @@ -87,7 +85,7 @@ func (man CounterpartyHandshaker) object(id string) CounterHandshakeObject { } func (man Handshaker) create(ctx sdk.Context, id string, connection Connection, counterpartyClient string) (obj HandshakeObject, err error) { - cobj, err := man.man.create(ctx, id, connection, man.Kind()) + cobj, err := man.man.create(ctx, id, connection, HandshakeKind) if err != nil { return } @@ -98,7 +96,7 @@ func (man Handshaker) create(ctx sdk.Context, id string, connection Connection, } func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeObject, err error) { - cobj, err := man.man.query(ctx, id, man.Kind()) + cobj, err := man.man.query(ctx, id, HandshakeKind) if err != nil { return } @@ -266,8 +264,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } */ - obj.sendable.Set(ctx, true) - obj.receivable.Set(ctx, true) + obj.available.Set(ctx, true) obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) return @@ -300,8 +297,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint return } - obj.sendable.Set(ctx, true) - obj.receivable.Set(ctx, true) + obj.available.Set(ctx, true) obj.nextTimeout.Set(ctx, 0) return diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index ad28264cc594..fff3c1bd1552 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -48,8 +48,7 @@ type Object struct { protocol state.Mapping connection state.Value - sendable state.Boolean - receivable state.Boolean + available state.Boolean kind state.String @@ -62,8 +61,7 @@ func (man Manager) object(id string) Object { protocol: man.protocol.Prefix([]byte(id + "/")), connection: man.protocol.Value([]byte(id)), - sendable: state.NewBoolean(man.protocol.Value([]byte(id + "/sendable"))), - receivable: state.NewBoolean(man.protocol.Value([]byte(id + "/receivable"))), + available: state.NewBoolean(man.protocol.Value([]byte(id + "/available"))), kind: state.NewString(man.protocol.Value([]byte(id + "/kind"))), @@ -76,8 +74,7 @@ type CounterObject struct { protocol commitment.Mapping connection commitment.Value - sendable commitment.Boolean - receivable commitment.Boolean + available commitment.Boolean kind commitment.String @@ -89,8 +86,7 @@ func (man CounterpartyManager) object(id string) CounterObject { id: id, protocol: man.protocol.Prefix([]byte(id + "/")), connection: man.protocol.Value([]byte(id)), - sendable: commitment.NewBoolean(man.protocol.Value([]byte(id + "/sendable"))), - receivable: commitment.NewBoolean(man.protocol.Value([]byte(id + "/receivable"))), + available: commitment.NewBoolean(man.protocol.Value([]byte(id + "/available"))), kind: commitment.NewString(man.protocol.Value([]byte(id + "/kind"))), @@ -106,12 +102,8 @@ func (obj Object) Connection(ctx sdk.Context) (res Connection) { return } -func (obj Object) Sendable(ctx sdk.Context) bool { - return obj.sendable.Get(ctx) -} - -func (obj Object) Receivable(ctx sdk.Context) bool { - return obj.receivable.Get(ctx) +func (obj Object) Available(ctx sdk.Context) bool { + return obj.available.Get(ctx) } func (obj Object) Client() client.Object { @@ -120,8 +112,7 @@ func (obj Object) Client() client.Object { func (obj Object) remove(ctx sdk.Context) { obj.connection.Delete(ctx) - obj.sendable.Delete(ctx) - obj.receivable.Delete(ctx) + obj.available.Delete(ctx) obj.kind.Delete(ctx) } diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 66bf2434db80..b0574b221ea7 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -112,8 +112,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { require.Equal(t, connection.Init, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient(ctx)) - require.False(t, obj.Sendable(ctx)) - require.False(t, obj.Receivable(ctx)) + require.False(t, obj.Available(ctx)) node.SetState(connection.Init) } @@ -124,8 +123,7 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { require.Equal(t, connection.OpenTry, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient(ctx)) - require.False(t, obj.Sendable(ctx)) - require.False(t, obj.Receivable(ctx)) + require.False(t, obj.Available(ctx)) node.SetState(connection.OpenTry) } @@ -135,8 +133,7 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) - require.True(t, obj.Sendable(ctx)) - require.True(t, obj.Receivable(ctx)) + require.True(t, obj.Available(ctx)) node.SetState(connection.Open) } @@ -146,7 +143,6 @@ func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) - require.True(t, obj.Sendable(ctx)) - require.True(t, obj.Receivable(ctx)) + require.True(t, obj.Available(ctx)) node.SetState(connection.CloseTry) } diff --git a/x/ibc/03-connection/types.go b/x/ibc/03-connection/types.go index 4811572a5284..428137aad893 100644 --- a/x/ibc/03-connection/types.go +++ b/x/ibc/03-connection/types.go @@ -23,3 +23,12 @@ func (conn *Connection) UnmarshalAmino(text string) (err error) { conn.Counterparty = fields[1] return nil } + +var kinds = map[string]Kind{ + "handshake": Kind{true, true}, +} + +type Kind struct { + Sendable bool + Receivable bool +} From 9481364ce2123ec40d9a2b6acbffa60506a54f56 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 16:34:48 +0200 Subject: [PATCH 043/182] add sendable/receivable method to object --- x/ibc/03-connection/manager.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index fff3c1bd1552..32602dc12ecd 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -110,6 +110,14 @@ func (obj Object) Client() client.Object { return obj.client } +func (obj Object) Sendable(ctx sdk.Context) bool { + return kinds[obj.kind.Get(ctx)].Sendable +} + +func (obj Object) Receivble(ctx sdk.Context) bool { + return kinds[obj.kind.Get(ctx)].Receivable +} + func (obj Object) remove(ctx sdk.Context) { obj.connection.Delete(ctx) obj.available.Delete(ctx) From a3261d7aea42a4dea16e2abd4a3732c722cc6916 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 16:40:01 +0200 Subject: [PATCH 044/182] add checking availabiltiy --- x/ibc/03-connection/manager.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 32602dc12ecd..510867404621 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -168,6 +168,10 @@ func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { err = errors.New("Object not exists") return } + if !obj.Available(ctx) { + err = errors.New("Object not available") + return + } obj.client, err = man.client.Query(ctx, obj.Connection(ctx).Client) return } From ca9ecbca657d1bdd2bbe3576716f32256ba815f0 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 17:47:49 +0200 Subject: [PATCH 045/182] add context() in test --- x/ibc/03-connection/tests/types.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index b0574b221ea7..c9770cfd281b 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -57,7 +57,7 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { } func (node *Node) CreateClient(t *testing.T) { - ctx := node.Context() + ctx := node.Context(t, nil) climan, _ := node.Manager() obj, err := climan.Create(ctx, node.Counterparty.LastStateVerifier().ConsensusState) require.NoError(t, err) @@ -66,7 +66,7 @@ func (node *Node) CreateClient(t *testing.T) { } func (node *Node) UpdateClient(t *testing.T, header client.Header) { - ctx := node.Context() + ctx := node.Context(t, nil) climan, _ := node.Manager() obj, err := climan.Query(ctx, node.Connection.Client) require.NoError(t, err) @@ -79,11 +79,16 @@ func (node *Node) SetState(state connection.State) { node.Counterparty.State = state } -func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, connection.Handshaker) { - ctx := node.Context() +func (node *Node) Context(t *testing.T, proofs []commitment.Proof) sdk.Context { + ctx := node.Node.Context() store, err := commitment.NewStore(node.Counterparty.Root, proofs) require.NoError(t, err) ctx = commitment.WithStore(ctx, store) + return ctx +} + +func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, connection.Handshaker) { + ctx := node.Context(t, proofs) _, man := node.Manager() return ctx, connection.NewHandshaker(man) } From 83b9f5a92afb2f20a98ea0d1d84aba1d5dba9ca6 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 18:49:29 +0200 Subject: [PATCH 046/182] fix most of lint --- store/state/string.go | 2 +- x/ibc/03-connection/handshake.go | 17 ++++++++--------- x/ibc/03-connection/manager.go | 1 + 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/store/state/string.go b/store/state/string.go index 38b92b16ec71..6bfc0300e2ca 100644 --- a/store/state/string.go +++ b/store/state/string.go @@ -14,7 +14,7 @@ func (v String) Get(ctx Context) (res string) { } func (v String) GetSafe(ctx Context) (res string, err error) { - v.Value.GetSafe(ctx, &res) + err = v.Value.GetSafe(ctx, &res) return } diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 1f694dbd6927..83dde7db5882 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -186,7 +186,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } @@ -250,22 +250,21 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } - // TODO: commented out, implement in v1 + // TODO: implement in v1 /* var expected client.ConsensusState - obj.self.Get(ctx, expheight, &expected) + // obj.self.Get(ctx, expheight, &expected) if !obj.counterparty.client.Is(ctx, expected) { - return errors.New("unexpected counterparty client value") + // return errors.New("unexpected counterparty client value") } */ - obj.available.Set(ctx, true) - obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) + obj.nextTimeout.Set(ctx, nextTimeoutHeight) return } @@ -304,7 +303,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint } func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + if !(obj.client.ConsensusState(ctx).GetHeight() > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } @@ -387,7 +386,7 @@ func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error } func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + if !(obj.client.ConsensusState(ctx).GetHeight() > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 510867404621..7d472dfc7e08 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -93,6 +93,7 @@ func (man CounterpartyManager) object(id string) CounterObject { // CONTRACT: client should be filled by the caller } } + func (obj Object) ID() string { return obj.id } From 94edc2f73ab37def0e2ce29ab4ef6511faed4c9e Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 19:15:56 +0200 Subject: [PATCH 047/182] fix lijt --- x/ibc/02-client/tendermint/tests/types.go | 5 ----- x/ibc/03-connection/manager.go | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 860cb424e11d..a601479dbec8 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -23,11 +23,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -// nolint: unused -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - const chainid = "testchain" func NewRoot(keyPrefix []byte) merkle.Root { diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 7d472dfc7e08..7e7f85c48975 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -78,7 +78,8 @@ type CounterObject struct { kind commitment.String - client client.CounterObject + // TODO: prove counterparty client in v1 + client client.CounterObject // nolint: unused } func (man CounterpartyManager) object(id string) CounterObject { From 8da259838247d909c954dc3d0c90427dad10b557 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 7 Jun 2019 23:47:01 +0200 Subject: [PATCH 048/182] add client --- x/ibc/02-client/manager.go | 146 ++++++++++++++++++++++++++++ x/ibc/02-client/tendermint/types.go | 79 +++++++++++++++ x/ibc/02-client/types.go | 46 +++++++++ 3 files changed, 271 insertions(+) create mode 100644 x/ibc/02-client/manager.go create mode 100644 x/ibc/02-client/tendermint/types.go create mode 100644 x/ibc/02-client/types.go diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go new file mode 100644 index 000000000000..89a8a878df49 --- /dev/null +++ b/x/ibc/02-client/manager.go @@ -0,0 +1,146 @@ +package client + +import ( + "errors" + "strconv" + + "github.com/cosmos/cosmos-sdk/store/mapping" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string + +func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { + id := mapping.NewInteger(v, mapping.Dec).Incr(ctx) + return strconv.FormatUint(id, 10) +} + +type Manager struct { + protocol mapping.Mapping + + idval mapping.Value + idgen IDGenerator +} + +func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { + return Manager{ + protocol: mapping.NewMapping(protocol, []byte("/")), + idval: mapping.NewValue(free, []byte("/id")), + idgen: idgen, + } +} + +/* +func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { + if _, ok := man.pred[kind]; ok { + panic("Kind already registered") + } + man.pred[kind] = pred + return man +} +*/ +func (man Manager) object(id string) Object { + return Object{ + id: id, + client: man.protocol.Value([]byte(id)), + freeze: mapping.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + } +} + +func (man Manager) Create(ctx sdk.Context, cs Client) string { + id := man.idgen(ctx, man.idval) + err := man.object(id).create(ctx, cs) + if err != nil { + panic(err) + } + return id +} + +func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { + res := man.object(id) + if !res.exists(ctx) { + return Object{}, errors.New("client not exists") + } + return res, nil +} + +type Object struct { + id string + client mapping.Value + freeze mapping.Boolean +} + +func (obj Object) create(ctx sdk.Context, st Client) error { + if obj.exists(ctx) { + return errors.New("Create client on already existing id") + } + obj.client.Set(ctx, st) + return nil +} + +func (obj Object) exists(ctx sdk.Context) bool { + return obj.client.Exists(ctx) +} + +func (obj Object) ID() string { + return obj.id +} + +func (obj Object) Value(ctx sdk.Context) (res Client) { + obj.client.Get(ctx, &res) + return +} + +func (obj Object) Is(ctx sdk.Context, client Client) bool { + return obj.client.Is(ctx, client) +} + +func (obj Object) Update(ctx sdk.Context, header Header) error { + if !obj.exists(ctx) { + panic("should not update nonexisting client") + } + + if obj.freeze.Get(ctx) { + return errors.New("client is frozen") + } + + var stored Client + obj.client.GetIfExists(ctx, &stored) + updated, err := stored.Validate(header) + if err != nil { + return err + } + + obj.client.Set(ctx, updated) + + return nil +} + +func (obj Object) Freeze(ctx sdk.Context) error { + if !obj.exists(ctx) { + panic("should not freeze nonexisting client") + } + + if obj.freeze.Get(ctx) { + return errors.New("client is already frozen") + } + + obj.freeze.Set(ctx, true) + + return nil +} + +func (obj Object) Delete(ctx sdk.Context) error { + if !obj.exists(ctx) { + panic("should not delete nonexisting client") + } + + if !obj.freeze.Get(ctx) { + return errors.New("client is not frozen") + } + + obj.client.Delete(ctx) + obj.freeze.Delete(ctx) + + return nil +} diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go new file mode 100644 index 000000000000..54655cf702d4 --- /dev/null +++ b/x/ibc/02-client/tendermint/types.go @@ -0,0 +1,79 @@ +package tendermint + +import ( + "bytes" + + "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +// Ref tendermint/lite/base_verifier.go + +var _ client.ValidityPredicateBase = ValidityPredicateBase{} + +type ValidityPredicateBase struct { + Height int64 + NextValidatorSet *types.ValidatorSet +} + +func (ValidityPredicateBase) Kind() client.Kind { + return client.Tendermint +} + +func (base ValidityPredicateBase) GetHeight() int64 { + return base.Height +} + +func (base ValidityPredicateBase) Equal(cbase client.ValidityPredicateBase) bool { + base0, ok := cbase.(ValidityPredicateBase) + if !ok { + return false + } + return base.Height == base0.Height && + bytes.Equal(base.NextValidatorSet.Hash(), base0.NextValidatorSet.Hash()) +} + +var _ client.Client = Client{} + +type Client struct { + Base ValidityPredicateBase + Root commitment.Root +} + +func (Client) Kind() client.Kind { + return client.Tendermint +} + +func (client Client) GetBase() client.ValidityPredicateBase { + return client.Base +} + +func (client Client) GetRoot() commitment.Root { + return client.Root +} + +func (client Client) Validate(header client.Header) (client.Client, error) { + return client, nil // XXX +} + +var _ client.Header = Header{} + +type Header struct { + Base ValidityPredicateBase + Root commitment.Root + Votes []*types.CommitSig +} + +func (header Header) Kind() client.Kind { + return client.Tendermint +} + +func (header Header) GetBase() client.ValidityPredicateBase { + return header.Base +} + +func (header Header) GetRoot() commitment.Root { + return header.Root +} diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go new file mode 100644 index 000000000000..7b9f81ec7789 --- /dev/null +++ b/x/ibc/02-client/types.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +// TODO: types in this file should be (de/)serialized with proto in the future + +type AminoMarshaler interface { + MarshalAmino() (string, error) + UnmarshalAmino(string) error +} + +type ValidityPredicateBase interface { + Kind() Kind + GetHeight() int64 + Equal(ValidityPredicateBase) bool +} + +// ConsensusState +type Client interface { + Kind() Kind + GetBase() ValidityPredicateBase + GetRoot() commitment.Root + Validate(Header) (Client, error) // ValidityPredicate +} + +func Equal(client1, client2 Client) bool { + return client1.Kind() == client2.Kind() && + client1.GetBase().Equal(client2.GetBase()) +} + +type Header interface { + Kind() Kind + // Proof() HeaderProof + GetBase() ValidityPredicateBase // can be nil + GetRoot() commitment.Root +} + +// XXX: Kind should be enum? + +type Kind byte + +const ( + Tendermint Kind = iota +) From 9a07feb7e261b667b3998c53a9f6b9c1edf08e79 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:14:19 +0200 Subject: [PATCH 049/182] add counterpartymanager --- x/ibc/02-client/manager.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 89a8a878df49..97f281cc9596 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -6,6 +6,8 @@ import ( "github.com/cosmos/cosmos-sdk/store/mapping" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string @@ -24,12 +26,22 @@ type Manager struct { func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/")), - idval: mapping.NewValue(free, []byte("/id")), + protocol: mapping.NewMapping(protocol, []byte("/client")), + idval: mapping.NewValue(free, []byte("/client/id")), idgen: idgen, } } +type CounterpartyManager struct { + protocol commitment.Mapping +} + +func NewCounterpartyManager(protocol commitment.Base) CounterpartyManager { + return CounterpartyManager{ + protocol: commitment.NewMapping(protocol, []byte("/client")), + } +} + /* func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { if _, ok := man.pred[kind]; ok { From 1c204dc8514c0fa51e0ea242c7f6ddc06c2dd7e8 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:29:24 +0200 Subject: [PATCH 050/182] fix manager --- x/ibc/02-client/manager.go | 16 ++++++++++++++++ x/ibc/23-commitment/value.go | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 97f281cc9596..c22576b18cd2 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -76,12 +76,28 @@ func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { return res, nil } +func (man CounterpartyManager) object(id string) CounterObject { + return CounterObject{ + id: id, + client: man.protocol.Value([]byte(id)), + } +} + +func (man CounterpartyManager) Query(id string) CounterObject { + return man.object(id) +} + type Object struct { id string client mapping.Value freeze mapping.Boolean } +type CounterObject struct { + id string + client commitment.Value +} + func (obj Object) create(ctx sdk.Context, st Client) error { if obj.exists(ctx) { return errors.New("Create client on already existing id") diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index 70b8502a44e6..10b409b28b99 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -45,6 +45,13 @@ func NewMapping(base Base, prefix []byte) Mapping { } } +func (m Mapping) Value(key []byte) Value { + return Value{ + base: m.base, + key: key, + } +} + type Value struct { base Base key []byte From 6e5346bb37163cfe7b2a3edf564289ab21f18cd4 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:44:25 +0200 Subject: [PATCH 051/182] add Is() to counterobject --- x/ibc/02-client/manager.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index c22576b18cd2..502478104757 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -123,6 +123,10 @@ func (obj Object) Is(ctx sdk.Context, client Client) bool { return obj.client.Is(ctx, client) } +func (obj CounterObject) Is(ctx sdk.Context, client Client) bool { + return obj.client.Is(ctx, client) +} + func (obj Object) Update(ctx sdk.Context, header Header) error { if !obj.exists(ctx) { panic("should not update nonexisting client") From 337040845984a443f61df6ad5333eaa542b9c179 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 12 Jun 2019 00:08:04 +0200 Subject: [PATCH 052/182] add readme, reflect ICS02 revision --- x/ibc/02-client/README.md | 49 ++++++++++++++++++++++++++++++++++++++ x/ibc/02-client/manager.go | 31 ++++++++++-------------- x/ibc/02-client/types.go | 26 ++++++++------------ 3 files changed, 72 insertions(+), 34 deletions(-) create mode 100644 x/ibc/02-client/README.md diff --git a/x/ibc/02-client/README.md b/x/ibc/02-client/README.md new file mode 100644 index 000000000000..a9bd6892771b --- /dev/null +++ b/x/ibc/02-client/README.md @@ -0,0 +1,49 @@ +# ICS 02: Client + +Package `client` defines types and method to store and update light clients which tracks on other chain's state. +The main type is `Client`, which provides `commitment.Root` to verify state proofs and `ConsensusState` to +verify header proofs. + +## Spec + +```typescript +interface ConsensusState { + height: uint64 + root: CommitmentRoot + validityPredicate: ValidityPredicate + eqivocationPredicate: EquivocationPredicate +} + +interface ClientState { + consensusState: ConsensusState + verifiedRoots: Map + frozen: bool +} + +interface Header { + height: uint64 + proof: HeaderProof + state: Maybe[ConsensusState] + root: CommitmentRoot +} + +type ValidityPredicate = (ConsensusState, Header) => Error | ConsensusState + +type EquivocationPredicate = (ConsensusState, Header, Header) => bool +``` + +## Impl + +### types.go + +`spec: interface ConsensusState` is implemented by `type ConsensusState`. `ConsensusState.{GetHeight(), GetRoot(), +Validate(), Equivocation()}` each corresponds to `spec: ConsensusState.{height, root, validityPredicate, +equivocationPredicate}`. `ConsensusState.Kind()` returns `Kind`, which is an enum indicating the type of the +consensus algorithm. + +`spec: interface Header` is implemented by `type Header`. `Header{GetHeight(), Proof(), State(), GetRoot()}` +each corresponds to `spec: Header.{height, proof, state, root}`. + +### manager.go + +`spec: interface ClientState` is implemented by `type Object`. // TODO diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 502478104757..0134d8340d55 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -10,6 +10,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) +// XXX: implement spec: ClientState.verifiedRoots + type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { @@ -59,13 +61,14 @@ func (man Manager) object(id string) Object { } } -func (man Manager) Create(ctx sdk.Context, cs Client) string { +func (man Manager) Create(ctx sdk.Context, cs ConsensusState) (Object, error) { id := man.idgen(ctx, man.idval) - err := man.object(id).create(ctx, cs) - if err != nil { - panic(err) + obj := man.object(id) + if obj.exists(ctx) { + return Object{}, errors.New("Create client on already existing id") } - return id + obj.client.Set(ctx, cs) + return obj, nil } func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { @@ -89,7 +92,7 @@ func (man CounterpartyManager) Query(id string) CounterObject { type Object struct { id string - client mapping.Value + client mapping.Value // ConsensusState freeze mapping.Boolean } @@ -98,14 +101,6 @@ type CounterObject struct { client commitment.Value } -func (obj Object) create(ctx sdk.Context, st Client) error { - if obj.exists(ctx) { - return errors.New("Create client on already existing id") - } - obj.client.Set(ctx, st) - return nil -} - func (obj Object) exists(ctx sdk.Context) bool { return obj.client.Exists(ctx) } @@ -114,16 +109,16 @@ func (obj Object) ID() string { return obj.id } -func (obj Object) Value(ctx sdk.Context) (res Client) { +func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { obj.client.Get(ctx, &res) return } -func (obj Object) Is(ctx sdk.Context, client Client) bool { +func (obj Object) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } -func (obj CounterObject) Is(ctx sdk.Context, client Client) bool { +func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } @@ -136,7 +131,7 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { return errors.New("client is frozen") } - var stored Client + var stored ConsensusState obj.client.GetIfExists(ctx, &stored) updated, err := stored.Validate(header) if err != nil { diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go index 7b9f81ec7789..2ae484853354 100644 --- a/x/ibc/02-client/types.go +++ b/x/ibc/02-client/types.go @@ -5,35 +5,29 @@ import ( ) // TODO: types in this file should be (de/)serialized with proto in the future - -type AminoMarshaler interface { - MarshalAmino() (string, error) - UnmarshalAmino(string) error -} - -type ValidityPredicateBase interface { - Kind() Kind - GetHeight() int64 - Equal(ValidityPredicateBase) bool -} +// currently amkno codec handles it // ConsensusState -type Client interface { +type ConsensusState interface { Kind() Kind - GetBase() ValidityPredicateBase + GetHeight() uint64 GetRoot() commitment.Root - Validate(Header) (Client, error) // ValidityPredicate + Validate(Header) (ConsensusState, error) // ValidityPredicate + Equivocation(Header, Header) bool // EquivocationPredicate } -func Equal(client1, client2 Client) bool { +/* +func Equal(client1, client2 ConsensusState) bool { return client1.Kind() == client2.Kind() && client1.GetBase().Equal(client2.GetBase()) } +*/ type Header interface { Kind() Kind + GetHeight() uint64 // Proof() HeaderProof - GetBase() ValidityPredicateBase // can be nil + State() ConsensusState // can be nil GetRoot() commitment.Root } From 2d43e209046d80a7ff10207c0cba4201ab68de75 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 12 Jun 2019 00:28:13 +0200 Subject: [PATCH 053/182] reflect downstream ics --- x/ibc/02-client/manager.go | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 0134d8340d55..196d62e62fdc 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -4,7 +4,7 @@ import ( "errors" "strconv" - "github.com/cosmos/cosmos-sdk/store/mapping" + "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" @@ -12,24 +12,24 @@ import ( // XXX: implement spec: ClientState.verifiedRoots -type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string +type IDGenerator func(sdk.Context /*Header,*/, state.Value) string -func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { - id := mapping.NewInteger(v, mapping.Dec).Incr(ctx) +func IntegerIDGenerator(ctx sdk.Context, v state.Value) string { + id := state.NewInteger(v, state.Dec).Incr(ctx) return strconv.FormatUint(id, 10) } type Manager struct { - protocol mapping.Mapping + protocol state.Mapping - idval mapping.Value + idval state.Value idgen IDGenerator } -func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { +func NewManager(protocol, free state.Base, idgen IDGenerator) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/client")), - idval: mapping.NewValue(free, []byte("/client/id")), + protocol: state.NewMapping(protocol, []byte("/client")), + idval: state.NewValue(free, []byte("/client/id")), idgen: idgen, } } @@ -57,7 +57,7 @@ func (man Manager) object(id string) Object { return Object{ id: id, client: man.protocol.Value([]byte(id)), - freeze: mapping.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + freeze: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), } } @@ -92,8 +92,8 @@ func (man CounterpartyManager) Query(id string) CounterObject { type Object struct { id string - client mapping.Value // ConsensusState - freeze mapping.Boolean + client state.Value // ConsensusState + freeze state.Boolean } type CounterObject struct { @@ -114,10 +114,6 @@ func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { return } -func (obj Object) Is(ctx sdk.Context, client ConsensusState) bool { - return obj.client.Is(ctx, client) -} - func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } From 2bd98e151839f62baa3d73c9d23cc285a3ce9efd Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 13 Jun 2019 16:00:18 +0200 Subject: [PATCH 054/182] test in progress --- x/ibc/02-client/tendermint/types.go | 96 ++++++----- x/ibc/02-client/tendermint/types_test.go | 131 ++++++++++++++ x/ibc/02-client/tendermint/valset_test.go | 197 ++++++++++++++++++++++ x/ibc/02-client/types.go | 3 - 4 files changed, 386 insertions(+), 41 deletions(-) create mode 100644 x/ibc/02-client/tendermint/types_test.go create mode 100644 x/ibc/02-client/tendermint/valset_test.go diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 54655cf702d4..1442d91d6c99 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -2,78 +2,98 @@ package tendermint import ( "bytes" + "errors" + "fmt" + lerr "github.com/tendermint/tendermint/lite/errors" "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -// Ref tendermint/lite/base_verifier.go - -var _ client.ValidityPredicateBase = ValidityPredicateBase{} +var _ client.ConsensusState = ConsensusState{} -type ValidityPredicateBase struct { - Height int64 +// Ref tendermint/lite/base_verifier.go +type ConsensusState struct { + ChainID string + Height uint64 + Root commitment.Root NextValidatorSet *types.ValidatorSet } -func (ValidityPredicateBase) Kind() client.Kind { +func (ConsensusState) Kind() client.Kind { return client.Tendermint } -func (base ValidityPredicateBase) GetHeight() int64 { - return base.Height +func (cs ConsensusState) GetHeight() uint64 { + return cs.Height } -func (base ValidityPredicateBase) Equal(cbase client.ValidityPredicateBase) bool { - base0, ok := cbase.(ValidityPredicateBase) - if !ok { - return false +func (cs ConsensusState) GetRoot() commitment.Root { + return cs.Root +} + +func (cs ConsensusState) update(header Header) ConsensusState { + return ConsensusState{ + ChainID: cs.ChainID, + Height: uint64(header.Height), + Root: header.AppHash, + NextValidatorSet: header.NextValidatorSet, } - return base.Height == base0.Height && - bytes.Equal(base.NextValidatorSet.Hash(), base0.NextValidatorSet.Hash()) } -var _ client.Client = Client{} +func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, error) { + header, ok := cheader.(Header) + if !ok { + return nil, errors.New("invalid type") + } -type Client struct { - Base ValidityPredicateBase - Root commitment.Root -} + nextvalset := cs.NextValidatorSet + nexthash := nextvalset.Hash() -func (Client) Kind() client.Kind { - return client.Tendermint -} + if cs.Height == uint64(header.Height-1) { + nexthash = cs.NextValidatorSet.Hash() + if !bytes.Equal(header.ValidatorsHash, nexthash) { + fmt.Println(111) + return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) + } + } -func (client Client) GetBase() client.ValidityPredicateBase { - return client.Base -} + if !bytes.Equal(header.NextValidatorsHash, header.NextValidatorSet.Hash()) { + fmt.Println(header) + return nil, lerr.ErrUnexpectedValidators(header.NextValidatorsHash, header.NextValidatorSet.Hash()) + } + + err := header.ValidateBasic(cs.ChainID) + if err != nil { + return nil, err + } -func (client Client) GetRoot() commitment.Root { - return client.Root + err = cs.NextValidatorSet.VerifyCommit(cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) + if err != nil { + return nil, err + } + + return cs.update(header), nil } -func (client Client) Validate(header client.Header) (client.Client, error) { - return client, nil // XXX +func (cs ConsensusState) Equivocation(header1, header2 client.Header) bool { + return false // XXX } var _ client.Header = Header{} type Header struct { - Base ValidityPredicateBase - Root commitment.Root - Votes []*types.CommitSig + // XXX: don't take the entire struct + types.SignedHeader + NextValidatorSet *types.ValidatorSet } func (header Header) Kind() client.Kind { return client.Tendermint } -func (header Header) GetBase() client.ValidityPredicateBase { - return header.Base -} - -func (header Header) GetRoot() commitment.Root { - return header.Root +func (header Header) GetHeight() uint64 { + return uint64(header.Height) } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go new file mode 100644 index 000000000000..44dc0fc9aba9 --- /dev/null +++ b/x/ibc/02-client/tendermint/types_test.go @@ -0,0 +1,131 @@ +package tendermint + +import ( + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/tendermint/tendermint/abci/types" + dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/libs/log" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store" + stypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const chainid = "testchain" + +func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { + key := sdk.NewKVStoreKey("ibc") + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) + err := cms.LoadLatestVersion() + if err != nil { + panic(err) + } + ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger()) + cdc := codec.New() + return key, ctx, cms, cdc +} + +type node struct { + valset MockValidators + + cms sdk.CommitMultiStore + store sdk.KVStore + + commits []tmtypes.SignedHeader +} + +func NewNode(valset MockValidators) *node { + key, ctx, cms, _ := defaultComponents() + return &node{ + valset: valset, + cms: cms, + store: ctx.KVStore(key), + commits: nil, + } +} + +func (node *node) last() tmtypes.SignedHeader { + if len(node.commits) == 0 { + return tmtypes.SignedHeader{} + } + return node.commits[len(node.commits)-1] +} + +func (node *node) Commit() tmtypes.SignedHeader { + valsethash := node.valset.ValidatorSet().Hash() + nextvalset := node.valset.Mutate(false) + nextvalsethash := nextvalset.ValidatorSet().Hash() + commitid := node.cms.Commit() + + header := tmtypes.Header{ + ChainID: chainid, + Height: int64(len(node.commits) + 1), + LastBlockID: tmtypes.BlockID{ + Hash: node.last().Header.Hash(), + }, + + ValidatorsHash: valsethash, + NextValidatorsHash: nextvalsethash, + AppHash: commitid.Hash, + } + + commit := node.valset.Sign(header) + + node.commits = append(node.commits, commit) + + return commit +} + +func (node *node) Set(key, value string) { + node.store.Set(append([]byte{0x00}, []byte(key)...), []byte(value)) +} + +type Verifier struct { + ConsensusState +} + +func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifier { + return &Verifier{ + ConsensusState{ + ChainID: chainid, + Height: uint64(header.Height), + Root: header.AppHash, + NextValidatorSet: nextvalset.ValidatorSet(), + }, + } +} + +func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidators) error { + newcs, err := v.ConsensusState.Validate( + Header{ + SignedHeader: header, + NextValidatorSet: nextvalset.ValidatorSet(), + }, + ) + if err != nil { + return err + } + v.ConsensusState = newcs.(ConsensusState) + + return nil +} + +func TestUpdate(t *testing.T) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + verifier := NewVerifier(node.last(), node.valset) + + header := node.Commit() + + err := verifier.Validate(header, node.valset) + require.NoError(t, err) +} diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/valset_test.go new file mode 100644 index 000000000000..10aa5dc0eae7 --- /dev/null +++ b/x/ibc/02-client/tendermint/valset_test.go @@ -0,0 +1,197 @@ +package tendermint + +import ( + "bytes" + "fmt" + "sort" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + tmtypes "github.com/tendermint/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// reimplementing tmtypes.MockPV to make it marshallable +type mockPV struct { + PrivKey crypto.PrivKey +} + +var _ tmtypes.PrivValidator = (*mockPV)(nil) + +func newMockPV() *mockPV { + return &mockPV{ed25519.GenPrivKey()} +} + +func (pv *mockPV) GetAddress() tmtypes.Address { + return pv.PrivKey.PubKey().Address() +} + +func (pv *mockPV) GetPubKey() crypto.PubKey { + return pv.PrivKey.PubKey() +} + +func (pv *mockPV) SignVote(chainID string, vote *tmtypes.Vote) error { + signBytes := vote.SignBytes(chainID) + sig, err := pv.PrivKey.Sign(signBytes) + if err != nil { + return err + } + vote.Signature = sig + return nil +} + +func (pv *mockPV) SignProposal(string, *tmtypes.Proposal) error { + panic("not needed") +} + +// MockValset +type MockValidator struct { + MockPV *mockPV + Power sdk.Dec +} + +func NewMockValidator(power sdk.Dec) MockValidator { + return MockValidator{ + MockPV: newMockPV(), + Power: power, + } +} + +func (val MockValidator) GetOperator() sdk.ValAddress { + return sdk.ValAddress(val.MockPV.GetAddress()) +} + +func (val MockValidator) GetConsAddr() sdk.ConsAddress { + return sdk.GetConsAddress(val.MockPV.GetPubKey()) +} + +func (val MockValidator) GetConsPubKey() crypto.PubKey { + return val.MockPV.GetPubKey() +} + +func (val MockValidator) GetPower() sdk.Dec { + return val.Power +} + +func (val MockValidator) Validator() *tmtypes.Validator { + return tmtypes.NewValidator( + val.GetConsPubKey(), + val.GetPower().RoundInt64(), + ) +} + +type MockValidators []MockValidator + +var _ sort.Interface = MockValidators{} + +func NewMockValidators(num int, power int64) MockValidators { + res := make(MockValidators, num) + for i := range res { + res[i] = NewMockValidator(sdk.NewDec(power)) + } + + // ddd + fmt.Println(333) + for _, val := range res { + fmt.Println(val) + } + + // ddd + return res +} + +func (vals MockValidators) Len() int { + return len(vals) +} + +func (vals MockValidators) Less(i, j int) bool { + return bytes.Compare([]byte(vals[i].GetConsAddr()), []byte(vals[j].GetConsAddr())) == -1 +} + +func (vals MockValidators) Swap(i, j int) { + it := vals[j] + vals[j] = vals[i] + vals[i] = it +} + +func (vals MockValidators) TotalPower() sdk.Dec { + res := sdk.ZeroDec() + for _, val := range vals { + res = res.Add(val.Power) + } + return res +} + +func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { + precommits := make([]*tmtypes.CommitSig, len(vals)) + for i, val := range vals { + precommits[i] = (&tmtypes.Vote{ + BlockID: tmtypes.BlockID{ + Hash: header.Hash(), + }, + ValidatorAddress: val.MockPV.GetAddress(), + ValidatorIndex: i, + Height: header.Height, + Type: tmtypes.PrecommitType, + }).CommitSig() + val.MockPV.SignVote("", (*tmtypes.Vote)(precommits[i])) + } + + return tmtypes.SignedHeader{ + Header: &header, + Commit: &tmtypes.Commit{ + BlockID: tmtypes.BlockID{ + Hash: header.Hash(), + }, + Precommits: precommits, + }, + } +} + +// Mutate valset +func (vals MockValidators) Mutate(majority bool) MockValidators { + var num int + if majority { + num = len(vals) * 2 / 3 + } else { + num = len(vals) * 1 / 6 + } + + res := make(MockValidators, len(vals)) + + for i := 0; i < len(vals)-num; i++ { + res[i] = vals[num:][i] + } + + for i := len(vals) - num; i < len(vals); i++ { + res[i] = NewMockValidator(vals[0].Power) + } + + // ddd + fmt.Println(333) + for _, val := range res { + fmt.Println(val) + } + + // ddd + + return res +} + +func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { + tmvals := make([]*tmtypes.Validator, len(vals)) + + for i, val := range vals { + tmvals[i] = val.Validator() + } + + // ddd + fmt.Println(333444) + for _, val := range tmvals { + fmt.Println(val) + } + + // ddd + return tmtypes.NewValidatorSet(tmvals) +} diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go index 2ae484853354..2a34855085b9 100644 --- a/x/ibc/02-client/types.go +++ b/x/ibc/02-client/types.go @@ -26,9 +26,6 @@ func Equal(client1, client2 ConsensusState) bool { type Header interface { Kind() Kind GetHeight() uint64 - // Proof() HeaderProof - State() ConsensusState // can be nil - GetRoot() commitment.Root } // XXX: Kind should be enum? From 0e52a48eeb1d90f7b6eb66c456b8c5e4f8088318 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 13 Jun 2019 19:08:13 +0200 Subject: [PATCH 055/182] add test --- x/ibc/02-client/tendermint/types.go | 6 +- x/ibc/02-client/tendermint/types_test.go | 108 +++++++++++++++++++--- x/ibc/02-client/tendermint/valset_test.go | 46 +++------ 3 files changed, 114 insertions(+), 46 deletions(-) diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 1442d91d6c99..8dd3cfca7294 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -3,7 +3,6 @@ package tendermint import ( "bytes" "errors" - "fmt" lerr "github.com/tendermint/tendermint/lite/errors" "github.com/tendermint/tendermint/types" @@ -55,13 +54,11 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, if cs.Height == uint64(header.Height-1) { nexthash = cs.NextValidatorSet.Hash() if !bytes.Equal(header.ValidatorsHash, nexthash) { - fmt.Println(111) return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) } } if !bytes.Equal(header.NextValidatorsHash, header.NextValidatorSet.Hash()) { - fmt.Println(header) return nil, lerr.ErrUnexpectedValidators(header.NextValidatorsHash, header.NextValidatorSet.Hash()) } @@ -70,7 +67,7 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, return nil, err } - err = cs.NextValidatorSet.VerifyCommit(cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) + err = cs.NextValidatorSet.VerifyFutureCommit(header.ValidatorSet, cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) if err != nil { return nil, err } @@ -87,6 +84,7 @@ var _ client.Header = Header{} type Header struct { // XXX: don't take the entire struct types.SignedHeader + ValidatorSet *types.ValidatorSet NextValidatorSet *types.ValidatorSet } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 44dc0fc9aba9..14ca7adad0ea 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -1,11 +1,13 @@ package tendermint import ( + "math/rand" "testing" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" tmtypes "github.com/tendermint/tendermint/types" @@ -14,6 +16,9 @@ import ( "github.com/cosmos/cosmos-sdk/store" stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) const chainid = "testchain" @@ -33,7 +38,8 @@ func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *c } type node struct { - valset MockValidators + prevvalset MockValidators + valset MockValidators cms sdk.CommitMultiStore store sdk.KVStore @@ -60,7 +66,7 @@ func (node *node) last() tmtypes.SignedHeader { func (node *node) Commit() tmtypes.SignedHeader { valsethash := node.valset.ValidatorSet().Hash() - nextvalset := node.valset.Mutate(false) + nextvalset := node.valset.Mutate() nextvalsethash := nextvalset.ValidatorSet().Hash() commitid := node.cms.Commit() @@ -78,15 +84,13 @@ func (node *node) Commit() tmtypes.SignedHeader { commit := node.valset.Sign(header) + node.prevvalset = node.valset + node.valset = nextvalset node.commits = append(node.commits, commit) return commit } -func (node *node) Set(key, value string) { - node.store.Set(append([]byte{0x00}, []byte(key)...), []byte(value)) -} - type Verifier struct { ConsensusState } @@ -102,10 +106,11 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifi } } -func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidators) error { +func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset MockValidators) error { newcs, err := v.ConsensusState.Validate( Header{ SignedHeader: header, + ValidatorSet: valset.ValidatorSet(), NextValidatorSet: nextvalset.ValidatorSet(), }, ) @@ -117,15 +122,96 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidato return nil } -func TestUpdate(t *testing.T) { +func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10)) node.Commit() verifier := NewVerifier(node.last(), node.valset) - header := node.Commit() + for i := 0; i < 100; i++ { + header := node.Commit() + + if i%interval == 0 { + err := verifier.Validate(header, node.prevvalset, node.valset) + if ok { + require.NoError(t, err) + } else { + require.Error(t, err) + } + } + } +} + +func TestEveryBlockUpdate(t *testing.T) { + testUpdate(t, 1, true) +} + +func TestEvenBlockUpdate(t *testing.T) { + testUpdate(t, 2, true) +} + +func TestSixthBlockUpdate(t *testing.T) { + testUpdate(t, 6, true) +} + +/* +// This should fail, since the amount of mutation is so large +// Commented out because it sometimes success +func TestTenthBlockUpdate(t *testing.T) { + testUpdate(t, 10, false) +} +*/ + +func key(str []byte) []byte { + return append([]byte{0x00}, str...) +} + +func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { + qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/ibc/key", Data: key(k), Prove: true}) + require.Equal(t, uint32(0), qres.Code, qres.Log) + proof := merkle.Proof{ + Key: []byte(k), + Proof: qres.Proof, + } + return qres.Value, proof +} + +func (node *node) Set(k, value []byte) { + node.store.Set(key(k), value) +} + +func testProof(t *testing.T) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + kvps := cmn.KVPairs{} + for h := 0; h < 20; h++ { + for i := 0; i < 100; i++ { + k := make([]byte, 32) + v := make([]byte, 32) + rand.Read(k) + rand.Read(v) + kvps = append(kvps, cmn.KVPair{Key: k, Value: v}) + node.Set(k, v) + } + header := node.Commit() + proofs := []commitment.Proof{} + for _, kvp := range kvps { + v, p := node.query(t, []byte(kvp.Key)) + require.Equal(t, kvp.Value, v) + proofs = append(proofs, p) + } + cstore, err := commitment.NewStore([]byte(header.AppHash), proofs) + require.NoError(t, err) + + for _, kvp := range kvps { + require.True(t, cstore.Prove(kvp.Key, kvp.Value)) + } + } +} - err := verifier.Validate(header, node.valset) - require.NoError(t, err) +func TestProofs(t *testing.T) { + testProof(t) } diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/valset_test.go index 10aa5dc0eae7..5649a3533273 100644 --- a/x/ibc/02-client/tendermint/valset_test.go +++ b/x/ibc/02-client/tendermint/valset_test.go @@ -2,7 +2,6 @@ package tendermint import ( "bytes" - "fmt" "sort" "github.com/tendermint/tendermint/crypto" @@ -91,13 +90,8 @@ func NewMockValidators(num int, power int64) MockValidators { res[i] = NewMockValidator(sdk.NewDec(power)) } - // ddd - fmt.Println(333) - for _, val := range res { - fmt.Println(val) - } + sort.Sort(res) - // ddd return res } @@ -124,9 +118,10 @@ func (vals MockValidators) TotalPower() sdk.Dec { } func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { + precommits := make([]*tmtypes.CommitSig, len(vals)) for i, val := range vals { - precommits[i] = (&tmtypes.Vote{ + vote := &tmtypes.Vote{ BlockID: tmtypes.BlockID{ Hash: header.Hash(), }, @@ -134,8 +129,9 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { ValidatorIndex: i, Height: header.Height, Type: tmtypes.PrecommitType, - }).CommitSig() - val.MockPV.SignVote("", (*tmtypes.Vote)(precommits[i])) + } + val.MockPV.SignVote(chainid, vote) + precommits[i] = vote.CommitSig() } return tmtypes.SignedHeader{ @@ -150,13 +146,8 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { } // Mutate valset -func (vals MockValidators) Mutate(majority bool) MockValidators { - var num int - if majority { - num = len(vals) * 2 / 3 - } else { - num = len(vals) * 1 / 6 - } +func (vals MockValidators) Mutate() MockValidators { + num := len(vals) / 20 // 5% change each block res := make(MockValidators, len(vals)) @@ -168,15 +159,15 @@ func (vals MockValidators) Mutate(majority bool) MockValidators { res[i] = NewMockValidator(vals[0].Power) } - // ddd - fmt.Println(333) - for _, val := range res { - fmt.Println(val) - } + sort.Sort(res) - // ddd + for i, val := range vals { + if val != res[i] { + return res + } + } - return res + panic("not mutated") } func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { @@ -186,12 +177,5 @@ func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { tmvals[i] = val.Validator() } - // ddd - fmt.Println(333444) - for _, val := range tmvals { - fmt.Println(val) - } - - // ddd return tmtypes.NewValidatorSet(tmvals) } From d234530b8178ea3acdf5b14170ddc679da6213f6 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 19 Jun 2019 13:07:06 +0100 Subject: [PATCH 056/182] in progres --- x/ibc/client/cli/query.go | 216 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 x/ibc/client/cli/query.go diff --git a/x/ibc/client/cli/query.go b/x/ibc/client/cli/query.go new file mode 100644 index 000000000000..ca979151c499 --- /dev/null +++ b/x/ibc/client/cli/query.go @@ -0,0 +1,216 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" + ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" +) + +func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcQueryCmd := &cobra.Command{ + Use: "ibc", + Short: "IBC query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcQueryCmd.AddCommand(client.GetCommands( + GetCmdQueryConsensusState(cdc), + GetCmdQueryHeader(cdc), + GetCmdQueryClient(cdc), + GetCmdQueryConnection(cdc), + GetCmdQueryChannel(cdc), + )...) + return ibcQueryCmd +} + +func GetCmdQueryClient(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "client", + Short: "Query stored client", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var state ibc.ConsensusState + statebz, _, err := query(ctx, keeper.Client.Object(args[0]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(statebz, &state) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryConsensusState(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "consensus-state", + Short: "Query the latest consensus state of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + state := tendermint.ConsensusState{ + ChainID: commit.ChainID, + Height: uint64(commit.Height), + Root: []byte(commit.AppHash), + NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "header", + Short: "Query the latest header of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + nextvalidators, err := node.Validators(&height) + if err != nil { + return err + } + + header := tendermint.Header{ + SignedHeader: commit.SignedHeader, + ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) + + return nil + }, + } +} + +func GetCmdQueryConnection(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "connection", + Short: "Query an existing connection", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var conn ibc.Connection + connbz, _, err := query(ctx, keeper.Connection.Object(args[0]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(connbz, &conn) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) + + return nil + }, + } +} + +func GetCmdQueryChannel(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "channel", + Short: "Query an existing channel", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var conn ibc.Channel + connbz, _, err := query(ctx, keeper.Channel.Object(args[0], args[1]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(connbz, &conn) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) + + return nil + }, + } +} + +func GetCmdQuerySendSequence(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "send-sequence", + Short: "Query the send sequence of a channel", + Args: cobra.ExactArgs(), + RunE: func(cmd *cobra.Command, args []string) error { + + }, + } +} + +func GetCmdQueryReceiveSequence(cdc *codec.Codec) *cobra.Command { + +} + +func GetCmdQueryPacket(cdc *codec.Codec) *cobra.Command { +} From 8caf0ba2caef5a8edf80427977484eeb4574233a Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 12:20:15 +0200 Subject: [PATCH 057/182] fin rebase --- x/ibc/02-client/tendermint/types.go | 2 +- x/ibc/02-client/tendermint/types_test.go | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 8dd3cfca7294..26a4c35370e6 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -37,7 +37,7 @@ func (cs ConsensusState) update(header Header) ConsensusState { return ConsensusState{ ChainID: cs.ChainID, Height: uint64(header.Height), - Root: header.AppHash, + Root: cs.GetRoot().Update(header.AppHash), NextValidatorSet: header.NextValidatorSet, } } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 14ca7adad0ea..8bde76d10302 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -24,7 +24,7 @@ import ( const chainid = "testchain" func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { - key := sdk.NewKVStoreKey("ibc") + key := sdk.NewKVStoreKey("test") db := dbm.NewMemDB() cms := store.NewCommitMultiStore(db) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) @@ -91,6 +91,13 @@ func (node *node) Commit() tmtypes.SignedHeader { return commit } +func keyPrefix() [][]byte { + return [][]byte{ + []byte("test"), + []byte{0x00}, + } +} + type Verifier struct { ConsensusState } @@ -100,7 +107,7 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifi ConsensusState{ ChainID: chainid, Height: uint64(header.Height), - Root: header.AppHash, + Root: merkle.NewRoot(header.AppHash, keyPrefix()), NextValidatorSet: nextvalset.ValidatorSet(), }, } @@ -168,7 +175,7 @@ func key(str []byte) []byte { } func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { - qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/ibc/key", Data: key(k), Prove: true}) + qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/test/key", Data: key(k), Prove: true}) require.Equal(t, uint32(0), qres.Code, qres.Log) proof := merkle.Proof{ Key: []byte(k), @@ -203,7 +210,7 @@ func testProof(t *testing.T) { require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore([]byte(header.AppHash), proofs) + cstore, err := commitment.NewStore(merkle.NewRoot([]byte(header.AppHash), keyPrefix()), proofs) require.NoError(t, err) for _, kvp := range kvps { From 9799769039de7ff1d416932f50563b03c2f6ca5f Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 16:07:00 +0200 Subject: [PATCH 058/182] in progress --- x/ibc/02-client/cli.go | 18 ++++++++++ x/ibc/02-client/manager.go | 34 ++++++++++--------- x/ibc/02-client/tendermint/types_test.go | 42 ++++++++++-------------- 3 files changed, 54 insertions(+), 40 deletions(-) create mode 100644 x/ibc/02-client/cli.go diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go new file mode 100644 index 000000000000..5c245ba0378e --- /dev/null +++ b/x/ibc/02-client/cli.go @@ -0,0 +1,18 @@ +package client + +import () + +// CLIObject stores the key for each object fields +type CLIObject struct { + ID string + ConsensusState []byte + Frozen []byte +} + +func (object Object) CLI() CLIObject { + return CLIObject{ + ID: object.id, + ConsensusState: object.consensusState.Key(), + Frozen: object.frozen.Key(), + } +} diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 196d62e62fdc..a99a4bcc785c 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -55,9 +55,9 @@ func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { */ func (man Manager) object(id string) Object { return Object{ - id: id, - client: man.protocol.Value([]byte(id)), - freeze: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + id: id, + consensusState: man.protocol.Value([]byte(id)), + frozen: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), } } @@ -67,7 +67,7 @@ func (man Manager) Create(ctx sdk.Context, cs ConsensusState) (Object, error) { if obj.exists(ctx) { return Object{}, errors.New("Create client on already existing id") } - obj.client.Set(ctx, cs) + obj.consensusState.Set(ctx, cs) return obj, nil } @@ -91,9 +91,9 @@ func (man CounterpartyManager) Query(id string) CounterObject { } type Object struct { - id string - client state.Value // ConsensusState - freeze state.Boolean + id string + consensusState state.Value // ConsensusState + frozen state.Boolean } type CounterObject struct { @@ -101,34 +101,38 @@ type CounterObject struct { client commitment.Value } -func (obj Object) exists(ctx sdk.Context) bool { - return obj.client.Exists(ctx) -} - func (obj Object) ID() string { return obj.id } -func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { - obj.client.Get(ctx, &res) +func (obj Object) ConsensusState(ctx sdk.Context) (res ConsensusState) { + obj.consensusState.Get(ctx, &res) return } +func (obj Object) Frozen(ctx sdk.Context) bool { + return obj.frozen.Get(ctx) +} + func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } +func (obj Object) exists(ctx sdk.Context) bool { + return obj.consensusState.Exists(ctx) +} + func (obj Object) Update(ctx sdk.Context, header Header) error { if !obj.exists(ctx) { panic("should not update nonexisting client") } - if obj.freeze.Get(ctx) { + if obj.Frozen(ctx) { return errors.New("client is frozen") } var stored ConsensusState - obj.client.GetIfExists(ctx, &stored) + obj.client.Get(ctx, &stored) updated, err := stored.Validate(header) if err != nil { return err diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 8bde76d10302..3cb99f52b549 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -91,23 +91,16 @@ func (node *node) Commit() tmtypes.SignedHeader { return commit } -func keyPrefix() [][]byte { - return [][]byte{ - []byte("test"), - []byte{0x00}, - } -} - type Verifier struct { ConsensusState } -func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifier { +func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root merkle.Root) *Verifier { return &Verifier{ ConsensusState{ ChainID: chainid, Height: uint64(header.Height), - Root: merkle.NewRoot(header.AppHash, keyPrefix()), + Root: root.Update(header.AppHash), NextValidatorSet: nextvalset.ValidatorSet(), }, } @@ -129,12 +122,18 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock return nil } +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10)) node.Commit() - verifier := NewVerifier(node.last(), node.valset) + root := newRoot() + + verifier := NewVerifier(node.last(), node.valset, root) for i := 0; i < 100; i++ { header := node.Commit() @@ -170,22 +169,14 @@ func TestTenthBlockUpdate(t *testing.T) { } */ -func key(str []byte) []byte { - return append([]byte{0x00}, str...) -} - -func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { - qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/test/key", Data: key(k), Prove: true}) - require.Equal(t, uint32(0), qres.Code, qres.Log) - proof := merkle.Proof{ - Key: []byte(k), - Proof: qres.Proof, - } - return qres.Value, proof +func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { + code, value, proof := root.Query(node.cms, k) + require.Equal(t, uint32(0), code) + return value, proof } func (node *node) Set(k, value []byte) { - node.store.Set(key(k), value) + node.store.Set(newRoot().Key(k), value) } func testProof(t *testing.T) { @@ -205,12 +196,13 @@ func testProof(t *testing.T) { } header := node.Commit() proofs := []commitment.Proof{} + root := newRoot().Update(header.AppHash) for _, kvp := range kvps { - v, p := node.query(t, []byte(kvp.Key)) + v, p := node.query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore(merkle.NewRoot([]byte(header.AppHash), keyPrefix()), proofs) + cstore, err := commitment.NewStore(root, proofs) require.NoError(t, err) for _, kvp := range kvps { From e67b97b30d66157c380a9106789e744db425d3ca Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 16:15:17 +0200 Subject: [PATCH 059/182] fin rebase --- x/ibc/02-client/manager.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index a99a4bcc785c..e94d14702b72 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -81,8 +81,8 @@ func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { func (man CounterpartyManager) object(id string) CounterObject { return CounterObject{ - id: id, - client: man.protocol.Value([]byte(id)), + id: id, + consensusState: man.protocol.Value([]byte(id)), } } @@ -97,8 +97,8 @@ type Object struct { } type CounterObject struct { - id string - client commitment.Value + id string + consensusState commitment.Value } func (obj Object) ID() string { @@ -115,7 +115,7 @@ func (obj Object) Frozen(ctx sdk.Context) bool { } func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { - return obj.client.Is(ctx, client) + return obj.consensusState.Is(ctx, client) } func (obj Object) exists(ctx sdk.Context) bool { @@ -132,13 +132,13 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { } var stored ConsensusState - obj.client.Get(ctx, &stored) + obj.consensusState.Get(ctx, &stored) updated, err := stored.Validate(header) if err != nil { return err } - obj.client.Set(ctx, updated) + obj.consensusState.Set(ctx, updated) return nil } @@ -148,11 +148,11 @@ func (obj Object) Freeze(ctx sdk.Context) error { panic("should not freeze nonexisting client") } - if obj.freeze.Get(ctx) { + if obj.Frozen(ctx) { return errors.New("client is already frozen") } - obj.freeze.Set(ctx, true) + obj.frozen.Set(ctx, true) return nil } @@ -162,12 +162,12 @@ func (obj Object) Delete(ctx sdk.Context) error { panic("should not delete nonexisting client") } - if !obj.freeze.Get(ctx) { + if !obj.Frozen(ctx) { return errors.New("client is not frozen") } - obj.client.Delete(ctx) - obj.freeze.Delete(ctx) + obj.consensusState.Delete(ctx) + obj.frozen.Delete(ctx) return nil } From fb375d270e4182a66f897e0c2f8e136b0e51c215 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 17:10:21 +0200 Subject: [PATCH 060/182] add CLIObject in progress --- client/context/query.go | 38 ++++++++++++++++++++++++-------------- x/ibc/02-client/cli.go | 24 ++++++++++++++++-------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 87f96aece166..1e52442c6c61 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,21 +31,31 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) ([]byte, int64, error) { - return ctx.query(path, nil) +func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { + val, _, height, err = ctx.query(path, nil) + return } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { - return ctx.query(path, data) +func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { + val, _, height, err = ctx.query(path, data) + return } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { + val, _, height, err = ctx.queryStore(key, storeName, "key") + return +} + +// QueryProof performs a query to a Tendermint node with the provided key and +// store name. It returns the result, the proof, and height of the query +// upon success or an error if the query fails. +func (ctx CLIContext) QueryProof(key cmn.HexBytes, storeName string) (val []byte, proof *merkle.Proof, height int64, err error) { return ctx.queryStore(key, storeName, "key") } @@ -53,7 +63,7 @@ func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, in // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, height int64, err error) { - resRaw, height, err := ctx.queryStore(subspace, storeName, "subspace") + resRaw, _, height, err := ctx.queryStore(subspace, storeName, "subspace") if err != nil { return res, height, err } @@ -75,10 +85,10 @@ func (ctx CLIContext) GetFromName() string { // query performs a query to a Tendermint node with the provided store name // and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height int64, err error) { +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *merkle.Proof, height int64, err error) { node, err := ctx.GetNode() if err != nil { - return res, height, err + return res, proof, height, err } opts := rpcclient.ABCIQueryOptions{ @@ -88,25 +98,25 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height i result, err := node.ABCIQueryWithOptions(path, key, opts) if err != nil { - return res, height, err + return res, proof, height, err } resp := result.Response if !resp.IsOK() { - return res, height, errors.New(resp.Log) + return res, proof, height, errors.New(resp.Log) } // data from trusted node or subspace query doesn't need verification if ctx.TrustNode || !isQueryStoreWithProof(path) { - return resp.Value, resp.Height, nil + return resp.Value, resp.Proof, resp.Height, nil } err = ctx.verifyProof(path, resp) if err != nil { - return res, height, err + return res, proof, height, err } - return resp.Value, resp.Height, nil + return resp.Value, resp.Proof, resp.Height, nil } // Verify verifies the consensus proof at given height. @@ -165,7 +175,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) { +func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, *merkle.Proof, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 5c245ba0378e..8767c3032724 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -1,18 +1,26 @@ package client -import () +import ( + "github.com/cosmos/cosmos-sdk/client/context" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) // CLIObject stores the key for each object fields type CLIObject struct { - ID string - ConsensusState []byte - Frozen []byte + ID string + ConsensusStateKey []byte + FrozenKey []byte } -func (object Object) CLI() CLIObject { +func (obj Object) CLI() CLIObject { return CLIObject{ - ID: object.id, - ConsensusState: object.consensusState.Key(), - Frozen: object.frozen.Key(), + ID: obj.id, + ConsensusStateKey: obj.consensusState.Key(), + FrozenKey: obj.frozen.Key(), } } + +func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle..Proof) { + val, proof, _, err := ctx.QueryProof(obj.ConsensusStateKey) +} From 092cd746161d8d9c877081cf80b93769666a2c5f Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:19:42 +0200 Subject: [PATCH 061/182] cli in progress --- client/context/query.go | 69 +++++++++++++++++++++++------------------ store/state/types.go | 5 +++ x/ibc/02-client/cli.go | 34 ++++++++++++++++++-- 3 files changed, 76 insertions(+), 32 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 1e52442c6c61..4738808ba4fe 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,39 +31,35 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { - val, _, height, err = ctx.query(path, nil) - return +func (ctx CLIContext) Query(path string) ([]byte, int64, error) { + return ctx.query(path, nil) } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { - val, _, height, err = ctx.query(path, data) - return +func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { + return ctx.query(path, data) } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { - val, _, height, err = ctx.queryStore(key, storeName, "key") - return +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { + return ctx.queryStore(key, storeName, "key") } -// QueryProof performs a query to a Tendermint node with the provided key and -// store name. It returns the result, the proof, and height of the query -// upon success or an error if the query fails. -func (ctx CLIContext) QueryProof(key cmn.HexBytes, storeName string) (val []byte, proof *merkle.Proof, height int64, err error) { - return ctx.queryStore(key, storeName, "key") +// QueryABCI performs a query to a Tendermint node with the provide RequestQuery. +// It returns the ResultQuery obtained from the query. +func (ctx CLIContext) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { + return ctx.queryABCI(req) } // QuerySubspace performs a query to a Tendermint node with the provided // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, height int64, err error) { - resRaw, _, height, err := ctx.queryStore(subspace, storeName, "subspace") + resRaw, height, err := ctx.queryStore(subspace, storeName, "subspace") if err != nil { return res, height, err } @@ -82,13 +78,10 @@ func (ctx CLIContext) GetFromName() string { return ctx.FromName } -// query performs a query to a Tendermint node with the provided store name -// and path. It returns the result and height of the query upon success -// or an error if the query fails. -func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *merkle.Proof, height int64, err error) { +func (ctx CLIContext) queryABCI(req abci.RequestQuery) (resp abci.ResponseQuery, err error) { node, err := ctx.GetNode() if err != nil { - return res, proof, height, err + return } opts := rpcclient.ABCIQueryOptions{ @@ -96,27 +89,43 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *m Prove: !ctx.TrustNode, } - result, err := node.ABCIQueryWithOptions(path, key, opts) + result, err := node.ABCIQueryWithOptions(req.Path, req.Data, opts) if err != nil { - return res, proof, height, err + return } - resp := result.Response + resp = result.Response if !resp.IsOK() { - return res, proof, height, errors.New(resp.Log) + err = errors.New(resp.Log) + return } // data from trusted node or subspace query doesn't need verification - if ctx.TrustNode || !isQueryStoreWithProof(path) { - return resp.Value, resp.Proof, resp.Height, nil + if ctx.TrustNode || !isQueryStoreWithProof(req.Path) { + return resp, nil } - err = ctx.verifyProof(path, resp) + err = ctx.verifyProof(req.Path, resp) + if err != nil { + return + } + + return +} + +// query performs a query to a Tendermint node with the provided store name +// and path. It returns the result and height of the query upon success +// or an error if the query fails. +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height int64, err error) { + resp, err := ctx.queryABCI(abci.RequestQuery{ + Path: path, + Data: key, + }) if err != nil { - return res, proof, height, err + return } - return resp.Value, resp.Proof, resp.Height, nil + return resp.Value, resp.Height, nil } // Verify verifies the consensus proof at given height. @@ -175,7 +184,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, *merkle.Proof, int64, error) { +func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/store/state/types.go b/store/state/types.go index a8d34d582a82..f5dbb4dc8648 100644 --- a/store/state/types.go +++ b/store/state/types.go @@ -1,8 +1,13 @@ package state import ( + "github.com/tendermint/tendermint/crypto/merkle" + + "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" ) type KVStore = sdk.KVStore type Context = sdk.Context +type CLIContext = context.CLIContext +type Proof = merkle.Proof diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 8767c3032724..f51b882e7725 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -2,6 +2,7 @@ package client import ( "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -11,6 +12,7 @@ type CLIObject struct { ID string ConsensusStateKey []byte FrozenKey []byte + Cdc *codec.Codec } func (obj Object) CLI() CLIObject { @@ -21,6 +23,34 @@ func (obj Object) CLI() CLIObject { } } -func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle..Proof) { - val, proof, _, err := ctx.QueryProof(obj.ConsensusStateKey) +func query(ctx context.CLIContext, root merkle.Root, key []byte) ([]byte, merkle.Proof, error) { + resp, err := ctx.QueryABCI(root.RequestQuery(key)) + if err != nil { + return nil, merkle.Proof{}, err + } + proof := merkle.Proof{ + Key: key, + Proof: resp.Proof, + } + return resp.Value, proof, nil + +} + +func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { + val, proof, err := query(ctx, root, obj.ConsensusStateKey) + obj.Cdc.MustUnmarshalBinaryBare(val, &res) + return +} + +func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { + val, tmproof, _, err := ctx.QueryProof(obj.FrozenKey, "ibc") // TODO + if err != nil { + return + } + proof = merkle.Proof{ + Key: obj.FrozenKey, + Proof: tmproof, + } + obj.Cdc.MustUnmarshalBinaryBare(val, &res) + return } From 9ddab3369f4c4bb365922d5abc9816a976c15b5b Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:40:30 +0200 Subject: [PATCH 062/182] add CLIObject --- x/ibc/02-client/cli.go | 31 ++++++++++------------- x/ibc/02-client/tendermint/types_test.go | 2 +- x/ibc/23-commitment/merkle/merkle_test.go | 12 ++++----- x/ibc/23-commitment/merkle/utils.go | 27 ++++++++++++-------- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index f51b882e7725..2592e697573c 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -12,45 +12,42 @@ type CLIObject struct { ID string ConsensusStateKey []byte FrozenKey []byte - Cdc *codec.Codec + + Root merkle.Root + Cdc *codec.Codec } -func (obj Object) CLI() CLIObject { +func (obj Object) CLI(root merkle.Root) CLIObject { return CLIObject{ ID: obj.id, ConsensusStateKey: obj.consensusState.Key(), FrozenKey: obj.frozen.Key(), + + Root: root, + Cdc: obj.consensusState.Cdc(), } } -func query(ctx context.CLIContext, root merkle.Root, key []byte) ([]byte, merkle.Proof, error) { - resp, err := ctx.QueryABCI(root.RequestQuery(key)) +func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { + resp, err := ctx.QueryABCI(obj.Root.RequestQuery(key)) if err != nil { - return nil, merkle.Proof{}, err + return merkle.Proof{}, err } proof := merkle.Proof{ Key: key, Proof: resp.Proof, } - return resp.Value, proof, nil + err = obj.Cdc.UnmarshalBinaryBare(resp.Value, ptr) + return proof, err } func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { - val, proof, err := query(ctx, root, obj.ConsensusStateKey) - obj.Cdc.MustUnmarshalBinaryBare(val, &res) + proof, err = obj.query(ctx, obj.ConsensusStateKey, &res) return } func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { - val, tmproof, _, err := ctx.QueryProof(obj.FrozenKey, "ibc") // TODO - if err != nil { - return - } - proof = merkle.Proof{ - Key: obj.FrozenKey, - Proof: tmproof, - } - obj.Cdc.MustUnmarshalBinaryBare(val, &res) + proof, err = obj.query(ctx, obj.FrozenKey, &res) return } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 3cb99f52b549..2b89f9be11c8 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -170,7 +170,7 @@ func TestTenthBlockUpdate(t *testing.T) { */ func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.Query(node.cms, k) + code, value, proof := root.QueryMultiStore(node.cms, k) require.Equal(t, uint32(0), code) return value, proof } diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index f93f64943609..dc7da05dfbc2 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -47,13 +47,13 @@ func TestStore(t *testing.T) { root := commit(cms) - c1, v1, p1 := path.Query(cms, []byte("hello")) + c1, v1, p1 := path.QueryMultiStore(cms, []byte("hello")) require.Equal(t, uint32(0), c1) require.Equal(t, []byte("world"), v1) - c2, v2, p2 := path.Query(cms, []byte("merkle")) + c2, v2, p2 := path.QueryMultiStore(cms, []byte("merkle")) require.Equal(t, uint32(0), c2) require.Equal(t, []byte("tree"), v2) - c3, v3, p3 := path.Query(cms, []byte("block")) + c3, v3, p3 := path.QueryMultiStore(cms, []byte("block")) require.Equal(t, uint32(0), c3) require.Equal(t, []byte("chain"), v3) @@ -70,13 +70,13 @@ func TestStore(t *testing.T) { root = commit(cms) - c1, v1, p1 = path.Query(cms, []byte("12345")) + c1, v1, p1 = path.QueryMultiStore(cms, []byte("12345")) require.Equal(t, uint32(0), c1) require.Equal(t, []byte("67890"), v1) - c2, v2, p2 = path.Query(cms, []byte("qwerty")) + c2, v2, p2 = path.QueryMultiStore(cms, []byte("qwerty")) require.Equal(t, uint32(0), c2) require.Equal(t, []byte("zxcv"), v2) - c3, v3, p3 = path.Query(cms, []byte("hello")) + c3, v3, p3 = path.QueryMultiStore(cms, []byte("hello")) require.Equal(t, uint32(0), c3) require.Equal(t, []byte("dlrow"), v3) diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index d2eabdaed99d..f122b0cd5383 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -7,22 +7,29 @@ import ( ) func (path Path) RequestQuery(key []byte) abci.RequestQuery { - pathstr := "" - for _, inter := range path.KeyPath { - pathstr = pathstr + "/" + string(inter) - } - pathstr = pathstr + "/key" - - data := append(path.KeyPrefix, key...) + req := path.RequestQueryMultiStore(key) + req.Path = "/store" + req.Path + return req +} - return abci.RequestQuery{Path: pathstr, Data: data, Prove: true} +func (path Path) RequestQueryMultiStore(key []byte) abci.RequestQuery { + return abci.RequestQuery{Path: path.Path() + "/key", Data: path.Key(key), Prove: true} } -func (path Path) Query(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { - qres := cms.(types.Queryable).Query(path.RequestQuery(key)) +func (path Path) QueryMultiStore(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { + qres := cms.(types.Queryable).Query(path.RequestQueryMultiStore(key)) return qres.Code, qres.Value, Proof{Key: key, Proof: qres.Proof} } func (path Path) Key(key []byte) []byte { return append(path.KeyPrefix, key...) // XXX: cloneAppend } + +func (path Path) Path() string { + pathstr := "" + for _, inter := range path.KeyPath { + pathstr = pathstr + "/" + string(inter) + } + + return pathstr +} From d1fad94453beb83ae2263be647a3c105f18377cc Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:58:28 +0200 Subject: [PATCH 063/182] separate testing from tendermint --- .../tendermint/tests/tendermint_test.go | 58 ++++++++ .../{types_test.go => tests/types.go} | 125 ++++++------------ .../{valset_test.go => tests/valset.go} | 0 3 files changed, 98 insertions(+), 85 deletions(-) create mode 100644 x/ibc/02-client/tendermint/tests/tendermint_test.go rename x/ibc/02-client/tendermint/{types_test.go => tests/types.go} (57%) rename x/ibc/02-client/tendermint/{valset_test.go => tests/valset.go} (100%) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go new file mode 100644 index 000000000000..29581e718e4c --- /dev/null +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -0,0 +1,58 @@ +package tendermint + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + +func testUpdate(t *testing.T, interval int, ok bool) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + verifier := node.LastStateVerifier(newRoot()) + + for i := 0; i < 100; i++ { + header := node.Commit() + + if i%interval == 0 { + err := verifier.Validate(header, node.PrevValset, node.Valset) + if ok { + require.NoError(t, err) + } else { + require.Error(t, err) + } + } + } +} + +func TestEveryBlockUpdate(t *testing.T) { + testUpdate(t, 1, true) +} + +func TestEvenBlockUpdate(t *testing.T) { + testUpdate(t, 2, true) +} + +func TestSixthBlockUpdate(t *testing.T) { + testUpdate(t, 6, true) +} + +/* +// This should fail, since the amount of mutation is so large +// Commented out because it sometimes success +func TestTenthBlockUpdate(t *testing.T) { + testUpdate(t, 10, false) +} +*/ + +func TestProofs(t *testing.T) { + testProof(t) +} diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/tests/types.go similarity index 57% rename from x/ibc/02-client/tendermint/types_test.go rename to x/ibc/02-client/tendermint/tests/types.go index 2b89f9be11c8..f32cae8efc9d 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -17,6 +17,8 @@ import ( stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -37,44 +39,44 @@ func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *c return key, ctx, cms, cdc } -type node struct { - prevvalset MockValidators - valset MockValidators +type Node struct { + PrevValset MockValidators + Valset MockValidators - cms sdk.CommitMultiStore - store sdk.KVStore + Cms sdk.CommitMultiStore + Store sdk.KVStore - commits []tmtypes.SignedHeader + Commits []tmtypes.SignedHeader } -func NewNode(valset MockValidators) *node { +func NewNode(valset MockValidators) *Node { key, ctx, cms, _ := defaultComponents() - return &node{ - valset: valset, - cms: cms, - store: ctx.KVStore(key), - commits: nil, + return &Node{ + Valset: valset, + Cms: cms, + Store: ctx.KVStore(key), + Commits: nil, } } -func (node *node) last() tmtypes.SignedHeader { - if len(node.commits) == 0 { +func (node *Node) Last() tmtypes.SignedHeader { + if len(node.Commits) == 0 { return tmtypes.SignedHeader{} } - return node.commits[len(node.commits)-1] + return node.Commits[len(node.Commits)-1] } -func (node *node) Commit() tmtypes.SignedHeader { - valsethash := node.valset.ValidatorSet().Hash() - nextvalset := node.valset.Mutate() +func (node *Node) Commit() tmtypes.SignedHeader { + valsethash := node.Valset.ValidatorSet().Hash() + nextvalset := node.Valset.Mutate() nextvalsethash := nextvalset.ValidatorSet().Hash() - commitid := node.cms.Commit() + commitid := node.Cms.Commit() header := tmtypes.Header{ ChainID: chainid, - Height: int64(len(node.commits) + 1), + Height: int64(len(node.Commits) + 1), LastBlockID: tmtypes.BlockID{ - Hash: node.last().Header.Hash(), + Hash: node.Last().Header.Hash(), }, ValidatorsHash: valsethash, @@ -82,22 +84,26 @@ func (node *node) Commit() tmtypes.SignedHeader { AppHash: commitid.Hash, } - commit := node.valset.Sign(header) + commit := node.Valset.Sign(header) - node.prevvalset = node.valset - node.valset = nextvalset - node.commits = append(node.commits, commit) + node.PrevValset = node.Valset + node.Valset = nextvalset + node.Commits = append(node.Commits, commit) return commit } +func (node *Node) LastStateVerifier(root merkle.Root) *Verifier { + return NewVerifier(node.Last(), node.Valset, root) +} + type Verifier struct { - ConsensusState + client.ConsensusState } func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root merkle.Root) *Verifier { return &Verifier{ - ConsensusState{ + tendermint.ConsensusState{ ChainID: chainid, Height: uint64(header.Height), Root: root.Update(header.AppHash), @@ -108,7 +114,7 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root me func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset MockValidators) error { newcs, err := v.ConsensusState.Validate( - Header{ + tendermint.Header{ SignedHeader: header, ValidatorSet: valset.ValidatorSet(), NextValidatorSet: nextvalset.ValidatorSet(), @@ -117,66 +123,19 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock if err != nil { return err } - v.ConsensusState = newcs.(ConsensusState) + v.ConsensusState = newcs.(tendermint.ConsensusState) return nil } -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - -func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10)) - - node.Commit() - - root := newRoot() - - verifier := NewVerifier(node.last(), node.valset, root) - - for i := 0; i < 100; i++ { - header := node.Commit() - - if i%interval == 0 { - err := verifier.Validate(header, node.prevvalset, node.valset) - if ok { - require.NoError(t, err) - } else { - require.Error(t, err) - } - } - } -} - -func TestEveryBlockUpdate(t *testing.T) { - testUpdate(t, 1, true) -} - -func TestEvenBlockUpdate(t *testing.T) { - testUpdate(t, 2, true) -} - -func TestSixthBlockUpdate(t *testing.T) { - testUpdate(t, 6, true) -} - -/* -// This should fail, since the amount of mutation is so large -// Commented out because it sometimes success -func TestTenthBlockUpdate(t *testing.T) { - testUpdate(t, 10, false) -} -*/ - -func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.QueryMultiStore(node.cms, k) +func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { + code, value, proof := root.QueryMultiStore(node.Cms, k) require.Equal(t, uint32(0), code) return value, proof } -func (node *node) Set(k, value []byte) { - node.store.Set(newRoot().Key(k), value) +func (node *Node) Set(k, value []byte) { + node.Store.Set(newRoot().Key(k), value) } func testProof(t *testing.T) { @@ -198,7 +157,7 @@ func testProof(t *testing.T) { proofs := []commitment.Proof{} root := newRoot().Update(header.AppHash) for _, kvp := range kvps { - v, p := node.query(t, root.(merkle.Root), []byte(kvp.Key)) + v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } @@ -210,7 +169,3 @@ func testProof(t *testing.T) { } } } - -func TestProofs(t *testing.T) { - testProof(t) -} diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/tests/valset.go similarity index 100% rename from x/ibc/02-client/tendermint/valset_test.go rename to x/ibc/02-client/tendermint/tests/valset.go From 5bc0068d14dffc08fa6b409a94017e383ee073e3 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 16:10:21 +0200 Subject: [PATCH 064/182] add key to node --- x/ibc/02-client/tendermint/tests/types.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index f32cae8efc9d..cc6d73592504 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -44,9 +44,12 @@ type Node struct { Valset MockValidators Cms sdk.CommitMultiStore + Key sdk.StoreKey Store sdk.KVStore Commits []tmtypes.SignedHeader + + Root merkle.Root } func NewNode(valset MockValidators) *Node { @@ -54,6 +57,7 @@ func NewNode(valset MockValidators) *Node { return &Node{ Valset: valset, Cms: cms, + Key: key, Store: ctx.KVStore(key), Commits: nil, } From 10f8e618a86d28901eb4cd11224631be9bae898c Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 18:58:29 +0200 Subject: [PATCH 065/182] add root and storekey to tests/node, add codec --- x/ibc/02-client/codec.go | 10 ++++++++++ x/ibc/02-client/tendermint/codec.go | 11 +++++++++++ x/ibc/02-client/tendermint/tests/types.go | 8 ++++++-- x/ibc/02-client/tendermint/tests/valset.go | 1 + 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 x/ibc/02-client/codec.go create mode 100644 x/ibc/02-client/tendermint/codec.go diff --git a/x/ibc/02-client/codec.go b/x/ibc/02-client/codec.go new file mode 100644 index 000000000000..fa194562e4f1 --- /dev/null +++ b/x/ibc/02-client/codec.go @@ -0,0 +1,10 @@ +package client + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterInterface((*ConsensusState)(nil), nil) + cdc.RegisterInterface((*Header)(nil), nil) +} diff --git a/x/ibc/02-client/tendermint/codec.go b/x/ibc/02-client/tendermint/codec.go new file mode 100644 index 000000000000..d8308a3e7ec8 --- /dev/null +++ b/x/ibc/02-client/tendermint/codec.go @@ -0,0 +1,11 @@ +package tendermint + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterConcrete(ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil) + cdc.RegisterConcrete(Header{}, "ibc/client/tendermint/Header", nil) + +} diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index cc6d73592504..88a27fd69f51 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -101,6 +101,10 @@ func (node *Node) LastStateVerifier(root merkle.Root) *Verifier { return NewVerifier(node.Last(), node.Valset, root) } +func (node *Node) Context() sdk.Context { + return sdk.NewContext(node.Cms, abci.Header{}, false, log.NewNopLogger()) +} + type Verifier struct { client.ConsensusState } @@ -139,7 +143,7 @@ func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commi } func (node *Node) Set(k, value []byte) { - node.Store.Set(newRoot().Key(k), value) + node.Store.Set(node.Root.Key(k), value) } func testProof(t *testing.T) { @@ -159,7 +163,7 @@ func testProof(t *testing.T) { } header := node.Commit() proofs := []commitment.Proof{} - root := newRoot().Update(header.AppHash) + root := node.Root.Update(header.AppHash) for _, kvp := range kvps { v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 5649a3533273..0d97a5427c9b 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -84,6 +84,7 @@ type MockValidators []MockValidator var _ sort.Interface = MockValidators{} +// TODO: differenciate power between the vals func NewMockValidators(num int, power int64) MockValidators { res := make(MockValidators, num) for i := range res { From eda101ad754bf0dd9e519227759f869d5d4c7c0a Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 12:22:46 +0200 Subject: [PATCH 066/182] rm cli/query.go --- x/ibc/client/cli/query.go | 216 -------------------------------------- 1 file changed, 216 deletions(-) delete mode 100644 x/ibc/client/cli/query.go diff --git a/x/ibc/client/cli/query.go b/x/ibc/client/cli/query.go deleted file mode 100644 index ca979151c499..000000000000 --- a/x/ibc/client/cli/query.go +++ /dev/null @@ -1,216 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/spf13/cobra" - - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" -) - -func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { - ibcQueryCmd := &cobra.Command{ - Use: "ibc", - Short: "IBC query subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - } - - ibcQueryCmd.AddCommand(client.GetCommands( - GetCmdQueryConsensusState(cdc), - GetCmdQueryHeader(cdc), - GetCmdQueryClient(cdc), - GetCmdQueryConnection(cdc), - GetCmdQueryChannel(cdc), - )...) - return ibcQueryCmd -} - -func GetCmdQueryClient(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "client", - Short: "Query stored client", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var state ibc.ConsensusState - statebz, _, err := query(ctx, keeper.Client.Object(args[0]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(statebz, &state) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) - - return nil - }, - } -} - -func GetCmdQueryConsensusState(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "consensus-state", - Short: "Query the latest consensus state of the running chain", - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - node, err := ctx.GetNode() - if err != nil { - return err - } - - info, err := node.ABCIInfo() - if err != nil { - return err - } - - height := info.Response.LastBlockHeight - prevheight := height - 1 - - commit, err := node.Commit(&height) - if err != nil { - return err - } - - validators, err := node.Validators(&prevheight) - if err != nil { - return err - } - - state := tendermint.ConsensusState{ - ChainID: commit.ChainID, - Height: uint64(commit.Height), - Root: []byte(commit.AppHash), - NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) - - return nil - }, - } -} - -func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "header", - Short: "Query the latest header of the running chain", - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - node, err := ctx.GetNode() - if err != nil { - return err - } - - info, err := node.ABCIInfo() - if err != nil { - return err - } - - height := info.Response.LastBlockHeight - prevheight := height - 1 - - commit, err := node.Commit(&height) - if err != nil { - return err - } - - validators, err := node.Validators(&prevheight) - if err != nil { - return err - } - - nextvalidators, err := node.Validators(&height) - if err != nil { - return err - } - - header := tendermint.Header{ - SignedHeader: commit.SignedHeader, - ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) - - return nil - }, - } -} - -func GetCmdQueryConnection(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "connection", - Short: "Query an existing connection", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var conn ibc.Connection - connbz, _, err := query(ctx, keeper.Connection.Object(args[0]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(connbz, &conn) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) - - return nil - }, - } -} - -func GetCmdQueryChannel(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "channel", - Short: "Query an existing channel", - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var conn ibc.Channel - connbz, _, err := query(ctx, keeper.Channel.Object(args[0], args[1]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(connbz, &conn) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) - - return nil - }, - } -} - -func GetCmdQuerySendSequence(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "send-sequence", - Short: "Query the send sequence of a channel", - Args: cobra.ExactArgs(), - RunE: func(cmd *cobra.Command, args []string) error { - - }, - } -} - -func GetCmdQueryReceiveSequence(cdc *codec.Codec) *cobra.Command { - -} - -func GetCmdQueryPacket(cdc *codec.Codec) *cobra.Command { -} From 5c254fbabdcadd7334b7eb873a93c5095b2916f3 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 18:21:20 +0200 Subject: [PATCH 067/182] fix test --- x/ibc/02-client/tendermint/tests/tendermint_test.go | 2 +- x/ibc/02-client/tendermint/tests/types.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index 29581e718e4c..caf866337c47 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -13,7 +13,7 @@ func newRoot() merkle.Root { } func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10)) + node := NewNode(NewMockValidators(100, 10), newRoot()) node.Commit() diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 88a27fd69f51..d0b7b488db39 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -52,7 +52,7 @@ type Node struct { Root merkle.Root } -func NewNode(valset MockValidators) *Node { +func NewNode(valset MockValidators, root merkle.Root) *Node { key, ctx, cms, _ := defaultComponents() return &Node{ Valset: valset, @@ -60,6 +60,7 @@ func NewNode(valset MockValidators) *Node { Key: key, Store: ctx.KVStore(key), Commits: nil, + Root: root, } } @@ -147,7 +148,7 @@ func (node *Node) Set(k, value []byte) { } func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10)) + node := NewNode(NewMockValidators(100, 10), newRoot()) node.Commit() From 6ada539b26634c0ec2add78cfcd6697f137bcc53 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 18:26:23 +0200 Subject: [PATCH 068/182] fix lint --- x/ibc/02-client/tendermint/tests/valset.go | 2 +- x/ibc/02-client/tendermint/types.go | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 0d97a5427c9b..1b5f88aa949b 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -84,7 +84,7 @@ type MockValidators []MockValidator var _ sort.Interface = MockValidators{} -// TODO: differenciate power between the vals +// TODO: differentiate power between the vals func NewMockValidators(num int, power int64) MockValidators { res := make(MockValidators, num) for i := range res { diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 26a4c35370e6..6bb1bb1f18dd 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -48,11 +48,8 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, return nil, errors.New("invalid type") } - nextvalset := cs.NextValidatorSet - nexthash := nextvalset.Hash() - if cs.Height == uint64(header.Height-1) { - nexthash = cs.NextValidatorSet.Hash() + nexthash := cs.NextValidatorSet.Hash() if !bytes.Equal(header.ValidatorsHash, nexthash) { return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) } From f7e1336ca7939330cb9adc2db96f668264390edd Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 19:12:36 +0200 Subject: [PATCH 069/182] fix lint --- .../tendermint/tests/tendermint_test.go | 6 ------ x/ibc/02-client/tendermint/tests/types.go | 16 ++++++++++++---- x/ibc/02-client/tendermint/tests/valset.go | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index caf866337c47..8a1c764f50f2 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -4,14 +4,8 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10), newRoot()) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index d0b7b488db39..5e0af44f3806 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -1,7 +1,7 @@ package tendermint import ( - "math/rand" + "crypto/rand" "testing" "github.com/stretchr/testify/require" @@ -23,6 +23,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) +// nolint: unused +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + const chainid = "testchain" func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { @@ -147,6 +152,7 @@ func (node *Node) Set(k, value []byte) { node.Store.Set(node.Root.Key(k), value) } +// nolint:deadcode,unused func testProof(t *testing.T) { node := NewNode(NewMockValidators(100, 10), newRoot()) @@ -157,8 +163,10 @@ func testProof(t *testing.T) { for i := 0; i < 100; i++ { k := make([]byte, 32) v := make([]byte, 32) - rand.Read(k) - rand.Read(v) + _, err := rand.Read(k) + require.NoError(t, err) + _, err = rand.Read(v) + require.NoError(t, err) kvps = append(kvps, cmn.KVPair{Key: k, Value: v}) node.Set(k, v) } @@ -166,7 +174,7 @@ func testProof(t *testing.T) { proofs := []commitment.Proof{} root := node.Root.Update(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) + v, p := node.Query(t, root.(merkle.Root), kvp.Key) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 1b5f88aa949b..30bd194682c8 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -131,7 +131,7 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { Height: header.Height, Type: tmtypes.PrecommitType, } - val.MockPV.SignVote(chainid, vote) + _ = val.MockPV.SignVote(chainid, vote) precommits[i] = vote.CommitSig() } From 7bd4ba556ea8754c09c70dfb985cbfa98f9046eb Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Jul 2019 23:53:46 +0900 Subject: [PATCH 070/182] add handler/msgs/client --- store/state/base.go | 12 +- x/ibc/02-client/cli.go | 9 +- x/ibc/02-client/client/cli/query.go | 159 ++++++++++++++++++++++++ x/ibc/02-client/client/cli/tx.go | 144 +++++++++++++++++++++ x/ibc/02-client/client/utils/receive.go | 94 ++++++++++++++ x/ibc/02-client/codec.go | 9 ++ x/ibc/02-client/handler.go | 29 +++++ x/ibc/02-client/manager.go | 15 +-- x/ibc/02-client/msgs.go | 69 ++++++++++ x/ibc/02-client/tendermint/codec.go | 7 +- 10 files changed, 526 insertions(+), 21 deletions(-) create mode 100644 x/ibc/02-client/client/cli/query.go create mode 100644 x/ibc/02-client/client/cli/tx.go create mode 100644 x/ibc/02-client/client/utils/receive.go create mode 100644 x/ibc/02-client/handler.go create mode 100644 x/ibc/02-client/msgs.go diff --git a/store/state/base.go b/store/state/base.go index f163c18b98a0..a6f429053248 100644 --- a/store/state/base.go +++ b/store/state/base.go @@ -15,13 +15,19 @@ type Base struct { } func EmptyBase() Base { - return NewBase(nil, nil) + return NewBase(nil, nil, nil) } -func NewBase(cdc *codec.Codec, key sdk.StoreKey) Base { +func NewBase(cdc *codec.Codec, key sdk.StoreKey, rootkey []byte) Base { + if len(rootkey) == 0 { + return Base{ + cdc: cdc, + storefn: func(ctx Context) KVStore { return ctx.KVStore(key) }, + } + } return Base{ cdc: cdc, - storefn: func(ctx Context) KVStore { return ctx.KVStore(key) }, + storefn: func(ctx Context) KVStore { return prefix.NewStore(ctx.KVStore(key), rootkey) }, } } diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 2592e697573c..45f2c9672a4d 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -17,9 +17,10 @@ type CLIObject struct { Cdc *codec.Codec } -func (obj Object) CLI(root merkle.Root) CLIObject { +func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { + obj := man.object(id) return CLIObject{ - ID: obj.id, + ID: id, ConsensusStateKey: obj.consensusState.Key(), FrozenKey: obj.frozen.Key(), @@ -42,12 +43,12 @@ func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) } -func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { +func (obj CLIObject) ConsensusState(ctx context.CLIContext) (res ConsensusState, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.ConsensusStateKey, &res) return } -func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { +func (obj CLIObject) Frozen(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.FrozenKey, &res) return } diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go new file mode 100644 index 000000000000..2506ed8dd905 --- /dev/null +++ b/x/ibc/02-client/client/cli/query.go @@ -0,0 +1,159 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + tmtypes "github.com/tendermint/tendermint/types" + + cli "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +func defaultRoot(storeKey string, root []byte) merkle.Root { + return merkle.NewRoot(root, [][]byte{[]byte(storeKey)}, []byte("protocol")) +} + +func defaultBase(cdc *codec.Codec) (state.Base, state.Base) { + protocol := state.NewBase(cdc, nil, []byte("protocol")) + free := state.NewBase(cdc, nil, []byte("free")) + return protocol, free +} + +func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcQueryCmd := &cobra.Command{ + Use: "ibc", + Short: "IBC query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcQueryCmd.AddCommand(cli.GetCommands( + GetCmdQueryConsensusState(storeKey, cdc), + GetCmdQueryHeader(cdc), + GetCmdQueryClient(storeKey, cdc), + )...) + return ibcQueryCmd +} + +func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "client", + Short: "Query stored client", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + man := client.NewManager(defaultBase(cdc)) + root := defaultRoot(storeKey, nil) + id := args[0] + + state, _, err := man.CLIObject(root, id).ConsensusState(ctx) + if err != nil { + return err + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryConsensusState(storeKey string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "consensus-state", + Short: "Query the latest consensus state of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + state := tendermint.ConsensusState{ + ChainID: commit.ChainID, + Height: uint64(commit.Height), + Root: defaultRoot(storeKey, []byte(commit.AppHash)), + NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "header", + Short: "Query the latest header of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + nextvalidators, err := node.Validators(&height) + if err != nil { + return err + } + + header := tendermint.Header{ + SignedHeader: commit.SignedHeader, + ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) + + return nil + }, + } +} diff --git a/x/ibc/02-client/client/cli/tx.go b/x/ibc/02-client/client/cli/tx.go new file mode 100644 index 000000000000..e654d76e7c3d --- /dev/null +++ b/x/ibc/02-client/client/cli/tx.go @@ -0,0 +1,144 @@ +package cli + +import ( + "errors" + "io/ioutil" + // "os" + + "github.com/spf13/cobra" + + // "github.com/tendermint/tendermint/libs/log" + rpcclient "github.com/tendermint/tendermint/rpc/client" + + cli "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + // "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + // "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +const ( + FlagStatePath = "state" + FlagClientID = "client-id" + FlagConnectionID = "connection-id" + FlagChannelID = "channel-id" + FlagCounterpartyID = "counterparty-id" + FlagCounterpartyClientID = "counterparty-client-id" + FlagSourceNode = "source-node" +) + +func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcTxCmd := &cobra.Command{ + Use: "ibc", + Short: "IBC transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcTxCmd.AddCommand(cli.PostCommands( + GetCmdCreateClient(cdc), + GetCmdUpdateClient(cdc), + )...) + + return ibcTxCmd +} + +func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "create-client", + Short: "create new client with a consensus state", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + cliCtx := context.NewCLIContext(). + WithCodec(cdc) + + contents, err := ioutil.ReadFile(args[1]) + if err != nil { + return err + } + + var state client.ConsensusState + if err := cdc.UnmarshalJSON(contents, &state); err != nil { + return err + } + + msg := client.MsgCreateClient{ + ClientID: args[0], + ConsensusState: state, + Signer: cliCtx.GetFromAddress(), + } + + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) + }, + } + + return cmd +} + +func GetCmdUpdateClient(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "update-client", + Short: "update existing client with a header", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + cliCtx := context.NewCLIContext(). + WithCodec(cdc) + + contents, err := ioutil.ReadFile(args[1]) + if err != nil { + return err + } + + var header client.Header + if err := cdc.UnmarshalJSON(contents, &header); err != nil { + return err + } + + msg := client.MsgUpdateClient{ + ClientID: args[0], + Header: header, + Signer: cliCtx.GetFromAddress(), + } + + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) + }, + } + + return cmd +} + +// Copied from client/context/query.go +func query(ctx context.CLIContext, key []byte) ([]byte, merkle.Proof, error) { + node, err := ctx.GetNode() + if err != nil { + return nil, merkle.Proof{}, err + } + + opts := rpcclient.ABCIQueryOptions{ + Height: ctx.Height, + Prove: true, + } + + result, err := node.ABCIQueryWithOptions("/store/ibc/key", key, opts) + if err != nil { + return nil, merkle.Proof{}, err + } + + resp := result.Response + if !resp.IsOK() { + return nil, merkle.Proof{}, errors.New(resp.Log) + } + + return resp.Value, merkle.Proof{ + Key: key, + Proof: resp.Proof, + }, nil +} diff --git a/x/ibc/02-client/client/utils/receive.go b/x/ibc/02-client/client/utils/receive.go new file mode 100644 index 000000000000..7a8df21189fb --- /dev/null +++ b/x/ibc/02-client/client/utils/receive.go @@ -0,0 +1,94 @@ +package cli + +import ( + "errors" + + "github.com/spf13/viper" + + rpcclient "github.com/tendermint/tendermint/rpc/client" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/store/state" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" + ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" +) + +const ( + FlagStatePath = "state" + FlagClientID = "client-id" + FlagConnectionID = "connection-id" + FlagChannelID = "channel-id" + FlagCounterpartyID = "counterparty-id" + FlagCounterpartyClientID = "counterparty-client-id" + FlagSourceNode = "source-node" +) + +// Copied from client/context/query.go +func query(ctx context.CLIContext, key []byte) ([]byte, merkle.Proof, error) { + node, err := ctx.GetNode() + if err != nil { + return nil, merkle.Proof{}, err + } + + opts := rpcclient.ABCIQueryOptions{ + Height: ctx.Height, + Prove: true, + } + + result, err := node.ABCIQueryWithOptions("/store/ibc/key", key, opts) + if err != nil { + return nil, merkle.Proof{}, err + } + + resp := result.Response + if !resp.IsOK() { + return nil, merkle.Proof{}, errors.New(resp.Log) + } + + return resp.Value, merkle.Proof{ + Key: key, + Proof: resp.Proof, + }, nil +} + +func GetRelayPacket(cliCtxSource, cliCtx context.CLIContext) (ibc.Packet, ibc.Proof, error) { + keeper := ibc.DummyKeeper() + cdc := cliCtx.Codec + + connid := viper.GetString(FlagConnectionID) + chanid := viper.GetString(FlagChannelID) + + obj := keeper.Channel.Object(connid, chanid) + + seqbz, _, err := query(cliCtx, obj.Seqrecv.Key()) + if err != nil { + return nil, nil, err + } + seq, err := state.DecodeInt(seqbz, state.Dec) + if err != nil { + return nil, nil, err + } + + sentbz, _, err := query(cliCtxSource, obj.Seqsend.Key()) + if err != nil { + return nil, nil, err + } + sent, err := state.DecodeInt(sentbz, state.Dec) + if err != nil { + return nil, nil, err + } + + if seq == sent { + return nil, nil, errors.New("no packet detected") + } + + var packet ibc.Packet + packetbz, proof, err := query(cliCtxSource, obj.Packets.Value(seq).Key()) + if err != nil { + return nil, nil, err + } + cdc.MustUnmarshalBinaryBare(packetbz, &packet) + + return packet, proof, nil +} diff --git a/x/ibc/02-client/codec.go b/x/ibc/02-client/codec.go index fa194562e4f1..ece7e750dc98 100644 --- a/x/ibc/02-client/codec.go +++ b/x/ibc/02-client/codec.go @@ -4,7 +4,16 @@ import ( "github.com/cosmos/cosmos-sdk/codec" ) +var MsgCdc = codec.New() + +func init() { + RegisterCodec(MsgCdc) +} + func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*ConsensusState)(nil), nil) cdc.RegisterInterface((*Header)(nil), nil) + + cdc.RegisterConcrete(MsgCreateClient{}, "ibc/client/MsgCreateClient", nil) + cdc.RegisterConcrete(MsgUpdateClient{}, "ibc/client/MsgUpdateClient", nil) } diff --git a/x/ibc/02-client/handler.go b/x/ibc/02-client/handler.go new file mode 100644 index 000000000000..dfab0725b8c4 --- /dev/null +++ b/x/ibc/02-client/handler.go @@ -0,0 +1,29 @@ +package client + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func HandleMsgCreateClient(ctx sdk.Context, msg MsgCreateClient, man Manager) sdk.Result { + _, err := man.Create(ctx, msg.ClientID, msg.ConsensusState) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), sdk.CodeType(100), err.Error()).Result() + } + + // TODO: events + return sdk.Result{} +} + +func HandleMsgUpdateClient(ctx sdk.Context, msg MsgUpdateClient, man Manager) sdk.Result { + obj, err := man.Query(ctx, msg.ClientID) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), sdk.CodeType(200), err.Error()).Result() + } + err = obj.Update(ctx, msg.Header) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), sdk.CodeType(300), err.Error()).Result() + } + + // TODO: events + return sdk.Result{} +} diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index e94d14702b72..67d43a4325eb 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -2,7 +2,6 @@ package client import ( "errors" - "strconv" "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,25 +11,16 @@ import ( // XXX: implement spec: ClientState.verifiedRoots -type IDGenerator func(sdk.Context /*Header,*/, state.Value) string - -func IntegerIDGenerator(ctx sdk.Context, v state.Value) string { - id := state.NewInteger(v, state.Dec).Incr(ctx) - return strconv.FormatUint(id, 10) -} - type Manager struct { protocol state.Mapping idval state.Value - idgen IDGenerator } -func NewManager(protocol, free state.Base, idgen IDGenerator) Manager { +func NewManager(protocol, free state.Base) Manager { return Manager{ protocol: state.NewMapping(protocol, []byte("/client")), idval: state.NewValue(free, []byte("/client/id")), - idgen: idgen, } } @@ -61,8 +51,7 @@ func (man Manager) object(id string) Object { } } -func (man Manager) Create(ctx sdk.Context, cs ConsensusState) (Object, error) { - id := man.idgen(ctx, man.idval) +func (man Manager) Create(ctx sdk.Context, id string, cs ConsensusState) (Object, error) { obj := man.object(id) if obj.exists(ctx) { return Object{}, errors.New("Create client on already existing id") diff --git a/x/ibc/02-client/msgs.go b/x/ibc/02-client/msgs.go new file mode 100644 index 000000000000..7f515c388c8f --- /dev/null +++ b/x/ibc/02-client/msgs.go @@ -0,0 +1,69 @@ +package client + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MsgCreateClient struct { + ClientID string + ConsensusState ConsensusState + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgCreateClient{} + +func (msg MsgCreateClient) Route() string { + return "ibc" +} + +func (msg MsgCreateClient) Type() string { + return "create-client" +} + +func (msg MsgCreateClient) ValidateBasic() sdk.Error { + if msg.Signer.Empty() { + return sdk.ErrInvalidAddress("empty address") + } + return nil +} + +func (msg MsgCreateClient) GetSignBytes() []byte { + bz := MsgCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg MsgCreateClient) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + +type MsgUpdateClient struct { + ClientID string + Header Header + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgUpdateClient{} + +func (msg MsgUpdateClient) Route() string { + return "ibc" +} + +func (msg MsgUpdateClient) Type() string { + return "update-client" +} + +func (msg MsgUpdateClient) ValidateBasic() sdk.Error { + if msg.Signer.Empty() { + return sdk.ErrInvalidAddress("empty address") + } + return nil +} + +func (msg MsgUpdateClient) GetSignBytes() []byte { + bz := MsgCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg MsgUpdateClient) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} diff --git a/x/ibc/02-client/tendermint/codec.go b/x/ibc/02-client/tendermint/codec.go index d8308a3e7ec8..eca3b38917fa 100644 --- a/x/ibc/02-client/tendermint/codec.go +++ b/x/ibc/02-client/tendermint/codec.go @@ -2,10 +2,15 @@ package tendermint import ( "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" ) +func init() { + RegisterCodec(client.MsgCdc) +} + func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil) cdc.RegisterConcrete(Header{}, "ibc/client/tendermint/Header", nil) - } From f750ac47da1e6e5de46a149e4ce9b3ffeefe278f Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Jul 2019 23:54:32 +0900 Subject: [PATCH 071/182] rm relay --- x/ibc/02-client/client/utils/receive.go | 94 ------------------------- 1 file changed, 94 deletions(-) delete mode 100644 x/ibc/02-client/client/utils/receive.go diff --git a/x/ibc/02-client/client/utils/receive.go b/x/ibc/02-client/client/utils/receive.go deleted file mode 100644 index 7a8df21189fb..000000000000 --- a/x/ibc/02-client/client/utils/receive.go +++ /dev/null @@ -1,94 +0,0 @@ -package cli - -import ( - "errors" - - "github.com/spf13/viper" - - rpcclient "github.com/tendermint/tendermint/rpc/client" - - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/store/state" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" -) - -const ( - FlagStatePath = "state" - FlagClientID = "client-id" - FlagConnectionID = "connection-id" - FlagChannelID = "channel-id" - FlagCounterpartyID = "counterparty-id" - FlagCounterpartyClientID = "counterparty-client-id" - FlagSourceNode = "source-node" -) - -// Copied from client/context/query.go -func query(ctx context.CLIContext, key []byte) ([]byte, merkle.Proof, error) { - node, err := ctx.GetNode() - if err != nil { - return nil, merkle.Proof{}, err - } - - opts := rpcclient.ABCIQueryOptions{ - Height: ctx.Height, - Prove: true, - } - - result, err := node.ABCIQueryWithOptions("/store/ibc/key", key, opts) - if err != nil { - return nil, merkle.Proof{}, err - } - - resp := result.Response - if !resp.IsOK() { - return nil, merkle.Proof{}, errors.New(resp.Log) - } - - return resp.Value, merkle.Proof{ - Key: key, - Proof: resp.Proof, - }, nil -} - -func GetRelayPacket(cliCtxSource, cliCtx context.CLIContext) (ibc.Packet, ibc.Proof, error) { - keeper := ibc.DummyKeeper() - cdc := cliCtx.Codec - - connid := viper.GetString(FlagConnectionID) - chanid := viper.GetString(FlagChannelID) - - obj := keeper.Channel.Object(connid, chanid) - - seqbz, _, err := query(cliCtx, obj.Seqrecv.Key()) - if err != nil { - return nil, nil, err - } - seq, err := state.DecodeInt(seqbz, state.Dec) - if err != nil { - return nil, nil, err - } - - sentbz, _, err := query(cliCtxSource, obj.Seqsend.Key()) - if err != nil { - return nil, nil, err - } - sent, err := state.DecodeInt(sentbz, state.Dec) - if err != nil { - return nil, nil, err - } - - if seq == sent { - return nil, nil, errors.New("no packet detected") - } - - var packet ibc.Packet - packetbz, proof, err := query(cliCtxSource, obj.Packets.Value(seq).Key()) - if err != nil { - return nil, nil, err - } - cdc.MustUnmarshalBinaryBare(packetbz, &packet) - - return packet, proof, nil -} From a3e2f9c707cad15373ff68bdde2667888742db96 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 12 Jul 2019 01:33:18 +0900 Subject: [PATCH 072/182] finalize rebase on 23 root/path sep --- x/ibc/02-client/cli.go | 8 +++--- .../tendermint/tests/tendermint_test.go | 8 +++--- x/ibc/02-client/tendermint/tests/types.go | 26 +++++++++---------- x/ibc/02-client/tendermint/types.go | 3 ++- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 45f2c9672a4d..382b1d2d4aea 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -13,24 +13,24 @@ type CLIObject struct { ConsensusStateKey []byte FrozenKey []byte - Root merkle.Root + Path merkle.Path Cdc *codec.Codec } -func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { +func (man Manager) CLIObject(path merkle.Path, id string) CLIObject { obj := man.object(id) return CLIObject{ ID: id, ConsensusStateKey: obj.consensusState.Key(), FrozenKey: obj.frozen.Key(), - Root: root, + Path: path, Cdc: obj.consensusState.Cdc(), } } func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { - resp, err := ctx.QueryABCI(obj.Root.RequestQuery(key)) + resp, err := ctx.QueryABCI(obj.Path.RequestQuery(key)) if err != nil { return merkle.Proof{}, err } diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index 8a1c764f50f2..61a0944fbaa0 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -4,14 +4,16 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10), newRoot()) + node := NewNode(NewMockValidators(100, 10), newPath()) - node.Commit() + header := node.Commit() - verifier := node.LastStateVerifier(newRoot()) + verifier := node.LastStateVerifier(merkle.NewRoot(header.AppHash)) for i := 0; i < 100; i++ { header := node.Commit() diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 5e0af44f3806..f9fd9fc9f0c8 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -24,8 +24,8 @@ import ( ) // nolint: unused -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +func newPath() merkle.Path { + return merkle.NewPath([][]byte{[]byte("test")}, []byte{0x12, 0x34}) } const chainid = "testchain" @@ -54,10 +54,10 @@ type Node struct { Commits []tmtypes.SignedHeader - Root merkle.Root + Path merkle.Path } -func NewNode(valset MockValidators, root merkle.Root) *Node { +func NewNode(valset MockValidators, path merkle.Path) *Node { key, ctx, cms, _ := defaultComponents() return &Node{ Valset: valset, @@ -65,7 +65,7 @@ func NewNode(valset MockValidators, root merkle.Root) *Node { Key: key, Store: ctx.KVStore(key), Commits: nil, - Root: root, + Path: path, } } @@ -120,7 +120,7 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root me tendermint.ConsensusState{ ChainID: chainid, Height: uint64(header.Height), - Root: root.Update(header.AppHash), + Root: merkle.NewRoot(header.AppHash), NextValidatorSet: nextvalset.ValidatorSet(), }, } @@ -142,19 +142,19 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock return nil } -func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.QueryMultiStore(node.Cms, k) +func (node *Node) Query(t *testing.T, path merkle.Path, k []byte) ([]byte, commitment.Proof) { + code, value, proof := path.QueryMultiStore(node.Cms, k) require.Equal(t, uint32(0), code) return value, proof } func (node *Node) Set(k, value []byte) { - node.Store.Set(node.Root.Key(k), value) + node.Store.Set(node.Path.Key(k), value) } // nolint:deadcode,unused func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10), newRoot()) + node := NewNode(NewMockValidators(100, 10), newPath()) node.Commit() @@ -172,13 +172,13 @@ func testProof(t *testing.T) { } header := node.Commit() proofs := []commitment.Proof{} - root := node.Root.Update(header.AppHash) + root := merkle.NewRoot(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, root.(merkle.Root), kvp.Key) + v, p := node.Query(t, node.Path, kvp.Key) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore(root, proofs) + cstore, err := commitment.NewStore(root, node.Path, proofs) require.NoError(t, err) for _, kvp := range kvps { diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 6bb1bb1f18dd..ca5da8c1cae5 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) var _ client.ConsensusState = ConsensusState{} @@ -37,7 +38,7 @@ func (cs ConsensusState) update(header Header) ConsensusState { return ConsensusState{ ChainID: cs.ChainID, Height: uint64(header.Height), - Root: cs.GetRoot().Update(header.AppHash), + Root: merkle.NewRoot(header.AppHash), NextValidatorSet: header.NextValidatorSet, } } From 56712b1fb32ee5744b52aae4182652d784e9f3dc Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 12 Jul 2019 01:35:54 +0900 Subject: [PATCH 073/182] fix lint, fix syntax --- x/ibc/02-client/client/cli/query.go | 10 +++++----- x/ibc/02-client/client/cli/tx.go | 31 ----------------------------- 2 files changed, 5 insertions(+), 36 deletions(-) diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 2506ed8dd905..9de2231427bb 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -17,8 +17,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func defaultRoot(storeKey string, root []byte) merkle.Root { - return merkle.NewRoot(root, [][]byte{[]byte(storeKey)}, []byte("protocol")) +func defaultPath(storeKey string) merkle.Path { + return merkle.NewPath([][]byte{[]byte(storeKey)}, []byte("protocol")) } func defaultBase(cdc *codec.Codec) (state.Base, state.Base) { @@ -51,10 +51,10 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) man := client.NewManager(defaultBase(cdc)) - root := defaultRoot(storeKey, nil) + path := defaultPath(storeKey) id := args[0] - state, _, err := man.CLIObject(root, id).ConsensusState(ctx) + state, _, err := man.CLIObject(path, id).ConsensusState(ctx) if err != nil { return err } @@ -99,7 +99,7 @@ func GetCmdQueryConsensusState(storeKey string, cdc *codec.Codec) *cobra.Command state := tendermint.ConsensusState{ ChainID: commit.ChainID, Height: uint64(commit.Height), - Root: defaultRoot(storeKey, []byte(commit.AppHash)), + Root: merkle.NewRoot(commit.AppHash), NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), } diff --git a/x/ibc/02-client/client/cli/tx.go b/x/ibc/02-client/client/cli/tx.go index e654d76e7c3d..1b18dbe34783 100644 --- a/x/ibc/02-client/client/cli/tx.go +++ b/x/ibc/02-client/client/cli/tx.go @@ -1,14 +1,12 @@ package cli import ( - "errors" "io/ioutil" // "os" "github.com/spf13/cobra" // "github.com/tendermint/tendermint/libs/log" - rpcclient "github.com/tendermint/tendermint/rpc/client" cli "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" @@ -20,7 +18,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client" // "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) const ( @@ -114,31 +111,3 @@ func GetCmdUpdateClient(cdc *codec.Codec) *cobra.Command { return cmd } - -// Copied from client/context/query.go -func query(ctx context.CLIContext, key []byte) ([]byte, merkle.Proof, error) { - node, err := ctx.GetNode() - if err != nil { - return nil, merkle.Proof{}, err - } - - opts := rpcclient.ABCIQueryOptions{ - Height: ctx.Height, - Prove: true, - } - - result, err := node.ABCIQueryWithOptions("/store/ibc/key", key, opts) - if err != nil { - return nil, merkle.Proof{}, err - } - - resp := result.Response - if !resp.IsOK() { - return nil, merkle.Proof{}, errors.New(resp.Log) - } - - return resp.Value, merkle.Proof{ - Key: key, - Proof: resp.Proof, - }, nil -} From ea91bb8c4ce4d5b19498d8766c9b62dd5804b123 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 02:32:36 +0900 Subject: [PATCH 074/182] finalize rebase on merkle root/path separation --- x/ibc/02-client/tendermint/tests/tendermint_test.go | 4 +++- x/ibc/02-client/tendermint/tests/types.go | 13 ++++--------- x/ibc/03-connection/handshake.go | 2 +- x/ibc/03-connection/tests/types.go | 6 +++--- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index 707d3aa252d2..df63032b3986 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -4,10 +4,12 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10), newPath()) + node := NewNode(NewMockValidators(100, 10), merkle.NewPath([][]byte{[]byte("f8wib")}, []byte{0x98, 0x78})) _ = node.Commit() diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index edd8497ce524..dd45fa0fe374 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -23,15 +23,10 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -// nolint: unused -func newPath() merkle.Path { - return merkle.NewPath([][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - const chainid = "testchain" -func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { - key := sdk.NewKVStoreKey("test") +func defaultComponents(storename string) (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { + key := sdk.NewKVStoreKey(storename) db := dbm.NewMemDB() cms := store.NewCommitMultiStore(db) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) @@ -58,7 +53,7 @@ type Node struct { } func NewNode(valset MockValidators, path merkle.Path) *Node { - key, ctx, cms, _ := defaultComponents() + key, ctx, cms, _ := defaultComponents(string(path.KeyPath[0])) return &Node{ Valset: valset, Cms: cms, @@ -156,7 +151,7 @@ func (node *Node) Set(k, value []byte) { // nolint:deadcode,unused func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10), newPath()) + node := NewNode(NewMockValidators(100, 10), merkle.NewPath([][]byte{[]byte("1")}, []byte{0x00, 0x01})) node.Commit() diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 83dde7db5882..b285c90747c3 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -233,7 +233,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } if !obj.counterparty.connection.Is(ctx, Connection{ - Client: obj.Connection(ctx).Client, + Client: obj.CounterpartyClient(ctx), Counterparty: obj.ID(), }) { err = errors.New("wrong counterparty") diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index fcb359b3e82e..9464b031143b 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -30,8 +30,8 @@ type Node struct { func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res := &Node{ - Name: "self", // hard coded, doesnt matter - Node: tendermint.NewNode(self, merkle.NewPath(nil, []byte("protocol"))), // TODO: test with key prefix + Name: "self", // hard coded, doesnt matter + Node: tendermint.NewNode(self, merkle.NewPath([][]byte{[]byte("teststoreself")}, []byte("protocol"))), // TODO: test with key prefix State: connection.Idle, Cdc: cdc, @@ -39,7 +39,7 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res.Counterparty = &Node{ Name: "counterparty", - Node: tendermint.NewNode(counter, merkle.NewPath(nil, []byte("protocol"))), + Node: tendermint.NewNode(counter, merkle.NewPath([][]byte{[]byte("teststorecounterparty")}, []byte("protocol"))), Counterparty: res, State: connection.Idle, From 812d3abf84ac4d1dbf484ddf82da7a8b5041ecc4 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 02:56:14 +0900 Subject: [PATCH 075/182] add path --- x/ibc/03-connection/manager.go | 1 - x/ibc/03-connection/types.go | 11 ++++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 7e7f85c48975..e5d32fafd454 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -78,7 +78,6 @@ type CounterObject struct { kind commitment.String - // TODO: prove counterparty client in v1 client client.CounterObject // nolint: unused } diff --git a/x/ibc/03-connection/types.go b/x/ibc/03-connection/types.go index 428137aad893..358d6a451fb9 100644 --- a/x/ibc/03-connection/types.go +++ b/x/ibc/03-connection/types.go @@ -1,15 +1,20 @@ package connection import ( - "errors" - "strings" + /* + "errors" + "strings" + */ + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type Connection struct { Client string Counterparty string + Path commitment.Path } +/* func (conn Connection) MarshalAmino() (string, error) { return strings.Join([]string{conn.Client, conn.Counterparty}, "/"), nil } @@ -23,7 +28,7 @@ func (conn *Connection) UnmarshalAmino(text string) (err error) { conn.Counterparty = fields[1] return nil } - +*/ var kinds = map[string]Kind{ "handshake": Kind{true, true}, } From 02a3b1c4b2b06f11bf4d2a1730b73f20d4a66841 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 03:11:53 +0900 Subject: [PATCH 076/182] add comments for manual proof arguments --- x/ibc/03-connection/handshake.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index b285c90747c3..59bdf7944d8e 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -154,8 +154,10 @@ func (man Handshaker) OpenInit(ctx sdk.Context, return obj, nil } -// Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} +// Using proofs: counterparty.{connection,state,nextTimeout,counterpartyClient, client} func (man Handshaker) OpenTry(ctx sdk.Context, + // TODO: proofs should be manually passed + // connectionp, statep, timeoutp, counterpartyClientp, clientp commitment.Proof, id string, connection Connection, counterpartyClient string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.create(ctx, id, connection, counterpartyClient) @@ -213,8 +215,10 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } -// Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} +// Using proofs: counterparty.{connection, state, timeout, counterpartyClient, client} func (man Handshaker) OpenAck(ctx sdk.Context, + // TODO: proofs should be manually passed + // connectionp, statep, timeoutp, counterpartyClientp, clientp commitment.Proof id string /*expheight uint64, */, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) @@ -270,7 +274,11 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } // Using proofs: counterparty.{connection,state, nextTimeout} -func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint64) (obj HandshakeObject, err error) { +func (man Handshaker) OpenConfirm(ctx sdk.Context, + // TODO: proofs should be manually passed + // statep, timeoutp, commitment.Proof, + id string, timeoutHeight uint64) (obj HandshakeObject, err error) { + obj, err = man.query(ctx, id) if err != nil { return From 631d7377cdf81e1c33cca96c2d50484e9ab33972 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 03:36:18 +0900 Subject: [PATCH 077/182] pass proofs manually --- x/ibc/03-connection/handshake.go | 45 ++++++++++++++++++++++++++---- x/ibc/03-connection/tests/types.go | 20 ++++--------- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 59bdf7944d8e..e96c805664bf 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -156,8 +156,7 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{connection,state,nextTimeout,counterpartyClient, client} func (man Handshaker) OpenTry(ctx sdk.Context, - // TODO: proofs should be manually passed - // connectionp, statep, timeoutp, counterpartyClientp, clientp commitment.Proof, + connectionp, statep, timeoutp, counterpartyClientp /*, clientp*/ commitment.Proof, id string, connection Connection, counterpartyClient string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.create(ctx, id, connection, counterpartyClient) @@ -165,6 +164,18 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } + store, err := commitment.NewStore( + // TODO: proof root should be able to be obtained from the past + obj.client.ConsensusState(ctx).GetRoot(), + connection.Path, + []commitment.Proof{connectionp, statep, timeoutp, counterpartyClientp}, + ) + if err != nil { + return + } + + ctx = commitment.WithStore(ctx, store) + err = assertTimeout(ctx, timeoutHeight) if err != nil { return @@ -217,8 +228,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{connection, state, timeout, counterpartyClient, client} func (man Handshaker) OpenAck(ctx sdk.Context, - // TODO: proofs should be manually passed - // connectionp, statep, timeoutp, counterpartyClientp, clientp commitment.Proof + connectionp, statep, timeoutp, counterpartyClientp /*, clientp*/ commitment.Proof, id string /*expheight uint64, */, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) @@ -226,6 +236,18 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } + store, err := commitment.NewStore( + // TODO: proof root should be able to be obtained from the past + obj.client.ConsensusState(ctx).GetRoot(), + obj.Connection(ctx).Path, + []commitment.Proof{connectionp, statep, timeoutp, counterpartyClientp}, + ) + if err != nil { + return + } + + ctx = commitment.WithStore(ctx, store) + if !obj.state.Transit(ctx, Init, Open) { err = errors.New("ack on non-init connection") return @@ -275,8 +297,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // Using proofs: counterparty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, - // TODO: proofs should be manually passed - // statep, timeoutp, commitment.Proof, + statep, timeoutp commitment.Proof, id string, timeoutHeight uint64) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) @@ -284,6 +305,18 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } + store, err := commitment.NewStore( + // TODO: proof root should be able to be obtained from the past + obj.client.ConsensusState(ctx).GetRoot(), + obj.Connection(ctx).Path, + []commitment.Proof{statep, timeoutp}, + ) + if err != nil { + return + } + + ctx = commitment.WithStore(ctx, store) + if !obj.state.Transit(ctx, OpenTry, Open) { err = errors.New("confirm on non-try connection") return diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 9464b031143b..931163dfe6cf 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -58,7 +58,7 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { } func (node *Node) CreateClient(t *testing.T) { - ctx := node.Context(t, nil) + ctx := node.Context() climan, _ := node.Manager() obj, err := climan.Create(ctx, node.Name, node.Counterparty.LastStateVerifier().ConsensusState) require.NoError(t, err) @@ -67,7 +67,7 @@ func (node *Node) CreateClient(t *testing.T) { } func (node *Node) UpdateClient(t *testing.T, header client.Header) { - ctx := node.Context(t, nil) + ctx := node.Context() climan, _ := node.Manager() obj, err := climan.Query(ctx, node.Connection.Client) require.NoError(t, err) @@ -80,16 +80,8 @@ func (node *Node) SetState(state connection.State) { node.Counterparty.State = state } -func (node *Node) Context(t *testing.T, proofs []commitment.Proof) sdk.Context { - ctx := node.Node.Context() - store, err := commitment.NewStore(node.Counterparty.Root(), node.Counterparty.Path, proofs) - require.NoError(t, err) - ctx = commitment.WithStore(ctx, store) - return ctx -} - func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, connection.Handshaker) { - ctx := node.Context(t, proofs) + ctx := node.Context() _, man := node.Manager() return ctx, connection.NewHandshaker(man) } @@ -124,7 +116,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs[0], proofs[1], proofs[2], proofs[3], node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.OpenTry, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) @@ -135,7 +127,7 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs[0], proofs[1], proofs[2], proofs[3], node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) @@ -145,7 +137,7 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs[0], proofs[1], node.Name, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) From 5266fc92c6e4fbce706992cbf59c375b6fe9043e Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 7 Jun 2019 23:47:01 +0200 Subject: [PATCH 078/182] add client --- x/ibc/02-client/manager.go | 146 ++++++++++++++++++++++++++++ x/ibc/02-client/tendermint/types.go | 79 +++++++++++++++ x/ibc/02-client/types.go | 46 +++++++++ 3 files changed, 271 insertions(+) create mode 100644 x/ibc/02-client/manager.go create mode 100644 x/ibc/02-client/tendermint/types.go create mode 100644 x/ibc/02-client/types.go diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go new file mode 100644 index 000000000000..89a8a878df49 --- /dev/null +++ b/x/ibc/02-client/manager.go @@ -0,0 +1,146 @@ +package client + +import ( + "errors" + "strconv" + + "github.com/cosmos/cosmos-sdk/store/mapping" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string + +func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { + id := mapping.NewInteger(v, mapping.Dec).Incr(ctx) + return strconv.FormatUint(id, 10) +} + +type Manager struct { + protocol mapping.Mapping + + idval mapping.Value + idgen IDGenerator +} + +func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { + return Manager{ + protocol: mapping.NewMapping(protocol, []byte("/")), + idval: mapping.NewValue(free, []byte("/id")), + idgen: idgen, + } +} + +/* +func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { + if _, ok := man.pred[kind]; ok { + panic("Kind already registered") + } + man.pred[kind] = pred + return man +} +*/ +func (man Manager) object(id string) Object { + return Object{ + id: id, + client: man.protocol.Value([]byte(id)), + freeze: mapping.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + } +} + +func (man Manager) Create(ctx sdk.Context, cs Client) string { + id := man.idgen(ctx, man.idval) + err := man.object(id).create(ctx, cs) + if err != nil { + panic(err) + } + return id +} + +func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { + res := man.object(id) + if !res.exists(ctx) { + return Object{}, errors.New("client not exists") + } + return res, nil +} + +type Object struct { + id string + client mapping.Value + freeze mapping.Boolean +} + +func (obj Object) create(ctx sdk.Context, st Client) error { + if obj.exists(ctx) { + return errors.New("Create client on already existing id") + } + obj.client.Set(ctx, st) + return nil +} + +func (obj Object) exists(ctx sdk.Context) bool { + return obj.client.Exists(ctx) +} + +func (obj Object) ID() string { + return obj.id +} + +func (obj Object) Value(ctx sdk.Context) (res Client) { + obj.client.Get(ctx, &res) + return +} + +func (obj Object) Is(ctx sdk.Context, client Client) bool { + return obj.client.Is(ctx, client) +} + +func (obj Object) Update(ctx sdk.Context, header Header) error { + if !obj.exists(ctx) { + panic("should not update nonexisting client") + } + + if obj.freeze.Get(ctx) { + return errors.New("client is frozen") + } + + var stored Client + obj.client.GetIfExists(ctx, &stored) + updated, err := stored.Validate(header) + if err != nil { + return err + } + + obj.client.Set(ctx, updated) + + return nil +} + +func (obj Object) Freeze(ctx sdk.Context) error { + if !obj.exists(ctx) { + panic("should not freeze nonexisting client") + } + + if obj.freeze.Get(ctx) { + return errors.New("client is already frozen") + } + + obj.freeze.Set(ctx, true) + + return nil +} + +func (obj Object) Delete(ctx sdk.Context) error { + if !obj.exists(ctx) { + panic("should not delete nonexisting client") + } + + if !obj.freeze.Get(ctx) { + return errors.New("client is not frozen") + } + + obj.client.Delete(ctx) + obj.freeze.Delete(ctx) + + return nil +} diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go new file mode 100644 index 000000000000..54655cf702d4 --- /dev/null +++ b/x/ibc/02-client/tendermint/types.go @@ -0,0 +1,79 @@ +package tendermint + +import ( + "bytes" + + "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +// Ref tendermint/lite/base_verifier.go + +var _ client.ValidityPredicateBase = ValidityPredicateBase{} + +type ValidityPredicateBase struct { + Height int64 + NextValidatorSet *types.ValidatorSet +} + +func (ValidityPredicateBase) Kind() client.Kind { + return client.Tendermint +} + +func (base ValidityPredicateBase) GetHeight() int64 { + return base.Height +} + +func (base ValidityPredicateBase) Equal(cbase client.ValidityPredicateBase) bool { + base0, ok := cbase.(ValidityPredicateBase) + if !ok { + return false + } + return base.Height == base0.Height && + bytes.Equal(base.NextValidatorSet.Hash(), base0.NextValidatorSet.Hash()) +} + +var _ client.Client = Client{} + +type Client struct { + Base ValidityPredicateBase + Root commitment.Root +} + +func (Client) Kind() client.Kind { + return client.Tendermint +} + +func (client Client) GetBase() client.ValidityPredicateBase { + return client.Base +} + +func (client Client) GetRoot() commitment.Root { + return client.Root +} + +func (client Client) Validate(header client.Header) (client.Client, error) { + return client, nil // XXX +} + +var _ client.Header = Header{} + +type Header struct { + Base ValidityPredicateBase + Root commitment.Root + Votes []*types.CommitSig +} + +func (header Header) Kind() client.Kind { + return client.Tendermint +} + +func (header Header) GetBase() client.ValidityPredicateBase { + return header.Base +} + +func (header Header) GetRoot() commitment.Root { + return header.Root +} diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go new file mode 100644 index 000000000000..7b9f81ec7789 --- /dev/null +++ b/x/ibc/02-client/types.go @@ -0,0 +1,46 @@ +package client + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +// TODO: types in this file should be (de/)serialized with proto in the future + +type AminoMarshaler interface { + MarshalAmino() (string, error) + UnmarshalAmino(string) error +} + +type ValidityPredicateBase interface { + Kind() Kind + GetHeight() int64 + Equal(ValidityPredicateBase) bool +} + +// ConsensusState +type Client interface { + Kind() Kind + GetBase() ValidityPredicateBase + GetRoot() commitment.Root + Validate(Header) (Client, error) // ValidityPredicate +} + +func Equal(client1, client2 Client) bool { + return client1.Kind() == client2.Kind() && + client1.GetBase().Equal(client2.GetBase()) +} + +type Header interface { + Kind() Kind + // Proof() HeaderProof + GetBase() ValidityPredicateBase // can be nil + GetRoot() commitment.Root +} + +// XXX: Kind should be enum? + +type Kind byte + +const ( + Tendermint Kind = iota +) From 06257bdfa0595474ff1fb48fe45b76bba435b823 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:14:19 +0200 Subject: [PATCH 079/182] add counterpartymanager --- x/ibc/02-client/manager.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 89a8a878df49..97f281cc9596 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -6,6 +6,8 @@ import ( "github.com/cosmos/cosmos-sdk/store/mapping" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string @@ -24,12 +26,22 @@ type Manager struct { func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/")), - idval: mapping.NewValue(free, []byte("/id")), + protocol: mapping.NewMapping(protocol, []byte("/client")), + idval: mapping.NewValue(free, []byte("/client/id")), idgen: idgen, } } +type CounterpartyManager struct { + protocol commitment.Mapping +} + +func NewCounterpartyManager(protocol commitment.Base) CounterpartyManager { + return CounterpartyManager{ + protocol: commitment.NewMapping(protocol, []byte("/client")), + } +} + /* func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { if _, ok := man.pred[kind]; ok { From 5b089e71a2f7671facd3f28e47d31e829cecc888 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:29:24 +0200 Subject: [PATCH 080/182] fix manager --- x/ibc/02-client/manager.go | 16 ++++++++++++++++ x/ibc/23-commitment/value.go | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 97f281cc9596..c22576b18cd2 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -76,12 +76,28 @@ func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { return res, nil } +func (man CounterpartyManager) object(id string) CounterObject { + return CounterObject{ + id: id, + client: man.protocol.Value([]byte(id)), + } +} + +func (man CounterpartyManager) Query(id string) CounterObject { + return man.object(id) +} + type Object struct { id string client mapping.Value freeze mapping.Boolean } +type CounterObject struct { + id string + client commitment.Value +} + func (obj Object) create(ctx sdk.Context, st Client) error { if obj.exists(ctx) { return errors.New("Create client on already existing id") diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index 70b8502a44e6..10b409b28b99 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -45,6 +45,13 @@ func NewMapping(base Base, prefix []byte) Mapping { } } +func (m Mapping) Value(key []byte) Value { + return Value{ + base: m.base, + key: key, + } +} + type Value struct { base Base key []byte From d0f61b054c4256f540a6da849445c452a24ad8be Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 18:44:25 +0200 Subject: [PATCH 081/182] add Is() to counterobject --- x/ibc/02-client/manager.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index c22576b18cd2..502478104757 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -123,6 +123,10 @@ func (obj Object) Is(ctx sdk.Context, client Client) bool { return obj.client.Is(ctx, client) } +func (obj CounterObject) Is(ctx sdk.Context, client Client) bool { + return obj.client.Is(ctx, client) +} + func (obj Object) Update(ctx sdk.Context, header Header) error { if !obj.exists(ctx) { panic("should not update nonexisting client") From a7b866f438f1e5127b8d1b379e7f2d3167170dc9 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 12 Jun 2019 00:08:04 +0200 Subject: [PATCH 082/182] add readme, reflect ICS02 revision --- x/ibc/02-client/README.md | 49 ++++++++++++++++++++++++++++++++++++++ x/ibc/02-client/manager.go | 31 ++++++++++-------------- x/ibc/02-client/types.go | 26 ++++++++------------ 3 files changed, 72 insertions(+), 34 deletions(-) create mode 100644 x/ibc/02-client/README.md diff --git a/x/ibc/02-client/README.md b/x/ibc/02-client/README.md new file mode 100644 index 000000000000..a9bd6892771b --- /dev/null +++ b/x/ibc/02-client/README.md @@ -0,0 +1,49 @@ +# ICS 02: Client + +Package `client` defines types and method to store and update light clients which tracks on other chain's state. +The main type is `Client`, which provides `commitment.Root` to verify state proofs and `ConsensusState` to +verify header proofs. + +## Spec + +```typescript +interface ConsensusState { + height: uint64 + root: CommitmentRoot + validityPredicate: ValidityPredicate + eqivocationPredicate: EquivocationPredicate +} + +interface ClientState { + consensusState: ConsensusState + verifiedRoots: Map + frozen: bool +} + +interface Header { + height: uint64 + proof: HeaderProof + state: Maybe[ConsensusState] + root: CommitmentRoot +} + +type ValidityPredicate = (ConsensusState, Header) => Error | ConsensusState + +type EquivocationPredicate = (ConsensusState, Header, Header) => bool +``` + +## Impl + +### types.go + +`spec: interface ConsensusState` is implemented by `type ConsensusState`. `ConsensusState.{GetHeight(), GetRoot(), +Validate(), Equivocation()}` each corresponds to `spec: ConsensusState.{height, root, validityPredicate, +equivocationPredicate}`. `ConsensusState.Kind()` returns `Kind`, which is an enum indicating the type of the +consensus algorithm. + +`spec: interface Header` is implemented by `type Header`. `Header{GetHeight(), Proof(), State(), GetRoot()}` +each corresponds to `spec: Header.{height, proof, state, root}`. + +### manager.go + +`spec: interface ClientState` is implemented by `type Object`. // TODO diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 502478104757..0134d8340d55 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -10,6 +10,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) +// XXX: implement spec: ClientState.verifiedRoots + type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { @@ -59,13 +61,14 @@ func (man Manager) object(id string) Object { } } -func (man Manager) Create(ctx sdk.Context, cs Client) string { +func (man Manager) Create(ctx sdk.Context, cs ConsensusState) (Object, error) { id := man.idgen(ctx, man.idval) - err := man.object(id).create(ctx, cs) - if err != nil { - panic(err) + obj := man.object(id) + if obj.exists(ctx) { + return Object{}, errors.New("Create client on already existing id") } - return id + obj.client.Set(ctx, cs) + return obj, nil } func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { @@ -89,7 +92,7 @@ func (man CounterpartyManager) Query(id string) CounterObject { type Object struct { id string - client mapping.Value + client mapping.Value // ConsensusState freeze mapping.Boolean } @@ -98,14 +101,6 @@ type CounterObject struct { client commitment.Value } -func (obj Object) create(ctx sdk.Context, st Client) error { - if obj.exists(ctx) { - return errors.New("Create client on already existing id") - } - obj.client.Set(ctx, st) - return nil -} - func (obj Object) exists(ctx sdk.Context) bool { return obj.client.Exists(ctx) } @@ -114,16 +109,16 @@ func (obj Object) ID() string { return obj.id } -func (obj Object) Value(ctx sdk.Context) (res Client) { +func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { obj.client.Get(ctx, &res) return } -func (obj Object) Is(ctx sdk.Context, client Client) bool { +func (obj Object) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } -func (obj CounterObject) Is(ctx sdk.Context, client Client) bool { +func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } @@ -136,7 +131,7 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { return errors.New("client is frozen") } - var stored Client + var stored ConsensusState obj.client.GetIfExists(ctx, &stored) updated, err := stored.Validate(header) if err != nil { diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go index 7b9f81ec7789..2ae484853354 100644 --- a/x/ibc/02-client/types.go +++ b/x/ibc/02-client/types.go @@ -5,35 +5,29 @@ import ( ) // TODO: types in this file should be (de/)serialized with proto in the future - -type AminoMarshaler interface { - MarshalAmino() (string, error) - UnmarshalAmino(string) error -} - -type ValidityPredicateBase interface { - Kind() Kind - GetHeight() int64 - Equal(ValidityPredicateBase) bool -} +// currently amkno codec handles it // ConsensusState -type Client interface { +type ConsensusState interface { Kind() Kind - GetBase() ValidityPredicateBase + GetHeight() uint64 GetRoot() commitment.Root - Validate(Header) (Client, error) // ValidityPredicate + Validate(Header) (ConsensusState, error) // ValidityPredicate + Equivocation(Header, Header) bool // EquivocationPredicate } -func Equal(client1, client2 Client) bool { +/* +func Equal(client1, client2 ConsensusState) bool { return client1.Kind() == client2.Kind() && client1.GetBase().Equal(client2.GetBase()) } +*/ type Header interface { Kind() Kind + GetHeight() uint64 // Proof() HeaderProof - GetBase() ValidityPredicateBase // can be nil + State() ConsensusState // can be nil GetRoot() commitment.Root } From 392e3abb3f81e0ce383583123389ba4bbd1b62ea Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 12 Jun 2019 00:28:13 +0200 Subject: [PATCH 083/182] reflect downstream ics --- x/ibc/02-client/manager.go | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 0134d8340d55..196d62e62fdc 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -4,7 +4,7 @@ import ( "errors" "strconv" - "github.com/cosmos/cosmos-sdk/store/mapping" + "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" @@ -12,24 +12,24 @@ import ( // XXX: implement spec: ClientState.verifiedRoots -type IDGenerator func(sdk.Context /*Header,*/, mapping.Value) string +type IDGenerator func(sdk.Context /*Header,*/, state.Value) string -func IntegerIDGenerator(ctx sdk.Context, v mapping.Value) string { - id := mapping.NewInteger(v, mapping.Dec).Incr(ctx) +func IntegerIDGenerator(ctx sdk.Context, v state.Value) string { + id := state.NewInteger(v, state.Dec).Incr(ctx) return strconv.FormatUint(id, 10) } type Manager struct { - protocol mapping.Mapping + protocol state.Mapping - idval mapping.Value + idval state.Value idgen IDGenerator } -func NewManager(protocol, free mapping.Base, idgen IDGenerator) Manager { +func NewManager(protocol, free state.Base, idgen IDGenerator) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/client")), - idval: mapping.NewValue(free, []byte("/client/id")), + protocol: state.NewMapping(protocol, []byte("/client")), + idval: state.NewValue(free, []byte("/client/id")), idgen: idgen, } } @@ -57,7 +57,7 @@ func (man Manager) object(id string) Object { return Object{ id: id, client: man.protocol.Value([]byte(id)), - freeze: mapping.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + freeze: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), } } @@ -92,8 +92,8 @@ func (man CounterpartyManager) Query(id string) CounterObject { type Object struct { id string - client mapping.Value // ConsensusState - freeze mapping.Boolean + client state.Value // ConsensusState + freeze state.Boolean } type CounterObject struct { @@ -114,10 +114,6 @@ func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { return } -func (obj Object) Is(ctx sdk.Context, client ConsensusState) bool { - return obj.client.Is(ctx, client) -} - func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } From 5d46c96f54ab118a7994e92150114835f54b2a8b Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 13 Jun 2019 16:00:18 +0200 Subject: [PATCH 084/182] test in progress --- x/ibc/02-client/tendermint/types.go | 96 ++++++----- x/ibc/02-client/tendermint/types_test.go | 131 ++++++++++++++ x/ibc/02-client/tendermint/valset_test.go | 197 ++++++++++++++++++++++ x/ibc/02-client/types.go | 3 - 4 files changed, 386 insertions(+), 41 deletions(-) create mode 100644 x/ibc/02-client/tendermint/types_test.go create mode 100644 x/ibc/02-client/tendermint/valset_test.go diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 54655cf702d4..1442d91d6c99 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -2,78 +2,98 @@ package tendermint import ( "bytes" + "errors" + "fmt" + lerr "github.com/tendermint/tendermint/lite/errors" "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -// Ref tendermint/lite/base_verifier.go - -var _ client.ValidityPredicateBase = ValidityPredicateBase{} +var _ client.ConsensusState = ConsensusState{} -type ValidityPredicateBase struct { - Height int64 +// Ref tendermint/lite/base_verifier.go +type ConsensusState struct { + ChainID string + Height uint64 + Root commitment.Root NextValidatorSet *types.ValidatorSet } -func (ValidityPredicateBase) Kind() client.Kind { +func (ConsensusState) Kind() client.Kind { return client.Tendermint } -func (base ValidityPredicateBase) GetHeight() int64 { - return base.Height +func (cs ConsensusState) GetHeight() uint64 { + return cs.Height } -func (base ValidityPredicateBase) Equal(cbase client.ValidityPredicateBase) bool { - base0, ok := cbase.(ValidityPredicateBase) - if !ok { - return false +func (cs ConsensusState) GetRoot() commitment.Root { + return cs.Root +} + +func (cs ConsensusState) update(header Header) ConsensusState { + return ConsensusState{ + ChainID: cs.ChainID, + Height: uint64(header.Height), + Root: header.AppHash, + NextValidatorSet: header.NextValidatorSet, } - return base.Height == base0.Height && - bytes.Equal(base.NextValidatorSet.Hash(), base0.NextValidatorSet.Hash()) } -var _ client.Client = Client{} +func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, error) { + header, ok := cheader.(Header) + if !ok { + return nil, errors.New("invalid type") + } -type Client struct { - Base ValidityPredicateBase - Root commitment.Root -} + nextvalset := cs.NextValidatorSet + nexthash := nextvalset.Hash() -func (Client) Kind() client.Kind { - return client.Tendermint -} + if cs.Height == uint64(header.Height-1) { + nexthash = cs.NextValidatorSet.Hash() + if !bytes.Equal(header.ValidatorsHash, nexthash) { + fmt.Println(111) + return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) + } + } -func (client Client) GetBase() client.ValidityPredicateBase { - return client.Base -} + if !bytes.Equal(header.NextValidatorsHash, header.NextValidatorSet.Hash()) { + fmt.Println(header) + return nil, lerr.ErrUnexpectedValidators(header.NextValidatorsHash, header.NextValidatorSet.Hash()) + } + + err := header.ValidateBasic(cs.ChainID) + if err != nil { + return nil, err + } -func (client Client) GetRoot() commitment.Root { - return client.Root + err = cs.NextValidatorSet.VerifyCommit(cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) + if err != nil { + return nil, err + } + + return cs.update(header), nil } -func (client Client) Validate(header client.Header) (client.Client, error) { - return client, nil // XXX +func (cs ConsensusState) Equivocation(header1, header2 client.Header) bool { + return false // XXX } var _ client.Header = Header{} type Header struct { - Base ValidityPredicateBase - Root commitment.Root - Votes []*types.CommitSig + // XXX: don't take the entire struct + types.SignedHeader + NextValidatorSet *types.ValidatorSet } func (header Header) Kind() client.Kind { return client.Tendermint } -func (header Header) GetBase() client.ValidityPredicateBase { - return header.Base -} - -func (header Header) GetRoot() commitment.Root { - return header.Root +func (header Header) GetHeight() uint64 { + return uint64(header.Height) } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go new file mode 100644 index 000000000000..44dc0fc9aba9 --- /dev/null +++ b/x/ibc/02-client/tendermint/types_test.go @@ -0,0 +1,131 @@ +package tendermint + +import ( + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/tendermint/tendermint/abci/types" + dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/libs/log" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store" + stypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const chainid = "testchain" + +func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { + key := sdk.NewKVStoreKey("ibc") + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) + err := cms.LoadLatestVersion() + if err != nil { + panic(err) + } + ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger()) + cdc := codec.New() + return key, ctx, cms, cdc +} + +type node struct { + valset MockValidators + + cms sdk.CommitMultiStore + store sdk.KVStore + + commits []tmtypes.SignedHeader +} + +func NewNode(valset MockValidators) *node { + key, ctx, cms, _ := defaultComponents() + return &node{ + valset: valset, + cms: cms, + store: ctx.KVStore(key), + commits: nil, + } +} + +func (node *node) last() tmtypes.SignedHeader { + if len(node.commits) == 0 { + return tmtypes.SignedHeader{} + } + return node.commits[len(node.commits)-1] +} + +func (node *node) Commit() tmtypes.SignedHeader { + valsethash := node.valset.ValidatorSet().Hash() + nextvalset := node.valset.Mutate(false) + nextvalsethash := nextvalset.ValidatorSet().Hash() + commitid := node.cms.Commit() + + header := tmtypes.Header{ + ChainID: chainid, + Height: int64(len(node.commits) + 1), + LastBlockID: tmtypes.BlockID{ + Hash: node.last().Header.Hash(), + }, + + ValidatorsHash: valsethash, + NextValidatorsHash: nextvalsethash, + AppHash: commitid.Hash, + } + + commit := node.valset.Sign(header) + + node.commits = append(node.commits, commit) + + return commit +} + +func (node *node) Set(key, value string) { + node.store.Set(append([]byte{0x00}, []byte(key)...), []byte(value)) +} + +type Verifier struct { + ConsensusState +} + +func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifier { + return &Verifier{ + ConsensusState{ + ChainID: chainid, + Height: uint64(header.Height), + Root: header.AppHash, + NextValidatorSet: nextvalset.ValidatorSet(), + }, + } +} + +func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidators) error { + newcs, err := v.ConsensusState.Validate( + Header{ + SignedHeader: header, + NextValidatorSet: nextvalset.ValidatorSet(), + }, + ) + if err != nil { + return err + } + v.ConsensusState = newcs.(ConsensusState) + + return nil +} + +func TestUpdate(t *testing.T) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + verifier := NewVerifier(node.last(), node.valset) + + header := node.Commit() + + err := verifier.Validate(header, node.valset) + require.NoError(t, err) +} diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/valset_test.go new file mode 100644 index 000000000000..10aa5dc0eae7 --- /dev/null +++ b/x/ibc/02-client/tendermint/valset_test.go @@ -0,0 +1,197 @@ +package tendermint + +import ( + "bytes" + "fmt" + "sort" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + tmtypes "github.com/tendermint/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// reimplementing tmtypes.MockPV to make it marshallable +type mockPV struct { + PrivKey crypto.PrivKey +} + +var _ tmtypes.PrivValidator = (*mockPV)(nil) + +func newMockPV() *mockPV { + return &mockPV{ed25519.GenPrivKey()} +} + +func (pv *mockPV) GetAddress() tmtypes.Address { + return pv.PrivKey.PubKey().Address() +} + +func (pv *mockPV) GetPubKey() crypto.PubKey { + return pv.PrivKey.PubKey() +} + +func (pv *mockPV) SignVote(chainID string, vote *tmtypes.Vote) error { + signBytes := vote.SignBytes(chainID) + sig, err := pv.PrivKey.Sign(signBytes) + if err != nil { + return err + } + vote.Signature = sig + return nil +} + +func (pv *mockPV) SignProposal(string, *tmtypes.Proposal) error { + panic("not needed") +} + +// MockValset +type MockValidator struct { + MockPV *mockPV + Power sdk.Dec +} + +func NewMockValidator(power sdk.Dec) MockValidator { + return MockValidator{ + MockPV: newMockPV(), + Power: power, + } +} + +func (val MockValidator) GetOperator() sdk.ValAddress { + return sdk.ValAddress(val.MockPV.GetAddress()) +} + +func (val MockValidator) GetConsAddr() sdk.ConsAddress { + return sdk.GetConsAddress(val.MockPV.GetPubKey()) +} + +func (val MockValidator) GetConsPubKey() crypto.PubKey { + return val.MockPV.GetPubKey() +} + +func (val MockValidator) GetPower() sdk.Dec { + return val.Power +} + +func (val MockValidator) Validator() *tmtypes.Validator { + return tmtypes.NewValidator( + val.GetConsPubKey(), + val.GetPower().RoundInt64(), + ) +} + +type MockValidators []MockValidator + +var _ sort.Interface = MockValidators{} + +func NewMockValidators(num int, power int64) MockValidators { + res := make(MockValidators, num) + for i := range res { + res[i] = NewMockValidator(sdk.NewDec(power)) + } + + // ddd + fmt.Println(333) + for _, val := range res { + fmt.Println(val) + } + + // ddd + return res +} + +func (vals MockValidators) Len() int { + return len(vals) +} + +func (vals MockValidators) Less(i, j int) bool { + return bytes.Compare([]byte(vals[i].GetConsAddr()), []byte(vals[j].GetConsAddr())) == -1 +} + +func (vals MockValidators) Swap(i, j int) { + it := vals[j] + vals[j] = vals[i] + vals[i] = it +} + +func (vals MockValidators) TotalPower() sdk.Dec { + res := sdk.ZeroDec() + for _, val := range vals { + res = res.Add(val.Power) + } + return res +} + +func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { + precommits := make([]*tmtypes.CommitSig, len(vals)) + for i, val := range vals { + precommits[i] = (&tmtypes.Vote{ + BlockID: tmtypes.BlockID{ + Hash: header.Hash(), + }, + ValidatorAddress: val.MockPV.GetAddress(), + ValidatorIndex: i, + Height: header.Height, + Type: tmtypes.PrecommitType, + }).CommitSig() + val.MockPV.SignVote("", (*tmtypes.Vote)(precommits[i])) + } + + return tmtypes.SignedHeader{ + Header: &header, + Commit: &tmtypes.Commit{ + BlockID: tmtypes.BlockID{ + Hash: header.Hash(), + }, + Precommits: precommits, + }, + } +} + +// Mutate valset +func (vals MockValidators) Mutate(majority bool) MockValidators { + var num int + if majority { + num = len(vals) * 2 / 3 + } else { + num = len(vals) * 1 / 6 + } + + res := make(MockValidators, len(vals)) + + for i := 0; i < len(vals)-num; i++ { + res[i] = vals[num:][i] + } + + for i := len(vals) - num; i < len(vals); i++ { + res[i] = NewMockValidator(vals[0].Power) + } + + // ddd + fmt.Println(333) + for _, val := range res { + fmt.Println(val) + } + + // ddd + + return res +} + +func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { + tmvals := make([]*tmtypes.Validator, len(vals)) + + for i, val := range vals { + tmvals[i] = val.Validator() + } + + // ddd + fmt.Println(333444) + for _, val := range tmvals { + fmt.Println(val) + } + + // ddd + return tmtypes.NewValidatorSet(tmvals) +} diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go index 2ae484853354..2a34855085b9 100644 --- a/x/ibc/02-client/types.go +++ b/x/ibc/02-client/types.go @@ -26,9 +26,6 @@ func Equal(client1, client2 ConsensusState) bool { type Header interface { Kind() Kind GetHeight() uint64 - // Proof() HeaderProof - State() ConsensusState // can be nil - GetRoot() commitment.Root } // XXX: Kind should be enum? From b934d57bc256a81d61e29ab658a46062eb4a9dc4 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 13 Jun 2019 19:08:13 +0200 Subject: [PATCH 085/182] add test --- x/ibc/02-client/tendermint/types.go | 6 +- x/ibc/02-client/tendermint/types_test.go | 108 +++++++++++++++++++--- x/ibc/02-client/tendermint/valset_test.go | 46 +++------ 3 files changed, 114 insertions(+), 46 deletions(-) diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 1442d91d6c99..8dd3cfca7294 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -3,7 +3,6 @@ package tendermint import ( "bytes" "errors" - "fmt" lerr "github.com/tendermint/tendermint/lite/errors" "github.com/tendermint/tendermint/types" @@ -55,13 +54,11 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, if cs.Height == uint64(header.Height-1) { nexthash = cs.NextValidatorSet.Hash() if !bytes.Equal(header.ValidatorsHash, nexthash) { - fmt.Println(111) return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) } } if !bytes.Equal(header.NextValidatorsHash, header.NextValidatorSet.Hash()) { - fmt.Println(header) return nil, lerr.ErrUnexpectedValidators(header.NextValidatorsHash, header.NextValidatorSet.Hash()) } @@ -70,7 +67,7 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, return nil, err } - err = cs.NextValidatorSet.VerifyCommit(cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) + err = cs.NextValidatorSet.VerifyFutureCommit(header.ValidatorSet, cs.ChainID, header.Commit.BlockID, header.Height, header.Commit) if err != nil { return nil, err } @@ -87,6 +84,7 @@ var _ client.Header = Header{} type Header struct { // XXX: don't take the entire struct types.SignedHeader + ValidatorSet *types.ValidatorSet NextValidatorSet *types.ValidatorSet } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 44dc0fc9aba9..14ca7adad0ea 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -1,11 +1,13 @@ package tendermint import ( + "math/rand" "testing" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" tmtypes "github.com/tendermint/tendermint/types" @@ -14,6 +16,9 @@ import ( "github.com/cosmos/cosmos-sdk/store" stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) const chainid = "testchain" @@ -33,7 +38,8 @@ func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *c } type node struct { - valset MockValidators + prevvalset MockValidators + valset MockValidators cms sdk.CommitMultiStore store sdk.KVStore @@ -60,7 +66,7 @@ func (node *node) last() tmtypes.SignedHeader { func (node *node) Commit() tmtypes.SignedHeader { valsethash := node.valset.ValidatorSet().Hash() - nextvalset := node.valset.Mutate(false) + nextvalset := node.valset.Mutate() nextvalsethash := nextvalset.ValidatorSet().Hash() commitid := node.cms.Commit() @@ -78,15 +84,13 @@ func (node *node) Commit() tmtypes.SignedHeader { commit := node.valset.Sign(header) + node.prevvalset = node.valset + node.valset = nextvalset node.commits = append(node.commits, commit) return commit } -func (node *node) Set(key, value string) { - node.store.Set(append([]byte{0x00}, []byte(key)...), []byte(value)) -} - type Verifier struct { ConsensusState } @@ -102,10 +106,11 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifi } } -func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidators) error { +func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset MockValidators) error { newcs, err := v.ConsensusState.Validate( Header{ SignedHeader: header, + ValidatorSet: valset.ValidatorSet(), NextValidatorSet: nextvalset.ValidatorSet(), }, ) @@ -117,15 +122,96 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, nextvalset MockValidato return nil } -func TestUpdate(t *testing.T) { +func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10)) node.Commit() verifier := NewVerifier(node.last(), node.valset) - header := node.Commit() + for i := 0; i < 100; i++ { + header := node.Commit() + + if i%interval == 0 { + err := verifier.Validate(header, node.prevvalset, node.valset) + if ok { + require.NoError(t, err) + } else { + require.Error(t, err) + } + } + } +} + +func TestEveryBlockUpdate(t *testing.T) { + testUpdate(t, 1, true) +} + +func TestEvenBlockUpdate(t *testing.T) { + testUpdate(t, 2, true) +} + +func TestSixthBlockUpdate(t *testing.T) { + testUpdate(t, 6, true) +} + +/* +// This should fail, since the amount of mutation is so large +// Commented out because it sometimes success +func TestTenthBlockUpdate(t *testing.T) { + testUpdate(t, 10, false) +} +*/ + +func key(str []byte) []byte { + return append([]byte{0x00}, str...) +} + +func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { + qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/ibc/key", Data: key(k), Prove: true}) + require.Equal(t, uint32(0), qres.Code, qres.Log) + proof := merkle.Proof{ + Key: []byte(k), + Proof: qres.Proof, + } + return qres.Value, proof +} + +func (node *node) Set(k, value []byte) { + node.store.Set(key(k), value) +} + +func testProof(t *testing.T) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + kvps := cmn.KVPairs{} + for h := 0; h < 20; h++ { + for i := 0; i < 100; i++ { + k := make([]byte, 32) + v := make([]byte, 32) + rand.Read(k) + rand.Read(v) + kvps = append(kvps, cmn.KVPair{Key: k, Value: v}) + node.Set(k, v) + } + header := node.Commit() + proofs := []commitment.Proof{} + for _, kvp := range kvps { + v, p := node.query(t, []byte(kvp.Key)) + require.Equal(t, kvp.Value, v) + proofs = append(proofs, p) + } + cstore, err := commitment.NewStore([]byte(header.AppHash), proofs) + require.NoError(t, err) + + for _, kvp := range kvps { + require.True(t, cstore.Prove(kvp.Key, kvp.Value)) + } + } +} - err := verifier.Validate(header, node.valset) - require.NoError(t, err) +func TestProofs(t *testing.T) { + testProof(t) } diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/valset_test.go index 10aa5dc0eae7..5649a3533273 100644 --- a/x/ibc/02-client/tendermint/valset_test.go +++ b/x/ibc/02-client/tendermint/valset_test.go @@ -2,7 +2,6 @@ package tendermint import ( "bytes" - "fmt" "sort" "github.com/tendermint/tendermint/crypto" @@ -91,13 +90,8 @@ func NewMockValidators(num int, power int64) MockValidators { res[i] = NewMockValidator(sdk.NewDec(power)) } - // ddd - fmt.Println(333) - for _, val := range res { - fmt.Println(val) - } + sort.Sort(res) - // ddd return res } @@ -124,9 +118,10 @@ func (vals MockValidators) TotalPower() sdk.Dec { } func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { + precommits := make([]*tmtypes.CommitSig, len(vals)) for i, val := range vals { - precommits[i] = (&tmtypes.Vote{ + vote := &tmtypes.Vote{ BlockID: tmtypes.BlockID{ Hash: header.Hash(), }, @@ -134,8 +129,9 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { ValidatorIndex: i, Height: header.Height, Type: tmtypes.PrecommitType, - }).CommitSig() - val.MockPV.SignVote("", (*tmtypes.Vote)(precommits[i])) + } + val.MockPV.SignVote(chainid, vote) + precommits[i] = vote.CommitSig() } return tmtypes.SignedHeader{ @@ -150,13 +146,8 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { } // Mutate valset -func (vals MockValidators) Mutate(majority bool) MockValidators { - var num int - if majority { - num = len(vals) * 2 / 3 - } else { - num = len(vals) * 1 / 6 - } +func (vals MockValidators) Mutate() MockValidators { + num := len(vals) / 20 // 5% change each block res := make(MockValidators, len(vals)) @@ -168,15 +159,15 @@ func (vals MockValidators) Mutate(majority bool) MockValidators { res[i] = NewMockValidator(vals[0].Power) } - // ddd - fmt.Println(333) - for _, val := range res { - fmt.Println(val) - } + sort.Sort(res) - // ddd + for i, val := range vals { + if val != res[i] { + return res + } + } - return res + panic("not mutated") } func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { @@ -186,12 +177,5 @@ func (vals MockValidators) ValidatorSet() *tmtypes.ValidatorSet { tmvals[i] = val.Validator() } - // ddd - fmt.Println(333444) - for _, val := range tmvals { - fmt.Println(val) - } - - // ddd return tmtypes.NewValidatorSet(tmvals) } From 2ac7d8c0482d9d56af262adb47d44dec6c8d99d1 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 19 Jun 2019 13:07:06 +0100 Subject: [PATCH 086/182] in progres --- x/ibc/client/cli/query.go | 216 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 x/ibc/client/cli/query.go diff --git a/x/ibc/client/cli/query.go b/x/ibc/client/cli/query.go new file mode 100644 index 000000000000..ca979151c499 --- /dev/null +++ b/x/ibc/client/cli/query.go @@ -0,0 +1,216 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" + ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" +) + +func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcQueryCmd := &cobra.Command{ + Use: "ibc", + Short: "IBC query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcQueryCmd.AddCommand(client.GetCommands( + GetCmdQueryConsensusState(cdc), + GetCmdQueryHeader(cdc), + GetCmdQueryClient(cdc), + GetCmdQueryConnection(cdc), + GetCmdQueryChannel(cdc), + )...) + return ibcQueryCmd +} + +func GetCmdQueryClient(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "client", + Short: "Query stored client", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var state ibc.ConsensusState + statebz, _, err := query(ctx, keeper.Client.Object(args[0]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(statebz, &state) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryConsensusState(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "consensus-state", + Short: "Query the latest consensus state of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + state := tendermint.ConsensusState{ + ChainID: commit.ChainID, + Height: uint64(commit.Height), + Root: []byte(commit.AppHash), + NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "header", + Short: "Query the latest header of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + nextvalidators, err := node.Validators(&height) + if err != nil { + return err + } + + header := tendermint.Header{ + SignedHeader: commit.SignedHeader, + ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) + + return nil + }, + } +} + +func GetCmdQueryConnection(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "connection", + Short: "Query an existing connection", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var conn ibc.Connection + connbz, _, err := query(ctx, keeper.Connection.Object(args[0]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(connbz, &conn) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) + + return nil + }, + } +} + +func GetCmdQueryChannel(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "channel", + Short: "Query an existing channel", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + keeper := ibc.DummyKeeper() + + var conn ibc.Channel + connbz, _, err := query(ctx, keeper.Channel.Object(args[0], args[1]).Key()) + if err != nil { + return err + } + cdc.MustUnmarshalBinaryBare(connbz, &conn) + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) + + return nil + }, + } +} + +func GetCmdQuerySendSequence(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "send-sequence", + Short: "Query the send sequence of a channel", + Args: cobra.ExactArgs(), + RunE: func(cmd *cobra.Command, args []string) error { + + }, + } +} + +func GetCmdQueryReceiveSequence(cdc *codec.Codec) *cobra.Command { + +} + +func GetCmdQueryPacket(cdc *codec.Codec) *cobra.Command { +} From a5d86b7c627f806d25a1f7d47942c4b6e0eaefcf Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 12:20:15 +0200 Subject: [PATCH 087/182] fin rebase --- x/ibc/02-client/tendermint/types.go | 2 +- x/ibc/02-client/tendermint/types_test.go | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 8dd3cfca7294..26a4c35370e6 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -37,7 +37,7 @@ func (cs ConsensusState) update(header Header) ConsensusState { return ConsensusState{ ChainID: cs.ChainID, Height: uint64(header.Height), - Root: header.AppHash, + Root: cs.GetRoot().Update(header.AppHash), NextValidatorSet: header.NextValidatorSet, } } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 14ca7adad0ea..8bde76d10302 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -24,7 +24,7 @@ import ( const chainid = "testchain" func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { - key := sdk.NewKVStoreKey("ibc") + key := sdk.NewKVStoreKey("test") db := dbm.NewMemDB() cms := store.NewCommitMultiStore(db) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) @@ -91,6 +91,13 @@ func (node *node) Commit() tmtypes.SignedHeader { return commit } +func keyPrefix() [][]byte { + return [][]byte{ + []byte("test"), + []byte{0x00}, + } +} + type Verifier struct { ConsensusState } @@ -100,7 +107,7 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifi ConsensusState{ ChainID: chainid, Height: uint64(header.Height), - Root: header.AppHash, + Root: merkle.NewRoot(header.AppHash, keyPrefix()), NextValidatorSet: nextvalset.ValidatorSet(), }, } @@ -168,7 +175,7 @@ func key(str []byte) []byte { } func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { - qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/ibc/key", Data: key(k), Prove: true}) + qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/test/key", Data: key(k), Prove: true}) require.Equal(t, uint32(0), qres.Code, qres.Log) proof := merkle.Proof{ Key: []byte(k), @@ -203,7 +210,7 @@ func testProof(t *testing.T) { require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore([]byte(header.AppHash), proofs) + cstore, err := commitment.NewStore(merkle.NewRoot([]byte(header.AppHash), keyPrefix()), proofs) require.NoError(t, err) for _, kvp := range kvps { From acd44f3067b751f7bc4ee3137fb00ef7aa663468 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 16:07:00 +0200 Subject: [PATCH 088/182] in progress --- x/ibc/02-client/cli.go | 18 ++++++++++ x/ibc/02-client/manager.go | 34 ++++++++++--------- x/ibc/02-client/tendermint/types_test.go | 42 ++++++++++-------------- 3 files changed, 54 insertions(+), 40 deletions(-) create mode 100644 x/ibc/02-client/cli.go diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go new file mode 100644 index 000000000000..5c245ba0378e --- /dev/null +++ b/x/ibc/02-client/cli.go @@ -0,0 +1,18 @@ +package client + +import () + +// CLIObject stores the key for each object fields +type CLIObject struct { + ID string + ConsensusState []byte + Frozen []byte +} + +func (object Object) CLI() CLIObject { + return CLIObject{ + ID: object.id, + ConsensusState: object.consensusState.Key(), + Frozen: object.frozen.Key(), + } +} diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 196d62e62fdc..a99a4bcc785c 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -55,9 +55,9 @@ func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { */ func (man Manager) object(id string) Object { return Object{ - id: id, - client: man.protocol.Value([]byte(id)), - freeze: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + id: id, + consensusState: man.protocol.Value([]byte(id)), + frozen: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), } } @@ -67,7 +67,7 @@ func (man Manager) Create(ctx sdk.Context, cs ConsensusState) (Object, error) { if obj.exists(ctx) { return Object{}, errors.New("Create client on already existing id") } - obj.client.Set(ctx, cs) + obj.consensusState.Set(ctx, cs) return obj, nil } @@ -91,9 +91,9 @@ func (man CounterpartyManager) Query(id string) CounterObject { } type Object struct { - id string - client state.Value // ConsensusState - freeze state.Boolean + id string + consensusState state.Value // ConsensusState + frozen state.Boolean } type CounterObject struct { @@ -101,34 +101,38 @@ type CounterObject struct { client commitment.Value } -func (obj Object) exists(ctx sdk.Context) bool { - return obj.client.Exists(ctx) -} - func (obj Object) ID() string { return obj.id } -func (obj Object) Value(ctx sdk.Context) (res ConsensusState) { - obj.client.Get(ctx, &res) +func (obj Object) ConsensusState(ctx sdk.Context) (res ConsensusState) { + obj.consensusState.Get(ctx, &res) return } +func (obj Object) Frozen(ctx sdk.Context) bool { + return obj.frozen.Get(ctx) +} + func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.client.Is(ctx, client) } +func (obj Object) exists(ctx sdk.Context) bool { + return obj.consensusState.Exists(ctx) +} + func (obj Object) Update(ctx sdk.Context, header Header) error { if !obj.exists(ctx) { panic("should not update nonexisting client") } - if obj.freeze.Get(ctx) { + if obj.Frozen(ctx) { return errors.New("client is frozen") } var stored ConsensusState - obj.client.GetIfExists(ctx, &stored) + obj.client.Get(ctx, &stored) updated, err := stored.Validate(header) if err != nil { return err diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 8bde76d10302..3cb99f52b549 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -91,23 +91,16 @@ func (node *node) Commit() tmtypes.SignedHeader { return commit } -func keyPrefix() [][]byte { - return [][]byte{ - []byte("test"), - []byte{0x00}, - } -} - type Verifier struct { ConsensusState } -func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators) *Verifier { +func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root merkle.Root) *Verifier { return &Verifier{ ConsensusState{ ChainID: chainid, Height: uint64(header.Height), - Root: merkle.NewRoot(header.AppHash, keyPrefix()), + Root: root.Update(header.AppHash), NextValidatorSet: nextvalset.ValidatorSet(), }, } @@ -129,12 +122,18 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock return nil } +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10)) node.Commit() - verifier := NewVerifier(node.last(), node.valset) + root := newRoot() + + verifier := NewVerifier(node.last(), node.valset, root) for i := 0; i < 100; i++ { header := node.Commit() @@ -170,22 +169,14 @@ func TestTenthBlockUpdate(t *testing.T) { } */ -func key(str []byte) []byte { - return append([]byte{0x00}, str...) -} - -func (node *node) query(t *testing.T, k []byte) ([]byte, commitment.Proof) { - qres := node.cms.(stypes.Queryable).Query(abci.RequestQuery{Path: "/test/key", Data: key(k), Prove: true}) - require.Equal(t, uint32(0), qres.Code, qres.Log) - proof := merkle.Proof{ - Key: []byte(k), - Proof: qres.Proof, - } - return qres.Value, proof +func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { + code, value, proof := root.Query(node.cms, k) + require.Equal(t, uint32(0), code) + return value, proof } func (node *node) Set(k, value []byte) { - node.store.Set(key(k), value) + node.store.Set(newRoot().Key(k), value) } func testProof(t *testing.T) { @@ -205,12 +196,13 @@ func testProof(t *testing.T) { } header := node.Commit() proofs := []commitment.Proof{} + root := newRoot().Update(header.AppHash) for _, kvp := range kvps { - v, p := node.query(t, []byte(kvp.Key)) + v, p := node.query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore(merkle.NewRoot([]byte(header.AppHash), keyPrefix()), proofs) + cstore, err := commitment.NewStore(root, proofs) require.NoError(t, err) for _, kvp := range kvps { From 582fd6ddd1778845fc05e8228b9a2f5b0d51b959 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 16:15:17 +0200 Subject: [PATCH 089/182] fin rebase --- x/ibc/02-client/manager.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index a99a4bcc785c..e94d14702b72 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -81,8 +81,8 @@ func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { func (man CounterpartyManager) object(id string) CounterObject { return CounterObject{ - id: id, - client: man.protocol.Value([]byte(id)), + id: id, + consensusState: man.protocol.Value([]byte(id)), } } @@ -97,8 +97,8 @@ type Object struct { } type CounterObject struct { - id string - client commitment.Value + id string + consensusState commitment.Value } func (obj Object) ID() string { @@ -115,7 +115,7 @@ func (obj Object) Frozen(ctx sdk.Context) bool { } func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { - return obj.client.Is(ctx, client) + return obj.consensusState.Is(ctx, client) } func (obj Object) exists(ctx sdk.Context) bool { @@ -132,13 +132,13 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { } var stored ConsensusState - obj.client.Get(ctx, &stored) + obj.consensusState.Get(ctx, &stored) updated, err := stored.Validate(header) if err != nil { return err } - obj.client.Set(ctx, updated) + obj.consensusState.Set(ctx, updated) return nil } @@ -148,11 +148,11 @@ func (obj Object) Freeze(ctx sdk.Context) error { panic("should not freeze nonexisting client") } - if obj.freeze.Get(ctx) { + if obj.Frozen(ctx) { return errors.New("client is already frozen") } - obj.freeze.Set(ctx, true) + obj.frozen.Set(ctx, true) return nil } @@ -162,12 +162,12 @@ func (obj Object) Delete(ctx sdk.Context) error { panic("should not delete nonexisting client") } - if !obj.freeze.Get(ctx) { + if !obj.Frozen(ctx) { return errors.New("client is not frozen") } - obj.client.Delete(ctx) - obj.freeze.Delete(ctx) + obj.consensusState.Delete(ctx) + obj.frozen.Delete(ctx) return nil } From cb3081df2603576a06b837709b4390d3e3eb5ae0 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 17:10:21 +0200 Subject: [PATCH 090/182] add CLIObject in progress --- client/context/query.go | 38 ++++++++++++++++++++++++-------------- x/ibc/02-client/cli.go | 24 ++++++++++++++++-------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 87f96aece166..1e52442c6c61 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,21 +31,31 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) ([]byte, int64, error) { - return ctx.query(path, nil) +func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { + val, _, height, err = ctx.query(path, nil) + return } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { - return ctx.query(path, data) +func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { + val, _, height, err = ctx.query(path, data) + return } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { + val, _, height, err = ctx.queryStore(key, storeName, "key") + return +} + +// QueryProof performs a query to a Tendermint node with the provided key and +// store name. It returns the result, the proof, and height of the query +// upon success or an error if the query fails. +func (ctx CLIContext) QueryProof(key cmn.HexBytes, storeName string) (val []byte, proof *merkle.Proof, height int64, err error) { return ctx.queryStore(key, storeName, "key") } @@ -53,7 +63,7 @@ func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, in // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, height int64, err error) { - resRaw, height, err := ctx.queryStore(subspace, storeName, "subspace") + resRaw, _, height, err := ctx.queryStore(subspace, storeName, "subspace") if err != nil { return res, height, err } @@ -75,10 +85,10 @@ func (ctx CLIContext) GetFromName() string { // query performs a query to a Tendermint node with the provided store name // and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height int64, err error) { +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *merkle.Proof, height int64, err error) { node, err := ctx.GetNode() if err != nil { - return res, height, err + return res, proof, height, err } opts := rpcclient.ABCIQueryOptions{ @@ -88,25 +98,25 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height i result, err := node.ABCIQueryWithOptions(path, key, opts) if err != nil { - return res, height, err + return res, proof, height, err } resp := result.Response if !resp.IsOK() { - return res, height, errors.New(resp.Log) + return res, proof, height, errors.New(resp.Log) } // data from trusted node or subspace query doesn't need verification if ctx.TrustNode || !isQueryStoreWithProof(path) { - return resp.Value, resp.Height, nil + return resp.Value, resp.Proof, resp.Height, nil } err = ctx.verifyProof(path, resp) if err != nil { - return res, height, err + return res, proof, height, err } - return resp.Value, resp.Height, nil + return resp.Value, resp.Proof, resp.Height, nil } // Verify verifies the consensus proof at given height. @@ -165,7 +175,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) { +func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, *merkle.Proof, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 5c245ba0378e..8767c3032724 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -1,18 +1,26 @@ package client -import () +import ( + "github.com/cosmos/cosmos-sdk/client/context" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) // CLIObject stores the key for each object fields type CLIObject struct { - ID string - ConsensusState []byte - Frozen []byte + ID string + ConsensusStateKey []byte + FrozenKey []byte } -func (object Object) CLI() CLIObject { +func (obj Object) CLI() CLIObject { return CLIObject{ - ID: object.id, - ConsensusState: object.consensusState.Key(), - Frozen: object.frozen.Key(), + ID: obj.id, + ConsensusStateKey: obj.consensusState.Key(), + FrozenKey: obj.frozen.Key(), } } + +func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle..Proof) { + val, proof, _, err := ctx.QueryProof(obj.ConsensusStateKey) +} From e48fd1c2bd9eee01986028b0476e73716554321a Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:19:42 +0200 Subject: [PATCH 091/182] cli in progress --- client/context/query.go | 69 +++++++++++++++++++++++------------------ store/state/types.go | 5 +++ x/ibc/02-client/cli.go | 34 ++++++++++++++++++-- 3 files changed, 76 insertions(+), 32 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 1e52442c6c61..4738808ba4fe 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,39 +31,35 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { - val, _, height, err = ctx.query(path, nil) - return +func (ctx CLIContext) Query(path string) ([]byte, int64, error) { + return ctx.query(path, nil) } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { - val, _, height, err = ctx.query(path, data) - return +func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { + return ctx.query(path, data) } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { - val, _, height, err = ctx.queryStore(key, storeName, "key") - return +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { + return ctx.queryStore(key, storeName, "key") } -// QueryProof performs a query to a Tendermint node with the provided key and -// store name. It returns the result, the proof, and height of the query -// upon success or an error if the query fails. -func (ctx CLIContext) QueryProof(key cmn.HexBytes, storeName string) (val []byte, proof *merkle.Proof, height int64, err error) { - return ctx.queryStore(key, storeName, "key") +// QueryABCI performs a query to a Tendermint node with the provide RequestQuery. +// It returns the ResultQuery obtained from the query. +func (ctx CLIContext) QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) { + return ctx.queryABCI(req) } // QuerySubspace performs a query to a Tendermint node with the provided // store name and subspace. It returns key value pair and height of the query // upon success or an error if the query fails. func (ctx CLIContext) QuerySubspace(subspace []byte, storeName string) (res []sdk.KVPair, height int64, err error) { - resRaw, _, height, err := ctx.queryStore(subspace, storeName, "subspace") + resRaw, height, err := ctx.queryStore(subspace, storeName, "subspace") if err != nil { return res, height, err } @@ -82,13 +78,10 @@ func (ctx CLIContext) GetFromName() string { return ctx.FromName } -// query performs a query to a Tendermint node with the provided store name -// and path. It returns the result and height of the query upon success -// or an error if the query fails. -func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *merkle.Proof, height int64, err error) { +func (ctx CLIContext) queryABCI(req abci.RequestQuery) (resp abci.ResponseQuery, err error) { node, err := ctx.GetNode() if err != nil { - return res, proof, height, err + return } opts := rpcclient.ABCIQueryOptions{ @@ -96,27 +89,43 @@ func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, proof *m Prove: !ctx.TrustNode, } - result, err := node.ABCIQueryWithOptions(path, key, opts) + result, err := node.ABCIQueryWithOptions(req.Path, req.Data, opts) if err != nil { - return res, proof, height, err + return } - resp := result.Response + resp = result.Response if !resp.IsOK() { - return res, proof, height, errors.New(resp.Log) + err = errors.New(resp.Log) + return } // data from trusted node or subspace query doesn't need verification - if ctx.TrustNode || !isQueryStoreWithProof(path) { - return resp.Value, resp.Proof, resp.Height, nil + if ctx.TrustNode || !isQueryStoreWithProof(req.Path) { + return resp, nil } - err = ctx.verifyProof(path, resp) + err = ctx.verifyProof(req.Path, resp) + if err != nil { + return + } + + return +} + +// query performs a query to a Tendermint node with the provided store name +// and path. It returns the result and height of the query upon success +// or an error if the query fails. +func (ctx CLIContext) query(path string, key cmn.HexBytes) (res []byte, height int64, err error) { + resp, err := ctx.queryABCI(abci.RequestQuery{ + Path: path, + Data: key, + }) if err != nil { - return res, proof, height, err + return } - return resp.Value, resp.Proof, resp.Height, nil + return resp.Value, resp.Height, nil } // Verify verifies the consensus proof at given height. @@ -175,7 +184,7 @@ func (ctx CLIContext) verifyProof(queryPath string, resp abci.ResponseQuery) err // queryStore performs a query to a Tendermint node with the provided a store // name and path. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, *merkle.Proof, int64, error) { +func (ctx CLIContext) queryStore(key cmn.HexBytes, storeName, endPath string) ([]byte, int64, error) { path := fmt.Sprintf("/store/%s/%s", storeName, endPath) return ctx.query(path, key) } diff --git a/store/state/types.go b/store/state/types.go index a8d34d582a82..f5dbb4dc8648 100644 --- a/store/state/types.go +++ b/store/state/types.go @@ -1,8 +1,13 @@ package state import ( + "github.com/tendermint/tendermint/crypto/merkle" + + "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" ) type KVStore = sdk.KVStore type Context = sdk.Context +type CLIContext = context.CLIContext +type Proof = merkle.Proof diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 8767c3032724..f51b882e7725 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -2,6 +2,7 @@ package client import ( "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -11,6 +12,7 @@ type CLIObject struct { ID string ConsensusStateKey []byte FrozenKey []byte + Cdc *codec.Codec } func (obj Object) CLI() CLIObject { @@ -21,6 +23,34 @@ func (obj Object) CLI() CLIObject { } } -func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle..Proof) { - val, proof, _, err := ctx.QueryProof(obj.ConsensusStateKey) +func query(ctx context.CLIContext, root merkle.Root, key []byte) ([]byte, merkle.Proof, error) { + resp, err := ctx.QueryABCI(root.RequestQuery(key)) + if err != nil { + return nil, merkle.Proof{}, err + } + proof := merkle.Proof{ + Key: key, + Proof: resp.Proof, + } + return resp.Value, proof, nil + +} + +func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { + val, proof, err := query(ctx, root, obj.ConsensusStateKey) + obj.Cdc.MustUnmarshalBinaryBare(val, &res) + return +} + +func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { + val, tmproof, _, err := ctx.QueryProof(obj.FrozenKey, "ibc") // TODO + if err != nil { + return + } + proof = merkle.Proof{ + Key: obj.FrozenKey, + Proof: tmproof, + } + obj.Cdc.MustUnmarshalBinaryBare(val, &res) + return } From a372f5607fbfd290e8165f748d790cdc5742e818 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:40:30 +0200 Subject: [PATCH 092/182] add CLIObject --- x/ibc/02-client/cli.go | 31 ++++++++++------------- x/ibc/02-client/tendermint/types_test.go | 2 +- x/ibc/23-commitment/merkle/merkle_test.go | 12 ++++----- x/ibc/23-commitment/merkle/utils.go | 27 ++++++++++++-------- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index f51b882e7725..2592e697573c 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -12,45 +12,42 @@ type CLIObject struct { ID string ConsensusStateKey []byte FrozenKey []byte - Cdc *codec.Codec + + Root merkle.Root + Cdc *codec.Codec } -func (obj Object) CLI() CLIObject { +func (obj Object) CLI(root merkle.Root) CLIObject { return CLIObject{ ID: obj.id, ConsensusStateKey: obj.consensusState.Key(), FrozenKey: obj.frozen.Key(), + + Root: root, + Cdc: obj.consensusState.Cdc(), } } -func query(ctx context.CLIContext, root merkle.Root, key []byte) ([]byte, merkle.Proof, error) { - resp, err := ctx.QueryABCI(root.RequestQuery(key)) +func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { + resp, err := ctx.QueryABCI(obj.Root.RequestQuery(key)) if err != nil { - return nil, merkle.Proof{}, err + return merkle.Proof{}, err } proof := merkle.Proof{ Key: key, Proof: resp.Proof, } - return resp.Value, proof, nil + err = obj.Cdc.UnmarshalBinaryBare(resp.Value, ptr) + return proof, err } func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { - val, proof, err := query(ctx, root, obj.ConsensusStateKey) - obj.Cdc.MustUnmarshalBinaryBare(val, &res) + proof, err = obj.query(ctx, obj.ConsensusStateKey, &res) return } func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { - val, tmproof, _, err := ctx.QueryProof(obj.FrozenKey, "ibc") // TODO - if err != nil { - return - } - proof = merkle.Proof{ - Key: obj.FrozenKey, - Proof: tmproof, - } - obj.Cdc.MustUnmarshalBinaryBare(val, &res) + proof, err = obj.query(ctx, obj.FrozenKey, &res) return } diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/types_test.go index 3cb99f52b549..2b89f9be11c8 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/types_test.go @@ -170,7 +170,7 @@ func TestTenthBlockUpdate(t *testing.T) { */ func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.Query(node.cms, k) + code, value, proof := root.QueryMultiStore(node.cms, k) require.Equal(t, uint32(0), code) return value, proof } diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index f93f64943609..dc7da05dfbc2 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -47,13 +47,13 @@ func TestStore(t *testing.T) { root := commit(cms) - c1, v1, p1 := path.Query(cms, []byte("hello")) + c1, v1, p1 := path.QueryMultiStore(cms, []byte("hello")) require.Equal(t, uint32(0), c1) require.Equal(t, []byte("world"), v1) - c2, v2, p2 := path.Query(cms, []byte("merkle")) + c2, v2, p2 := path.QueryMultiStore(cms, []byte("merkle")) require.Equal(t, uint32(0), c2) require.Equal(t, []byte("tree"), v2) - c3, v3, p3 := path.Query(cms, []byte("block")) + c3, v3, p3 := path.QueryMultiStore(cms, []byte("block")) require.Equal(t, uint32(0), c3) require.Equal(t, []byte("chain"), v3) @@ -70,13 +70,13 @@ func TestStore(t *testing.T) { root = commit(cms) - c1, v1, p1 = path.Query(cms, []byte("12345")) + c1, v1, p1 = path.QueryMultiStore(cms, []byte("12345")) require.Equal(t, uint32(0), c1) require.Equal(t, []byte("67890"), v1) - c2, v2, p2 = path.Query(cms, []byte("qwerty")) + c2, v2, p2 = path.QueryMultiStore(cms, []byte("qwerty")) require.Equal(t, uint32(0), c2) require.Equal(t, []byte("zxcv"), v2) - c3, v3, p3 = path.Query(cms, []byte("hello")) + c3, v3, p3 = path.QueryMultiStore(cms, []byte("hello")) require.Equal(t, uint32(0), c3) require.Equal(t, []byte("dlrow"), v3) diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index d2eabdaed99d..f122b0cd5383 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -7,22 +7,29 @@ import ( ) func (path Path) RequestQuery(key []byte) abci.RequestQuery { - pathstr := "" - for _, inter := range path.KeyPath { - pathstr = pathstr + "/" + string(inter) - } - pathstr = pathstr + "/key" - - data := append(path.KeyPrefix, key...) + req := path.RequestQueryMultiStore(key) + req.Path = "/store" + req.Path + return req +} - return abci.RequestQuery{Path: pathstr, Data: data, Prove: true} +func (path Path) RequestQueryMultiStore(key []byte) abci.RequestQuery { + return abci.RequestQuery{Path: path.Path() + "/key", Data: path.Key(key), Prove: true} } -func (path Path) Query(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { - qres := cms.(types.Queryable).Query(path.RequestQuery(key)) +func (path Path) QueryMultiStore(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { + qres := cms.(types.Queryable).Query(path.RequestQueryMultiStore(key)) return qres.Code, qres.Value, Proof{Key: key, Proof: qres.Proof} } func (path Path) Key(key []byte) []byte { return append(path.KeyPrefix, key...) // XXX: cloneAppend } + +func (path Path) Path() string { + pathstr := "" + for _, inter := range path.KeyPath { + pathstr = pathstr + "/" + string(inter) + } + + return pathstr +} From 67b1d73575e788bbcef119a8472cd18d573b0cb0 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:58:28 +0200 Subject: [PATCH 093/182] separate testing from tendermint --- .../tendermint/tests/tendermint_test.go | 58 ++++++++ .../{types_test.go => tests/types.go} | 125 ++++++------------ .../{valset_test.go => tests/valset.go} | 0 3 files changed, 98 insertions(+), 85 deletions(-) create mode 100644 x/ibc/02-client/tendermint/tests/tendermint_test.go rename x/ibc/02-client/tendermint/{types_test.go => tests/types.go} (57%) rename x/ibc/02-client/tendermint/{valset_test.go => tests/valset.go} (100%) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go new file mode 100644 index 000000000000..29581e718e4c --- /dev/null +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -0,0 +1,58 @@ +package tendermint + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + +func testUpdate(t *testing.T, interval int, ok bool) { + node := NewNode(NewMockValidators(100, 10)) + + node.Commit() + + verifier := node.LastStateVerifier(newRoot()) + + for i := 0; i < 100; i++ { + header := node.Commit() + + if i%interval == 0 { + err := verifier.Validate(header, node.PrevValset, node.Valset) + if ok { + require.NoError(t, err) + } else { + require.Error(t, err) + } + } + } +} + +func TestEveryBlockUpdate(t *testing.T) { + testUpdate(t, 1, true) +} + +func TestEvenBlockUpdate(t *testing.T) { + testUpdate(t, 2, true) +} + +func TestSixthBlockUpdate(t *testing.T) { + testUpdate(t, 6, true) +} + +/* +// This should fail, since the amount of mutation is so large +// Commented out because it sometimes success +func TestTenthBlockUpdate(t *testing.T) { + testUpdate(t, 10, false) +} +*/ + +func TestProofs(t *testing.T) { + testProof(t) +} diff --git a/x/ibc/02-client/tendermint/types_test.go b/x/ibc/02-client/tendermint/tests/types.go similarity index 57% rename from x/ibc/02-client/tendermint/types_test.go rename to x/ibc/02-client/tendermint/tests/types.go index 2b89f9be11c8..f32cae8efc9d 100644 --- a/x/ibc/02-client/tendermint/types_test.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -17,6 +17,8 @@ import ( stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -37,44 +39,44 @@ func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *c return key, ctx, cms, cdc } -type node struct { - prevvalset MockValidators - valset MockValidators +type Node struct { + PrevValset MockValidators + Valset MockValidators - cms sdk.CommitMultiStore - store sdk.KVStore + Cms sdk.CommitMultiStore + Store sdk.KVStore - commits []tmtypes.SignedHeader + Commits []tmtypes.SignedHeader } -func NewNode(valset MockValidators) *node { +func NewNode(valset MockValidators) *Node { key, ctx, cms, _ := defaultComponents() - return &node{ - valset: valset, - cms: cms, - store: ctx.KVStore(key), - commits: nil, + return &Node{ + Valset: valset, + Cms: cms, + Store: ctx.KVStore(key), + Commits: nil, } } -func (node *node) last() tmtypes.SignedHeader { - if len(node.commits) == 0 { +func (node *Node) Last() tmtypes.SignedHeader { + if len(node.Commits) == 0 { return tmtypes.SignedHeader{} } - return node.commits[len(node.commits)-1] + return node.Commits[len(node.Commits)-1] } -func (node *node) Commit() tmtypes.SignedHeader { - valsethash := node.valset.ValidatorSet().Hash() - nextvalset := node.valset.Mutate() +func (node *Node) Commit() tmtypes.SignedHeader { + valsethash := node.Valset.ValidatorSet().Hash() + nextvalset := node.Valset.Mutate() nextvalsethash := nextvalset.ValidatorSet().Hash() - commitid := node.cms.Commit() + commitid := node.Cms.Commit() header := tmtypes.Header{ ChainID: chainid, - Height: int64(len(node.commits) + 1), + Height: int64(len(node.Commits) + 1), LastBlockID: tmtypes.BlockID{ - Hash: node.last().Header.Hash(), + Hash: node.Last().Header.Hash(), }, ValidatorsHash: valsethash, @@ -82,22 +84,26 @@ func (node *node) Commit() tmtypes.SignedHeader { AppHash: commitid.Hash, } - commit := node.valset.Sign(header) + commit := node.Valset.Sign(header) - node.prevvalset = node.valset - node.valset = nextvalset - node.commits = append(node.commits, commit) + node.PrevValset = node.Valset + node.Valset = nextvalset + node.Commits = append(node.Commits, commit) return commit } +func (node *Node) LastStateVerifier(root merkle.Root) *Verifier { + return NewVerifier(node.Last(), node.Valset, root) +} + type Verifier struct { - ConsensusState + client.ConsensusState } func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root merkle.Root) *Verifier { return &Verifier{ - ConsensusState{ + tendermint.ConsensusState{ ChainID: chainid, Height: uint64(header.Height), Root: root.Update(header.AppHash), @@ -108,7 +114,7 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root me func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset MockValidators) error { newcs, err := v.ConsensusState.Validate( - Header{ + tendermint.Header{ SignedHeader: header, ValidatorSet: valset.ValidatorSet(), NextValidatorSet: nextvalset.ValidatorSet(), @@ -117,66 +123,19 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock if err != nil { return err } - v.ConsensusState = newcs.(ConsensusState) + v.ConsensusState = newcs.(tendermint.ConsensusState) return nil } -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - -func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10)) - - node.Commit() - - root := newRoot() - - verifier := NewVerifier(node.last(), node.valset, root) - - for i := 0; i < 100; i++ { - header := node.Commit() - - if i%interval == 0 { - err := verifier.Validate(header, node.prevvalset, node.valset) - if ok { - require.NoError(t, err) - } else { - require.Error(t, err) - } - } - } -} - -func TestEveryBlockUpdate(t *testing.T) { - testUpdate(t, 1, true) -} - -func TestEvenBlockUpdate(t *testing.T) { - testUpdate(t, 2, true) -} - -func TestSixthBlockUpdate(t *testing.T) { - testUpdate(t, 6, true) -} - -/* -// This should fail, since the amount of mutation is so large -// Commented out because it sometimes success -func TestTenthBlockUpdate(t *testing.T) { - testUpdate(t, 10, false) -} -*/ - -func (node *node) query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.QueryMultiStore(node.cms, k) +func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { + code, value, proof := root.QueryMultiStore(node.Cms, k) require.Equal(t, uint32(0), code) return value, proof } -func (node *node) Set(k, value []byte) { - node.store.Set(newRoot().Key(k), value) +func (node *Node) Set(k, value []byte) { + node.Store.Set(newRoot().Key(k), value) } func testProof(t *testing.T) { @@ -198,7 +157,7 @@ func testProof(t *testing.T) { proofs := []commitment.Proof{} root := newRoot().Update(header.AppHash) for _, kvp := range kvps { - v, p := node.query(t, root.(merkle.Root), []byte(kvp.Key)) + v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } @@ -210,7 +169,3 @@ func testProof(t *testing.T) { } } } - -func TestProofs(t *testing.T) { - testProof(t) -} diff --git a/x/ibc/02-client/tendermint/valset_test.go b/x/ibc/02-client/tendermint/tests/valset.go similarity index 100% rename from x/ibc/02-client/tendermint/valset_test.go rename to x/ibc/02-client/tendermint/tests/valset.go From ee95a839d35e5c4f62f5647b3bc64f3d5434c74c Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 16:10:21 +0200 Subject: [PATCH 094/182] add key to node --- x/ibc/02-client/tendermint/tests/types.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index f32cae8efc9d..cc6d73592504 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -44,9 +44,12 @@ type Node struct { Valset MockValidators Cms sdk.CommitMultiStore + Key sdk.StoreKey Store sdk.KVStore Commits []tmtypes.SignedHeader + + Root merkle.Root } func NewNode(valset MockValidators) *Node { @@ -54,6 +57,7 @@ func NewNode(valset MockValidators) *Node { return &Node{ Valset: valset, Cms: cms, + Key: key, Store: ctx.KVStore(key), Commits: nil, } From b6865aa9490cbb0bb24cf2fb771d09b0ef534e8e Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 18:58:29 +0200 Subject: [PATCH 095/182] add root and storekey to tests/node, add codec --- x/ibc/02-client/codec.go | 10 ++++++++++ x/ibc/02-client/tendermint/codec.go | 11 +++++++++++ x/ibc/02-client/tendermint/tests/types.go | 8 ++++++-- x/ibc/02-client/tendermint/tests/valset.go | 1 + 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 x/ibc/02-client/codec.go create mode 100644 x/ibc/02-client/tendermint/codec.go diff --git a/x/ibc/02-client/codec.go b/x/ibc/02-client/codec.go new file mode 100644 index 000000000000..fa194562e4f1 --- /dev/null +++ b/x/ibc/02-client/codec.go @@ -0,0 +1,10 @@ +package client + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterInterface((*ConsensusState)(nil), nil) + cdc.RegisterInterface((*Header)(nil), nil) +} diff --git a/x/ibc/02-client/tendermint/codec.go b/x/ibc/02-client/tendermint/codec.go new file mode 100644 index 000000000000..d8308a3e7ec8 --- /dev/null +++ b/x/ibc/02-client/tendermint/codec.go @@ -0,0 +1,11 @@ +package tendermint + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterConcrete(ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil) + cdc.RegisterConcrete(Header{}, "ibc/client/tendermint/Header", nil) + +} diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index cc6d73592504..88a27fd69f51 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -101,6 +101,10 @@ func (node *Node) LastStateVerifier(root merkle.Root) *Verifier { return NewVerifier(node.Last(), node.Valset, root) } +func (node *Node) Context() sdk.Context { + return sdk.NewContext(node.Cms, abci.Header{}, false, log.NewNopLogger()) +} + type Verifier struct { client.ConsensusState } @@ -139,7 +143,7 @@ func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commi } func (node *Node) Set(k, value []byte) { - node.Store.Set(newRoot().Key(k), value) + node.Store.Set(node.Root.Key(k), value) } func testProof(t *testing.T) { @@ -159,7 +163,7 @@ func testProof(t *testing.T) { } header := node.Commit() proofs := []commitment.Proof{} - root := newRoot().Update(header.AppHash) + root := node.Root.Update(header.AppHash) for _, kvp := range kvps { v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) require.Equal(t, kvp.Value, v) diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 5649a3533273..0d97a5427c9b 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -84,6 +84,7 @@ type MockValidators []MockValidator var _ sort.Interface = MockValidators{} +// TODO: differenciate power between the vals func NewMockValidators(num int, power int64) MockValidators { res := make(MockValidators, num) for i := range res { From 631b72d0a13a66fd05cc0d5c45df240423452d99 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 12:22:46 +0200 Subject: [PATCH 096/182] rm cli/query.go --- x/ibc/client/cli/query.go | 216 -------------------------------------- 1 file changed, 216 deletions(-) delete mode 100644 x/ibc/client/cli/query.go diff --git a/x/ibc/client/cli/query.go b/x/ibc/client/cli/query.go deleted file mode 100644 index ca979151c499..000000000000 --- a/x/ibc/client/cli/query.go +++ /dev/null @@ -1,216 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/spf13/cobra" - - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" -) - -func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { - ibcQueryCmd := &cobra.Command{ - Use: "ibc", - Short: "IBC query subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - } - - ibcQueryCmd.AddCommand(client.GetCommands( - GetCmdQueryConsensusState(cdc), - GetCmdQueryHeader(cdc), - GetCmdQueryClient(cdc), - GetCmdQueryConnection(cdc), - GetCmdQueryChannel(cdc), - )...) - return ibcQueryCmd -} - -func GetCmdQueryClient(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "client", - Short: "Query stored client", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var state ibc.ConsensusState - statebz, _, err := query(ctx, keeper.Client.Object(args[0]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(statebz, &state) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) - - return nil - }, - } -} - -func GetCmdQueryConsensusState(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "consensus-state", - Short: "Query the latest consensus state of the running chain", - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - node, err := ctx.GetNode() - if err != nil { - return err - } - - info, err := node.ABCIInfo() - if err != nil { - return err - } - - height := info.Response.LastBlockHeight - prevheight := height - 1 - - commit, err := node.Commit(&height) - if err != nil { - return err - } - - validators, err := node.Validators(&prevheight) - if err != nil { - return err - } - - state := tendermint.ConsensusState{ - ChainID: commit.ChainID, - Height: uint64(commit.Height), - Root: []byte(commit.AppHash), - NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) - - return nil - }, - } -} - -func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "header", - Short: "Query the latest header of the running chain", - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - node, err := ctx.GetNode() - if err != nil { - return err - } - - info, err := node.ABCIInfo() - if err != nil { - return err - } - - height := info.Response.LastBlockHeight - prevheight := height - 1 - - commit, err := node.Commit(&height) - if err != nil { - return err - } - - validators, err := node.Validators(&prevheight) - if err != nil { - return err - } - - nextvalidators, err := node.Validators(&height) - if err != nil { - return err - } - - header := tendermint.Header{ - SignedHeader: commit.SignedHeader, - ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) - - return nil - }, - } -} - -func GetCmdQueryConnection(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "connection", - Short: "Query an existing connection", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var conn ibc.Connection - connbz, _, err := query(ctx, keeper.Connection.Object(args[0]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(connbz, &conn) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) - - return nil - }, - } -} - -func GetCmdQueryChannel(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "channel", - Short: "Query an existing channel", - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - - keeper := ibc.DummyKeeper() - - var conn ibc.Channel - connbz, _, err := query(ctx, keeper.Channel.Object(args[0], args[1]).Key()) - if err != nil { - return err - } - cdc.MustUnmarshalBinaryBare(connbz, &conn) - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, conn)) - - return nil - }, - } -} - -func GetCmdQuerySendSequence(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "send-sequence", - Short: "Query the send sequence of a channel", - Args: cobra.ExactArgs(), - RunE: func(cmd *cobra.Command, args []string) error { - - }, - } -} - -func GetCmdQueryReceiveSequence(cdc *codec.Codec) *cobra.Command { - -} - -func GetCmdQueryPacket(cdc *codec.Codec) *cobra.Command { -} From b9d89296eab4dfb18a1e8bf050fe6527e32b8687 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 18:21:20 +0200 Subject: [PATCH 097/182] fix test --- x/ibc/02-client/tendermint/tests/tendermint_test.go | 2 +- x/ibc/02-client/tendermint/tests/types.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index 29581e718e4c..caf866337c47 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -13,7 +13,7 @@ func newRoot() merkle.Root { } func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10)) + node := NewNode(NewMockValidators(100, 10), newRoot()) node.Commit() diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 88a27fd69f51..d0b7b488db39 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -52,7 +52,7 @@ type Node struct { Root merkle.Root } -func NewNode(valset MockValidators) *Node { +func NewNode(valset MockValidators, root merkle.Root) *Node { key, ctx, cms, _ := defaultComponents() return &Node{ Valset: valset, @@ -60,6 +60,7 @@ func NewNode(valset MockValidators) *Node { Key: key, Store: ctx.KVStore(key), Commits: nil, + Root: root, } } @@ -147,7 +148,7 @@ func (node *Node) Set(k, value []byte) { } func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10)) + node := NewNode(NewMockValidators(100, 10), newRoot()) node.Commit() From dbd6b8349713abf9f6851bb5a03848495b2b4ea1 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 18:26:23 +0200 Subject: [PATCH 098/182] fix lint --- x/ibc/02-client/tendermint/tests/valset.go | 2 +- x/ibc/02-client/tendermint/types.go | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 0d97a5427c9b..1b5f88aa949b 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -84,7 +84,7 @@ type MockValidators []MockValidator var _ sort.Interface = MockValidators{} -// TODO: differenciate power between the vals +// TODO: differentiate power between the vals func NewMockValidators(num int, power int64) MockValidators { res := make(MockValidators, num) for i := range res { diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 26a4c35370e6..6bb1bb1f18dd 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -48,11 +48,8 @@ func (cs ConsensusState) Validate(cheader client.Header) (client.ConsensusState, return nil, errors.New("invalid type") } - nextvalset := cs.NextValidatorSet - nexthash := nextvalset.Hash() - if cs.Height == uint64(header.Height-1) { - nexthash = cs.NextValidatorSet.Hash() + nexthash := cs.NextValidatorSet.Hash() if !bytes.Equal(header.ValidatorsHash, nexthash) { return nil, lerr.ErrUnexpectedValidators(header.ValidatorsHash, nexthash) } From f6e5f9011ce5da4e6a44c9bbdc383eec7fa533b8 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 19:12:36 +0200 Subject: [PATCH 099/182] fix lint --- .../tendermint/tests/tendermint_test.go | 6 ------ x/ibc/02-client/tendermint/tests/types.go | 16 ++++++++++++---- x/ibc/02-client/tendermint/tests/valset.go | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index caf866337c47..8a1c764f50f2 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -4,14 +4,8 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - func testUpdate(t *testing.T, interval int, ok bool) { node := NewNode(NewMockValidators(100, 10), newRoot()) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index d0b7b488db39..5e0af44f3806 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -1,7 +1,7 @@ package tendermint import ( - "math/rand" + "crypto/rand" "testing" "github.com/stretchr/testify/require" @@ -23,6 +23,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) +// nolint: unused +func newRoot() merkle.Root { + return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +} + const chainid = "testchain" func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { @@ -147,6 +152,7 @@ func (node *Node) Set(k, value []byte) { node.Store.Set(node.Root.Key(k), value) } +// nolint:deadcode,unused func testProof(t *testing.T) { node := NewNode(NewMockValidators(100, 10), newRoot()) @@ -157,8 +163,10 @@ func testProof(t *testing.T) { for i := 0; i < 100; i++ { k := make([]byte, 32) v := make([]byte, 32) - rand.Read(k) - rand.Read(v) + _, err := rand.Read(k) + require.NoError(t, err) + _, err = rand.Read(v) + require.NoError(t, err) kvps = append(kvps, cmn.KVPair{Key: k, Value: v}) node.Set(k, v) } @@ -166,7 +174,7 @@ func testProof(t *testing.T) { proofs := []commitment.Proof{} root := node.Root.Update(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, root.(merkle.Root), []byte(kvp.Key)) + v, p := node.Query(t, root.(merkle.Root), kvp.Key) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } diff --git a/x/ibc/02-client/tendermint/tests/valset.go b/x/ibc/02-client/tendermint/tests/valset.go index 1b5f88aa949b..30bd194682c8 100644 --- a/x/ibc/02-client/tendermint/tests/valset.go +++ b/x/ibc/02-client/tendermint/tests/valset.go @@ -131,7 +131,7 @@ func (vals MockValidators) Sign(header tmtypes.Header) tmtypes.SignedHeader { Height: header.Height, Type: tmtypes.PrecommitType, } - val.MockPV.SignVote(chainid, vote) + _ = val.MockPV.SignVote(chainid, vote) precommits[i] = vote.CommitSig() } From 892a12028f88b97c0f8c62594ae642bb585006a3 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Jul 2019 23:53:46 +0900 Subject: [PATCH 100/182] add handler/msgs/client --- store/state/base.go | 12 +- x/ibc/02-client/cli.go | 9 +- x/ibc/02-client/client/cli/query.go | 159 ++++++++++++++++++++++++ x/ibc/02-client/client/cli/tx.go | 144 +++++++++++++++++++++ x/ibc/02-client/client/utils/receive.go | 94 ++++++++++++++ x/ibc/02-client/codec.go | 9 ++ x/ibc/02-client/handler.go | 29 +++++ x/ibc/02-client/manager.go | 15 +-- x/ibc/02-client/msgs.go | 69 ++++++++++ x/ibc/02-client/tendermint/codec.go | 7 +- 10 files changed, 526 insertions(+), 21 deletions(-) create mode 100644 x/ibc/02-client/client/cli/query.go create mode 100644 x/ibc/02-client/client/cli/tx.go create mode 100644 x/ibc/02-client/client/utils/receive.go create mode 100644 x/ibc/02-client/handler.go create mode 100644 x/ibc/02-client/msgs.go diff --git a/store/state/base.go b/store/state/base.go index f163c18b98a0..a6f429053248 100644 --- a/store/state/base.go +++ b/store/state/base.go @@ -15,13 +15,19 @@ type Base struct { } func EmptyBase() Base { - return NewBase(nil, nil) + return NewBase(nil, nil, nil) } -func NewBase(cdc *codec.Codec, key sdk.StoreKey) Base { +func NewBase(cdc *codec.Codec, key sdk.StoreKey, rootkey []byte) Base { + if len(rootkey) == 0 { + return Base{ + cdc: cdc, + storefn: func(ctx Context) KVStore { return ctx.KVStore(key) }, + } + } return Base{ cdc: cdc, - storefn: func(ctx Context) KVStore { return ctx.KVStore(key) }, + storefn: func(ctx Context) KVStore { return prefix.NewStore(ctx.KVStore(key), rootkey) }, } } diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 2592e697573c..45f2c9672a4d 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -17,9 +17,10 @@ type CLIObject struct { Cdc *codec.Codec } -func (obj Object) CLI(root merkle.Root) CLIObject { +func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { + obj := man.object(id) return CLIObject{ - ID: obj.id, + ID: id, ConsensusStateKey: obj.consensusState.Key(), FrozenKey: obj.frozen.Key(), @@ -42,12 +43,12 @@ func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) } -func (obj CLIObject) ConsensusState(ctx context.CLIContext, root merkle.Root) (res ConsensusState, proof merkle.Proof, err error) { +func (obj CLIObject) ConsensusState(ctx context.CLIContext) (res ConsensusState, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.ConsensusStateKey, &res) return } -func (obj CLIObject) Frozen(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { +func (obj CLIObject) Frozen(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.FrozenKey, &res) return } diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go new file mode 100644 index 000000000000..2506ed8dd905 --- /dev/null +++ b/x/ibc/02-client/client/cli/query.go @@ -0,0 +1,159 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + tmtypes "github.com/tendermint/tendermint/types" + + cli "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +func defaultRoot(storeKey string, root []byte) merkle.Root { + return merkle.NewRoot(root, [][]byte{[]byte(storeKey)}, []byte("protocol")) +} + +func defaultBase(cdc *codec.Codec) (state.Base, state.Base) { + protocol := state.NewBase(cdc, nil, []byte("protocol")) + free := state.NewBase(cdc, nil, []byte("free")) + return protocol, free +} + +func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcQueryCmd := &cobra.Command{ + Use: "ibc", + Short: "IBC query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcQueryCmd.AddCommand(cli.GetCommands( + GetCmdQueryConsensusState(storeKey, cdc), + GetCmdQueryHeader(cdc), + GetCmdQueryClient(storeKey, cdc), + )...) + return ibcQueryCmd +} + +func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "client", + Short: "Query stored client", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + man := client.NewManager(defaultBase(cdc)) + root := defaultRoot(storeKey, nil) + id := args[0] + + state, _, err := man.CLIObject(root, id).ConsensusState(ctx) + if err != nil { + return err + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryConsensusState(storeKey string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "consensus-state", + Short: "Query the latest consensus state of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + state := tendermint.ConsensusState{ + ChainID: commit.ChainID, + Height: uint64(commit.Height), + Root: defaultRoot(storeKey, []byte(commit.AppHash)), + NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "header", + Short: "Query the latest header of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + nextvalidators, err := node.Validators(&height) + if err != nil { + return err + } + + header := tendermint.Header{ + SignedHeader: commit.SignedHeader, + ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) + + return nil + }, + } +} diff --git a/x/ibc/02-client/client/cli/tx.go b/x/ibc/02-client/client/cli/tx.go new file mode 100644 index 000000000000..e654d76e7c3d --- /dev/null +++ b/x/ibc/02-client/client/cli/tx.go @@ -0,0 +1,144 @@ +package cli + +import ( + "errors" + "io/ioutil" + // "os" + + "github.com/spf13/cobra" + + // "github.com/tendermint/tendermint/libs/log" + rpcclient "github.com/tendermint/tendermint/rpc/client" + + cli "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + // "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + // "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +const ( + FlagStatePath = "state" + FlagClientID = "client-id" + FlagConnectionID = "connection-id" + FlagChannelID = "channel-id" + FlagCounterpartyID = "counterparty-id" + FlagCounterpartyClientID = "counterparty-client-id" + FlagSourceNode = "source-node" +) + +func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcTxCmd := &cobra.Command{ + Use: "ibc", + Short: "IBC transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcTxCmd.AddCommand(cli.PostCommands( + GetCmdCreateClient(cdc), + GetCmdUpdateClient(cdc), + )...) + + return ibcTxCmd +} + +func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "create-client", + Short: "create new client with a consensus state", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + cliCtx := context.NewCLIContext(). + WithCodec(cdc) + + contents, err := ioutil.ReadFile(args[1]) + if err != nil { + return err + } + + var state client.ConsensusState + if err := cdc.UnmarshalJSON(contents, &state); err != nil { + return err + } + + msg := client.MsgCreateClient{ + ClientID: args[0], + ConsensusState: state, + Signer: cliCtx.GetFromAddress(), + } + + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) + }, + } + + return cmd +} + +func GetCmdUpdateClient(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "update-client", + Short: "update existing client with a header", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + cliCtx := context.NewCLIContext(). + WithCodec(cdc) + + contents, err := ioutil.ReadFile(args[1]) + if err != nil { + return err + } + + var header client.Header + if err := cdc.UnmarshalJSON(contents, &header); err != nil { + return err + } + + msg := client.MsgUpdateClient{ + ClientID: args[0], + Header: header, + Signer: cliCtx.GetFromAddress(), + } + + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) + }, + } + + return cmd +} + +// Copied from client/context/query.go +func query(ctx context.CLIContext, key []byte) ([]byte, merkle.Proof, error) { + node, err := ctx.GetNode() + if err != nil { + return nil, merkle.Proof{}, err + } + + opts := rpcclient.ABCIQueryOptions{ + Height: ctx.Height, + Prove: true, + } + + result, err := node.ABCIQueryWithOptions("/store/ibc/key", key, opts) + if err != nil { + return nil, merkle.Proof{}, err + } + + resp := result.Response + if !resp.IsOK() { + return nil, merkle.Proof{}, errors.New(resp.Log) + } + + return resp.Value, merkle.Proof{ + Key: key, + Proof: resp.Proof, + }, nil +} diff --git a/x/ibc/02-client/client/utils/receive.go b/x/ibc/02-client/client/utils/receive.go new file mode 100644 index 000000000000..7a8df21189fb --- /dev/null +++ b/x/ibc/02-client/client/utils/receive.go @@ -0,0 +1,94 @@ +package cli + +import ( + "errors" + + "github.com/spf13/viper" + + rpcclient "github.com/tendermint/tendermint/rpc/client" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/store/state" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" + ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" +) + +const ( + FlagStatePath = "state" + FlagClientID = "client-id" + FlagConnectionID = "connection-id" + FlagChannelID = "channel-id" + FlagCounterpartyID = "counterparty-id" + FlagCounterpartyClientID = "counterparty-client-id" + FlagSourceNode = "source-node" +) + +// Copied from client/context/query.go +func query(ctx context.CLIContext, key []byte) ([]byte, merkle.Proof, error) { + node, err := ctx.GetNode() + if err != nil { + return nil, merkle.Proof{}, err + } + + opts := rpcclient.ABCIQueryOptions{ + Height: ctx.Height, + Prove: true, + } + + result, err := node.ABCIQueryWithOptions("/store/ibc/key", key, opts) + if err != nil { + return nil, merkle.Proof{}, err + } + + resp := result.Response + if !resp.IsOK() { + return nil, merkle.Proof{}, errors.New(resp.Log) + } + + return resp.Value, merkle.Proof{ + Key: key, + Proof: resp.Proof, + }, nil +} + +func GetRelayPacket(cliCtxSource, cliCtx context.CLIContext) (ibc.Packet, ibc.Proof, error) { + keeper := ibc.DummyKeeper() + cdc := cliCtx.Codec + + connid := viper.GetString(FlagConnectionID) + chanid := viper.GetString(FlagChannelID) + + obj := keeper.Channel.Object(connid, chanid) + + seqbz, _, err := query(cliCtx, obj.Seqrecv.Key()) + if err != nil { + return nil, nil, err + } + seq, err := state.DecodeInt(seqbz, state.Dec) + if err != nil { + return nil, nil, err + } + + sentbz, _, err := query(cliCtxSource, obj.Seqsend.Key()) + if err != nil { + return nil, nil, err + } + sent, err := state.DecodeInt(sentbz, state.Dec) + if err != nil { + return nil, nil, err + } + + if seq == sent { + return nil, nil, errors.New("no packet detected") + } + + var packet ibc.Packet + packetbz, proof, err := query(cliCtxSource, obj.Packets.Value(seq).Key()) + if err != nil { + return nil, nil, err + } + cdc.MustUnmarshalBinaryBare(packetbz, &packet) + + return packet, proof, nil +} diff --git a/x/ibc/02-client/codec.go b/x/ibc/02-client/codec.go index fa194562e4f1..ece7e750dc98 100644 --- a/x/ibc/02-client/codec.go +++ b/x/ibc/02-client/codec.go @@ -4,7 +4,16 @@ import ( "github.com/cosmos/cosmos-sdk/codec" ) +var MsgCdc = codec.New() + +func init() { + RegisterCodec(MsgCdc) +} + func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*ConsensusState)(nil), nil) cdc.RegisterInterface((*Header)(nil), nil) + + cdc.RegisterConcrete(MsgCreateClient{}, "ibc/client/MsgCreateClient", nil) + cdc.RegisterConcrete(MsgUpdateClient{}, "ibc/client/MsgUpdateClient", nil) } diff --git a/x/ibc/02-client/handler.go b/x/ibc/02-client/handler.go new file mode 100644 index 000000000000..dfab0725b8c4 --- /dev/null +++ b/x/ibc/02-client/handler.go @@ -0,0 +1,29 @@ +package client + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func HandleMsgCreateClient(ctx sdk.Context, msg MsgCreateClient, man Manager) sdk.Result { + _, err := man.Create(ctx, msg.ClientID, msg.ConsensusState) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), sdk.CodeType(100), err.Error()).Result() + } + + // TODO: events + return sdk.Result{} +} + +func HandleMsgUpdateClient(ctx sdk.Context, msg MsgUpdateClient, man Manager) sdk.Result { + obj, err := man.Query(ctx, msg.ClientID) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), sdk.CodeType(200), err.Error()).Result() + } + err = obj.Update(ctx, msg.Header) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), sdk.CodeType(300), err.Error()).Result() + } + + // TODO: events + return sdk.Result{} +} diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index e94d14702b72..67d43a4325eb 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -2,7 +2,6 @@ package client import ( "errors" - "strconv" "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,25 +11,16 @@ import ( // XXX: implement spec: ClientState.verifiedRoots -type IDGenerator func(sdk.Context /*Header,*/, state.Value) string - -func IntegerIDGenerator(ctx sdk.Context, v state.Value) string { - id := state.NewInteger(v, state.Dec).Incr(ctx) - return strconv.FormatUint(id, 10) -} - type Manager struct { protocol state.Mapping idval state.Value - idgen IDGenerator } -func NewManager(protocol, free state.Base, idgen IDGenerator) Manager { +func NewManager(protocol, free state.Base) Manager { return Manager{ protocol: state.NewMapping(protocol, []byte("/client")), idval: state.NewValue(free, []byte("/client/id")), - idgen: idgen, } } @@ -61,8 +51,7 @@ func (man Manager) object(id string) Object { } } -func (man Manager) Create(ctx sdk.Context, cs ConsensusState) (Object, error) { - id := man.idgen(ctx, man.idval) +func (man Manager) Create(ctx sdk.Context, id string, cs ConsensusState) (Object, error) { obj := man.object(id) if obj.exists(ctx) { return Object{}, errors.New("Create client on already existing id") diff --git a/x/ibc/02-client/msgs.go b/x/ibc/02-client/msgs.go new file mode 100644 index 000000000000..7f515c388c8f --- /dev/null +++ b/x/ibc/02-client/msgs.go @@ -0,0 +1,69 @@ +package client + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MsgCreateClient struct { + ClientID string + ConsensusState ConsensusState + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgCreateClient{} + +func (msg MsgCreateClient) Route() string { + return "ibc" +} + +func (msg MsgCreateClient) Type() string { + return "create-client" +} + +func (msg MsgCreateClient) ValidateBasic() sdk.Error { + if msg.Signer.Empty() { + return sdk.ErrInvalidAddress("empty address") + } + return nil +} + +func (msg MsgCreateClient) GetSignBytes() []byte { + bz := MsgCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg MsgCreateClient) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + +type MsgUpdateClient struct { + ClientID string + Header Header + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgUpdateClient{} + +func (msg MsgUpdateClient) Route() string { + return "ibc" +} + +func (msg MsgUpdateClient) Type() string { + return "update-client" +} + +func (msg MsgUpdateClient) ValidateBasic() sdk.Error { + if msg.Signer.Empty() { + return sdk.ErrInvalidAddress("empty address") + } + return nil +} + +func (msg MsgUpdateClient) GetSignBytes() []byte { + bz := MsgCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg MsgUpdateClient) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} diff --git a/x/ibc/02-client/tendermint/codec.go b/x/ibc/02-client/tendermint/codec.go index d8308a3e7ec8..eca3b38917fa 100644 --- a/x/ibc/02-client/tendermint/codec.go +++ b/x/ibc/02-client/tendermint/codec.go @@ -2,10 +2,15 @@ package tendermint import ( "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" ) +func init() { + RegisterCodec(client.MsgCdc) +} + func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil) cdc.RegisterConcrete(Header{}, "ibc/client/tendermint/Header", nil) - } From dce114840b5933e839819e30b194c9a7c5ea47f6 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 9 Jul 2019 23:54:32 +0900 Subject: [PATCH 101/182] rm relay --- x/ibc/02-client/client/utils/receive.go | 94 ------------------------- 1 file changed, 94 deletions(-) delete mode 100644 x/ibc/02-client/client/utils/receive.go diff --git a/x/ibc/02-client/client/utils/receive.go b/x/ibc/02-client/client/utils/receive.go deleted file mode 100644 index 7a8df21189fb..000000000000 --- a/x/ibc/02-client/client/utils/receive.go +++ /dev/null @@ -1,94 +0,0 @@ -package cli - -import ( - "errors" - - "github.com/spf13/viper" - - rpcclient "github.com/tendermint/tendermint/rpc/client" - - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/store/state" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/keeper" -) - -const ( - FlagStatePath = "state" - FlagClientID = "client-id" - FlagConnectionID = "connection-id" - FlagChannelID = "channel-id" - FlagCounterpartyID = "counterparty-id" - FlagCounterpartyClientID = "counterparty-client-id" - FlagSourceNode = "source-node" -) - -// Copied from client/context/query.go -func query(ctx context.CLIContext, key []byte) ([]byte, merkle.Proof, error) { - node, err := ctx.GetNode() - if err != nil { - return nil, merkle.Proof{}, err - } - - opts := rpcclient.ABCIQueryOptions{ - Height: ctx.Height, - Prove: true, - } - - result, err := node.ABCIQueryWithOptions("/store/ibc/key", key, opts) - if err != nil { - return nil, merkle.Proof{}, err - } - - resp := result.Response - if !resp.IsOK() { - return nil, merkle.Proof{}, errors.New(resp.Log) - } - - return resp.Value, merkle.Proof{ - Key: key, - Proof: resp.Proof, - }, nil -} - -func GetRelayPacket(cliCtxSource, cliCtx context.CLIContext) (ibc.Packet, ibc.Proof, error) { - keeper := ibc.DummyKeeper() - cdc := cliCtx.Codec - - connid := viper.GetString(FlagConnectionID) - chanid := viper.GetString(FlagChannelID) - - obj := keeper.Channel.Object(connid, chanid) - - seqbz, _, err := query(cliCtx, obj.Seqrecv.Key()) - if err != nil { - return nil, nil, err - } - seq, err := state.DecodeInt(seqbz, state.Dec) - if err != nil { - return nil, nil, err - } - - sentbz, _, err := query(cliCtxSource, obj.Seqsend.Key()) - if err != nil { - return nil, nil, err - } - sent, err := state.DecodeInt(sentbz, state.Dec) - if err != nil { - return nil, nil, err - } - - if seq == sent { - return nil, nil, errors.New("no packet detected") - } - - var packet ibc.Packet - packetbz, proof, err := query(cliCtxSource, obj.Packets.Value(seq).Key()) - if err != nil { - return nil, nil, err - } - cdc.MustUnmarshalBinaryBare(packetbz, &packet) - - return packet, proof, nil -} From 26e80388c4238d40c5d261f4cf932bd2a151ad8a Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 12 Jul 2019 01:33:18 +0900 Subject: [PATCH 102/182] finalize rebase on 23 root/path sep --- x/ibc/02-client/cli.go | 8 +++--- .../tendermint/tests/tendermint_test.go | 8 +++--- x/ibc/02-client/tendermint/tests/types.go | 26 +++++++++---------- x/ibc/02-client/tendermint/types.go | 3 ++- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 45f2c9672a4d..382b1d2d4aea 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -13,24 +13,24 @@ type CLIObject struct { ConsensusStateKey []byte FrozenKey []byte - Root merkle.Root + Path merkle.Path Cdc *codec.Codec } -func (man Manager) CLIObject(root merkle.Root, id string) CLIObject { +func (man Manager) CLIObject(path merkle.Path, id string) CLIObject { obj := man.object(id) return CLIObject{ ID: id, ConsensusStateKey: obj.consensusState.Key(), FrozenKey: obj.frozen.Key(), - Root: root, + Path: path, Cdc: obj.consensusState.Cdc(), } } func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { - resp, err := ctx.QueryABCI(obj.Root.RequestQuery(key)) + resp, err := ctx.QueryABCI(obj.Path.RequestQuery(key)) if err != nil { return merkle.Proof{}, err } diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index 8a1c764f50f2..61a0944fbaa0 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -4,14 +4,16 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10), newRoot()) + node := NewNode(NewMockValidators(100, 10), newPath()) - node.Commit() + header := node.Commit() - verifier := node.LastStateVerifier(newRoot()) + verifier := node.LastStateVerifier(merkle.NewRoot(header.AppHash)) for i := 0; i < 100; i++ { header := node.Commit() diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 5e0af44f3806..f9fd9fc9f0c8 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -24,8 +24,8 @@ import ( ) // nolint: unused -func newRoot() merkle.Root { - return merkle.NewRoot(nil, [][]byte{[]byte("test")}, []byte{0x12, 0x34}) +func newPath() merkle.Path { + return merkle.NewPath([][]byte{[]byte("test")}, []byte{0x12, 0x34}) } const chainid = "testchain" @@ -54,10 +54,10 @@ type Node struct { Commits []tmtypes.SignedHeader - Root merkle.Root + Path merkle.Path } -func NewNode(valset MockValidators, root merkle.Root) *Node { +func NewNode(valset MockValidators, path merkle.Path) *Node { key, ctx, cms, _ := defaultComponents() return &Node{ Valset: valset, @@ -65,7 +65,7 @@ func NewNode(valset MockValidators, root merkle.Root) *Node { Key: key, Store: ctx.KVStore(key), Commits: nil, - Root: root, + Path: path, } } @@ -120,7 +120,7 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root me tendermint.ConsensusState{ ChainID: chainid, Height: uint64(header.Height), - Root: root.Update(header.AppHash), + Root: merkle.NewRoot(header.AppHash), NextValidatorSet: nextvalset.ValidatorSet(), }, } @@ -142,19 +142,19 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock return nil } -func (node *Node) Query(t *testing.T, root merkle.Root, k []byte) ([]byte, commitment.Proof) { - code, value, proof := root.QueryMultiStore(node.Cms, k) +func (node *Node) Query(t *testing.T, path merkle.Path, k []byte) ([]byte, commitment.Proof) { + code, value, proof := path.QueryMultiStore(node.Cms, k) require.Equal(t, uint32(0), code) return value, proof } func (node *Node) Set(k, value []byte) { - node.Store.Set(node.Root.Key(k), value) + node.Store.Set(node.Path.Key(k), value) } // nolint:deadcode,unused func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10), newRoot()) + node := NewNode(NewMockValidators(100, 10), newPath()) node.Commit() @@ -172,13 +172,13 @@ func testProof(t *testing.T) { } header := node.Commit() proofs := []commitment.Proof{} - root := node.Root.Update(header.AppHash) + root := merkle.NewRoot(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, root.(merkle.Root), kvp.Key) + v, p := node.Query(t, node.Path, kvp.Key) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore(root, proofs) + cstore, err := commitment.NewStore(root, node.Path, proofs) require.NoError(t, err) for _, kvp := range kvps { diff --git a/x/ibc/02-client/tendermint/types.go b/x/ibc/02-client/tendermint/types.go index 6bb1bb1f18dd..ca5da8c1cae5 100644 --- a/x/ibc/02-client/tendermint/types.go +++ b/x/ibc/02-client/tendermint/types.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) var _ client.ConsensusState = ConsensusState{} @@ -37,7 +38,7 @@ func (cs ConsensusState) update(header Header) ConsensusState { return ConsensusState{ ChainID: cs.ChainID, Height: uint64(header.Height), - Root: cs.GetRoot().Update(header.AppHash), + Root: merkle.NewRoot(header.AppHash), NextValidatorSet: header.NextValidatorSet, } } From 812bea4a62b62263866b87b3e716939a65b200b2 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 12 Jul 2019 01:35:54 +0900 Subject: [PATCH 103/182] fix lint, fix syntax --- x/ibc/02-client/client/cli/query.go | 10 +++++----- x/ibc/02-client/client/cli/tx.go | 31 ----------------------------- 2 files changed, 5 insertions(+), 36 deletions(-) diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 2506ed8dd905..9de2231427bb 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -17,8 +17,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func defaultRoot(storeKey string, root []byte) merkle.Root { - return merkle.NewRoot(root, [][]byte{[]byte(storeKey)}, []byte("protocol")) +func defaultPath(storeKey string) merkle.Path { + return merkle.NewPath([][]byte{[]byte(storeKey)}, []byte("protocol")) } func defaultBase(cdc *codec.Codec) (state.Base, state.Base) { @@ -51,10 +51,10 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) man := client.NewManager(defaultBase(cdc)) - root := defaultRoot(storeKey, nil) + path := defaultPath(storeKey) id := args[0] - state, _, err := man.CLIObject(root, id).ConsensusState(ctx) + state, _, err := man.CLIObject(path, id).ConsensusState(ctx) if err != nil { return err } @@ -99,7 +99,7 @@ func GetCmdQueryConsensusState(storeKey string, cdc *codec.Codec) *cobra.Command state := tendermint.ConsensusState{ ChainID: commit.ChainID, Height: uint64(commit.Height), - Root: defaultRoot(storeKey, []byte(commit.AppHash)), + Root: merkle.NewRoot(commit.AppHash), NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), } diff --git a/x/ibc/02-client/client/cli/tx.go b/x/ibc/02-client/client/cli/tx.go index e654d76e7c3d..1b18dbe34783 100644 --- a/x/ibc/02-client/client/cli/tx.go +++ b/x/ibc/02-client/client/cli/tx.go @@ -1,14 +1,12 @@ package cli import ( - "errors" "io/ioutil" // "os" "github.com/spf13/cobra" // "github.com/tendermint/tendermint/libs/log" - rpcclient "github.com/tendermint/tendermint/rpc/client" cli "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" @@ -20,7 +18,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client" // "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) const ( @@ -114,31 +111,3 @@ func GetCmdUpdateClient(cdc *codec.Codec) *cobra.Command { return cmd } - -// Copied from client/context/query.go -func query(ctx context.CLIContext, key []byte) ([]byte, merkle.Proof, error) { - node, err := ctx.GetNode() - if err != nil { - return nil, merkle.Proof{}, err - } - - opts := rpcclient.ABCIQueryOptions{ - Height: ctx.Height, - Prove: true, - } - - result, err := node.ABCIQueryWithOptions("/store/ibc/key", key, opts) - if err != nil { - return nil, merkle.Proof{}, err - } - - resp := result.Response - if !resp.IsOK() { - return nil, merkle.Proof{}, errors.New(resp.Log) - } - - return resp.Value, merkle.Proof{ - Key: key, - Proof: resp.Proof, - }, nil -} From 00df063c8adac70c4c15822ed1d72a828ecce78b Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 04:45:14 +0900 Subject: [PATCH 104/182] fix querying --- store/state/base.go | 33 ++++++++++++----------- store/state/mapping.go | 4 +++ x/ibc/02-client/tendermint/tests/types.go | 14 +++++++--- x/ibc/03-connection/cli.go | 15 +++++++---- x/ibc/03-connection/handshake.go | 2 ++ x/ibc/03-connection/manager.go | 12 +++++++++ x/ibc/03-connection/tests/types.go | 2 ++ x/ibc/23-commitment/merkle/merkle.go | 10 ++++++- x/ibc/23-commitment/store.go | 7 ++--- x/ibc/23-commitment/types.go | 1 + 10 files changed, 73 insertions(+), 27 deletions(-) diff --git a/store/state/base.go b/store/state/base.go index a6f429053248..d4575f779679 100644 --- a/store/state/base.go +++ b/store/state/base.go @@ -9,9 +9,9 @@ import ( ) type Base struct { - cdc *codec.Codec - storefn func(Context) KVStore - prefix []byte + storeKey sdk.StoreKey + cdc *codec.Codec + prefix []byte } func EmptyBase() Base { @@ -19,20 +19,15 @@ func EmptyBase() Base { } func NewBase(cdc *codec.Codec, key sdk.StoreKey, rootkey []byte) Base { - if len(rootkey) == 0 { - return Base{ - cdc: cdc, - storefn: func(ctx Context) KVStore { return ctx.KVStore(key) }, - } - } return Base{ - cdc: cdc, - storefn: func(ctx Context) KVStore { return prefix.NewStore(ctx.KVStore(key), rootkey) }, + storeKey: key, + cdc: cdc, + prefix: rootkey, } } func (base Base) Store(ctx Context) KVStore { - return prefix.NewStore(base.storefn(ctx), base.prefix) + return prefix.NewStore(ctx.KVStore(base.storeKey), base.prefix) } func join(a, b []byte) (res []byte) { @@ -44,9 +39,9 @@ func join(a, b []byte) (res []byte) { func (base Base) Prefix(prefix []byte) (res Base) { res = Base{ - cdc: base.cdc, - storefn: base.storefn, - prefix: join(base.prefix, prefix), + storeKey: base.storeKey, + cdc: base.cdc, + prefix: join(base.prefix, prefix), } return } @@ -58,3 +53,11 @@ func (base Base) Cdc() *codec.Codec { func (base Base) key(key []byte) []byte { return join(base.prefix, key) } + +func (base Base) StoreName() string { + return base.storeKey.Name() +} + +func (base Base) PrefixBytes() []byte { + return base.prefix +} diff --git a/store/state/mapping.go b/store/state/mapping.go index 0d0ae990cf5a..cc3c2f8a4495 100644 --- a/store/state/mapping.go +++ b/store/state/mapping.go @@ -58,3 +58,7 @@ func (m Mapping) Prefix(prefix []byte) Mapping { func (m Mapping) Cdc() *Codec { return m.base.Cdc() } + +func (m Mapping) StoreName() string { + return m.base.StoreName() +} diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 1627f4451764..5c0d009095e6 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -143,9 +143,17 @@ func (v *Verifier) Validate(header tendermint.Header, valset, nextvalset MockVal } func (node *Node) Query(t *testing.T, k []byte) ([]byte, commitment.Proof) { - code, value, proof := node.Path.QueryMultiStore(node.Cms, k) - require.Equal(t, uint32(0), code) - return value, proof + resp := node.Cms.(stypes.Queryable).Query(abci.RequestQuery{ + Path: "/" + string(node.Path.KeyPath[0]) + "/key", + Data: k, + Prove: true, + }) + require.Equal(t, uint32(0), resp.Code) + proof := merkle.Proof{ + Key: k, + Proof: resp.Proof, + } + return resp.Value, proof } func (node *Node) Set(k, value []byte) { diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 9334a251aec2..85a2e4d53ccf 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -1,6 +1,8 @@ package connection import ( + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" @@ -17,8 +19,8 @@ type CLIObject struct { Client client.CLIObject - Path merkle.Path - Cdc *codec.Codec + StoreName string + Cdc *codec.Codec } func (man Manager) CLIObject(path merkle.Path, id string, clientid string) CLIObject { @@ -31,13 +33,16 @@ func (man Manager) CLIObject(path merkle.Path, id string, clientid string) CLIOb Client: man.client.CLIObject(path, clientid), - Path: path, - Cdc: obj.connection.Cdc(), + StoreName: man.protocol.StoreName(), + Cdc: obj.connection.Cdc(), } } func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { - resp, err := ctx.QueryABCI(obj.Path.RequestQuery(key)) + resp, err := ctx.QueryABCI(abci.RequestQuery{ + Path: "/store/" + obj.StoreName + "/key", + Data: key, + }) if err != nil { return merkle.Proof{}, err } diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index e96c805664bf..83f040457f8f 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -189,6 +189,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, if !obj.counterparty.connection.Is(ctx, Connection{ Client: counterpartyClient, Counterparty: id, + Path: obj.path, }) { err = errors.New("wrong counterparty connection") return @@ -261,6 +262,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, if !obj.counterparty.connection.Is(ctx, Connection{ Client: obj.CounterpartyClient(ctx), Counterparty: obj.ID(), + Path: obj.path, }) { err = errors.New("wrong counterparty") return diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index e5d32fafd454..41976053917a 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) type Manager struct { @@ -17,6 +18,8 @@ type Manager struct { client client.Manager counterparty CounterpartyManager + + path merkle.Path } func NewManager(protocol state.Base, client client.Manager) Manager { @@ -24,6 +27,7 @@ func NewManager(protocol state.Base, client client.Manager) Manager { protocol: state.NewMapping(protocol, ([]byte("/connection/"))), client: client, counterparty: NewCounterpartyManager(protocol.Cdc()), + path: merkle.NewPath([][]byte{[]byte(protocol.StoreName())}, protocol.PrefixBytes()), } } @@ -53,6 +57,8 @@ type Object struct { kind state.String client client.Object + + path merkle.Path } func (man Manager) object(id string) Object { @@ -66,6 +72,8 @@ func (man Manager) object(id string) Object { kind: state.NewString(man.protocol.Value([]byte(id + "/kind"))), // CONTRACT: client must be filled by the caller + + path: man.path, } } @@ -139,6 +147,10 @@ func (man Manager) create(ctx sdk.Context, id string, connection Connection, kin err = errors.New("Object already exists") return } + obj.client, err = man.client.Query(ctx, connection.Client) + if err != nil { + return + } obj.connection.Set(ctx, connection) obj.kind.Set(ctx, kind) return diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 931163dfe6cf..608446439be0 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -48,10 +48,12 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res.Connection = connection.Connection{ Counterparty: res.Counterparty.Name, + Path: res.Counterparty.Path, } res.Counterparty.Connection = connection.Connection{ Counterparty: res.Name, + Path: res.Path, } return res diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index 9fb11c7f38cb..5a0c6e9565a2 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -48,6 +48,13 @@ func (Path) CommitmentKind() string { return merkleKind } +func (path Path) Pathify(key []byte) (res []byte) { + res = make([]byte, len(path.KeyPrefix)+len(key)) + copy(res, path.KeyPrefix) + copy(res[len(path.KeyPrefix):], key) + return +} + var _ commitment.Proof = Proof{} type Proof struct { @@ -78,7 +85,8 @@ func (proof Proof) Verify(croot commitment.Root, cpath commitment.Path, value [] for _, key := range path.KeyPath { keypath = keypath.AppendKey(key, merkle.KeyEncodingHex) } - keypath = keypath.AppendKey(append(path.KeyPrefix, proof.Key...), merkle.KeyEncodingHex) + // KeyPrefix is not appended, we assume that the proof.Key already contains it + keypath = keypath.AppendKey(proof.Key, merkle.KeyEncodingHex) // Hard coded for now runtime := rootmulti.DefaultProofRuntime() diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index e3acb1158f34..7e469dcda483 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -72,11 +72,12 @@ func (store *store) Get(key []byte) ([]byte, bool) { } func (store *store) Prove(key, value []byte) bool { - stored, ok := store.Get(key) + pathkey := store.path.Pathify(key) + stored, ok := store.Get(pathkey) if ok && bytes.Equal(stored, value) { return true } - proof, ok := store.proofs[string(key)] + proof, ok := store.proofs[string(pathkey)] if !ok { return false } @@ -84,7 +85,7 @@ func (store *store) Prove(key, value []byte) bool { if err != nil { return false } - store.verified[string(key)] = value + store.verified[string(pathkey)] = value return true } diff --git a/x/ibc/23-commitment/types.go b/x/ibc/23-commitment/types.go index 6453511a24e3..543965eb68f0 100644 --- a/x/ibc/23-commitment/types.go +++ b/x/ibc/23-commitment/types.go @@ -6,6 +6,7 @@ type Root interface { type Path interface { CommitmentKind() string + Pathify([]byte) []byte } type Proof interface { From 19321f1cfed50f3deda880962b44cd7f401e38d0 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 04:55:28 +0900 Subject: [PATCH 105/182] extract out context withstore --- x/ibc/03-connection/handshake.go | 27 +++------------------------ x/ibc/03-connection/manager.go | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 83f040457f8f..467aa664b64b 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -164,18 +164,11 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - store, err := commitment.NewStore( - // TODO: proof root should be able to be obtained from the past - obj.client.ConsensusState(ctx).GetRoot(), - connection.Path, - []commitment.Proof{connectionp, statep, timeoutp, counterpartyClientp}, - ) + ctx, err = obj.Context(ctx, connection.Path, connectionp, statep, timeoutp, counterpartyClientp) if err != nil { return } - ctx = commitment.WithStore(ctx, store) - err = assertTimeout(ctx, timeoutHeight) if err != nil { return @@ -237,18 +230,11 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - store, err := commitment.NewStore( - // TODO: proof root should be able to be obtained from the past - obj.client.ConsensusState(ctx).GetRoot(), - obj.Connection(ctx).Path, - []commitment.Proof{connectionp, statep, timeoutp, counterpartyClientp}, - ) + ctx, err = obj.Context(ctx, nil, connectionp, statep, timeoutp, counterpartyClientp) if err != nil { return } - ctx = commitment.WithStore(ctx, store) - if !obj.state.Transit(ctx, Init, Open) { err = errors.New("ack on non-init connection") return @@ -307,18 +293,11 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - store, err := commitment.NewStore( - // TODO: proof root should be able to be obtained from the past - obj.client.ConsensusState(ctx).GetRoot(), - obj.Connection(ctx).Path, - []commitment.Proof{statep, timeoutp}, - ) + ctx, err = obj.Context(ctx, nil, statep, timeoutp) if err != nil { return } - ctx = commitment.WithStore(ctx, store) - if !obj.state.Transit(ctx, OpenTry, Open) { err = errors.New("confirm on non-try connection") return diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 41976053917a..2663b4dcdcf4 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -102,6 +102,24 @@ func (man CounterpartyManager) object(id string) CounterObject { } } +func (obj Object) Context(ctx sdk.Context, optpath commitment.Path, proofs ...commitment.Proof) (sdk.Context, error) { + if optpath == nil { + optpath = obj.Connection(ctx).Path + } + + store, err := commitment.NewStore( + // TODO: proof root should be able to be obtained from the past + obj.client.ConsensusState(ctx).GetRoot(), + optpath, + proofs, + ) + if err != nil { + return ctx, err + } + + return commitment.WithStore(ctx, store), nil +} + func (obj Object) ID() string { return obj.id } From 486e862187c2cda48825b16ed846044eddc8409f Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 05:11:14 +0900 Subject: [PATCH 106/182] fix 02-client test --- x/ibc/02-client/tendermint/tests/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 5c0d009095e6..1bb843698122 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -183,7 +183,7 @@ func testProof(t *testing.T) { proofs := []commitment.Proof{} root := merkle.NewRoot(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, kvp.Key) + v, p := node.Query(t, node.Path.Key(kvp.Key)) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) From 67a3e1b63c9a38c6d35e068cf2b1c2e2f071823e Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 05:20:25 +0900 Subject: [PATCH 107/182] fix 23-commitment test --- x/ibc/23-commitment/merkle/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index f122b0cd5383..43c14648fa15 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -18,7 +18,7 @@ func (path Path) RequestQueryMultiStore(key []byte) abci.RequestQuery { func (path Path) QueryMultiStore(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { qres := cms.(types.Queryable).Query(path.RequestQueryMultiStore(key)) - return qres.Code, qres.Value, Proof{Key: key, Proof: qres.Proof} + return qres.Code, qres.Value, Proof{Key: path.Key(key), Proof: qres.Proof} } func (path Path) Key(key []byte) []byte { From 8e660ea0c106c3e5c33e5cce5e74eeeea7238025 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 15 Jul 2019 17:40:43 +0900 Subject: [PATCH 108/182] add query in progress --- x/ibc/03-connection/client/cli/query.go | 159 ++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 x/ibc/03-connection/client/cli/query.go diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go new file mode 100644 index 000000000000..ba283c4cf97d --- /dev/null +++ b/x/ibc/03-connection/client/cli/query.go @@ -0,0 +1,159 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + tmtypes "github.com/tendermint/tendermint/types" + + cli "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +func defaultPath(storeKey string) merkle.Path { + return merkle.NewPath([][]byte{[]byte(storeKey)}, []byte("protocol")) +} + +func defaultBase(cdc *codec.Codec) (state.Base, state.Base) { + protocol := state.NewBase(cdc, nil, []byte("protocol")) + free := state.NewBase(cdc, nil, []byte("free")) + return protocol, free +} + +func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcQueryCmd := &cobra.Command{ + Use: "connection", + Short: "Connection query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcQueryCmd.AddCommand(cli.GetCommands( + GetCmdQueryConnection(storeKey, cdc), + GetCmdQueryHandshake(storeKey, cdc), + )...) + return ibcQueryCmd +} + +func GetCmdQueryConnection(storeKey string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "connection", + Short: "Query stored connection", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + protocol, _ := defaultBase(cdc) + man := connection.NewManager(client.NewManager(protocol), protocol) + path := defaultPath(storeKey) + id := args[0] + + state, _, err := man.CLIObject(path, id).Connection(ctx) + if err != nil { + return err + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryConsensusState(storeKey string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "consensus-state", + Short: "Query the latest consensus state of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + state := tendermint.ConsensusState{ + ChainID: commit.ChainID, + Height: uint64(commit.Height), + Root: merkle.NewRoot(commit.AppHash), + NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + + return nil + }, + } +} + +func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "header", + Short: "Query the latest header of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + node, err := ctx.GetNode() + if err != nil { + return err + } + + info, err := node.ABCIInfo() + if err != nil { + return err + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return err + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return err + } + + nextvalidators, err := node.Validators(&height) + if err != nil { + return err + } + + header := tendermint.Header{ + SignedHeader: commit.SignedHeader, + ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) + + return nil + }, + } +} From dbd47aa9abcb66e59626a8aa5c51926798b39396 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 15 Jul 2019 17:52:19 +0900 Subject: [PATCH 109/182] rm freebase, reformat query --- x/ibc/02-client/client/cli/query.go | 24 ++++++++++++------------ x/ibc/02-client/manager.go | 5 +---- x/ibc/version.go | 3 +++ 3 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 x/ibc/version.go diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 9de2231427bb..fb2c7f73da0e 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "strconv" "github.com/spf13/cobra" @@ -11,26 +12,25 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func defaultPath(storeKey string) merkle.Path { - return merkle.NewPath([][]byte{[]byte(storeKey)}, []byte("protocol")) -} - -func defaultBase(cdc *codec.Codec) (state.Base, state.Base) { - protocol := state.NewBase(cdc, nil, []byte("protocol")) - free := state.NewBase(cdc, nil, []byte("free")) - return protocol, free +func components(cdc *codec.Codec, storeKey string, version int64) (path merkle.Path, base state.Base) { + prefix := []byte(strconv.FormatInt(version, 10) + "/") + path = merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) + base = state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) + return } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { ibcQueryCmd := &cobra.Command{ - Use: "ibc", - Short: "IBC query subcommands", + Use: "client", + Short: "IBC client query subcommands", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, } @@ -50,8 +50,8 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - man := client.NewManager(defaultBase(cdc)) - path := defaultPath(storeKey) + path, base := components(cdc, storeKey, ibc.Version) + man := client.NewManager(base) id := args[0] state, _, err := man.CLIObject(path, id).ConsensusState(ctx) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 67d43a4325eb..4f5195bc1850 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -13,14 +13,11 @@ import ( type Manager struct { protocol state.Mapping - - idval state.Value } -func NewManager(protocol, free state.Base) Manager { +func NewManager(protocol state.Base) Manager { return Manager{ protocol: state.NewMapping(protocol, []byte("/client")), - idval: state.NewValue(free, []byte("/client/id")), } } diff --git a/x/ibc/version.go b/x/ibc/version.go new file mode 100644 index 000000000000..11bd8ee5b3d3 --- /dev/null +++ b/x/ibc/version.go @@ -0,0 +1,3 @@ +package ibc + +const Version int64 = 1 From 5584cebffe7c65bc1ce8b2744e404a3fe28db610 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 16 Jul 2019 04:10:06 +0900 Subject: [PATCH 110/182] add cli/handler/msg in progress --- x/ibc/03-connection/cli.go | 17 ++- x/ibc/03-connection/client/cli/query.go | 158 +++++++--------------- x/ibc/03-connection/client/cli/tx.go | 65 +++++++++ x/ibc/03-connection/client/utils/types.go | 59 ++++++++ x/ibc/03-connection/handler.go | 8 ++ x/ibc/03-connection/msgs.go | 68 ++++++++++ 6 files changed, 261 insertions(+), 114 deletions(-) create mode 100644 x/ibc/03-connection/client/cli/tx.go create mode 100644 x/ibc/03-connection/client/utils/types.go create mode 100644 x/ibc/03-connection/handler.go create mode 100644 x/ibc/03-connection/msgs.go diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 85a2e4d53ccf..e85594ead21b 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -23,19 +23,24 @@ type CLIObject struct { Cdc *codec.Codec } -func (man Manager) CLIObject(path merkle.Path, id string, clientid string) CLIObject { +func (man Manager) CLIObject(ctx context.CLIContext, path merkle.Path, id string) CLIObject { obj := man.object(id) - return CLIObject{ + res := CLIObject{ ID: obj.id, ConnectionKey: obj.connection.Key(), AvailableKey: obj.available.Key(), KindKey: obj.kind.Key(), - Client: man.client.CLIObject(path, clientid), - StoreName: man.protocol.StoreName(), Cdc: obj.connection.Cdc(), } + + connection, _, err := res.Connection(ctx) + if err != nil { + return res + } + res.Client = man.client.CLIObject(path, connection.Client) + return res } func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { @@ -78,10 +83,10 @@ type CLIHandshakeObject struct { TimeoutKey []byte } -func (man Handshaker) CLIObject(path merkle.Path, id string, clientid string) CLIHandshakeObject { +func (man Handshaker) CLIObject(ctx context.CLIContext, path merkle.Path, id string) CLIHandshakeObject { obj := man.object(man.man.object(id)) return CLIHandshakeObject{ - CLIObject: man.man.CLIObject(path, id, clientid), + CLIObject: man.man.CLIObject(ctx, path, id), StateKey: obj.state.Key(), CounterpartyClientKey: obj.counterpartyClient.Key(), diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index ba283c4cf97d..da606af27c50 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -2,29 +2,35 @@ package cli import ( "fmt" + "strconv" "github.com/spf13/cobra" - - tmtypes "github.com/tendermint/tendermint/types" + "github.com/spf13/viper" cli "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/utils" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func defaultPath(storeKey string) merkle.Path { - return merkle.NewPath([][]byte{[]byte(storeKey)}, []byte("protocol")) -} +const ( + FlagProve = "prove" +) -func defaultBase(cdc *codec.Codec) (state.Base, state.Base) { - protocol := state.NewBase(cdc, nil, []byte("protocol")) - free := state.NewBase(cdc, nil, []byte("free")) - return protocol, free +func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) connection.CLIObject { + prefix := []byte(strconv.FormatInt(version, 10) + "/") + path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) + base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) + climan := client.NewManager(base) + man := connection.NewManager(base, climan) + return man.CLIObject(ctx, path, id) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -37,123 +43,59 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { ibcQueryCmd.AddCommand(cli.GetCommands( GetCmdQueryConnection(storeKey, cdc), - GetCmdQueryHandshake(storeKey, cdc), )...) return ibcQueryCmd } -func GetCmdQueryConnection(storeKey string, cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "connection", - Short: "Query stored connection", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - protocol, _ := defaultBase(cdc) - man := connection.NewManager(client.NewManager(protocol), protocol) - path := defaultPath(storeKey) - id := args[0] - - state, _, err := man.CLIObject(path, id).Connection(ctx) - if err != nil { - return err - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) +func QueryConnection(ctx context.CLIContext, obj connection.CLIObject, prove bool) (res utils.JSONObject, err error) { + conn, connp, err := obj.Connection(ctx) + if err != nil { + return + } + avail, availp, err := obj.Available(ctx) + if err != nil { + return + } + kind, kindp, err := obj.Kind(ctx) + if err != nil { + return + } - return nil - }, + if prove { + return utils.NewJSONObject( + conn, connp, + avail, availp, + kind, kindp, + ), nil } + + return utils.NewJSONObject( + conn, nil, + avail, nil, + kind, nil, + ), nil } -func GetCmdQueryConsensusState(storeKey string, cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "consensus-state", - Short: "Query the latest consensus state of the running chain", +func GetCmdQueryConnection(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "connection", + Short: "Query stored connection", + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - - node, err := ctx.GetNode() - if err != nil { - return err - } - - info, err := node.ABCIInfo() - if err != nil { - return err - } - - height := info.Response.LastBlockHeight - prevheight := height - 1 - - commit, err := node.Commit(&height) - if err != nil { - return err - } - - validators, err := node.Validators(&prevheight) + obj := object(ctx, cdc, storeKey, ibc.Version, args[0]) + jsonobj, err := QueryConnection(ctx, obj, viper.GetBool(FlagProve)) if err != nil { return err } - state := tendermint.ConsensusState{ - ChainID: commit.ChainID, - Height: uint64(commit.Height), - Root: merkle.NewRoot(commit.AppHash), - NextValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, state)) + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, jsonobj)) return nil }, } -} - -func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "header", - Short: "Query the latest header of the running chain", - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.NewCLIContext().WithCodec(cdc) - node, err := ctx.GetNode() - if err != nil { - return err - } + cmd.Flags().Bool(FlagProve, false, "(optional) show proofs for the query results") - info, err := node.ABCIInfo() - if err != nil { - return err - } - - height := info.Response.LastBlockHeight - prevheight := height - 1 - - commit, err := node.Commit(&height) - if err != nil { - return err - } - - validators, err := node.Validators(&prevheight) - if err != nil { - return err - } - - nextvalidators, err := node.Validators(&height) - if err != nil { - return err - } - - header := tendermint.Header{ - SignedHeader: commit.SignedHeader, - ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), - } - - fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, header)) - - return nil - }, - } + return cmd } diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go new file mode 100644 index 000000000000..bbbfd8642860 --- /dev/null +++ b/x/ibc/03-connection/client/cli/tx.go @@ -0,0 +1,65 @@ +package cli + +import ( + "strconv" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +/* +func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + +} +*/ +const ( + FlagNode1 = "node1" + FlagNode2 = "node2" + FlagFrom1 = "from1" + FlagFrom2 = "from2" +) + +func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) connection.CLIHandshakeObject { + prefix := []byte(strconv.FormatInt(version, 10) + "/") + path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) + base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) + climan := client.NewManager(base) + man := connection.NewHandshaker(connection.NewManager(base, climan)) + return man.CLIObject(ctx, path, id) +} + +func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "handshake", + Short: "initiate connection handshake between two chains", + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + ctx1 := context.NewCLIContext(). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode1)). + WithFrom(viper.GetString(FlagFrom1)) + + ctx2 := context.NewCLIContext(). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode2)). + WithFrom(viper.GetString(FlagFrom2)) + + obj1 := object(ctx1, cdc, storeKey, ibc.Version, args[0]) + obj2 := object(ctx2, cdc, storeKey, ibc.Version, args[1]) + + }, + } +} diff --git a/x/ibc/03-connection/client/utils/types.go b/x/ibc/03-connection/client/utils/types.go new file mode 100644 index 000000000000..33480a68291f --- /dev/null +++ b/x/ibc/03-connection/client/utils/types.go @@ -0,0 +1,59 @@ +package utils + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +type JSONObject struct { + Connection connection.Connection `json:"connection"` + ConnectionProof commitment.Proof `json:"connection_proof,omitempty"` + Available bool `json:"available"` + AvailableProof commitment.Proof `json:"available_proof,omitempty"` + Kind string `json:"kind"` + KindProof commitment.Proof `json:"kind_proof,omitempty"` +} + +func NewJSONObject( + conn connection.Connection, connp commitment.Proof, + avail bool, availp commitment.Proof, + kind string, kindp commitment.Proof, +) JSONObject { + return JSONObject{ + Connection: conn, + ConnectionProof: connp, + Available: avail, + AvailableProof: availp, + Kind: kind, + KindProof: kindp, + } +} + +type HandshakeJSONObject struct { + JSONObject `json:"connection"` + State byte `json:"state"` + StateProof commitment.Proof `json:"state_proof,omitempty"` + CounterpartyClient string `json:"counterparty_client"` + CounterpartyClientProof commitment.Proof `json:"counterparty_client_proof,omitempty"` + NextTimeout uint64 `json:"next_timeout"` + NextTimeoutProof commitment.Proof `json:"next_timeout_proof,omitempty"` +} + +func NewHandshakeJSONObject( + conn connection.Connection, connp commitment.Proof, + avail bool, availp commitment.Proof, + kind string, kindp commitment.Proof, + state byte, statep commitment.Proof, + cpclient string, cpclientp commitment.Proof, + timeout uint64, timeoutp commitment.Proof, +) HandshakeJSONObject { + return HandshakeJSONObject{ + JSONObject: NewJSONObject(conn, connp, avail, availp, kind, kindp), + State: state, + StateProof: statep, + CounterpartyClient: cpclient, + CounterpartyClientProof: cpclientp, + NextTimeout: timeout, + NextTimeoutProof: timeoutp, + } +} diff --git a/x/ibc/03-connection/handler.go b/x/ibc/03-connection/handler.go new file mode 100644 index 000000000000..7ed58cdb9f41 --- /dev/null +++ b/x/ibc/03-connection/handler.go @@ -0,0 +1,8 @@ +package connection + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Manager) sdk.Result { +} diff --git a/x/ibc/03-connection/msgs.go b/x/ibc/03-connection/msgs.go new file mode 100644 index 000000000000..71f529927fd6 --- /dev/null +++ b/x/ibc/03-connection/msgs.go @@ -0,0 +1,68 @@ +package connection + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +type MsgOpenInit struct { + ConnectionID string + Connection Connection + CounterpartyClient string + NextTimeout uint64 + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgOpenInit{} + +func (msg MsgOpenInit) Route() string { + return "ibc" +} + +func (msg MsgOpenInit) Type() string { + return "open-init" +} + +func (msg MsgOpenInit) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgOpenInit) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgOpenInit) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + +type MsgOpenTry struct { + ConnectionID string + Connection Connection + CounterpartyClient string + Timeout uint64 + NextTimeout uint64 + Proofs []commitment.Proof + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgOpenTry{} + +type MsgOpenAck struct { + ConnectionID string + Timeout uint64 + NextTimeout uint64 + Proofs []commitment.Proof + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgOpenAck{} + +type MsgOpenConfirm struct { + ConnectionID string + Timeout uint64 + Proofs []commitment.Proof + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgOpenConfirm{} From 503a399a493e7f0d2fdf8f7f8ff351b96b1d00ab Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 17 Jul 2019 15:34:54 +0900 Subject: [PATCH 111/182] add cli/msg/handler --- x/ibc/03-connection/cli.go | 6 +- x/ibc/03-connection/client/cli/tx.go | 160 ++++++++++++++++++++++++++- x/ibc/03-connection/handler.go | 31 +++++- x/ibc/03-connection/handshake.go | 12 +- x/ibc/03-connection/manager.go | 2 +- x/ibc/03-connection/msgs.go | 60 ++++++++++ 6 files changed, 258 insertions(+), 13 deletions(-) diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index e85594ead21b..0f6ed658eba6 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -94,17 +94,17 @@ func (man Handshaker) CLIObject(ctx context.CLIContext, path merkle.Path, id str } } -func (obj CLIHandshakeObject) State(ctx context.CLIContext, root merkle.Root) (res byte, proof merkle.Proof, err error) { +func (obj CLIHandshakeObject) State(ctx context.CLIContext) (res byte, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.StateKey, &res) return } -func (obj CLIHandshakeObject) CounterpartyClient(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { +func (obj CLIHandshakeObject) CounterpartyClient(ctx context.CLIContext) (res string, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.CounterpartyClientKey, &res) return } -func (obj CLIHandshakeObject) Timeout(ctx context.CLIContext, root merkle.Root) (res uint64, proof merkle.Proof, err error) { +func (obj CLIHandshakeObject) NextTimeout(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.TimeoutKey, &res) return } diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index bbbfd8642860..e29a402b2979 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -1,6 +1,7 @@ package cli import ( + "io/ioutil" "strconv" "github.com/spf13/cobra" @@ -16,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -40,11 +42,26 @@ func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, versio return man.CLIObject(ctx, path, id) } +func lastheight(ctx context.CLIContext) (uint64, error) { + node, err := ctx.GetNode() + if err != nil { + return 0, err + } + + info, err := node.ABCIInfo() + if err != nil { + return 0, err + } + + return uint64(info.Response.LastBlockHeight), nil +} + func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "handshake", Short: "initiate connection handshake between two chains", Args: cobra.ExactArgs(4), + // Args: []string{connid1, connfilepath1, connid2, connfilepath2} RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContext(). @@ -57,9 +74,148 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command WithNodeURI(viper.GetString(FlagNode2)). WithFrom(viper.GetString(FlagFrom2)) - obj1 := object(ctx1, cdc, storeKey, ibc.Version, args[0]) - obj2 := object(ctx2, cdc, storeKey, ibc.Version, args[1]) + conn1id := args[0] + conn1bz, err := ioutil.ReadFile(args[1]) + if err != nil { + return err + } + var conn1 connection.Connection + if err := cdc.UnmarshalJSON(conn1bz, &conn1); err != nil { + return err + } + + obj1 := handshake(ctx1, cdc, storeKey, ibc.Version, conn1id) + + conn2id := args[2] + conn2bz, err := ioutil.ReadFile(args[3]) + if err != nil { + return err + } + var conn2 connection.Connection + if err := cdc.UnmarshalJSON(conn2bz, &conn2); err != nil { + return err + } + + obj2 := handshake(ctx2, cdc, storeKey, ibc.Version, conn1id) + + // TODO: check state and if not Idle continue existing process + height, err := lastheight(ctx2) + if err != nil { + return err + } + nextTimeout := height + 1000 // TODO: parameterize + msginit := connection.MsgOpenInit{ + ConnectionID: conn1id, + Connection: conn1, + CounterpartyClient: conn2.Client, + NextTimeout: nextTimeout, + Signer: ctx1.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msginit}) + if err != nil { + return err + } + timeout := nextTimeout + height, err = lastheight(ctx1) + if err != nil { + return err + } + nextTimeout = height + 1000 + _, pconn, err := obj1.Connection(ctx1) + if err != nil { + return err + } + _, pstate, err := obj1.State(ctx1) + if err != nil { + return err + } + _, ptimeout, err := obj1.NextTimeout(ctx1) + if err != nil { + return err + } + _, pcounter, err := obj1.CounterpartyClient(ctx1) + if err != nil { + return err + } + + msgtry := connection.MsgOpenTry{ + ConnectionID: conn2id, + Connection: conn2, + CounterpartyClient: conn1.Client, + Timeout: timeout, + NextTimeout: nextTimeout, + Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Signer: ctx2.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) + if err != nil { + return err + } + + timeout = nextTimeout + height, err = lastheight(ctx2) + if err != nil { + return err + } + nextTimeout = height + 1000 + _, pconn, err = obj2.Connection(ctx2) + if err != nil { + return err + } + _, pstate, err = obj2.State(ctx2) + if err != nil { + return err + } + _, ptimeout, err = obj2.NextTimeout(ctx2) + if err != nil { + return err + } + _, pcounter, err = obj2.CounterpartyClient(ctx2) + if err != nil { + return err + } + + msgack := connection.MsgOpenAck{ + ConnectionID: conn1id, + Timeout: timeout, + NextTimeout: nextTimeout, + Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Signer: ctx1.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgack}) + if err != nil { + return err + } + + timeout = nextTimeout + _, pstate, err = obj1.State(ctx1) + if err != nil { + return err + } + _, ptimeout, err = obj1.NextTimeout(ctx1) + if err != nil { + return err + } + + msgconfirm := connection.MsgOpenConfirm{ + ConnectionID: conn2id, + Timeout: timeout, + Proofs: []commitment.Proof{pstate, ptimeout}, + Signer: ctx2.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgconfirm}) + if err != nil { + return err + } + + return nil }, } + + return cmd } diff --git a/x/ibc/03-connection/handler.go b/x/ibc/03-connection/handler.go index 7ed58cdb9f41..738ba38da7e0 100644 --- a/x/ibc/03-connection/handler.go +++ b/x/ibc/03-connection/handler.go @@ -4,5 +4,34 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Manager) sdk.Result { +func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Result { + _, err := man.OpenInit(ctx, msg.ConnectionID, msg.Connection, msg.CounterpartyClient, msg.NextTimeout) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 100, "").Result() + } + return sdk.Result{} +} + +func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Result { + _, err := man.OpenTry(ctx, msg.Proofs, msg.ConnectionID, msg.Connection, msg.CounterpartyClient, msg.Timeout, msg.NextTimeout) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 200, "").Result() + } + return sdk.Result{} +} + +func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Result { + _, err := man.OpenAck(ctx, msg.Proofs, msg.ConnectionID, msg.Timeout, msg.NextTimeout) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 300, "").Result() + } + return sdk.Result{} +} + +func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) sdk.Result { + _, err := man.OpenConfirm(ctx, msg.Proofs, msg.ConnectionID, msg.Timeout) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 400, "").Result() + } + return sdk.Result{} } diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 467aa664b64b..c8a69c7fb9b5 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -156,7 +156,7 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{connection,state,nextTimeout,counterpartyClient, client} func (man Handshaker) OpenTry(ctx sdk.Context, - connectionp, statep, timeoutp, counterpartyClientp /*, clientp*/ commitment.Proof, + proofs []commitment.Proof, id string, connection Connection, counterpartyClient string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.create(ctx, id, connection, counterpartyClient) @@ -164,7 +164,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, connection.Path, connectionp, statep, timeoutp, counterpartyClientp) + ctx, err = obj.Context(ctx, connection.Path, proofs) if err != nil { return } @@ -222,7 +222,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{connection, state, timeout, counterpartyClient, client} func (man Handshaker) OpenAck(ctx sdk.Context, - connectionp, statep, timeoutp, counterpartyClientp /*, clientp*/ commitment.Proof, + proofs []commitment.Proof, id string /*expheight uint64, */, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) @@ -230,7 +230,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, nil, connectionp, statep, timeoutp, counterpartyClientp) + ctx, err = obj.Context(ctx, nil, proofs) if err != nil { return } @@ -285,7 +285,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // Using proofs: counterparty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, - statep, timeoutp commitment.Proof, + proofs []commitment.Proof, id string, timeoutHeight uint64) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) @@ -293,7 +293,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, nil, statep, timeoutp) + ctx, err = obj.Context(ctx, nil, proofs) if err != nil { return } diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 2663b4dcdcf4..5a693d58c2e4 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -102,7 +102,7 @@ func (man CounterpartyManager) object(id string) CounterObject { } } -func (obj Object) Context(ctx sdk.Context, optpath commitment.Path, proofs ...commitment.Proof) (sdk.Context, error) { +func (obj Object) Context(ctx sdk.Context, optpath commitment.Path, proofs []commitment.Proof) (sdk.Context, error) { if optpath == nil { optpath = obj.Connection(ctx).Path } diff --git a/x/ibc/03-connection/msgs.go b/x/ibc/03-connection/msgs.go index 71f529927fd6..6ec74ef03696 100644 --- a/x/ibc/03-connection/msgs.go +++ b/x/ibc/03-connection/msgs.go @@ -48,6 +48,26 @@ type MsgOpenTry struct { var _ sdk.Msg = MsgOpenTry{} +func (msg MsgOpenTry) Route() string { + return "ibc" +} + +func (msg MsgOpenTry) Type() string { + return "open-init" +} + +func (msg MsgOpenTry) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgOpenTry) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgOpenTry) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + type MsgOpenAck struct { ConnectionID string Timeout uint64 @@ -58,6 +78,26 @@ type MsgOpenAck struct { var _ sdk.Msg = MsgOpenAck{} +func (msg MsgOpenAck) Route() string { + return "ibc" +} + +func (msg MsgOpenAck) Type() string { + return "open-init" +} + +func (msg MsgOpenAck) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgOpenAck) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgOpenAck) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + type MsgOpenConfirm struct { ConnectionID string Timeout uint64 @@ -66,3 +106,23 @@ type MsgOpenConfirm struct { } var _ sdk.Msg = MsgOpenConfirm{} + +func (msg MsgOpenConfirm) Route() string { + return "ibc" +} + +func (msg MsgOpenConfirm) Type() string { + return "open-init" +} + +func (msg MsgOpenConfirm) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgOpenConfirm) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgOpenConfirm) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} From 3351a6adfef50a20db093fc8c718df887746ed7e Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 18 Jul 2019 03:02:41 +0900 Subject: [PATCH 112/182] add CLIQuery, fix tests --- x/ibc/03-connection/cli.go | 40 ++++++++++++++++++------- x/ibc/03-connection/client/cli/query.go | 2 +- x/ibc/03-connection/client/cli/tx.go | 2 +- x/ibc/03-connection/tests/types.go | 15 +++++----- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 0f6ed658eba6..a9617d4b0e38 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -23,24 +23,30 @@ type CLIObject struct { Cdc *codec.Codec } -func (man Manager) CLIObject(ctx context.CLIContext, path merkle.Path, id string) CLIObject { +func (man Manager) CLIQuery(ctx context.CLIContext, path merkle.Path, id string) CLIObject { + res := man.CLIObject(path, id, "") + + connection, _, err := res.Connection(ctx) + if err != nil { + return res + } + res.Client = man.client.CLIObject(path, connection.Client) + return res +} + +func (man Manager) CLIObject(path merkle.Path, id, clientid string) CLIObject { obj := man.object(id) - res := CLIObject{ + return CLIObject{ ID: obj.id, ConnectionKey: obj.connection.Key(), AvailableKey: obj.available.Key(), KindKey: obj.kind.Key(), + Client: man.client.CLIObject(path, clientid), + StoreName: man.protocol.StoreName(), Cdc: obj.connection.Cdc(), } - - connection, _, err := res.Connection(ctx) - if err != nil { - return res - } - res.Client = man.client.CLIObject(path, connection.Client) - return res } func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { @@ -83,10 +89,10 @@ type CLIHandshakeObject struct { TimeoutKey []byte } -func (man Handshaker) CLIObject(ctx context.CLIContext, path merkle.Path, id string) CLIHandshakeObject { +func (man Handshaker) CLIQuery(ctx context.CLIContext, path merkle.Path, id string) CLIHandshakeObject { obj := man.object(man.man.object(id)) return CLIHandshakeObject{ - CLIObject: man.man.CLIObject(ctx, path, id), + CLIObject: man.man.CLIQuery(ctx, path, id), StateKey: obj.state.Key(), CounterpartyClientKey: obj.counterpartyClient.Key(), @@ -94,6 +100,18 @@ func (man Handshaker) CLIObject(ctx context.CLIContext, path merkle.Path, id str } } +func (man Handshaker) CLIObject(path merkle.Path, id, clientid string) CLIHandshakeObject { + obj := man.object(man.man.object(id)) + return CLIHandshakeObject{ + CLIObject: man.man.CLIObject(path, id, clientid), + + StateKey: obj.state.Key(), + CounterpartyClientKey: obj.counterpartyClient.Key(), + TimeoutKey: obj.nextTimeout.Key(), + } + +} + func (obj CLIHandshakeObject) State(ctx context.CLIContext) (res byte, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.StateKey, &res) return diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index da606af27c50..efc30534e913 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -30,7 +30,7 @@ func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version i base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) climan := client.NewManager(base) man := connection.NewManager(base, climan) - return man.CLIObject(ctx, path, id) + return man.CLIQuery(ctx, path, id) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index e29a402b2979..0aaa1c5cda27 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -39,7 +39,7 @@ func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, versio base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) climan := client.NewManager(base) man := connection.NewHandshaker(connection.NewManager(base, climan)) - return man.CLIObject(ctx, path, id) + return man.CLIQuery(ctx, path, id) } func lastheight(ctx context.CLIContext) (uint64, error) { diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 608446439be0..0b4444b05338 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -93,15 +93,14 @@ func (node *Node) CLIObject() connection.CLIHandshakeObject { return connection.NewHandshaker(man).CLIObject(node.Path, node.Name, node.Name) } -func base(cdc *codec.Codec, key sdk.StoreKey) (state.Base, state.Base) { +func base(cdc *codec.Codec, key sdk.StoreKey) state.Base { protocol := state.NewBase(cdc, key, []byte("protocol")) - free := state.NewBase(cdc, key, []byte("free")) - return protocol, free + return protocol } func (node *Node) Manager() (client.Manager, connection.Manager) { - protocol, free := base(node.Cdc, node.Key) - clientman := client.NewManager(protocol, free) + protocol := base(node.Cdc, node.Key) + clientman := client.NewManager(protocol) return clientman, connection.NewManager(protocol, clientman) } @@ -118,7 +117,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, proofs[0], proofs[1], proofs[2], proofs[3], node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs, node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.OpenTry, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) @@ -129,7 +128,7 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, proofs[0], proofs[1], proofs[2], proofs[3], node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) @@ -139,7 +138,7 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, proofs[0], proofs[1], node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs, node.Name, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State(ctx)) require.Equal(t, node.Connection, obj.Connection(ctx)) From bed527607a2645995cf67e19ede49b29671183ad Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 19 Jul 2019 00:55:18 +0900 Subject: [PATCH 113/182] fix golangci --- x/ibc/03-connection/msgs.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/x/ibc/03-connection/msgs.go b/x/ibc/03-connection/msgs.go index 6ec74ef03696..3944599ff6a3 100644 --- a/x/ibc/03-connection/msgs.go +++ b/x/ibc/03-connection/msgs.go @@ -6,6 +6,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) +const Route = "ibc" + type MsgOpenInit struct { ConnectionID string Connection Connection @@ -17,7 +19,7 @@ type MsgOpenInit struct { var _ sdk.Msg = MsgOpenInit{} func (msg MsgOpenInit) Route() string { - return "ibc" + return Route } func (msg MsgOpenInit) Type() string { @@ -49,11 +51,11 @@ type MsgOpenTry struct { var _ sdk.Msg = MsgOpenTry{} func (msg MsgOpenTry) Route() string { - return "ibc" + return Route } func (msg MsgOpenTry) Type() string { - return "open-init" + return "open-try" } func (msg MsgOpenTry) ValidateBasic() sdk.Error { @@ -79,11 +81,11 @@ type MsgOpenAck struct { var _ sdk.Msg = MsgOpenAck{} func (msg MsgOpenAck) Route() string { - return "ibc" + return Route } func (msg MsgOpenAck) Type() string { - return "open-init" + return "open-ack" } func (msg MsgOpenAck) ValidateBasic() sdk.Error { @@ -108,11 +110,11 @@ type MsgOpenConfirm struct { var _ sdk.Msg = MsgOpenConfirm{} func (msg MsgOpenConfirm) Route() string { - return "ibc" + return Route } func (msg MsgOpenConfirm) Type() string { - return "open-init" + return "open-confirm" } func (msg MsgOpenConfirm) ValidateBasic() sdk.Error { From 02a9ba541cc09a127d759300ebedf497671de5ef Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 30 Jul 2019 17:46:12 +0900 Subject: [PATCH 114/182] add godoc in progress --- x/ibc/02-client/types.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go index 2a34855085b9..134837a43aa8 100644 --- a/x/ibc/02-client/types.go +++ b/x/ibc/02-client/types.go @@ -5,15 +5,24 @@ import ( ) // TODO: types in this file should be (de/)serialized with proto in the future -// currently amkno codec handles it +// currently amino codec handles it -// ConsensusState +// ConsensusState is the state of the consensus process. type ConsensusState interface { + // Kind() is the kind of the consensus algorithm. Kind() Kind GetHeight() uint64 + + // GetRoot() returns the commitment root of the consensus state, + // which is used for key-value pair verification. GetRoot() commitment.Root + + // Validate() returns the updated consensus state + // only if the header is a descendent of this consensus state. Validate(Header) (ConsensusState, error) // ValidityPredicate - Equivocation(Header, Header) bool // EquivocationPredicate + + // Equivocation checks two headers' confliction. + Equivocation(Header, Header) bool // EquivocationPredicate } /* @@ -23,8 +32,11 @@ func Equal(client1, client2 ConsensusState) bool { } */ +// Header is the consensus state update information. type Header interface { + // Kind() is the kind of the consensus algorithm. Kind() Kind + GetHeight() uint64 } From 54a67b0b2106522dd65a80453abefe0585eef13c Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 31 Jul 2019 17:46:32 +0900 Subject: [PATCH 115/182] modify store --- x/ibc/02-client/cli.go | 42 +++---------- x/ibc/02-client/client/cli/query.go | 10 +-- x/ibc/02-client/manager.go | 74 +++++++++++------------ x/ibc/23-commitment/merkle/merkle.go | 16 ++++- x/ibc/23-commitment/merkle/merkle_test.go | 6 +- x/ibc/23-commitment/merkle/utils.go | 26 +++++++- 6 files changed, 92 insertions(+), 82 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 382b1d2d4aea..d4a02a028c3a 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -2,53 +2,29 @@ package client import ( "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -// CLIObject stores the key for each object fields type CLIObject struct { - ID string - ConsensusStateKey []byte - FrozenKey []byte - - Path merkle.Path - Cdc *codec.Codec + obj Object } -func (man Manager) CLIObject(path merkle.Path, id string) CLIObject { - obj := man.object(id) - return CLIObject{ - ID: id, - ConsensusStateKey: obj.consensusState.Key(), - FrozenKey: obj.frozen.Key(), - - Path: path, - Cdc: obj.consensusState.Cdc(), - } +func (obj Object) CLIObject() CLIObject { + return CLIObject{obj} } -func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { - resp, err := ctx.QueryABCI(obj.Path.RequestQuery(key)) - if err != nil { - return merkle.Proof{}, err - } - proof := merkle.Proof{ - Key: key, - Proof: resp.Proof, - } - err = obj.Cdc.UnmarshalBinaryBare(resp.Value, ptr) - return proof, err - -} +// (path, ) func (obj CLIObject) ConsensusState(ctx context.CLIContext) (res ConsensusState, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.ConsensusStateKey, &res) + tmproof, err := obj.obj.ConsensusState.Query(ctx, &res) + proof = merkle.NewProofFromValue(tmproof, obj.obj.ConsensusState) return } func (obj CLIObject) Frozen(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.FrozenKey, &res) + res, tmproof, err := obj.obj.Frozen.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, obj.obj.Frozen) return } + diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index fb2c7f73da0e..ed044444eeb8 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -15,15 +15,15 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func components(cdc *codec.Codec, storeKey string, version int64) (path merkle.Path, base state.Base) { +func components(cdc *codec.Codec, storeKey string, version int64) (path merkle.Path, mapp state.Mapping) { prefix := []byte(strconv.FormatInt(version, 10) + "/") path = merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) - base = state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) + mapp = state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) return } @@ -50,8 +50,8 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - path, base := components(cdc, storeKey, ibc.Version) - man := client.NewManager(base) + path, mapp := components(cdc, storeKey, ibc.Version) + man := client.NewManager(mapp) id := args[0] state, _, err := man.CLIObject(path, id).ConsensusState(ctx) diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 4f5195bc1850..fe69a59caa05 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -3,21 +3,21 @@ package client import ( "errors" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -// XXX: implement spec: ClientState.verifiedRoots - +// Any actor holding the Manager can access on and modify any client information type Manager struct { protocol state.Mapping } -func NewManager(protocol state.Base) Manager { +func NewManager(base state.Mapping) Manager { return Manager{ - protocol: state.NewMapping(protocol, []byte("/client")), + protocol: base.Prefix([]byte("/client")), } } @@ -25,9 +25,9 @@ type CounterpartyManager struct { protocol commitment.Mapping } -func NewCounterpartyManager(protocol commitment.Base) CounterpartyManager { +func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { return CounterpartyManager{ - protocol: commitment.NewMapping(protocol, []byte("/client")), + protocol: commitment.NewMapping(cdc, []byte("/client")), } } @@ -40,72 +40,69 @@ func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { return man } */ -func (man Manager) object(id string) Object { +func (man Manager) Object(id string) Object { return Object{ id: id, - consensusState: man.protocol.Value([]byte(id)), - frozen: state.NewBoolean(man.protocol.Value([]byte(id + "/freeze"))), + ConsensusState: man.protocol.Value([]byte(id)), + Frozen: man.protocol.Value([]byte(id + "/freeze")).Boolean(), } } func (man Manager) Create(ctx sdk.Context, id string, cs ConsensusState) (Object, error) { - obj := man.object(id) + obj := man.Object(id) if obj.exists(ctx) { return Object{}, errors.New("Create client on already existing id") } - obj.consensusState.Set(ctx, cs) + obj.ConsensusState.Set(ctx, cs) return obj, nil } func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { - res := man.object(id) + res := man.Object(id) if !res.exists(ctx) { return Object{}, errors.New("client not exists") } return res, nil } -func (man CounterpartyManager) object(id string) CounterObject { +func (man CounterpartyManager) Object(id string) CounterObject { return CounterObject{ id: id, - consensusState: man.protocol.Value([]byte(id)), + ConsensusState: man.protocol.Value([]byte(id)), } } func (man CounterpartyManager) Query(id string) CounterObject { - return man.object(id) + return man.Object(id) } +// Any actor holding the Object can access on and modify that client information type Object struct { id string - consensusState state.Value // ConsensusState - frozen state.Boolean + ConsensusState state.Value // ConsensusState + Frozen state.Boolean } type CounterObject struct { id string - consensusState commitment.Value + ConsensusState commitment.Value } func (obj Object) ID() string { return obj.id } -func (obj Object) ConsensusState(ctx sdk.Context) (res ConsensusState) { - obj.consensusState.Get(ctx, &res) +func (obj Object) GetConsensusState(ctx sdk.Context) (res ConsensusState) { + obj.ConsensusState.Get(ctx, &res) return } -func (obj Object) Frozen(ctx sdk.Context) bool { - return obj.frozen.Get(ctx) -} - func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { - return obj.consensusState.Is(ctx, client) + return obj.ConsensusState.Is(ctx, client) } func (obj Object) exists(ctx sdk.Context) bool { - return obj.consensusState.Exists(ctx) + return obj.ConsensusState.Exists(ctx) } func (obj Object) Update(ctx sdk.Context, header Header) error { @@ -113,18 +110,17 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { panic("should not update nonexisting client") } - if obj.Frozen(ctx) { - return errors.New("client is frozen") + if obj.Frozen.Get(ctx) { + return errors.New("client is Frozen") } - var stored ConsensusState - obj.consensusState.Get(ctx, &stored) + stored := obj.GetConsensusState(ctx) updated, err := stored.Validate(header) if err != nil { return err } - obj.consensusState.Set(ctx, updated) + obj.ConsensusState.Set(ctx, updated) return nil } @@ -134,11 +130,11 @@ func (obj Object) Freeze(ctx sdk.Context) error { panic("should not freeze nonexisting client") } - if obj.Frozen(ctx) { - return errors.New("client is already frozen") + if obj.Frozen.Get(ctx) { + return errors.New("client is already Frozen") } - obj.frozen.Set(ctx, true) + obj.Frozen.Set(ctx, true) return nil } @@ -148,12 +144,12 @@ func (obj Object) Delete(ctx sdk.Context) error { panic("should not delete nonexisting client") } - if !obj.Frozen(ctx) { - return errors.New("client is not frozen") + if !obj.Frozen.Get(ctx) { + return errors.New("client is not Frozen") } - obj.consensusState.Delete(ctx) - obj.frozen.Delete(ctx) + obj.ConsensusState.Delete(ctx) + obj.Frozen.Delete(ctx) return nil } diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index a5acbdd43c3a..9e0b5e6b1152 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -6,8 +6,9 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" "github.com/cosmos/cosmos-sdk/store/rootmulti" + "github.com/cosmos/cosmos-sdk/store/state" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) const merkleKind = "merkle" @@ -57,6 +58,10 @@ func (Path) CommitmentKind() string { return merkleKind } +func NewPathFromMapping(mapp state.Mapping) Path { + return NewPath([][]byte{[]byte(mapp.StoreName())}, mapp.PrefixBytes()) +} + var _ commitment.Proof = Proof{} // Proof is Merkle proof with the key information. @@ -101,3 +106,12 @@ func (proof Proof) Verify(croot commitment.Root, cpath commitment.Path, value [] } return runtime.VerifyAbsence(proof.Proof, root.Hash, keypath.String()) } + +type Value interface { + KeyBytes() []byte + Unmarshal([]byte, interface{}) +} + +func NewProofFromValue(proof *merkle.Proof, value Value) Proof { + return Proof{proof, value.KeyBytes()} +} diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index fab3880a06a0..4c4f49ce274a 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -65,7 +65,7 @@ func TestStore(t *testing.T) { // Test query, and accumulate proofs proofs := make([]commitment.Proof, 0, kvpn) for k, v := range m { - c, v0, p := path.Query(cms, []byte(k)) + c, v0, p := path.QueryMultiStore(cms, []byte(k)) require.Equal(t, uint32(0), c) require.Equal(t, v, v0) proofs = append(proofs, p) @@ -75,7 +75,7 @@ func TestStore(t *testing.T) { for i := 0; i < 100; i++ { k := make([]byte, 64) rand.Read(k) - c, v, p := path.Query(cms, k) + c, v, p := path.QueryMultiStore(cms, k) require.Equal(t, uint32(0), c) require.Nil(t, v) proofs = append(proofs, p) @@ -107,7 +107,7 @@ func TestStore(t *testing.T) { // Test query, and accumulate proofs proofs = make([]commitment.Proof, 0, kvpn) for k, v := range m { - c, v0, p := path.Query(cms, []byte(k)) + c, v0, p := path.QueryMultiStore(cms, []byte(k)) require.Equal(t, uint32(0), c) require.Equal(t, v, v0) proofs = append(proofs, p) diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index e1659d696432..b8497c757cae 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -1,8 +1,12 @@ package merkle import ( + "errors" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -28,12 +32,32 @@ func (path Path) RequestQueryMultiStore(key []byte) abci.RequestQuery { return abci.RequestQuery{Path: path.Path() + "/key", Data: path.Key(key), Prove: true} } +func (path Path) Query(ctx context.CLIContext, key []byte) (code uint32, value []byte, proof Proof, err error) { + resp, err := ctx.QueryABCI(path.RequestQuery(key)) + if err != nil { + return code, value, proof, err + } + if !resp.IsOK() { + return resp.Code, value, proof, errors.New(resp.Log) + } + return resp.Code, resp.Value, Proof{Key: key, Proof: resp.Proof}, nil +} + +func (path Path) QueryValue(ctx context.CLIContext, cdc *codec.Codec, key []byte, ptr interface{}) (Proof, error) { + _, value, proof, err := path.Query(ctx, key) + if err != nil { + return Proof{}, err + } + err = cdc.UnmarshalBinaryBare(value, ptr) // TODO + return proof, err +} + func (path Path) QueryMultiStore(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { queryable, ok := cms.(types.Queryable) if !ok { panic("CommitMultiStore not queryable") } - qres := queryable.Query(path.RequestQuery(key)) + qres := queryable.Query(path.RequestQueryMultiStore(key)) return qres.Code, qres.Value, Proof{Key: key, Proof: qres.Proof} } From e7f67085a8411f0c4f10f0ab4056da321b6a145b Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 31 Jul 2019 22:42:51 +0900 Subject: [PATCH 116/182] cli refactor in progress --- x/ibc/02-client/cli.go | 2 -- x/ibc/02-client/client/cli/query.go | 10 ++++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index d4a02a028c3a..acf0ecc2218c 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -14,8 +14,6 @@ func (obj Object) CLIObject() CLIObject { return CLIObject{obj} } -// (path, ) - func (obj CLIObject) ConsensusState(ctx context.CLIContext) (res ConsensusState, proof merkle.Proof, err error) { tmproof, err := obj.obj.ConsensusState.Query(ctx, &res) proof = merkle.NewProofFromValue(tmproof, obj.obj.ConsensusState) diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index ed044444eeb8..6232d50e2a5f 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -20,11 +20,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func components(cdc *codec.Codec, storeKey string, version int64) (path merkle.Path, mapp state.Mapping) { +func mapping(cdc *codec.Codec, storeKey string, version int64) state.Mapping { prefix := []byte(strconv.FormatInt(version, 10) + "/") - path = merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) - mapp = state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) - return + return state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -50,11 +48,11 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - path, mapp := components(cdc, storeKey, ibc.Version) + mapp := mapping(cdc, storeKey, ibc.Version) man := client.NewManager(mapp) id := args[0] - state, _, err := man.CLIObject(path, id).ConsensusState(ctx) + state, _, err := man.Object(id).CLIObject().ConsensusState(ctx) if err != nil { return err } From 0d134d5e61afad671cde87c02a1a217edd19f63c Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 31 Jul 2019 22:43:20 +0900 Subject: [PATCH 117/182] cli refactor in progress --- x/ibc/23-commitment/merkle/merkle.go | 7 ++- x/ibc/23-commitment/merkle/merkle_test.go | 32 ++++++----- x/ibc/23-commitment/merkle/utils.go | 67 ++++++++++++++--------- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index 9e0b5e6b1152..615b49ccadb9 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -1,6 +1,7 @@ package merkle import ( + "bytes" "errors" "github.com/tendermint/tendermint/crypto/merkle" @@ -109,9 +110,9 @@ func (proof Proof) Verify(croot commitment.Root, cpath commitment.Path, value [] type Value interface { KeyBytes() []byte - Unmarshal([]byte, interface{}) } -func NewProofFromValue(proof *merkle.Proof, value Value) Proof { - return Proof{proof, value.KeyBytes()} +func NewProofFromValue(proof *merkle.Proof, path Path, value Value) Proof { + // TODO: check HasPrefix + return Proof{proof, bytes.TrimPrefix(value.KeyBytes(), path.KeyPrefix)} } diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index 4c4f49ce274a..3c49a2dee82b 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/state" "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -40,23 +41,24 @@ func commit(cms types.CommitMultiStore) Root { // TestStore tests Merkle proof on the commitment.Store // Sets/upates key-value pairs and prove with the query result proofs func TestStore(t *testing.T) { - k, ctx, cms, _ := defaultComponents() - kvstore := ctx.KVStore(k) - path := Path{KeyPath: [][]byte{[]byte("test")}, KeyPrefix: []byte{0x01, 0x03, 0x05}} + k, ctx, cms, cdc := defaultComponents() + prefix := []byte{0x01, 0x03, 0x05, 0xAA, 0xBB} + mapp := state.NewMapping(k, cdc, prefix) + path := NewPath([][]byte{[]byte(k.Name())}, prefix) m := make(map[string][]byte) - kvpn := 1000 + kvpn := 10 - // Repeat 100 times to test on multiple commits + // Repeat to test on multiple commits for repeat := 0; repeat < 10; repeat++ { // Initializes random generated key-value pairs for i := 0; i < kvpn; i++ { - k, v := make([]byte, 64), make([]byte, 64) + k, v := make([]byte, 16), make([]byte, 16) rand.Read(k) rand.Read(v) m[string(k)] = v - kvstore.Set(path.Key(k), v) + mapp.Value(k).Set(ctx, v) } // Commit store @@ -65,18 +67,18 @@ func TestStore(t *testing.T) { // Test query, and accumulate proofs proofs := make([]commitment.Proof, 0, kvpn) for k, v := range m { - c, v0, p := path.QueryMultiStore(cms, []byte(k)) - require.Equal(t, uint32(0), c) + v0, p, err := QueryMultiStore(cms, path, []byte(k)) + require.NoError(t, err) require.Equal(t, v, v0) proofs = append(proofs, p) } // Add some exclusion proofs - for i := 0; i < 100; i++ { + for i := 0; i < 10; i++ { k := make([]byte, 64) rand.Read(k) - c, v, p := path.QueryMultiStore(cms, k) - require.Equal(t, uint32(0), c) + v, p, err := QueryMultiStore(cms, path, k) + require.NoError(t, err) require.Nil(t, v) proofs = append(proofs, p) m[string(k)] = []byte{} @@ -99,7 +101,7 @@ func TestStore(t *testing.T) { v := make([]byte, 64) rand.Read(v) m[k] = v - kvstore.Set(path.Key([]byte(k)), v) + mapp.Value([]byte(k)).Set(ctx, v) } root = commit(cms) @@ -107,8 +109,8 @@ func TestStore(t *testing.T) { // Test query, and accumulate proofs proofs = make([]commitment.Proof, 0, kvpn) for k, v := range m { - c, v0, p := path.QueryMultiStore(cms, []byte(k)) - require.Equal(t, uint32(0), c) + v0, p, err := QueryMultiStore(cms, path, []byte(k)) + require.NoError(t, err) require.Equal(t, v, v0) proofs = append(proofs, p) } diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index b8497c757cae..4dbd6cb292ec 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -1,15 +1,53 @@ package merkle import ( + "bytes" "errors" + "fmt" abci "github.com/tendermint/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/types" ) +func QueryMultiStore(cms types.CommitMultiStore, path Path, key []byte) ([]byte, Proof, error) { + queryable, ok := cms.(types.Queryable) + if !ok { + panic("CommitMultiStore not queryable") + } + qres := queryable.Query(RequestQueryMultiStore(path, key)) + if !qres.IsOK() { + return nil, Proof{}, errors.New(qres.Log) + } + + fmt.Printf("Q: %X -> %X\n", path.Key(key), qres.Value) + return qres.Value, Proof{Key: key, Proof: qres.Proof}, nil +} + +func RequestQueryMultiStore(path Path, key []byte) abci.RequestQuery { + // Suffixing path with "/key". + // iavl.Store.Query() switches over the last path element, + // and performs key-value query only if it is "/key" + return abci.RequestQuery{ + Path: "/" + string(bytes.Join(path.KeyPath, []byte("/"))) + "/key", + Data: path.Key(key), + Prove: true, + } +} + +func (path Path) Key(key []byte) []byte { + return join(path.KeyPrefix, key) +} + +func join(a, b []byte) (res []byte) { + res = make([]byte, len(a)+len(b)) + copy(res, a) + copy(res[len(a):], b) + return +} + +/* + // RequestQuery() constructs the abci.RequestQuery. // // RequestQuery.Path is a slash separated key list, ending with "/key" @@ -25,12 +63,6 @@ func (path Path) RequestQuery(key []byte) abci.RequestQuery { return req } -func (path Path) RequestQueryMultiStore(key []byte) abci.RequestQuery { - // Suffixing path with "/key". - // iavl.Store.Query() switches over the last path element, - // and performs key-value query only if it is "/key" - return abci.RequestQuery{Path: path.Path() + "/key", Data: path.Key(key), Prove: true} -} func (path Path) Query(ctx context.CLIContext, key []byte) (code uint32, value []byte, proof Proof, err error) { resp, err := ctx.QueryABCI(path.RequestQuery(key)) @@ -52,25 +84,9 @@ func (path Path) QueryValue(ctx context.CLIContext, cdc *codec.Codec, key []byte return proof, err } -func (path Path) QueryMultiStore(cms types.CommitMultiStore, key []byte) (uint32, []byte, Proof) { - queryable, ok := cms.(types.Queryable) - if !ok { - panic("CommitMultiStore not queryable") - } - qres := queryable.Query(path.RequestQueryMultiStore(key)) - return qres.Code, qres.Value, Proof{Key: key, Proof: qres.Proof} -} -func (path Path) Key(key []byte) []byte { - return join(path.KeyPrefix, key) -} -func join(a, b []byte) (res []byte) { - res = make([]byte, len(a)+len(b)) - copy(res, a) - copy(res[len(a):], b) - return -} + func (path Path) Path() string { pathstr := "" @@ -81,3 +97,4 @@ func (path Path) Path() string { return pathstr } +*/ From 62b7d75ebe3718b9b016a1bbb7c479650c7ce68c Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 1 Aug 2019 23:41:12 +0900 Subject: [PATCH 118/182] fix cli / merkle test --- x/ibc/02-client/cli.go | 20 ++++++-------------- x/ibc/02-client/client/cli/query.go | 8 ++++---- x/ibc/02-client/tendermint/tests/types.go | 4 ++-- x/ibc/23-commitment/merkle/merkle_test.go | 8 ++++---- x/ibc/23-commitment/merkle/utils.go | 2 -- 5 files changed, 16 insertions(+), 26 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index acf0ecc2218c..aa563f3c170b 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -6,23 +6,15 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -type CLIObject struct { - obj Object -} - -func (obj Object) CLIObject() CLIObject { - return CLIObject{obj} -} - -func (obj CLIObject) ConsensusState(ctx context.CLIContext) (res ConsensusState, proof merkle.Proof, err error) { - tmproof, err := obj.obj.ConsensusState.Query(ctx, &res) - proof = merkle.NewProofFromValue(tmproof, obj.obj.ConsensusState) +func (obj Object) ConsensusStateCLI(ctx context.CLIContext, path merkle.Path) (res ConsensusState, proof merkle.Proof, err error) { + tmproof, err := obj.ConsensusState.Query(ctx, &res) + proof = merkle.NewProofFromValue(tmproof, path, obj.ConsensusState) return } -func (obj CLIObject) Frozen(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - res, tmproof, err := obj.obj.Frozen.Query(ctx) - proof = merkle.NewProofFromValue(tmproof, obj.obj.Frozen) +func (obj Object) FrozenCLI(ctx context.CLIContext, path merkle.Path) (res bool, proof merkle.Proof, err error) { + res, tmproof, err := obj.Frozen.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, path, obj.Frozen) return } diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 6232d50e2a5f..1cf445dae389 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -20,9 +20,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func mapping(cdc *codec.Codec, storeKey string, version int64) state.Mapping { +func mapping(cdc *codec.Codec, storeKey string, version int64) (state.Mapping, merkle.Path) { prefix := []byte(strconv.FormatInt(version, 10) + "/") - return state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) + return state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix), merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -48,11 +48,11 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - mapp := mapping(cdc, storeKey, ibc.Version) + mapp, path := mapping(cdc, storeKey, ibc.Version) man := client.NewManager(mapp) id := args[0] - state, _, err := man.Object(id).CLIObject().ConsensusState(ctx) + state, _, err := man.Object(id).ConsensusStateCLI(ctx, path) if err != nil { return err } diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index f9fd9fc9f0c8..40caa5d6f041 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -143,8 +143,8 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock } func (node *Node) Query(t *testing.T, path merkle.Path, k []byte) ([]byte, commitment.Proof) { - code, value, proof := path.QueryMultiStore(node.Cms, k) - require.Equal(t, uint32(0), code) + value, proof, err := merkle.QueryMultiStore(node.Cms, path, k) + require.NoError(t, err) return value, proof } diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index 3c49a2dee82b..2624d54eccde 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -69,7 +69,7 @@ func TestStore(t *testing.T) { for k, v := range m { v0, p, err := QueryMultiStore(cms, path, []byte(k)) require.NoError(t, err) - require.Equal(t, v, v0) + require.Equal(t, cdc.MustMarshalBinaryBare(v), v0, "Queried value different at %d", repeat) proofs = append(proofs, p) } @@ -90,7 +90,7 @@ func TestStore(t *testing.T) { // Test commitment store for k, v := range m { if len(v) != 0 { - require.True(t, cstore.Prove([]byte(k), v)) + require.True(t, cstore.Prove([]byte(k), cdc.MustMarshalBinaryBare(v))) } else { require.True(t, cstore.Prove([]byte(k), nil)) } @@ -111,7 +111,7 @@ func TestStore(t *testing.T) { for k, v := range m { v0, p, err := QueryMultiStore(cms, path, []byte(k)) require.NoError(t, err) - require.Equal(t, v, v0) + require.Equal(t, cdc.MustMarshalBinaryBare(v), v0) proofs = append(proofs, p) } @@ -121,7 +121,7 @@ func TestStore(t *testing.T) { // Test commitment store for k, v := range m { if len(v) != 0 { - require.True(t, cstore.Prove([]byte(k), v)) + require.True(t, cstore.Prove([]byte(k), cdc.MustMarshalBinaryBare(v))) } else { require.True(t, cstore.Prove([]byte(k), nil)) } diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index 4dbd6cb292ec..b71d4500963b 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -3,7 +3,6 @@ package merkle import ( "bytes" "errors" - "fmt" abci "github.com/tendermint/tendermint/abci/types" @@ -20,7 +19,6 @@ func QueryMultiStore(cms types.CommitMultiStore, path Path, key []byte) ([]byte, return nil, Proof{}, errors.New(qres.Log) } - fmt.Printf("Q: %X -> %X\n", path.Key(key), qres.Value) return qres.Value, Proof{Key: key, Proof: qres.Proof}, nil } From 7286fed7868a390be026fa32610b9701e1e81793 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 15 Aug 2019 02:22:47 +0900 Subject: [PATCH 119/182] fix test --- store/state/value.go | 12 ++ x/ibc/02-client/keys.go | 5 + x/ibc/02-client/manager.go | 4 +- .../tendermint/tests/tendermint_test.go | 4 +- x/ibc/02-client/tendermint/tests/types.go | 30 ++-- x/ibc/02-client/tendermint/tests/utils.go | 8 + x/ibc/03-connection/cli.go | 142 +++-------------- x/ibc/03-connection/client/cli/query.go | 6 +- x/ibc/03-connection/handshake.go | 150 ++++++++---------- x/ibc/03-connection/keys.go | 5 + x/ibc/03-connection/manager.go | 90 +++++------ x/ibc/03-connection/tests/connection_test.go | 20 +-- x/ibc/03-connection/tests/types.go | 52 +++--- x/ibc/23-commitment/merkle/merkle.go | 6 +- x/ibc/23-commitment/merkle/merkle_test.go | 9 +- x/ibc/23-commitment/merkle/utils.go | 11 +- x/ibc/23-commitment/store.go | 10 +- x/ibc/23-commitment/value.go | 8 +- 18 files changed, 248 insertions(+), 324 deletions(-) create mode 100644 x/ibc/02-client/keys.go create mode 100644 x/ibc/02-client/tendermint/tests/utils.go create mode 100644 x/ibc/03-connection/keys.go diff --git a/store/state/value.go b/store/state/value.go index c54445f59e9f..c3b4b3089bbc 100644 --- a/store/state/value.go +++ b/store/state/value.go @@ -95,6 +95,18 @@ func (v Value) Delete(ctx Context) { v.store(ctx).Delete(v.KeyBytes()) } +func (v Value) StoreName() string { + return v.m.StoreName() +} + +func (v Value) PrefixBytes() []byte { + return v.m.PrefixBytes() +} + +func (v Value) KeyBytesRaw() []byte { + return v.key +} + // KeyBytes() returns the prefixed key that the Value is providing to the KVStore func (v Value) KeyBytes() []byte { return v.m.KeyBytes(v.key) diff --git a/x/ibc/02-client/keys.go b/x/ibc/02-client/keys.go new file mode 100644 index 000000000000..a67761f20d36 --- /dev/null +++ b/x/ibc/02-client/keys.go @@ -0,0 +1,5 @@ +package client + +func LocalRoot() []byte { + return []byte("client/") +} diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index fe69a59caa05..eb9a83ff7d2e 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -17,7 +17,7 @@ type Manager struct { func NewManager(base state.Mapping) Manager { return Manager{ - protocol: base.Prefix([]byte("/client")), + protocol: base.Prefix(LocalRoot()), } } @@ -27,7 +27,7 @@ type CounterpartyManager struct { func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { return CounterpartyManager{ - protocol: commitment.NewMapping(cdc, []byte("/client")), + protocol: commitment.NewMapping(cdc, LocalRoot()), } } diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index df63032b3986..e7d09644126a 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -4,12 +4,10 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10), merkle.NewPath([][]byte{[]byte("f8wib")}, []byte{0x98, 0x78})) + node := NewNode(NewMockValidators(100, 10), "f8wib", []byte{0x98, 0x78}) _ = node.Commit() diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index c27ad9837822..027d3a28a5f5 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -3,6 +3,7 @@ package tendermint import ( "crypto/rand" "testing" + "bytes" "github.com/stretchr/testify/require" @@ -50,11 +51,12 @@ type Node struct { Commits []tmtypes.SignedHeader - Path merkle.Path + StoreName string + Prefix []byte } -func NewNode(valset MockValidators, path merkle.Path) *Node { - key, ctx, cms, _ := defaultComponents(string(path.KeyPath[0])) +func NewNode(valset MockValidators, storeName string, prefix []byte) *Node { + key, ctx, cms, _ := defaultComponents(storeName) return &Node{ Valset: valset, @@ -62,10 +64,15 @@ func NewNode(valset MockValidators, path merkle.Path) *Node { Key: key, Store: ctx.KVStore(key), Commits: nil, - Path: path, + StoreName: storeName, + Prefix: prefix, } } +func (node *Node) Path() merkle.Path { + return merkle.NewPath([][]byte{[]byte(node.StoreName)}, node.Prefix) +} + func (node *Node) Last() tmtypes.SignedHeader { if len(node.Commits) == 0 { return tmtypes.SignedHeader{} @@ -143,19 +150,22 @@ func (v *Verifier) Validate(header tendermint.Header, valset, nextvalset MockVal } -func (node *Node) Query(t *testing.T, path merkle.Path, k []byte) ([]byte, commitment.Proof) { - value, proof, err := merkle.QueryMultiStore(node.Cms, path, k) +func (node *Node) Query(t *testing.T, k []byte) ([]byte, commitment.Proof) { + if bytes.HasPrefix(k, node.Prefix) { + k = bytes.TrimPrefix(k, node.Prefix) + } + value, proof, err := merkle.QueryMultiStore(node.Cms, node.StoreName, node.Prefix, k) require.NoError(t, err) return value, proof } func (node *Node) Set(k, value []byte) { - node.Store.Set(node.Path.Key(k), value) + node.Store.Set(join(node.Prefix, k), value) } // nolint:deadcode,unused func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10), merkle.NewPath([][]byte{[]byte("1")}, []byte{0x00, 0x01})) + node := NewNode(NewMockValidators(100, 10), "1", []byte{0x00, 0x01}) node.Commit() @@ -176,12 +186,12 @@ func testProof(t *testing.T) { proofs := []commitment.Proof{} root := merkle.NewRoot(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, node.Path.Key(kvp.Key)) + v, p := node.Query(t, kvp.Key) require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore(root, node.Path, proofs) + cstore, err := commitment.NewStore(root, node.Path(), proofs) require.NoError(t, err) for _, kvp := range kvps { diff --git a/x/ibc/02-client/tendermint/tests/utils.go b/x/ibc/02-client/tendermint/tests/utils.go new file mode 100644 index 000000000000..d5262a14a29b --- /dev/null +++ b/x/ibc/02-client/tendermint/tests/utils.go @@ -0,0 +1,8 @@ +package tendermint + +func join(a, b []byte) (res []byte) { + res = make([]byte, len(a)+len(b)) + copy(res, a) + copy(res[len(a):], b) + return +} diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index a9617d4b0e38..8503be6b02e6 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -1,145 +1,53 @@ package connection import ( - abci "github.com/tendermint/tendermint/abci/types" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -// CLIObject stores the key for each object fields -type CLIObject struct { - ID string - ConnectionKey []byte - AvailableKey []byte - KindKey []byte - - Client client.CLIObject - - StoreName string - Cdc *codec.Codec -} - -func (man Manager) CLIQuery(ctx context.CLIContext, path merkle.Path, id string) CLIObject { - res := man.CLIObject(path, id, "") - - connection, _, err := res.Connection(ctx) - if err != nil { - return res - } - res.Client = man.client.CLIObject(path, connection.Client) - return res -} - -func (man Manager) CLIObject(path merkle.Path, id, clientid string) CLIObject { - obj := man.object(id) - return CLIObject{ - ID: obj.id, - ConnectionKey: obj.connection.Key(), - AvailableKey: obj.available.Key(), - KindKey: obj.kind.Key(), - - Client: man.client.CLIObject(path, clientid), - - StoreName: man.protocol.StoreName(), - Cdc: obj.connection.Cdc(), - } -} - -func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { - resp, err := ctx.QueryABCI(abci.RequestQuery{ - Path: "/store/" + obj.StoreName + "/key", - Data: key, - }) - if err != nil { - return merkle.Proof{}, err - } - proof := merkle.Proof{ - Key: key, - Proof: resp.Proof, - } - err = obj.Cdc.UnmarshalBinaryBare(resp.Value, ptr) - return proof, err - +func (man Manager) CLIObject(connid, clientid string) Object { + obj := man.Object(connid) + obj.Client = man.client.Object(clientid) + return obj } -func (obj CLIObject) Connection(ctx context.CLIContext) (res Connection, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.ConnectionKey, &res) +func (obj Object) ConnectionCLI(ctx context.CLIContext, path merkle.Path) (res Connection, proof merkle.Proof, err error) { + tmproof, err := obj.Connection.Query(ctx, &res) + proof = merkle.NewProofFromValue(tmproof, path, obj.Connection) return } -func (obj CLIObject) Available(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.AvailableKey, &res) +func (obj Object) AvailableCLI(ctx context.CLIContext, path merkle.Path) (res bool, proof merkle.Proof, err error) { + res, tmproof, err := obj.Available.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, path, obj.Available) return } -func (obj CLIObject) Kind(ctx context.CLIContext) (res string, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.KindKey, &res) +func (obj Object) KindCLI(ctx context.CLIContext, path merkle.Path) (res string, proof merkle.Proof, err error) { + res, tmproof, err := obj.Kind.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, path, obj.Kind) return } -type CLIHandshakeObject struct { - CLIObject - - StateKey []byte - CounterpartyClientKey []byte - TimeoutKey []byte +func (man Handshaker) CLIObject(connid, clientid string) HandshakeObject { + return man.Object(man.man.CLIObject(connid, clientid)) } -func (man Handshaker) CLIQuery(ctx context.CLIContext, path merkle.Path, id string) CLIHandshakeObject { - obj := man.object(man.man.object(id)) - return CLIHandshakeObject{ - CLIObject: man.man.CLIQuery(ctx, path, id), - - StateKey: obj.state.Key(), - CounterpartyClientKey: obj.counterpartyClient.Key(), - TimeoutKey: obj.nextTimeout.Key(), - } -} - -func (man Handshaker) CLIObject(path merkle.Path, id, clientid string) CLIHandshakeObject { - obj := man.object(man.man.object(id)) - return CLIHandshakeObject{ - CLIObject: man.man.CLIObject(path, id, clientid), - - StateKey: obj.state.Key(), - CounterpartyClientKey: obj.counterpartyClient.Key(), - TimeoutKey: obj.nextTimeout.Key(), - } - -} - -func (obj CLIHandshakeObject) State(ctx context.CLIContext) (res byte, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.StateKey, &res) - return -} - -func (obj CLIHandshakeObject) CounterpartyClient(ctx context.CLIContext) (res string, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.CounterpartyClientKey, &res) +func (obj HandshakeObject) StateCLI(ctx context.CLIContext, path merkle.Path) (res byte, proof merkle.Proof, err error){ + res, tmproof, err := obj.State.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, path, obj.State) return } -func (obj CLIHandshakeObject) NextTimeout(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.TimeoutKey, &res) - return -} - -/* -func (obj CLIObject) State(ctx context.CLIContext, root merkle.Root) (res bool, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.StateKey, &res) - return -} - -func (obj CLIObject) NextTimeout(ctx context.CLIContext, root merkle.Root) (res time.Time, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.NextTimeoutKey, &res) - return +func (obj HandshakeObject) CounterpartyClientCLI(ctx context.CLIContext, path merkle.Path) (res string, proof merkle.Proof, err error) { + res, tmproof, err := obj.CounterpartyClient.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, path, obj.CounterpartyClient) + return } -func (obj CLIObject) Permission(ctx context.CLIContext, root merkle.Root) (res string, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.PermissionKey, &res) +func (obj HandshakeObject) NextTimeoutCLI(ctx context.CLIContext, path merkle.Path) (res uint64, proof merkle.Proof, err error){ + res, tmproof, err := obj.NextTimeout.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, path, obj.NextTimeout) return } -*/ diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index efc30534e913..6be3c81bd9ce 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -24,13 +24,13 @@ const ( FlagProve = "prove" ) -func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) connection.CLIObject { +func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) connection.Object { prefix := []byte(strconv.FormatInt(version, 10) + "/") path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) - base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) + base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) man := connection.NewManager(base, climan) - return man.CLIQuery(ctx, path, id) + return man.Query(ctx, path, id) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index c8a69c7fb9b5..c5d9debba1a3 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -46,41 +46,41 @@ type CounterpartyHandshaker struct { type HandshakeObject struct { Object - state state.Enum - counterpartyClient state.String - nextTimeout state.Integer + State state.Enum + CounterpartyClient state.String + NextTimeout state.Integer - counterparty CounterHandshakeObject + Counterparty CounterHandshakeObject } type CounterHandshakeObject struct { CounterObject - state commitment.Enum - counterpartyClient commitment.String - nextTimeout commitment.Integer + State commitment.Enum + CounterpartyClient commitment.String + NextTimeout commitment.Integer } // CONTRACT: client and remote must be filled by the caller -func (man Handshaker) object(parent Object) HandshakeObject { +func (man Handshaker) Object(parent Object) HandshakeObject { return HandshakeObject{ Object: parent, - state: state.NewEnum(man.man.protocol.Value([]byte(parent.id + "/state"))), - counterpartyClient: state.NewString(man.man.protocol.Value([]byte(parent.id + "/counterpartyClient"))), - nextTimeout: state.NewInteger(man.man.protocol.Value([]byte(parent.id+"/timeout")), state.Dec), + State: man.man.protocol.Value([]byte(parent.id + "/state")).Enum(), + CounterpartyClient: man.man.protocol.Value([]byte(parent.id + "/counterpartyClient")).String(), + NextTimeout: man.man.protocol.Value([]byte(parent.id + "/timeout")).Integer(state.Dec), // CONTRACT: counterparty must be filled by the caller } } -func (man CounterpartyHandshaker) object(id string) CounterHandshakeObject { +func (man CounterpartyHandshaker) Object(id string) CounterHandshakeObject { return CounterHandshakeObject{ - CounterObject: man.man.object(id), + CounterObject: man.man.Object(id), - state: commitment.NewEnum(man.man.protocol.Value([]byte(id + "/state"))), - counterpartyClient: commitment.NewString(man.man.protocol.Value([]byte(id + "/counterpartyClient"))), - nextTimeout: commitment.NewInteger(man.man.protocol.Value([]byte(id+"/timeout")), state.Dec), + State: man.man.protocol.Value([]byte(id + "/state")).Enum(), + CounterpartyClient: man.man.protocol.Value([]byte(id + "/counterpartyClient")).String(), + NextTimeout: man.man.protocol.Value([]byte(id + "/timeout")).Integer(state.Dec), } } @@ -89,9 +89,9 @@ func (man Handshaker) create(ctx sdk.Context, id string, connection Connection, if err != nil { return } - obj = man.object(cobj) - obj.counterpartyClient.Set(ctx, counterpartyClient) - obj.counterparty = man.counterparty.object(connection.Counterparty) + obj = man.Object(cobj) + obj.CounterpartyClient.Set(ctx, counterpartyClient) + obj.Counterparty = man.counterparty.Object(connection.Counterparty) return obj, nil } @@ -100,32 +100,16 @@ func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeObject, er if err != nil { return } - obj = man.object(cobj) - obj.counterparty = man.counterparty.object(obj.Connection(ctx).Counterparty) + obj = man.Object(cobj) + obj.Counterparty = man.counterparty.Object(obj.GetConnection(ctx).Counterparty) return } -func (obj HandshakeObject) State(ctx sdk.Context) byte { - return obj.state.Get(ctx) -} - -func (obj HandshakeObject) CounterpartyClient(ctx sdk.Context) string { - return obj.counterpartyClient.Get(ctx) -} - -func (obj HandshakeObject) Timeout(ctx sdk.Context) uint64 { - return obj.nextTimeout.Get(ctx) -} - -func (obj HandshakeObject) NextTimeout(ctx sdk.Context) uint64 { - return obj.nextTimeout.Get(ctx) -} - func (obj HandshakeObject) remove(ctx sdk.Context) { obj.Object.remove(ctx) - obj.state.Delete(ctx) - obj.counterpartyClient.Delete(ctx) - obj.nextTimeout.Delete(ctx) + obj.State.Delete(ctx) + obj.CounterpartyClient.Delete(ctx) + obj.NextTimeout.Delete(ctx) } func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { @@ -148,8 +132,8 @@ func (man Handshaker) OpenInit(ctx sdk.Context, return HandshakeObject{}, err } - obj.nextTimeout.Set(ctx, nextTimeoutHeight) - obj.state.Set(ctx, Init) + obj.NextTimeout.Set(ctx, nextTimeoutHeight) + obj.State.Set(ctx, Init) return obj, nil } @@ -174,12 +158,12 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.state.Is(ctx, Init) { + if !obj.Counterparty.State.Is(ctx, Init) { err = errors.New("counterparty state not init") return } - if !obj.counterparty.connection.Is(ctx, Connection{ + if !obj.Counterparty.Connection.Is(ctx, Connection{ Client: counterpartyClient, Counterparty: id, Path: obj.path, @@ -188,12 +172,12 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.counterpartyClient.Is(ctx, connection.Client) { + if !obj.Counterparty.CounterpartyClient.Is(ctx, connection.Client) { err = errors.New("counterparty client not match") return } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } @@ -214,8 +198,8 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // assert(get("connections/{desiredIdentifier}") === null) and // set("connections{identifier}", connection) - obj.state.Set(ctx, OpenTry) - obj.nextTimeout.Set(ctx, nextTimeoutHeight) + obj.State.Set(ctx, OpenTry) + obj.NextTimeout.Set(ctx, nextTimeoutHeight) return } @@ -235,7 +219,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.state.Transit(ctx, Init, Open) { + if !obj.State.Transit(ctx, Init, Open) { err = errors.New("ack on non-init connection") return } @@ -245,8 +229,8 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.connection.Is(ctx, Connection{ - Client: obj.CounterpartyClient(ctx), + if !obj.Counterparty.Connection.Is(ctx, Connection{ + Client: obj.CounterpartyClient.Get(ctx), Counterparty: obj.ID(), Path: obj.path, }) { @@ -254,17 +238,17 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.state.Is(ctx, OpenTry) { + if !obj.Counterparty.State.Is(ctx, OpenTry) { err = errors.New("counterparty state not opentry") return } - if !obj.counterparty.counterpartyClient.Is(ctx, obj.Connection(ctx).Client) { + if !obj.Counterparty.CounterpartyClient.Is(ctx, obj.GetConnection(ctx).Client) { err = errors.New("counterparty client not match") return } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } @@ -277,8 +261,8 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // return errors.New("unexpected counterparty client value") } */ - obj.available.Set(ctx, true) - obj.nextTimeout.Set(ctx, nextTimeoutHeight) + obj.Available.Set(ctx, true) + obj.NextTimeout.Set(ctx, nextTimeoutHeight) return } @@ -298,7 +282,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - if !obj.state.Transit(ctx, OpenTry, Open) { + if !obj.State.Transit(ctx, OpenTry, Open) { err = errors.New("confirm on non-try connection") return } @@ -308,40 +292,40 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - if !obj.counterparty.state.Is(ctx, Open) { + if !obj.Counterparty.State.Is(ctx, Open) { err = errors.New("counterparty state not open") return } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } - obj.available.Set(ctx, true) - obj.nextTimeout.Set(ctx, 0) + obj.Available.Set(ctx, true) + obj.NextTimeout.Set(ctx, 0) return } func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { - if !(obj.client.ConsensusState(ctx).GetHeight() > obj.nextTimeout.Get(ctx)) { + if !(obj.Client.GetConsensusState(ctx).GetHeight() > obj.NextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } - switch obj.state.Get(ctx) { + switch obj.State.Get(ctx) { case Init: - if !obj.counterparty.connection.Is(ctx, nil) { + if !obj.Counterparty.Connection.Is(ctx, nil) { return errors.New("counterparty connection exists") } case OpenTry: - if !(obj.counterparty.state.Is(ctx, Init) || - obj.counterparty.connection.Is(ctx, nil)) { + if !(obj.Counterparty.State.Is(ctx, Init) || + obj.Counterparty.Connection.Is(ctx, nil)) { return errors.New("counterparty connection state not init") } // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) case Open: - if obj.counterparty.state.Is(ctx, OpenTry) { + if obj.Counterparty.State.Is(ctx, OpenTry) { return errors.New("counterparty connection state not tryopen") } } @@ -352,17 +336,17 @@ func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { } func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error { - if !obj.state.Transit(ctx, Open, CloseTry) { + if !obj.State.Transit(ctx, Open, CloseTry) { return errors.New("closeinit on non-open connection") } - obj.nextTimeout.Set(ctx, nextTimeout) + obj.NextTimeout.Set(ctx, nextTimeout) return nil } func (obj HandshakeObject) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { - if !obj.state.Transit(ctx, Open, Closed) { + if !obj.State.Transit(ctx, Open, Closed) { return errors.New("closetry on non-open connection") } @@ -371,21 +355,21 @@ func (obj HandshakeObject) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutH return err } - if !obj.counterparty.state.Is(ctx, CloseTry) { + if !obj.Counterparty.State.Is(ctx, CloseTry) { return errors.New("unexpected counterparty state value") } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } - obj.nextTimeout.Set(ctx, nextTimeoutHeight) + obj.NextTimeout.Set(ctx, nextTimeoutHeight) return nil } func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { - if !obj.state.Transit(ctx, CloseTry, Closed) { + if !obj.State.Transit(ctx, CloseTry, Closed) { return errors.New("closeack on non-closetry connection") } @@ -394,38 +378,38 @@ func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error return err } - if !obj.counterparty.state.Is(ctx, Closed) { + if !obj.Counterparty.State.Is(ctx, Closed) { return errors.New("unexpected counterparty state value") } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } - obj.nextTimeout.Set(ctx, 0) + obj.NextTimeout.Set(ctx, 0) return nil } func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { - if !(obj.client.ConsensusState(ctx).GetHeight() > obj.nextTimeout.Get(ctx)) { + if !(obj.Client.GetConsensusState(ctx).GetHeight() > obj.NextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } // XXX: double check if the user can bypass the verification logic somehow - switch obj.state.Get(ctx) { + switch obj.State.Get(ctx) { case CloseTry: - if !obj.counterparty.state.Is(ctx, Open) { + if !obj.Counterparty.State.Is(ctx, Open) { return errors.New("counterparty connection state not open") } case Closed: - if !obj.counterparty.state.Is(ctx, CloseTry) { + if !obj.Counterparty.State.Is(ctx, CloseTry) { return errors.New("counterparty connection state not closetry") } } - obj.state.Set(ctx, Open) - obj.nextTimeout.Set(ctx, 0) + obj.State.Set(ctx, Open) + obj.NextTimeout.Set(ctx, 0) return nil diff --git a/x/ibc/03-connection/keys.go b/x/ibc/03-connection/keys.go new file mode 100644 index 000000000000..3ce706ab0bc7 --- /dev/null +++ b/x/ibc/03-connection/keys.go @@ -0,0 +1,5 @@ +package connection + +func LocalRoot() []byte { + return []byte("connection/") +} diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 5a693d58c2e4..cc5da97a1386 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -22,9 +22,9 @@ type Manager struct { path merkle.Path } -func NewManager(protocol state.Base, client client.Manager) Manager { +func NewManager(protocol state.Mapping, client client.Manager) Manager { return Manager{ - protocol: state.NewMapping(protocol, ([]byte("/connection/"))), + protocol: protocol.Prefix(LocalRoot()), client: client, counterparty: NewCounterpartyManager(protocol.Cdc()), path: merkle.NewPath([][]byte{[]byte(protocol.StoreName())}, protocol.PrefixBytes()), @@ -38,12 +38,12 @@ type CounterpartyManager struct { } func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { - protocol := commitment.NewBase(cdc) + protocol := commitment.NewMapping(cdc, nil) return CounterpartyManager{ - protocol: commitment.NewMapping(protocol, []byte("/connection/")), + protocol: protocol.Prefix(LocalRoot()), - client: client.NewCounterpartyManager(protocol), + client: client.NewCounterpartyManager(cdc), } } @@ -51,25 +51,25 @@ type Object struct { id string protocol state.Mapping - connection state.Value - available state.Boolean + Connection state.Value + Available state.Boolean - kind state.String + Kind state.String - client client.Object + Client client.Object path merkle.Path } -func (man Manager) object(id string) Object { +func (man Manager) Object(id string) Object { return Object{ id: id, protocol: man.protocol.Prefix([]byte(id + "/")), - connection: man.protocol.Value([]byte(id)), - available: state.NewBoolean(man.protocol.Value([]byte(id + "/available"))), + Connection: man.protocol.Value([]byte(id)), + Available: man.protocol.Value([]byte(id + "/available")).Boolean(), - kind: state.NewString(man.protocol.Value([]byte(id + "/kind"))), + Kind: man.protocol.Value([]byte(id + "/kind")).String(), // CONTRACT: client must be filled by the caller @@ -81,22 +81,22 @@ type CounterObject struct { id string protocol commitment.Mapping - connection commitment.Value - available commitment.Boolean + Connection commitment.Value + Available commitment.Boolean - kind commitment.String + Kind commitment.String - client client.CounterObject // nolint: unused + Client client.CounterObject // nolint: unused } -func (man CounterpartyManager) object(id string) CounterObject { +func (man CounterpartyManager) Object(id string) CounterObject { return CounterObject{ id: id, protocol: man.protocol.Prefix([]byte(id + "/")), - connection: man.protocol.Value([]byte(id)), - available: commitment.NewBoolean(man.protocol.Value([]byte(id + "/available"))), + Connection: man.protocol.Value([]byte(id)), + Available: man.protocol.Value([]byte(id + "/available")).Boolean(), - kind: commitment.NewString(man.protocol.Value([]byte(id + "/kind"))), + Kind: man.protocol.Value([]byte(id + "/kind")).String(), // CONTRACT: client should be filled by the caller } @@ -104,12 +104,12 @@ func (man CounterpartyManager) object(id string) CounterObject { func (obj Object) Context(ctx sdk.Context, optpath commitment.Path, proofs []commitment.Proof) (sdk.Context, error) { if optpath == nil { - optpath = obj.Connection(ctx).Path + optpath = obj.GetConnection(ctx).Path } store, err := commitment.NewStore( // TODO: proof root should be able to be obtained from the past - obj.client.ConsensusState(ctx).GetRoot(), + obj.Client.GetConsensusState(ctx).GetRoot(), optpath, proofs, ) @@ -124,35 +124,27 @@ func (obj Object) ID() string { return obj.id } -func (obj Object) Connection(ctx sdk.Context) (res Connection) { - obj.connection.Get(ctx, &res) +func (obj Object) GetConnection(ctx sdk.Context) (res Connection) { + obj.Connection.Get(ctx, &res) return } -func (obj Object) Available(ctx sdk.Context) bool { - return obj.available.Get(ctx) -} - -func (obj Object) Client() client.Object { - return obj.client -} - func (obj Object) Sendable(ctx sdk.Context) bool { - return kinds[obj.kind.Get(ctx)].Sendable + return kinds[obj.Kind.Get(ctx)].Sendable } func (obj Object) Receivble(ctx sdk.Context) bool { - return kinds[obj.kind.Get(ctx)].Receivable + return kinds[obj.Kind.Get(ctx)].Receivable } func (obj Object) remove(ctx sdk.Context) { - obj.connection.Delete(ctx) - obj.available.Delete(ctx) - obj.kind.Delete(ctx) + obj.Connection.Delete(ctx) + obj.Available.Delete(ctx) + obj.Kind.Delete(ctx) } func (obj Object) exists(ctx sdk.Context) bool { - return obj.connection.Exists(ctx) + return obj.Connection.Exists(ctx) } func (man Manager) Cdc() *codec.Codec { @@ -160,33 +152,33 @@ func (man Manager) Cdc() *codec.Codec { } func (man Manager) create(ctx sdk.Context, id string, connection Connection, kind string) (obj Object, err error) { - obj = man.object(id) + obj = man.Object(id) if obj.exists(ctx) { err = errors.New("Object already exists") return } - obj.client, err = man.client.Query(ctx, connection.Client) + obj.Client, err = man.client.Query(ctx, connection.Client) if err != nil { return } - obj.connection.Set(ctx, connection) - obj.kind.Set(ctx, kind) + obj.Connection.Set(ctx, connection) + obj.Kind.Set(ctx, kind) return } // query() is used internally by the connection creators // checks connection kind, doesn't check avilability func (man Manager) query(ctx sdk.Context, id string, kind string) (obj Object, err error) { - obj = man.object(id) + obj = man.Object(id) if !obj.exists(ctx) { err = errors.New("Object not exists") return } - obj.client, err = man.client.Query(ctx, obj.Connection(ctx).Client) + obj.Client, err = man.client.Query(ctx, obj.GetConnection(ctx).Client) if err != nil { return } - if obj.kind.Get(ctx) != kind { + if obj.Kind.Get(ctx) != kind { err = errors.New("kind mismatch") return } @@ -194,15 +186,15 @@ func (man Manager) query(ctx sdk.Context, id string, kind string) (obj Object, e } func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { - obj = man.object(id) + obj = man.Object(id) if !obj.exists(ctx) { err = errors.New("Object not exists") return } - if !obj.Available(ctx) { + if !obj.Available.Get(ctx) { err = errors.New("Object not available") return } - obj.client, err = man.client.Query(ctx, obj.Connection(ctx).Client) + obj.Client, err = man.client.Query(ctx, obj.GetConnection(ctx).Client) return } diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index 2edc9c3ad3cf..665f15b3142d 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -38,10 +38,10 @@ func TestHandshake(t *testing.T) { // counterparty.OpenTry node.Counterparty.UpdateClient(t, header) cliobj := node.CLIObject() - _, pconn := node.Query(t, cliobj.ConnectionKey) - _, pstate := node.Query(t, cliobj.StateKey) - _, ptimeout := node.Query(t, cliobj.TimeoutKey) - _, pcounterclient := node.Query(t, cliobj.CounterpartyClientKey) + _, pconn := node.QueryValue(t, cliobj.Connection) + _, pstate := node.QueryValue(t, cliobj.State) + _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) + _, pcounterclient := node.QueryValue(t, cliobj.CounterpartyClient) // TODO: implement consensus state checking // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) node.Counterparty.OpenTry(t, pconn, pstate, ptimeout, pcounterclient) @@ -50,17 +50,17 @@ func TestHandshake(t *testing.T) { // self.OpenAck node.UpdateClient(t, header) cliobj = node.Counterparty.CLIObject() - _, pconn = node.Counterparty.Query(t, cliobj.ConnectionKey) - _, pstate = node.Counterparty.Query(t, cliobj.StateKey) - _, ptimeout = node.Counterparty.Query(t, cliobj.TimeoutKey) - _, pcounterclient = node.Counterparty.Query(t, cliobj.CounterpartyClientKey) + _, pconn = node.Counterparty.QueryValue(t, cliobj.Connection) + _, pstate = node.Counterparty.QueryValue(t, cliobj.State) + _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) + _, pcounterclient = node.Counterparty.QueryValue(t, cliobj.CounterpartyClient) node.OpenAck(t, pconn, pstate, ptimeout, pcounterclient) header = node.Commit() // counterparty.OpenConfirm node.Counterparty.UpdateClient(t, header) cliobj = node.CLIObject() - _, pstate = node.Query(t, cliobj.StateKey) - _, ptimeout = node.Query(t, cliobj.TimeoutKey) + _, pstate = node.QueryValue(t, cliobj.State) + _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) node.Counterparty.OpenConfirm(t, pstate, ptimeout) } diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 0b4444b05338..29b7b0706721 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -13,7 +13,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) type Node struct { @@ -31,7 +30,7 @@ type Node struct { func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res := &Node{ Name: "self", // hard coded, doesnt matter - Node: tendermint.NewNode(self, merkle.NewPath([][]byte{[]byte("teststoreself")}, []byte("protocol"))), // TODO: test with key prefix + Node: tendermint.NewNode(self, "teststoreself", []byte("protocol/")), // TODO: test with key prefix State: connection.Idle, Cdc: cdc, @@ -39,7 +38,7 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res.Counterparty = &Node{ Name: "counterparty", - Node: tendermint.NewNode(counter, merkle.NewPath([][]byte{[]byte("teststorecounterparty")}, []byte("protocol"))), + Node: tendermint.NewNode(counter, "teststorecounterparty", []byte("protocol/")), Counterparty: res, State: connection.Idle, @@ -48,17 +47,22 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res.Connection = connection.Connection{ Counterparty: res.Counterparty.Name, - Path: res.Counterparty.Path, + Path: res.Counterparty.Path(), } res.Counterparty.Connection = connection.Connection{ Counterparty: res.Name, - Path: res.Path, + Path: res.Path(), } return res } +// TODO: typeify v +func (node *Node) QueryValue(t *testing.T, v interface{KeyBytes() []byte}) ([]byte, commitment.Proof) { + return node.Query(t, v.KeyBytes()) +} + func (node *Node) CreateClient(t *testing.T) { ctx := node.Context() climan, _ := node.Manager() @@ -88,18 +92,18 @@ func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Conte return ctx, connection.NewHandshaker(man) } -func (node *Node) CLIObject() connection.CLIHandshakeObject { +func (node *Node) CLIObject() connection.HandshakeObject { _, man := node.Manager() - return connection.NewHandshaker(man).CLIObject(node.Path, node.Name, node.Name) + return connection.NewHandshaker(man).CLIObject(node.Name, node.Name) } -func base(cdc *codec.Codec, key sdk.StoreKey) state.Base { - protocol := state.NewBase(cdc, key, []byte("protocol")) +func (node *Node) Mapping() state.Mapping { + protocol := state.NewMapping(node.Key, node.Cdc, node.Prefix) return protocol } func (node *Node) Manager() (client.Manager, connection.Manager) { - protocol := base(node.Cdc, node.Key) + protocol := node.Mapping() clientman := client.NewManager(protocol) return clientman, connection.NewManager(protocol, clientman) } @@ -108,10 +112,10 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenInit(ctx, node.Name, node.Connection, node.CounterpartyClient, 100) // TODO: test timeout require.NoError(t, err) - require.Equal(t, connection.Init, obj.State(ctx)) - require.Equal(t, node.Connection, obj.Connection(ctx)) - require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient(ctx)) - require.False(t, obj.Available(ctx)) + require.Equal(t, connection.Init, obj.State.Get(ctx)) + require.Equal(t, node.Connection, obj.GetConnection(ctx)) + require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient.Get(ctx)) + require.False(t, obj.Available.Get(ctx)) node.SetState(connection.Init) } @@ -119,10 +123,10 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenTry(ctx, proofs, node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) - require.Equal(t, connection.OpenTry, obj.State(ctx)) - require.Equal(t, node.Connection, obj.Connection(ctx)) - require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient(ctx)) - require.False(t, obj.Available(ctx)) + require.Equal(t, connection.OpenTry, obj.State.Get(ctx)) + require.Equal(t, node.Connection, obj.GetConnection(ctx)) + require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient.Get(ctx)) + require.False(t, obj.Available.Get(ctx)) node.SetState(connection.OpenTry) } @@ -130,9 +134,9 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenAck(ctx, proofs, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) - require.Equal(t, connection.Open, obj.State(ctx)) - require.Equal(t, node.Connection, obj.Connection(ctx)) - require.True(t, obj.Available(ctx)) + require.Equal(t, connection.Open, obj.State.Get(ctx)) + require.Equal(t, node.Connection, obj.GetConnection(ctx)) + require.True(t, obj.Available.Get(ctx)) node.SetState(connection.Open) } @@ -140,8 +144,8 @@ func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenConfirm(ctx, proofs, node.Name, 100 /*TODO*/) require.NoError(t, err) - require.Equal(t, connection.Open, obj.State(ctx)) - require.Equal(t, node.Connection, obj.Connection(ctx)) - require.True(t, obj.Available(ctx)) + require.Equal(t, connection.Open, obj.State.Get(ctx)) + require.Equal(t, node.Connection, obj.GetConnection(ctx)) + require.True(t, obj.Available.Get(ctx)) node.SetState(connection.CloseTry) } diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index e97a2a9896e3..5dda3702a186 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -7,7 +7,7 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" "github.com/cosmos/cosmos-sdk/store/rootmulti" - "github.com/cosmos/cosmos-sdk/store/state" +// "github.com/cosmos/cosmos-sdk/store/state" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -59,10 +59,6 @@ func (Path) CommitmentKind() string { return merkleKind } -func NewPathFromMapping(mapp state.Mapping) Path { - return NewPath([][]byte{[]byte(mapp.StoreName())}, mapp.PrefixBytes()) -} - var _ commitment.Proof = Proof{} // Proof is Merkle proof with the key information. diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index 2624d54eccde..222a6bf5abd9 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -42,9 +42,10 @@ func commit(cms types.CommitMultiStore) Root { // Sets/upates key-value pairs and prove with the query result proofs func TestStore(t *testing.T) { k, ctx, cms, cdc := defaultComponents() + storeName := k.Name() prefix := []byte{0x01, 0x03, 0x05, 0xAA, 0xBB} mapp := state.NewMapping(k, cdc, prefix) - path := NewPath([][]byte{[]byte(k.Name())}, prefix) + path := NewPath([][]byte{[]byte(storeName)}, prefix) m := make(map[string][]byte) kvpn := 10 @@ -67,7 +68,7 @@ func TestStore(t *testing.T) { // Test query, and accumulate proofs proofs := make([]commitment.Proof, 0, kvpn) for k, v := range m { - v0, p, err := QueryMultiStore(cms, path, []byte(k)) + v0, p, err := QueryMultiStore(cms, storeName, prefix, []byte(k)) require.NoError(t, err) require.Equal(t, cdc.MustMarshalBinaryBare(v), v0, "Queried value different at %d", repeat) proofs = append(proofs, p) @@ -77,7 +78,7 @@ func TestStore(t *testing.T) { for i := 0; i < 10; i++ { k := make([]byte, 64) rand.Read(k) - v, p, err := QueryMultiStore(cms, path, k) + v, p, err := QueryMultiStore(cms, storeName, prefix, k) require.NoError(t, err) require.Nil(t, v) proofs = append(proofs, p) @@ -109,7 +110,7 @@ func TestStore(t *testing.T) { // Test query, and accumulate proofs proofs = make([]commitment.Proof, 0, kvpn) for k, v := range m { - v0, p, err := QueryMultiStore(cms, path, []byte(k)) + v0, p, err := QueryMultiStore(cms, storeName, prefix, []byte(k)) require.NoError(t, err) require.Equal(t, cdc.MustMarshalBinaryBare(v), v0) proofs = append(proofs, p) diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index bd96cf84fdce..636fae569c28 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -1,7 +1,6 @@ package merkle import ( - "bytes" "errors" abci "github.com/tendermint/tendermint/abci/types" @@ -9,12 +8,12 @@ import ( "github.com/cosmos/cosmos-sdk/store/types" ) -func QueryMultiStore(cms types.CommitMultiStore, path Path, key []byte) ([]byte, Proof, error) { +func QueryMultiStore(cms types.CommitMultiStore, storeName string, prefix []byte, key []byte) ([]byte, Proof, error) { queryable, ok := cms.(types.Queryable) if !ok { panic("CommitMultiStore not queryable") } - qres := queryable.Query(RequestQueryMultiStore(path, key)) + qres := queryable.Query(RequestQueryMultiStore(storeName, prefix, key)) if !qres.IsOK() { return nil, Proof{}, errors.New(qres.Log) } @@ -22,13 +21,13 @@ func QueryMultiStore(cms types.CommitMultiStore, path Path, key []byte) ([]byte, return qres.Value, Proof{Key: key, Proof: qres.Proof}, nil } -func RequestQueryMultiStore(path Path, key []byte) abci.RequestQuery { +func RequestQueryMultiStore(storeName string, prefix []byte, key []byte) abci.RequestQuery { // Suffixing path with "/key". // iavl.Store.Query() switches over the last path element, // and performs key-value query only if it is "/key" return abci.RequestQuery{ - Path: "/" + string(bytes.Join(path.KeyPath, []byte("/"))) + "/key", - Data: path.Key(key), + Path: "/" + storeName + "/key", + Data: join(prefix, key), Prove: true, } } diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index cc5ac4a2fdc3..cf76caac4b39 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -42,13 +42,13 @@ type store struct { // NewStore constructs a new Store with the root, path, and proofs. // The proofs are not proven immediately because proofs require value bytes to verify. // If the kinds of the arguments don't match, returns error. -func NewStore(root Root, path Path, proofs []Proof) (res store, err error) { +func NewStore(root Root, path Path, proofs []Proof) (res *store, err error) { if root.CommitmentKind() != path.CommitmentKind() { err = errors.New("path type not matching with root's") return } - res = store{ + res = &store{ root: root, path: path, proofs: make(map[string]Proof), @@ -67,13 +67,13 @@ func NewStore(root Root, path Path, proofs []Proof) (res store, err error) { } // Get() returns the value only if it is already proven. -func (store store) Get(key []byte) ([]byte, bool) { +func (store *store) Get(key []byte) ([]byte, bool) { res, ok := store.verified[string(key)] return res, ok } // Prove() proves the key-value pair with the stored proof. -func (store store) Prove(key, value []byte) bool { +func (store *store) Prove(key, value []byte) bool { stored, ok := store.Get(key) if ok && bytes.Equal(stored, value) { return true @@ -93,7 +93,7 @@ func (store store) Prove(key, value []byte) bool { // Proven() returns true if the key-value pair is already proven -func (store store) Proven(key []byte) bool { +func (store *store) Proven(key []byte) bool { _, ok := store.Get(key) return ok } diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index 5162b0453d39..165b3666d4d3 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -1,6 +1,7 @@ package commitment import ( + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" @@ -52,6 +53,7 @@ func (v Value) Is(ctx sdk.Context, value interface{}) bool { // IsRaw() proves the proof with the Value's key and the provided raw value bytes. func (v Value) IsRaw(ctx sdk.Context, value []byte) bool { + return v.m.store(ctx).Prove(v.key, value) } @@ -75,19 +77,19 @@ type String struct { Value } -func NewString(v Value) String { +func (v Value) String() String { return String{v} } func (v String) Is(ctx sdk.Context, value string) bool { - return v.Value.Is(ctx, value) + return v.Value.IsRaw(ctx, []byte(value)) } type Boolean struct { Value } -func NewBoolean(v Value) Boolean { +func (v Value) Boolean() Boolean { return Boolean{v} } From f81d7b4b55c801da83e6fe42bb160bbdc098539e Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 15 Aug 2019 02:53:01 +0900 Subject: [PATCH 120/182] fix client --- store/state/value.go | 4 --- x/ibc/02-client/cli.go | 14 ++++++--- x/ibc/02-client/client/cli/query.go | 8 ++--- x/ibc/03-connection/cli.go | 42 ++++++++++++++++++------- x/ibc/03-connection/client/cli/query.go | 19 +++++------ x/ibc/03-connection/client/cli/tx.go | 40 ++++++++++++----------- x/ibc/23-commitment/merkle/merkle.go | 4 +-- x/ibc/version.go | 6 ++++ 8 files changed, 81 insertions(+), 56 deletions(-) diff --git a/store/state/value.go b/store/state/value.go index c3b4b3089bbc..eb8cd12cf76a 100644 --- a/store/state/value.go +++ b/store/state/value.go @@ -103,10 +103,6 @@ func (v Value) PrefixBytes() []byte { return v.m.PrefixBytes() } -func (v Value) KeyBytesRaw() []byte { - return v.key -} - // KeyBytes() returns the prefixed key that the Value is providing to the KVStore func (v Value) KeyBytes() []byte { return v.m.KeyBytes(v.key) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index aa563f3c170b..f199ac00d2b6 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -1,20 +1,26 @@ package client import ( + "bytes" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func (obj Object) ConsensusStateCLI(ctx context.CLIContext, path merkle.Path) (res ConsensusState, proof merkle.Proof, err error) { +func (obj Object) prefix() []byte { + return bytes.Split(obj.ConsensusState.KeyBytes(), LocalRoot())[0] +} + +func (obj Object) ConsensusStateCLI(ctx context.CLIContext) (res ConsensusState, proof merkle.Proof, err error) { tmproof, err := obj.ConsensusState.Query(ctx, &res) - proof = merkle.NewProofFromValue(tmproof, path, obj.ConsensusState) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.ConsensusState) return } -func (obj Object) FrozenCLI(ctx context.CLIContext, path merkle.Path) (res bool, proof merkle.Proof, err error) { +func (obj Object) FrozenCLI(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { res, tmproof, err := obj.Frozen.Query(ctx) - proof = merkle.NewProofFromValue(tmproof, path, obj.Frozen) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Frozen) return } diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 1cf445dae389..c4238dae8cdb 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -20,9 +20,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func mapping(cdc *codec.Codec, storeKey string, version int64) (state.Mapping, merkle.Path) { +func mapping(cdc *codec.Codec, storeKey string, version int64) state.Mapping { prefix := []byte(strconv.FormatInt(version, 10) + "/") - return state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix), merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) + return state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -48,11 +48,11 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - mapp, path := mapping(cdc, storeKey, ibc.Version) + mapp := mapping(cdc, storeKey, ibc.Version) man := client.NewManager(mapp) id := args[0] - state, _, err := man.Object(id).ConsensusStateCLI(ctx, path) + state, _, err := man.Object(id).ConsensusStateCLI(ctx) if err != nil { return err } diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 8503be6b02e6..769792c16358 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -1,6 +1,8 @@ package connection import ( + "bytes" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" @@ -12,21 +14,27 @@ func (man Manager) CLIObject(connid, clientid string) Object { return obj } -func (obj Object) ConnectionCLI(ctx context.CLIContext, path merkle.Path) (res Connection, proof merkle.Proof, err error) { + + +func (obj Object) prefix() []byte { + return bytes.Split(obj.Connection.KeyBytes(), LocalRoot())[0] +} + +func (obj Object) ConnectionCLI(ctx context.CLIContext) (res Connection, proof merkle.Proof, err error) { tmproof, err := obj.Connection.Query(ctx, &res) - proof = merkle.NewProofFromValue(tmproof, path, obj.Connection) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Connection) return } -func (obj Object) AvailableCLI(ctx context.CLIContext, path merkle.Path) (res bool, proof merkle.Proof, err error) { +func (obj Object) AvailableCLI(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { res, tmproof, err := obj.Available.Query(ctx) - proof = merkle.NewProofFromValue(tmproof, path, obj.Available) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Available) return } -func (obj Object) KindCLI(ctx context.CLIContext, path merkle.Path) (res string, proof merkle.Proof, err error) { +func (obj Object) KindCLI(ctx context.CLIContext) (res string, proof merkle.Proof, err error) { res, tmproof, err := obj.Kind.Query(ctx) - proof = merkle.NewProofFromValue(tmproof, path, obj.Kind) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Kind) return } @@ -34,20 +42,30 @@ func (man Handshaker) CLIObject(connid, clientid string) HandshakeObject { return man.Object(man.man.CLIObject(connid, clientid)) } -func (obj HandshakeObject) StateCLI(ctx context.CLIContext, path merkle.Path) (res byte, proof merkle.Proof, err error){ +func (man Handshaker) CLIQuery(ctx context.CLIContext, connid string) (HandshakeObject, error) { + obj := man.man.Object(connid) + conn, _, err := obj.ConnectionCLI(ctx) + if err != nil { + return HandshakeObject{}, err + } + obj.Client = man.man.client.Object(conn.Client) + return man.Object(obj), nil +} + +func (obj HandshakeObject) StateCLI(ctx context.CLIContext) (res byte, proof merkle.Proof, err error){ res, tmproof, err := obj.State.Query(ctx) - proof = merkle.NewProofFromValue(tmproof, path, obj.State) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) return } -func (obj HandshakeObject) CounterpartyClientCLI(ctx context.CLIContext, path merkle.Path) (res string, proof merkle.Proof, err error) { +func (obj HandshakeObject) CounterpartyClientCLI(ctx context.CLIContext) (res string, proof merkle.Proof, err error) { res, tmproof, err := obj.CounterpartyClient.Query(ctx) - proof = merkle.NewProofFromValue(tmproof, path, obj.CounterpartyClient) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.CounterpartyClient) return } -func (obj HandshakeObject) NextTimeoutCLI(ctx context.CLIContext, path merkle.Path) (res uint64, proof merkle.Proof, err error){ +func (obj HandshakeObject) NextTimeoutCLI(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error){ res, tmproof, err := obj.NextTimeout.Query(ctx) - proof = merkle.NewProofFromValue(tmproof, path, obj.NextTimeout) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.NextTimeout) return } diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index 6be3c81bd9ce..efc330969faa 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -2,7 +2,6 @@ package cli import ( "fmt" - "strconv" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -17,20 +16,18 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) const ( FlagProve = "prove" ) -func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) connection.Object { - prefix := []byte(strconv.FormatInt(version, 10) + "/") - path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) + +func object(cdc *codec.Codec, storeKey string, prefix []byte, connid, clientid string) connection.Object { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) man := connection.NewManager(base, climan) - return man.Query(ctx, path, id) + return man.CLIObject(connid, clientid) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -47,16 +44,16 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { return ibcQueryCmd } -func QueryConnection(ctx context.CLIContext, obj connection.CLIObject, prove bool) (res utils.JSONObject, err error) { - conn, connp, err := obj.Connection(ctx) +func QueryConnection(ctx context.CLIContext, obj connection.Object, prove bool) (res utils.JSONObject, err error) { + conn, connp, err := obj.ConnectionCLI(ctx) if err != nil { return } - avail, availp, err := obj.Available(ctx) + avail, availp, err := obj.AvailableCLI(ctx) if err != nil { return } - kind, kindp, err := obj.Kind(ctx) + kind, kindp, err := obj.KindCLI(ctx) if err != nil { return } @@ -83,7 +80,7 @@ func GetCmdQueryConnection(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - obj := object(ctx, cdc, storeKey, ibc.Version, args[0]) + obj := object(cdc, storeKey, ibc.VersionPrefix(ibc.Version), args[0], "") jsonobj, err := QueryConnection(ctx, obj, viper.GetBool(FlagProve)) if err != nil { return err diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 0aaa1c5cda27..68283021c36e 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -2,7 +2,6 @@ package cli import ( "io/ioutil" - "strconv" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -18,7 +17,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) /* @@ -33,13 +31,11 @@ const ( FlagFrom2 = "from2" ) -func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) connection.CLIHandshakeObject { - prefix := []byte(strconv.FormatInt(version, 10) + "/") - path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) - base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) +func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, prefix []byte, connid string) (connection.HandshakeObject, error) { + base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) man := connection.NewHandshaker(connection.NewManager(base, climan)) - return man.CLIQuery(ctx, path, id) + return man.CLIQuery(ctx, connid) } func lastheight(ctx context.CLIContext) (uint64, error) { @@ -84,7 +80,10 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } - obj1 := handshake(ctx1, cdc, storeKey, ibc.Version, conn1id) + obj1, err := handshake(ctx1, cdc, storeKey, ibc.VersionPrefix(ibc.Version), conn1id) + if err != nil { + return err + } conn2id := args[2] conn2bz, err := ioutil.ReadFile(args[3]) @@ -96,7 +95,10 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } - obj2 := handshake(ctx2, cdc, storeKey, ibc.Version, conn1id) + obj2, err := handshake(ctx2, cdc, storeKey, ibc.VersionPrefix(ibc.Version), conn1id) + if err != nil { + return err + } // TODO: check state and if not Idle continue existing process height, err := lastheight(ctx2) @@ -123,19 +125,19 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } nextTimeout = height + 1000 - _, pconn, err := obj1.Connection(ctx1) + _, pconn, err := obj1.ConnectionCLI(ctx1) if err != nil { return err } - _, pstate, err := obj1.State(ctx1) + _, pstate, err := obj1.StateCLI(ctx1) if err != nil { return err } - _, ptimeout, err := obj1.NextTimeout(ctx1) + _, ptimeout, err := obj1.NextTimeoutCLI(ctx1) if err != nil { return err } - _, pcounter, err := obj1.CounterpartyClient(ctx1) + _, pcounter, err := obj1.CounterpartyClientCLI(ctx1) if err != nil { return err } @@ -161,19 +163,19 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } nextTimeout = height + 1000 - _, pconn, err = obj2.Connection(ctx2) + _, pconn, err = obj2.ConnectionCLI(ctx2) if err != nil { return err } - _, pstate, err = obj2.State(ctx2) + _, pstate, err = obj2.StateCLI(ctx2) if err != nil { return err } - _, ptimeout, err = obj2.NextTimeout(ctx2) + _, ptimeout, err = obj2.NextTimeoutCLI(ctx2) if err != nil { return err } - _, pcounter, err = obj2.CounterpartyClient(ctx2) + _, pcounter, err = obj2.CounterpartyClientCLI(ctx2) if err != nil { return err } @@ -192,11 +194,11 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command } timeout = nextTimeout - _, pstate, err = obj1.State(ctx1) + _, pstate, err = obj1.StateCLI(ctx1) if err != nil { return err } - _, ptimeout, err = obj1.NextTimeout(ctx1) + _, ptimeout, err = obj1.NextTimeoutCLI(ctx1) if err != nil { return err } diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index 5dda3702a186..1606497ec4f8 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -108,7 +108,7 @@ type Value interface { KeyBytes() []byte } -func NewProofFromValue(proof *merkle.Proof, path Path, value Value) Proof { +func NewProofFromValue(proof *merkle.Proof, prefix []byte, value Value) Proof { // TODO: check HasPrefix - return Proof{proof, bytes.TrimPrefix(value.KeyBytes(), path.KeyPrefix)} + return Proof{proof, bytes.TrimPrefix(value.KeyBytes(), prefix)} } diff --git a/x/ibc/version.go b/x/ibc/version.go index 11bd8ee5b3d3..b6648efb40c8 100644 --- a/x/ibc/version.go +++ b/x/ibc/version.go @@ -1,3 +1,9 @@ package ibc +import "strconv" + const Version int64 = 1 + +func VersionPrefix(version int64) []byte { + return []byte(strconv.FormatInt(version, 10) + "/") +} From 30aff5504d2ea9f153600b307d20a713e6a0ac00 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 25 Jun 2019 17:10:21 +0200 Subject: [PATCH 121/182] add CLIObject in progress --- client/context/query.go | 15 +++++++++------ x/ibc/02-client/cli.go | 1 - 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 98cd30690f0c..e8790cf3d5bf 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,22 +31,25 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) ([]byte, int64, error) { - return ctx.query(path, nil) +func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { + val, height, err = ctx.query(path, nil) + return } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { - return ctx.query(path, data) +func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { + val, height, err = ctx.query(path, data) + return } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { - return ctx.queryStore(key, storeName, "key") +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { + val, height, err = ctx.queryStore(key, storeName, "key") + return } // QueryABCI performs a query to a Tendermint node with the provide RequestQuery. diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index f199ac00d2b6..db03c1441329 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -23,4 +23,3 @@ func (obj Object) FrozenCLI(ctx context.CLIContext) (res bool, proof merkle.Proo proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Frozen) return } - From 9e46e5fa5a86117d1a9c784875122026661d79b1 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 26 Jun 2019 15:19:42 +0200 Subject: [PATCH 122/182] cli in progress --- client/context/query.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index e8790cf3d5bf..98cd30690f0c 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,25 +31,22 @@ func (ctx CLIContext) GetNode() (rpcclient.Client, error) { // Query performs a query to a Tendermint node with the provided path. // It returns the result and height of the query upon success or an error if // the query fails. -func (ctx CLIContext) Query(path string) (val []byte, height int64, err error) { - val, height, err = ctx.query(path, nil) - return +func (ctx CLIContext) Query(path string) ([]byte, int64, error) { + return ctx.query(path, nil) } // QueryWithData performs a query to a Tendermint node with the provided path // and a data payload. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryWithData(path string, data []byte) (val []byte, height int64, err error) { - val, height, err = ctx.query(path, data) - return +func (ctx CLIContext) QueryWithData(path string, data []byte) ([]byte, int64, error) { + return ctx.query(path, data) } // QueryStore performs a query to a Tendermint node with the provided key and // store name. It returns the result and height of the query upon success // or an error if the query fails. -func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (val []byte, height int64, err error) { - val, height, err = ctx.queryStore(key, storeName, "key") - return +func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) ([]byte, int64, error) { + return ctx.queryStore(key, storeName, "key") } // QueryABCI performs a query to a Tendermint node with the provide RequestQuery. From ee8d154f94a9c9f432c66884123855ccf1f5bccb Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 28 Jun 2019 17:43:53 +0200 Subject: [PATCH 123/182] add test in progress/ --- x/ibc/03-connection/manager.go | 2 ++ x/ibc/03-connection/tests/connection_test.go | 1 + x/ibc/23-commitment/store.go | 7 +++++++ 3 files changed, 10 insertions(+) diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index cc5da97a1386..ad3dd830503d 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -164,6 +164,7 @@ func (man Manager) create(ctx sdk.Context, id string, connection Connection, kin obj.Connection.Set(ctx, connection) obj.Kind.Set(ctx, kind) return + } // query() is used internally by the connection creators @@ -190,6 +191,7 @@ func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { if !obj.exists(ctx) { err = errors.New("Object not exists") return + } if !obj.Available.Get(ctx) { err = errors.New("Object not available") diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index 665f15b3142d..241e0acbc9ad 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -63,4 +63,5 @@ func TestHandshake(t *testing.T) { _, pstate = node.QueryValue(t, cliobj.State) _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) node.Counterparty.OpenConfirm(t, pstate, ptimeout) + } diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index cf76caac4b39..aa67723709b9 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -3,6 +3,7 @@ package commitment import ( "bytes" "errors" + "fmt" ) // Store proves key-value pairs' inclusion or non-inclusion with @@ -60,9 +61,12 @@ func NewStore(root Root, path Path, proofs []Proof) (res *store, err error) { err = errors.New("proof type not matching with root's") return } + fmt.Println("set key", string(proof.GetKey())) res.proofs[string(proof.GetKey())] = proof } + fmt.Printf("%+v\n", res) + return } @@ -80,10 +84,13 @@ func (store *store) Prove(key, value []byte) bool { } proof, ok := store.proofs[string(key)] if !ok { + fmt.Println("no proof") + fmt.Println("get key", string(key)) return false } err := proof.Verify(store.root, store.path, value) if err != nil { + fmt.Println("invalid proof") return false } store.verified[string(key)] = value From 10835cfaa0b03c2c360305d84b7c408e56000f12 Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 29 Jun 2019 14:40:30 +0200 Subject: [PATCH 124/182] handshake test now working --- x/ibc/03-connection/tests/connection_test.go | 1 - x/ibc/23-commitment/store.go | 7 ------- 2 files changed, 8 deletions(-) diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index 241e0acbc9ad..665f15b3142d 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -63,5 +63,4 @@ func TestHandshake(t *testing.T) { _, pstate = node.QueryValue(t, cliobj.State) _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) node.Counterparty.OpenConfirm(t, pstate, ptimeout) - } diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index aa67723709b9..cf76caac4b39 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -3,7 +3,6 @@ package commitment import ( "bytes" "errors" - "fmt" ) // Store proves key-value pairs' inclusion or non-inclusion with @@ -61,12 +60,9 @@ func NewStore(root Root, path Path, proofs []Proof) (res *store, err error) { err = errors.New("proof type not matching with root's") return } - fmt.Println("set key", string(proof.GetKey())) res.proofs[string(proof.GetKey())] = proof } - fmt.Printf("%+v\n", res) - return } @@ -84,13 +80,10 @@ func (store *store) Prove(key, value []byte) bool { } proof, ok := store.proofs[string(key)] if !ok { - fmt.Println("no proof") - fmt.Println("get key", string(key)) return false } err := proof.Verify(store.root, store.path, value) if err != nil { - fmt.Println("invalid proof") return false } store.verified[string(key)] = value From d7a5c3075d528f3688502fd8bcc370f82ab197a5 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 00:43:01 +0200 Subject: [PATCH 125/182] in progress --- x/ibc/04-channel/manager.go | 75 +++++++++++++++++++++++++++++++++++++ x/ibc/04-channel/types.go | 29 ++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 x/ibc/04-channel/manager.go create mode 100644 x/ibc/04-channel/types.go diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go new file mode 100644 index 000000000000..62e3ea9c5310 --- /dev/null +++ b/x/ibc/04-channel/manager.go @@ -0,0 +1,75 @@ +package channel + +import ( + "github.com/cosmos/cosmos-sdk/store/mapping" + + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +type Manager struct { + protocol mapping.Mapping + + connection connection.Manager + + remote *Manager +} + +func NewManager(protocol mapping.Base, connection connection.Manager) Manager { + return Manager{ + protocol: mapping.NewMapping(protocol, []byte("/")), + connection: connection, + } +} + +// CONTRACT: remote must be filled by the caller +func (man Manager) object(connid, chanid string) Object { + key := connid + "/channels/" + chanid + return Object{ + connid: connid, + chanid: chanid, + channel: man.protocol.Value([]byte(key)), + state: mapping.NewEnum(man.protocol.Value([]byte(key + "/state"))), + nexttimeout: mapping.NewInteger(man.protocol.Value([]byte(key+"/timeout")), mapping.Dec), + + // TODO: remove length functionality from mapping.Indeer(will be handled manually) + seqsend: mapping.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), mapping.Dec), + seqrecv: mapping.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), mapping.Dec), + packets: mapping.NewIndexer(man.protocol.Prefix([]byte(key+"/packets/")), mapping.Dec), + } +} + +func (man Manager) Create(ctx sdk.Context, connid, chanid string, channel Channel) (obj Object, err error) { + obj := man.object(connid, chanid) + if obj.exists(ctx) { + err = errors.New("channel already exists for the provided id") + return + } + obj.connection, err = man.connection.Query(ctx, connid) + if err != nil { + return + } + obj.channel.Set(ctx, channel) + remote := man.remote.object() +} + +type Object struct { + connid string + chanid string + channel mapping.Value + state mapping.Enum + nexttimeout mapping.Integer + + seqsend mapping.Integer + seqrecv mapping.Integer + packets mapping.Indexer + + connection connection.Object + + // CONTRACT: remote should not be used when remote + remote *Object +} + +func (obj Object) OpenInit(ctx sdk.Context) error { + // OpenInit will +} diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go new file mode 100644 index 000000000000..339b7c067c52 --- /dev/null +++ b/x/ibc/04-channel/types.go @@ -0,0 +1,29 @@ +package channel + +type State = byte + +const ( + Init State = iota + OpenTry + Open + CloseTry + Closed +) + +type Packet struct { + Sequence uint64 + TimeoutHeight uint64 + + SourceConnection string + SourceChannel string + DestConnection string + DestChannel string + + Data []byte +} + +type Channel struct { + Module string + Counterparty string + CounterpartyModule string +} From f951098175c01bf7805379dd4aa05cef81456d72 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 01:48:36 +0200 Subject: [PATCH 126/182] in progress --- x/ibc/04-channel/manager.go | 118 ++++++++++++++++++++++++++++++++++-- x/ibc/04-channel/types.go | 3 +- 2 files changed, 115 insertions(+), 6 deletions(-) diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 62e3ea9c5310..649dbc5cb75b 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -1,7 +1,11 @@ package channel import ( + "errors" + + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/mapping" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" @@ -16,8 +20,21 @@ type Manager struct { } func NewManager(protocol mapping.Base, connection connection.Manager) Manager { + man := newManager(protocol, connection) + man.remote = newRemoteManager(protocol.Cdc()) + return man +} + +func newRemoteManager(cdc *codec.Codec) *Manager { + protocol := mapping.NewBaseWithGetter(cdc, commitment.GetStore) + connection := connection.NewRemoteManager(cdc) + res := newManager(protocol, *connection) + return &res +} + +func newManager(protocol mapping.Base, connection connection.Manager) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/")), + protocol: mapping.NewMapping(protocol, []byte("/connection/")), connection: connection, } } @@ -40,7 +57,7 @@ func (man Manager) object(connid, chanid string) Object { } func (man Manager) Create(ctx sdk.Context, connid, chanid string, channel Channel) (obj Object, err error) { - obj := man.object(connid, chanid) + obj = man.object(connid, chanid) if obj.exists(ctx) { err = errors.New("channel already exists for the provided id") return @@ -49,8 +66,35 @@ func (man Manager) Create(ctx sdk.Context, connid, chanid string, channel Channe if err != nil { return } + if obj.connection.State(ctx) != connection.Open { + err = errors.New("connection exists but not opened") + return + } obj.channel.Set(ctx, channel) - remote := man.remote.object() + remote := man.remote.object(obj.connection.Value(ctx).Counterparty, channel.Counterparty) + obj.remote = &remote + return +} + +func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, err error) { + obj = man.object(connid, chanid) + if !obj.exists(ctx) { + err = errors.New("channel not exists for the provided id") + return + } + obj.connection, err = man.connection.Query(ctx, connid) + if err != nil { + return + } + if obj.connection.State(ctx) != connection.Open { + err = errors.New("connection exists but not opened") + return + } + + channel := obj.Value(ctx) + remote := man.remote.object(obj.connection.Value(ctx).Counterparty, channel.Counterparty) + obj.remote = &remote + return } type Object struct { @@ -70,6 +114,70 @@ type Object struct { remote *Object } -func (obj Object) OpenInit(ctx sdk.Context) error { - // OpenInit will +func (obj Object) ConnID() string { + return obj.connid +} + +func (obj Object) ChanID() string { + return obj.chanid +} + +func (obj Object) Value(ctx sdk.Context) (res Channel) { + obj.channel.Get(ctx, &res) + return +} + +func (obj Object) exists(ctx sdk.Context) bool { + return obj.channel.Exists(ctx) +} + +func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { + if uint64(ctx.BlockHeight()) > timeoutHeight { + return errors.New("timeout") + } + return nil +} + +// TODO: ocapify callingModule +func (obj Object) OpenInit(ctx sdk.Context, callingModule string) error { + // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), + // which will ensure + // assert(get() === null) and + // set() and + // connection.state == open + + if !obj.state.Transit(ctx, Idle, Init) { + return errors.New("init on non-idle channel") + } + + channel := obj.Value(ctx) + if callingModule != channel.Module { + return errors.New("setting wrong module") + } + + obj.seqsend.Set(ctx, 0) + obj.seqrecv.Set(ctx, 0) + + return nil +} + +func (obj Object) OpenTry(ctx sdk.Context, callingModule string, timeoutHeight, nextTimeoutHeight uint64) error { + if !obj.state.Transit(ctx, Idle, OpenTry) { + return errors.New("opentry on non-idle channel") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + // XXX +} + +func (obj Object) Send(ctx sdk.Context, packet Packet) { + +} + +func (obj Object) Receive(ctx sdk.Context, packet Packet) { + } diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index 339b7c067c52..a679780a6cba 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -3,7 +3,8 @@ package channel type State = byte const ( - Init State = iota + Idle State = iota + Init OpenTry Open CloseTry From 7a0b2550ffd6922f55d5482aa4e0428de83c3335 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 17:11:46 +0200 Subject: [PATCH 127/182] add send/receive --- x/ibc/04-channel/manager.go | 93 +++++++++++++++++++++++++++++++++---- x/ibc/04-channel/types.go | 7 +++ 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 649dbc5cb75b..65831512a465 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) +// Manager is unrestricted type Manager struct { protocol mapping.Mapping @@ -97,6 +98,51 @@ func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, er return } +func (man Manager) Module(module string, chanid func(string) bool) ModuleManager { + return ModuleManager{ + man: man, + module: module, + chanid: chanid, + } +} + +// ModuleManage is module specific +type ModuleManager struct { + man Manager + module string + chanid func(string) bool +} + +func (man ModuleManager) Create(ctx sdk.Context, connid, chanid string, channel Channel) (Object, error) { + if !man.chanid(chanid) { + return Object{}, errors.New("invalid channel id") + } + + if channel.Module != man.module { + return Object{}, errors.New("invalid module") + } + + return man.man.Create(ctx, connid, chanid, channel) +} + +func (man ModuleManager) Query(ctx sdk.Context, connid, chanid string) (Object, error) { + if !man.chanid(chanid) { + return Object{}, errors.New("invalid channel id") + } + + obj, err := man.man.Query(ctx, connid, chanid) + if err != nil { + return Object{}, err + } + + if obj.Value(ctx).Module != man.module { + return Object{}, errors.New("invalid module") + } + + return obj, nil +} + +// XXX: remove connid(already exists in connection.id) type Object struct { connid string chanid string @@ -139,29 +185,26 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { } // TODO: ocapify callingModule -func (obj Object) OpenInit(ctx sdk.Context, callingModule string) error { +func (obj Object) OpenInit(ctx sdk.Context) error { // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), // which will ensure // assert(get() === null) and // set() and // connection.state == open + // getCallingModule() === channel.moduleIdentifier is ensured by ModuleManager + if !obj.state.Transit(ctx, Idle, Init) { return errors.New("init on non-idle channel") } - channel := obj.Value(ctx) - if callingModule != channel.Module { - return errors.New("setting wrong module") - } - obj.seqsend.Set(ctx, 0) obj.seqrecv.Set(ctx, 0) return nil } -func (obj Object) OpenTry(ctx sdk.Context, callingModule string, timeoutHeight, nextTimeoutHeight uint64) error { +func (obj Object) OpenTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { if !obj.state.Transit(ctx, Idle, OpenTry) { return errors.New("opentry on non-idle channel") } @@ -174,10 +217,42 @@ func (obj Object) OpenTry(ctx sdk.Context, callingModule string, timeoutHeight, // XXX } -func (obj Object) Send(ctx sdk.Context, packet Packet) { +func (obj Object) Send(ctx sdk.Context, packet Packet) error { + if obj.state.Get(ctx) != Open { + return errors.New("send on non-open channel") + } + + if obj.connection.State(ctx) != Open { + return errors.New("send on non-open connection") + } + + if uint64(obj.connection.Client(ctx).GetBase().GetHeight()) >= packet.Timeout() { + return errors.New("timeout height higher than the latest known") + } + obj.packets.Set(ctx, obj.seqsend.Incr(ctx), packet) + + return nil } -func (obj Object) Receive(ctx sdk.Context, packet Packet) { +func (obj Object) Receive(ctx sdk.Context, packet Packet) error { + if obj.state.Get(ctx) != Open { + return errors.New("send on non-open channel") + } + + if obj.connection.State(ctx) != Open { + return errors.New("send on non-open connection") + } + + err := assertTimeout(ctx, packet.Timeout()) + if err != nil { + return err + } + // XXX: increment should happen before verification, reflect on the spec + if !obj.remote.packets.Value(obj.seqrecv.Incr(ctx)).Is(ctx, packet.Commit()) { + return errors.New("verification failed") + } + + return nil } diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index a679780a6cba..ede4dc69c8d6 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -11,6 +11,7 @@ const ( Closed ) +/* type Packet struct { Sequence uint64 TimeoutHeight uint64 @@ -22,6 +23,12 @@ type Packet struct { Data []byte } +*/ + +type Packet interface { + Timeout() uint64 + Commit() []byte // Can be a commit message +} type Channel struct { Module string From e8f16aa99e2bbb1e80970c9148c4b386b771d6f2 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 19:08:55 +0200 Subject: [PATCH 128/182] in progress --- x/ibc/04-channel/manager.go | 85 +++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 31 deletions(-) diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 65831512a465..854d9095e791 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -17,34 +17,36 @@ type Manager struct { connection connection.Manager - remote *Manager + counterparty CounterpartyManager } -func NewManager(protocol mapping.Base, connection connection.Manager) Manager { - man := newManager(protocol, connection) - man.remote = newRemoteManager(protocol.Cdc()) - return man -} +type CounterpartyManager struct { + protocol commitment.Mapping -func newRemoteManager(cdc *codec.Codec) *Manager { - protocol := mapping.NewBaseWithGetter(cdc, commitment.GetStore) - connection := connection.NewRemoteManager(cdc) - res := newManager(protocol, *connection) - return &res + connection connection.CounterpartyManager } -func newManager(protocol mapping.Base, connection connection.Manager) Manager { +func NewManager(protocol mapping.Base, connection connection.Manager) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/connection/")), - connection: connection, + protocol: mapping.NewMapping(protocol, []byte("/connection/")), + connection: connection, + counterparty: NewCounterpartyManager(protocol.Cdc()), + } +} + +func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { + protocol := commitment.NewBase(cdc) + + return CounterpartyManager{ + protocol: commitment.NewMapping(protocol, []byte("/connection/")), + connection: connection.NewCounterpartyManager(cdc), } } -// CONTRACT: remote must be filled by the caller +// CONTRACT: connection and counterparty must be filled by the caller func (man Manager) object(connid, chanid string) Object { key := connid + "/channels/" + chanid return Object{ - connid: connid, chanid: chanid, channel: man.protocol.Value([]byte(key)), state: mapping.NewEnum(man.protocol.Value([]byte(key + "/state"))), @@ -57,6 +59,20 @@ func (man Manager) object(connid, chanid string) Object { } } +func (man CounterpartyManager) object(connid, chanid string) CounterObject { + key := connid + "/channels/" + chanid + return CounterObject{ + chanid: chanid, + channel: man.protocol.Value([]byte(key)), + state: commitment.NewEnum(man.protocol.Value([]byte(key + "/state"))), + nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(key+"/timeout")), mapping.Dec), + + seqsend: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), mapping.Dec), + seqrecv: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), mapping.Dec), + // packets: commitment.NewIndexer(man.protocol.Prefix([]byte(key + "/packets")), mapping.Dec), + } +} + func (man Manager) Create(ctx sdk.Context, connid, chanid string, channel Channel) (obj Object, err error) { obj = man.object(connid, chanid) if obj.exists(ctx) { @@ -67,13 +83,12 @@ func (man Manager) Create(ctx sdk.Context, connid, chanid string, channel Channe if err != nil { return } - if obj.connection.State(ctx) != connection.Open { - err = errors.New("connection exists but not opened") - return - } + counterconnid := obj.connection.Value(ctx).Counterparty + obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) + obj.counterparty.connection = man.counterparty.connection.Query(counterconnid) + obj.channel.Set(ctx, channel) - remote := man.remote.object(obj.connection.Value(ctx).Counterparty, channel.Counterparty) - obj.remote = &remote + return } @@ -93,8 +108,10 @@ func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, er } channel := obj.Value(ctx) - remote := man.remote.object(obj.connection.Value(ctx).Counterparty, channel.Counterparty) - obj.remote = &remote + counterconnid := obj.connection.Value(ctx).Counterparty + obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) + obj.counterparty.connection = man.counterparty.connection.Query(counterconnid) + return } @@ -142,9 +159,7 @@ func (man ModuleManager) Query(ctx sdk.Context, connid, chanid string) (Object, return obj, nil } -// XXX: remove connid(already exists in connection.id) type Object struct { - connid string chanid string channel mapping.Value state mapping.Enum @@ -156,12 +171,20 @@ type Object struct { connection connection.Object - // CONTRACT: remote should not be used when remote - remote *Object + counterparty CounterObject } -func (obj Object) ConnID() string { - return obj.connid +type CounterObject struct { + chanid string + channel commitment.Value + state commitment.Enum + nexttimeout commitment.Integer + + seqsend commitment.Integer + seqrecv commitment.Integer + //packets commitment.Indexer + + connection connection.CounterObject } func (obj Object) ChanID() string { @@ -250,7 +273,7 @@ func (obj Object) Receive(ctx sdk.Context, packet Packet) error { } // XXX: increment should happen before verification, reflect on the spec - if !obj.remote.packets.Value(obj.seqrecv.Incr(ctx)).Is(ctx, packet.Commit()) { + if !obj.counterparty.packets.Value(obj.seqrecv.Incr(ctx)).Is(ctx, packet.Commit()) { return errors.New("verification failed") } From 833aeab40a60140bac6f593c8f4c19b8c2541fba Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 11 Jun 2019 19:16:45 +0200 Subject: [PATCH 129/182] fix packets --- x/ibc/04-channel/manager.go | 4 ++-- x/ibc/23-commitment/value.go | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 854d9095e791..d56451ba1195 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -69,7 +69,7 @@ func (man CounterpartyManager) object(connid, chanid string) CounterObject { seqsend: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), mapping.Dec), seqrecv: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), mapping.Dec), - // packets: commitment.NewIndexer(man.protocol.Prefix([]byte(key + "/packets")), mapping.Dec), + packets: commitment.NewIndexer(man.protocol.Prefix([]byte(key+"/packets")), mapping.Dec), } } @@ -182,7 +182,7 @@ type CounterObject struct { seqsend commitment.Integer seqrecv commitment.Integer - //packets commitment.Indexer + packets commitment.Indexer connection connection.CounterObject } diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index 165b3666d4d3..18e1a19c2a9e 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -35,8 +35,22 @@ func (m Mapping) Prefix(prefix []byte) Mapping { } } -// Value is for proving commitment proof on a speicifc key-value point in the other state -// using the already initialized commitment store. +type Indexer struct { + Mapping + enc state.IntEncoding +} + +func NewIndexer(m Mapping, enc state.IntEncoding) Indexer { + return Indexer{ + Mapping: m, + enc: enc, + } +} + +func (ix Indexer) Value(index uint64) Value { + return ix.Mapping.Value(state.EncodeInt(index, ix.enc)) +} + type Value struct { m Mapping key []byte From 8893b4b989f4de335717d9e6415fcbafe874643d Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 13 Jun 2019 16:59:05 +0200 Subject: [PATCH 130/182] in progress --- x/ibc/04-channel/manager.go | 45 +++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index d56451ba1195..0eccb94b5dd8 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -4,7 +4,7 @@ import ( "errors" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/mapping" + "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" @@ -13,7 +13,7 @@ import ( // Manager is unrestricted type Manager struct { - protocol mapping.Mapping + protocol state.Mapping connection connection.Manager @@ -26,9 +26,9 @@ type CounterpartyManager struct { connection connection.CounterpartyManager } -func NewManager(protocol mapping.Base, connection connection.Manager) Manager { +func NewManager(protocol state.Base, connection connection.Manager) Manager { return Manager{ - protocol: mapping.NewMapping(protocol, []byte("/connection/")), + protocol: state.NewMapping(protocol, []byte("/connection/")), connection: connection, counterparty: NewCounterpartyManager(protocol.Cdc()), } @@ -49,13 +49,13 @@ func (man Manager) object(connid, chanid string) Object { return Object{ chanid: chanid, channel: man.protocol.Value([]byte(key)), - state: mapping.NewEnum(man.protocol.Value([]byte(key + "/state"))), - nexttimeout: mapping.NewInteger(man.protocol.Value([]byte(key+"/timeout")), mapping.Dec), + state: state.NewEnum(man.protocol.Value([]byte(key + "/state"))), + nexttimeout: state.NewInteger(man.protocol.Value([]byte(key+"/timeout")), state.Dec), - // TODO: remove length functionality from mapping.Indeer(will be handled manually) - seqsend: mapping.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), mapping.Dec), - seqrecv: mapping.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), mapping.Dec), - packets: mapping.NewIndexer(man.protocol.Prefix([]byte(key+"/packets/")), mapping.Dec), + // TODO: remove length functionality from state.Indeer(will be handled manually) + seqsend: state.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), + seqrecv: state.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), state.Dec), + packets: state.NewIndexer(man.protocol.Prefix([]byte(key+"/packets/")), state.Dec), } } @@ -65,11 +65,11 @@ func (man CounterpartyManager) object(connid, chanid string) CounterObject { chanid: chanid, channel: man.protocol.Value([]byte(key)), state: commitment.NewEnum(man.protocol.Value([]byte(key + "/state"))), - nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(key+"/timeout")), mapping.Dec), + nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(key+"/timeout")), state.Dec), - seqsend: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), mapping.Dec), - seqrecv: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), mapping.Dec), - packets: commitment.NewIndexer(man.protocol.Prefix([]byte(key+"/packets")), mapping.Dec), + seqsend: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), + seqrecv: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), state.Dec), + packets: commitment.NewIndexer(man.protocol.Prefix([]byte(key+"/packets")), state.Dec), } } @@ -161,13 +161,13 @@ func (man ModuleManager) Query(ctx sdk.Context, connid, chanid string) (Object, type Object struct { chanid string - channel mapping.Value - state mapping.Enum - nexttimeout mapping.Integer + channel state.Value + state state.Enum + nexttimeout state.Integer - seqsend mapping.Integer - seqrecv mapping.Integer - packets mapping.Indexer + seqsend state.Integer + seqrecv state.Integer + packets state.Indexer connection connection.Object @@ -227,6 +227,7 @@ func (obj Object) OpenInit(ctx sdk.Context) error { return nil } +/* func (obj Object) OpenTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { if !obj.state.Transit(ctx, Idle, OpenTry) { return errors.New("opentry on non-idle channel") @@ -239,7 +240,7 @@ func (obj Object) OpenTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint // XXX } - +*/ func (obj Object) Send(ctx sdk.Context, packet Packet) error { if obj.state.Get(ctx) != Open { return errors.New("send on non-open channel") @@ -249,7 +250,7 @@ func (obj Object) Send(ctx sdk.Context, packet Packet) error { return errors.New("send on non-open connection") } - if uint64(obj.connection.Client(ctx).GetBase().GetHeight()) >= packet.Timeout() { + if uint64(obj.connection.Client(ctx).GetHeight()) >= packet.Timeout() { return errors.New("timeout height higher than the latest known") } From 99de876fba2f587872ca8481c8288f357f8f0847 Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 6 Jul 2019 19:59:22 +0200 Subject: [PATCH 131/182] in progress --- x/ibc/04-channel/cli.go | 91 +++++++++++++++++++++++++++++++++ x/ibc/04-channel/manager.go | 28 +++++----- x/ibc/04-channel/tests/types.go | 28 ++++++++++ x/ibc/04-channel/types.go | 6 +-- x/ibc/05-port/manager.go | 14 +++++ 5 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 x/ibc/04-channel/cli.go create mode 100644 x/ibc/04-channel/tests/types.go create mode 100644 x/ibc/05-port/manager.go diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go new file mode 100644 index 000000000000..600c8d2bacee --- /dev/null +++ b/x/ibc/04-channel/cli.go @@ -0,0 +1,91 @@ +package channel + +import ( + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +// CLIObject stores the key for each object fields +type CLIObject struct { + ChanID string + ChannelKey []byte + StateKey []byte + TimeoutKey []byte + + SeqSendKey []byte + SeqRecvKey []byte + PacketKey func(index uint64) []byte + + Connection connection.CLIObject + + Root merkle.Root + Cdc *codec.Codec +} + +func (man Manager) CLIObject(root merkle.Root, connid, chanid string) CLIObject { + obj := man.object(connid, chanid) + return CLIObject{ + ChanID: chanid, + ChannelKey: obj.channel.Key(), + StateKey: obj.state.Key(), + TimeoutKey: obj.nexttimeout.Key(), + + SeqSendKey: obj.seqsend.Key(), + SeqRecvKey: obj.seqrecv.Key(), + PacketKey: func(index uint64) []byte { + return obj.packets.Value(index).Key() + }, + + Connection: man.connection.CLIObject(root, connid), + + Root: root, + Cdc: obj.channel.Cdc(), + } +} + +func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { + resp, err := ctx.QueryABCI(obj.Root.RequestQuery(key)) + if err != nil { + return merkle.Proof{}, err + } + proof := merkle.Proof{ + Key: key, + Proof: resp.Proof, + } + err = obj.Cdc.UnmarshalBinaryBare(resp.Value, ptr) + return proof, err + +} + +func (obj CLIObject) Channel(ctx context.CLIContext) (res Channel, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.ChannelKey, &res) + return +} + +func (obj CLIObject) State(ctx context.CLIContext) (res State, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.StateKey, &res) + return +} + +func (obj CLIObject) Timeout(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.TimeoutKey, &res) + return +} + +func (obj CLIObject) SeqSend(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.SeqSendKey, &res) + return +} + +func (obj CLIObject) SeqRecv(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.SeqRecvKey, &res) + return +} + +func (obj CLIObject) Packet(ctx context.CLIContext, index uint64) (res Packet, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.PacketKey(index), &res) + return +} diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 0eccb94b5dd8..e32c113ff716 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -115,34 +115,34 @@ func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, er return } -func (man Manager) Module(module string, chanid func(string) bool) ModuleManager { - return ModuleManager{ +func (man Manager) Port(port string, chanid func(string) bool) PortManager { + return PortManager{ man: man, - module: module, + port: module, chanid: chanid, } } -// ModuleManage is module specific -type ModuleManager struct { +// PortManage is port specific +type PortManager struct { man Manager - module string + port string chanid func(string) bool } -func (man ModuleManager) Create(ctx sdk.Context, connid, chanid string, channel Channel) (Object, error) { +func (man PortManager) Create(ctx sdk.Context, connid, chanid string, channel Channel) (Object, error) { if !man.chanid(chanid) { return Object{}, errors.New("invalid channel id") } - if channel.Module != man.module { - return Object{}, errors.New("invalid module") + if channel.Port != man.port { + return Object{}, errors.New("invalid port") } return man.man.Create(ctx, connid, chanid, channel) } -func (man ModuleManager) Query(ctx sdk.Context, connid, chanid string) (Object, error) { +func (man PortManager) Query(ctx sdk.Context, connid, chanid string) (Object, error) { if !man.chanid(chanid) { return Object{}, errors.New("invalid channel id") } @@ -152,8 +152,8 @@ func (man ModuleManager) Query(ctx sdk.Context, connid, chanid string) (Object, return Object{}, err } - if obj.Value(ctx).Module != man.module { - return Object{}, errors.New("invalid module") + if obj.Value(ctx).Port != man.port { + return Object{}, errors.New("invalid port") } return obj, nil @@ -207,7 +207,7 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { return nil } -// TODO: ocapify callingModule +// TODO: ocapify callingPort func (obj Object) OpenInit(ctx sdk.Context) error { // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), // which will ensure @@ -215,7 +215,7 @@ func (obj Object) OpenInit(ctx sdk.Context) error { // set() and // connection.state == open - // getCallingModule() === channel.moduleIdentifier is ensured by ModuleManager + // getCallingPort() === channel.portIdentifier is ensured by PortManager if !obj.state.Transit(ctx, Idle, Init) { return errors.New("init on non-idle channel") diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go new file mode 100644 index 000000000000..049556b0ecd3 --- /dev/null +++ b/x/ibc/04-channel/tests/types.go @@ -0,0 +1,28 @@ +package channel + +import ( + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/tests" +) + +type Node struct { + *connection.Node + Counterparty *Node +} + +func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { + conn := connection.NewNode(self, counter, cdc) + + res := &Node{ + Node: conn, + } + + res.Counterparty = &Node{ + Node: conn.Counterparty, + Counterparty: res, + } + + return res +} diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index ede4dc69c8d6..2a8922b41abc 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -31,7 +31,7 @@ type Packet interface { } type Channel struct { - Module string - Counterparty string - CounterpartyModule string + Port string + Counterparty string + CounterpartyPort string } diff --git a/x/ibc/05-port/manager.go b/x/ibc/05-port/manager.go new file mode 100644 index 000000000000..782bf7202763 --- /dev/null +++ b/x/ibc/05-port/manager.go @@ -0,0 +1,14 @@ +package port + +import ( + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type Manager struct { + protocol state.Mapping +} + +func NewManager(protocol state.Base) Manager { + return Manager +} From 48d9088aaffb1c36731a9efaaf2e2bfdde0d8940 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 13:05:02 +0200 Subject: [PATCH 132/182] in progress --- x/ibc/04-channel/manager.go | 25 +++++++++++++++---------- x/ibc/04-channel/tests/types.go | 5 +++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index e32c113ff716..f4926d529f75 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -160,25 +160,30 @@ func (man PortManager) Query(ctx sdk.Context, connid, chanid string) (Object, er } type Object struct { - chanid string - channel state.Value - state state.Enum - nexttimeout state.Integer + chanid string + + protocol state.Mapping + channel state.Value + /* + state state.Enum + nexttimeout state.Integer + */ seqsend state.Integer seqrecv state.Integer packets state.Indexer connection connection.Object - - counterparty CounterObject } type CounterObject struct { - chanid string - channel commitment.Value - state commitment.Enum - nexttimeout commitment.Integer + chanid string + channel commitment.Value + + /* + state commitment.Enum + nexttimeout commitment.Integer + */ seqsend commitment.Integer seqrecv commitment.Integer diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 049556b0ecd3..cb2e94bfc780 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -26,3 +26,8 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { return res } + +func OpenInit(t *testing.T) { + ctx, man := node.Handshaker(t) + +} From b991e8451003046cca0374fcdb7073d54b8817f6 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 15:16:38 +0200 Subject: [PATCH 133/182] in progress --- x/ibc/04-channel/handshake.go | 420 ++++++++++++++++++++++++++++++++++ x/ibc/04-channel/manager.go | 20 +- 2 files changed, 432 insertions(+), 8 deletions(-) create mode 100644 x/ibc/04-channel/handshake.go diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go new file mode 100644 index 000000000000..d08a3209deca --- /dev/null +++ b/x/ibc/04-channel/handshake.go @@ -0,0 +1,420 @@ +package connection + +import ( + "errors" + + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +type State = byte + +const ( + Idle State = iota + Init + OpenTry + Open + CloseTry + Closed +) + +type Handshake struct { + Counterparty string + CounterpartyClient string +} + +type Handshaker struct { + man Manager + + counterparty CounterpartyHandshaker +} + +func (man Handshaker) Kind() string { + return "handshake" +} + +// TODO: ocapify Manager; an actor who holds Manager +// should not be able to construct creaters from it +// or add Seal() method to Manager? +func NewHandshaker(man Manager) Handshaker { + return Handshaker{ + man: man, + + counterparty: CounterpartyHandshaker{man.counterparty}, + } +} + +type CounterpartyHandshaker struct { + man CounterpartyManager +} + +type HandshakeObject struct { + Object + + state state.Enum + handshake state.Value // type Handshake + nextTimeout state.Integer + + counterparty CounterHandshakeObject +} + +type CounterHandshakeObject struct { + CounterObject + + state commitment.Enum + handshake commitment.Value + nextTimeout commitment.Integer +} + +// CONTRACT: client and remote must be filled by the caller +func (man Handshaker) object(parent Object) HandshakeObject { + return HandshakeObject{ + Object: parent, + + state: state.NewEnum(man.man.protocol.Value([]byte(parent.id + "/state"))), + handshake: man.man.protocol.Value([]byte(parent.id + "/handshake")), + nextTimeout: state.NewInteger(man.man.protocol.Value([]byte(parent.id+"/timeout")), state.Dec), + + // CONTRACT: counterparty must be filled by the caller + } +} + +func (man CounterpartyHandshaker) object(id string) CounterHandshakeObject { + return CounterHandshakeObject{ + CounterObject: man.man.object(id), + + state: commitment.NewEnum(man.man.protocol.Value([]byte(id + "/state"))), + handshake: man.man.protocol.Value([]byte(id + "/handshake")), + nextTimeout: commitment.NewInteger(man.man.protocol.Value([]byte(id+"/timeout")), state.Dec), + } +} + +func (man Handshaker) create(ctx sdk.Context, id, clientid string, handshake Handshake) (obj HandshakeObject, err error) { + cobj, err := man.man.create(ctx, id, clientid, man.Kind()) + if err != nil { + return + } + obj = man.object(cobj) + obj.handshake.Set(ctx, handshake) + obj.counterparty = man.counterparty.object(handshake.Counterparty) + return obj, nil +} + +func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeObject, err error) { + cobj, err := man.man.query(ctx, id, man.Kind()) + if err != nil { + return + } + obj = man.object(cobj) + handshake := obj.Handshake(ctx) + obj.counterparty = man.counterparty.object(handshake.Counterparty) + return +} + +func (obj HandshakeObject) State(ctx sdk.Context) byte { + return obj.state.Get(ctx) +} + +func (obj HandshakeObject) Handshake(ctx sdk.Context) (res Handshake) { + obj.handshake.Get(ctx, &res) + return +} + +func (obj HandshakeObject) Timeout(ctx sdk.Context) uint64 { + return obj.nextTimeout.Get(ctx) +} + +func (obj HandshakeObject) NextTimeout(ctx sdk.Context) uint64 { + return obj.nextTimeout.Get(ctx) +} + +func (obj HandshakeObject) remove(ctx sdk.Context) { + obj.Object.remove(ctx) + obj.state.Delete(ctx) + obj.handshake.Delete(ctx) + obj.nextTimeout.Delete(ctx) +} + +func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { + if uint64(ctx.BlockHeight()) > timeoutHeight { + return errors.New("timeout") + } + + return nil +} + +// Using proofs: none +func (man Handshaker) OpenInit(ctx sdk.Context, + id, clientid string, handshake Handshake, nextTimeoutHeight uint64, +) (HandshakeObject, error) { + // man.Create() will ensure + // assert(get("connections/{identifier}") === null) and + // set("connections{identifier}", connection) + obj, err := man.create(ctx, id, clientid, handshake) + if err != nil { + return HandshakeObject{}, err + } + + obj.nextTimeout.Set(ctx, nextTimeoutHeight) + obj.state.Set(ctx, Init) + + return obj, nil +} + +// Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} +func (man Handshaker) OpenTry(ctx sdk.Context, + id, clientid string, handshake Handshake, timeoutHeight, nextTimeoutHeight uint64, +) (obj HandshakeObject, err error) { + obj, err = man.create(ctx, id, clientid, handshake) + if err != nil { + return + } + + err = assertTimeout(ctx, timeoutHeight) + if err != nil { + return + } + + if !obj.counterparty.state.Is(ctx, Init) { + err = errors.New("counterparty state not init") + return + } + + if !obj.counterparty.handshake.Is(ctx, Handshake{ + Counterparty: id, + CounterpartyClient: clientid, + }) { + err = errors.New("wrong counterparty") + return + } + + if !obj.counterparty.clientid.Is(ctx, handshake.CounterpartyClient) { + err = errors.New("counterparty client not match") + return + } + + if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { + err = errors.New("unexpected counterparty timeout value") + return + } + + // TODO: commented out, need to check whether the stored client is compatible + // make a separate module that manages recent n block headers + // ref #4647 + /* + var expected client.ConsensusState + obj.self.Get(ctx, expheight, &expected) + if !obj.counterparty.client.Is(ctx, expected) { + return errors.New("unexpected counterparty client value") + } + */ + + // CONTRACT: OpenTry() should be called after man.Create(), not man.Query(), + // which will ensure + // assert(get("connections/{desiredIdentifier}") === null) and + // set("connections{identifier}", connection) + + obj.state.Set(ctx, OpenTry) + obj.nextTimeout.Set(ctx, nextTimeoutHeight) + + return +} + +// Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} +func (man Handshaker) OpenAck(ctx sdk.Context, + id string /*expheight uint64, */, timeoutHeight, nextTimeoutHeight uint64, +) (obj HandshakeObject, err error) { + obj, err = man.query(ctx, id) + if err != nil { + return + } + + if !obj.state.Transit(ctx, Init, Open) { + err = errors.New("ack on non-init connection") + return + } + + err = assertTimeout(ctx, timeoutHeight) + if err != nil { + return + } + + if !obj.counterparty.handshake.Is(ctx, Handshake{ + Counterparty: obj.ID(), + CounterpartyClient: obj.Client().ID(), + }) { + err = errors.New("wrong counterparty") + return + } + + if !obj.counterparty.state.Is(ctx, OpenTry) { + err = errors.New("counterparty state not opentry") + return + } + + if !obj.counterparty.clientid.Is(ctx, obj.Handshake(ctx).CounterpartyClient) { + err = errors.New("counterparty client not match") + return + } + + if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { + err = errors.New("unexpected counterparty timeout value") + return + } + + // TODO: commented out, implement in v1 + /* + var expected client.ConsensusState + obj.self.Get(ctx, expheight, &expected) + if !obj.counterparty.client.Is(ctx, expected) { + return errors.New("unexpected counterparty client value") + } + */ + + obj.available.Set(ctx, true) + obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) + + return +} + +// Using proofs: counterparty.{connection,state, nextTimeout} +func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint64) (obj HandshakeObject, err error) { + obj, err = man.query(ctx, id) + if err != nil { + return + } + + if !obj.state.Transit(ctx, OpenTry, Open) { + err = errors.New("confirm on non-try connection") + return + } + + err = assertTimeout(ctx, timeoutHeight) + if err != nil { + return + } + + if !obj.counterparty.state.Is(ctx, Open) { + err = errors.New("counterparty state not open") + return + } + + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + err = errors.New("unexpected counterparty timeout value") + return + } + + obj.available.Set(ctx, true) + obj.nextTimeout.Set(ctx, 0) + + return +} + +func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { + if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + return errors.New("timeout height not yet reached") + } + + switch obj.state.Get(ctx) { + case Init: + if !obj.counterparty.handshake.Is(ctx, nil) { + return errors.New("counterparty connection exists") + } + case OpenTry: + if !(obj.counterparty.state.Is(ctx, Init) || + obj.counterparty.clientid.Is(ctx, "")) /*FIXME: empty string does not work, it should be nil*/ { + return errors.New("counterparty connection state not init") + } + // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) + case Open: + if obj.counterparty.state.Is(ctx, OpenTry) { + return errors.New("counterparty connection state not tryopen") + } + } + + obj.remove(ctx) + + return nil +} + +func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error { + if !obj.state.Transit(ctx, Open, CloseTry) { + return errors.New("closeinit on non-open connection") + } + + obj.nextTimeout.Set(ctx, nextTimeout) + + return nil +} + +func (obj HandshakeObject) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { + if !obj.state.Transit(ctx, Open, Closed) { + return errors.New("closetry on non-open connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.counterparty.state.Is(ctx, CloseTry) { + return errors.New("unexpected counterparty state value") + } + + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + return errors.New("unexpected counterparty timeout value") + } + + obj.nextTimeout.Set(ctx, nextTimeoutHeight) + + return nil +} + +func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { + if !obj.state.Transit(ctx, CloseTry, Closed) { + return errors.New("closeack on non-closetry connection") + } + + err := assertTimeout(ctx, timeoutHeight) + if err != nil { + return err + } + + if !obj.counterparty.state.Is(ctx, Closed) { + return errors.New("unexpected counterparty state value") + } + + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + return errors.New("unexpected counterparty timeout value") + } + + obj.nextTimeout.Set(ctx, 0) + + return nil +} + +func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { + if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + return errors.New("timeout height not yet reached") + } + + // XXX: double check if the user can bypass the verification logic somehow + switch obj.state.Get(ctx) { + case CloseTry: + if !obj.counterparty.state.Is(ctx, Open) { + return errors.New("counterparty connection state not open") + } + case Closed: + if !obj.counterparty.state.Is(ctx, CloseTry) { + return errors.New("counterparty connection state not closetry") + } + } + + obj.state.Set(ctx, Open) + obj.nextTimeout.Set(ctx, 0) + + return nil + +} diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index f4926d529f75..f9ac5b2f047b 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -47,10 +47,12 @@ func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { func (man Manager) object(connid, chanid string) Object { key := connid + "/channels/" + chanid return Object{ - chanid: chanid, - channel: man.protocol.Value([]byte(key)), - state: state.NewEnum(man.protocol.Value([]byte(key + "/state"))), - nexttimeout: state.NewInteger(man.protocol.Value([]byte(key+"/timeout")), state.Dec), + chanid: chanid, + channel: man.protocol.Value([]byte(key)), + /* + state: state.NewEnum(man.protocol.Value([]byte(key + "/state"))), + nexttimeout: state.NewInteger(man.protocol.Value([]byte(key+"/timeout")), state.Dec), + */ // TODO: remove length functionality from state.Indeer(will be handled manually) seqsend: state.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), @@ -62,10 +64,12 @@ func (man Manager) object(connid, chanid string) Object { func (man CounterpartyManager) object(connid, chanid string) CounterObject { key := connid + "/channels/" + chanid return CounterObject{ - chanid: chanid, - channel: man.protocol.Value([]byte(key)), - state: commitment.NewEnum(man.protocol.Value([]byte(key + "/state"))), - nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(key+"/timeout")), state.Dec), + chanid: chanid, + channel: man.protocol.Value([]byte(key)), + /* + state: commitment.NewEnum(man.protocol.Value([]byte(key + "/state"))), + nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(key+"/timeout")), state.Dec), + */ seqsend: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), seqrecv: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), state.Dec), From 9b5b38e9cf400b87fe0306ad74010d4c578bc11f Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 16:23:25 +0200 Subject: [PATCH 134/182] in progress --- x/ibc/04-channel/handshake.go | 89 +++++++++++++++-------------------- x/ibc/04-channel/manager.go | 18 +++---- x/ibc/04-channel/types.go | 11 ----- 3 files changed, 45 insertions(+), 73 deletions(-) diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index d08a3209deca..d90846727fbb 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -1,4 +1,4 @@ -package connection +package channel import ( "errors" @@ -20,11 +20,6 @@ const ( Closed ) -type Handshake struct { - Counterparty string - CounterpartyClient string -} - type Handshaker struct { man Manager @@ -54,7 +49,6 @@ type HandshakeObject struct { Object state state.Enum - handshake state.Value // type Handshake nextTimeout state.Integer counterparty CounterHandshakeObject @@ -64,52 +58,51 @@ type CounterHandshakeObject struct { CounterObject state commitment.Enum - handshake commitment.Value nextTimeout commitment.Integer } // CONTRACT: client and remote must be filled by the caller func (man Handshaker) object(parent Object) HandshakeObject { + prefix := parent.connection.ID() + "/channels/" + parent.chanid + return HandshakeObject{ Object: parent, - state: state.NewEnum(man.man.protocol.Value([]byte(parent.id + "/state"))), - handshake: man.man.protocol.Value([]byte(parent.id + "/handshake")), - nextTimeout: state.NewInteger(man.man.protocol.Value([]byte(parent.id+"/timeout")), state.Dec), + state: state.NewEnum(man.man.protocol.Value([]byte(prefix + "/state"))), + nextTimeout: state.NewInteger(man.man.protocol.Value([]byte(prefix+"/timeout")), state.Dec), // CONTRACT: counterparty must be filled by the caller } } -func (man CounterpartyHandshaker) object(id string) CounterHandshakeObject { +func (man CounterpartyHandshaker) object(connid, chanid string) CounterHandshakeObject { + prefix := connid + "/channels/" + chanid + return CounterHandshakeObject{ - CounterObject: man.man.object(id), + CounterObject: man.man.object(connid, chanid), - state: commitment.NewEnum(man.man.protocol.Value([]byte(id + "/state"))), - handshake: man.man.protocol.Value([]byte(id + "/handshake")), - nextTimeout: commitment.NewInteger(man.man.protocol.Value([]byte(id+"/timeout")), state.Dec), + state: commitment.NewEnum(man.man.protocol.Value([]byte(prefix + "/state"))), + nextTimeout: commitment.NewInteger(man.man.protocol.Value([]byte(prefix+"/timeout")), state.Dec), } } -func (man Handshaker) create(ctx sdk.Context, id, clientid string, handshake Handshake) (obj HandshakeObject, err error) { - cobj, err := man.man.create(ctx, id, clientid, man.Kind()) +func (man Handshaker) create(ctx sdk.Context, connid, chanid string, channel Channel) (obj HandshakeObject, err error) { + cobj, err := man.man.create(ctx, connid, chanid, channel) if err != nil { return } obj = man.object(cobj) - obj.handshake.Set(ctx, handshake) - obj.counterparty = man.counterparty.object(handshake.Counterparty) + obj.counterparty = man.counterparty.object(obj.connection.Connection(ctx).Counterparty, channel.Counterparty) return obj, nil } -func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeObject, err error) { - cobj, err := man.man.query(ctx, id, man.Kind()) +func (man Handshaker) query(ctx sdk.Context, connid, chanid string) (obj HandshakeObject, err error) { + cobj, err := man.man.Query(ctx, connid, chanid) if err != nil { return } obj = man.object(cobj) - handshake := obj.Handshake(ctx) - obj.counterparty = man.counterparty.object(handshake.Counterparty) + obj.counterparty = man.counterparty.object(obj.connection.Connection(ctx).Counterparty, obj.Channel(ctx).Counterparty) return } @@ -117,11 +110,6 @@ func (obj HandshakeObject) State(ctx sdk.Context) byte { return obj.state.Get(ctx) } -func (obj HandshakeObject) Handshake(ctx sdk.Context) (res Handshake) { - obj.handshake.Get(ctx, &res) - return -} - func (obj HandshakeObject) Timeout(ctx sdk.Context) uint64 { return obj.nextTimeout.Get(ctx) } @@ -130,12 +118,14 @@ func (obj HandshakeObject) NextTimeout(ctx sdk.Context) uint64 { return obj.nextTimeout.Get(ctx) } +/* func (obj HandshakeObject) remove(ctx sdk.Context) { obj.Object.remove(ctx) obj.state.Delete(ctx) - obj.handshake.Delete(ctx) + obj.counterpartyClient.Delete(ctx) obj.nextTimeout.Delete(ctx) } +*/ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { if uint64(ctx.BlockHeight()) > timeoutHeight { @@ -147,12 +137,12 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { // Using proofs: none func (man Handshaker) OpenInit(ctx sdk.Context, - id, clientid string, handshake Handshake, nextTimeoutHeight uint64, + connid, chanid string, channel Channel, nextTimeoutHeight uint64, ) (HandshakeObject, error) { // man.Create() will ensure - // assert(get("connections/{identifier}") === null) and - // set("connections{identifier}", connection) - obj, err := man.create(ctx, id, clientid, handshake) + // assert(get("channels/{identifier}") === null) and + // set("channels/{identifier}", connection) + obj, err := man.create(ctx, connid, chanid, channel) if err != nil { return HandshakeObject{}, err } @@ -165,9 +155,9 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenTry(ctx sdk.Context, - id, clientid string, handshake Handshake, timeoutHeight, nextTimeoutHeight uint64, + connid, chanid string, channel Channel, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { - obj, err = man.create(ctx, id, clientid, handshake) + obj, err = man.create(ctx, connid, chanid, channel) if err != nil { return } @@ -182,15 +172,12 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.handshake.Is(ctx, Handshake{ - Counterparty: id, - CounterpartyClient: clientid, - }) { - err = errors.New("wrong counterparty") + if !obj.counterparty.channel.Is(ctx) { + err = errors.New("wrong counterparty connection") return } - if !obj.counterparty.clientid.Is(ctx, handshake.CounterpartyClient) { + if !obj.counterparty.counterpartyClient.Is(ctx, connection.Client) { err = errors.New("counterparty client not match") return } @@ -241,9 +228,9 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.handshake.Is(ctx, Handshake{ - Counterparty: obj.ID(), - CounterpartyClient: obj.Client().ID(), + if !obj.counterparty.connection.Is(ctx, Connection{ + Client: obj.Connection(ctx).Client, + Counterparty: obj.ID(), }) { err = errors.New("wrong counterparty") return @@ -254,7 +241,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.clientid.Is(ctx, obj.Handshake(ctx).CounterpartyClient) { + if !obj.counterparty.counterpartyClient.Is(ctx, obj.Connection(ctx).Client) { err = errors.New("counterparty client not match") return } @@ -273,7 +260,8 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } */ - obj.available.Set(ctx, true) + obj.sendable.Set(ctx, true) + obj.receivable.Set(ctx, true) obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) return @@ -306,7 +294,8 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint return } - obj.available.Set(ctx, true) + obj.sendable.Set(ctx, true) + obj.receivable.Set(ctx, true) obj.nextTimeout.Set(ctx, 0) return @@ -319,12 +308,12 @@ func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { switch obj.state.Get(ctx) { case Init: - if !obj.counterparty.handshake.Is(ctx, nil) { + if !obj.counterparty.connection.Is(ctx, nil) { return errors.New("counterparty connection exists") } case OpenTry: if !(obj.counterparty.state.Is(ctx, Init) || - obj.counterparty.clientid.Is(ctx, "")) /*FIXME: empty string does not work, it should be nil*/ { + obj.counterparty.connection.Is(ctx, nil)) { return errors.New("counterparty connection state not init") } // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index f9ac5b2f047b..703b9d77bfa7 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -77,7 +77,7 @@ func (man CounterpartyManager) object(connid, chanid string) CounterObject { } } -func (man Manager) Create(ctx sdk.Context, connid, chanid string, channel Channel) (obj Object, err error) { +func (man Manager) create(ctx sdk.Context, connid, chanid string, channel Channel) (obj Object, err error) { obj = man.object(connid, chanid) if obj.exists(ctx) { err = errors.New("channel already exists for the provided id") @@ -106,10 +106,6 @@ func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, er if err != nil { return } - if obj.connection.State(ctx) != connection.Open { - err = errors.New("connection exists but not opened") - return - } channel := obj.Value(ctx) counterconnid := obj.connection.Value(ctx).Counterparty @@ -200,6 +196,11 @@ func (obj Object) ChanID() string { return obj.chanid } +func (obj Object) Channel(ctx sdk.Context) (res Channel) { + obj.channel.Get(ctx, &res) + return +} + func (obj Object) Value(ctx sdk.Context) (res Channel) { obj.channel.Get(ctx, &res) return @@ -209,13 +210,6 @@ func (obj Object) exists(ctx sdk.Context) bool { return obj.channel.Exists(ctx) } -func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { - if uint64(ctx.BlockHeight()) > timeoutHeight { - return errors.New("timeout") - } - return nil -} - // TODO: ocapify callingPort func (obj Object) OpenInit(ctx sdk.Context) error { // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index 2a8922b41abc..11c73fe834d4 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -1,16 +1,5 @@ package channel -type State = byte - -const ( - Idle State = iota - Init - OpenTry - Open - CloseTry - Closed -) - /* type Packet struct { Sequence uint64 From ad8b7bf52f5b5d35ae72ac3c51e9e47432beb46a Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 16:39:22 +0200 Subject: [PATCH 135/182] in progress --- x/ibc/04-channel/handshake.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index d90846727fbb..bde8af1e7773 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -172,16 +172,15 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.channel.Is(ctx) { + if !obj.counterparty.channel.Is(ctx, Channel{ + Port: channel.CounterpartyPort, + Counterparty: chanid, + CounterpartyPort: "", // TODO + }) { err = errors.New("wrong counterparty connection") return } - if !obj.counterparty.counterpartyClient.Is(ctx, connection.Client) { - err = errors.New("counterparty client not match") - return - } - if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { err = errors.New("unexpected counterparty timeout value") return From be293beb9c3a2388f3b9625b8efc40293dc52ed9 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 17:44:32 +0200 Subject: [PATCH 136/182] implement test in progress --- x/ibc/03-connection/manager.go | 2 +- x/ibc/03-connection/tests/connection_test.go | 39 +---- x/ibc/03-connection/tests/types.go | 41 +++++ x/ibc/04-channel/cli.go | 53 ++++--- x/ibc/04-channel/codec.go | 9 ++ x/ibc/04-channel/handshake.go | 47 +++--- x/ibc/04-channel/manager.go | 133 ++++++++-------- x/ibc/04-channel/tests/channel_test.go | 57 +++++++ x/ibc/04-channel/tests/types.go | 152 ++++++++++++++++++- 9 files changed, 378 insertions(+), 155 deletions(-) create mode 100644 x/ibc/04-channel/codec.go create mode 100644 x/ibc/04-channel/tests/channel_test.go diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index ad3dd830503d..f4e4d6432c29 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -133,7 +133,7 @@ func (obj Object) Sendable(ctx sdk.Context) bool { return kinds[obj.Kind.Get(ctx)].Sendable } -func (obj Object) Receivble(ctx sdk.Context) bool { +func (obj Object) Receivable(ctx sdk.Context) bool { return kinds[obj.Kind.Get(ctx)].Receivable } diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index 665f15b3142d..62a8e52fbf85 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -25,42 +25,5 @@ func TestHandshake(t *testing.T) { registerCodec(cdc) node := NewNode(tendermint.NewMockValidators(100, 10), tendermint.NewMockValidators(100, 10), cdc) - node.Commit() - node.Counterparty.Commit() - - node.CreateClient(t) - node.Counterparty.CreateClient(t) - - // self.OpenInit - node.OpenInit(t) - header := node.Commit() - - // counterparty.OpenTry - node.Counterparty.UpdateClient(t, header) - cliobj := node.CLIObject() - _, pconn := node.QueryValue(t, cliobj.Connection) - _, pstate := node.QueryValue(t, cliobj.State) - _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) - _, pcounterclient := node.QueryValue(t, cliobj.CounterpartyClient) - // TODO: implement consensus state checking - // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) - node.Counterparty.OpenTry(t, pconn, pstate, ptimeout, pcounterclient) - header = node.Counterparty.Commit() - - // self.OpenAck - node.UpdateClient(t, header) - cliobj = node.Counterparty.CLIObject() - _, pconn = node.Counterparty.QueryValue(t, cliobj.Connection) - _, pstate = node.Counterparty.QueryValue(t, cliobj.State) - _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) - _, pcounterclient = node.Counterparty.QueryValue(t, cliobj.CounterpartyClient) - node.OpenAck(t, pconn, pstate, ptimeout, pcounterclient) - header = node.Commit() - - // counterparty.OpenConfirm - node.Counterparty.UpdateClient(t, header) - cliobj = node.CLIObject() - _, pstate = node.QueryValue(t, cliobj.State) - _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) - node.Counterparty.OpenConfirm(t, pstate, ptimeout) + node.Handshake(t) } diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 29b7b0706721..9fbd375aa4b3 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -149,3 +149,44 @@ func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { require.True(t, obj.Available.Get(ctx)) node.SetState(connection.CloseTry) } + +func (node *Node) Handshake(t *testing.T) { + node.Commit() + node.Counterparty.Commit() + + node.CreateClient(t) + node.Counterparty.CreateClient(t) + + // self.OpenInit + node.OpenInit(t) + header := node.Commit() + + // counterparty.OpenTry + node.Counterparty.UpdateClient(t, header) + cliobj := node.CLIObject() + _, pconn := node.QueryValue(t, cliobj.Connection) + _, pstate := node.QueryValue(t, cliobj.State) + _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) + _, pcounterclient := node.QueryValue(t, cliobj.CounterpartyClient) + // TODO: implement consensus state checking + // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) + node.Counterparty.OpenTry(t, pconn, pstate, ptimeout, pcounterclient) + header = node.Counterparty.Commit() + + // self.OpenAck + node.UpdateClient(t, header) + cliobj = node.Counterparty.CLIObject() + _, pconn = node.Counterparty.QueryValue(t, cliobj.Connection) + _, pstate = node.Counterparty.QueryValue(t, cliobj.State) + _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) + _, pcounterclient = node.Counterparty.QueryValue(t, cliobj.CounterpartyClient) + node.OpenAck(t, pconn, pstate, ptimeout, pcounterclient) + header = node.Commit() + + // counterparty.OpenConfirm + node.Counterparty.UpdateClient(t, header) + cliobj = node.CLIObject() + _, pstate = node.QueryValue(t, cliobj.State) + _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) + node.Counterparty.OpenConfirm(t, pstate, ptimeout) +} diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index 600c8d2bacee..bbf965808388 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -12,12 +12,11 @@ import ( type CLIObject struct { ChanID string ChannelKey []byte - StateKey []byte - TimeoutKey []byte - SeqSendKey []byte - SeqRecvKey []byte - PacketKey func(index uint64) []byte + AvailableKey []byte + SeqSendKey []byte + SeqRecvKey []byte + PacketKey func(index uint64) []byte Connection connection.CLIObject @@ -30,11 +29,10 @@ func (man Manager) CLIObject(root merkle.Root, connid, chanid string) CLIObject return CLIObject{ ChanID: chanid, ChannelKey: obj.channel.Key(), - StateKey: obj.state.Key(), - TimeoutKey: obj.nexttimeout.Key(), - SeqSendKey: obj.seqsend.Key(), - SeqRecvKey: obj.seqrecv.Key(), + AvailableKey: obj.available.Key(), + SeqSendKey: obj.seqsend.Key(), + SeqRecvKey: obj.seqrecv.Key(), PacketKey: func(index uint64) []byte { return obj.packets.Value(index).Key() }, @@ -65,16 +63,6 @@ func (obj CLIObject) Channel(ctx context.CLIContext) (res Channel, proof merkle. return } -func (obj CLIObject) State(ctx context.CLIContext) (res State, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.StateKey, &res) - return -} - -func (obj CLIObject) Timeout(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.TimeoutKey, &res) - return -} - func (obj CLIObject) SeqSend(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.SeqSendKey, &res) return @@ -89,3 +77,30 @@ func (obj CLIObject) Packet(ctx context.CLIContext, index uint64) (res Packet, p proof, err = obj.query(ctx, obj.PacketKey(index), &res) return } + +type CLIHandshakeObject struct { + CLIObject + + StateKey []byte + TimeoutKey []byte +} + +func (man Handshaker) CLIObject(root merkle.Root, connid, chanid string) CLIHandshakeObject { + obj := man.object(man.man.object(connid, chanid)) + return CLIHandshakeObject{ + CLIObject: man.man.CLIObject(root, connid, chanid), + + StateKey: obj.state.Key(), + TimeoutKey: obj.nextTimeout.Key(), + } +} + +func (obj CLIHandshakeObject) State(ctx context.CLIContext) (res State, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.StateKey, &res) + return +} + +func (obj CLIHandshakeObject) Timeout(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.TimeoutKey, &res) + return +} diff --git a/x/ibc/04-channel/codec.go b/x/ibc/04-channel/codec.go new file mode 100644 index 000000000000..4da636c4edc7 --- /dev/null +++ b/x/ibc/04-channel/codec.go @@ -0,0 +1,9 @@ +package channel + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterInterface((*Packet)(nil), nil) +} diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index bde8af1e7773..27fc54cb7d1e 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -63,7 +63,7 @@ type CounterHandshakeObject struct { // CONTRACT: client and remote must be filled by the caller func (man Handshaker) object(parent Object) HandshakeObject { - prefix := parent.connection.ID() + "/channels/" + parent.chanid + prefix := parent.connid + "/channels/" + parent.chanid return HandshakeObject{ Object: parent, @@ -92,17 +92,23 @@ func (man Handshaker) create(ctx sdk.Context, connid, chanid string, channel Cha return } obj = man.object(cobj) - obj.counterparty = man.counterparty.object(obj.connection.Connection(ctx).Counterparty, channel.Counterparty) + counterconnid := obj.connection.Connection(ctx).Counterparty + obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) + obj.counterparty.connection = man.counterparty.man.connection.Object(counterconnid) + return obj, nil } func (man Handshaker) query(ctx sdk.Context, connid, chanid string) (obj HandshakeObject, err error) { - cobj, err := man.man.Query(ctx, connid, chanid) + cobj, err := man.man.query(ctx, connid, chanid) if err != nil { return } obj = man.object(cobj) - obj.counterparty = man.counterparty.object(obj.connection.Connection(ctx).Counterparty, obj.Channel(ctx).Counterparty) + channel := obj.Channel(ctx) + counterconnid := obj.connection.Connection(ctx).Counterparty + obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) + obj.counterparty.connection = man.counterparty.man.connection.Object(counterconnid) return } @@ -210,9 +216,9 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenAck(ctx sdk.Context, - id string /*expheight uint64, */, timeoutHeight, nextTimeoutHeight uint64, + connid, chanid string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { - obj, err = man.query(ctx, id) + obj, err = man.query(ctx, connid, chanid) if err != nil { return } @@ -227,9 +233,11 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.connection.Is(ctx, Connection{ - Client: obj.Connection(ctx).Client, - Counterparty: obj.ID(), + channel := obj.Channel(ctx) + if !obj.counterparty.channel.Is(ctx, Channel{ + Port: channel.CounterpartyPort, + Counterparty: chanid, + CounterpartyPort: "", // TODO }) { err = errors.New("wrong counterparty") return @@ -240,11 +248,6 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.counterpartyClient.Is(ctx, obj.Connection(ctx).Client) { - err = errors.New("counterparty client not match") - return - } - if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { err = errors.New("unexpected counterparty timeout value") return @@ -259,16 +262,15 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } */ - obj.sendable.Set(ctx, true) - obj.receivable.Set(ctx, true) obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) + obj.available.Set(ctx, true) return } // Using proofs: counterparty.{connection,state, nextTimeout} -func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint64) (obj HandshakeObject, err error) { - obj, err = man.query(ctx, id) +func (man Handshaker) OpenConfirm(ctx sdk.Context, connid, chanid string, timeoutHeight uint64) (obj HandshakeObject, err error) { + obj, err = man.query(ctx, connid, chanid) if err != nil { return } @@ -293,15 +295,16 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, id string, timeoutHeight uint return } - obj.sendable.Set(ctx, true) - obj.receivable.Set(ctx, true) + obj.available.Set(ctx, true) obj.nextTimeout.Set(ctx, 0) return } +// TODO +/* func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + if !(uint64(obj.connection.Client().ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } @@ -327,6 +330,7 @@ func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { return nil } + func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error { if !obj.state.Transit(ctx, Open, CloseTry) { return errors.New("closeinit on non-open connection") @@ -406,3 +410,4 @@ func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { return nil } +*/ diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 703b9d77bfa7..a1595608463b 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -48,13 +48,11 @@ func (man Manager) object(connid, chanid string) Object { key := connid + "/channels/" + chanid return Object{ chanid: chanid, + connid: connid, channel: man.protocol.Value([]byte(key)), - /* - state: state.NewEnum(man.protocol.Value([]byte(key + "/state"))), - nexttimeout: state.NewInteger(man.protocol.Value([]byte(key+"/timeout")), state.Dec), - */ - // TODO: remove length functionality from state.Indeer(will be handled manually) + available: state.NewBoolean(man.protocol.Value([]byte(key + "/available"))), + seqsend: state.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), seqrecv: state.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), state.Dec), packets: state.NewIndexer(man.protocol.Prefix([]byte(key+"/packets/")), state.Dec), @@ -65,11 +63,10 @@ func (man CounterpartyManager) object(connid, chanid string) CounterObject { key := connid + "/channels/" + chanid return CounterObject{ chanid: chanid, + connid: connid, channel: man.protocol.Value([]byte(key)), - /* - state: commitment.NewEnum(man.protocol.Value([]byte(key + "/state"))), - nexttimeout: commitment.NewInteger(man.protocol.Value([]byte(key+"/timeout")), state.Dec), - */ + + available: commitment.NewBoolean(man.protocol.Value([]byte(key + "/available"))), seqsend: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), seqrecv: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), state.Dec), @@ -87,16 +84,17 @@ func (man Manager) create(ctx sdk.Context, connid, chanid string, channel Channe if err != nil { return } - counterconnid := obj.connection.Value(ctx).Counterparty - obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) - obj.counterparty.connection = man.counterparty.connection.Query(counterconnid) - obj.channel.Set(ctx, channel) + counterconnid := obj.connection.Connection(ctx).Counterparty + obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) + obj.counterparty.connection = man.counterparty.connection.Object(counterconnid) + return } -func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, err error) { +// Does not check availability +func (man Manager) query(ctx sdk.Context, connid, chanid string) (obj Object, err error) { obj = man.object(connid, chanid) if !obj.exists(ctx) { err = errors.New("channel not exists for the provided id") @@ -107,18 +105,29 @@ func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, er return } - channel := obj.Value(ctx) - counterconnid := obj.connection.Value(ctx).Counterparty - obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) - obj.counterparty.connection = man.counterparty.connection.Query(counterconnid) + counterconnid := obj.connection.Connection(ctx).Counterparty + obj.counterparty = man.counterparty.object(counterconnid, obj.Channel(ctx).Counterparty) + obj.counterparty.connection = man.counterparty.connection.Object(counterconnid) return + } +func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, err error) { + obj, err = man.query(ctx, connid, chanid) + if !obj.Available(ctx) { + err = errors.New("channel not available") + return + } + return +} + +// TODO +/* func (man Manager) Port(port string, chanid func(string) bool) PortManager { return PortManager{ man: man, - port: module, + port: le, chanid: chanid, } } @@ -158,37 +167,37 @@ func (man PortManager) Query(ctx sdk.Context, connid, chanid string) (Object, er return obj, nil } +*/ type Object struct { chanid string + connid string protocol state.Mapping channel state.Value - /* - state state.Enum - nexttimeout state.Integer - */ seqsend state.Integer seqrecv state.Integer packets state.Indexer + available state.Boolean + connection connection.Object + + counterparty CounterObject } type CounterObject struct { chanid string + connid string channel commitment.Value - /* - state commitment.Enum - nexttimeout commitment.Integer - */ - seqsend commitment.Integer seqrecv commitment.Integer packets commitment.Indexer + available commitment.Boolean + connection connection.CounterObject } @@ -206,54 +215,42 @@ func (obj Object) Value(ctx sdk.Context) (res Channel) { return } -func (obj Object) exists(ctx sdk.Context) bool { - return obj.channel.Exists(ctx) +func (obj Object) Available(ctx sdk.Context) bool { + return obj.available.Get(ctx) } -// TODO: ocapify callingPort -func (obj Object) OpenInit(ctx sdk.Context) error { - // CONTRACT: OpenInit() should be called after man.Create(), not man.Query(), - // which will ensure - // assert(get() === null) and - // set() and - // connection.state == open - - // getCallingPort() === channel.portIdentifier is ensured by PortManager - - if !obj.state.Transit(ctx, Idle, Init) { - return errors.New("init on non-idle channel") - } +func (obj Object) Sendable(ctx sdk.Context) bool { + // TODO: sendable/receivable should be also defined for channels + return obj.connection.Sendable(ctx) +} - obj.seqsend.Set(ctx, 0) - obj.seqrecv.Set(ctx, 0) +func (obj Object) Receivable(ctx sdk.Context) bool { + return obj.connection.Receivable(ctx) +} - return nil +func (obj Object) SeqSend(ctx sdk.Context) uint64 { + return obj.seqsend.Get(ctx) } -/* -func (obj Object) OpenTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { - if !obj.state.Transit(ctx, Idle, OpenTry) { - return errors.New("opentry on non-idle channel") - } +func (obj Object) SeqRecv(ctx sdk.Context) uint64 { + return obj.seqrecv.Get(ctx) +} - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } +func (obj Object) Packet(ctx sdk.Context, index uint64) (res Packet) { + obj.packets.Value(index).Get(ctx, &res) + return +} - // XXX +func (obj Object) exists(ctx sdk.Context) bool { + return obj.channel.Exists(ctx) } -*/ -func (obj Object) Send(ctx sdk.Context, packet Packet) error { - if obj.state.Get(ctx) != Open { - return errors.New("send on non-open channel") - } - if obj.connection.State(ctx) != Open { - return errors.New("send on non-open connection") +func (obj Object) Send(ctx sdk.Context, packet Packet) error { + if !obj.Sendable(ctx) { + return errors.New("cannot send packets on this channel") } - if uint64(obj.connection.Client(ctx).GetHeight()) >= packet.Timeout() { + if uint64(obj.connection.Client().ConsensusState(ctx).GetHeight()) >= packet.Timeout() { return errors.New("timeout height higher than the latest known") } @@ -263,12 +260,8 @@ func (obj Object) Send(ctx sdk.Context, packet Packet) error { } func (obj Object) Receive(ctx sdk.Context, packet Packet) error { - if obj.state.Get(ctx) != Open { - return errors.New("send on non-open channel") - } - - if obj.connection.State(ctx) != Open { - return errors.New("send on non-open connection") + if !obj.Receivable(ctx) { + return errors.New("cannot receive packets on this channel") } err := assertTimeout(ctx, packet.Timeout()) diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go new file mode 100644 index 000000000000..c145dcaf4f71 --- /dev/null +++ b/x/ibc/04-channel/tests/channel_test.go @@ -0,0 +1,57 @@ +package channel + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + tmclient "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +func registerCodec(cdc *codec.Codec) { + client.RegisterCodec(cdc) + tmclient.RegisterCodec(cdc) + commitment.RegisterCodec(cdc) + merkle.RegisterCodec(cdc) + codec.RegisterCrypto(cdc) + channel.RegisterCodec(cdc) + cdc.RegisterConcrete(MyPacket{}, "test/MyPacket", nil) +} + +func TestHandshake(t *testing.T) { + cdc := codec.New() + registerCodec(cdc) + + node := NewNode(tendermint.NewMockValidators(100, 10), tendermint.NewMockValidators(100, 10), cdc) + + node.Handshake(t) +} + +type MyPacket struct { + Message string +} + +func (packet MyPacket) Commit() []byte { + return []byte(packet.Message) +} + +func (packet MyPacket) Timeout() uint64 { + return 100 // TODO +} + +func TestPacket(t *testing.T) { + cdc := codec.New() + registerCodec(cdc) + + node := NewNode(tendermint.NewMockValidators(100, 10), tendermint.NewMockValidators(100, 10), cdc) + + node.Handshake(t) + + node.Send(t, MyPacket{"ping"}) + node.Counterparty.Receive(t, MyPacket{"ping"}) +} diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index cb2e94bfc780..24873f7df738 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -1,33 +1,173 @@ package channel import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/tests" + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type Node struct { *connection.Node Counterparty *Node + + Channel channel.Channel + + Cdc *codec.Codec } func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { - conn := connection.NewNode(self, counter, cdc) - res := &Node{ - Node: conn, + Node: connection.NewNode(self, counter, cdc), // TODO: test with key prefix + + Cdc: cdc, } res.Counterparty = &Node{ - Node: conn.Counterparty, + Node: res.Node.Counterparty, Counterparty: res, + + Cdc: cdc, + } + + res.Channel = channel.Channel{ + Port: "", // TODO + Counterparty: res.Counterparty.Name, + CounterpartyPort: "", //TODO + } + + res.Counterparty.Channel = channel.Channel{ + Port: "", // TODO + Counterparty: res.Name, + CounterpartyPort: "", // TODO } return res } -func OpenInit(t *testing.T) { - ctx, man := node.Handshaker(t) +func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, channel.Handshaker) { + ctx := node.Context() + store, err := commitment.NewStore(node.Counterparty.Root, proofs) + require.NoError(t, err) + ctx = commitment.WithStore(ctx, store) + man := node.Manager() + return ctx, channel.NewHandshaker(man) +} + +func (node *Node) CLIObject() channel.CLIHandshakeObject { + man := node.Manager() + return channel.NewHandshaker(man).CLIObject(node.Root, node.Name, node.Name) +} + +func base(cdc *codec.Codec, key sdk.StoreKey) (state.Base, state.Base) { + protocol := state.NewBase(cdc, key, []byte("protocol")) + free := state.NewBase(cdc, key, []byte("free")) + return protocol, free +} + +func (node *Node) Manager() channel.Manager { + protocol, _ := base(node.Cdc, node.Key) + _, connman := node.Node.Manager() + return channel.NewManager(protocol, connman) +} + +func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { + ctx, man := node.Handshaker(t, proofs) + obj, err := man.OpenInit(ctx, node.Name, node.Name, node.Channel, 100) // TODO: test timeout + require.NoError(t, err) + require.Equal(t, channel.Init, obj.State(ctx)) + require.Equal(t, node.Channel, obj.Channel(ctx)) + require.False(t, obj.Available(ctx)) +} + +func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { + ctx, man := node.Handshaker(t, proofs) + obj, err := man.OpenTry(ctx, node.Name, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, channel.OpenTry, obj.State(ctx)) + require.Equal(t, node.Channel, obj.Channel(ctx)) + require.False(t, obj.Available(ctx)) + node.SetState(channel.OpenTry) +} + +func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { + ctx, man := node.Handshaker(t, proofs) + obj, err := man.OpenAck(ctx, node.Name, node.Name, 100 /*TODO*/, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, channel.Open, obj.State(ctx)) + require.Equal(t, node.Channel, obj.Channel(ctx)) + require.True(t, obj.Available(ctx)) + node.SetState(channel.Open) +} + +func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { + ctx, man := node.Handshaker(t, proofs) + obj, err := man.OpenConfirm(ctx, node.Name, node.Name, 100 /*TODO*/) + require.NoError(t, err) + require.Equal(t, channel.Open, obj.State(ctx)) + require.Equal(t, node.Channel, obj.Channel(ctx)) + require.True(t, obj.Available(ctx)) + node.SetState(channel.CloseTry) +} + +func (node *Node) Handshake(t *testing.T) { + node.Node.Handshake(t) + + // self.OpenInit + node.OpenInit(t) + header := node.Commit() + + // counterparty.OpenTry + node.Counterparty.UpdateClient(t, header) + cliobj := node.CLIObject() + _, pchan := node.Query(t, cliobj.ChannelKey) + _, pstate := node.Query(t, cliobj.StateKey) + _, ptimeout := node.Query(t, cliobj.TimeoutKey) + node.Counterparty.OpenTry(t, pchan, pstate, ptimeout) + header = node.Counterparty.Commit() + + // self.OpenAck + node.UpdateClient(t, header) + cliobj = node.Counterparty.CLIObject() + _, pchan = node.Counterparty.Query(t, cliobj.ChannelKey) + _, pstate = node.Counterparty.Query(t, cliobj.StateKey) + _, ptimeout = node.Counterparty.Query(t, cliobj.TimeoutKey) + node.OpenAck(t, pchan, pstate, ptimeout) + header = node.Commit() + + // counterparty.OpenConfirm + node.Counterparty.UpdateClient(t, header) + cliobj = node.CLIObject() + _, pstate = node.Query(t, cliobj.StateKey) + _, ptimeout = node.Query(t, cliobj.TimeoutKey) + node.Counterparty.OpenConfirm(t, pstate, ptimeout) +} + +func (node *Node) Send(t *testing.T, packet channel.Packet) { + ctx, man := node.Context(), node.Manager() + obj, err := man.Query(ctx, node.Name, node.Name) + require.NoError(t, err) + seq := obj.SeqSend(ctx) + err = obj.Send(ctx, packet) + require.NoError(t, err) + require.Equal(t, seq+1, obj.SeqSend(ctx)) + require.Equal(t, packet, obj.Packet(ctx, seq+1)) +} +func (node *Node) Receive(t *testing.T, packet channel.Packet) { + ctx, man := node.Context(), node.Manager() + obj, err := man.Query(ctx, node.Name, node.Name) + require.NoError(t, err) + seq := obj.SeqRecv(ctx) + err = obj.Receive(ctx, packet) + require.NoError(t, err) + require.Equal(t, seq+1, obj.SeqRecv(ctx)) } From bf1d7f7817f2d952eca03db1b5d58703aa7dbb11 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 18:09:26 +0200 Subject: [PATCH 137/182] send/receive test working --- store/state/indexer.go | 4 ++++ store/state/mapping.go | 4 ++++ x/ibc/04-channel/cli.go | 14 +++++++------- x/ibc/04-channel/manager.go | 11 +++++------ x/ibc/04-channel/tests/channel_test.go | 7 ++++++- x/ibc/04-channel/tests/types.go | 10 +++++----- x/ibc/05-port/manager.go | 14 -------------- 7 files changed, 31 insertions(+), 33 deletions(-) delete mode 100644 x/ibc/05-port/manager.go diff --git a/store/state/indexer.go b/store/state/indexer.go index 6b837c2021a3..666d31b45667 100644 --- a/store/state/indexer.go +++ b/store/state/indexer.go @@ -94,6 +94,10 @@ func (ix Indexer) Set(ctx Context, index uint64, o interface{}) { ix.Value(index).Set(ctx, o) } +func (ix Indexer) SetRaw(ctx Context, index uint64, value []byte) { + ix.Value(index).SetRaw(ctx, value) +} + // Has() returns true if the stored value is not nil func (ix Indexer) Has(ctx Context, index uint64) bool { return ix.Value(index).Exists(ctx) diff --git a/store/state/mapping.go b/store/state/mapping.go index 7bc120ffaed7..8cebbf97c1d7 100644 --- a/store/state/mapping.go +++ b/store/state/mapping.go @@ -49,6 +49,10 @@ func (m Mapping) Set(ctx Context, key []byte, o interface{}) { m.Value(key).Set(ctx, o) } +func (m Mapping) SetRaw(ctx Context, key []byte, value []byte) { + m.Value(key).SetRaw(ctx, value) +} + // Has() returns true if the stored value is not nil func (m Mapping) Has(ctx Context, key []byte) bool { return m.Value(key).Exists(ctx) diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index bbf965808388..51a6c8d526e0 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -13,10 +13,10 @@ type CLIObject struct { ChanID string ChannelKey []byte - AvailableKey []byte - SeqSendKey []byte - SeqRecvKey []byte - PacketKey func(index uint64) []byte + AvailableKey []byte + SeqSendKey []byte + SeqRecvKey []byte + PacketCommitKey func(index uint64) []byte Connection connection.CLIObject @@ -33,7 +33,7 @@ func (man Manager) CLIObject(root merkle.Root, connid, chanid string) CLIObject AvailableKey: obj.available.Key(), SeqSendKey: obj.seqsend.Key(), SeqRecvKey: obj.seqrecv.Key(), - PacketKey: func(index uint64) []byte { + PacketCommitKey: func(index uint64) []byte { return obj.packets.Value(index).Key() }, @@ -73,8 +73,8 @@ func (obj CLIObject) SeqRecv(ctx context.CLIContext) (res uint64, proof merkle.P return } -func (obj CLIObject) Packet(ctx context.CLIContext, index uint64) (res Packet, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.PacketKey(index), &res) +func (obj CLIObject) PacketCommit(ctx context.CLIContext, index uint64) (res Packet, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.PacketCommitKey(index), &res) return } diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index a1595608463b..baffac7fabf5 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -70,7 +70,7 @@ func (man CounterpartyManager) object(connid, chanid string) CounterObject { seqsend: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), seqrecv: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), state.Dec), - packets: commitment.NewIndexer(man.protocol.Prefix([]byte(key+"/packets")), state.Dec), + packets: commitment.NewIndexer(man.protocol.Prefix([]byte(key+"/packets/")), state.Dec), } } @@ -236,9 +236,8 @@ func (obj Object) SeqRecv(ctx sdk.Context) uint64 { return obj.seqrecv.Get(ctx) } -func (obj Object) Packet(ctx sdk.Context, index uint64) (res Packet) { - obj.packets.Value(index).Get(ctx, &res) - return +func (obj Object) PacketCommit(ctx sdk.Context, index uint64) []byte { + return obj.packets.Value(index).GetRaw(ctx) } func (obj Object) exists(ctx sdk.Context) bool { @@ -254,7 +253,7 @@ func (obj Object) Send(ctx sdk.Context, packet Packet) error { return errors.New("timeout height higher than the latest known") } - obj.packets.Set(ctx, obj.seqsend.Incr(ctx), packet) + obj.packets.SetRaw(ctx, obj.seqsend.Incr(ctx), packet.Commit()) return nil } @@ -270,7 +269,7 @@ func (obj Object) Receive(ctx sdk.Context, packet Packet) error { } // XXX: increment should happen before verification, reflect on the spec - if !obj.counterparty.packets.Value(obj.seqrecv.Incr(ctx)).Is(ctx, packet.Commit()) { + if !obj.counterparty.packets.Value(obj.seqrecv.Incr(ctx)).IsRaw(ctx, packet.Commit()) { return errors.New("verification failed") } diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go index c145dcaf4f71..db2aac451268 100644 --- a/x/ibc/04-channel/tests/channel_test.go +++ b/x/ibc/04-channel/tests/channel_test.go @@ -53,5 +53,10 @@ func TestPacket(t *testing.T) { node.Handshake(t) node.Send(t, MyPacket{"ping"}) - node.Counterparty.Receive(t, MyPacket{"ping"}) + header := node.Commit() + + node.Counterparty.UpdateClient(t, header) + cliobj := node.CLIObject() + _, ppacket := node.Query(t, cliobj.PacketCommitKey(1)) + node.Counterparty.Receive(t, MyPacket{"ping"}, ppacket) } diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 24873f7df738..56021467d4db 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -54,7 +54,7 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { } func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, channel.Handshaker) { - ctx := node.Context() + ctx := node.Context(t, proofs) store, err := commitment.NewStore(node.Counterparty.Root, proofs) require.NoError(t, err) ctx = commitment.WithStore(ctx, store) @@ -152,18 +152,18 @@ func (node *Node) Handshake(t *testing.T) { } func (node *Node) Send(t *testing.T, packet channel.Packet) { - ctx, man := node.Context(), node.Manager() + ctx, man := node.Context(t, nil), node.Manager() obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) seq := obj.SeqSend(ctx) err = obj.Send(ctx, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqSend(ctx)) - require.Equal(t, packet, obj.Packet(ctx, seq+1)) + require.Equal(t, packet.Commit(), obj.PacketCommit(ctx, seq+1)) } -func (node *Node) Receive(t *testing.T, packet channel.Packet) { - ctx, man := node.Context(), node.Manager() +func (node *Node) Receive(t *testing.T, packet channel.Packet, proofs ...commitment.Proof) { + ctx, man := node.Context(t, proofs), node.Manager() obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) seq := obj.SeqRecv(ctx) diff --git a/x/ibc/05-port/manager.go b/x/ibc/05-port/manager.go deleted file mode 100644 index 782bf7202763..000000000000 --- a/x/ibc/05-port/manager.go +++ /dev/null @@ -1,14 +0,0 @@ -package port - -import ( - "github.com/cosmos/cosmos-sdk/store/state" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type Manager struct { - protocol state.Mapping -} - -func NewManager(protocol state.Base) Manager { - return Manager -} From 705b1099de0f2c21c83a208d8731bfe7d3413aab Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 7 Jul 2019 19:05:41 +0200 Subject: [PATCH 138/182] fix most of lint --- x/ibc/04-channel/handshake.go | 10 +++++----- x/ibc/04-channel/manager.go | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index 27fc54cb7d1e..eb38c63f5475 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -187,7 +187,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } @@ -248,7 +248,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.nextTimeout.Is(ctx, uint64(timeoutHeight)) { + if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } @@ -262,7 +262,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } */ - obj.nextTimeout.Set(ctx, uint64(nextTimeoutHeight)) + obj.nextTimeout.Set(ctx, nextTimeoutHeight) obj.available.Set(ctx, true) return @@ -304,7 +304,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, connid, chanid string, timeou // TODO /* func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { - if !(uint64(obj.connection.Client().ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + if !(obj.connection.Client().ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } @@ -388,7 +388,7 @@ func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error } func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { - if !(uint64(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + if !(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index baffac7fabf5..8d8287a1f3d8 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -173,8 +173,7 @@ type Object struct { chanid string connid string - protocol state.Mapping - channel state.Value + channel state.Value seqsend state.Integer seqrecv state.Integer @@ -249,7 +248,7 @@ func (obj Object) Send(ctx sdk.Context, packet Packet) error { return errors.New("cannot send packets on this channel") } - if uint64(obj.connection.Client().ConsensusState(ctx).GetHeight()) >= packet.Timeout() { + if obj.connection.Client().ConsensusState(ctx).GetHeight() >= packet.Timeout() { return errors.New("timeout height higher than the latest known") } From 72090e7e1962b0bfa86228e43cd20ec721f8f869 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 02:41:21 +0900 Subject: [PATCH 139/182] finalize rebase on merkle path / root separatio --- x/ibc/04-channel/cli.go | 14 +++++++------- x/ibc/04-channel/tests/types.go | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index 51a6c8d526e0..52e1780ec237 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -20,11 +20,11 @@ type CLIObject struct { Connection connection.CLIObject - Root merkle.Root + Path merkle.Path Cdc *codec.Codec } -func (man Manager) CLIObject(root merkle.Root, connid, chanid string) CLIObject { +func (man Manager) CLIObject(path merkle.Path, chanid, connid, clientid string) CLIObject { obj := man.object(connid, chanid) return CLIObject{ ChanID: chanid, @@ -37,15 +37,15 @@ func (man Manager) CLIObject(root merkle.Root, connid, chanid string) CLIObject return obj.packets.Value(index).Key() }, - Connection: man.connection.CLIObject(root, connid), + Connection: man.connection.CLIObject(path, connid, clientid), - Root: root, + Path: path, Cdc: obj.channel.Cdc(), } } func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { - resp, err := ctx.QueryABCI(obj.Root.RequestQuery(key)) + resp, err := ctx.QueryABCI(obj.Path.RequestQuery(key)) if err != nil { return merkle.Proof{}, err } @@ -85,10 +85,10 @@ type CLIHandshakeObject struct { TimeoutKey []byte } -func (man Handshaker) CLIObject(root merkle.Root, connid, chanid string) CLIHandshakeObject { +func (man Handshaker) CLIObject(path merkle.Path, chanid, connid, clientid string) CLIHandshakeObject { obj := man.object(man.man.object(connid, chanid)) return CLIHandshakeObject{ - CLIObject: man.man.CLIObject(root, connid, chanid), + CLIObject: man.man.CLIObject(path, chanid, connid, clientid), StateKey: obj.state.Key(), TimeoutKey: obj.nextTimeout.Key(), diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 56021467d4db..fc62aa251510 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -55,7 +55,7 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, channel.Handshaker) { ctx := node.Context(t, proofs) - store, err := commitment.NewStore(node.Counterparty.Root, proofs) + store, err := commitment.NewStore(node.Counterparty.Root(), node.Counterparty.Path, proofs) require.NoError(t, err) ctx = commitment.WithStore(ctx, store) man := node.Manager() @@ -64,7 +64,7 @@ func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Conte func (node *Node) CLIObject() channel.CLIHandshakeObject { man := node.Manager() - return channel.NewHandshaker(man).CLIObject(node.Root, node.Name, node.Name) + return channel.NewHandshaker(man).CLIObject(node.Path, node.Name, node.Name, node.Name) } func base(cdc *codec.Codec, key sdk.StoreKey) (state.Base, state.Base) { From 5f57caa04e68fae1608811d1d493146c12c485a7 Mon Sep 17 00:00:00 2001 From: mossid Date: Sun, 14 Jul 2019 05:03:31 +0900 Subject: [PATCH 140/182] manually pass proofs --- x/ibc/04-channel/handshake.go | 23 +++++++++++++++++++++-- x/ibc/04-channel/manager.go | 13 +++++++++++-- x/ibc/04-channel/tests/types.go | 14 +++++++------- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index eb38c63f5475..2889aa8183fc 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -159,8 +159,9 @@ func (man Handshaker) OpenInit(ctx sdk.Context, return obj, nil } -// Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} +// Using proofs: counterparty.{channel,state,nextTimeout} func (man Handshaker) OpenTry(ctx sdk.Context, + pchannel, pstate, ptimeout commitment.Proof, connid, chanid string, channel Channel, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.create(ctx, connid, chanid, channel) @@ -168,6 +169,11 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } + ctx, err = obj.Context(ctx, pchannel, pstate, ptimeout) + if err != nil { + return + } + err = assertTimeout(ctx, timeoutHeight) if err != nil { return @@ -216,6 +222,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenAck(ctx sdk.Context, + pchannel, pstate, ptimeout commitment.Proof, connid, chanid string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, connid, chanid) @@ -223,6 +230,11 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } + ctx, err = obj.Context(ctx, pchannel, pstate, ptimeout) + if err != nil { + return + } + if !obj.state.Transit(ctx, Init, Open) { err = errors.New("ack on non-init connection") return @@ -269,12 +281,19 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } // Using proofs: counterparty.{connection,state, nextTimeout} -func (man Handshaker) OpenConfirm(ctx sdk.Context, connid, chanid string, timeoutHeight uint64) (obj HandshakeObject, err error) { +func (man Handshaker) OpenConfirm(ctx sdk.Context, + pstate, ptimeout commitment.Proof, + connid, chanid string, timeoutHeight uint64) (obj HandshakeObject, err error) { obj, err = man.query(ctx, connid, chanid) if err != nil { return } + ctx, err = obj.Context(ctx, pstate, ptimeout) + if err != nil { + return + } + if !obj.state.Transit(ctx, OpenTry, Open) { err = errors.New("confirm on non-try connection") return diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 8d8287a1f3d8..fe095ec8dfe4 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -200,6 +200,10 @@ type CounterObject struct { connection connection.CounterObject } +func (obj Object) Context(ctx sdk.Context, proofs ...commitment.Proof) (sdk.Context, error) { + return obj.connection.Context(ctx, nil, proofs...) +} + func (obj Object) ChanID() string { return obj.chanid } @@ -257,12 +261,17 @@ func (obj Object) Send(ctx sdk.Context, packet Packet) error { return nil } -func (obj Object) Receive(ctx sdk.Context, packet Packet) error { +func (obj Object) Receive(ctx sdk.Context, ppacket commitment.Proof, packet Packet) error { if !obj.Receivable(ctx) { return errors.New("cannot receive packets on this channel") } - err := assertTimeout(ctx, packet.Timeout()) + ctx, err := obj.Context(ctx, ppacket) + if err != nil { + return err + } + + err = assertTimeout(ctx, packet.Timeout()) if err != nil { return err } diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index fc62aa251510..80f94e7e248c 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -54,7 +54,7 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { } func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, channel.Handshaker) { - ctx := node.Context(t, proofs) + ctx := node.Context() store, err := commitment.NewStore(node.Counterparty.Root(), node.Counterparty.Path, proofs) require.NoError(t, err) ctx = commitment.WithStore(ctx, store) @@ -90,7 +90,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, node.Name, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs[0], proofs[1], proofs[2], node.Name, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.OpenTry, obj.State(ctx)) require.Equal(t, node.Channel, obj.Channel(ctx)) @@ -100,7 +100,7 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, node.Name, node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs[0], proofs[1], proofs[2], node.Name, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.Open, obj.State(ctx)) require.Equal(t, node.Channel, obj.Channel(ctx)) @@ -110,7 +110,7 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, node.Name, node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs[0], proofs[1], node.Name, node.Name, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.Open, obj.State(ctx)) require.Equal(t, node.Channel, obj.Channel(ctx)) @@ -152,7 +152,7 @@ func (node *Node) Handshake(t *testing.T) { } func (node *Node) Send(t *testing.T, packet channel.Packet) { - ctx, man := node.Context(t, nil), node.Manager() + ctx, man := node.Context(), node.Manager() obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) seq := obj.SeqSend(ctx) @@ -163,11 +163,11 @@ func (node *Node) Send(t *testing.T, packet channel.Packet) { } func (node *Node) Receive(t *testing.T, packet channel.Packet, proofs ...commitment.Proof) { - ctx, man := node.Context(t, proofs), node.Manager() + ctx, man := node.Context(), node.Manager() obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) seq := obj.SeqRecv(ctx) - err = obj.Receive(ctx, packet) + err = obj.Receive(ctx, proofs[0], packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqRecv(ctx)) } From b01c3f963612c6567295691395cf17c3f250c41f Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 18 Jul 2019 02:43:47 +0900 Subject: [PATCH 141/182] add msgs/handler in progress --- x/ibc/04-channel/cli.go | 8 +- x/ibc/04-channel/client/cli/query.go | 101 +++++++++++ x/ibc/04-channel/client/cli/tx.go | 221 +++++++++++++++++++++++++ x/ibc/04-channel/client/utils/types.go | 59 +++++++ x/ibc/04-channel/handler.go | 37 +++++ x/ibc/04-channel/handshake.go | 12 +- x/ibc/04-channel/manager.go | 8 +- x/ibc/04-channel/msgs.go | 132 +++++++++++++++ 8 files changed, 564 insertions(+), 14 deletions(-) create mode 100644 x/ibc/04-channel/client/cli/query.go create mode 100644 x/ibc/04-channel/client/cli/tx.go create mode 100644 x/ibc/04-channel/client/utils/types.go create mode 100644 x/ibc/04-channel/handler.go create mode 100644 x/ibc/04-channel/msgs.go diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index 52e1780ec237..8512182615a6 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -24,7 +24,7 @@ type CLIObject struct { Cdc *codec.Codec } -func (man Manager) CLIObject(path merkle.Path, chanid, connid, clientid string) CLIObject { +func (man Manager) CLIObject(ctx context.CLIContext, path merkle.Path, chanid, connid string) CLIObject { obj := man.object(connid, chanid) return CLIObject{ ChanID: chanid, @@ -37,7 +37,7 @@ func (man Manager) CLIObject(path merkle.Path, chanid, connid, clientid string) return obj.packets.Value(index).Key() }, - Connection: man.connection.CLIObject(path, connid, clientid), + Connection: man.connection.CLIObject(ctx, path, connid), Path: path, Cdc: obj.channel.Cdc(), @@ -85,10 +85,10 @@ type CLIHandshakeObject struct { TimeoutKey []byte } -func (man Handshaker) CLIObject(path merkle.Path, chanid, connid, clientid string) CLIHandshakeObject { +func (man Handshaker) CLIObject(ctx context.CLIContext, path merkle.Path, chanid, connid string) CLIHandshakeObject { obj := man.object(man.man.object(connid, chanid)) return CLIHandshakeObject{ - CLIObject: man.man.CLIObject(path, chanid, connid, clientid), + CLIObject: man.man.CLIObject(ctx, path, chanid, connid), StateKey: obj.state.Key(), TimeoutKey: obj.nextTimeout.Key(), diff --git a/x/ibc/04-channel/client/cli/query.go b/x/ibc/04-channel/client/cli/query.go new file mode 100644 index 000000000000..33cf4c7faa64 --- /dev/null +++ b/x/ibc/04-channel/client/cli/query.go @@ -0,0 +1,101 @@ +package cli + +import ( + "fmt" + "strconv" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + cli "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/utils" + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +const ( + FlagProve = "prove" +) + +func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) channel.CLIObject { + prefix := []byte(strconv.FormatInt(version, 10) + "/") + path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) + base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) + climan := client.NewManager(base) + man := channel.NewManager(base, climan) + return man.CLIObject(ctx, path, id) +} + +func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcQueryCmd := &cobra.Command{ + Use: "connection", + Short: "Channel query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcQueryCmd.AddCommand(cli.GetCommands( + GetCmdQueryChannel(storeKey, cdc), + )...) + return ibcQueryCmd +} + +func QueryChannel(ctx context.CLIContext, obj channel.CLIObject, prove bool) (res utils.JSONObject, err error) { + conn, connp, err := obj.Channel(ctx) + if err != nil { + return + } + avail, availp, err := obj.Available(ctx) + if err != nil { + return + } + kind, kindp, err := obj.Kind(ctx) + if err != nil { + return + } + + if prove { + return utils.NewJSONObject( + conn, connp, + avail, availp, + kind, kindp, + ), nil + } + + return utils.NewJSONObject( + conn, nil, + avail, nil, + kind, nil, + ), nil +} + +func GetCmdQueryChannel(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "connection", + Short: "Query stored connection", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + obj := object(ctx, cdc, storeKey, ibc.Version, args[0]) + jsonobj, err := QueryChannel(ctx, obj, viper.GetBool(FlagProve)) + if err != nil { + return err + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, jsonobj)) + + return nil + }, + } + + cmd.Flags().Bool(FlagProve, false, "(optional) show proofs for the query results") + + return cmd +} diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go new file mode 100644 index 000000000000..e29a402b2979 --- /dev/null +++ b/x/ibc/04-channel/client/cli/tx.go @@ -0,0 +1,221 @@ +package cli + +import ( + "io/ioutil" + "strconv" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +/* +func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + +} +*/ +const ( + FlagNode1 = "node1" + FlagNode2 = "node2" + FlagFrom1 = "from1" + FlagFrom2 = "from2" +) + +func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) connection.CLIHandshakeObject { + prefix := []byte(strconv.FormatInt(version, 10) + "/") + path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) + base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) + climan := client.NewManager(base) + man := connection.NewHandshaker(connection.NewManager(base, climan)) + return man.CLIObject(ctx, path, id) +} + +func lastheight(ctx context.CLIContext) (uint64, error) { + node, err := ctx.GetNode() + if err != nil { + return 0, err + } + + info, err := node.ABCIInfo() + if err != nil { + return 0, err + } + + return uint64(info.Response.LastBlockHeight), nil +} + +func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "handshake", + Short: "initiate connection handshake between two chains", + Args: cobra.ExactArgs(4), + // Args: []string{connid1, connfilepath1, connid2, connfilepath2} + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + ctx1 := context.NewCLIContext(). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode1)). + WithFrom(viper.GetString(FlagFrom1)) + + ctx2 := context.NewCLIContext(). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode2)). + WithFrom(viper.GetString(FlagFrom2)) + + conn1id := args[0] + conn1bz, err := ioutil.ReadFile(args[1]) + if err != nil { + return err + } + var conn1 connection.Connection + if err := cdc.UnmarshalJSON(conn1bz, &conn1); err != nil { + return err + } + + obj1 := handshake(ctx1, cdc, storeKey, ibc.Version, conn1id) + + conn2id := args[2] + conn2bz, err := ioutil.ReadFile(args[3]) + if err != nil { + return err + } + var conn2 connection.Connection + if err := cdc.UnmarshalJSON(conn2bz, &conn2); err != nil { + return err + } + + obj2 := handshake(ctx2, cdc, storeKey, ibc.Version, conn1id) + + // TODO: check state and if not Idle continue existing process + height, err := lastheight(ctx2) + if err != nil { + return err + } + nextTimeout := height + 1000 // TODO: parameterize + msginit := connection.MsgOpenInit{ + ConnectionID: conn1id, + Connection: conn1, + CounterpartyClient: conn2.Client, + NextTimeout: nextTimeout, + Signer: ctx1.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msginit}) + if err != nil { + return err + } + + timeout := nextTimeout + height, err = lastheight(ctx1) + if err != nil { + return err + } + nextTimeout = height + 1000 + _, pconn, err := obj1.Connection(ctx1) + if err != nil { + return err + } + _, pstate, err := obj1.State(ctx1) + if err != nil { + return err + } + _, ptimeout, err := obj1.NextTimeout(ctx1) + if err != nil { + return err + } + _, pcounter, err := obj1.CounterpartyClient(ctx1) + if err != nil { + return err + } + + msgtry := connection.MsgOpenTry{ + ConnectionID: conn2id, + Connection: conn2, + CounterpartyClient: conn1.Client, + Timeout: timeout, + NextTimeout: nextTimeout, + Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Signer: ctx2.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) + if err != nil { + return err + } + + timeout = nextTimeout + height, err = lastheight(ctx2) + if err != nil { + return err + } + nextTimeout = height + 1000 + _, pconn, err = obj2.Connection(ctx2) + if err != nil { + return err + } + _, pstate, err = obj2.State(ctx2) + if err != nil { + return err + } + _, ptimeout, err = obj2.NextTimeout(ctx2) + if err != nil { + return err + } + _, pcounter, err = obj2.CounterpartyClient(ctx2) + if err != nil { + return err + } + + msgack := connection.MsgOpenAck{ + ConnectionID: conn1id, + Timeout: timeout, + NextTimeout: nextTimeout, + Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Signer: ctx1.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgack}) + if err != nil { + return err + } + + timeout = nextTimeout + _, pstate, err = obj1.State(ctx1) + if err != nil { + return err + } + _, ptimeout, err = obj1.NextTimeout(ctx1) + if err != nil { + return err + } + + msgconfirm := connection.MsgOpenConfirm{ + ConnectionID: conn2id, + Timeout: timeout, + Proofs: []commitment.Proof{pstate, ptimeout}, + Signer: ctx2.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgconfirm}) + if err != nil { + return err + } + + return nil + }, + } + + return cmd +} diff --git a/x/ibc/04-channel/client/utils/types.go b/x/ibc/04-channel/client/utils/types.go new file mode 100644 index 000000000000..33480a68291f --- /dev/null +++ b/x/ibc/04-channel/client/utils/types.go @@ -0,0 +1,59 @@ +package utils + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +type JSONObject struct { + Connection connection.Connection `json:"connection"` + ConnectionProof commitment.Proof `json:"connection_proof,omitempty"` + Available bool `json:"available"` + AvailableProof commitment.Proof `json:"available_proof,omitempty"` + Kind string `json:"kind"` + KindProof commitment.Proof `json:"kind_proof,omitempty"` +} + +func NewJSONObject( + conn connection.Connection, connp commitment.Proof, + avail bool, availp commitment.Proof, + kind string, kindp commitment.Proof, +) JSONObject { + return JSONObject{ + Connection: conn, + ConnectionProof: connp, + Available: avail, + AvailableProof: availp, + Kind: kind, + KindProof: kindp, + } +} + +type HandshakeJSONObject struct { + JSONObject `json:"connection"` + State byte `json:"state"` + StateProof commitment.Proof `json:"state_proof,omitempty"` + CounterpartyClient string `json:"counterparty_client"` + CounterpartyClientProof commitment.Proof `json:"counterparty_client_proof,omitempty"` + NextTimeout uint64 `json:"next_timeout"` + NextTimeoutProof commitment.Proof `json:"next_timeout_proof,omitempty"` +} + +func NewHandshakeJSONObject( + conn connection.Connection, connp commitment.Proof, + avail bool, availp commitment.Proof, + kind string, kindp commitment.Proof, + state byte, statep commitment.Proof, + cpclient string, cpclientp commitment.Proof, + timeout uint64, timeoutp commitment.Proof, +) HandshakeJSONObject { + return HandshakeJSONObject{ + JSONObject: NewJSONObject(conn, connp, avail, availp, kind, kindp), + State: state, + StateProof: statep, + CounterpartyClient: cpclient, + CounterpartyClientProof: cpclientp, + NextTimeout: timeout, + NextTimeoutProof: timeoutp, + } +} diff --git a/x/ibc/04-channel/handler.go b/x/ibc/04-channel/handler.go new file mode 100644 index 000000000000..76d9ace3e6e4 --- /dev/null +++ b/x/ibc/04-channel/handler.go @@ -0,0 +1,37 @@ +package channel + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Result { + _, err := man.OpenInit(ctx, msg.ConnectionID, msg.ChannelID, msg.Channel, msg.NextTimeout) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 100, "").Result() + } + return sdk.Result{} +} + +func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Result { + _, err := man.OpenTry(ctx, msg.Proofs, msg.ConnectionID, msg.ChannelID, msg.Channel, msg.Timeout, msg.NextTimeout) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 200, "").Result() + } + return sdk.Result{} +} + +func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Result { + _, err := man.OpenAck(ctx, msg.Proofs, msg.ConnectionID, msg.ChannelID, msg.Timeout, msg.NextTimeout) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 300, "").Result() + } + return sdk.Result{} +} + +func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) sdk.Result { + _, err := man.OpenConfirm(ctx, msg.Proofs, msg.ConnectionID, msg.ChannelID, msg.Timeout) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 400, "").Result() + } + return sdk.Result{} +} diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index 2889aa8183fc..96ceefe1cef9 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -161,7 +161,7 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{channel,state,nextTimeout} func (man Handshaker) OpenTry(ctx sdk.Context, - pchannel, pstate, ptimeout commitment.Proof, + proofs []commitment.Proof, connid, chanid string, channel Channel, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.create(ctx, connid, chanid, channel) @@ -169,7 +169,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, pchannel, pstate, ptimeout) + ctx, err = obj.Context(ctx, proofs) if err != nil { return } @@ -222,7 +222,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenAck(ctx sdk.Context, - pchannel, pstate, ptimeout commitment.Proof, + proofs []commitment.Proof, connid, chanid string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, connid, chanid) @@ -230,7 +230,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, pchannel, pstate, ptimeout) + ctx, err = obj.Context(ctx, proofs) if err != nil { return } @@ -282,14 +282,14 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // Using proofs: counterparty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, - pstate, ptimeout commitment.Proof, + proofs []commitment.Proof, connid, chanid string, timeoutHeight uint64) (obj HandshakeObject, err error) { obj, err = man.query(ctx, connid, chanid) if err != nil { return } - ctx, err = obj.Context(ctx, pstate, ptimeout) + ctx, err = obj.Context(ctx, proofs) if err != nil { return } diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index fe095ec8dfe4..3163d3c50455 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -200,8 +200,8 @@ type CounterObject struct { connection connection.CounterObject } -func (obj Object) Context(ctx sdk.Context, proofs ...commitment.Proof) (sdk.Context, error) { - return obj.connection.Context(ctx, nil, proofs...) +func (obj Object) Context(ctx sdk.Context, proofs []commitment.Proof) (sdk.Context, error) { + return obj.connection.Context(ctx, nil, proofs) } func (obj Object) ChanID() string { @@ -261,12 +261,12 @@ func (obj Object) Send(ctx sdk.Context, packet Packet) error { return nil } -func (obj Object) Receive(ctx sdk.Context, ppacket commitment.Proof, packet Packet) error { +func (obj Object) Receive(ctx sdk.Context, proofs []commitment.Proof, packet Packet) error { if !obj.Receivable(ctx) { return errors.New("cannot receive packets on this channel") } - ctx, err := obj.Context(ctx, ppacket) + ctx, err := obj.Context(ctx, proofs) if err != nil { return err } diff --git a/x/ibc/04-channel/msgs.go b/x/ibc/04-channel/msgs.go new file mode 100644 index 000000000000..b62d3a16bdf5 --- /dev/null +++ b/x/ibc/04-channel/msgs.go @@ -0,0 +1,132 @@ +package channel + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +type MsgOpenInit struct { + ConnectionID string + ChannelID string + Channel Channel + CounterpartyClient string + NextTimeout uint64 + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgOpenInit{} + +func (msg MsgOpenInit) Route() string { + return "ibc" +} + +func (msg MsgOpenInit) Type() string { + return "open-init" +} + +func (msg MsgOpenInit) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgOpenInit) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgOpenInit) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + +type MsgOpenTry struct { + ConnectionID string + ChannelID string + Channel Channel + CounterpartyClient string + Timeout uint64 + NextTimeout uint64 + Proofs []commitment.Proof + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgOpenTry{} + +func (msg MsgOpenTry) Route() string { + return "ibc" +} + +func (msg MsgOpenTry) Type() string { + return "open-init" +} + +func (msg MsgOpenTry) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgOpenTry) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgOpenTry) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + +type MsgOpenAck struct { + ConnectionID string + ChannelID string + Timeout uint64 + NextTimeout uint64 + Proofs []commitment.Proof + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgOpenAck{} + +func (msg MsgOpenAck) Route() string { + return "ibc" +} + +func (msg MsgOpenAck) Type() string { + return "open-init" +} + +func (msg MsgOpenAck) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgOpenAck) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgOpenAck) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} + +type MsgOpenConfirm struct { + ConnectionID string + ChannelID string + Timeout uint64 + Proofs []commitment.Proof + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgOpenConfirm{} + +func (msg MsgOpenConfirm) Route() string { + return "ibc" +} + +func (msg MsgOpenConfirm) Type() string { + return "open-init" +} + +func (msg MsgOpenConfirm) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgOpenConfirm) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgOpenConfirm) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} From 2ae06c4d6972e799228858a849ef0a256ea0bc88 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 18 Jul 2019 15:33:38 +0900 Subject: [PATCH 142/182] add client query/tx --- x/ibc/04-channel/cli.go | 37 ++++++++++-- x/ibc/04-channel/client/cli/query.go | 32 ++++++++--- x/ibc/04-channel/client/cli/tx.go | 79 +++++++++++++------------- x/ibc/04-channel/client/utils/types.go | 58 ++++++++++--------- x/ibc/04-channel/tests/types.go | 8 +-- 5 files changed, 129 insertions(+), 85 deletions(-) diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index 8512182615a6..f3d165ac7d4a 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -24,7 +24,7 @@ type CLIObject struct { Cdc *codec.Codec } -func (man Manager) CLIObject(ctx context.CLIContext, path merkle.Path, chanid, connid string) CLIObject { +func (man Manager) cliObject(path merkle.Path, chanid, connid string) CLIObject { obj := man.object(connid, chanid) return CLIObject{ ChanID: chanid, @@ -37,13 +37,23 @@ func (man Manager) CLIObject(ctx context.CLIContext, path merkle.Path, chanid, c return obj.packets.Value(index).Key() }, - Connection: man.connection.CLIObject(ctx, path, connid), - Path: path, Cdc: obj.channel.Cdc(), } } +func (man Manager) CLIQuery(ctx context.CLIContext, path merkle.Path, chanid, connid string) CLIObject { + obj := man.cliObject(path, chanid, connid) + obj.Connection = man.connection.CLIQuery(ctx, path, connid) + return obj +} + +func (man Manager) CLIObject(path merkle.Path, chanid, connid, clientid string) CLIObject { + obj := man.cliObject(path, chanid, connid) + obj.Connection = man.connection.CLIObject(path, connid, clientid) + return obj +} + func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { resp, err := ctx.QueryABCI(obj.Path.RequestQuery(key)) if err != nil { @@ -63,6 +73,11 @@ func (obj CLIObject) Channel(ctx context.CLIContext) (res Channel, proof merkle. return } +func (obj CLIObject) Available(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { + proof, err = obj.query(ctx, obj.AvailableKey, &res) + return +} + func (obj CLIObject) SeqSend(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.SeqSendKey, &res) return @@ -85,10 +100,20 @@ type CLIHandshakeObject struct { TimeoutKey []byte } -func (man Handshaker) CLIObject(ctx context.CLIContext, path merkle.Path, chanid, connid string) CLIHandshakeObject { +func (man Handshaker) CLIQuery(ctx context.CLIContext, path merkle.Path, chanid, connid string) CLIHandshakeObject { + obj := man.object(man.man.object(connid, chanid)) + return CLIHandshakeObject{ + CLIObject: man.man.CLIQuery(ctx, path, chanid, connid), + + StateKey: obj.state.Key(), + TimeoutKey: obj.nextTimeout.Key(), + } +} + +func (man Handshaker) CLIObject(path merkle.Path, chanid, connid, clientid string) CLIHandshakeObject { obj := man.object(man.man.object(connid, chanid)) return CLIHandshakeObject{ - CLIObject: man.man.CLIObject(ctx, path, chanid, connid), + CLIObject: man.man.CLIObject(path, chanid, connid, clientid), StateKey: obj.state.Key(), TimeoutKey: obj.nextTimeout.Key(), @@ -100,7 +125,7 @@ func (obj CLIHandshakeObject) State(ctx context.CLIContext) (res State, proof me return } -func (obj CLIHandshakeObject) Timeout(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { +func (obj CLIHandshakeObject) NextTimeout(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.TimeoutKey, &res) return } diff --git a/x/ibc/04-channel/client/cli/query.go b/x/ibc/04-channel/client/cli/query.go index 33cf4c7faa64..6f11957f7ab3 100644 --- a/x/ibc/04-channel/client/cli/query.go +++ b/x/ibc/04-channel/client/cli/query.go @@ -15,8 +15,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/utils" + "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/client/utils" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -24,13 +25,14 @@ const ( FlagProve = "prove" ) -func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) channel.CLIObject { +func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, connid, chanid string) channel.CLIObject { prefix := []byte(strconv.FormatInt(version, 10) + "/") path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) climan := client.NewManager(base) - man := channel.NewManager(base, climan) - return man.CLIObject(ctx, path, id) + connman := connection.NewManager(base, climan) + man := channel.NewManager(base, connman) + return man.CLIQuery(ctx, path, connid, chanid) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -56,7 +58,18 @@ func QueryChannel(ctx context.CLIContext, obj channel.CLIObject, prove bool) (re if err != nil { return } - kind, kindp, err := obj.Kind(ctx) + /* + kind, kindp, err := obj.Kind(ctx) + if err != nil { + return + } + */ + seqsend, seqsendp, err := obj.SeqSend(ctx) + if err != nil { + return + } + + seqrecv, seqrecvp, err := obj.SeqRecv(ctx) if err != nil { return } @@ -65,14 +78,17 @@ func QueryChannel(ctx context.CLIContext, obj channel.CLIObject, prove bool) (re return utils.NewJSONObject( conn, connp, avail, availp, - kind, kindp, + // kind, kindp, + seqsend, seqsendp, + seqrecv, seqrecvp, ), nil } return utils.NewJSONObject( conn, nil, avail, nil, - kind, nil, + seqsend, nil, + seqrecv, nil, ), nil } @@ -83,7 +99,7 @@ func GetCmdQueryChannel(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - obj := object(ctx, cdc, storeKey, ibc.Version, args[0]) + obj := object(ctx, cdc, storeKey, ibc.Version, args[0], args[1]) jsonobj, err := QueryChannel(ctx, obj, viper.GetBool(FlagProve)) if err != nil { return err diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index e29a402b2979..bad1375a08b8 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -17,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -33,13 +34,14 @@ const ( FlagFrom2 = "from2" ) -func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, id string) connection.CLIHandshakeObject { +func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, connid, chanid string) channel.CLIHandshakeObject { prefix := []byte(strconv.FormatInt(version, 10) + "/") path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) climan := client.NewManager(base) - man := connection.NewHandshaker(connection.NewManager(base, climan)) - return man.CLIObject(ctx, path, id) + connman := connection.NewManager(base, climan) + man := channel.NewHandshaker(channel.NewManager(base, connman)) + return man.CLIQuery(ctx, path, connid, chanid) } func lastheight(ctx context.CLIContext) (uint64, error) { @@ -56,12 +58,12 @@ func lastheight(ctx context.CLIContext) (uint64, error) { return uint64(info.Response.LastBlockHeight), nil } -func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { +func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "handshake", - Short: "initiate connection handshake between two chains", + Short: "initiate channel handshake between two chains", Args: cobra.ExactArgs(4), - // Args: []string{connid1, connfilepath1, connid2, connfilepath2} + // Args: []string{connid1, chanid1, chanfilepath1, connid2, chanid2, chanfilepath2} RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContext(). @@ -75,28 +77,30 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command WithFrom(viper.GetString(FlagFrom2)) conn1id := args[0] - conn1bz, err := ioutil.ReadFile(args[1]) + chan1id := args[1] + conn1bz, err := ioutil.ReadFile(args[2]) if err != nil { return err } - var conn1 connection.Connection + var conn1 channel.Channel if err := cdc.UnmarshalJSON(conn1bz, &conn1); err != nil { return err } - obj1 := handshake(ctx1, cdc, storeKey, ibc.Version, conn1id) + obj1 := handshake(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) - conn2id := args[2] - conn2bz, err := ioutil.ReadFile(args[3]) + conn2id := args[3] + chan2id := args[4] + conn2bz, err := ioutil.ReadFile(args[5]) if err != nil { return err } - var conn2 connection.Connection + var conn2 channel.Channel if err := cdc.UnmarshalJSON(conn2bz, &conn2); err != nil { return err } - obj2 := handshake(ctx2, cdc, storeKey, ibc.Version, conn1id) + obj2 := handshake(ctx2, cdc, storeKey, ibc.Version, conn1id, chan1id) // TODO: check state and if not Idle continue existing process height, err := lastheight(ctx2) @@ -104,12 +108,12 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } nextTimeout := height + 1000 // TODO: parameterize - msginit := connection.MsgOpenInit{ - ConnectionID: conn1id, - Connection: conn1, - CounterpartyClient: conn2.Client, - NextTimeout: nextTimeout, - Signer: ctx1.GetFromAddress(), + msginit := channel.MsgOpenInit{ + ConnectionID: conn1id, + ChannelID: chan1id, + Channel: conn1, + NextTimeout: nextTimeout, + Signer: ctx1.GetFromAddress(), } err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msginit}) @@ -123,7 +127,7 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } nextTimeout = height + 1000 - _, pconn, err := obj1.Connection(ctx1) + _, pconn, err := obj1.Channel(ctx1) if err != nil { return err } @@ -135,19 +139,15 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command if err != nil { return err } - _, pcounter, err := obj1.CounterpartyClient(ctx1) - if err != nil { - return err - } - msgtry := connection.MsgOpenTry{ - ConnectionID: conn2id, - Connection: conn2, - CounterpartyClient: conn1.Client, - Timeout: timeout, - NextTimeout: nextTimeout, - Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, - Signer: ctx2.GetFromAddress(), + msgtry := channel.MsgOpenTry{ + ConnectionID: conn2id, + ChannelID: chan2id, + Channel: conn2, + Timeout: timeout, + NextTimeout: nextTimeout, + Proofs: []commitment.Proof{pconn, pstate, ptimeout}, + Signer: ctx2.GetFromAddress(), } err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) @@ -161,7 +161,7 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } nextTimeout = height + 1000 - _, pconn, err = obj2.Connection(ctx2) + _, pconn, err = obj2.Channel(ctx2) if err != nil { return err } @@ -173,16 +173,12 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command if err != nil { return err } - _, pcounter, err = obj2.CounterpartyClient(ctx2) - if err != nil { - return err - } - msgack := connection.MsgOpenAck{ + msgack := channel.MsgOpenAck{ ConnectionID: conn1id, + ChannelID: chan1id, Timeout: timeout, - NextTimeout: nextTimeout, - Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Proofs: []commitment.Proof{pconn, pstate, ptimeout}, Signer: ctx1.GetFromAddress(), } @@ -201,8 +197,9 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } - msgconfirm := connection.MsgOpenConfirm{ + msgconfirm := channel.MsgOpenConfirm{ ConnectionID: conn2id, + ChannelID: chan2id, Timeout: timeout, Proofs: []commitment.Proof{pstate, ptimeout}, Signer: ctx2.GetFromAddress(), diff --git a/x/ibc/04-channel/client/utils/types.go b/x/ibc/04-channel/client/utils/types.go index 33480a68291f..4006e7bacebb 100644 --- a/x/ibc/04-channel/client/utils/types.go +++ b/x/ibc/04-channel/client/utils/types.go @@ -1,36 +1,42 @@ package utils import ( - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type JSONObject struct { - Connection connection.Connection `json:"connection"` - ConnectionProof commitment.Proof `json:"connection_proof,omitempty"` - Available bool `json:"available"` - AvailableProof commitment.Proof `json:"available_proof,omitempty"` - Kind string `json:"kind"` - KindProof commitment.Proof `json:"kind_proof,omitempty"` + Channel channel.Channel `json:"channel"` + ChannelProof commitment.Proof `json:"channel_proof,omitempty"` + Available bool `json:"available"` + AvailableProof commitment.Proof `json:"available_proof,omitempty"` + SequenceSend uint64 `json:"sequence_send"` + SequenceSendProof commitment.Proof `json:"sequence_send_proof,omitempty"` + SequenceReceive uint64 `json:"sequence_receive"` + SequenceReceiveProof commitment.Proof `json:"sequence_receive_proof,omitempty"` + // Kind string `json:"kind"` + // KindProof commitment.Proof `json:"kind_proof,omitempty"` } func NewJSONObject( - conn connection.Connection, connp commitment.Proof, + channel channel.Channel, channelp commitment.Proof, avail bool, availp commitment.Proof, - kind string, kindp commitment.Proof, + // kind string, kindp commitment.Proof, + seqsend uint64, seqsendp commitment.Proof, + seqrecv uint64, seqrecvp commitment.Proof, ) JSONObject { return JSONObject{ - Connection: conn, - ConnectionProof: connp, - Available: avail, - AvailableProof: availp, - Kind: kind, - KindProof: kindp, + Channel: channel, + ChannelProof: channelp, + Available: avail, + AvailableProof: availp, + // Kind: kind, + // KindProof: kindp, } } type HandshakeJSONObject struct { - JSONObject `json:"connection"` + JSONObject `json:"channel"` State byte `json:"state"` StateProof commitment.Proof `json:"state_proof,omitempty"` CounterpartyClient string `json:"counterparty_client"` @@ -40,20 +46,20 @@ type HandshakeJSONObject struct { } func NewHandshakeJSONObject( - conn connection.Connection, connp commitment.Proof, + channel channel.Channel, channelp commitment.Proof, avail bool, availp commitment.Proof, - kind string, kindp commitment.Proof, + // kind string, kindp commitment.Proof, + seqsend uint64, seqsendp commitment.Proof, + seqrecv uint64, seqrecvp commitment.Proof, + state byte, statep commitment.Proof, - cpclient string, cpclientp commitment.Proof, timeout uint64, timeoutp commitment.Proof, ) HandshakeJSONObject { return HandshakeJSONObject{ - JSONObject: NewJSONObject(conn, connp, avail, availp, kind, kindp), - State: state, - StateProof: statep, - CounterpartyClient: cpclient, - CounterpartyClientProof: cpclientp, - NextTimeout: timeout, - NextTimeoutProof: timeoutp, + JSONObject: NewJSONObject(channel, channelp, avail, availp, seqsend, seqsendp, seqrecv, seqrecvp), + State: state, + StateProof: statep, + NextTimeout: timeout, + NextTimeoutProof: timeoutp, } } diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 80f94e7e248c..fae2418d4ee3 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -90,7 +90,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, proofs[0], proofs[1], proofs[2], node.Name, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs, node.Name, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.OpenTry, obj.State(ctx)) require.Equal(t, node.Channel, obj.Channel(ctx)) @@ -100,7 +100,7 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, proofs[0], proofs[1], proofs[2], node.Name, node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs, node.Name, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.Open, obj.State(ctx)) require.Equal(t, node.Channel, obj.Channel(ctx)) @@ -110,7 +110,7 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, proofs[0], proofs[1], node.Name, node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs, node.Name, node.Name, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.Open, obj.State(ctx)) require.Equal(t, node.Channel, obj.Channel(ctx)) @@ -167,7 +167,7 @@ func (node *Node) Receive(t *testing.T, packet channel.Packet, proofs ...commitm obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) seq := obj.SeqRecv(ctx) - err = obj.Receive(ctx, proofs[0], packet) + err = obj.Receive(ctx, proofs, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqRecv(ctx)) } From 7ecd36016199acdfe16f96e2f620e7b9b03eb36f Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 19 Jul 2019 00:56:10 +0900 Subject: [PATCH 143/182] fix golangci --- x/ibc/04-channel/msgs.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/x/ibc/04-channel/msgs.go b/x/ibc/04-channel/msgs.go index b62d3a16bdf5..9e4d5fe987a5 100644 --- a/x/ibc/04-channel/msgs.go +++ b/x/ibc/04-channel/msgs.go @@ -6,6 +6,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) +const Route = "ibc" + type MsgOpenInit struct { ConnectionID string ChannelID string @@ -18,7 +20,7 @@ type MsgOpenInit struct { var _ sdk.Msg = MsgOpenInit{} func (msg MsgOpenInit) Route() string { - return "ibc" + return Route } func (msg MsgOpenInit) Type() string { @@ -51,11 +53,11 @@ type MsgOpenTry struct { var _ sdk.Msg = MsgOpenTry{} func (msg MsgOpenTry) Route() string { - return "ibc" + return Route } func (msg MsgOpenTry) Type() string { - return "open-init" + return "open-try" } func (msg MsgOpenTry) ValidateBasic() sdk.Error { @@ -82,11 +84,11 @@ type MsgOpenAck struct { var _ sdk.Msg = MsgOpenAck{} func (msg MsgOpenAck) Route() string { - return "ibc" + return Route } func (msg MsgOpenAck) Type() string { - return "open-init" + return "open-ack" } func (msg MsgOpenAck) ValidateBasic() sdk.Error { @@ -112,11 +114,11 @@ type MsgOpenConfirm struct { var _ sdk.Msg = MsgOpenConfirm{} func (msg MsgOpenConfirm) Route() string { - return "ibc" + return Route } func (msg MsgOpenConfirm) Type() string { - return "open-init" + return "open-confirm" } func (msg MsgOpenConfirm) ValidateBasic() sdk.Error { From 33d1760d5bab61a072f448594e7d2ddf6e98580b Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 19 Jul 2019 02:57:50 +0900 Subject: [PATCH 144/182] add MsgReceive --- x/ibc/04-channel/client/cli/tx.go | 51 ++++++++++++++++++++++++++ x/ibc/04-channel/handler.go | 11 ++++++ x/ibc/04-channel/manager.go | 16 ++++++-- x/ibc/04-channel/msgs.go | 30 +++++++++++++++ x/ibc/04-channel/router.go | 34 +++++++++++++++++ x/ibc/04-channel/tests/channel_test.go | 7 +++- x/ibc/04-channel/tests/types.go | 4 +- x/ibc/04-channel/types.go | 3 +- 8 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 x/ibc/04-channel/router.go diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index bad1375a08b8..4b314f523866 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -216,3 +216,54 @@ func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return cmd } + +func GetCmdRelay(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "relay", + Short: "relay pakcets between two channels", + Args: cobra.ExactArgs(4), + // Args: []string{connid1, chanid1, chanfilepath1, connid2, chanid2, chanfilepath2} + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + ctx1 := context.NewCLIContext(). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode1)). + WithFrom(viper.GetString(FlagFrom1)) + + ctx2 := context.NewCLIContext(). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode2)). + WithFrom(viper.GetString(FlagFrom2)) + + conn1id, chan1id, conn2id, chan2id := args[0], args[1], args[2], args[3] + + obj1 := object(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) + obj2 := object(ctx2, cdc, storeKey, ibc.Version, conn2id, chan2id) + }, + } + + return cmd +} + +func relay(ctxFrom, ctxTo context.CLIContext, objFrom, objTo channel.Object) error { + seq, _, err := objTo.SeqRecv(ctxTo) + if err != nil { + return err + } + + sent, _, err := objFrom.SeqSend(ctxFrom) + if err != nil { + return err + } + + if seq == sent { + return nil + } + + packet, proof, err := query(ctxFrom, objFrom.Packet(seq)) + if err != nil { + return err + } + + msg := channel.MsgReceive{} +} diff --git a/x/ibc/04-channel/handler.go b/x/ibc/04-channel/handler.go index 76d9ace3e6e4..02c2c334fb45 100644 --- a/x/ibc/04-channel/handler.go +++ b/x/ibc/04-channel/handler.go @@ -35,3 +35,14 @@ func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) s } return sdk.Result{} } + +type Handler func(sdk.Context, Packet) sdk.Result + +func HandleMsgReceive(ctx sdk.Context, msg MsgReceive, man Manager) sdk.Result { + err := man.Receive(ctx, msg.Proofs, msg.ConnectionID, msg.ChannelID, msg.Packet) + if err != nil { + return sdk.NewError(sdk.CodespaceType("ibc"), 500, "").Result() + } + handler := man.router.Route(msg.Packet.Route()) + return handler(ctx, msg.Packet) +} diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 3163d3c50455..f21115e3006c 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -18,6 +18,8 @@ type Manager struct { connection connection.Manager counterparty CounterpartyManager + + router Router } type CounterpartyManager struct { @@ -256,17 +258,22 @@ func (obj Object) Send(ctx sdk.Context, packet Packet) error { return errors.New("timeout height higher than the latest known") } - obj.packets.SetRaw(ctx, obj.seqsend.Incr(ctx), packet.Commit()) + obj.packets.Set(ctx, obj.seqsend.Incr(ctx), packet) return nil } -func (obj Object) Receive(ctx sdk.Context, proofs []commitment.Proof, packet Packet) error { +func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, connid, chanid string, packet Packet) error { + obj, err := man.Query(ctx, connid, chanid) + if err != nil { + return err + } + if !obj.Receivable(ctx) { return errors.New("cannot receive packets on this channel") } - ctx, err := obj.Context(ctx, proofs) + ctx, err = obj.Context(ctx, proofs) if err != nil { return err } @@ -277,7 +284,8 @@ func (obj Object) Receive(ctx sdk.Context, proofs []commitment.Proof, packet Pac } // XXX: increment should happen before verification, reflect on the spec - if !obj.counterparty.packets.Value(obj.seqrecv.Incr(ctx)).IsRaw(ctx, packet.Commit()) { + // TODO: packet should be custom marshalled + if !obj.counterparty.packets.Value(obj.seqrecv.Incr(ctx)).Is(ctx, packet) { return errors.New("verification failed") } diff --git a/x/ibc/04-channel/msgs.go b/x/ibc/04-channel/msgs.go index 9e4d5fe987a5..ba35f0bbc406 100644 --- a/x/ibc/04-channel/msgs.go +++ b/x/ibc/04-channel/msgs.go @@ -132,3 +132,33 @@ func (msg MsgOpenConfirm) GetSignBytes() []byte { func (msg MsgOpenConfirm) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.Signer} } + +type MsgReceive struct { + ConnectionID string + ChannelID string + Packet Packet + Proofs []commitment.Proof + Signer sdk.AccAddress +} + +var _ sdk.Msg = MsgReceive{} + +func (msg MsgReceive) Route() string { + return Route +} + +func (msg MsgReceive) Type() string { + return "receive" +} + +func (msg MsgReceive) ValidateBasic() sdk.Error { + return nil // TODO +} + +func (msg MsgReceive) GetSignBytes() []byte { + return nil // TODO +} + +func (msg MsgReceive) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} diff --git a/x/ibc/04-channel/router.go b/x/ibc/04-channel/router.go new file mode 100644 index 000000000000..40c2c180fb31 --- /dev/null +++ b/x/ibc/04-channel/router.go @@ -0,0 +1,34 @@ +package channel + +type Router interface { + AddRoute(path string, h Handler) Router + Route(path string) Handler +} + +type router struct { + routes map[string]Handler +} + +func NewRouter() Router { + return &router{ + routes: make(map[string]Handler), + } +} + +func (router *router) AddRoute(path string, h Handler) Router { + // TODO + /* + if !isAlphaNumeric(path) { + panic("route expressions can only contain alphanumeric characters") + } + */ + if router.routes[path] != nil { + panic("route " + path + "has already been initialized") + } + router.routes[path] = h + return router +} + +func (router *router) Route(path string) Handler { + return router.routes[path] +} diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go index db2aac451268..6463d6db0c2d 100644 --- a/x/ibc/04-channel/tests/channel_test.go +++ b/x/ibc/04-channel/tests/channel_test.go @@ -36,14 +36,19 @@ type MyPacket struct { Message string } +/* func (packet MyPacket) Commit() []byte { return []byte(packet.Message) } - +*/ func (packet MyPacket) Timeout() uint64 { return 100 // TODO } +func (MyPacket) Route() string { + return "my" +} + func TestPacket(t *testing.T) { cdc := codec.New() registerCodec(cdc) diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index fae2418d4ee3..daa17e526bb3 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -159,7 +159,7 @@ func (node *Node) Send(t *testing.T, packet channel.Packet) { err = obj.Send(ctx, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqSend(ctx)) - require.Equal(t, packet.Commit(), obj.PacketCommit(ctx, seq+1)) + require.Equal(t, node.Cdc.MustMarshalBinaryBare(packet), obj.PacketCommit(ctx, seq+1)) } func (node *Node) Receive(t *testing.T, packet channel.Packet, proofs ...commitment.Proof) { @@ -167,7 +167,7 @@ func (node *Node) Receive(t *testing.T, packet channel.Packet, proofs ...commitm obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) seq := obj.SeqRecv(ctx) - err = obj.Receive(ctx, proofs, packet) + err = man.Receive(ctx, proofs, node.Name, node.Name, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqRecv(ctx)) } diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index 11c73fe834d4..891bea6f9985 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -16,7 +16,8 @@ type Packet struct { type Packet interface { Timeout() uint64 - Commit() []byte // Can be a commit message + // Commit() []byte // Can be a commit message + Route() string } type Channel struct { From bf762ba4dfe6d0684c2e53baf0883c115bc879bf Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 19 Jul 2019 13:43:42 +0900 Subject: [PATCH 145/182] fix relayer cli --- x/ibc/04-channel/cli.go | 2 +- x/ibc/04-channel/client/cli/tx.go | 51 +++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index f3d165ac7d4a..ffb0aeaa3f9e 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -88,7 +88,7 @@ func (obj CLIObject) SeqRecv(ctx context.CLIContext) (res uint64, proof merkle.P return } -func (obj CLIObject) PacketCommit(ctx context.CLIContext, index uint64) (res Packet, proof merkle.Proof, err error) { +func (obj CLIObject) Packet(ctx context.CLIContext, index uint64) (res Packet, proof merkle.Proof, err error) { proof, err = obj.query(ctx, obj.PacketCommitKey(index), &res) return } diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index 4b314f523866..7f67c9902cb2 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -3,6 +3,7 @@ package cli import ( "io/ioutil" "strconv" + "time" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -224,7 +225,6 @@ func GetCmdRelay(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(4), // Args: []string{connid1, chanid1, chanfilepath1, connid2, chanid2, chanfilepath2} RunE: func(cmd *cobra.Command, args []string) error { - txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContext(). WithCodec(cdc). WithNodeURI(viper.GetString(FlagNode1)). @@ -239,13 +239,33 @@ func GetCmdRelay(storeKey string, cdc *codec.Codec) *cobra.Command { obj1 := object(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) obj2 := object(ctx2, cdc, storeKey, ibc.Version, conn2id, chan2id) + + return relayLoop(cdc, ctx1, ctx2, obj1, obj2, conn1id, chan1id, conn2id, chan2id) }, } return cmd } -func relay(ctxFrom, ctxTo context.CLIContext, objFrom, objTo channel.Object) error { +func relayLoop(cdc *codec.Codec, + ctx1, ctx2 context.CLIContext, + obj1, obj2 channel.CLIObject, + conn1id, chan1id, conn2id, chan2id string, +) error { + for { + // TODO: relay() should be goroutine and return error by channel + err := relay(cdc, ctx1, ctx2, obj1, obj2, conn2id, chan2id) + // TODO: relayBetween() should retry several times before halt + if err != nil { + return err + } + time.Sleep(1 * time.Second) + } +} + +func relay(cdc *codec.Codec, ctxFrom, ctxTo context.CLIContext, objFrom, objTo channel.CLIObject, connidTo, chanidTo string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + seq, _, err := objTo.SeqRecv(ctxTo) if err != nil { return err @@ -256,14 +276,25 @@ func relay(ctxFrom, ctxTo context.CLIContext, objFrom, objTo channel.Object) err return err } - if seq == sent { - return nil - } - - packet, proof, err := query(ctxFrom, objFrom.Packet(seq)) - if err != nil { - return err + for i := seq; i <= sent; i++ { + packet, proof, err := objFrom.Packet(ctxFrom, seq) + if err != nil { + return err + } + + msg := channel.MsgReceive{ + ConnectionID: connidTo, + ChannelID: chanidTo, + Packet: packet, + Proofs: []commitment.Proof{proof}, + Signer: ctxTo.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctxTo, txBldr, []sdk.Msg{msg}) + if err != nil { + return err + } } - msg := channel.MsgReceive{} + return nil } From 1061a7888faafe37ce01806a7868e8e7cedd40a2 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 15 Aug 2019 20:12:00 +0900 Subject: [PATCH 146/182] finalize rebase, fix test --- store/state/indexer.go | 5 +- store/state/mapping_test.go | 2 +- x/ibc/03-connection/cli.go | 2 - x/ibc/04-channel/cli.go | 133 ++++++---------- x/ibc/04-channel/handshake.go | 148 +++++++++--------- x/ibc/04-channel/keys.go | 5 + x/ibc/04-channel/manager.go | 205 +++++++++++++------------ x/ibc/04-channel/tests/channel_test.go | 10 +- x/ibc/04-channel/tests/types.go | 78 +++++----- x/ibc/04-channel/types.go | 9 ++ x/ibc/23-commitment/store.go | 4 +- x/ibc/23-commitment/value.go | 3 +- 12 files changed, 286 insertions(+), 318 deletions(-) create mode 100644 x/ibc/04-channel/keys.go diff --git a/store/state/indexer.go b/store/state/indexer.go index 666d31b45667..c948937306da 100644 --- a/store/state/indexer.go +++ b/store/state/indexer.go @@ -31,8 +31,9 @@ type Indexer struct { enc IntEncoding } -// NewIndexer() constructs the Indexer with a predetermined prefix and IntEncoding -func NewIndexer(m Mapping, enc IntEncoding) Indexer { + +// Indexer() constructs the Indexer with an IntEncoding +func (m Mapping) Indexer(enc IntEncoding) Indexer { return Indexer{ m: m, enc: enc, diff --git a/store/state/mapping_test.go b/store/state/mapping_test.go index 0a29fead8a6e..2f44b9fcccc2 100644 --- a/store/state/mapping_test.go +++ b/store/state/mapping_test.go @@ -60,7 +60,7 @@ type indexerT struct { var _ mapping = indexerT{} func newIndexer(enc IntEncoding) indexerT { - return indexerT{NewIndexer(NewMapping(testkey, testcdc, nil), enc)} + return indexerT{NewMapping(testkey, testcdc, nil).Indexer(enc)} } func (m indexerT) Get(ctx Context, key interface{}, ptr interface{}) { diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 769792c16358..2a6c65d7c824 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -14,8 +14,6 @@ func (man Manager) CLIObject(connid, clientid string) Object { return obj } - - func (obj Object) prefix() []byte { return bytes.Split(obj.Connection.KeyBytes(), LocalRoot())[0] } diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index ffb0aeaa3f9e..acfbb9bd8d0f 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -1,131 +1,88 @@ package channel import ( + "bytes" + "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -// CLIObject stores the key for each object fields -type CLIObject struct { - ChanID string - ChannelKey []byte - - AvailableKey []byte - SeqSendKey []byte - SeqRecvKey []byte - PacketCommitKey func(index uint64) []byte - - Connection connection.CLIObject - - Path merkle.Path - Cdc *codec.Codec -} - -func (man Manager) cliObject(path merkle.Path, chanid, connid string) CLIObject { - obj := man.object(connid, chanid) - return CLIObject{ - ChanID: chanid, - ChannelKey: obj.channel.Key(), - - AvailableKey: obj.available.Key(), - SeqSendKey: obj.seqsend.Key(), - SeqRecvKey: obj.seqrecv.Key(), - PacketCommitKey: func(index uint64) []byte { - return obj.packets.Value(index).Key() - }, - - Path: path, - Cdc: obj.channel.Cdc(), +func (man Manager) CLIObject(portid, chanid string, connids []string) Object { + obj := man.object(portid, chanid) + for _, connid := range connids { + obj.Connections = append(obj.Connections, man.connection.Object(connid)) } -} - -func (man Manager) CLIQuery(ctx context.CLIContext, path merkle.Path, chanid, connid string) CLIObject { - obj := man.cliObject(path, chanid, connid) - obj.Connection = man.connection.CLIQuery(ctx, path, connid) - return obj -} - -func (man Manager) CLIObject(path merkle.Path, chanid, connid, clientid string) CLIObject { - obj := man.cliObject(path, chanid, connid) - obj.Connection = man.connection.CLIObject(path, connid, clientid) return obj } -func (obj CLIObject) query(ctx context.CLIContext, key []byte, ptr interface{}) (merkle.Proof, error) { - resp, err := ctx.QueryABCI(obj.Path.RequestQuery(key)) +func (man Manager) CLIQuery(ctx context.CLIContext, portid, chanid string) (obj Object, err error) { + obj = man.object(portid, chanid) + channel, _, err := obj.ChannelCLI(ctx) if err != nil { - return merkle.Proof{}, err + return } - proof := merkle.Proof{ - Key: key, - Proof: resp.Proof, + for _, connid := range channel.ConnectionHops { + obj.Connections = append(obj.Connections, man.connection.Object(connid)) } - err = obj.Cdc.UnmarshalBinaryBare(resp.Value, ptr) - return proof, err - + return } -func (obj CLIObject) Channel(ctx context.CLIContext) (res Channel, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.ChannelKey, &res) - return +func (obj Object) prefix() []byte { + return bytes.Split(obj.Channel.KeyBytes(), LocalRoot())[0] } -func (obj CLIObject) Available(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.AvailableKey, &res) +func (obj Object) ChannelCLI(ctx context.CLIContext) (res Channel, proof merkle.Proof, err error) { + tmproof, err := obj.Channel.Query(ctx, &res) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Channel) return } -func (obj CLIObject) SeqSend(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.SeqSendKey, &res) +func (obj Object) AvailableCLI(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { + res, tmproof, err := obj.Available.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Available) return } -func (obj CLIObject) SeqRecv(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.SeqRecvKey, &res) +func (obj Object) SeqSendCLI(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { + res, tmproof, err := obj.SeqSend.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.SeqSend) return } -func (obj CLIObject) Packet(ctx context.CLIContext, index uint64) (res Packet, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.PacketCommitKey(index), &res) +func (obj Object) SeqRecvCLI(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { + res, tmproof, err := obj.SeqRecv.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.SeqRecv) return } -type CLIHandshakeObject struct { - CLIObject - - StateKey []byte - TimeoutKey []byte +func (obj Object) PacketCLI(ctx context.CLIContext, index uint64) (res Packet, proof merkle.Proof, err error) { + packet := obj.Packets.Value(index) + tmproof, err := packet.Query(ctx, &res) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), packet) + return } -func (man Handshaker) CLIQuery(ctx context.CLIContext, path merkle.Path, chanid, connid string) CLIHandshakeObject { - obj := man.object(man.man.object(connid, chanid)) - return CLIHandshakeObject{ - CLIObject: man.man.CLIQuery(ctx, path, chanid, connid), - - StateKey: obj.state.Key(), - TimeoutKey: obj.nextTimeout.Key(), +func (man Handshaker) CLIQuery(ctx context.CLIContext, portid, chanid string) (HandshakeObject, error) { + obj, err := man.man.CLIQuery(ctx, portid, chanid) + if err != nil { + return HandshakeObject{}, err } + return man.object(obj), nil } -func (man Handshaker) CLIObject(path merkle.Path, chanid, connid, clientid string) CLIHandshakeObject { - obj := man.object(man.man.object(connid, chanid)) - return CLIHandshakeObject{ - CLIObject: man.man.CLIObject(path, chanid, connid, clientid), - - StateKey: obj.state.Key(), - TimeoutKey: obj.nextTimeout.Key(), - } +func (man Handshaker) CLIObject(portid, chanid string, connids []string) HandshakeObject { + return man.object(man.man.CLIObject(portid, chanid, connids)) } -func (obj CLIHandshakeObject) State(ctx context.CLIContext) (res State, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.StateKey, &res) +func (obj HandshakeObject) StateCLI(ctx context.CLIContext) (res State, proof merkle.Proof, err error) { + res, tmproof, err := obj.State.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) return } -func (obj CLIHandshakeObject) NextTimeout(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { - proof, err = obj.query(ctx, obj.TimeoutKey, &res) +func (obj HandshakeObject) NextTimeoutCLI(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { + res, tmproof, err := obj.NextTimeout.Query(ctx) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.NextTimeout) return } diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index 96ceefe1cef9..48faa877b838 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type State = byte @@ -48,8 +48,8 @@ type CounterpartyHandshaker struct { type HandshakeObject struct { Object - state state.Enum - nextTimeout state.Integer + State state.Enum + NextTimeout state.Integer counterparty CounterHandshakeObject } @@ -57,32 +57,32 @@ type HandshakeObject struct { type CounterHandshakeObject struct { CounterObject - state commitment.Enum - nextTimeout commitment.Integer + State commitment.Enum + NextTimeout commitment.Integer } // CONTRACT: client and remote must be filled by the caller func (man Handshaker) object(parent Object) HandshakeObject { - prefix := parent.connid + "/channels/" + parent.chanid + prefix := parent.portid + "/channels/" + parent.chanid return HandshakeObject{ Object: parent, - state: state.NewEnum(man.man.protocol.Value([]byte(prefix + "/state"))), - nextTimeout: state.NewInteger(man.man.protocol.Value([]byte(prefix+"/timeout")), state.Dec), + State: man.man.protocol.Value([]byte(prefix + "/state")).Enum(), + NextTimeout: man.man.protocol.Value([]byte(prefix + "/timeout")).Integer(state.Dec), - // CONTRACT: counterparty must be filled by the caller + counterparty: man.counterparty.object(parent.counterparty), } } -func (man CounterpartyHandshaker) object(connid, chanid string) CounterHandshakeObject { - prefix := connid + "/channels/" + chanid +func (man CounterpartyHandshaker) object(parent CounterObject) CounterHandshakeObject { + prefix := parent.portid + "/channels/" + parent.chanid return CounterHandshakeObject{ - CounterObject: man.man.object(connid, chanid), + CounterObject: man.man.object(parent.portid, parent.chanid), - state: commitment.NewEnum(man.man.protocol.Value([]byte(prefix + "/state"))), - nextTimeout: commitment.NewInteger(man.man.protocol.Value([]byte(prefix+"/timeout")), state.Dec), + State: man.man.protocol.Value([]byte(prefix + "/state")).Enum(), + NextTimeout: man.man.protocol.Value([]byte(prefix + "/timeout")).Integer(state.Dec), } } @@ -92,9 +92,6 @@ func (man Handshaker) create(ctx sdk.Context, connid, chanid string, channel Cha return } obj = man.object(cobj) - counterconnid := obj.connection.Connection(ctx).Counterparty - obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) - obj.counterparty.connection = man.counterparty.man.connection.Object(counterconnid) return obj, nil } @@ -105,31 +102,16 @@ func (man Handshaker) query(ctx sdk.Context, connid, chanid string) (obj Handsha return } obj = man.object(cobj) - channel := obj.Channel(ctx) - counterconnid := obj.connection.Connection(ctx).Counterparty - obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) - obj.counterparty.connection = man.counterparty.man.connection.Object(counterconnid) - return -} - -func (obj HandshakeObject) State(ctx sdk.Context) byte { - return obj.state.Get(ctx) -} - -func (obj HandshakeObject) Timeout(ctx sdk.Context) uint64 { - return obj.nextTimeout.Get(ctx) -} -func (obj HandshakeObject) NextTimeout(ctx sdk.Context) uint64 { - return obj.nextTimeout.Get(ctx) + return obj, nil } /* func (obj HandshakeObject) remove(ctx sdk.Context) { obj.Object.remove(ctx) - obj.state.Delete(ctx) + obj.State.Delete(ctx) obj.counterpartyClient.Delete(ctx) - obj.nextTimeout.Delete(ctx) + obj.NextTimeout.Delete(ctx) } */ @@ -146,15 +128,20 @@ func (man Handshaker) OpenInit(ctx sdk.Context, connid, chanid string, channel Channel, nextTimeoutHeight uint64, ) (HandshakeObject, error) { // man.Create() will ensure + // assert(connectionHops.length === 2) // assert(get("channels/{identifier}") === null) and // set("channels/{identifier}", connection) + if len(channel.ConnectionHops) != 1 { + return HandshakeObject{}, errors.New("ConnectionHops length must be 1") + } + obj, err := man.create(ctx, connid, chanid, channel) if err != nil { return HandshakeObject{}, err } - obj.nextTimeout.Set(ctx, nextTimeoutHeight) - obj.state.Set(ctx, Init) + obj.NextTimeout.Set(ctx, nextTimeoutHeight) + obj.State.Set(ctx, Init) return obj, nil } @@ -162,9 +149,12 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{channel,state,nextTimeout} func (man Handshaker) OpenTry(ctx sdk.Context, proofs []commitment.Proof, - connid, chanid string, channel Channel, timeoutHeight, nextTimeoutHeight uint64, + portid, chanid string, channel Channel, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { - obj, err = man.create(ctx, connid, chanid, channel) + if len(channel.ConnectionHops) != 1 { + return HandshakeObject{}, errors.New("ConnectionHops length must be 1") + } + obj, err = man.create(ctx, portid, chanid, channel) if err != nil { return } @@ -179,21 +169,22 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.state.Is(ctx, Init) { + if !obj.counterparty.State.Is(ctx, Init) { err = errors.New("counterparty state not init") return } - if !obj.counterparty.channel.Is(ctx, Channel{ + if !obj.counterparty.Channel.Is(ctx, Channel{ Port: channel.CounterpartyPort, Counterparty: chanid, - CounterpartyPort: "", // TODO + CounterpartyPort: channel.Port, + ConnectionHops: []string{obj.Connections[0].GetConnection(ctx).Counterparty}, }) { err = errors.New("wrong counterparty connection") return } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } @@ -214,8 +205,8 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // assert(get("connections/{desiredIdentifier}") === null) and // set("connections{identifier}", connection) - obj.state.Set(ctx, OpenTry) - obj.nextTimeout.Set(ctx, nextTimeoutHeight) + obj.State.Set(ctx, OpenTry) + obj.NextTimeout.Set(ctx, nextTimeoutHeight) return } @@ -235,7 +226,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.state.Transit(ctx, Init, Open) { + if !obj.State.Transit(ctx, Init, Open) { err = errors.New("ack on non-init connection") return } @@ -245,22 +236,23 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - channel := obj.Channel(ctx) - if !obj.counterparty.channel.Is(ctx, Channel{ + channel := obj.GetChannel(ctx) + if !obj.counterparty.Channel.Is(ctx, Channel{ Port: channel.CounterpartyPort, Counterparty: chanid, - CounterpartyPort: "", // TODO + CounterpartyPort: channel.Port, + ConnectionHops: []string{obj.Connections[0].GetConnection(ctx).Counterparty}, }) { err = errors.New("wrong counterparty") return } - if !obj.counterparty.state.Is(ctx, OpenTry) { + if !obj.counterparty.State.Is(ctx, OpenTry) { err = errors.New("counterparty state not opentry") return } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } @@ -274,8 +266,8 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } */ - obj.nextTimeout.Set(ctx, nextTimeoutHeight) - obj.available.Set(ctx, true) + obj.NextTimeout.Set(ctx, nextTimeoutHeight) + obj.Available.Set(ctx, true) return } @@ -294,7 +286,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - if !obj.state.Transit(ctx, OpenTry, Open) { + if !obj.State.Transit(ctx, OpenTry, Open) { err = errors.New("confirm on non-try connection") return } @@ -304,18 +296,18 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - if !obj.counterparty.state.Is(ctx, Open) { + if !obj.counterparty.State.Is(ctx, Open) { err = errors.New("counterparty state not open") return } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { err = errors.New("unexpected counterparty timeout value") return } - obj.available.Set(ctx, true) - obj.nextTimeout.Set(ctx, 0) + obj.Available.Set(ctx, true) + obj.NextTimeout.Set(ctx, 0) return } @@ -323,23 +315,23 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, // TODO /* func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { - if !(obj.connection.Client().ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + if !(obj.connection.Client().ConsensusState(ctx).GetHeight()) > obj.NextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } - switch obj.state.Get(ctx) { + switch obj.State.Get(ctx) { case Init: if !obj.counterparty.connection.Is(ctx, nil) { return errors.New("counterparty connection exists") } case OpenTry: - if !(obj.counterparty.state.Is(ctx, Init) || + if !(obj.counterparty.State.Is(ctx, Init) || obj.counterparty.connection.Is(ctx, nil)) { return errors.New("counterparty connection state not init") } // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) case Open: - if obj.counterparty.state.Is(ctx, OpenTry) { + if obj.counterparty.State.Is(ctx, OpenTry) { return errors.New("counterparty connection state not tryopen") } } @@ -351,17 +343,17 @@ func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error { - if !obj.state.Transit(ctx, Open, CloseTry) { + if !obj.State.Transit(ctx, Open, CloseTry) { return errors.New("closeinit on non-open connection") } - obj.nextTimeout.Set(ctx, nextTimeout) + obj.NextTimeout.Set(ctx, nextTimeout) return nil } func (obj HandshakeObject) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { - if !obj.state.Transit(ctx, Open, Closed) { + if !obj.State.Transit(ctx, Open, Closed) { return errors.New("closetry on non-open connection") } @@ -370,21 +362,21 @@ func (obj HandshakeObject) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutH return err } - if !obj.counterparty.state.Is(ctx, CloseTry) { + if !obj.counterparty.State.Is(ctx, CloseTry) { return errors.New("unexpected counterparty state value") } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } - obj.nextTimeout.Set(ctx, nextTimeoutHeight) + obj.NextTimeout.Set(ctx, nextTimeoutHeight) return nil } func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { - if !obj.state.Transit(ctx, CloseTry, Closed) { + if !obj.State.Transit(ctx, CloseTry, Closed) { return errors.New("closeack on non-closetry connection") } @@ -393,38 +385,38 @@ func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error return err } - if !obj.counterparty.state.Is(ctx, Closed) { + if !obj.counterparty.State.Is(ctx, Closed) { return errors.New("unexpected counterparty state value") } - if !obj.counterparty.nextTimeout.Is(ctx, timeoutHeight) { + if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { return errors.New("unexpected counterparty timeout value") } - obj.nextTimeout.Set(ctx, 0) + obj.NextTimeout.Set(ctx, 0) return nil } func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { - if !(obj.client.ConsensusState(ctx).GetHeight()) > obj.nextTimeout.Get(ctx)) { + if !(obj.client.ConsensusState(ctx).GetHeight()) > obj.NextTimeout.Get(ctx)) { return errors.New("timeout height not yet reached") } // XXX: double check if the user can bypass the verification logic somehow - switch obj.state.Get(ctx) { + switch obj.State.Get(ctx) { case CloseTry: - if !obj.counterparty.state.Is(ctx, Open) { + if !obj.counterparty.State.Is(ctx, Open) { return errors.New("counterparty connection state not open") } case Closed: - if !obj.counterparty.state.Is(ctx, CloseTry) { + if !obj.counterparty.State.Is(ctx, CloseTry) { return errors.New("counterparty connection state not closetry") } } - obj.state.Set(ctx, Open) - obj.nextTimeout.Set(ctx, 0) + obj.State.Set(ctx, Open) + obj.NextTimeout.Set(ctx, 0) return nil diff --git a/x/ibc/04-channel/keys.go b/x/ibc/04-channel/keys.go new file mode 100644 index 000000000000..383187d33c44 --- /dev/null +++ b/x/ibc/04-channel/keys.go @@ -0,0 +1,5 @@ +package channel + +func LocalRoot() []byte { + return []byte("ports/") +} diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index f21115e3006c..6b76f7cef4c4 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -7,8 +7,8 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) // Manager is unrestricted @@ -28,97 +28,110 @@ type CounterpartyManager struct { connection connection.CounterpartyManager } -func NewManager(protocol state.Base, connection connection.Manager) Manager { +func NewManager(protocol state.Mapping, connection connection.Manager) Manager { return Manager{ - protocol: state.NewMapping(protocol, []byte("/connection/")), + protocol: protocol.Prefix(LocalRoot()), connection: connection, counterparty: NewCounterpartyManager(protocol.Cdc()), } } func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { - protocol := commitment.NewBase(cdc) + protocol := commitment.NewMapping(cdc, nil) return CounterpartyManager{ - protocol: commitment.NewMapping(protocol, []byte("/connection/")), + protocol: protocol.Prefix(LocalRoot()), connection: connection.NewCounterpartyManager(cdc), } } // CONTRACT: connection and counterparty must be filled by the caller -func (man Manager) object(connid, chanid string) Object { - key := connid + "/channels/" + chanid +func (man Manager) object(portid, chanid string) Object { + key := portid + "/channels/" + chanid return Object{ chanid: chanid, - connid: connid, - channel: man.protocol.Value([]byte(key)), + portid: portid, + Channel: man.protocol.Value([]byte(key)), - available: state.NewBoolean(man.protocol.Value([]byte(key + "/available"))), + Available: man.protocol.Value([]byte(key + "/available")).Boolean(), - seqsend: state.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), - seqrecv: state.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), state.Dec), - packets: state.NewIndexer(man.protocol.Prefix([]byte(key+"/packets/")), state.Dec), + SeqSend: man.protocol.Value([]byte(key + "/nextSequenceSend")).Integer(state.Dec), + SeqRecv: man.protocol.Value([]byte(key + "/nextSequenceRecv")).Integer(state.Dec), + Packets: man.protocol.Prefix([]byte(key + "/packets/")).Indexer(state.Dec), } } -func (man CounterpartyManager) object(connid, chanid string) CounterObject { - key := connid + "/channels/" + chanid +func (man CounterpartyManager) object(portid, chanid string) CounterObject { + key := portid + "/channels/" + chanid return CounterObject{ chanid: chanid, - connid: connid, - channel: man.protocol.Value([]byte(key)), + portid: portid, + Channel: man.protocol.Value([]byte(key)), - available: commitment.NewBoolean(man.protocol.Value([]byte(key + "/available"))), + Available: man.protocol.Value([]byte(key + "/available")).Boolean(), - seqsend: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceSend")), state.Dec), - seqrecv: commitment.NewInteger(man.protocol.Value([]byte(key+"/nextSequenceRecv")), state.Dec), - packets: commitment.NewIndexer(man.protocol.Prefix([]byte(key+"/packets/")), state.Dec), + SeqSend: man.protocol.Value([]byte(key + "/nextSequenceSend")).Integer(state.Dec), + SeqRecv: man.protocol.Value([]byte(key + "/nextSequenceRecv")).Integer(state.Dec), + Packets: man.protocol.Prefix([]byte(key + "/packets/")).Indexer(state.Dec), } } -func (man Manager) create(ctx sdk.Context, connid, chanid string, channel Channel) (obj Object, err error) { - obj = man.object(connid, chanid) +func (man Manager) create(ctx sdk.Context, portid, chanid string, channel Channel) (obj Object, err error) { + obj = man.object(portid, chanid) if obj.exists(ctx) { err = errors.New("channel already exists for the provided id") return } - obj.connection, err = man.connection.Query(ctx, connid) - if err != nil { - return + obj.Channel.Set(ctx, channel) + obj.counterparty = man.counterparty.object(channel.CounterpartyPort, channel.Counterparty) + + for _, hop := range channel.ConnectionHops { + connobj, err := man.connection.Query(ctx, hop) + if err != nil { + return obj, err + } + obj.Connections = append(obj.Connections, connobj) } - obj.channel.Set(ctx, channel) - counterconnid := obj.connection.Connection(ctx).Counterparty - obj.counterparty = man.counterparty.object(counterconnid, channel.Counterparty) - obj.counterparty.connection = man.counterparty.connection.Object(counterconnid) + for _, hop := range channel.CounterpartyHops() { + connobj := man.counterparty.connection.Object(hop) + obj.counterparty.Connections = append(obj.counterparty.Connections, connobj) + } return } // Does not check availability -func (man Manager) query(ctx sdk.Context, connid, chanid string) (obj Object, err error) { - obj = man.object(connid, chanid) +func (man Manager) query(ctx sdk.Context, portid, chanid string) (obj Object, err error) { + obj = man.object(portid, chanid) if !obj.exists(ctx) { err = errors.New("channel not exists for the provided id") return } - obj.connection, err = man.connection.Query(ctx, connid) - if err != nil { - return + + channel := obj.GetChannel(ctx) + obj.counterparty = man.counterparty.object(channel.CounterpartyPort, channel.Counterparty) + for _, hop := range channel.ConnectionHops { + connobj, err := man.connection.Query(ctx, hop) + if err != nil { + return obj, err + } + obj.Connections = append(obj.Connections, connobj) } - counterconnid := obj.connection.Connection(ctx).Counterparty - obj.counterparty = man.counterparty.object(counterconnid, obj.Channel(ctx).Counterparty) - obj.counterparty.connection = man.counterparty.connection.Object(counterconnid) + for _, hop := range channel.CounterpartyHops() { + connobj := man.counterparty.connection.Object(hop) + obj.counterparty.Connections = append(obj.counterparty.Connections, connobj) + } return } -func (man Manager) Query(ctx sdk.Context, connid, chanid string) (obj Object, err error) { - obj, err = man.query(ctx, connid, chanid) - if !obj.Available(ctx) { - err = errors.New("channel not available") +func (man Manager) Query(ctx sdk.Context, portid, chanid string) (obj Object, err error) { + obj, err = man.query(ctx, portid, chanid) + if !obj.Available.Get(ctx) { + err = errors.New("channel not Available") return } return @@ -141,7 +154,7 @@ type PortManager struct { chanid func(string) bool } -func (man PortManager) Create(ctx sdk.Context, connid, chanid string, channel Channel) (Object, error) { +func (man PortManager) Create(ctx sdk.Context, portid, chanid string, channel Channel) (Object, error) { if !man.chanid(chanid) { return Object{}, errors.New("invalid channel id") } @@ -150,15 +163,15 @@ func (man PortManager) Create(ctx sdk.Context, connid, chanid string, channel Ch return Object{}, errors.New("invalid port") } - return man.man.Create(ctx, connid, chanid, channel) + return man.man.Create(ctx, portid, chanid, channel) } -func (man PortManager) Query(ctx sdk.Context, connid, chanid string) (Object, error) { +func (man PortManager) Query(ctx sdk.Context, portid, chanid string) (Object, error) { if !man.chanid(chanid) { return Object{}, errors.New("invalid channel id") } - obj, err := man.man.Query(ctx, connid, chanid) + obj, err := man.man.Query(ctx, portid, chanid) if err != nil { return Object{}, err } @@ -173,105 +186,97 @@ func (man PortManager) Query(ctx sdk.Context, connid, chanid string) (Object, er type Object struct { chanid string - connid string + portid string - channel state.Value + Channel state.Value - seqsend state.Integer - seqrecv state.Integer - packets state.Indexer + SeqSend state.Integer + SeqRecv state.Integer + Packets state.Indexer - available state.Boolean + Available state.Boolean - connection connection.Object + Connections []connection.Object counterparty CounterObject } type CounterObject struct { - chanid string - connid string - channel commitment.Value + chanid string + portid string + + Channel commitment.Value - seqsend commitment.Integer - seqrecv commitment.Integer - packets commitment.Indexer + SeqSend commitment.Integer + SeqRecv commitment.Integer + Packets commitment.Indexer - available commitment.Boolean + Available commitment.Boolean + + Connections []connection.CounterObject +} - connection connection.CounterObject +func (obj Object) OriginConnection() connection.Object { + return obj.Connections[0] } func (obj Object) Context(ctx sdk.Context, proofs []commitment.Proof) (sdk.Context, error) { - return obj.connection.Context(ctx, nil, proofs) + return obj.OriginConnection().Context(ctx, nil, proofs) } func (obj Object) ChanID() string { return obj.chanid } -func (obj Object) Channel(ctx sdk.Context) (res Channel) { - obj.channel.Get(ctx, &res) - return -} - -func (obj Object) Value(ctx sdk.Context) (res Channel) { - obj.channel.Get(ctx, &res) +func (obj Object) GetChannel(ctx sdk.Context) (res Channel) { + obj.Channel.Get(ctx, &res) return } -func (obj Object) Available(ctx sdk.Context) bool { - return obj.available.Get(ctx) +func (obj Object) PacketCommit(ctx sdk.Context, index uint64) []byte { + return obj.Packets.Value(index).GetRaw(ctx) } +/* func (obj Object) Sendable(ctx sdk.Context) bool { - // TODO: sendable/receivable should be also defined for channels - return obj.connection.Sendable(ctx) + return obj.connection } func (obj Object) Receivable(ctx sdk.Context) bool { - return obj.connection.Receivable(ctx) -} - -func (obj Object) SeqSend(ctx sdk.Context) uint64 { - return obj.seqsend.Get(ctx) + return kinds[obj.kind.Get(ctx)].Receivable } - -func (obj Object) SeqRecv(ctx sdk.Context) uint64 { - return obj.seqrecv.Get(ctx) -} - -func (obj Object) PacketCommit(ctx sdk.Context, index uint64) []byte { - return obj.packets.Value(index).GetRaw(ctx) -} - +*/ func (obj Object) exists(ctx sdk.Context) bool { - return obj.channel.Exists(ctx) + return obj.Channel.Exists(ctx) } func (obj Object) Send(ctx sdk.Context, packet Packet) error { - if !obj.Sendable(ctx) { - return errors.New("cannot send packets on this channel") - } + /* + if !obj.Sendable(ctx) { + return errors.New("cannot send Packets on this channel") + } + */ - if obj.connection.Client().ConsensusState(ctx).GetHeight() >= packet.Timeout() { + if obj.OriginConnection().Client.GetConsensusState(ctx).GetHeight() >= packet.Timeout() { return errors.New("timeout height higher than the latest known") } - obj.packets.Set(ctx, obj.seqsend.Incr(ctx), packet) + obj.Packets.Set(ctx, obj.SeqSend.Incr(ctx), packet) return nil } -func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, connid, chanid string, packet Packet) error { - obj, err := man.Query(ctx, connid, chanid) +func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, portid, chanid string, packet Packet) error { + obj, err := man.Query(ctx, portid, chanid) if err != nil { return err } - if !obj.Receivable(ctx) { - return errors.New("cannot receive packets on this channel") - } + /* + if !obj.Receivable(ctx) { + return errors.New("cannot receive Packets on this channel") + } + */ ctx, err = obj.Context(ctx, proofs) if err != nil { @@ -285,7 +290,7 @@ func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, connid, c // XXX: increment should happen before verification, reflect on the spec // TODO: packet should be custom marshalled - if !obj.counterparty.packets.Value(obj.seqrecv.Incr(ctx)).Is(ctx, packet) { + if !obj.counterparty.Packets.Value(obj.SeqRecv.Incr(ctx)).Is(ctx, packet) { return errors.New("verification failed") } diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go index 6463d6db0c2d..82d27dca8089 100644 --- a/x/ibc/04-channel/tests/channel_test.go +++ b/x/ibc/04-channel/tests/channel_test.go @@ -5,11 +5,11 @@ import ( "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" tmclient "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" - "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + tendermint "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -62,6 +62,6 @@ func TestPacket(t *testing.T) { node.Counterparty.UpdateClient(t, header) cliobj := node.CLIObject() - _, ppacket := node.Query(t, cliobj.PacketCommitKey(1)) + _, ppacket := node.QueryValue(t, cliobj.Packets.Value(1)) node.Counterparty.Receive(t, MyPacket{"ping"}, ppacket) } diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index daa17e526bb3..651a3665827a 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -9,10 +9,10 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/tests" - "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + tendermint "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/tests" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type Node struct { @@ -39,15 +39,17 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { } res.Channel = channel.Channel{ - Port: "", // TODO + Port: res.Name, Counterparty: res.Counterparty.Name, - CounterpartyPort: "", //TODO + CounterpartyPort: res.Counterparty.Name, + ConnectionHops: []string{res.Name}, } res.Counterparty.Channel = channel.Channel{ - Port: "", // TODO + Port: res.Counterparty.Name, Counterparty: res.Name, - CounterpartyPort: "", // TODO + CounterpartyPort: res.Name, + ConnectionHops: []string{res.Counterparty.Name}, } return res @@ -55,21 +57,21 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Context, channel.Handshaker) { ctx := node.Context() - store, err := commitment.NewStore(node.Counterparty.Root(), node.Counterparty.Path, proofs) + store, err := commitment.NewStore(node.Counterparty.Root(), node.Counterparty.Path(), proofs) require.NoError(t, err) ctx = commitment.WithStore(ctx, store) man := node.Manager() return ctx, channel.NewHandshaker(man) } -func (node *Node) CLIObject() channel.CLIHandshakeObject { +func (node *Node) CLIObject() channel.HandshakeObject { man := node.Manager() - return channel.NewHandshaker(man).CLIObject(node.Path, node.Name, node.Name, node.Name) + return channel.NewHandshaker(man).CLIObject(node.Name, node.Name, []string{node.Counterparty.Name, node.Name}) } -func base(cdc *codec.Codec, key sdk.StoreKey) (state.Base, state.Base) { - protocol := state.NewBase(cdc, key, []byte("protocol")) - free := state.NewBase(cdc, key, []byte("free")) +func base(cdc *codec.Codec, key sdk.StoreKey) (state.Mapping, state.Mapping) { + protocol := state.NewMapping(key, cdc, []byte("protocol/")) + free := state.NewMapping(key, cdc, []byte("free")) return protocol, free } @@ -83,18 +85,18 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenInit(ctx, node.Name, node.Name, node.Channel, 100) // TODO: test timeout require.NoError(t, err) - require.Equal(t, channel.Init, obj.State(ctx)) - require.Equal(t, node.Channel, obj.Channel(ctx)) - require.False(t, obj.Available(ctx)) + require.Equal(t, channel.Init, obj.State.Get(ctx)) + require.Equal(t, node.Channel, obj.GetChannel(ctx)) + require.False(t, obj.Available.Get(ctx)) } func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenTry(ctx, proofs, node.Name, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) - require.Equal(t, channel.OpenTry, obj.State(ctx)) - require.Equal(t, node.Channel, obj.Channel(ctx)) - require.False(t, obj.Available(ctx)) + require.Equal(t, channel.OpenTry, obj.State.Get(ctx)) + require.Equal(t, node.Channel, obj.GetChannel(ctx)) + require.False(t, obj.Available.Get(ctx)) node.SetState(channel.OpenTry) } @@ -102,9 +104,9 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenAck(ctx, proofs, node.Name, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) - require.Equal(t, channel.Open, obj.State(ctx)) - require.Equal(t, node.Channel, obj.Channel(ctx)) - require.True(t, obj.Available(ctx)) + require.Equal(t, channel.Open, obj.State.Get(ctx)) + require.Equal(t, node.Channel, obj.GetChannel(ctx)) + require.True(t, obj.Available.Get(ctx)) node.SetState(channel.Open) } @@ -112,9 +114,9 @@ func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenConfirm(ctx, proofs, node.Name, node.Name, 100 /*TODO*/) require.NoError(t, err) - require.Equal(t, channel.Open, obj.State(ctx)) - require.Equal(t, node.Channel, obj.Channel(ctx)) - require.True(t, obj.Available(ctx)) + require.Equal(t, channel.Open, obj.State.Get(ctx)) + require.Equal(t, node.Channel, obj.GetChannel(ctx)) + require.True(t, obj.Available.Get(ctx)) node.SetState(channel.CloseTry) } @@ -128,26 +130,26 @@ func (node *Node) Handshake(t *testing.T) { // counterparty.OpenTry node.Counterparty.UpdateClient(t, header) cliobj := node.CLIObject() - _, pchan := node.Query(t, cliobj.ChannelKey) - _, pstate := node.Query(t, cliobj.StateKey) - _, ptimeout := node.Query(t, cliobj.TimeoutKey) + _, pchan := node.QueryValue(t, cliobj.Channel) + _, pstate := node.QueryValue(t, cliobj.State) + _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) node.Counterparty.OpenTry(t, pchan, pstate, ptimeout) header = node.Counterparty.Commit() // self.OpenAck node.UpdateClient(t, header) cliobj = node.Counterparty.CLIObject() - _, pchan = node.Counterparty.Query(t, cliobj.ChannelKey) - _, pstate = node.Counterparty.Query(t, cliobj.StateKey) - _, ptimeout = node.Counterparty.Query(t, cliobj.TimeoutKey) + _, pchan = node.Counterparty.QueryValue(t, cliobj.Channel) + _, pstate = node.Counterparty.QueryValue(t, cliobj.State) + _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) node.OpenAck(t, pchan, pstate, ptimeout) header = node.Commit() // counterparty.OpenConfirm node.Counterparty.UpdateClient(t, header) cliobj = node.CLIObject() - _, pstate = node.Query(t, cliobj.StateKey) - _, ptimeout = node.Query(t, cliobj.TimeoutKey) + _, pstate = node.QueryValue(t, cliobj.State) + _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) node.Counterparty.OpenConfirm(t, pstate, ptimeout) } @@ -155,10 +157,10 @@ func (node *Node) Send(t *testing.T, packet channel.Packet) { ctx, man := node.Context(), node.Manager() obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) - seq := obj.SeqSend(ctx) + seq := obj.SeqSend.Get(ctx) err = obj.Send(ctx, packet) require.NoError(t, err) - require.Equal(t, seq+1, obj.SeqSend(ctx)) + require.Equal(t, seq+1, obj.SeqSend.Get(ctx)) require.Equal(t, node.Cdc.MustMarshalBinaryBare(packet), obj.PacketCommit(ctx, seq+1)) } @@ -166,8 +168,8 @@ func (node *Node) Receive(t *testing.T, packet channel.Packet, proofs ...commitm ctx, man := node.Context(), node.Manager() obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) - seq := obj.SeqRecv(ctx) + seq := obj.SeqRecv.Get(ctx) err = man.Receive(ctx, proofs, node.Name, node.Name, packet) require.NoError(t, err) - require.Equal(t, seq+1, obj.SeqRecv(ctx)) + require.Equal(t, seq+1, obj.SeqRecv.Get(ctx)) } diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index 891bea6f9985..fe25a08dfc5f 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -24,4 +24,13 @@ type Channel struct { Port string Counterparty string CounterpartyPort string + ConnectionHops []string +} + +func (ch Channel) CounterpartyHops() (res []string) { + res = make([]string, len(ch.ConnectionHops)) + for i, hop := range ch.ConnectionHops { + res[len(res)-(i+1)] = hop + } + return } diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index cf76caac4b39..923a065334ea 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -3,6 +3,7 @@ package commitment import ( "bytes" "errors" + "fmt" ) // Store proves key-value pairs' inclusion or non-inclusion with @@ -25,7 +26,6 @@ func NewPrefix(store Store, pref []byte) prefix { } } - func (prefix prefix) Prove(key, value []byte) bool { return prefix.store.Prove(join(prefix.prefix, key), value) } @@ -80,6 +80,7 @@ func (store *store) Prove(key, value []byte) bool { } proof, ok := store.proofs[string(key)] if !ok { + fmt.Println(111, string(key)) return false } err := proof.Verify(store.root, store.path, value) @@ -91,7 +92,6 @@ func (store *store) Prove(key, value []byte) bool { return true } - // Proven() returns true if the key-value pair is already proven func (store *store) Proven(key []byte) bool { _, ok := store.Get(key) diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index 18e1a19c2a9e..947d322c06bd 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -1,7 +1,6 @@ package commitment import ( - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" @@ -40,7 +39,7 @@ type Indexer struct { enc state.IntEncoding } -func NewIndexer(m Mapping, enc state.IntEncoding) Indexer { +func (m Mapping) Indexer(enc state.IntEncoding) Indexer { return Indexer{ Mapping: m, enc: enc, From 7a863d7dcba04c445e17a0d6f133b644b358ba41 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 15 Aug 2019 20:22:47 +0900 Subject: [PATCH 147/182] comment out client --- x/ibc/04-channel/client/cli/query.go | 47 ++++++++------------------ x/ibc/04-channel/client/cli/tx.go | 50 ++++++++++------------------ 2 files changed, 31 insertions(+), 66 deletions(-) diff --git a/x/ibc/04-channel/client/cli/query.go b/x/ibc/04-channel/client/cli/query.go index 6f11957f7ab3..d50573cdc724 100644 --- a/x/ibc/04-channel/client/cli/query.go +++ b/x/ibc/04-channel/client/cli/query.go @@ -1,38 +1,17 @@ package cli -import ( - "fmt" - "strconv" - - "github.com/spf13/cobra" - "github.com/spf13/viper" - - cli "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/state" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/cosmos-sdk/x/ibc" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" - "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" - "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" -) - const ( FlagProve = "prove" ) -func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, connid, chanid string) channel.CLIObject { - prefix := []byte(strconv.FormatInt(version, 10) + "/") - path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) - base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) +// TODO +/* +func object(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string, connids []string) channel.Object { + base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) connman := connection.NewManager(base, climan) man := channel.NewManager(base, connman) - return man.CLIQuery(ctx, path, connid, chanid) + return man.CLIObject(portid, chanid, connids) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -44,17 +23,17 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { } ibcQueryCmd.AddCommand(cli.GetCommands( - GetCmdQueryChannel(storeKey, cdc), + // GetCmdQueryChannel(storeKey, cdc), )...) return ibcQueryCmd } -func QueryChannel(ctx context.CLIContext, obj channel.CLIObject, prove bool) (res utils.JSONObject, err error) { - conn, connp, err := obj.Channel(ctx) +func QueryChannel(ctx context.CLIContext, obj channel.Object, prove bool) (res utils.JSONObject, err error) { + conn, connp, err := obj.ChannelCLI(ctx) if err != nil { return } - avail, availp, err := obj.Available(ctx) + avail, availp, err := obj.AvailableCLI(ctx) if err != nil { return } @@ -63,13 +42,13 @@ func QueryChannel(ctx context.CLIContext, obj channel.CLIObject, prove bool) (re if err != nil { return } - */ - seqsend, seqsendp, err := obj.SeqSend(ctx) + + seqsend, seqsendp, err := obj.SeqSendCLI(ctx) if err != nil { return } - seqrecv, seqrecvp, err := obj.SeqRecv(ctx) + seqrecv, seqrecvp, err := obj.SeqRecvCLI(ctx) if err != nil { return } @@ -92,6 +71,7 @@ func QueryChannel(ctx context.CLIContext, obj channel.CLIObject, prove bool) (re ), nil } + func GetCmdQueryChannel(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "connection", @@ -115,3 +95,4 @@ func GetCmdQueryChannel(storeKey string, cdc *codec.Codec) *cobra.Command { return cmd } +*/ diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index 7f67c9902cb2..c166bda866db 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -1,28 +1,5 @@ package cli -import ( - "io/ioutil" - "strconv" - "time" - - "github.com/spf13/cobra" - "github.com/spf13/viper" - - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/state" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" - "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" -) - /* func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -35,14 +12,14 @@ const ( FlagFrom2 = "from2" ) -func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, version int64, connid, chanid string) channel.CLIHandshakeObject { - prefix := []byte(strconv.FormatInt(version, 10) + "/") - path := merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) - base := state.NewBase(cdc, sdk.NewKVStoreKey(storeKey), prefix) +// TODO +/* +func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.HandshakeObject, error) { + base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) connman := connection.NewManager(base, climan) man := channel.NewHandshaker(channel.NewManager(base, connman)) - return man.CLIQuery(ctx, path, connid, chanid) + return man.CLIQuery(ctx, portid, chanid) } func lastheight(ctx context.CLIContext) (uint64, error) { @@ -88,7 +65,10 @@ func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - obj1 := handshake(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) + obj1, err := handshake(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) + if err != nil { + return err + } conn2id := args[3] chan2id := args[4] @@ -101,7 +81,10 @@ func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - obj2 := handshake(ctx2, cdc, storeKey, ibc.Version, conn1id, chan1id) + obj2, err := handshake(ctx2, cdc, storeKey, ibc.Version, conn1id, chan1id) + if err != nil { + return err + } // TODO: check state and if not Idle continue existing process height, err := lastheight(ctx2) @@ -128,15 +111,15 @@ func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } nextTimeout = height + 1000 - _, pconn, err := obj1.Channel(ctx1) + _, pconn, err := obj1.ChannelCLI(ctx1) if err != nil { return err } - _, pstate, err := obj1.State(ctx1) + _, pstate, err := obj1.StateCLI(ctx1) if err != nil { return err } - _, ptimeout, err := obj1.NextTimeout(ctx1) + _, ptimeout, err := obj1.NextTimeoutCLI(ctx1) if err != nil { return err } @@ -298,3 +281,4 @@ func relay(cdc *codec.Codec, ctxFrom, ctxTo context.CLIContext, objFrom, objTo c return nil } +*/ From 17f18d735e10b733495c7fc2c495230a5ff4aae9 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 15 Aug 2019 20:42:09 +0900 Subject: [PATCH 148/182] merge from ics04 branch --- x/ibc/02-client/cli.go | 15 ++-- x/ibc/02-client/client/cli/query.go | 8 +-- x/ibc/02-client/keys.go | 5 ++ x/ibc/02-client/manager.go | 4 +- x/ibc/02-client/tendermint/codec.go | 1 - .../tendermint/tests/tendermint_test.go | 8 +-- x/ibc/02-client/tendermint/tests/types.go | 71 +++++++++++-------- x/ibc/02-client/tendermint/tests/utils.go | 8 +++ 8 files changed, 74 insertions(+), 46 deletions(-) create mode 100644 x/ibc/02-client/keys.go create mode 100644 x/ibc/02-client/tendermint/tests/utils.go diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index aa563f3c170b..db03c1441329 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -1,20 +1,25 @@ package client import ( + "bytes" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func (obj Object) ConsensusStateCLI(ctx context.CLIContext, path merkle.Path) (res ConsensusState, proof merkle.Proof, err error) { +func (obj Object) prefix() []byte { + return bytes.Split(obj.ConsensusState.KeyBytes(), LocalRoot())[0] +} + +func (obj Object) ConsensusStateCLI(ctx context.CLIContext) (res ConsensusState, proof merkle.Proof, err error) { tmproof, err := obj.ConsensusState.Query(ctx, &res) - proof = merkle.NewProofFromValue(tmproof, path, obj.ConsensusState) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.ConsensusState) return } -func (obj Object) FrozenCLI(ctx context.CLIContext, path merkle.Path) (res bool, proof merkle.Proof, err error) { +func (obj Object) FrozenCLI(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { res, tmproof, err := obj.Frozen.Query(ctx) - proof = merkle.NewProofFromValue(tmproof, path, obj.Frozen) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Frozen) return } - diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 1cf445dae389..c4238dae8cdb 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -20,9 +20,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func mapping(cdc *codec.Codec, storeKey string, version int64) (state.Mapping, merkle.Path) { +func mapping(cdc *codec.Codec, storeKey string, version int64) state.Mapping { prefix := []byte(strconv.FormatInt(version, 10) + "/") - return state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix), merkle.NewPath([][]byte{[]byte(storeKey)}, prefix) + return state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -48,11 +48,11 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - mapp, path := mapping(cdc, storeKey, ibc.Version) + mapp := mapping(cdc, storeKey, ibc.Version) man := client.NewManager(mapp) id := args[0] - state, _, err := man.Object(id).ConsensusStateCLI(ctx, path) + state, _, err := man.Object(id).ConsensusStateCLI(ctx) if err != nil { return err } diff --git a/x/ibc/02-client/keys.go b/x/ibc/02-client/keys.go new file mode 100644 index 000000000000..a67761f20d36 --- /dev/null +++ b/x/ibc/02-client/keys.go @@ -0,0 +1,5 @@ +package client + +func LocalRoot() []byte { + return []byte("client/") +} diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index fe69a59caa05..eb9a83ff7d2e 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -17,7 +17,7 @@ type Manager struct { func NewManager(base state.Mapping) Manager { return Manager{ - protocol: base.Prefix([]byte("/client")), + protocol: base.Prefix(LocalRoot()), } } @@ -27,7 +27,7 @@ type CounterpartyManager struct { func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { return CounterpartyManager{ - protocol: commitment.NewMapping(cdc, []byte("/client")), + protocol: commitment.NewMapping(cdc, LocalRoot()), } } diff --git a/x/ibc/02-client/tendermint/codec.go b/x/ibc/02-client/tendermint/codec.go index eca3b38917fa..31a25031f9fc 100644 --- a/x/ibc/02-client/tendermint/codec.go +++ b/x/ibc/02-client/tendermint/codec.go @@ -2,7 +2,6 @@ package tendermint import ( "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" ) diff --git a/x/ibc/02-client/tendermint/tests/tendermint_test.go b/x/ibc/02-client/tendermint/tests/tendermint_test.go index 61a0944fbaa0..e7d09644126a 100644 --- a/x/ibc/02-client/tendermint/tests/tendermint_test.go +++ b/x/ibc/02-client/tendermint/tests/tendermint_test.go @@ -4,16 +4,14 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) func testUpdate(t *testing.T, interval int, ok bool) { - node := NewNode(NewMockValidators(100, 10), newPath()) + node := NewNode(NewMockValidators(100, 10), "f8wib", []byte{0x98, 0x78}) - header := node.Commit() + _ = node.Commit() - verifier := node.LastStateVerifier(merkle.NewRoot(header.AppHash)) + verifier := node.LastStateVerifier() for i := 0; i < 100; i++ { header := node.Commit() diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 40caa5d6f041..027d3a28a5f5 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -3,6 +3,7 @@ package tendermint import ( "crypto/rand" "testing" + "bytes" "github.com/stretchr/testify/require" @@ -23,15 +24,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -// nolint: unused -func newPath() merkle.Path { - return merkle.NewPath([][]byte{[]byte("test")}, []byte{0x12, 0x34}) -} - const chainid = "testchain" -func defaultComponents() (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { - key := sdk.NewKVStoreKey("test") +func defaultComponents(storename string) (sdk.StoreKey, sdk.Context, stypes.CommitMultiStore, *codec.Codec) { + key := sdk.NewKVStoreKey(storename) + db := dbm.NewMemDB() cms := store.NewCommitMultiStore(db) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) @@ -54,21 +51,28 @@ type Node struct { Commits []tmtypes.SignedHeader - Path merkle.Path + StoreName string + Prefix []byte } -func NewNode(valset MockValidators, path merkle.Path) *Node { - key, ctx, cms, _ := defaultComponents() +func NewNode(valset MockValidators, storeName string, prefix []byte) *Node { + key, ctx, cms, _ := defaultComponents(storeName) + return &Node{ Valset: valset, Cms: cms, Key: key, Store: ctx.KVStore(key), Commits: nil, - Path: path, + StoreName: storeName, + Prefix: prefix, } } +func (node *Node) Path() merkle.Path { + return merkle.NewPath([][]byte{[]byte(node.StoreName)}, node.Prefix) +} + func (node *Node) Last() tmtypes.SignedHeader { if len(node.Commits) == 0 { return tmtypes.SignedHeader{} @@ -76,7 +80,7 @@ func (node *Node) Last() tmtypes.SignedHeader { return node.Commits[len(node.Commits)-1] } -func (node *Node) Commit() tmtypes.SignedHeader { +func (node *Node) Commit() tendermint.Header { valsethash := node.Valset.ValidatorSet().Hash() nextvalset := node.Valset.Mutate() nextvalsethash := nextvalset.ValidatorSet().Hash() @@ -100,11 +104,20 @@ func (node *Node) Commit() tmtypes.SignedHeader { node.Valset = nextvalset node.Commits = append(node.Commits, commit) - return commit + return tendermint.Header{ + SignedHeader: commit, + ValidatorSet: node.PrevValset.ValidatorSet(), + NextValidatorSet: node.Valset.ValidatorSet(), + } +} + +func (node *Node) LastStateVerifier() *Verifier { + return NewVerifier(node.Last(), node.Valset, node.Root()) } -func (node *Node) LastStateVerifier(root merkle.Root) *Verifier { - return NewVerifier(node.Last(), node.Valset, root) +func (node *Node) Root() merkle.Root { + return merkle.NewRoot(node.Last().AppHash) + } func (node *Node) Context() sdk.Context { @@ -126,14 +139,8 @@ func NewVerifier(header tmtypes.SignedHeader, nextvalset MockValidators, root me } } -func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset MockValidators) error { - newcs, err := v.ConsensusState.Validate( - tendermint.Header{ - SignedHeader: header, - ValidatorSet: valset.ValidatorSet(), - NextValidatorSet: nextvalset.ValidatorSet(), - }, - ) +func (v *Verifier) Validate(header tendermint.Header, valset, nextvalset MockValidators) error { + newcs, err := v.ConsensusState.Validate(header) if err != nil { return err } @@ -142,19 +149,23 @@ func (v *Verifier) Validate(header tmtypes.SignedHeader, valset, nextvalset Mock return nil } -func (node *Node) Query(t *testing.T, path merkle.Path, k []byte) ([]byte, commitment.Proof) { - value, proof, err := merkle.QueryMultiStore(node.Cms, path, k) + +func (node *Node) Query(t *testing.T, k []byte) ([]byte, commitment.Proof) { + if bytes.HasPrefix(k, node.Prefix) { + k = bytes.TrimPrefix(k, node.Prefix) + } + value, proof, err := merkle.QueryMultiStore(node.Cms, node.StoreName, node.Prefix, k) require.NoError(t, err) return value, proof } func (node *Node) Set(k, value []byte) { - node.Store.Set(node.Path.Key(k), value) + node.Store.Set(join(node.Prefix, k), value) } // nolint:deadcode,unused func testProof(t *testing.T) { - node := NewNode(NewMockValidators(100, 10), newPath()) + node := NewNode(NewMockValidators(100, 10), "1", []byte{0x00, 0x01}) node.Commit() @@ -170,15 +181,17 @@ func testProof(t *testing.T) { kvps = append(kvps, cmn.KVPair{Key: k, Value: v}) node.Set(k, v) } + header := node.Commit() proofs := []commitment.Proof{} root := merkle.NewRoot(header.AppHash) for _, kvp := range kvps { - v, p := node.Query(t, node.Path, kvp.Key) + v, p := node.Query(t, kvp.Key) + require.Equal(t, kvp.Value, v) proofs = append(proofs, p) } - cstore, err := commitment.NewStore(root, node.Path, proofs) + cstore, err := commitment.NewStore(root, node.Path(), proofs) require.NoError(t, err) for _, kvp := range kvps { diff --git a/x/ibc/02-client/tendermint/tests/utils.go b/x/ibc/02-client/tendermint/tests/utils.go new file mode 100644 index 000000000000..d5262a14a29b --- /dev/null +++ b/x/ibc/02-client/tendermint/tests/utils.go @@ -0,0 +1,8 @@ +package tendermint + +func join(a, b []byte) (res []byte) { + res = make([]byte, len(a)+len(b)) + copy(res, a) + copy(res[len(a):], b) + return +} From e1abf4950923de7ed47e37a2246cb6b12e152685 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 15 Aug 2019 20:47:07 +0900 Subject: [PATCH 149/182] merge from ics04 branch --- x/ibc/03-connection/cli.go | 2 - x/ibc/03-connection/manager.go | 4 +- x/ibc/03-connection/tests/connection_test.go | 39 +------------------ x/ibc/03-connection/tests/types.go | 41 ++++++++++++++++++++ 4 files changed, 45 insertions(+), 41 deletions(-) diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 769792c16358..2a6c65d7c824 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -14,8 +14,6 @@ func (man Manager) CLIObject(connid, clientid string) Object { return obj } - - func (obj Object) prefix() []byte { return bytes.Split(obj.Connection.KeyBytes(), LocalRoot())[0] } diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index cc5da97a1386..f4e4d6432c29 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -133,7 +133,7 @@ func (obj Object) Sendable(ctx sdk.Context) bool { return kinds[obj.Kind.Get(ctx)].Sendable } -func (obj Object) Receivble(ctx sdk.Context) bool { +func (obj Object) Receivable(ctx sdk.Context) bool { return kinds[obj.Kind.Get(ctx)].Receivable } @@ -164,6 +164,7 @@ func (man Manager) create(ctx sdk.Context, id string, connection Connection, kin obj.Connection.Set(ctx, connection) obj.Kind.Set(ctx, kind) return + } // query() is used internally by the connection creators @@ -190,6 +191,7 @@ func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { if !obj.exists(ctx) { err = errors.New("Object not exists") return + } if !obj.Available.Get(ctx) { err = errors.New("Object not available") diff --git a/x/ibc/03-connection/tests/connection_test.go b/x/ibc/03-connection/tests/connection_test.go index 665f15b3142d..62a8e52fbf85 100644 --- a/x/ibc/03-connection/tests/connection_test.go +++ b/x/ibc/03-connection/tests/connection_test.go @@ -25,42 +25,5 @@ func TestHandshake(t *testing.T) { registerCodec(cdc) node := NewNode(tendermint.NewMockValidators(100, 10), tendermint.NewMockValidators(100, 10), cdc) - node.Commit() - node.Counterparty.Commit() - - node.CreateClient(t) - node.Counterparty.CreateClient(t) - - // self.OpenInit - node.OpenInit(t) - header := node.Commit() - - // counterparty.OpenTry - node.Counterparty.UpdateClient(t, header) - cliobj := node.CLIObject() - _, pconn := node.QueryValue(t, cliobj.Connection) - _, pstate := node.QueryValue(t, cliobj.State) - _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) - _, pcounterclient := node.QueryValue(t, cliobj.CounterpartyClient) - // TODO: implement consensus state checking - // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) - node.Counterparty.OpenTry(t, pconn, pstate, ptimeout, pcounterclient) - header = node.Counterparty.Commit() - - // self.OpenAck - node.UpdateClient(t, header) - cliobj = node.Counterparty.CLIObject() - _, pconn = node.Counterparty.QueryValue(t, cliobj.Connection) - _, pstate = node.Counterparty.QueryValue(t, cliobj.State) - _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) - _, pcounterclient = node.Counterparty.QueryValue(t, cliobj.CounterpartyClient) - node.OpenAck(t, pconn, pstate, ptimeout, pcounterclient) - header = node.Commit() - - // counterparty.OpenConfirm - node.Counterparty.UpdateClient(t, header) - cliobj = node.CLIObject() - _, pstate = node.QueryValue(t, cliobj.State) - _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) - node.Counterparty.OpenConfirm(t, pstate, ptimeout) + node.Handshake(t) } diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 29b7b0706721..9fbd375aa4b3 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -149,3 +149,44 @@ func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { require.True(t, obj.Available.Get(ctx)) node.SetState(connection.CloseTry) } + +func (node *Node) Handshake(t *testing.T) { + node.Commit() + node.Counterparty.Commit() + + node.CreateClient(t) + node.Counterparty.CreateClient(t) + + // self.OpenInit + node.OpenInit(t) + header := node.Commit() + + // counterparty.OpenTry + node.Counterparty.UpdateClient(t, header) + cliobj := node.CLIObject() + _, pconn := node.QueryValue(t, cliobj.Connection) + _, pstate := node.QueryValue(t, cliobj.State) + _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) + _, pcounterclient := node.QueryValue(t, cliobj.CounterpartyClient) + // TODO: implement consensus state checking + // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) + node.Counterparty.OpenTry(t, pconn, pstate, ptimeout, pcounterclient) + header = node.Counterparty.Commit() + + // self.OpenAck + node.UpdateClient(t, header) + cliobj = node.Counterparty.CLIObject() + _, pconn = node.Counterparty.QueryValue(t, cliobj.Connection) + _, pstate = node.Counterparty.QueryValue(t, cliobj.State) + _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) + _, pcounterclient = node.Counterparty.QueryValue(t, cliobj.CounterpartyClient) + node.OpenAck(t, pconn, pstate, ptimeout, pcounterclient) + header = node.Commit() + + // counterparty.OpenConfirm + node.Counterparty.UpdateClient(t, header) + cliobj = node.CLIObject() + _, pstate = node.QueryValue(t, cliobj.State) + _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) + node.Counterparty.OpenConfirm(t, pstate, ptimeout) +} From df2b7fe2d7502521b28b47df55686a26596f37b6 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 15 Aug 2019 21:15:38 +0900 Subject: [PATCH 150/182] add port --- x/ibc/04-channel/manager.go | 10 +++++++++- x/ibc/04-channel/port.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 x/ibc/04-channel/port.go diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 6b76f7cef4c4..b5e2507ea9c9 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -20,6 +20,8 @@ type Manager struct { counterparty CounterpartyManager router Router + + ports map[string]struct{} } type CounterpartyManager struct { @@ -33,6 +35,8 @@ func NewManager(protocol state.Mapping, connection connection.Manager) Manager { protocol: protocol.Prefix(LocalRoot()), connection: connection, counterparty: NewCounterpartyManager(protocol.Cdc()), + + ports: make(map[string]struct{}), } } @@ -250,12 +254,16 @@ func (obj Object) exists(ctx sdk.Context) bool { return obj.Channel.Exists(ctx) } -func (obj Object) Send(ctx sdk.Context, packet Packet) error { +func (man Manager) Send(ctx sdk.Context, portid, chanid string, packet Packet) error { /* if !obj.Sendable(ctx) { return errors.New("cannot send Packets on this channel") } */ + obj, err := man.Query(ctx, portid, chanid) + if err != nil { + return err + } if obj.OriginConnection().Client.GetConsensusState(ctx).GetHeight() >= packet.Timeout() { return errors.New("timeout height higher than the latest known") diff --git a/x/ibc/04-channel/port.go b/x/ibc/04-channel/port.go new file mode 100644 index 000000000000..2b3505a50169 --- /dev/null +++ b/x/ibc/04-channel/port.go @@ -0,0 +1,37 @@ +package channel + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +type Port struct { + channel Manager + id string + valid *bool // once invalid forever invalid +} + +// bindPort, expected to be called only at init time +// TODO: is it safe to support runtime bindPort? +func (man Manager) Port(id string) Port { + if _, ok := man.ports[id]; ok { + panic("port already occupied") + } + man.ports[id] = struct{}{} + valid := true + return Port{man, id, &valid} +} + +// releasePort +func (port Port) Release() { + delete(port.channel.ports, port.id) + *port.valid = false +} + +func (port Port) Send(ctx sdk.Context, chanid string, packet Packet) error { + return port.channel.Send(ctx, port.id, chanid, packet) +} + +func (port Port) Receive(ctx sdk.Context, proof []commitment.Proof, chanid string, packet Packet) error { + return port.channel.Receive(ctx, proof, port.id, chanid, packet) +} From 51303fd58454cfdc2e76cb518fafb0dda87756ed Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 15 Aug 2019 21:16:39 +0900 Subject: [PATCH 151/182] fix test --- x/ibc/04-channel/tests/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 651a3665827a..22c8234fbabe 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -158,7 +158,7 @@ func (node *Node) Send(t *testing.T, packet channel.Packet) { obj, err := man.Query(ctx, node.Name, node.Name) require.NoError(t, err) seq := obj.SeqSend.Get(ctx) - err = obj.Send(ctx, packet) + err = man.Send(ctx, node.Name, node.Name, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqSend.Get(ctx)) require.Equal(t, node.Cdc.MustMarshalBinaryBare(packet), obj.PacketCommit(ctx, seq+1)) From c60fd53096e6fd766f69e36e64fe1ac26c263390 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 21 Aug 2019 16:00:06 +0200 Subject: [PATCH 152/182] add mocks --- x/ibc/02-client/client/cli/query.go | 4 +- x/ibc/03-connection/client/cli/query.go | 9 ++-- x/ibc/03-connection/client/cli/tx.go | 12 ++--- x/ibc/04-channel/codec.go | 2 + x/ibc/04-channel/handler.go | 4 +- x/ibc/04-channel/msgs.go | 42 ++++++++-------- x/ibc/04-channel/tests/channel_test.go | 3 +- x/ibc/04-channel/types.go | 12 ++++- x/ibc/ante.go | 64 +++++++++++++++++++++++++ x/ibc/handler.go | 39 +++++++++++++++ x/ibc/mock/packets.go | 63 ++++++++++++++++++++++++ x/ibc/msg.go | 19 ++++++++ x/ibc/types.go | 7 +++ x/ibc/version.go | 9 ---- x/ibc/version/version.go | 13 +++++ 15 files changed, 253 insertions(+), 49 deletions(-) create mode 100644 x/ibc/ante.go create mode 100644 x/ibc/handler.go create mode 100644 x/ibc/mock/packets.go create mode 100644 x/ibc/msg.go create mode 100644 x/ibc/types.go delete mode 100644 x/ibc/version.go create mode 100644 x/ibc/version/version.go diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index c4238dae8cdb..6dd79d353a67 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -14,10 +14,10 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" + "github.com/cosmos/cosmos-sdk/x/ibc/version" ) func mapping(cdc *codec.Codec, storeKey string, version int64) state.Mapping { @@ -48,7 +48,7 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - mapp := mapping(cdc, storeKey, ibc.Version) + mapp := mapping(cdc, storeKey, version.Version) man := client.NewManager(mapp) id := args[0] diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index efc330969faa..c11c1f059a08 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -12,17 +12,16 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/utils" + "github.com/cosmos/cosmos-sdk/x/ibc/version" ) const ( FlagProve = "prove" ) - func object(cdc *codec.Codec, storeKey string, prefix []byte, connid, clientid string) connection.Object { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) @@ -80,7 +79,7 @@ func GetCmdQueryConnection(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - obj := object(cdc, storeKey, ibc.VersionPrefix(ibc.Version), args[0], "") + obj := object(cdc, storeKey, version.Prefix(version.Version), args[0], "") jsonobj, err := QueryConnection(ctx, obj, viper.GetBool(FlagProve)) if err != nil { return err diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 68283021c36e..32df94715bd0 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -13,10 +13,10 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/version" ) /* @@ -80,7 +80,7 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } - obj1, err := handshake(ctx1, cdc, storeKey, ibc.VersionPrefix(ibc.Version), conn1id) + obj1, err := handshake(ctx1, cdc, storeKey, version.DefaultPrefix(), conn1id) if err != nil { return err } @@ -95,7 +95,7 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } - obj2, err := handshake(ctx2, cdc, storeKey, ibc.VersionPrefix(ibc.Version), conn1id) + obj2, err := handshake(ctx2, cdc, storeKey, version.DefaultPrefix(), conn1id) if err != nil { return err } diff --git a/x/ibc/04-channel/codec.go b/x/ibc/04-channel/codec.go index 4da636c4edc7..922009db6bd8 100644 --- a/x/ibc/04-channel/codec.go +++ b/x/ibc/04-channel/codec.go @@ -4,6 +4,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" ) +var msgCdc = codec.New() + func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*Packet)(nil), nil) } diff --git a/x/ibc/04-channel/handler.go b/x/ibc/04-channel/handler.go index 02c2c334fb45..078effaa433c 100644 --- a/x/ibc/04-channel/handler.go +++ b/x/ibc/04-channel/handler.go @@ -38,8 +38,8 @@ func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) s type Handler func(sdk.Context, Packet) sdk.Result -func HandleMsgReceive(ctx sdk.Context, msg MsgReceive, man Manager) sdk.Result { - err := man.Receive(ctx, msg.Proofs, msg.ConnectionID, msg.ChannelID, msg.Packet) +func HandleMsgPacket(ctx sdk.Context, msg MsgPacket, man Manager) sdk.Result { + err := man.Receive(ctx, msg.Proofs, msg.PortID, msg.ChannelID, msg.Packet) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 500, "").Result() } diff --git a/x/ibc/04-channel/msgs.go b/x/ibc/04-channel/msgs.go index ba35f0bbc406..adb53c7e62c0 100644 --- a/x/ibc/04-channel/msgs.go +++ b/x/ibc/04-channel/msgs.go @@ -2,8 +2,7 @@ package channel import ( sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) const Route = "ibc" @@ -133,32 +132,33 @@ func (msg MsgOpenConfirm) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.Signer} } -type MsgReceive struct { - ConnectionID string - ChannelID string - Packet Packet - Proofs []commitment.Proof - Signer sdk.AccAddress +type MsgPacket struct { + Packet `json:"packet" yaml:"packet"` + // PortID, ChannelID can be empty if batched & not first MsgPacket + PortID string `json:"port_id,omitempty" yaml:"port_id"` + ChannelID string `json:"channel_id,omitempty" yaml:"channel_id"` + // Height uint64 // height of the commitment root for the proofs + Proofs []commitment.Proof `json:"proofs" yaml:"proofs"` + Signer sdk.AccAddress `json:"signer,omitempty" yaml:"signer"` } -var _ sdk.Msg = MsgReceive{} +var _ sdk.Msg = MsgPacket{} -func (msg MsgReceive) Route() string { - return Route -} - -func (msg MsgReceive) Type() string { - return "receive" -} - -func (msg MsgReceive) ValidateBasic() sdk.Error { +func (msg MsgPacket) ValidateBasic() sdk.Error { + // Check PortID ChannelID len + // Check packet != nil + // Check proofs != nil + // Signer can be empty return nil // TODO } -func (msg MsgReceive) GetSignBytes() []byte { - return nil // TODO +func (msg MsgPacket) GetSignBytes() []byte { + return msgCdc.MustMarshalJSON(msg) // TODO: Sort } -func (msg MsgReceive) GetSigners() []sdk.AccAddress { +func (msg MsgPacket) GetSigners() []sdk.AccAddress { + if msg.Signer.Empty() { + return []sdk.AccAddress{} + } return []sdk.AccAddress{msg.Signer} } diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go index 82d27dca8089..366eaae8277d 100644 --- a/x/ibc/04-channel/tests/channel_test.go +++ b/x/ibc/04-channel/tests/channel_test.go @@ -36,11 +36,10 @@ type MyPacket struct { Message string } -/* func (packet MyPacket) Commit() []byte { return []byte(packet.Message) } -*/ + func (packet MyPacket) Timeout() uint64 { return 100 // TODO } diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index fe25a08dfc5f..0a95624cf39c 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -1,5 +1,9 @@ package channel +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + /* type Packet struct { Sequence uint64 @@ -15,9 +19,13 @@ type Packet struct { */ type Packet interface { - Timeout() uint64 - // Commit() []byte // Can be a commit message Route() string + Type() string + ValidateBasic() sdk.Error + String() string + Timeout() uint64 + MarshalAmino() (string, error) + MarshalJSON() ([]byte, error) } type Channel struct { diff --git a/x/ibc/ante.go b/x/ibc/ante.go new file mode 100644 index 000000000000..916f4445ce8f --- /dev/null +++ b/x/ibc/ante.go @@ -0,0 +1,64 @@ +package ibc + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" +) + +// TODO: Should extract timeout msgs too +func ExtractMsgPackets(msgs []sdk.Msg) (res []MsgPacket, abort bool) { + res = make([]MsgPacket, 0, len(msgs)) + for _, msg := range msgs { + msgp, ok := msg.(MsgPacket) + if ok { + res = append(res, msgp) + } + } + + if len(res) >= 2 { + first := res[0] + for _, msg := range res[1:] { + if len(msg.PortID) != 0 && msg.PortID != first.PortID { + return res, true + } + msg.PortID = first.PortID + if len(msg.ChannelID) != 0 && msg.ChannelID != first.ChannelID { + return res, true + } + msg.ChannelID = first.ChannelID + } + } + + return +} + +func VerifyMsgPackets(ctx sdk.Context, channel channel.Manager, msgs []MsgPacket) error { + for _, msg := range msgs { + err := channel.Receive(ctx, msg.Proofs, msg.PortID, msg.ChannelID, msg.Packet) + if err != nil { + return err + } + } + + return nil +} + +func NewAnteHandler(channel channel.Manager) sdk.AnteHandler { + return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) { + msgs, abort := ExtractMsgPackets(tx.GetMsgs()) + if abort { + return + } + + // GasMeter already set by auth.AnteHandler + + err := VerifyMsgPackets(ctx, channel, msgs) + if err != nil { + abort = true + return + } + + return ctx, res, false + } +} diff --git a/x/ibc/handler.go b/x/ibc/handler.go new file mode 100644 index 000000000000..9614e00a1c30 --- /dev/null +++ b/x/ibc/handler.go @@ -0,0 +1,39 @@ +package ibc + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// IBC Handler should not return error. Returning error will make the channel +// not able to be proceed. Send receipt packet when the packet is non executable. +type Handler func(ctx sdk.Context, packet Packet) + +/* +type ReturnHandler func(ctx sdk.Context, packet sdk.Packet) sdk.Packet +*/ + +func WrapHandler(h Handler, sdkh sdk.Handler) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + switch msg := msg.(type) { + case MsgPacket: + h(ctx, msg.Packet) + return sdk.Result{Events:ctx.EventManager().Events()} + default: + return sdkh(ctx, msg) + } + } +} + +// TODO +/* +func WrapReturnHandler(h ReturnHandler) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + receipt := h(ctx, msg.Packet) + if receipt != nil { + // Send receipt packet to the receipt channel + } + + return sdk.Result{Events: ctx.EventManager().Events()} + } +} +*/ diff --git a/x/ibc/mock/packets.go b/x/ibc/mock/packets.go new file mode 100644 index 000000000000..5e649b1300e4 --- /dev/null +++ b/x/ibc/mock/packets.go @@ -0,0 +1,63 @@ +package mock + +import ( + "errors" + "fmt" + "strings" + "strconv" + "bytes" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc" +) + +var _ ibc.Packet = SequencePacket{} + +type SequencePacket struct { + Sequence uint64 +} + +func (packet SequencePacket) MarshalAmino() (string, error) { + return fmt.Sprintf("sequence-packet-%d", packet.Sequence), nil +} + +func (packet *SequencePacket) UnmarshalAmino(text string) (err error) { + if !strings.HasPrefix(text, "sequence-packet-") { + return errors.New("invalid SequencePacket string") + } + packet.Sequence, err = strconv.ParseUint(strings.TrimPrefix(text, "sequence-packet-"), 10, 64) + return +} + +func (packet SequencePacket) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf("\"sequence-packet-%d\"", packet.Sequence)), nil +} + +func (packet *SequencePacket) UnmarshalJSON(bz []byte) (err error) { + bz = bz[1:len(bz)-1] + if !bytes.HasPrefix(bz, []byte("sequence-packet-")) { + return errors.New("invalid SequencePacket string") + } + packet.Sequence, err = strconv.ParseUint(strings.TrimPrefix(string(bz), "sequence-packet-"), 10, 64) + return +} + +func (SequencePacket) Route() string { + return "ibc-mock" +} + +func (SequencePacket) String() string { + return "sequence-packet" +} + +func (SequencePacket) Timeout() uint64 { + return 0 +} + +func (SequencePacket) Type() string { + return "empty-packet" +} + +func (SequencePacket) ValidateBasic() sdk.Error { + return nil +} diff --git a/x/ibc/msg.go b/x/ibc/msg.go new file mode 100644 index 000000000000..fc05da83d817 --- /dev/null +++ b/x/ibc/msg.go @@ -0,0 +1,19 @@ +package ibc + +import ( + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" +) + +type MsgCreateClient = client.MsgCreateClient +type MsgUpdateClient = client.MsgUpdateClient +type MsgOpenInitConnection = connection.MsgOpenInit +type MsgOpenTryConnection = connection.MsgOpenTry +type MsgOpenAckConnection = connection.MsgOpenAck +type MsgOpenConfirmConnection = connection.MsgOpenConfirm +type MsgOpenInitChannel = channel.MsgOpenInit +type MsgOpenTryChannel = channel.MsgOpenTry +type MsgOpenAckChannel = channel.MsgOpenAck +type MsgOpenConfirmChannel = channel.MsgOpenConfirm +type MsgPacket = channel.MsgPacket diff --git a/x/ibc/types.go b/x/ibc/types.go new file mode 100644 index 000000000000..5ccf47815198 --- /dev/null +++ b/x/ibc/types.go @@ -0,0 +1,7 @@ +package ibc + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" +) + +type Packet = channel.Packet diff --git a/x/ibc/version.go b/x/ibc/version.go deleted file mode 100644 index b6648efb40c8..000000000000 --- a/x/ibc/version.go +++ /dev/null @@ -1,9 +0,0 @@ -package ibc - -import "strconv" - -const Version int64 = 1 - -func VersionPrefix(version int64) []byte { - return []byte(strconv.FormatInt(version, 10) + "/") -} diff --git a/x/ibc/version/version.go b/x/ibc/version/version.go new file mode 100644 index 000000000000..5c80adf66a24 --- /dev/null +++ b/x/ibc/version/version.go @@ -0,0 +1,13 @@ +package version + +import "strconv" + +const Version int64 = 1 + +func DefaultPrefix() []byte { + return Prefix(Version) +} + +func Prefix(version int64) []byte { + return []byte(strconv.FormatInt(version, 10) + "/") +} From ee9bad2ac9d0566741ae46212badfc73699384a5 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 21 Aug 2019 17:40:14 +0200 Subject: [PATCH 153/182] fix connid -> portid in handshake.go --- x/ibc/04-channel/handshake.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index 48faa877b838..76e372bb929f 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -86,8 +86,8 @@ func (man CounterpartyHandshaker) object(parent CounterObject) CounterHandshakeO } } -func (man Handshaker) create(ctx sdk.Context, connid, chanid string, channel Channel) (obj HandshakeObject, err error) { - cobj, err := man.man.create(ctx, connid, chanid, channel) +func (man Handshaker) create(ctx sdk.Context, portid, chanid string, channel Channel) (obj HandshakeObject, err error) { + cobj, err := man.man.create(ctx, portid, chanid, channel) if err != nil { return } @@ -96,8 +96,8 @@ func (man Handshaker) create(ctx sdk.Context, connid, chanid string, channel Cha return obj, nil } -func (man Handshaker) query(ctx sdk.Context, connid, chanid string) (obj HandshakeObject, err error) { - cobj, err := man.man.query(ctx, connid, chanid) +func (man Handshaker) query(ctx sdk.Context, portid, chanid string) (obj HandshakeObject, err error) { + cobj, err := man.man.query(ctx, portid, chanid) if err != nil { return } @@ -125,7 +125,7 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { // Using proofs: none func (man Handshaker) OpenInit(ctx sdk.Context, - connid, chanid string, channel Channel, nextTimeoutHeight uint64, + portid, chanid string, channel Channel, nextTimeoutHeight uint64, ) (HandshakeObject, error) { // man.Create() will ensure // assert(connectionHops.length === 2) @@ -135,7 +135,7 @@ func (man Handshaker) OpenInit(ctx sdk.Context, return HandshakeObject{}, errors.New("ConnectionHops length must be 1") } - obj, err := man.create(ctx, connid, chanid, channel) + obj, err := man.create(ctx, portid, chanid, channel) if err != nil { return HandshakeObject{}, err } @@ -214,9 +214,9 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenAck(ctx sdk.Context, proofs []commitment.Proof, - connid, chanid string, timeoutHeight, nextTimeoutHeight uint64, + portid, chanid string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { - obj, err = man.query(ctx, connid, chanid) + obj, err = man.query(ctx, portid, chanid) if err != nil { return } @@ -275,8 +275,8 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // Using proofs: counterparty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, proofs []commitment.Proof, - connid, chanid string, timeoutHeight uint64) (obj HandshakeObject, err error) { - obj, err = man.query(ctx, connid, chanid) + portid, chanid string, timeoutHeight uint64) (obj HandshakeObject, err error) { + obj, err = man.query(ctx, portid, chanid) if err != nil { return } From 649ea6e2c184c2279b8c457fcf60e55434be4048 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 26 Aug 2019 16:14:01 +0200 Subject: [PATCH 154/182] add mock --- x/ibc/04-channel/events.go | 10 ++++++ x/ibc/04-channel/handler.go | 11 ------ x/ibc/04-channel/manager.go | 17 +++++++-- x/ibc/04-channel/msgs.go | 8 +++-- x/ibc/04-channel/port.go | 3 ++ x/ibc/04-channel/router.go | 34 ------------------ x/ibc/04-channel/tests/channel_test.go | 40 +++++++++++++++++++-- x/ibc/04-channel/types.go | 8 ++--- x/ibc/ante.go | 8 ++--- x/ibc/handler.go | 39 -------------------- x/ibc/mock/handler.go | 28 +++++++++++++++ x/ibc/mock/keeper.go | 49 ++++++++++++++++++++++++++ x/ibc/mock/packets.go | 12 ++++--- x/ibc/types.go | 4 ++- 14 files changed, 166 insertions(+), 105 deletions(-) create mode 100644 x/ibc/04-channel/events.go delete mode 100644 x/ibc/04-channel/router.go delete mode 100644 x/ibc/handler.go create mode 100644 x/ibc/mock/handler.go create mode 100644 x/ibc/mock/keeper.go diff --git a/x/ibc/04-channel/events.go b/x/ibc/04-channel/events.go new file mode 100644 index 000000000000..f9097af6a3b7 --- /dev/null +++ b/x/ibc/04-channel/events.go @@ -0,0 +1,10 @@ +package channel + +const ( + EventTypeSendPacket = "send_packet" + + AttributeKeySenderPort = "sender_port" + AttributeKeyReceiverPort = "receiver_port" + AttributeKeyChannelID = "channel_id" + AttributeKeySequence = "sequence" +) diff --git a/x/ibc/04-channel/handler.go b/x/ibc/04-channel/handler.go index 078effaa433c..76d9ace3e6e4 100644 --- a/x/ibc/04-channel/handler.go +++ b/x/ibc/04-channel/handler.go @@ -35,14 +35,3 @@ func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) s } return sdk.Result{} } - -type Handler func(sdk.Context, Packet) sdk.Result - -func HandleMsgPacket(ctx sdk.Context, msg MsgPacket, man Manager) sdk.Result { - err := man.Receive(ctx, msg.Proofs, msg.PortID, msg.ChannelID, msg.Packet) - if err != nil { - return sdk.NewError(sdk.CodespaceType("ibc"), 500, "").Result() - } - handler := man.router.Route(msg.Packet.Route()) - return handler(ctx, msg.Packet) -} diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index b5e2507ea9c9..e7c2e1a2ee14 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -2,6 +2,7 @@ package channel import ( "errors" + "strconv" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" @@ -19,8 +20,6 @@ type Manager struct { counterparty CounterpartyManager - router Router - ports map[string]struct{} } @@ -260,6 +259,10 @@ func (man Manager) Send(ctx sdk.Context, portid, chanid string, packet Packet) e return errors.New("cannot send Packets on this channel") } */ + if portid != packet.SenderPort() { + return errors.New("Invalid portid") + } + obj, err := man.Query(ctx, portid, chanid) if err != nil { return err @@ -271,6 +274,16 @@ func (man Manager) Send(ctx sdk.Context, portid, chanid string, packet Packet) e obj.Packets.Set(ctx, obj.SeqSend.Incr(ctx), packet) + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + EventTypeSendPacket, + sdk.NewAttribute(AttributeKeySenderPort, packet.SenderPort()), + sdk.NewAttribute(AttributeKeyReceiverPort, packet.ReceiverPort()), + sdk.NewAttribute(AttributeKeyChannelID, chanid), + sdk.NewAttribute(AttributeKeySequence, strconv.FormatUint(obj.SeqSend.Get(ctx), 10)), + ), + }) + return nil } diff --git a/x/ibc/04-channel/msgs.go b/x/ibc/04-channel/msgs.go index adb53c7e62c0..c12f4a338b1a 100644 --- a/x/ibc/04-channel/msgs.go +++ b/x/ibc/04-channel/msgs.go @@ -134,8 +134,8 @@ func (msg MsgOpenConfirm) GetSigners() []sdk.AccAddress { type MsgPacket struct { Packet `json:"packet" yaml:"packet"` - // PortID, ChannelID can be empty if batched & not first MsgPacket - PortID string `json:"port_id,omitempty" yaml:"port_id"` + // PortID dependent on type + // ChannelID can be empty if batched & not first MsgPacket ChannelID string `json:"channel_id,omitempty" yaml:"channel_id"` // Height uint64 // height of the commitment root for the proofs Proofs []commitment.Proof `json:"proofs" yaml:"proofs"` @@ -152,6 +152,10 @@ func (msg MsgPacket) ValidateBasic() sdk.Error { return nil // TODO } +func (msg MsgPacket) Route() string { + return msg.ReceiverPort() +} + func (msg MsgPacket) GetSignBytes() []byte { return msgCdc.MustMarshalJSON(msg) // TODO: Sort } diff --git a/x/ibc/04-channel/port.go b/x/ibc/04-channel/port.go index 2b3505a50169..dfa8738655b2 100644 --- a/x/ibc/04-channel/port.go +++ b/x/ibc/04-channel/port.go @@ -29,6 +29,9 @@ func (port Port) Release() { } func (port Port) Send(ctx sdk.Context, chanid string, packet Packet) error { + if packet.SenderPort() != port.id { + panic("Packet sent on wrong port") + } return port.channel.Send(ctx, port.id, chanid, packet) } diff --git a/x/ibc/04-channel/router.go b/x/ibc/04-channel/router.go deleted file mode 100644 index 40c2c180fb31..000000000000 --- a/x/ibc/04-channel/router.go +++ /dev/null @@ -1,34 +0,0 @@ -package channel - -type Router interface { - AddRoute(path string, h Handler) Router - Route(path string) Handler -} - -type router struct { - routes map[string]Handler -} - -func NewRouter() Router { - return &router{ - routes: make(map[string]Handler), - } -} - -func (router *router) AddRoute(path string, h Handler) Router { - // TODO - /* - if !isAlphaNumeric(path) { - panic("route expressions can only contain alphanumeric characters") - } - */ - if router.routes[path] != nil { - panic("route " + path + "has already been initialized") - } - router.routes[path] = h - return router -} - -func (router *router) Route(path string) Handler { - return router.routes[path] -} diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go index 366eaae8277d..b3c79ca70779 100644 --- a/x/ibc/04-channel/tests/channel_test.go +++ b/x/ibc/04-channel/tests/channel_test.go @@ -2,7 +2,9 @@ package channel import ( "testing" + "errors" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/codec" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" @@ -44,8 +46,42 @@ func (packet MyPacket) Timeout() uint64 { return 100 // TODO } -func (MyPacket) Route() string { - return "my" +func (MyPacket) SenderPort() string { + return "channel-test" +} + +func (MyPacket) ReceiverPort() string { + return "channel-test" +} + +func (MyPacket) Type() string { + return "my-packet" +} + +func (MyPacket) ValidateBasic() sdk.Error { + return nil +} + +func (packet MyPacket) MarshalAmino() (string, error) { + return "mp-"+packet.Message, nil +} + +func (packet *MyPacket) UnmarshalAmino(text string) error { + if text[:3] != "mp-" { + return errors.New("Invalid text for MyPacket") + } + packet.Message = text[3:] + return nil +} + +func (packet MyPacket) MarshalJSON() ([]byte, error) { + res, _ := packet.MarshalAmino() + return []byte("\""+res+"\""), nil +} + +func (packet *MyPacket) UnmarshalJSON(bz []byte) error { + bz = bz[1:len(bz)-1] + return packet.UnmarshalAmino(string(bz)) } func TestPacket(t *testing.T) { diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index 0a95624cf39c..d186a786bb2d 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -19,13 +19,13 @@ type Packet struct { */ type Packet interface { - Route() string + SenderPort() string + ReceiverPort() string // == Route() Type() string ValidateBasic() sdk.Error - String() string Timeout() uint64 - MarshalAmino() (string, error) - MarshalJSON() ([]byte, error) + MarshalAmino() (string, error) // Should exclude PortID/ChannelID info + MarshalJSON() ([]byte, error) // Should exclude PortID/ChannelID info } type Channel struct { diff --git a/x/ibc/ante.go b/x/ibc/ante.go index 916f4445ce8f..696275ea08a6 100644 --- a/x/ibc/ante.go +++ b/x/ibc/ante.go @@ -19,10 +19,6 @@ func ExtractMsgPackets(msgs []sdk.Msg) (res []MsgPacket, abort bool) { if len(res) >= 2 { first := res[0] for _, msg := range res[1:] { - if len(msg.PortID) != 0 && msg.PortID != first.PortID { - return res, true - } - msg.PortID = first.PortID if len(msg.ChannelID) != 0 && msg.ChannelID != first.ChannelID { return res, true } @@ -35,7 +31,7 @@ func ExtractMsgPackets(msgs []sdk.Msg) (res []MsgPacket, abort bool) { func VerifyMsgPackets(ctx sdk.Context, channel channel.Manager, msgs []MsgPacket) error { for _, msg := range msgs { - err := channel.Receive(ctx, msg.Proofs, msg.PortID, msg.ChannelID, msg.Packet) + err := channel.Receive(ctx, msg.Proofs, msg.ReceiverPort(), msg.ChannelID, msg.Packet) if err != nil { return err } @@ -59,6 +55,6 @@ func NewAnteHandler(channel channel.Manager) sdk.AnteHandler { return } - return ctx, res, false + return ctx, res, false } } diff --git a/x/ibc/handler.go b/x/ibc/handler.go deleted file mode 100644 index 9614e00a1c30..000000000000 --- a/x/ibc/handler.go +++ /dev/null @@ -1,39 +0,0 @@ -package ibc - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// IBC Handler should not return error. Returning error will make the channel -// not able to be proceed. Send receipt packet when the packet is non executable. -type Handler func(ctx sdk.Context, packet Packet) - -/* -type ReturnHandler func(ctx sdk.Context, packet sdk.Packet) sdk.Packet -*/ - -func WrapHandler(h Handler, sdkh sdk.Handler) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - switch msg := msg.(type) { - case MsgPacket: - h(ctx, msg.Packet) - return sdk.Result{Events:ctx.EventManager().Events()} - default: - return sdkh(ctx, msg) - } - } -} - -// TODO -/* -func WrapReturnHandler(h ReturnHandler) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - receipt := h(ctx, msg.Packet) - if receipt != nil { - // Send receipt packet to the receipt channel - } - - return sdk.Result{Events: ctx.EventManager().Events()} - } -} -*/ diff --git a/x/ibc/mock/handler.go b/x/ibc/mock/handler.go new file mode 100644 index 000000000000..659e84ea5c1f --- /dev/null +++ b/x/ibc/mock/handler.go @@ -0,0 +1,28 @@ +package mock + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc" +) + +func NewHandler(k Keeper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + switch msg := msg.(type) { + case ibc.MsgPacket: + switch packet := msg.Packet.(type) { + case SequencePacket: + return handleMyPacket(ctx, k, packet, msg.ChannelID) + } + } + return sdk.ErrUnknownRequest("21345").Result() + } +} + +func handleMyPacket(ctx sdk.Context, k Keeper, packet SequencePacket, chanid string) (res sdk.Result) { + err := k.CheckAndSetSequence(ctx, chanid, packet.Sequence) + if err != nil { + res.Log = "Invalid sequence" // should not return error, set only log + } + return +} diff --git a/x/ibc/mock/keeper.go b/x/ibc/mock/keeper.go new file mode 100644 index 000000000000..c1b27635e5ff --- /dev/null +++ b/x/ibc/mock/keeper.go @@ -0,0 +1,49 @@ +package mock + +import ( + "errors" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc" +) + +var sequence = []byte("sequence") + +type Keeper struct { + cdc *codec.Codec + key sdk.StoreKey + port ibc.Port +} + +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, port ibc.Port) Keeper { + return Keeper{ + cdc: cdc, + key: key, + port: port, + } +} + +func (k Keeper) GetSequence(ctx sdk.Context, chanid string) (res uint64) { + store := ctx.KVStore(k.key) + if store.Has(sequence) { + k.cdc.MustUnmarshalBinaryBare(store.Get(sequence), &res) + } else { + res = 0 + } + + return +} + +func (k Keeper) SetSequence(ctx sdk.Context, chanid string, seq uint64) { + store := ctx.KVStore(k.key) + store.Set(sequence, k.cdc.MustMarshalBinaryBare(seq)) +} + +func (k Keeper) CheckAndSetSequence(ctx sdk.Context, chanid string, seq uint64) error { + if k.GetSequence(ctx, chanid)+1 != seq { + return errors.New("fjidow;af") + } + k.SetSequence(ctx, chanid, seq) + return nil +} diff --git a/x/ibc/mock/packets.go b/x/ibc/mock/packets.go index 5e649b1300e4..20f53f65d7e1 100644 --- a/x/ibc/mock/packets.go +++ b/x/ibc/mock/packets.go @@ -1,11 +1,11 @@ package mock import ( + "bytes" "errors" "fmt" - "strings" "strconv" - "bytes" + "strings" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc" @@ -34,7 +34,7 @@ func (packet SequencePacket) MarshalJSON() ([]byte, error) { } func (packet *SequencePacket) UnmarshalJSON(bz []byte) (err error) { - bz = bz[1:len(bz)-1] + bz = bz[1 : len(bz)-1] if !bytes.HasPrefix(bz, []byte("sequence-packet-")) { return errors.New("invalid SequencePacket string") } @@ -42,7 +42,11 @@ func (packet *SequencePacket) UnmarshalJSON(bz []byte) (err error) { return } -func (SequencePacket) Route() string { +func (SequencePacket) SenderPort() string { + return "ibc-mock" +} + +func (SequencePacket) ReceiverPort() string { return "ibc-mock" } diff --git a/x/ibc/types.go b/x/ibc/types.go index 5ccf47815198..be9303d07504 100644 --- a/x/ibc/types.go +++ b/x/ibc/types.go @@ -1,7 +1,9 @@ package ibc import ( - "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" ) +type Port = channel.Port + type Packet = channel.Packet From 5ea508b3a73c3cd90964fb96b4f3eb988795b0da Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 2 Sep 2019 15:57:13 +0200 Subject: [PATCH 155/182] add ibc module.go, finalize mock --- x/ibc/02-client/client/cli/tx.go | 8 +- x/ibc/03-connection/client/cli/tx.go | 15 ++- x/ibc/04-channel/cli.go | 4 +- x/ibc/04-channel/handshake.go | 12 +- x/ibc/mock/client/cli/query.go | 53 +++++++++ x/ibc/mock/client/cli/tx.go | 53 +++++++++ x/ibc/mock/codec.go | 10 ++ x/ibc/mock/handler.go | 5 +- x/ibc/mock/keeper.go | 9 +- x/ibc/mock/module.go | 102 +++++++++++++++++ x/ibc/mock/types/keys.go | 3 + x/ibc/mock/types/msgs.go | 42 +++++++ x/ibc/mock/{ => types}/packets.go | 30 ++--- x/ibc/module.go | 164 +++++++++++++++++++++++++++ 14 files changed, 475 insertions(+), 35 deletions(-) create mode 100644 x/ibc/mock/client/cli/query.go create mode 100644 x/ibc/mock/client/cli/tx.go create mode 100644 x/ibc/mock/codec.go create mode 100644 x/ibc/mock/module.go create mode 100644 x/ibc/mock/types/keys.go create mode 100644 x/ibc/mock/types/msgs.go rename x/ibc/mock/{ => types}/packets.go (53%) create mode 100644 x/ibc/module.go diff --git a/x/ibc/02-client/client/cli/tx.go b/x/ibc/02-client/client/cli/tx.go index 1b18dbe34783..d79bbbcf70e2 100644 --- a/x/ibc/02-client/client/cli/tx.go +++ b/x/ibc/02-client/client/cli/tx.go @@ -32,8 +32,8 @@ const ( func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { ibcTxCmd := &cobra.Command{ - Use: "ibc", - Short: "IBC transaction subcommands", + Use: "client", + Short: "Client transaction subcommands", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, } @@ -48,7 +48,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "create-client", + Use: "create", Short: "create new client with a consensus state", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { @@ -81,7 +81,7 @@ func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command { func GetCmdUpdateClient(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "update-client", + Use: "update", Short: "update existing client with a header", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 32df94715bd0..c889015c8b2c 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -52,7 +52,20 @@ func lastheight(ctx context.CLIContext) (uint64, error) { return uint64(info.Response.LastBlockHeight), nil } -func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { +func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "connection", + Short: "IBC connection transaction subcommands", + } + + cmd.AddCommand( + GetCmdHandshake(storeKey, cdc), + ) + + return cmd +} + +func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "handshake", Short: "initiate connection handshake between two chains", diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index acfbb9bd8d0f..2462a11f4eda 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -64,7 +64,7 @@ func (obj Object) PacketCLI(ctx context.CLIContext, index uint64) (res Packet, p } func (man Handshaker) CLIQuery(ctx context.CLIContext, portid, chanid string) (HandshakeObject, error) { - obj, err := man.man.CLIQuery(ctx, portid, chanid) + obj, err := man.Manager.CLIQuery(ctx, portid, chanid) if err != nil { return HandshakeObject{}, err } @@ -72,7 +72,7 @@ func (man Handshaker) CLIQuery(ctx context.CLIContext, portid, chanid string) (H } func (man Handshaker) CLIObject(portid, chanid string, connids []string) HandshakeObject { - return man.object(man.man.CLIObject(portid, chanid, connids)) + return man.object(man.Manager.CLIObject(portid, chanid, connids)) } func (obj HandshakeObject) StateCLI(ctx context.CLIContext) (res State, proof merkle.Proof, err error) { diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index 48faa877b838..16dbcc0cb2ac 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -21,7 +21,7 @@ const ( ) type Handshaker struct { - man Manager + Manager counterparty CounterpartyHandshaker } @@ -35,7 +35,7 @@ func (man Handshaker) Kind() string { // or add Seal() method to Manager? func NewHandshaker(man Manager) Handshaker { return Handshaker{ - man: man, + Manager: man, counterparty: CounterpartyHandshaker{man.counterparty}, } @@ -68,8 +68,8 @@ func (man Handshaker) object(parent Object) HandshakeObject { return HandshakeObject{ Object: parent, - State: man.man.protocol.Value([]byte(prefix + "/state")).Enum(), - NextTimeout: man.man.protocol.Value([]byte(prefix + "/timeout")).Integer(state.Dec), + State: man.protocol.Value([]byte(prefix + "/state")).Enum(), + NextTimeout: man.protocol.Value([]byte(prefix + "/timeout")).Integer(state.Dec), counterparty: man.counterparty.object(parent.counterparty), } @@ -87,7 +87,7 @@ func (man CounterpartyHandshaker) object(parent CounterObject) CounterHandshakeO } func (man Handshaker) create(ctx sdk.Context, connid, chanid string, channel Channel) (obj HandshakeObject, err error) { - cobj, err := man.man.create(ctx, connid, chanid, channel) + cobj, err := man.Manager.create(ctx, connid, chanid, channel) if err != nil { return } @@ -97,7 +97,7 @@ func (man Handshaker) create(ctx sdk.Context, connid, chanid string, channel Cha } func (man Handshaker) query(ctx sdk.Context, connid, chanid string) (obj HandshakeObject, err error) { - cobj, err := man.man.query(ctx, connid, chanid) + cobj, err := man.Manager.query(ctx, connid, chanid) if err != nil { return } diff --git a/x/ibc/mock/client/cli/query.go b/x/ibc/mock/client/cli/query.go new file mode 100644 index 000000000000..a3817350902a --- /dev/null +++ b/x/ibc/mock/client/cli/query.go @@ -0,0 +1,53 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" +) + +func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { + queryCmd := &cobra.Command{ + Use: "ibcmock", + Short: "Querying commands for the ibcmock module", + RunE: client.ValidateCmd, + } + + queryCmd.AddCommand(client.GetCommands( + GetCmdQuerySequence(queryRoute, cdc), + )...) + + return queryCmd +} + +func GetCmdQuerySequence(storeName string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "sequence [channel-id]", + Short: "Query the current sequence for the channel", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + val, _, err := ctx.QueryStore(types.SequenceKey, storeName) + if err != nil { + return err + } + + var res uint64 + if val == nil { + res = 0 + } else { + cdc.MustUnmarshalBinaryBare(val, &res) + } + fmt.Println(res) + + return nil + }, + } +} diff --git a/x/ibc/mock/client/cli/tx.go b/x/ibc/mock/client/cli/tx.go new file mode 100644 index 000000000000..996baa46dc37 --- /dev/null +++ b/x/ibc/mock/client/cli/tx.go @@ -0,0 +1,53 @@ +package cli + +import ( + "strconv" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" +) + +func GetTxCmd(cdc *codec.Codec) *cobra.Command { + txCmd := &cobra.Command{ + Use: "ibctypes", + Short: "IBC types module transaction subcommands", + RunE: client.ValidateCmd, + } + txCmd.AddCommand( + SequenceTxCmd(cdc), + ) + + return txCmd +} + +func SequenceTxCmd(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "sequence [from-key-or-address] [channel-id] [sequence]", + Short: "Send SequencePacket", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + ctx := context.NewCLIContextWithFrom(args[0]).WithCodec(cdc) + + chanid := args[1] + seq, err := strconv.ParseUint(args[2], 10, 64) + if err != nil { + return err + } + + msg := types.NewMsgSequence(ctx.GetFromAddress(), chanid, seq) + return utils.GenerateOrBroadcastMsgs(ctx, txBldr, []sdk.Msg{msg}) + }, + } + + cmd = client.PostCommands(cmd)[0] + + return cmd +} diff --git a/x/ibc/mock/codec.go b/x/ibc/mock/codec.go new file mode 100644 index 000000000000..20812bf738e8 --- /dev/null +++ b/x/ibc/mock/codec.go @@ -0,0 +1,10 @@ +package mock + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterConcrete(types.PacketSequence{}, "ibcmock/types.PacketSequence", nil) +} diff --git a/x/ibc/mock/handler.go b/x/ibc/mock/handler.go index 659e84ea5c1f..aa7b8168b62e 100644 --- a/x/ibc/mock/handler.go +++ b/x/ibc/mock/handler.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" ) func NewHandler(k Keeper) sdk.Handler { @@ -11,7 +12,7 @@ func NewHandler(k Keeper) sdk.Handler { switch msg := msg.(type) { case ibc.MsgPacket: switch packet := msg.Packet.(type) { - case SequencePacket: + case types.PacketSequence: return handleMyPacket(ctx, k, packet, msg.ChannelID) } } @@ -19,7 +20,7 @@ func NewHandler(k Keeper) sdk.Handler { } } -func handleMyPacket(ctx sdk.Context, k Keeper, packet SequencePacket, chanid string) (res sdk.Result) { +func handleMyPacket(ctx sdk.Context, k Keeper, packet types.PacketSequence, chanid string) (res sdk.Result) { err := k.CheckAndSetSequence(ctx, chanid, packet.Sequence) if err != nil { res.Log = "Invalid sequence" // should not return error, set only log diff --git a/x/ibc/mock/keeper.go b/x/ibc/mock/keeper.go index c1b27635e5ff..953dc889cf32 100644 --- a/x/ibc/mock/keeper.go +++ b/x/ibc/mock/keeper.go @@ -6,10 +6,9 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" ) -var sequence = []byte("sequence") - type Keeper struct { cdc *codec.Codec key sdk.StoreKey @@ -26,8 +25,8 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, port ibc.Port) Keeper { func (k Keeper) GetSequence(ctx sdk.Context, chanid string) (res uint64) { store := ctx.KVStore(k.key) - if store.Has(sequence) { - k.cdc.MustUnmarshalBinaryBare(store.Get(sequence), &res) + if store.Has(types.SequenceKey) { + k.cdc.MustUnmarshalBinaryBare(store.Get(types.SequenceKey), &res) } else { res = 0 } @@ -37,7 +36,7 @@ func (k Keeper) GetSequence(ctx sdk.Context, chanid string) (res uint64) { func (k Keeper) SetSequence(ctx sdk.Context, chanid string, seq uint64) { store := ctx.KVStore(k.key) - store.Set(sequence, k.cdc.MustMarshalBinaryBare(seq)) + store.Set(types.SequenceKey, k.cdc.MustMarshalBinaryBare(seq)) } func (k Keeper) CheckAndSetSequence(ctx sdk.Context, chanid string, seq uint64) error { diff --git a/x/ibc/mock/module.go b/x/ibc/mock/module.go new file mode 100644 index 000000000000..79aab119570d --- /dev/null +++ b/x/ibc/mock/module.go @@ -0,0 +1,102 @@ +package mock + +import ( + "encoding/json" + + "github.com/gorilla/mux" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/client/cli" +) + +const ( + ModuleName = "ibcmock" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +type AppModuleBasic struct{} + +var _ module.AppModuleBasic = AppModuleBasic{} + +func (AppModuleBasic) Name() string { + return ModuleName +} + +func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { + RegisterCodec(cdc) +} + +func (AppModuleBasic) DefaultGenesis() json.RawMessage { + return nil +} + +func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { + return nil +} + +func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) { + //noop +} + +func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { + return cli.GetTxCmd(cdc) +} + +func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { + return cli.GetQueryCmd(ModuleName, cdc) +} + +type AppModule struct { + AppModuleBasic + k Keeper +} + +func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + +} + +func (AppModule) Name() string { + return ModuleName +} + +func (AppModule) Route() string { + return ModuleName +} + +func (am AppModule) NewHandler() sdk.Handler { + return NewHandler(am.k) +} + +func (am AppModule) QuerierRoute() string { + return ModuleName +} + +func (am AppModule) NewQuerierHandler() sdk.Querier { + return nil +} + +func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage { + return nil +} + +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { + +} + +func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} diff --git a/x/ibc/mock/types/keys.go b/x/ibc/mock/types/keys.go new file mode 100644 index 000000000000..2e69fd34755e --- /dev/null +++ b/x/ibc/mock/types/keys.go @@ -0,0 +1,3 @@ +package types + +var SequenceKey = []byte("sequence") diff --git a/x/ibc/mock/types/msgs.go b/x/ibc/mock/types/msgs.go new file mode 100644 index 000000000000..1cd26b66a984 --- /dev/null +++ b/x/ibc/mock/types/msgs.go @@ -0,0 +1,42 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var cdc = codec.New() + +type MsgSequence struct { + Sequence uint64 + ChannelID string + Signer sdk.AccAddress +} + +func NewMsgSequence(signer sdk.AccAddress, chanid string, sequence uint64) MsgSequence { + return MsgSequence{ + Sequence: sequence, + ChannelID: chanid, + Signer: signer, + } +} + +func (MsgSequence) Route() string { + return "ibcmock" +} + +func (MsgSequence) Type() string { + return "sequence" +} + +func (msg MsgSequence) ValidateBasic() sdk.Error { + return nil +} + +func (msg MsgSequence) GetSignBytes() []byte { + return cdc.MustMarshalJSON(msg) // TODO +} + +func (msg MsgSequence) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Signer} +} diff --git a/x/ibc/mock/packets.go b/x/ibc/mock/types/packets.go similarity index 53% rename from x/ibc/mock/packets.go rename to x/ibc/mock/types/packets.go index 20f53f65d7e1..5daf0147756b 100644 --- a/x/ibc/mock/packets.go +++ b/x/ibc/mock/types/packets.go @@ -1,4 +1,4 @@ -package mock +package types import ( "bytes" @@ -11,57 +11,57 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc" ) -var _ ibc.Packet = SequencePacket{} +var _ ibc.Packet = PacketSequence{} -type SequencePacket struct { +type PacketSequence struct { Sequence uint64 } -func (packet SequencePacket) MarshalAmino() (string, error) { +func (packet PacketSequence) MarshalAmino() (string, error) { return fmt.Sprintf("sequence-packet-%d", packet.Sequence), nil } -func (packet *SequencePacket) UnmarshalAmino(text string) (err error) { +func (packet *PacketSequence) UnmarshalAmino(text string) (err error) { if !strings.HasPrefix(text, "sequence-packet-") { - return errors.New("invalid SequencePacket string") + return errors.New("invalid PacketSequence string") } packet.Sequence, err = strconv.ParseUint(strings.TrimPrefix(text, "sequence-packet-"), 10, 64) return } -func (packet SequencePacket) MarshalJSON() ([]byte, error) { +func (packet PacketSequence) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf("\"sequence-packet-%d\"", packet.Sequence)), nil } -func (packet *SequencePacket) UnmarshalJSON(bz []byte) (err error) { +func (packet *PacketSequence) UnmarshalJSON(bz []byte) (err error) { bz = bz[1 : len(bz)-1] if !bytes.HasPrefix(bz, []byte("sequence-packet-")) { - return errors.New("invalid SequencePacket string") + return errors.New("invalid PacketSequence string") } packet.Sequence, err = strconv.ParseUint(strings.TrimPrefix(string(bz), "sequence-packet-"), 10, 64) return } -func (SequencePacket) SenderPort() string { +func (PacketSequence) SenderPort() string { return "ibc-mock" } -func (SequencePacket) ReceiverPort() string { +func (PacketSequence) ReceiverPort() string { return "ibc-mock" } -func (SequencePacket) String() string { +func (PacketSequence) String() string { return "sequence-packet" } -func (SequencePacket) Timeout() uint64 { +func (PacketSequence) Timeout() uint64 { return 0 } -func (SequencePacket) Type() string { +func (PacketSequence) Type() string { return "empty-packet" } -func (SequencePacket) ValidateBasic() sdk.Error { +func (PacketSequence) ValidateBasic() sdk.Error { return nil } diff --git a/x/ibc/module.go b/x/ibc/module.go new file mode 100644 index 000000000000..ab21878de42b --- /dev/null +++ b/x/ibc/module.go @@ -0,0 +1,164 @@ +package ibc + +import ( + "encoding/json" + "fmt" + + "github.com/gorilla/mux" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + clicli "github.com/cosmos/cosmos-sdk/x/ibc/02-client/client/cli" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + conncli "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/cli" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" +) + +const ( + ModuleName = "ibc" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +type AppModuleBasic struct{} + +var _ module.AppModuleBasic = AppModuleBasic{} + +func (AppModuleBasic) Name() string { + return ModuleName +} + +func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { + commitment.RegisterCodec(cdc) + merkle.RegisterCodec(cdc) + client.RegisterCodec(cdc) + tendermint.RegisterCodec(cdc) + channel.RegisterCodec(cdc) +} + +func (AppModuleBasic) DefaultGenesis() json.RawMessage { + return nil +} + +func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { + return nil +} + +func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) { + //noop +} + +func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "ibc", + Short: "IBC transaction subcommands", + } + + cmd.AddCommand( + clicli.GetTxCmd(ModuleName, cdc), + conncli.GetTxCmd(ModuleName, cdc), + // chancli.GetTxCmd(ModuleName, cdc), + ) + + return cmd +} + +func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "ibc", + Short: "IBC query subcommands", + } + + cmd.AddCommand( + clicli.GetQueryCmd(ModuleName, cdc), + conncli.GetQueryCmd(ModuleName, cdc), + // chancli.GetQueryCmd(ModuleName, cdc), + ) + + return cmd +} + +type AppModule struct { + AppModuleBasic + client client.Manager + connection connection.Handshaker + channel channel.Handshaker +} + +func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + +} + +func (AppModule) Name() string { + return ModuleName +} + +func (AppModule) Route() string { + return ModuleName +} + +func (am AppModule) NewHandler() sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + switch msg := msg.(type) { + case client.MsgCreateClient: + return client.HandleMsgCreateClient(ctx, msg, am.client) + case client.MsgUpdateClient: + return client.HandleMsgUpdateClient(ctx, msg, am.client) + case connection.MsgOpenInit: + return connection.HandleMsgOpenInit(ctx, msg, am.connection) + case connection.MsgOpenTry: + return connection.HandleMsgOpenTry(ctx, msg, am.connection) + case connection.MsgOpenAck: + return connection.HandleMsgOpenAck(ctx, msg, am.connection) + case connection.MsgOpenConfirm: + return connection.HandleMsgOpenConfirm(ctx, msg, am.connection) + case channel.MsgOpenInit: + return channel.HandleMsgOpenInit(ctx, msg, am.channel) + case channel.MsgOpenTry: + return channel.HandleMsgOpenTry(ctx, msg, am.channel) + case channel.MsgOpenAck: + return channel.HandleMsgOpenAck(ctx, msg, am.channel) + case channel.MsgOpenConfirm: + return channel.HandleMsgOpenConfirm(ctx, msg, am.channel) + default: + errMsg := fmt.Sprintf("unrecognized IBC message type: %T", msg) + return sdk.ErrUnknownRequest(errMsg).Result() + } + } +} + +func (am AppModule) QuerierRoute() string { + return ModuleName +} + +func (am AppModule) NewQuerierHandler() sdk.Querier { + return nil +} + +func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage { + return nil +} + +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { + +} + +func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} From 418ec863bbfa1aaac94f8ca762ffceccf5081212 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 2 Sep 2019 20:06:29 +0200 Subject: [PATCH 156/182] add keeper --- x/ibc/keeper.go | 29 +++++++++++++++++++++++++++++ x/ibc/module.go | 10 +++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 x/ibc/keeper.go diff --git a/x/ibc/keeper.go b/x/ibc/keeper.go new file mode 100644 index 000000000000..859d909ad82a --- /dev/null +++ b/x/ibc/keeper.go @@ -0,0 +1,29 @@ +package ibc + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + "github.com/cosmos/cosmos-sdk/x/ibc/version" +) + +type Keeper struct { + client client.Manager + connection connection.Handshaker + channel channel.Handshaker +} + +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey) Keeper { + base := state.NewMapping(key, cdc, version.DefaultPrefix()) + climan := client.NewManager(base) + connman := connection.NewManager(base, climan) + chanman := channel.NewManager(base, connman) + return Keeper{ + client: climan, + connection: connection.NewHandshaker(connman), + channel: channel.NewHandshaker(chanman), + } +} diff --git a/x/ibc/module.go b/x/ibc/module.go index ab21878de42b..20da38e8c00b 100644 --- a/x/ibc/module.go +++ b/x/ibc/module.go @@ -92,9 +92,13 @@ func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { type AppModule struct { AppModuleBasic - client client.Manager - connection connection.Handshaker - channel channel.Handshaker + Keeper +} + +func NewAppModule(k Keeper) AppModule { + return AppModule{ + Keeper: k, + } } func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { From 0570f84331ae232f16098f0bed8f3de46135b072 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 2 Sep 2019 20:11:21 +0200 Subject: [PATCH 157/182] add StoreKey const --- x/ibc/module.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/ibc/module.go b/x/ibc/module.go index 20da38e8c00b..74c0edf946b8 100644 --- a/x/ibc/module.go +++ b/x/ibc/module.go @@ -25,6 +25,7 @@ import ( const ( ModuleName = "ibc" + StoreKey = ModuleName ) var ( From 075f7c996c0492b08a194db7ed243b2b7b212763 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 3 Sep 2019 16:31:55 +0200 Subject: [PATCH 158/182] fix test --- x/ibc/02-client/tendermint/tests/types.go | 23 +++++++++---------- x/ibc/04-channel/handshake.go | 14 ++---------- x/ibc/04-channel/tests/channel_test.go | 16 ++++++------- x/ibc/04-channel/tests/types.go | 28 ++++++++++++----------- x/ibc/23-commitment/merkle/merkle_test.go | 2 +- x/ibc/{msg.go => msgs.go} | 0 6 files changed, 37 insertions(+), 46 deletions(-) rename x/ibc/{msg.go => msgs.go} (100%) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 027d3a28a5f5..26255358f483 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -1,26 +1,26 @@ package tendermint import ( + "bytes" "crypto/rand" "testing" - "bytes" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" - dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" tmtypes "github.com/tendermint/tendermint/types" + dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store" stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -52,20 +52,20 @@ type Node struct { Commits []tmtypes.SignedHeader StoreName string - Prefix []byte + Prefix []byte } func NewNode(valset MockValidators, storeName string, prefix []byte) *Node { key, ctx, cms, _ := defaultComponents(storeName) return &Node{ - Valset: valset, - Cms: cms, - Key: key, - Store: ctx.KVStore(key), - Commits: nil, + Valset: valset, + Cms: cms, + Key: key, + Store: ctx.KVStore(key), + Commits: nil, StoreName: storeName, - Prefix: prefix, + Prefix: prefix, } } @@ -149,7 +149,6 @@ func (v *Verifier) Validate(header tendermint.Header, valset, nextvalset MockVal return nil } - func (node *Node) Query(t *testing.T, k []byte) ([]byte, commitment.Proof) { if bytes.HasPrefix(k, node.Prefix) { k = bytes.TrimPrefix(k, node.Prefix) diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index f31d459d545f..9b946ab4165e 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -86,13 +86,8 @@ func (man CounterpartyHandshaker) object(parent CounterObject) CounterHandshakeO } } -<<<<<<< HEAD -func (man Handshaker) create(ctx sdk.Context, connid, chanid string, channel Channel) (obj HandshakeObject, err error) { - cobj, err := man.Manager.create(ctx, connid, chanid, channel) -======= func (man Handshaker) create(ctx sdk.Context, portid, chanid string, channel Channel) (obj HandshakeObject, err error) { - cobj, err := man.man.create(ctx, portid, chanid, channel) ->>>>>>> joon/ics-04-implementation + cobj, err := man.Manager.create(ctx, portid, chanid, channel) if err != nil { return } @@ -101,13 +96,8 @@ func (man Handshaker) create(ctx sdk.Context, portid, chanid string, channel Cha return obj, nil } -<<<<<<< HEAD -func (man Handshaker) query(ctx sdk.Context, connid, chanid string) (obj HandshakeObject, err error) { - cobj, err := man.Manager.query(ctx, connid, chanid) -======= func (man Handshaker) query(ctx sdk.Context, portid, chanid string) (obj HandshakeObject, err error) { - cobj, err := man.man.query(ctx, portid, chanid) ->>>>>>> joon/ics-04-implementation + cobj, err := man.Manager.query(ctx, portid, chanid) if err != nil { return } diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go index b3c79ca70779..fbc8b01a3a76 100644 --- a/x/ibc/04-channel/tests/channel_test.go +++ b/x/ibc/04-channel/tests/channel_test.go @@ -1,11 +1,11 @@ package channel import ( - "testing" "errors" + "testing" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" tmclient "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" @@ -47,11 +47,11 @@ func (packet MyPacket) Timeout() uint64 { } func (MyPacket) SenderPort() string { - return "channel-test" + return PortName } func (MyPacket) ReceiverPort() string { - return "channel-test" + return PortName } func (MyPacket) Type() string { @@ -63,7 +63,7 @@ func (MyPacket) ValidateBasic() sdk.Error { } func (packet MyPacket) MarshalAmino() (string, error) { - return "mp-"+packet.Message, nil + return "mp-" + packet.Message, nil } func (packet *MyPacket) UnmarshalAmino(text string) error { @@ -74,13 +74,13 @@ func (packet *MyPacket) UnmarshalAmino(text string) error { return nil } -func (packet MyPacket) MarshalJSON() ([]byte, error) { +func (packet MyPacket) MarshalJSON() ([]byte, error) { res, _ := packet.MarshalAmino() - return []byte("\""+res+"\""), nil + return []byte("\"" + res + "\""), nil } func (packet *MyPacket) UnmarshalJSON(bz []byte) error { - bz = bz[1:len(bz)-1] + bz = bz[1 : len(bz)-1] return packet.UnmarshalAmino(string(bz)) } diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 22c8234fbabe..d9ca7089241a 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -15,6 +15,8 @@ import ( commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) +const PortName = "port-test" + type Node struct { *connection.Node Counterparty *Node @@ -39,16 +41,16 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { } res.Channel = channel.Channel{ - Port: res.Name, + Port: PortName, Counterparty: res.Counterparty.Name, - CounterpartyPort: res.Counterparty.Name, + CounterpartyPort: PortName, ConnectionHops: []string{res.Name}, } res.Counterparty.Channel = channel.Channel{ - Port: res.Counterparty.Name, + Port: PortName, Counterparty: res.Name, - CounterpartyPort: res.Name, + CounterpartyPort: PortName, ConnectionHops: []string{res.Counterparty.Name}, } @@ -66,7 +68,7 @@ func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Conte func (node *Node) CLIObject() channel.HandshakeObject { man := node.Manager() - return channel.NewHandshaker(man).CLIObject(node.Name, node.Name, []string{node.Counterparty.Name, node.Name}) + return channel.NewHandshaker(man).CLIObject(PortName, node.Name, []string{node.Name}) } func base(cdc *codec.Codec, key sdk.StoreKey) (state.Mapping, state.Mapping) { @@ -83,7 +85,7 @@ func (node *Node) Manager() channel.Manager { func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenInit(ctx, node.Name, node.Name, node.Channel, 100) // TODO: test timeout + obj, err := man.OpenInit(ctx, PortName, node.Name, node.Channel, 100) // TODO: test timeout require.NoError(t, err) require.Equal(t, channel.Init, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -92,7 +94,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, proofs, node.Name, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs, PortName, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.OpenTry, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -102,7 +104,7 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, proofs, node.Name, node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs, PortName, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.Open, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -112,7 +114,7 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, proofs, node.Name, node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs, PortName, node.Name, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.Open, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -155,10 +157,10 @@ func (node *Node) Handshake(t *testing.T) { func (node *Node) Send(t *testing.T, packet channel.Packet) { ctx, man := node.Context(), node.Manager() - obj, err := man.Query(ctx, node.Name, node.Name) + obj, err := man.Query(ctx, PortName, node.Name) require.NoError(t, err) seq := obj.SeqSend.Get(ctx) - err = man.Send(ctx, node.Name, node.Name, packet) + err = man.Send(ctx, PortName, node.Name, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqSend.Get(ctx)) require.Equal(t, node.Cdc.MustMarshalBinaryBare(packet), obj.PacketCommit(ctx, seq+1)) @@ -166,10 +168,10 @@ func (node *Node) Send(t *testing.T, packet channel.Packet) { func (node *Node) Receive(t *testing.T, packet channel.Packet, proofs ...commitment.Proof) { ctx, man := node.Context(), node.Manager() - obj, err := man.Query(ctx, node.Name, node.Name) + obj, err := man.Query(ctx, PortName, node.Name) require.NoError(t, err) seq := obj.SeqRecv.Get(ctx) - err = man.Receive(ctx, proofs, node.Name, node.Name, packet) + err = man.Receive(ctx, proofs, PortName, node.Name, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqRecv.Get(ctx)) } diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index 222a6bf5abd9..efa384a6c317 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" + dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store" diff --git a/x/ibc/msg.go b/x/ibc/msgs.go similarity index 100% rename from x/ibc/msg.go rename to x/ibc/msgs.go From 08efad16a6d27dc9ef9656b3c42394700b32ad58 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 16 Sep 2019 20:49:08 +0200 Subject: [PATCH 159/182] fix cli errors --- x/ibc/02-client/client/cli/query.go | 14 +++++ x/ibc/02-client/codec.go | 16 ++++-- x/ibc/02-client/tendermint/codec.go | 5 -- x/ibc/03-connection/client/cli/tx.go | 62 +++++++++++++++++------ x/ibc/03-connection/client/utils/types.go | 33 ++++++------ x/ibc/03-connection/handshake.go | 2 +- x/ibc/03-connection/manager.go | 6 +-- x/ibc/03-connection/types.go | 8 +-- x/ibc/04-channel/codec.go | 12 ++++- x/ibc/module.go | 3 ++ 10 files changed, 111 insertions(+), 50 deletions(-) diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 6dd79d353a67..df4b21f962df 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -35,6 +35,7 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { ibcQueryCmd.AddCommand(cli.GetCommands( GetCmdQueryConsensusState(storeKey, cdc), + GetCmdQueryPath(storeKey, cdc), GetCmdQueryHeader(cdc), GetCmdQueryClient(storeKey, cdc), )...) @@ -108,6 +109,19 @@ func GetCmdQueryConsensusState(storeKey string, cdc *codec.Codec) *cobra.Command } } +func GetCmdQueryPath(storeName string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "path", + Short: "Query the commitment path of the running chain", + RunE: func(cmd *cobra.Command, args []string) error { + mapp := mapping(cdc, storeName, version.Version) + path := merkle.NewPath([][]byte{[]byte(storeName)}, mapp.PrefixBytes()) + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, path)) + return nil + }, + } +} + func GetCmdQueryHeader(cdc *codec.Codec) *cobra.Command { return &cobra.Command{ Use: "header", diff --git a/x/ibc/02-client/codec.go b/x/ibc/02-client/codec.go index ece7e750dc98..d130e624f476 100644 --- a/x/ibc/02-client/codec.go +++ b/x/ibc/02-client/codec.go @@ -4,11 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" ) -var MsgCdc = codec.New() - -func init() { - RegisterCodec(MsgCdc) -} +var MsgCdc *codec.Codec func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*ConsensusState)(nil), nil) @@ -17,3 +13,13 @@ func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(MsgCreateClient{}, "ibc/client/MsgCreateClient", nil) cdc.RegisterConcrete(MsgUpdateClient{}, "ibc/client/MsgUpdateClient", nil) } + +func SetMsgCodec(cdc *codec.Codec) { + // TODO + /* + if MsgCdc != nil && MsgCdc != cdc { + panic("MsgCdc set more than once") + } + */ + MsgCdc = cdc +} diff --git a/x/ibc/02-client/tendermint/codec.go b/x/ibc/02-client/tendermint/codec.go index 31a25031f9fc..1c149c0a3fe3 100644 --- a/x/ibc/02-client/tendermint/codec.go +++ b/x/ibc/02-client/tendermint/codec.go @@ -2,13 +2,8 @@ package tendermint import ( "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" ) -func init() { - RegisterCodec(client.MsgCdc) -} - func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil) cdc.RegisterConcrete(Header{}, "ibc/client/tendermint/Header", nil) diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index c889015c8b2c..edd44174089a 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -1,6 +1,7 @@ package cli import ( + "fmt" "io/ioutil" "github.com/spf13/cobra" @@ -69,9 +70,10 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "handshake", Short: "initiate connection handshake between two chains", - Args: cobra.ExactArgs(4), - // Args: []string{connid1, connfilepath1, connid2, connfilepath2} + Args: cobra.ExactArgs(6), + // Args: []string{connid1, clientid1, path1, connid2, clientid2, connfilepath2} RunE: func(cmd *cobra.Command, args []string) error { + fmt.Println(0000) txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContext(). WithCodec(cdc). @@ -83,36 +85,53 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { WithNodeURI(viper.GetString(FlagNode2)). WithFrom(viper.GetString(FlagFrom2)) - conn1id := args[0] - conn1bz, err := ioutil.ReadFile(args[1]) + fmt.Println(3333) + connid1 := args[0] + clientid1 := args[1] + connid2 := args[3] + clientid2 := args[4] + + var path1 commitment.Path + path1bz, err := ioutil.ReadFile(args[2]) if err != nil { return err } - var conn1 connection.Connection - if err := cdc.UnmarshalJSON(conn1bz, &conn1); err != nil { + if err = cdc.UnmarshalJSON(path1bz, &path1); err != nil { return err } + conn1 := connection.Connection{ + Client: clientid1, + Counterparty: connid2, + Path: path1, + } - obj1, err := handshake(ctx1, cdc, storeKey, version.DefaultPrefix(), conn1id) + fmt.Println(1111) + obj1, err := handshake(ctx1, cdc, storeKey, version.DefaultPrefix(), connid1) if err != nil { return err } - conn2id := args[2] - conn2bz, err := ioutil.ReadFile(args[3]) + var path2 commitment.Path + path2bz, err := ioutil.ReadFile(args[5]) if err != nil { return err } - var conn2 connection.Connection - if err := cdc.UnmarshalJSON(conn2bz, &conn2); err != nil { + if err = cdc.UnmarshalJSON(path2bz, &path2); err != nil { return err } + conn2 := connection.Connection{ + Client: clientid2, + Counterparty: connid1, + Path: path2, + } - obj2, err := handshake(ctx2, cdc, storeKey, version.DefaultPrefix(), conn1id) + fmt.Println(2222) + obj2, err := handshake(ctx2, cdc, storeKey, version.DefaultPrefix(), connid2) if err != nil { return err } + fmt.Println(111) // TODO: check state and if not Idle continue existing process height, err := lastheight(ctx2) if err != nil { @@ -120,7 +139,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { } nextTimeout := height + 1000 // TODO: parameterize msginit := connection.MsgOpenInit{ - ConnectionID: conn1id, + ConnectionID: connid1, Connection: conn1, CounterpartyClient: conn2.Client, NextTimeout: nextTimeout, @@ -132,6 +151,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } + fmt.Println(222) timeout := nextTimeout height, err = lastheight(ctx1) if err != nil { @@ -146,6 +166,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } + fmt.Println(333) _, ptimeout, err := obj1.NextTimeoutCLI(ctx1) if err != nil { return err @@ -156,7 +177,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { } msgtry := connection.MsgOpenTry{ - ConnectionID: conn2id, + ConnectionID: connid2, Connection: conn2, CounterpartyClient: conn1.Client, Timeout: timeout, @@ -165,6 +186,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Signer: ctx2.GetFromAddress(), } + fmt.Println(444) err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) if err != nil { return err @@ -194,7 +216,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { } msgack := connection.MsgOpenAck{ - ConnectionID: conn1id, + ConnectionID: connid1, Timeout: timeout, NextTimeout: nextTimeout, Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, @@ -217,7 +239,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { } msgconfirm := connection.MsgOpenConfirm{ - ConnectionID: conn2id, + ConnectionID: connid2, Timeout: timeout, Proofs: []commitment.Proof{pstate, ptimeout}, Signer: ctx2.GetFromAddress(), @@ -232,5 +254,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { }, } + cmd.Flags().String(FlagNode1, "tcp://localhost:26657", "") + cmd.Flags().String(FlagNode2, "tcp://localhost:26657", "") + cmd.Flags().String(FlagFrom1, "", "") + cmd.Flags().String(FlagFrom2, "", "") + + cmd.MarkFlagRequired(FlagFrom1) + cmd.MarkFlagRequired(FlagFrom2) + return cmd } diff --git a/x/ibc/03-connection/client/utils/types.go b/x/ibc/03-connection/client/utils/types.go index 33480a68291f..95989e93d650 100644 --- a/x/ibc/03-connection/client/utils/types.go +++ b/x/ibc/03-connection/client/utils/types.go @@ -1,8 +1,8 @@ package utils import ( - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type JSONObject struct { @@ -12,6 +12,13 @@ type JSONObject struct { AvailableProof commitment.Proof `json:"available_proof,omitempty"` Kind string `json:"kind"` KindProof commitment.Proof `json:"kind_proof,omitempty"` + + State byte `json:"state,omitempty"` + StateProof commitment.Proof `json:"state_proof,omitempty"` + CounterpartyClient string `json:"counterparty_client,omitempty"` + CounterpartyClientProof commitment.Proof `json:"counterparty_client_proof,omitempty"` + NextTimeout uint64 `json:"next_timeout,omitempty"` + NextTimeoutProof commitment.Proof `json:"next_timeout_proof,omitempty"` } func NewJSONObject( @@ -29,16 +36,6 @@ func NewJSONObject( } } -type HandshakeJSONObject struct { - JSONObject `json:"connection"` - State byte `json:"state"` - StateProof commitment.Proof `json:"state_proof,omitempty"` - CounterpartyClient string `json:"counterparty_client"` - CounterpartyClientProof commitment.Proof `json:"counterparty_client_proof,omitempty"` - NextTimeout uint64 `json:"next_timeout"` - NextTimeoutProof commitment.Proof `json:"next_timeout_proof,omitempty"` -} - func NewHandshakeJSONObject( conn connection.Connection, connp commitment.Proof, avail bool, availp commitment.Proof, @@ -46,9 +43,15 @@ func NewHandshakeJSONObject( state byte, statep commitment.Proof, cpclient string, cpclientp commitment.Proof, timeout uint64, timeoutp commitment.Proof, -) HandshakeJSONObject { - return HandshakeJSONObject{ - JSONObject: NewJSONObject(conn, connp, avail, availp, kind, kindp), +) JSONObject { + return JSONObject{ + Connection: conn, + ConnectionProof: connp, + Available: avail, + AvailableProof: availp, + Kind: kind, + KindProof: kindp, + State: state, StateProof: statep, CounterpartyClient: cpclient, diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index c5d9debba1a3..ab956b428d55 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type State = byte diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index f4e4d6432c29..de1f7219200b 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -7,8 +7,8 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -24,7 +24,7 @@ type Manager struct { func NewManager(protocol state.Mapping, client client.Manager) Manager { return Manager{ - protocol: protocol.Prefix(LocalRoot()), + protocol: protocol.Prefix(LocalRoot()), client: client, counterparty: NewCounterpartyManager(protocol.Cdc()), path: merkle.NewPath([][]byte{[]byte(protocol.StoreName())}, protocol.PrefixBytes()), diff --git a/x/ibc/03-connection/types.go b/x/ibc/03-connection/types.go index 358d6a451fb9..af5b1c987689 100644 --- a/x/ibc/03-connection/types.go +++ b/x/ibc/03-connection/types.go @@ -5,13 +5,13 @@ import ( "errors" "strings" */ - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type Connection struct { - Client string - Counterparty string - Path commitment.Path + Client string `json:"client"` + Counterparty string `json:"counterparty"` + Path commitment.Path `json:"path"` } /* diff --git a/x/ibc/04-channel/codec.go b/x/ibc/04-channel/codec.go index 922009db6bd8..ebf30115d09a 100644 --- a/x/ibc/04-channel/codec.go +++ b/x/ibc/04-channel/codec.go @@ -4,8 +4,18 @@ import ( "github.com/cosmos/cosmos-sdk/codec" ) -var msgCdc = codec.New() +var msgCdc *codec.Codec func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*Packet)(nil), nil) } + +func SetMsgCodec(cdc *codec.Codec) { + // TODO + /* + if msgCdc != nil && msgCdc != cdc { + panic("MsgCdc set more than once") + } + */ + msgCdc = cdc +} diff --git a/x/ibc/module.go b/x/ibc/module.go index 74c0edf946b8..2be7ba8ed4d5 100644 --- a/x/ibc/module.go +++ b/x/ibc/module.go @@ -47,6 +47,9 @@ func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { client.RegisterCodec(cdc) tendermint.RegisterCodec(cdc) channel.RegisterCodec(cdc) + + client.SetMsgCodec(cdc) + channel.SetMsgCodec(cdc) } func (AppModuleBasic) DefaultGenesis() json.RawMessage { From acaaaf299546fb8f1032e71229ec6e4da36ad4e4 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 17 Sep 2019 17:33:50 +0200 Subject: [PATCH 160/182] fix dependency --- x/ibc/02-client/tendermint/tests/types.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/x/ibc/02-client/tendermint/tests/types.go b/x/ibc/02-client/tendermint/tests/types.go index 027d3a28a5f5..26255358f483 100644 --- a/x/ibc/02-client/tendermint/tests/types.go +++ b/x/ibc/02-client/tendermint/tests/types.go @@ -1,26 +1,26 @@ package tendermint import ( + "bytes" "crypto/rand" "testing" - "bytes" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" - dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" tmtypes "github.com/tendermint/tendermint/types" + dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store" stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -52,20 +52,20 @@ type Node struct { Commits []tmtypes.SignedHeader StoreName string - Prefix []byte + Prefix []byte } func NewNode(valset MockValidators, storeName string, prefix []byte) *Node { key, ctx, cms, _ := defaultComponents(storeName) return &Node{ - Valset: valset, - Cms: cms, - Key: key, - Store: ctx.KVStore(key), - Commits: nil, + Valset: valset, + Cms: cms, + Key: key, + Store: ctx.KVStore(key), + Commits: nil, StoreName: storeName, - Prefix: prefix, + Prefix: prefix, } } @@ -149,7 +149,6 @@ func (v *Verifier) Validate(header tendermint.Header, valset, nextvalset MockVal return nil } - func (node *Node) Query(t *testing.T, k []byte) ([]byte, commitment.Proof) { if bytes.HasPrefix(k, node.Prefix) { k = bytes.TrimPrefix(k, node.Prefix) From 4e53dcd35d7b0cc3580274d0d0f32ee000690886 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 17 Sep 2019 17:36:16 +0200 Subject: [PATCH 161/182] reflect method name change --- x/ibc/04-channel/manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index b5e2507ea9c9..8bcbbddedce5 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -269,7 +269,7 @@ func (man Manager) Send(ctx sdk.Context, portid, chanid string, packet Packet) e return errors.New("timeout height higher than the latest known") } - obj.Packets.Set(ctx, obj.SeqSend.Incr(ctx), packet) + obj.Packets.Set(ctx, obj.SeqSend.Increment(ctx), packet) return nil } @@ -298,7 +298,7 @@ func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, portid, c // XXX: increment should happen before verification, reflect on the spec // TODO: packet should be custom marshalled - if !obj.counterparty.Packets.Value(obj.SeqRecv.Incr(ctx)).Is(ctx, packet) { + if !obj.counterparty.Packets.Value(obj.SeqRecv.Increment(ctx)).Is(ctx, packet) { return errors.New("verification failed") } From f88d8d3b1c639a2555c1a2430f2fab6b9e37c609 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 18 Sep 2019 17:51:40 +0200 Subject: [PATCH 162/182] revise querier interface to work both on cli & store --- store/state/mapping_test.go | 2 +- store/state/types.go | 45 +++++++++++++++++++++++++++- store/state/value.go | 18 +++-------- store/state/value_test.go | 59 +++++++++++++++++++++++++++++++++++-- 4 files changed, 105 insertions(+), 19 deletions(-) diff --git a/store/state/mapping_test.go b/store/state/mapping_test.go index 2f44b9fcccc2..3d4110fdf672 100644 --- a/store/state/mapping_test.go +++ b/store/state/mapping_test.go @@ -88,7 +88,7 @@ func (m indexerT) RandomKey() interface{} { } func TestMapping(t *testing.T) { - ctx := defaultComponents() + ctx, _ := defaultComponents() table := []mapping{newMapping(), newIndexer(Dec), newIndexer(Hex), newIndexer(Bin)} for _, m := range table { diff --git a/store/state/types.go b/store/state/types.go index 9251c808db88..66ffb1f5255f 100644 --- a/store/state/types.go +++ b/store/state/types.go @@ -4,7 +4,9 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/merkle" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" + stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -14,5 +16,46 @@ type Proof = merkle.Proof type Codec = codec.Codec type ABCIQuerier interface { - QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) + Query(storeName string, key []byte) (abci.ResponseQuery, error) +} + +var _ ABCIQuerier = CLIQuerier{} + +type CLIQuerier struct { + ctx context.CLIContext +} + +func NewCLIQuerier(ctx context.CLIContext) CLIQuerier { + return CLIQuerier{ctx} +} + +func (q CLIQuerier) Query(storeName string, key []byte) (abci.ResponseQuery, error) { + req := abci.RequestQuery{ + Path: "/store/" + storeName + "/key", + Data: key, + Prove: true, + } + + return q.ctx.QueryABCI(req) +} + +var _ ABCIQuerier = StoreQuerier{} + +type StoreQuerier struct { + store stypes.Queryable +} + +func NewStoreQuerier(store stypes.Queryable) StoreQuerier { + return StoreQuerier{store} +} + +func (q StoreQuerier) Query(storeName string, key []byte) (abci.ResponseQuery, error) { + req := abci.RequestQuery{ + Path: "/" + storeName + "/key", + Data: key, + Prove: true, + } + + return q.store.Query(req), nil + } diff --git a/store/state/value.go b/store/state/value.go index 60df0c9718d6..1d467b0ab380 100644 --- a/store/state/value.go +++ b/store/state/value.go @@ -1,11 +1,7 @@ package state import ( - "errors" - - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" ) // Value is a capability for reading and writing on a specific key-value point @@ -29,7 +25,7 @@ func (v Value) store(ctx Context) KVStore { } // Cdc() returns the codec that the value is using to marshal/unmarshal -func (v Value) Cdc() *codec.Codec { +func (v Value) Cdc() *Codec { return v.m.Cdc() } @@ -108,19 +104,13 @@ func (v Value) KeyBytes() []byte { } func (v Value) QueryRaw(q ABCIQuerier) ([]byte, *Proof, error) { - req := abci.RequestQuery{ - Path: "/store" + v.m.StoreName() + "/key", - Data: v.KeyBytes(), - Prove: true, - } - - resp, err := q.QueryABCI(req) + resp, err := q.Query(v.m.StoreName(), v.KeyBytes()) if err != nil { return nil, nil, err } if !resp.IsOK() { - return nil, nil, errors.New(resp.Log) + return nil, nil, sdk.NewError(sdk.CodespaceRoot, sdk.CodeType(resp.Code), resp.Log) } return resp.Value, resp.Proof, nil diff --git a/store/state/value_test.go b/store/state/value_test.go index 88f75c32bdbb..38888890bbdf 100644 --- a/store/state/value_test.go +++ b/store/state/value_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/libs/log" dbm "github.com/tendermint/tm-db" @@ -30,6 +31,7 @@ func key() (res []byte) { } type value interface { + KeyBytes() []byte Get(Context, interface{}) GetSafe(Context, interface{}) error GetRaw(Context) []byte @@ -37,6 +39,7 @@ type value interface { SetRaw(Context, []byte) Exists(Context) bool Delete(Context) + Query(ABCIQuerier, interface{}) (*Proof, error) Marshal(interface{}) []byte Unmarshal([]byte, interface{}) } @@ -110,6 +113,15 @@ func (v booleanT) Unmarshal(bz []byte, ptr interface{}) { } } +func (v booleanT) Query(q ABCIQuerier, ptr interface{}) (proof *Proof, err error) { + res, proof, err := v.Boolean.Query(q) + if err != nil { + return + } + reflect.ValueOf(ptr).Elem().SetBool(res) + return +} + type integerT struct { Integer } @@ -153,6 +165,15 @@ func (v integerT) Unmarshal(bz []byte, ptr interface{}) { reflect.ValueOf(ptr).Elem().SetUint(res) } +func (v integerT) Query(q ABCIQuerier, ptr interface{}) (proof *Proof, err error) { + res, proof, err := v.Integer.Query(q) + if err != nil { + return + } + reflect.ValueOf(ptr).Elem().SetUint(res) + return +} + type enumT struct { Enum } @@ -192,6 +213,15 @@ func (v enumT) Unmarshal(bz []byte, ptr interface{}) { reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(bz[0])) } +func (v enumT) Query(q ABCIQuerier, ptr interface{}) (proof *Proof, err error) { + res, proof, err := v.Enum.Query(q) + if err != nil { + return + } + reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(res)) + return +} + type stringT struct { String } @@ -231,13 +261,22 @@ func (v stringT) Unmarshal(bz []byte, ptr interface{}) { reflect.ValueOf(ptr).Elem().SetString(string(bz)) } -func defaultComponents() sdk.Context { +func (v stringT) Query(q ABCIQuerier, ptr interface{}) (proof *Proof, err error) { + res, proof, err := v.String.Query(q) + if err != nil { + return + } + reflect.ValueOf(ptr).Elem().SetString(res) + return +} + +func defaultComponents() (sdk.Context, *rootmulti.Store) { db := dbm.NewMemDB() cms := rootmulti.NewStore(db) cms.MountStoreWithDB(testkey, sdk.StoreTypeIAVL, db) cms.LoadLatestVersion() ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger()) - return ctx + return ctx, cms } func indirect(ptr interface{}) interface{} { @@ -245,7 +284,7 @@ func indirect(ptr interface{}) interface{} { } func TestTypeValue(t *testing.T) { - ctx := defaultComponents() + ctx, cms := defaultComponents() var table = []struct { ty typeValue @@ -296,5 +335,19 @@ func TestTypeValue(t *testing.T) { require.Error(t, err) require.Equal(t, reflect.Zero(reflect.TypeOf(ptr).Elem()).Interface(), indirect(ptr)) require.Nil(t, v.GetRaw(ctx)) + + // Set again and test abci query + v.Set(ctx, tc.orig) + cid := cms.Commit() + ptr = v.Proto() + q := NewStoreQuerier(cms) + proof, err := v.Query(q, ptr) + require.NoError(t, err) + require.Equal(t, tc.orig, indirect(ptr), "Expected equal on tc %d", i) + prt := rootmulti.DefaultProofRuntime() + kp := merkle.KeyPath{}. + AppendKey([]byte(testkey.Name()), merkle.KeyEncodingHex). + AppendKey(v.KeyBytes(), merkle.KeyEncodingHex) + require.NoError(t, prt.VerifyValue(proof, cid.Hash, kp.String(), v.GetRaw(ctx))) } } From 1e64e92e625029fbc7bd8e6de55cdfc3ef63e9f6 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 18 Sep 2019 17:51:40 +0200 Subject: [PATCH 163/182] revise querier interface to work both on cli & store --- store/state/mapping_test.go | 2 +- store/state/types.go | 45 +++++++++++++++++++++++++++- store/state/value.go | 18 +++-------- store/state/value_test.go | 59 +++++++++++++++++++++++++++++++++++-- 4 files changed, 105 insertions(+), 19 deletions(-) diff --git a/store/state/mapping_test.go b/store/state/mapping_test.go index 2f44b9fcccc2..3d4110fdf672 100644 --- a/store/state/mapping_test.go +++ b/store/state/mapping_test.go @@ -88,7 +88,7 @@ func (m indexerT) RandomKey() interface{} { } func TestMapping(t *testing.T) { - ctx := defaultComponents() + ctx, _ := defaultComponents() table := []mapping{newMapping(), newIndexer(Dec), newIndexer(Hex), newIndexer(Bin)} for _, m := range table { diff --git a/store/state/types.go b/store/state/types.go index 9251c808db88..66ffb1f5255f 100644 --- a/store/state/types.go +++ b/store/state/types.go @@ -4,7 +4,9 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/merkle" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/codec" + stypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -14,5 +16,46 @@ type Proof = merkle.Proof type Codec = codec.Codec type ABCIQuerier interface { - QueryABCI(req abci.RequestQuery) (abci.ResponseQuery, error) + Query(storeName string, key []byte) (abci.ResponseQuery, error) +} + +var _ ABCIQuerier = CLIQuerier{} + +type CLIQuerier struct { + ctx context.CLIContext +} + +func NewCLIQuerier(ctx context.CLIContext) CLIQuerier { + return CLIQuerier{ctx} +} + +func (q CLIQuerier) Query(storeName string, key []byte) (abci.ResponseQuery, error) { + req := abci.RequestQuery{ + Path: "/store/" + storeName + "/key", + Data: key, + Prove: true, + } + + return q.ctx.QueryABCI(req) +} + +var _ ABCIQuerier = StoreQuerier{} + +type StoreQuerier struct { + store stypes.Queryable +} + +func NewStoreQuerier(store stypes.Queryable) StoreQuerier { + return StoreQuerier{store} +} + +func (q StoreQuerier) Query(storeName string, key []byte) (abci.ResponseQuery, error) { + req := abci.RequestQuery{ + Path: "/" + storeName + "/key", + Data: key, + Prove: true, + } + + return q.store.Query(req), nil + } diff --git a/store/state/value.go b/store/state/value.go index 60df0c9718d6..1d467b0ab380 100644 --- a/store/state/value.go +++ b/store/state/value.go @@ -1,11 +1,7 @@ package state import ( - "errors" - - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" ) // Value is a capability for reading and writing on a specific key-value point @@ -29,7 +25,7 @@ func (v Value) store(ctx Context) KVStore { } // Cdc() returns the codec that the value is using to marshal/unmarshal -func (v Value) Cdc() *codec.Codec { +func (v Value) Cdc() *Codec { return v.m.Cdc() } @@ -108,19 +104,13 @@ func (v Value) KeyBytes() []byte { } func (v Value) QueryRaw(q ABCIQuerier) ([]byte, *Proof, error) { - req := abci.RequestQuery{ - Path: "/store" + v.m.StoreName() + "/key", - Data: v.KeyBytes(), - Prove: true, - } - - resp, err := q.QueryABCI(req) + resp, err := q.Query(v.m.StoreName(), v.KeyBytes()) if err != nil { return nil, nil, err } if !resp.IsOK() { - return nil, nil, errors.New(resp.Log) + return nil, nil, sdk.NewError(sdk.CodespaceRoot, sdk.CodeType(resp.Code), resp.Log) } return resp.Value, resp.Proof, nil diff --git a/store/state/value_test.go b/store/state/value_test.go index 88f75c32bdbb..38888890bbdf 100644 --- a/store/state/value_test.go +++ b/store/state/value_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/libs/log" dbm "github.com/tendermint/tm-db" @@ -30,6 +31,7 @@ func key() (res []byte) { } type value interface { + KeyBytes() []byte Get(Context, interface{}) GetSafe(Context, interface{}) error GetRaw(Context) []byte @@ -37,6 +39,7 @@ type value interface { SetRaw(Context, []byte) Exists(Context) bool Delete(Context) + Query(ABCIQuerier, interface{}) (*Proof, error) Marshal(interface{}) []byte Unmarshal([]byte, interface{}) } @@ -110,6 +113,15 @@ func (v booleanT) Unmarshal(bz []byte, ptr interface{}) { } } +func (v booleanT) Query(q ABCIQuerier, ptr interface{}) (proof *Proof, err error) { + res, proof, err := v.Boolean.Query(q) + if err != nil { + return + } + reflect.ValueOf(ptr).Elem().SetBool(res) + return +} + type integerT struct { Integer } @@ -153,6 +165,15 @@ func (v integerT) Unmarshal(bz []byte, ptr interface{}) { reflect.ValueOf(ptr).Elem().SetUint(res) } +func (v integerT) Query(q ABCIQuerier, ptr interface{}) (proof *Proof, err error) { + res, proof, err := v.Integer.Query(q) + if err != nil { + return + } + reflect.ValueOf(ptr).Elem().SetUint(res) + return +} + type enumT struct { Enum } @@ -192,6 +213,15 @@ func (v enumT) Unmarshal(bz []byte, ptr interface{}) { reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(bz[0])) } +func (v enumT) Query(q ABCIQuerier, ptr interface{}) (proof *Proof, err error) { + res, proof, err := v.Enum.Query(q) + if err != nil { + return + } + reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(res)) + return +} + type stringT struct { String } @@ -231,13 +261,22 @@ func (v stringT) Unmarshal(bz []byte, ptr interface{}) { reflect.ValueOf(ptr).Elem().SetString(string(bz)) } -func defaultComponents() sdk.Context { +func (v stringT) Query(q ABCIQuerier, ptr interface{}) (proof *Proof, err error) { + res, proof, err := v.String.Query(q) + if err != nil { + return + } + reflect.ValueOf(ptr).Elem().SetString(res) + return +} + +func defaultComponents() (sdk.Context, *rootmulti.Store) { db := dbm.NewMemDB() cms := rootmulti.NewStore(db) cms.MountStoreWithDB(testkey, sdk.StoreTypeIAVL, db) cms.LoadLatestVersion() ctx := sdk.NewContext(cms, abci.Header{}, false, log.NewNopLogger()) - return ctx + return ctx, cms } func indirect(ptr interface{}) interface{} { @@ -245,7 +284,7 @@ func indirect(ptr interface{}) interface{} { } func TestTypeValue(t *testing.T) { - ctx := defaultComponents() + ctx, cms := defaultComponents() var table = []struct { ty typeValue @@ -296,5 +335,19 @@ func TestTypeValue(t *testing.T) { require.Error(t, err) require.Equal(t, reflect.Zero(reflect.TypeOf(ptr).Elem()).Interface(), indirect(ptr)) require.Nil(t, v.GetRaw(ctx)) + + // Set again and test abci query + v.Set(ctx, tc.orig) + cid := cms.Commit() + ptr = v.Proto() + q := NewStoreQuerier(cms) + proof, err := v.Query(q, ptr) + require.NoError(t, err) + require.Equal(t, tc.orig, indirect(ptr), "Expected equal on tc %d", i) + prt := rootmulti.DefaultProofRuntime() + kp := merkle.KeyPath{}. + AppendKey([]byte(testkey.Name()), merkle.KeyEncodingHex). + AppendKey(v.KeyBytes(), merkle.KeyEncodingHex) + require.NoError(t, prt.VerifyValue(proof, cid.Hash, kp.String(), v.GetRaw(ctx))) } } From b4d74913b49a3d1b5d81481df1ec4ad8a27b4228 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 18 Sep 2019 19:33:20 +0200 Subject: [PATCH 164/182] reflect downstream change --- x/ibc/02-client/cli.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index db03c1441329..67740d181748 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -3,7 +3,7 @@ package client import ( "bytes" - "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/store/state" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -12,14 +12,14 @@ func (obj Object) prefix() []byte { return bytes.Split(obj.ConsensusState.KeyBytes(), LocalRoot())[0] } -func (obj Object) ConsensusStateCLI(ctx context.CLIContext) (res ConsensusState, proof merkle.Proof, err error) { - tmproof, err := obj.ConsensusState.Query(ctx, &res) +func (obj Object) ConsensusStateCLI(q state.ABCIQuerier) (res ConsensusState, proof merkle.Proof, err error) { + tmproof, err := obj.ConsensusState.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.ConsensusState) return } -func (obj Object) FrozenCLI(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - res, tmproof, err := obj.Frozen.Query(ctx) +func (obj Object) FrozenCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { + res, tmproof, err := obj.Frozen.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Frozen) return } From de1a0454c4ad97d06a05785a90628f5b1e598df8 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 18 Sep 2019 19:37:22 +0200 Subject: [PATCH 165/182] fix cli --- x/ibc/02-client/client/cli/query.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index c4238dae8cdb..624cfd7af9ff 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -48,11 +48,12 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) + q := state.NewCLIQuerier(ctx) mapp := mapping(cdc, storeKey, ibc.Version) man := client.NewManager(mapp) id := args[0] - state, _, err := man.Object(id).ConsensusStateCLI(ctx) + state, _, err := man.Object(id).ConsensusStateCLI(q) if err != nil { return err } From a60058963f193bb0217e1a2807902315b4648328 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 18 Sep 2019 19:44:42 +0200 Subject: [PATCH 166/182] reflect downstream changes --- x/ibc/03-connection/cli.go | 33 +++++++++++------------ x/ibc/03-connection/client/cli/query.go | 13 ++++----- x/ibc/03-connection/client/cli/tx.go | 36 +++++++++++++------------ 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 2a6c65d7c824..c9450bd150db 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -3,8 +3,7 @@ package connection import ( "bytes" - "github.com/cosmos/cosmos-sdk/client/context" - + "github.com/cosmos/cosmos-sdk/store/state" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -18,20 +17,20 @@ func (obj Object) prefix() []byte { return bytes.Split(obj.Connection.KeyBytes(), LocalRoot())[0] } -func (obj Object) ConnectionCLI(ctx context.CLIContext) (res Connection, proof merkle.Proof, err error) { - tmproof, err := obj.Connection.Query(ctx, &res) +func (obj Object) ConnectionCLI(q state.ABCIQuerier) (res Connection, proof merkle.Proof, err error) { + tmproof, err := obj.Connection.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Connection) return } -func (obj Object) AvailableCLI(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - res, tmproof, err := obj.Available.Query(ctx) +func (obj Object) AvailableCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { + res, tmproof, err := obj.Available.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Available) return } -func (obj Object) KindCLI(ctx context.CLIContext) (res string, proof merkle.Proof, err error) { - res, tmproof, err := obj.Kind.Query(ctx) +func (obj Object) KindCLI(q state.ABCIQuerier) (res string, proof merkle.Proof, err error) { + res, tmproof, err := obj.Kind.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Kind) return } @@ -40,9 +39,9 @@ func (man Handshaker) CLIObject(connid, clientid string) HandshakeObject { return man.Object(man.man.CLIObject(connid, clientid)) } -func (man Handshaker) CLIQuery(ctx context.CLIContext, connid string) (HandshakeObject, error) { +func (man Handshaker) CLIQuery(q state.ABCIQuerier, connid string) (HandshakeObject, error) { obj := man.man.Object(connid) - conn, _, err := obj.ConnectionCLI(ctx) + conn, _, err := obj.ConnectionCLI(q) if err != nil { return HandshakeObject{}, err } @@ -50,20 +49,20 @@ func (man Handshaker) CLIQuery(ctx context.CLIContext, connid string) (Handshake return man.Object(obj), nil } -func (obj HandshakeObject) StateCLI(ctx context.CLIContext) (res byte, proof merkle.Proof, err error){ - res, tmproof, err := obj.State.Query(ctx) +func (obj HandshakeObject) StateCLI(q state.ABCIQuerier) (res byte, proof merkle.Proof, err error) { + res, tmproof, err := obj.State.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) return } -func (obj HandshakeObject) CounterpartyClientCLI(ctx context.CLIContext) (res string, proof merkle.Proof, err error) { - res, tmproof, err := obj.CounterpartyClient.Query(ctx) +func (obj HandshakeObject) CounterpartyClientCLI(q state.ABCIQuerier) (res string, proof merkle.Proof, err error) { + res, tmproof, err := obj.CounterpartyClient.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.CounterpartyClient) - return + return } -func (obj HandshakeObject) NextTimeoutCLI(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error){ - res, tmproof, err := obj.NextTimeout.Query(ctx) +func (obj HandshakeObject) NextTimeoutCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { + res, tmproof, err := obj.NextTimeout.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.NextTimeout) return } diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index efc330969faa..4c6c4a06f1e0 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -13,8 +13,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/utils" ) @@ -22,7 +22,6 @@ const ( FlagProve = "prove" ) - func object(cdc *codec.Codec, storeKey string, prefix []byte, connid, clientid string) connection.Object { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) @@ -45,15 +44,17 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { } func QueryConnection(ctx context.CLIContext, obj connection.Object, prove bool) (res utils.JSONObject, err error) { - conn, connp, err := obj.ConnectionCLI(ctx) + q := state.NewCLIQuerier(ctx) + + conn, connp, err := obj.ConnectionCLI(q) if err != nil { return } - avail, availp, err := obj.AvailableCLI(ctx) + avail, availp, err := obj.AvailableCLI(q) if err != nil { return } - kind, kindp, err := obj.KindCLI(ctx) + kind, kindp, err := obj.KindCLI(q) if err != nil { return } diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 68283021c36e..afac66e2f6a0 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -14,9 +14,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/client/utils" "github.com/cosmos/cosmos-sdk/x/ibc" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) /* @@ -31,11 +31,11 @@ const ( FlagFrom2 = "from2" ) -func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, prefix []byte, connid string) (connection.HandshakeObject, error) { +func handshake(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, connid string) (connection.HandshakeObject, error) { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) man := connection.NewHandshaker(connection.NewManager(base, climan)) - return man.CLIQuery(ctx, connid) + return man.CLIQuery(q, connid) } func lastheight(ctx context.CLIContext) (uint64, error) { @@ -64,11 +64,13 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command WithCodec(cdc). WithNodeURI(viper.GetString(FlagNode1)). WithFrom(viper.GetString(FlagFrom1)) + q1 := state.NewCLIQuerier(ctx1) ctx2 := context.NewCLIContext(). WithCodec(cdc). WithNodeURI(viper.GetString(FlagNode2)). WithFrom(viper.GetString(FlagFrom2)) + q2 := state.NewCLIQuerier(ctx2) conn1id := args[0] conn1bz, err := ioutil.ReadFile(args[1]) @@ -80,7 +82,7 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } - obj1, err := handshake(ctx1, cdc, storeKey, ibc.VersionPrefix(ibc.Version), conn1id) + obj1, err := handshake(q1, cdc, storeKey, ibc.VersionPrefix(ibc.Version), conn1id) if err != nil { return err } @@ -95,7 +97,7 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } - obj2, err := handshake(ctx2, cdc, storeKey, ibc.VersionPrefix(ibc.Version), conn1id) + obj2, err := handshake(q2, cdc, storeKey, ibc.VersionPrefix(ibc.Version), conn1id) if err != nil { return err } @@ -125,19 +127,19 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } nextTimeout = height + 1000 - _, pconn, err := obj1.ConnectionCLI(ctx1) + _, pconn, err := obj1.ConnectionCLI(q1) if err != nil { return err } - _, pstate, err := obj1.StateCLI(ctx1) + _, pstate, err := obj1.StateCLI(q1) if err != nil { return err } - _, ptimeout, err := obj1.NextTimeoutCLI(ctx1) + _, ptimeout, err := obj1.NextTimeoutCLI(q1) if err != nil { return err } - _, pcounter, err := obj1.CounterpartyClientCLI(ctx1) + _, pcounter, err := obj1.CounterpartyClientCLI(q1) if err != nil { return err } @@ -163,19 +165,19 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command return err } nextTimeout = height + 1000 - _, pconn, err = obj2.ConnectionCLI(ctx2) + _, pconn, err = obj2.ConnectionCLI(q2) if err != nil { return err } - _, pstate, err = obj2.StateCLI(ctx2) + _, pstate, err = obj2.StateCLI(q2) if err != nil { return err } - _, ptimeout, err = obj2.NextTimeoutCLI(ctx2) + _, ptimeout, err = obj2.NextTimeoutCLI(q2) if err != nil { return err } - _, pcounter, err = obj2.CounterpartyClientCLI(ctx2) + _, pcounter, err = obj2.CounterpartyClientCLI(q2) if err != nil { return err } @@ -194,11 +196,11 @@ func GetCmdConnectionHandshake(storeKey string, cdc *codec.Codec) *cobra.Command } timeout = nextTimeout - _, pstate, err = obj1.StateCLI(ctx1) + _, pstate, err = obj1.StateCLI(q1) if err != nil { return err } - _, ptimeout, err = obj1.NextTimeoutCLI(ctx1) + _, ptimeout, err = obj1.NextTimeoutCLI(q1) if err != nil { return err } From c90ed2d5c688d1886d36d9ff813901ce8ea793f2 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 18 Sep 2019 19:46:00 +0200 Subject: [PATCH 167/182] reflect downstream changes --- x/ibc/04-channel/cli.go | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index acfbb9bd8d0f..cfac26ab4090 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -3,8 +3,7 @@ package channel import ( "bytes" - "github.com/cosmos/cosmos-sdk/client/context" - + "github.com/cosmos/cosmos-sdk/store/state" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -16,9 +15,9 @@ func (man Manager) CLIObject(portid, chanid string, connids []string) Object { return obj } -func (man Manager) CLIQuery(ctx context.CLIContext, portid, chanid string) (obj Object, err error) { +func (man Manager) CLIQuery(q state.ABCIQuerier, portid, chanid string) (obj Object, err error) { obj = man.object(portid, chanid) - channel, _, err := obj.ChannelCLI(ctx) + channel, _, err := obj.ChannelCLI(q) if err != nil { return } @@ -32,39 +31,39 @@ func (obj Object) prefix() []byte { return bytes.Split(obj.Channel.KeyBytes(), LocalRoot())[0] } -func (obj Object) ChannelCLI(ctx context.CLIContext) (res Channel, proof merkle.Proof, err error) { - tmproof, err := obj.Channel.Query(ctx, &res) +func (obj Object) ChannelCLI(q state.ABCIQuerier) (res Channel, proof merkle.Proof, err error) { + tmproof, err := obj.Channel.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Channel) return } -func (obj Object) AvailableCLI(ctx context.CLIContext) (res bool, proof merkle.Proof, err error) { - res, tmproof, err := obj.Available.Query(ctx) +func (obj Object) AvailableCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { + res, tmproof, err := obj.Available.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Available) return } -func (obj Object) SeqSendCLI(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { - res, tmproof, err := obj.SeqSend.Query(ctx) +func (obj Object) SeqSendCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { + res, tmproof, err := obj.SeqSend.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.SeqSend) return } -func (obj Object) SeqRecvCLI(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { - res, tmproof, err := obj.SeqRecv.Query(ctx) +func (obj Object) SeqRecvCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { + res, tmproof, err := obj.SeqRecv.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.SeqRecv) return } -func (obj Object) PacketCLI(ctx context.CLIContext, index uint64) (res Packet, proof merkle.Proof, err error) { +func (obj Object) PacketCLI(q state.ABCIQuerier, index uint64) (res Packet, proof merkle.Proof, err error) { packet := obj.Packets.Value(index) - tmproof, err := packet.Query(ctx, &res) + tmproof, err := packet.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), packet) return } -func (man Handshaker) CLIQuery(ctx context.CLIContext, portid, chanid string) (HandshakeObject, error) { - obj, err := man.man.CLIQuery(ctx, portid, chanid) +func (man Handshaker) CLIQuery(q state.ABCIQuerier, portid, chanid string) (HandshakeObject, error) { + obj, err := man.man.CLIQuery(q, portid, chanid) if err != nil { return HandshakeObject{}, err } @@ -75,14 +74,14 @@ func (man Handshaker) CLIObject(portid, chanid string, connids []string) Handsha return man.object(man.man.CLIObject(portid, chanid, connids)) } -func (obj HandshakeObject) StateCLI(ctx context.CLIContext) (res State, proof merkle.Proof, err error) { - res, tmproof, err := obj.State.Query(ctx) +func (obj HandshakeObject) StateCLI(q state.ABCIQuerier) (res State, proof merkle.Proof, err error) { + res, tmproof, err := obj.State.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) return } -func (obj HandshakeObject) NextTimeoutCLI(ctx context.CLIContext) (res uint64, proof merkle.Proof, err error) { - res, tmproof, err := obj.NextTimeout.Query(ctx) +func (obj HandshakeObject) NextTimeoutCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { + res, tmproof, err := obj.NextTimeout.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.NextTimeout) return } From cbfb04392de101b1cedf73dbc2728021664fed4d Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 18 Sep 2019 23:42:51 +0200 Subject: [PATCH 168/182] fix from address in tx cli --- x/ibc/03-connection/client/cli/tx.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index c9e7d9ac78e9..0983dc8012e7 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -76,16 +76,14 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { fmt.Println(0000) txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) - ctx1 := context.NewCLIContext(). + ctx1 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom1)). WithCodec(cdc). - WithNodeURI(viper.GetString(FlagNode1)). - WithFrom(viper.GetString(FlagFrom1)) + WithNodeURI(viper.GetString(FlagNode1)) q1 := state.NewCLIQuerier(ctx1) - ctx2 := context.NewCLIContext(). + ctx2 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom2)). WithCodec(cdc). - WithNodeURI(viper.GetString(FlagNode2)). - WithFrom(viper.GetString(FlagFrom2)) + WithNodeURI(viper.GetString(FlagNode2)) q2 := state.NewCLIQuerier(ctx2) fmt.Println(3333) From b15a44d5fe24912d2daa0e07188c371114071097 Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 19 Sep 2019 14:08:06 +0200 Subject: [PATCH 169/182] fix cli in progress(squash later) --- x/ibc/03-connection/client/cli/tx.go | 7 ++-- x/ibc/03-connection/codec.go | 24 +++++++++++++ x/ibc/03-connection/handler.go | 8 ++--- x/ibc/03-connection/handshake.go | 12 +++---- x/ibc/03-connection/manager.go | 2 +- x/ibc/03-connection/msgs.go | 51 ++++++++++++++-------------- x/ibc/23-commitment/store.go | 2 ++ x/ibc/module.go | 2 ++ 8 files changed, 69 insertions(+), 39 deletions(-) create mode 100644 x/ibc/03-connection/codec.go diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 0983dc8012e7..01f8daf5ffe2 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" @@ -78,12 +79,14 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom1)). WithCodec(cdc). - WithNodeURI(viper.GetString(FlagNode1)) + WithNodeURI(viper.GetString(FlagNode1)). + WithBroadcastMode(flags.BroadcastBlock) q1 := state.NewCLIQuerier(ctx1) ctx2 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom2)). WithCodec(cdc). - WithNodeURI(viper.GetString(FlagNode2)) + WithNodeURI(viper.GetString(FlagNode2)). + WithBroadcastMode(flags.BroadcastBlock) q2 := state.NewCLIQuerier(ctx2) fmt.Println(3333) diff --git a/x/ibc/03-connection/codec.go b/x/ibc/03-connection/codec.go new file mode 100644 index 000000000000..49d5c7678fdd --- /dev/null +++ b/x/ibc/03-connection/codec.go @@ -0,0 +1,24 @@ +package connection + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +var MsgCdc *codec.Codec + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterConcrete(MsgOpenInit{}, "ibc/client/MsgOpenInit", nil) + cdc.RegisterConcrete(MsgOpenTry{}, "ibc/client/MsgOpenTry", nil) + cdc.RegisterConcrete(MsgOpenAck{}, "ibc/client/MsgOpenAck", nil) + cdc.RegisterConcrete(MsgOpenConfirm{}, "ibc/client/MsgOpenConfirm", nil) +} + +func SetMsgCodec(cdc *codec.Codec) { + // TODO + /* + if MsgCdc != nil && MsgCdc != cdc { + panic("MsgCdc set more than once") + } + */ + MsgCdc = cdc +} diff --git a/x/ibc/03-connection/handler.go b/x/ibc/03-connection/handler.go index 738ba38da7e0..ab306b90b25d 100644 --- a/x/ibc/03-connection/handler.go +++ b/x/ibc/03-connection/handler.go @@ -7,7 +7,7 @@ import ( func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Result { _, err := man.OpenInit(ctx, msg.ConnectionID, msg.Connection, msg.CounterpartyClient, msg.NextTimeout) if err != nil { - return sdk.NewError(sdk.CodespaceType("ibc"), 100, "").Result() + return sdk.NewError(sdk.CodespaceType("ibc"), 100, err.Error()).Result() } return sdk.Result{} } @@ -15,7 +15,7 @@ func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Res func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Result { _, err := man.OpenTry(ctx, msg.Proofs, msg.ConnectionID, msg.Connection, msg.CounterpartyClient, msg.Timeout, msg.NextTimeout) if err != nil { - return sdk.NewError(sdk.CodespaceType("ibc"), 200, "").Result() + return sdk.NewError(sdk.CodespaceType("ibc"), 200, err.Error()).Result() } return sdk.Result{} } @@ -23,7 +23,7 @@ func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Resul func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Result { _, err := man.OpenAck(ctx, msg.Proofs, msg.ConnectionID, msg.Timeout, msg.NextTimeout) if err != nil { - return sdk.NewError(sdk.CodespaceType("ibc"), 300, "").Result() + return sdk.NewError(sdk.CodespaceType("ibc"), 300, err.Error()).Result() } return sdk.Result{} } @@ -31,7 +31,7 @@ func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Resul func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) sdk.Result { _, err := man.OpenConfirm(ctx, msg.Proofs, msg.ConnectionID, msg.Timeout) if err != nil { - return sdk.NewError(sdk.CodespaceType("ibc"), 400, "").Result() + return sdk.NewError(sdk.CodespaceType("ibc"), 400, err.Error()).Result() } return sdk.Result{} } diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index ab956b428d55..3a929094d53d 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -140,7 +140,7 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{connection,state,nextTimeout,counterpartyClient, client} func (man Handshaker) OpenTry(ctx sdk.Context, - proofs []commitment.Proof, + proofs []commitment.Proof, height uint64, id string, connection Connection, counterpartyClient string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.create(ctx, id, connection, counterpartyClient) @@ -148,7 +148,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, connection.Path, proofs) + ctx, err = obj.Context(ctx, connection.Path, height, proofs) if err != nil { return } @@ -206,7 +206,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{connection, state, timeout, counterpartyClient, client} func (man Handshaker) OpenAck(ctx sdk.Context, - proofs []commitment.Proof, + proofs []commitment.Proof, height uint64, id string /*expheight uint64, */, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) @@ -214,7 +214,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, nil, proofs) + ctx, err = obj.Context(ctx, obj.GetConnection(ctx).Path, height, proofs) if err != nil { return } @@ -269,7 +269,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // Using proofs: counterparty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, - proofs []commitment.Proof, + proofs []commitment.Proof, height uint64, id string, timeoutHeight uint64) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) @@ -277,7 +277,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, nil, proofs) + ctx, err = obj.Context(ctx, obj.GetConnection(ctx).Path, height, proofs) if err != nil { return } diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index de1f7219200b..85c0152e5925 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -102,7 +102,7 @@ func (man CounterpartyManager) Object(id string) CounterObject { } } -func (obj Object) Context(ctx sdk.Context, optpath commitment.Path, proofs []commitment.Proof) (sdk.Context, error) { +func (obj Object) Context(ctx sdk.Context, optpath commitment.Path, height uint64, proofs []commitment.Proof) (sdk.Context, error) { if optpath == nil { optpath = obj.GetConnection(ctx).Path } diff --git a/x/ibc/03-connection/msgs.go b/x/ibc/03-connection/msgs.go index 3944599ff6a3..4f0ae1945825 100644 --- a/x/ibc/03-connection/msgs.go +++ b/x/ibc/03-connection/msgs.go @@ -2,18 +2,17 @@ package connection import ( sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) const Route = "ibc" type MsgOpenInit struct { - ConnectionID string - Connection Connection - CounterpartyClient string - NextTimeout uint64 - Signer sdk.AccAddress + ConnectionID string `json:"connection_id"` + Connection Connection `json:"connection"` + CounterpartyClient string `json:"counterparty_client"` + NextTimeout uint64 `json:"next_timeout"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenInit{} @@ -31,7 +30,7 @@ func (msg MsgOpenInit) ValidateBasic() sdk.Error { } func (msg MsgOpenInit) GetSignBytes() []byte { - return nil // TODO + return sdk.MustSortJSON(MsgCdc.MustMarshalJSON(msg)) } func (msg MsgOpenInit) GetSigners() []sdk.AccAddress { @@ -39,13 +38,13 @@ func (msg MsgOpenInit) GetSigners() []sdk.AccAddress { } type MsgOpenTry struct { - ConnectionID string - Connection Connection - CounterpartyClient string - Timeout uint64 - NextTimeout uint64 - Proofs []commitment.Proof - Signer sdk.AccAddress + ConnectionID string `json:"connection_id"` + Connection Connection `json:"connection"` + CounterpartyClient string `json:"counterparty_client"` + Timeout uint64 `json:"timeout"` + NextTimeout uint64 `json:"next_timeout"` + Proofs []commitment.Proof `json:"proofs"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenTry{} @@ -63,7 +62,7 @@ func (msg MsgOpenTry) ValidateBasic() sdk.Error { } func (msg MsgOpenTry) GetSignBytes() []byte { - return nil // TODO + return sdk.MustSortJSON(MsgCdc.MustMarshalJSON(msg)) } func (msg MsgOpenTry) GetSigners() []sdk.AccAddress { @@ -71,11 +70,11 @@ func (msg MsgOpenTry) GetSigners() []sdk.AccAddress { } type MsgOpenAck struct { - ConnectionID string - Timeout uint64 - NextTimeout uint64 - Proofs []commitment.Proof - Signer sdk.AccAddress + ConnectionID string `json:"connection_id"` + Timeout uint64 `json:"timeout"` + NextTimeout uint64 `json:"next_timeout"` + Proofs []commitment.Proof `json:"proofs"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenAck{} @@ -93,7 +92,7 @@ func (msg MsgOpenAck) ValidateBasic() sdk.Error { } func (msg MsgOpenAck) GetSignBytes() []byte { - return nil // TODO + return sdk.MustSortJSON(MsgCdc.MustMarshalJSON(msg)) } func (msg MsgOpenAck) GetSigners() []sdk.AccAddress { @@ -101,10 +100,10 @@ func (msg MsgOpenAck) GetSigners() []sdk.AccAddress { } type MsgOpenConfirm struct { - ConnectionID string - Timeout uint64 - Proofs []commitment.Proof - Signer sdk.AccAddress + ConnectionID string `json:"connection_id"` + Timeout uint64 `json:"timeout"` + Proofs []commitment.Proof `json:"proofs"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenConfirm{} diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index 923a065334ea..2894561d316b 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -60,6 +60,7 @@ func NewStore(root Root, path Path, proofs []Proof) (res *store, err error) { err = errors.New("proof type not matching with root's") return } + fmt.Println("set", string(proof.GetKey())) res.proofs[string(proof.GetKey())] = proof } @@ -85,6 +86,7 @@ func (store *store) Prove(key, value []byte) bool { } err := proof.Verify(store.root, store.path, value) if err != nil { + fmt.Println(222, string(key), err) return false } store.verified[string(key)] = value diff --git a/x/ibc/module.go b/x/ibc/module.go index 2be7ba8ed4d5..602930a9525b 100644 --- a/x/ibc/module.go +++ b/x/ibc/module.go @@ -45,10 +45,12 @@ func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { commitment.RegisterCodec(cdc) merkle.RegisterCodec(cdc) client.RegisterCodec(cdc) + connection.RegisterCodec(cdc) tendermint.RegisterCodec(cdc) channel.RegisterCodec(cdc) client.SetMsgCodec(cdc) + connection.SetMsgCodec(cdc) channel.SetMsgCodec(cdc) } From 8820838f43bcd55f588a17b613d0127b4db9078f Mon Sep 17 00:00:00 2001 From: mossid Date: Thu, 19 Sep 2019 22:38:48 +0200 Subject: [PATCH 170/182] fix cli --- store/state/enum.go | 3 + x/ibc/02-client/cli.go | 8 ++ x/ibc/02-client/client/cli/query.go | 32 ++++++- x/ibc/02-client/manager.go | 9 ++ x/ibc/02-client/types.go | 2 +- x/ibc/03-connection/client/cli/tx.go | 113 +++++++++++++++++++++++-- x/ibc/03-connection/handler.go | 6 +- x/ibc/03-connection/handshake.go | 6 +- x/ibc/03-connection/manager.go | 12 +-- x/ibc/03-connection/msgs.go | 3 + x/ibc/03-connection/tests/types.go | 32 +++---- x/ibc/04-channel/handler.go | 6 +- x/ibc/04-channel/handshake.go | 12 +-- x/ibc/04-channel/manager.go | 8 +- x/ibc/04-channel/msgs.go | 78 +++++++++-------- x/ibc/04-channel/port.go | 4 +- x/ibc/04-channel/tests/channel_test.go | 2 +- x/ibc/04-channel/tests/types.go | 22 ++--- x/ibc/23-commitment/merkle/merkle.go | 14 +-- x/ibc/ante.go | 2 +- x/ibc/version/version.go | 2 +- 21 files changed, 267 insertions(+), 109 deletions(-) diff --git a/store/state/enum.go b/store/state/enum.go index c580dca614aa..18937ce18bf7 100644 --- a/store/state/enum.go +++ b/store/state/enum.go @@ -56,5 +56,8 @@ func (v Enum) Transit(ctx Context, from, to byte) bool { // Query() retrives state value and proof from a queryable reference func (v Enum) Query(q ABCIQuerier) (res byte, proof *Proof, err error) { value, proof, err := v.Value.QueryRaw(q) + if err != nil { + return + } return value[0], proof, err } diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 67740d181748..29533883c76a 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -12,6 +13,13 @@ func (obj Object) prefix() []byte { return bytes.Split(obj.ConsensusState.KeyBytes(), LocalRoot())[0] } +func (obj Object) RootCLI(q state.ABCIQuerier, height uint64) (res commitment.Root, proof merkle.Proof, err error) { + root := obj.Roots.Value(height) + tmproof, err := root.Query(q, &res) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), root) + return +} + func (obj Object) ConsensusStateCLI(q state.ABCIQuerier) (res ConsensusState, proof merkle.Proof, err error) { tmproof, err := obj.ConsensusState.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.ConsensusState) diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 79cff3198df4..49a5ac8b65dc 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -20,8 +20,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/version" ) -func mapping(cdc *codec.Codec, storeKey string, version int64) state.Mapping { - prefix := []byte(strconv.FormatInt(version, 10) + "/") +func mapping(cdc *codec.Codec, storeKey string, v int64) state.Mapping { + prefix := version.Prefix(v) return state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) } @@ -38,6 +38,7 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { GetCmdQueryPath(storeKey, cdc), GetCmdQueryHeader(cdc), GetCmdQueryClient(storeKey, cdc), + GetCmdQueryRoot(storeKey, cdc), )...) return ibcQueryCmd } @@ -66,6 +67,33 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { } } +func GetCmdQueryRoot(storeKey string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "root", + Short: "Query stored root", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + q := state.NewCLIQuerier(ctx) + mapp := mapping(cdc, storeKey, version.Version) + man := client.NewManager(mapp) + id := args[0] + height, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + root, _, err := man.Object(id).RootCLI(q, height) + if err != nil { + return err + } + + fmt.Printf("%s\n", codec.MustMarshalJSONIndent(cdc, root)) + + return nil + }, + } +} func GetCmdQueryConsensusState(storeKey string, cdc *codec.Codec) *cobra.Command { return &cobra.Command{ Use: "consensus-state", diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index eb9a83ff7d2e..1a732c6dc824 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -43,6 +43,7 @@ func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { func (man Manager) Object(id string) Object { return Object{ id: id, + Roots: man.protocol.Prefix([]byte(id + "/roots/")).Indexer(state.Dec), ConsensusState: man.protocol.Value([]byte(id)), Frozen: man.protocol.Value([]byte(id + "/freeze")).Boolean(), } @@ -53,6 +54,7 @@ func (man Manager) Create(ctx sdk.Context, id string, cs ConsensusState) (Object if obj.exists(ctx) { return Object{}, errors.New("Create client on already existing id") } + obj.Roots.Set(ctx, cs.GetHeight(), cs.GetRoot()) obj.ConsensusState.Set(ctx, cs) return obj, nil } @@ -79,6 +81,7 @@ func (man CounterpartyManager) Query(id string) CounterObject { // Any actor holding the Object can access on and modify that client information type Object struct { id string + Roots state.Indexer ConsensusState state.Value // ConsensusState Frozen state.Boolean } @@ -97,6 +100,11 @@ func (obj Object) GetConsensusState(ctx sdk.Context) (res ConsensusState) { return } +func (obj Object) GetRoot(ctx sdk.Context, height uint64) (res commitment.Root, err error) { + err = obj.Roots.GetSafe(ctx, height, &res) + return +} + func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { return obj.ConsensusState.Is(ctx, client) } @@ -121,6 +129,7 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { } obj.ConsensusState.Set(ctx, updated) + obj.Roots.Set(ctx, updated.GetHeight(), updated.GetRoot()) return nil } diff --git a/x/ibc/02-client/types.go b/x/ibc/02-client/types.go index 134837a43aa8..36ba2b307913 100644 --- a/x/ibc/02-client/types.go +++ b/x/ibc/02-client/types.go @@ -1,7 +1,7 @@ package client import ( - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) // TODO: types in this file should be (de/)serialized with proto in the future diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 01f8daf5ffe2..277a128cf7e2 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -3,10 +3,13 @@ package cli import ( "fmt" "io/ioutil" + "time" "github.com/spf13/cobra" "github.com/spf13/viper" + tmtypes "github.com/tendermint/tendermint/types" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" @@ -17,6 +20,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/client/utils" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/version" @@ -68,6 +72,45 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { return cmd } +// TODO: move to 02/tendermint +func getHeader(ctx context.CLIContext) (res tendermint.Header, err error) { + node, err := ctx.GetNode() + if err != nil { + return + } + + info, err := node.ABCIInfo() + if err != nil { + return + } + + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return + } + + nextvalidators, err := node.Validators(&height) + if err != nil { + return + } + + res = tendermint.Header{ + SignedHeader: commit.SignedHeader, + ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + } + + return +} + func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "handshake", @@ -75,7 +118,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(6), // Args: []string{connid1, clientid1, path1, connid2, clientid2, connfilepath2} RunE: func(cmd *cobra.Command, args []string) error { - fmt.Println(0000) txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom1)). WithCodec(cdc). @@ -133,7 +175,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - fmt.Println(111) // TODO: check state and if not Idle continue existing process height, err := lastheight(ctx2) if err != nil { @@ -153,13 +194,35 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - fmt.Println(222) + // Another block has to be passed after msginit is commited + // to retrieve the correct proofs + time.Sleep(8 * time.Second) + + header, err := getHeader(ctx1) + if err != nil { + return err + } + + msgupdate := client.MsgUpdateClient{ + ClientID: conn2.Client, + Header: header, + Signer: ctx2.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + + fmt.Printf("updated apphash to %X\n", header.AppHash) + + q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) + fmt.Printf("querying from %d\n", header.Height-1) + timeout := nextTimeout height, err = lastheight(ctx1) if err != nil { return err } nextTimeout = height + 1000 + _, pconn, err := obj1.ConnectionCLI(q1) if err != nil { return err @@ -184,16 +247,35 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Timeout: timeout, NextTimeout: nextTimeout, Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Height: uint64(header.Height), Signer: ctx2.GetFromAddress(), } - fmt.Println(444) err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) if err != nil { return err } - timeout = nextTimeout + + // Another block has to be passed after msginit is commited + // to retrieve the correct proofs + time.Sleep(8 * time.Second) + + header, err = getHeader(ctx2) + if err != nil { + return err + } + + msgupdate = client.MsgUpdateClient{ + ClientID: conn1.Client, + Header: header, + Signer: ctx2.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgupdate}) + + q2 = state.NewCLIQuerier(ctx2.WithHeight(header.Height - 1)) + height, err = lastheight(ctx2) if err != nil { return err @@ -221,6 +303,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Timeout: timeout, NextTimeout: nextTimeout, Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Height: uint64(header.Height), Signer: ctx1.GetFromAddress(), } @@ -229,6 +312,25 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } + // Another block has to be passed after msginit is commited + // to retrieve the correct proofs + time.Sleep(8 * time.Second) + + header, err = getHeader(ctx1) + if err != nil { + return err + } + + msgupdate = client.MsgUpdateClient{ + ClientID: conn2.Client, + Header: header, + Signer: ctx2.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + + q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) + timeout = nextTimeout _, pstate, err = obj1.StateCLI(q1) if err != nil { @@ -243,6 +345,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { ConnectionID: connid2, Timeout: timeout, Proofs: []commitment.Proof{pstate, ptimeout}, + Height: uint64(header.Height), Signer: ctx2.GetFromAddress(), } diff --git a/x/ibc/03-connection/handler.go b/x/ibc/03-connection/handler.go index ab306b90b25d..8509e6b58c65 100644 --- a/x/ibc/03-connection/handler.go +++ b/x/ibc/03-connection/handler.go @@ -13,7 +13,7 @@ func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Res } func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Result { - _, err := man.OpenTry(ctx, msg.Proofs, msg.ConnectionID, msg.Connection, msg.CounterpartyClient, msg.Timeout, msg.NextTimeout) + _, err := man.OpenTry(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.Connection, msg.CounterpartyClient, msg.Timeout, msg.NextTimeout) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 200, err.Error()).Result() } @@ -21,7 +21,7 @@ func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Resul } func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Result { - _, err := man.OpenAck(ctx, msg.Proofs, msg.ConnectionID, msg.Timeout, msg.NextTimeout) + _, err := man.OpenAck(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.Timeout, msg.NextTimeout) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 300, err.Error()).Result() } @@ -29,7 +29,7 @@ func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Resul } func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) sdk.Result { - _, err := man.OpenConfirm(ctx, msg.Proofs, msg.ConnectionID, msg.Timeout) + _, err := man.OpenConfirm(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.Timeout) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 400, err.Error()).Result() } diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 3a929094d53d..342d87d5cdd6 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -148,7 +148,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, connection.Path, height, proofs) + ctx, err = obj.Context(ctx, height, proofs) if err != nil { return } @@ -214,7 +214,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, obj.GetConnection(ctx).Path, height, proofs) + ctx, err = obj.Context(ctx, height, proofs) if err != nil { return } @@ -277,7 +277,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, obj.GetConnection(ctx).Path, height, proofs) + ctx, err = obj.Context(ctx, height, proofs) if err != nil { return } diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 85c0152e5925..57e5a3456fea 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -102,15 +102,15 @@ func (man CounterpartyManager) Object(id string) CounterObject { } } -func (obj Object) Context(ctx sdk.Context, optpath commitment.Path, height uint64, proofs []commitment.Proof) (sdk.Context, error) { - if optpath == nil { - optpath = obj.GetConnection(ctx).Path +func (obj Object) Context(ctx sdk.Context, height uint64, proofs []commitment.Proof) (sdk.Context, error) { + root, err := obj.Client.GetRoot(ctx, height) + if err != nil { + return ctx, err } store, err := commitment.NewStore( - // TODO: proof root should be able to be obtained from the past - obj.Client.GetConsensusState(ctx).GetRoot(), - optpath, + root, + obj.GetConnection(ctx).Path, proofs, ) if err != nil { diff --git a/x/ibc/03-connection/msgs.go b/x/ibc/03-connection/msgs.go index 4f0ae1945825..5848558554b0 100644 --- a/x/ibc/03-connection/msgs.go +++ b/x/ibc/03-connection/msgs.go @@ -44,6 +44,7 @@ type MsgOpenTry struct { Timeout uint64 `json:"timeout"` NextTimeout uint64 `json:"next_timeout"` Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` Signer sdk.AccAddress `json:"signer"` } @@ -74,6 +75,7 @@ type MsgOpenAck struct { Timeout uint64 `json:"timeout"` NextTimeout uint64 `json:"next_timeout"` Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` Signer sdk.AccAddress `json:"signer"` } @@ -103,6 +105,7 @@ type MsgOpenConfirm struct { ConnectionID string `json:"connection_id"` Timeout uint64 `json:"timeout"` Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` Signer sdk.AccAddress `json:"signer"` } diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 9fbd375aa4b3..a0c27dd3e768 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -9,10 +9,10 @@ import ( "github.com/cosmos/cosmos-sdk/store/state" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" - "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + tendermint "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint/tests" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) type Node struct { @@ -29,8 +29,8 @@ type Node struct { func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res := &Node{ - Name: "self", // hard coded, doesnt matter - Node: tendermint.NewNode(self, "teststoreself", []byte("protocol/")), // TODO: test with key prefix + Name: "self", // hard coded, doesnt matter + Node: tendermint.NewNode(self, "teststoreself", []byte("protocol/")), State: connection.Idle, Cdc: cdc, @@ -59,7 +59,7 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { } // TODO: typeify v -func (node *Node) QueryValue(t *testing.T, v interface{KeyBytes() []byte}) ([]byte, commitment.Proof) { +func (node *Node) QueryValue(t *testing.T, v interface{ KeyBytes() []byte }) ([]byte, commitment.Proof) { return node.Query(t, v.KeyBytes()) } @@ -119,9 +119,9 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { node.SetState(connection.Init) } -func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { +func (node *Node) OpenTry(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, proofs, node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs, height, node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.OpenTry, obj.State.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) @@ -130,9 +130,9 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { node.SetState(connection.OpenTry) } -func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { +func (node *Node) OpenAck(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, proofs, node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs, height, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) @@ -140,9 +140,9 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { node.SetState(connection.Open) } -func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { +func (node *Node) OpenConfirm(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, proofs, node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs, height, node.Name, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, connection.Open, obj.State.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) @@ -170,7 +170,7 @@ func (node *Node) Handshake(t *testing.T) { _, pcounterclient := node.QueryValue(t, cliobj.CounterpartyClient) // TODO: implement consensus state checking // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) - node.Counterparty.OpenTry(t, pconn, pstate, ptimeout, pcounterclient) + node.Counterparty.OpenTry(t, uint64(header.Height), pconn, pstate, ptimeout, pcounterclient) header = node.Counterparty.Commit() // self.OpenAck @@ -180,7 +180,7 @@ func (node *Node) Handshake(t *testing.T) { _, pstate = node.Counterparty.QueryValue(t, cliobj.State) _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) _, pcounterclient = node.Counterparty.QueryValue(t, cliobj.CounterpartyClient) - node.OpenAck(t, pconn, pstate, ptimeout, pcounterclient) + node.OpenAck(t, uint64(header.Height), pconn, pstate, ptimeout, pcounterclient) header = node.Commit() // counterparty.OpenConfirm @@ -188,5 +188,5 @@ func (node *Node) Handshake(t *testing.T) { cliobj = node.CLIObject() _, pstate = node.QueryValue(t, cliobj.State) _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) - node.Counterparty.OpenConfirm(t, pstate, ptimeout) + node.Counterparty.OpenConfirm(t, uint64(header.Height), pstate, ptimeout) } diff --git a/x/ibc/04-channel/handler.go b/x/ibc/04-channel/handler.go index 76d9ace3e6e4..bb18de6e17e8 100644 --- a/x/ibc/04-channel/handler.go +++ b/x/ibc/04-channel/handler.go @@ -13,7 +13,7 @@ func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Res } func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Result { - _, err := man.OpenTry(ctx, msg.Proofs, msg.ConnectionID, msg.ChannelID, msg.Channel, msg.Timeout, msg.NextTimeout) + _, err := man.OpenTry(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.ChannelID, msg.Channel, msg.Timeout, msg.NextTimeout) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 200, "").Result() } @@ -21,7 +21,7 @@ func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Resul } func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Result { - _, err := man.OpenAck(ctx, msg.Proofs, msg.ConnectionID, msg.ChannelID, msg.Timeout, msg.NextTimeout) + _, err := man.OpenAck(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.ChannelID, msg.Timeout, msg.NextTimeout) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 300, "").Result() } @@ -29,7 +29,7 @@ func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Resul } func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) sdk.Result { - _, err := man.OpenConfirm(ctx, msg.Proofs, msg.ConnectionID, msg.ChannelID, msg.Timeout) + _, err := man.OpenConfirm(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.ChannelID, msg.Timeout) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 400, "").Result() } diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index 9b946ab4165e..d0cb14574c47 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -148,7 +148,7 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{channel,state,nextTimeout} func (man Handshaker) OpenTry(ctx sdk.Context, - proofs []commitment.Proof, + proofs []commitment.Proof, height uint64, portid, chanid string, channel Channel, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { if len(channel.ConnectionHops) != 1 { @@ -159,7 +159,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, proofs) + ctx, err = obj.Context(ctx, proofs, height) if err != nil { return } @@ -213,7 +213,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenAck(ctx sdk.Context, - proofs []commitment.Proof, + proofs []commitment.Proof, height uint64, portid, chanid string, timeoutHeight, nextTimeoutHeight uint64, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, portid, chanid) @@ -221,7 +221,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - ctx, err = obj.Context(ctx, proofs) + ctx, err = obj.Context(ctx, proofs, height) if err != nil { return } @@ -274,14 +274,14 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // Using proofs: counterparty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, - proofs []commitment.Proof, + proofs []commitment.Proof, height uint64, portid, chanid string, timeoutHeight uint64) (obj HandshakeObject, err error) { obj, err = man.query(ctx, portid, chanid) if err != nil { return } - ctx, err = obj.Context(ctx, proofs) + ctx, err = obj.Context(ctx, proofs, height) if err != nil { return } diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index ad33e6453d4f..0920e9119e65 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -223,8 +223,8 @@ func (obj Object) OriginConnection() connection.Object { return obj.Connections[0] } -func (obj Object) Context(ctx sdk.Context, proofs []commitment.Proof) (sdk.Context, error) { - return obj.OriginConnection().Context(ctx, nil, proofs) +func (obj Object) Context(ctx sdk.Context, proofs []commitment.Proof, height uint64) (sdk.Context, error) { + return obj.OriginConnection().Context(ctx, height, proofs) } func (obj Object) ChanID() string { @@ -287,7 +287,7 @@ func (man Manager) Send(ctx sdk.Context, portid, chanid string, packet Packet) e return nil } -func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, portid, chanid string, packet Packet) error { +func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, height uint64, portid, chanid string, packet Packet) error { obj, err := man.Query(ctx, portid, chanid) if err != nil { return err @@ -299,7 +299,7 @@ func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, portid, c } */ - ctx, err = obj.Context(ctx, proofs) + ctx, err = obj.Context(ctx, proofs, height) if err != nil { return err } diff --git a/x/ibc/04-channel/msgs.go b/x/ibc/04-channel/msgs.go index c12f4a338b1a..adb764900798 100644 --- a/x/ibc/04-channel/msgs.go +++ b/x/ibc/04-channel/msgs.go @@ -8,12 +8,12 @@ import ( const Route = "ibc" type MsgOpenInit struct { - ConnectionID string - ChannelID string - Channel Channel - CounterpartyClient string - NextTimeout uint64 - Signer sdk.AccAddress + ConnectionID string `json:"connection_id"` + ChannelID string `json:"channel_id"` + Channel Channel `json:"channel"` + CounterpartyClient string `json:"counterparty_client"` + NextTimeout uint64 `json:"next_timeout"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenInit{} @@ -31,7 +31,7 @@ func (msg MsgOpenInit) ValidateBasic() sdk.Error { } func (msg MsgOpenInit) GetSignBytes() []byte { - return nil // TODO + return sdk.MustSortJSON(msgCdc.MustMarshalJSON(msg)) } func (msg MsgOpenInit) GetSigners() []sdk.AccAddress { @@ -39,14 +39,15 @@ func (msg MsgOpenInit) GetSigners() []sdk.AccAddress { } type MsgOpenTry struct { - ConnectionID string - ChannelID string - Channel Channel - CounterpartyClient string - Timeout uint64 - NextTimeout uint64 - Proofs []commitment.Proof - Signer sdk.AccAddress + ConnectionID string `json:"connection_id"` + ChannelID string `json:"channel_id"` + Channel Channel `json:"channel"` + CounterpartyClient string `json:"counterparty_client"` + Timeout uint64 `json:"timeout"` + NextTimeout uint64 `json:"next_timeout"` + Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenTry{} @@ -64,7 +65,7 @@ func (msg MsgOpenTry) ValidateBasic() sdk.Error { } func (msg MsgOpenTry) GetSignBytes() []byte { - return nil // TODO + return sdk.MustSortJSON(msgCdc.MustMarshalJSON(msg)) } func (msg MsgOpenTry) GetSigners() []sdk.AccAddress { @@ -72,12 +73,13 @@ func (msg MsgOpenTry) GetSigners() []sdk.AccAddress { } type MsgOpenAck struct { - ConnectionID string - ChannelID string - Timeout uint64 - NextTimeout uint64 - Proofs []commitment.Proof - Signer sdk.AccAddress + ConnectionID string `json:"connection_id"` + ChannelID string `json:"channel_id"` + Timeout uint64 `json:"timeout"` + NextTimeout uint64 `json:"next_timeout"` + Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenAck{} @@ -95,7 +97,7 @@ func (msg MsgOpenAck) ValidateBasic() sdk.Error { } func (msg MsgOpenAck) GetSignBytes() []byte { - return nil // TODO + return sdk.MustSortJSON(msgCdc.MustMarshalJSON(msg)) } func (msg MsgOpenAck) GetSigners() []sdk.AccAddress { @@ -103,11 +105,12 @@ func (msg MsgOpenAck) GetSigners() []sdk.AccAddress { } type MsgOpenConfirm struct { - ConnectionID string - ChannelID string - Timeout uint64 - Proofs []commitment.Proof - Signer sdk.AccAddress + ConnectionID string `json:"connection_id"` + ChannelID string `json:"channel_id"` + Timeout uint64 `json:"timeout"` + Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenConfirm{} @@ -125,21 +128,22 @@ func (msg MsgOpenConfirm) ValidateBasic() sdk.Error { } func (msg MsgOpenConfirm) GetSignBytes() []byte { - return nil // TODO + return sdk.MustSortJSON(msgCdc.MustMarshalJSON(msg)) } func (msg MsgOpenConfirm) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.Signer} } +// PortID dependent on type +// ChannelID can be empty if batched & not first MsgPacket +// Height uint64 // height of the commitment root for the proofs type MsgPacket struct { - Packet `json:"packet" yaml:"packet"` - // PortID dependent on type - // ChannelID can be empty if batched & not first MsgPacket - ChannelID string `json:"channel_id,omitempty" yaml:"channel_id"` - // Height uint64 // height of the commitment root for the proofs - Proofs []commitment.Proof `json:"proofs" yaml:"proofs"` - Signer sdk.AccAddress `json:"signer,omitempty" yaml:"signer"` + Packet `json:"packet" yaml:"packet"` + ChannelID string `json:"channel_id,omitempty" yaml:"channel_id"` + Proofs []commitment.Proof `json:"proofs" yaml:"proofs"` + Height uint64 `json:"height" yaml:"height"` + Signer sdk.AccAddress `json:"signer,omitempty" yaml:"signer"` } var _ sdk.Msg = MsgPacket{} @@ -157,7 +161,7 @@ func (msg MsgPacket) Route() string { } func (msg MsgPacket) GetSignBytes() []byte { - return msgCdc.MustMarshalJSON(msg) // TODO: Sort + return sdk.MustSortJSON(msgCdc.MustMarshalJSON(msg)) } func (msg MsgPacket) GetSigners() []sdk.AccAddress { diff --git a/x/ibc/04-channel/port.go b/x/ibc/04-channel/port.go index dfa8738655b2..8c06a1e6f12f 100644 --- a/x/ibc/04-channel/port.go +++ b/x/ibc/04-channel/port.go @@ -35,6 +35,6 @@ func (port Port) Send(ctx sdk.Context, chanid string, packet Packet) error { return port.channel.Send(ctx, port.id, chanid, packet) } -func (port Port) Receive(ctx sdk.Context, proof []commitment.Proof, chanid string, packet Packet) error { - return port.channel.Receive(ctx, proof, port.id, chanid, packet) +func (port Port) Receive(ctx sdk.Context, proof []commitment.Proof, height uint64, chanid string, packet Packet) error { + return port.channel.Receive(ctx, proof, height, port.id, chanid, packet) } diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go index fbc8b01a3a76..432709585414 100644 --- a/x/ibc/04-channel/tests/channel_test.go +++ b/x/ibc/04-channel/tests/channel_test.go @@ -98,5 +98,5 @@ func TestPacket(t *testing.T) { node.Counterparty.UpdateClient(t, header) cliobj := node.CLIObject() _, ppacket := node.QueryValue(t, cliobj.Packets.Value(1)) - node.Counterparty.Receive(t, MyPacket{"ping"}, ppacket) + node.Counterparty.Receive(t, MyPacket{"ping"}, uint64(header.Height), ppacket) } diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index d9ca7089241a..1079fccfc8c0 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -92,9 +92,9 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { require.False(t, obj.Available.Get(ctx)) } -func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { +func (node *Node) OpenTry(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, proofs, PortName, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs, height, PortName, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.OpenTry, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -102,9 +102,9 @@ func (node *Node) OpenTry(t *testing.T, proofs ...commitment.Proof) { node.SetState(channel.OpenTry) } -func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { +func (node *Node) OpenAck(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, proofs, PortName, node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs, height, PortName, node.Name, 100 /*TODO*/, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.Open, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -112,9 +112,9 @@ func (node *Node) OpenAck(t *testing.T, proofs ...commitment.Proof) { node.SetState(channel.Open) } -func (node *Node) OpenConfirm(t *testing.T, proofs ...commitment.Proof) { +func (node *Node) OpenConfirm(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, proofs, PortName, node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs, height, PortName, node.Name, 100 /*TODO*/) require.NoError(t, err) require.Equal(t, channel.Open, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -135,7 +135,7 @@ func (node *Node) Handshake(t *testing.T) { _, pchan := node.QueryValue(t, cliobj.Channel) _, pstate := node.QueryValue(t, cliobj.State) _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) - node.Counterparty.OpenTry(t, pchan, pstate, ptimeout) + node.Counterparty.OpenTry(t, uint64(header.Height), pchan, pstate, ptimeout) header = node.Counterparty.Commit() // self.OpenAck @@ -144,7 +144,7 @@ func (node *Node) Handshake(t *testing.T) { _, pchan = node.Counterparty.QueryValue(t, cliobj.Channel) _, pstate = node.Counterparty.QueryValue(t, cliobj.State) _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) - node.OpenAck(t, pchan, pstate, ptimeout) + node.OpenAck(t, uint64(header.Height), pchan, pstate, ptimeout) header = node.Commit() // counterparty.OpenConfirm @@ -152,7 +152,7 @@ func (node *Node) Handshake(t *testing.T) { cliobj = node.CLIObject() _, pstate = node.QueryValue(t, cliobj.State) _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) - node.Counterparty.OpenConfirm(t, pstate, ptimeout) + node.Counterparty.OpenConfirm(t, uint64(header.Height), pstate, ptimeout) } func (node *Node) Send(t *testing.T, packet channel.Packet) { @@ -166,12 +166,12 @@ func (node *Node) Send(t *testing.T, packet channel.Packet) { require.Equal(t, node.Cdc.MustMarshalBinaryBare(packet), obj.PacketCommit(ctx, seq+1)) } -func (node *Node) Receive(t *testing.T, packet channel.Packet, proofs ...commitment.Proof) { +func (node *Node) Receive(t *testing.T, packet channel.Packet, height uint64, proofs ...commitment.Proof) { ctx, man := node.Context(), node.Manager() obj, err := man.Query(ctx, PortName, node.Name) require.NoError(t, err) seq := obj.SeqRecv.Get(ctx) - err = man.Receive(ctx, proofs, PortName, node.Name, packet) + err = man.Receive(ctx, proofs, height, PortName, node.Name, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqRecv.Get(ctx)) } diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index 1606497ec4f8..7ca7579d9eb8 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -7,7 +7,7 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" "github.com/cosmos/cosmos-sdk/store/rootmulti" -// "github.com/cosmos/cosmos-sdk/store/state" + // "github.com/cosmos/cosmos-sdk/store/state" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -20,7 +20,7 @@ var _ commitment.Root = Root{} // Root is Merkle root hash type Root struct { - Hash []byte + Hash []byte `json:"hash"` } // NewRoot constructs a new Root @@ -41,9 +41,9 @@ var _ commitment.Path = Path{} // The constructed key from the Path and the key will be append(Path.KeyPath, append(Path.KeyPrefix, key...)) type Path struct { // KeyPath is the list of keys prepended before the prefixed key - KeyPath [][]byte + KeyPath [][]byte `json:"key_path"` // KeyPrefix is a byte slice prefixed before the key - KeyPrefix []byte + KeyPrefix []byte `json:"key_prefix"` } // NewPath() constructs new Path @@ -63,8 +63,8 @@ var _ commitment.Proof = Proof{} // Proof is Merkle proof with the key information. type Proof struct { - Proof *merkle.Proof - Key []byte + Proof *merkle.Proof `json:"proof"` + Key []byte `json:"key"` } // Implements commitment.Proof @@ -93,7 +93,7 @@ func (proof Proof) Verify(croot commitment.Root, cpath commitment.Path, value [] for _, key := range path.KeyPath { keypath = keypath.AppendKey(key, merkle.KeyEncodingHex) } - keypath = keypath.AppendKey(append(path.KeyPrefix, proof.Key...), merkle.KeyEncodingHex) + keypath = keypath.AppendKey(append(path.KeyPrefix, proof.Key...), merkle.KeyEncodingHex) // TODO: hard coded for now, should be extensible runtime := rootmulti.DefaultProofRuntime() diff --git a/x/ibc/ante.go b/x/ibc/ante.go index 696275ea08a6..ae0a00315a05 100644 --- a/x/ibc/ante.go +++ b/x/ibc/ante.go @@ -31,7 +31,7 @@ func ExtractMsgPackets(msgs []sdk.Msg) (res []MsgPacket, abort bool) { func VerifyMsgPackets(ctx sdk.Context, channel channel.Manager, msgs []MsgPacket) error { for _, msg := range msgs { - err := channel.Receive(ctx, msg.Proofs, msg.ReceiverPort(), msg.ChannelID, msg.Packet) + err := channel.Receive(ctx, msg.Proofs, msg.Height, msg.ReceiverPort(), msg.ChannelID, msg.Packet) if err != nil { return err } diff --git a/x/ibc/version/version.go b/x/ibc/version/version.go index 5c80adf66a24..a7d3275fae5b 100644 --- a/x/ibc/version/version.go +++ b/x/ibc/version/version.go @@ -9,5 +9,5 @@ func DefaultPrefix() []byte { } func Prefix(version int64) []byte { - return []byte(strconv.FormatInt(version, 10) + "/") + return []byte("v" + strconv.FormatInt(version, 10) + "/") } From a72f6c59135bb36a84f4672a3e74220666708276 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 20 Sep 2019 18:11:21 +0200 Subject: [PATCH 171/182] remove timeout, add channel cli --- x/ibc/03-connection/cli.go | 6 - x/ibc/03-connection/client/cli/tx.go | 46 +-- x/ibc/03-connection/client/utils/types.go | 5 - x/ibc/03-connection/handler.go | 8 +- x/ibc/03-connection/handshake.go | 162 +------- x/ibc/03-connection/tests/types.go | 17 +- x/ibc/04-channel/cli.go | 6 - x/ibc/04-channel/client/cli/query.go | 79 +++- x/ibc/04-channel/client/cli/tx.go | 440 ++++++++++++++-------- x/ibc/04-channel/handler.go | 8 +- x/ibc/04-channel/handshake.go | 76 +--- x/ibc/04-channel/msgs.go | 48 +-- x/ibc/04-channel/tests/types.go | 19 +- x/ibc/04-channel/types.go | 3 +- x/ibc/module.go | 5 +- 15 files changed, 408 insertions(+), 520 deletions(-) diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index c9450bd150db..7fa3986465d7 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -60,9 +60,3 @@ func (obj HandshakeObject) CounterpartyClientCLI(q state.ABCIQuerier) (res strin proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.CounterpartyClient) return } - -func (obj HandshakeObject) NextTimeoutCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { - res, tmproof, err := obj.NextTimeout.Query(q) - proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.NextTimeout) - return -} diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 277a128cf7e2..0ecb6c97cf61 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -131,7 +131,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { WithBroadcastMode(flags.BroadcastBlock) q2 := state.NewCLIQuerier(ctx2) - fmt.Println(3333) connid1 := args[0] clientid1 := args[1] connid2 := args[3] @@ -176,16 +175,10 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { } // TODO: check state and if not Idle continue existing process - height, err := lastheight(ctx2) - if err != nil { - return err - } - nextTimeout := height + 1000 // TODO: parameterize msginit := connection.MsgOpenInit{ ConnectionID: connid1, Connection: conn1, CounterpartyClient: conn2.Client, - NextTimeout: nextTimeout, Signer: ctx1.GetFromAddress(), } @@ -216,13 +209,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) fmt.Printf("querying from %d\n", header.Height-1) - timeout := nextTimeout - height, err = lastheight(ctx1) - if err != nil { - return err - } - nextTimeout = height + 1000 - _, pconn, err := obj1.ConnectionCLI(q1) if err != nil { return err @@ -231,10 +217,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } - _, ptimeout, err := obj1.NextTimeoutCLI(q1) - if err != nil { - return err - } _, pcounter, err := obj1.CounterpartyClientCLI(q1) if err != nil { return err @@ -244,9 +226,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { ConnectionID: connid2, Connection: conn2, CounterpartyClient: conn1.Client, - Timeout: timeout, - NextTimeout: nextTimeout, - Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Proofs: []commitment.Proof{pconn, pstate, pcounter}, Height: uint64(header.Height), Signer: ctx2.GetFromAddress(), } @@ -255,7 +235,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } - timeout = nextTimeout // Another block has to be passed after msginit is commited // to retrieve the correct proofs @@ -269,18 +248,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { msgupdate = client.MsgUpdateClient{ ClientID: conn1.Client, Header: header, - Signer: ctx2.GetFromAddress(), + Signer: ctx1.GetFromAddress(), } err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgupdate}) q2 = state.NewCLIQuerier(ctx2.WithHeight(header.Height - 1)) - height, err = lastheight(ctx2) - if err != nil { - return err - } - nextTimeout = height + 1000 _, pconn, err = obj2.ConnectionCLI(q2) if err != nil { return err @@ -289,10 +263,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } - _, ptimeout, err = obj2.NextTimeoutCLI(q2) - if err != nil { - return err - } _, pcounter, err = obj2.CounterpartyClientCLI(q2) if err != nil { return err @@ -300,9 +270,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { msgack := connection.MsgOpenAck{ ConnectionID: connid1, - Timeout: timeout, - NextTimeout: nextTimeout, - Proofs: []commitment.Proof{pconn, pstate, ptimeout, pcounter}, + Proofs: []commitment.Proof{pconn, pstate, pcounter}, Height: uint64(header.Height), Signer: ctx1.GetFromAddress(), } @@ -331,20 +299,14 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) - timeout = nextTimeout _, pstate, err = obj1.StateCLI(q1) if err != nil { return err } - _, ptimeout, err = obj1.NextTimeoutCLI(q1) - if err != nil { - return err - } msgconfirm := connection.MsgOpenConfirm{ ConnectionID: connid2, - Timeout: timeout, - Proofs: []commitment.Proof{pstate, ptimeout}, + Proofs: []commitment.Proof{pstate}, Height: uint64(header.Height), Signer: ctx2.GetFromAddress(), } diff --git a/x/ibc/03-connection/client/utils/types.go b/x/ibc/03-connection/client/utils/types.go index 95989e93d650..9ef404879a4b 100644 --- a/x/ibc/03-connection/client/utils/types.go +++ b/x/ibc/03-connection/client/utils/types.go @@ -17,8 +17,6 @@ type JSONObject struct { StateProof commitment.Proof `json:"state_proof,omitempty"` CounterpartyClient string `json:"counterparty_client,omitempty"` CounterpartyClientProof commitment.Proof `json:"counterparty_client_proof,omitempty"` - NextTimeout uint64 `json:"next_timeout,omitempty"` - NextTimeoutProof commitment.Proof `json:"next_timeout_proof,omitempty"` } func NewJSONObject( @@ -42,7 +40,6 @@ func NewHandshakeJSONObject( kind string, kindp commitment.Proof, state byte, statep commitment.Proof, cpclient string, cpclientp commitment.Proof, - timeout uint64, timeoutp commitment.Proof, ) JSONObject { return JSONObject{ Connection: conn, @@ -56,7 +53,5 @@ func NewHandshakeJSONObject( StateProof: statep, CounterpartyClient: cpclient, CounterpartyClientProof: cpclientp, - NextTimeout: timeout, - NextTimeoutProof: timeoutp, } } diff --git a/x/ibc/03-connection/handler.go b/x/ibc/03-connection/handler.go index 8509e6b58c65..8395579663d2 100644 --- a/x/ibc/03-connection/handler.go +++ b/x/ibc/03-connection/handler.go @@ -5,7 +5,7 @@ import ( ) func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Result { - _, err := man.OpenInit(ctx, msg.ConnectionID, msg.Connection, msg.CounterpartyClient, msg.NextTimeout) + _, err := man.OpenInit(ctx, msg.ConnectionID, msg.Connection, msg.CounterpartyClient) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 100, err.Error()).Result() } @@ -13,7 +13,7 @@ func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Res } func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Result { - _, err := man.OpenTry(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.Connection, msg.CounterpartyClient, msg.Timeout, msg.NextTimeout) + _, err := man.OpenTry(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.Connection, msg.CounterpartyClient) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 200, err.Error()).Result() } @@ -21,7 +21,7 @@ func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Resul } func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Result { - _, err := man.OpenAck(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.Timeout, msg.NextTimeout) + _, err := man.OpenAck(ctx, msg.Proofs, msg.Height, msg.ConnectionID) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 300, err.Error()).Result() } @@ -29,7 +29,7 @@ func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Resul } func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) sdk.Result { - _, err := man.OpenConfirm(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.Timeout) + _, err := man.OpenConfirm(ctx, msg.Proofs, msg.Height, msg.ConnectionID) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 400, err.Error()).Result() } diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 342d87d5cdd6..04eb96fc298f 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -48,7 +48,6 @@ type HandshakeObject struct { State state.Enum CounterpartyClient state.String - NextTimeout state.Integer Counterparty CounterHandshakeObject } @@ -58,7 +57,6 @@ type CounterHandshakeObject struct { State commitment.Enum CounterpartyClient commitment.String - NextTimeout commitment.Integer } // CONTRACT: client and remote must be filled by the caller @@ -68,7 +66,6 @@ func (man Handshaker) Object(parent Object) HandshakeObject { State: man.man.protocol.Value([]byte(parent.id + "/state")).Enum(), CounterpartyClient: man.man.protocol.Value([]byte(parent.id + "/counterpartyClient")).String(), - NextTimeout: man.man.protocol.Value([]byte(parent.id + "/timeout")).Integer(state.Dec), // CONTRACT: counterparty must be filled by the caller } @@ -80,7 +77,6 @@ func (man CounterpartyHandshaker) Object(id string) CounterHandshakeObject { State: man.man.protocol.Value([]byte(id + "/state")).Enum(), CounterpartyClient: man.man.protocol.Value([]byte(id + "/counterpartyClient")).String(), - NextTimeout: man.man.protocol.Value([]byte(id + "/timeout")).Integer(state.Dec), } } @@ -109,20 +105,11 @@ func (obj HandshakeObject) remove(ctx sdk.Context) { obj.Object.remove(ctx) obj.State.Delete(ctx) obj.CounterpartyClient.Delete(ctx) - obj.NextTimeout.Delete(ctx) -} - -func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { - if uint64(ctx.BlockHeight()) > timeoutHeight { - return errors.New("timeout") - } - - return nil } // Using proofs: none func (man Handshaker) OpenInit(ctx sdk.Context, - id string, connection Connection, counterpartyClient string, nextTimeoutHeight uint64, + id string, connection Connection, counterpartyClient string, ) (HandshakeObject, error) { // man.Create() will ensure // assert(get("connections/{identifier}") === null) and @@ -132,7 +119,6 @@ func (man Handshaker) OpenInit(ctx sdk.Context, return HandshakeObject{}, err } - obj.NextTimeout.Set(ctx, nextTimeoutHeight) obj.State.Set(ctx, Init) return obj, nil @@ -141,7 +127,7 @@ func (man Handshaker) OpenInit(ctx sdk.Context, // Using proofs: counterparty.{connection,state,nextTimeout,counterpartyClient, client} func (man Handshaker) OpenTry(ctx sdk.Context, proofs []commitment.Proof, height uint64, - id string, connection Connection, counterpartyClient string, timeoutHeight, nextTimeoutHeight uint64, + id string, connection Connection, counterpartyClient string, ) (obj HandshakeObject, err error) { obj, err = man.create(ctx, id, connection, counterpartyClient) if err != nil { @@ -153,11 +139,6 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - err = assertTimeout(ctx, timeoutHeight) - if err != nil { - return - } - if !obj.Counterparty.State.Is(ctx, Init) { err = errors.New("counterparty state not init") return @@ -177,11 +158,6 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { - err = errors.New("unexpected counterparty timeout value") - return - } - // TODO: commented out, need to check whether the stored client is compatible // make a separate module that manages recent n block headers // ref #4647 @@ -199,7 +175,6 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // set("connections{identifier}", connection) obj.State.Set(ctx, OpenTry) - obj.NextTimeout.Set(ctx, nextTimeoutHeight) return } @@ -207,7 +182,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{connection, state, timeout, counterpartyClient, client} func (man Handshaker) OpenAck(ctx sdk.Context, proofs []commitment.Proof, height uint64, - id string /*expheight uint64, */, timeoutHeight, nextTimeoutHeight uint64, + id string, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) if err != nil { @@ -224,11 +199,6 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - err = assertTimeout(ctx, timeoutHeight) - if err != nil { - return - } - if !obj.Counterparty.Connection.Is(ctx, Connection{ Client: obj.CounterpartyClient.Get(ctx), Counterparty: obj.ID(), @@ -248,11 +218,6 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { - err = errors.New("unexpected counterparty timeout value") - return - } - // TODO: implement in v1 /* var expected client.ConsensusState @@ -262,7 +227,6 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } */ obj.Available.Set(ctx, true) - obj.NextTimeout.Set(ctx, nextTimeoutHeight) return } @@ -270,7 +234,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // Using proofs: counterparty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, proofs []commitment.Proof, height uint64, - id string, timeoutHeight uint64) (obj HandshakeObject, err error) { + id string) (obj HandshakeObject, err error) { obj, err = man.query(ctx, id) if err != nil { @@ -287,130 +251,12 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - err = assertTimeout(ctx, timeoutHeight) - if err != nil { - return - } - if !obj.Counterparty.State.Is(ctx, Open) { err = errors.New("counterparty state not open") return } - if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { - err = errors.New("unexpected counterparty timeout value") - return - } - obj.Available.Set(ctx, true) - obj.NextTimeout.Set(ctx, 0) return } - -func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { - if !(obj.Client.GetConsensusState(ctx).GetHeight() > obj.NextTimeout.Get(ctx)) { - return errors.New("timeout height not yet reached") - } - - switch obj.State.Get(ctx) { - case Init: - if !obj.Counterparty.Connection.Is(ctx, nil) { - return errors.New("counterparty connection exists") - } - case OpenTry: - if !(obj.Counterparty.State.Is(ctx, Init) || - obj.Counterparty.Connection.Is(ctx, nil)) { - return errors.New("counterparty connection state not init") - } - // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) - case Open: - if obj.Counterparty.State.Is(ctx, OpenTry) { - return errors.New("counterparty connection state not tryopen") - } - } - - obj.remove(ctx) - - return nil -} - -func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error { - if !obj.State.Transit(ctx, Open, CloseTry) { - return errors.New("closeinit on non-open connection") - } - - obj.NextTimeout.Set(ctx, nextTimeout) - - return nil -} - -func (obj HandshakeObject) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { - if !obj.State.Transit(ctx, Open, Closed) { - return errors.New("closetry on non-open connection") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.Counterparty.State.Is(ctx, CloseTry) { - return errors.New("unexpected counterparty state value") - } - - if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { - return errors.New("unexpected counterparty timeout value") - } - - obj.NextTimeout.Set(ctx, nextTimeoutHeight) - - return nil -} - -func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { - if !obj.State.Transit(ctx, CloseTry, Closed) { - return errors.New("closeack on non-closetry connection") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.Counterparty.State.Is(ctx, Closed) { - return errors.New("unexpected counterparty state value") - } - - if !obj.Counterparty.NextTimeout.Is(ctx, timeoutHeight) { - return errors.New("unexpected counterparty timeout value") - } - - obj.NextTimeout.Set(ctx, 0) - - return nil -} - -func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { - if !(obj.Client.GetConsensusState(ctx).GetHeight() > obj.NextTimeout.Get(ctx)) { - return errors.New("timeout height not yet reached") - } - - // XXX: double check if the user can bypass the verification logic somehow - switch obj.State.Get(ctx) { - case CloseTry: - if !obj.Counterparty.State.Is(ctx, Open) { - return errors.New("counterparty connection state not open") - } - case Closed: - if !obj.Counterparty.State.Is(ctx, CloseTry) { - return errors.New("counterparty connection state not closetry") - } - } - - obj.State.Set(ctx, Open) - obj.NextTimeout.Set(ctx, 0) - - return nil - -} diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index a0c27dd3e768..0162b392b494 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -110,7 +110,7 @@ func (node *Node) Manager() (client.Manager, connection.Manager) { func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenInit(ctx, node.Name, node.Connection, node.CounterpartyClient, 100) // TODO: test timeout + obj, err := man.OpenInit(ctx, node.Name, node.Connection, node.CounterpartyClient) require.NoError(t, err) require.Equal(t, connection.Init, obj.State.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) @@ -121,7 +121,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenTry(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, proofs, height, node.Name, node.Connection, node.CounterpartyClient, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs, height, node.Name, node.Connection, node.CounterpartyClient) require.NoError(t, err) require.Equal(t, connection.OpenTry, obj.State.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) @@ -132,7 +132,7 @@ func (node *Node) OpenTry(t *testing.T, height uint64, proofs ...commitment.Proo func (node *Node) OpenAck(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, proofs, height, node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs, height, node.Name) require.NoError(t, err) require.Equal(t, connection.Open, obj.State.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) @@ -142,7 +142,7 @@ func (node *Node) OpenAck(t *testing.T, height uint64, proofs ...commitment.Proo func (node *Node) OpenConfirm(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, proofs, height, node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs, height, node.Name) require.NoError(t, err) require.Equal(t, connection.Open, obj.State.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) @@ -166,11 +166,10 @@ func (node *Node) Handshake(t *testing.T) { cliobj := node.CLIObject() _, pconn := node.QueryValue(t, cliobj.Connection) _, pstate := node.QueryValue(t, cliobj.State) - _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) _, pcounterclient := node.QueryValue(t, cliobj.CounterpartyClient) // TODO: implement consensus state checking // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) - node.Counterparty.OpenTry(t, uint64(header.Height), pconn, pstate, ptimeout, pcounterclient) + node.Counterparty.OpenTry(t, uint64(header.Height), pconn, pstate, pcounterclient) header = node.Counterparty.Commit() // self.OpenAck @@ -178,15 +177,13 @@ func (node *Node) Handshake(t *testing.T) { cliobj = node.Counterparty.CLIObject() _, pconn = node.Counterparty.QueryValue(t, cliobj.Connection) _, pstate = node.Counterparty.QueryValue(t, cliobj.State) - _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) _, pcounterclient = node.Counterparty.QueryValue(t, cliobj.CounterpartyClient) - node.OpenAck(t, uint64(header.Height), pconn, pstate, ptimeout, pcounterclient) + node.OpenAck(t, uint64(header.Height), pconn, pstate, pcounterclient) header = node.Commit() // counterparty.OpenConfirm node.Counterparty.UpdateClient(t, header) cliobj = node.CLIObject() _, pstate = node.QueryValue(t, cliobj.State) - _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) - node.Counterparty.OpenConfirm(t, uint64(header.Height), pstate, ptimeout) + node.Counterparty.OpenConfirm(t, uint64(header.Height), pstate) } diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index 5f624b7af02b..ebf0f1755890 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -79,9 +79,3 @@ func (obj HandshakeObject) StateCLI(q state.ABCIQuerier) (res State, proof merkl proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) return } - -func (obj HandshakeObject) NextTimeoutCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { - res, tmproof, err := obj.NextTimeout.Query(q) - proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.NextTimeout) - return -} diff --git a/x/ibc/04-channel/client/cli/query.go b/x/ibc/04-channel/client/cli/query.go index d50573cdc724..9a5c7d4fb9b7 100644 --- a/x/ibc/04-channel/client/cli/query.go +++ b/x/ibc/04-channel/client/cli/query.go @@ -1,11 +1,28 @@ package cli +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + cli "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/client/utils" + "github.com/cosmos/cosmos-sdk/x/ibc/version" +) + const ( FlagProve = "prove" ) -// TODO -/* func object(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string, connids []string) channel.Object { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) @@ -16,39 +33,36 @@ func object(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid str func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { ibcQueryCmd := &cobra.Command{ - Use: "connection", - Short: "Channel query subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, + Use: "channel", + Short: "Channel query subcommands", + DisableFlagParsing: true, } ibcQueryCmd.AddCommand(cli.GetCommands( - // GetCmdQueryChannel(storeKey, cdc), + GetCmdQueryChannel(storeKey, cdc), )...) + return ibcQueryCmd } func QueryChannel(ctx context.CLIContext, obj channel.Object, prove bool) (res utils.JSONObject, err error) { - conn, connp, err := obj.ChannelCLI(ctx) + q := state.NewCLIQuerier(ctx) + + conn, connp, err := obj.ChannelCLI(q) if err != nil { return } - avail, availp, err := obj.AvailableCLI(ctx) + avail, availp, err := obj.AvailableCLI(q) if err != nil { return } - /* - kind, kindp, err := obj.Kind(ctx) - if err != nil { - return - } - seqsend, seqsendp, err := obj.SeqSendCLI(ctx) + seqsend, seqsendp, err := obj.SeqSendCLI(q) if err != nil { return } - seqrecv, seqrecvp, err := obj.SeqRecvCLI(ctx) + seqrecv, seqrecvp, err := obj.SeqRecvCLI(q) if err != nil { return } @@ -71,15 +85,14 @@ func QueryChannel(ctx context.CLIContext, obj channel.Object, prove bool) (res u ), nil } - func GetCmdQueryChannel(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "connection", Short: "Query stored connection", - Args: cobra.ExactArgs(1), + Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - obj := object(ctx, cdc, storeKey, ibc.Version, args[0], args[1]) + obj := object(cdc, storeKey, version.DefaultPrefix(), args[0], args[1], []string{args[2]}) jsonobj, err := QueryChannel(ctx, obj, viper.GetBool(FlagProve)) if err != nil { return err @@ -95,4 +108,32 @@ func GetCmdQueryChannel(storeKey string, cdc *codec.Codec) *cobra.Command { return cmd } + +/* +func object(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string, connids []string) channel.Object { + base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) + climan := client.NewManager(base) + connman := connection.NewManager(base, climan) + man := channel.NewManager(base, connman) + return man.CLIObject(portid, chanid, connids) +} +*/ +/* +func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ibcQueryCmd := &cobra.Command{ + Use: "connection", + Short: "Channel query subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ibcQueryCmd.AddCommand(cli.GetCommands( + // GetCmdQueryChannel(storeKey, cdc), + )...) + return ibcQueryCmd +} */ +/* + + + */ diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index c166bda866db..90696ee9ab6d 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -1,5 +1,129 @@ +/* + + +func lastheight(ctx context.CLIContext) (uint64, error) { + node, err := ctx.GetNode() + if err != nil { + return 0, err + } + + info, err := node.ABCIInfo() + if err != nil { + return 0, err + } + + return uint64(info.Response.LastBlockHeight), nil +} + +func GetCmdRelay(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "relay", + Short: "relay pakcets between two channels", + Args: cobra.ExactArgs(4), + // Args: []string{connid1, chanid1, chanfilepath1, connid2, chanid2, chanfilepath2} + RunE: func(cmd *cobra.Command, args []string) error { + ctx1 := context.NewCLIContext(). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode1)). + WithFrom(viper.GetString(FlagFrom1)) + + ctx2 := context.NewCLIContext(). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode2)). + WithFrom(viper.GetString(FlagFrom2)) + + conn1id, chan1id, conn2id, chan2id := args[0], args[1], args[2], args[3] + + obj1 := object(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) + obj2 := object(ctx2, cdc, storeKey, ibc.Version, conn2id, chan2id) + + return relayLoop(cdc, ctx1, ctx2, obj1, obj2, conn1id, chan1id, conn2id, chan2id) + }, + } + + return cmd +} + +func relayLoop(cdc *codec.Codec, + ctx1, ctx2 context.CLIContext, + obj1, obj2 channel.CLIObject, + conn1id, chan1id, conn2id, chan2id string, +) error { + for { + // TODO: relay() should be goroutine and return error by channel + err := relay(cdc, ctx1, ctx2, obj1, obj2, conn2id, chan2id) + // TODO: relayBetween() should retry several times before halt + if err != nil { + return err + } + time.Sleep(1 * time.Second) + } +} + +func relay(cdc *codec.Codec, ctxFrom, ctxTo context.CLIContext, objFrom, objTo channel.CLIObject, connidTo, chanidTo string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + + seq, _, err := objTo.SeqRecv(ctxTo) + if err != nil { + return err + } + + sent, _, err := objFrom.SeqSend(ctxFrom) + if err != nil { + return err + } + + for i := seq; i <= sent; i++ { + packet, proof, err := objFrom.Packet(ctxFrom, seq) + if err != nil { + return err + } + + msg := channel.MsgReceive{ + ConnectionID: connidTo, + ChannelID: chanidTo, + Packet: packet, + Proofs: []commitment.Proof{proof}, + Signer: ctxTo.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctxTo, txBldr, []sdk.Msg{msg}) + if err != nil { + return err + } + } + + return nil +} +*/ package cli +import ( + "fmt" + "time" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/state" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + + client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/tendermint" + connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + "github.com/cosmos/cosmos-sdk/x/ibc/version" +) + /* func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -12,92 +136,133 @@ const ( FlagFrom2 = "from2" ) -// TODO -/* -func handshake(ctx context.CLIContext, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.HandshakeObject, error) { +func handshake(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.HandshakeObject, error) { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) connman := connection.NewManager(base, climan) man := channel.NewHandshaker(channel.NewManager(base, connman)) - return man.CLIQuery(ctx, portid, chanid) + return man.CLIQuery(q, portid, chanid) } -func lastheight(ctx context.CLIContext) (uint64, error) { +func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "channel", + Short: "IBC channel transaction subcommands", + } + + cmd.AddCommand( + GetCmdHandshake(storeKey, cdc), + ) + + return cmd +} + +// TODO: move to 02/tendermint +func getHeader(ctx context.CLIContext) (res tendermint.Header, err error) { node, err := ctx.GetNode() if err != nil { - return 0, err + return } info, err := node.ABCIInfo() if err != nil { - return 0, err + return } - return uint64(info.Response.LastBlockHeight), nil + height := info.Response.LastBlockHeight + prevheight := height - 1 + + commit, err := node.Commit(&height) + if err != nil { + return + } + + validators, err := node.Validators(&prevheight) + if err != nil { + return + } + + nextvalidators, err := node.Validators(&height) + if err != nil { + return + } + + res = tendermint.Header{ + SignedHeader: commit.SignedHeader, + ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + } + + return } -func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { +func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "handshake", - Short: "initiate channel handshake between two chains", - Args: cobra.ExactArgs(4), - // Args: []string{connid1, chanid1, chanfilepath1, connid2, chanid2, chanfilepath2} + Short: "initiate connection handshake between two chains", + Args: cobra.ExactArgs(6), + // Args: []string{portid1, chanid1, connid1, portid2, chanid2, connid2} RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) - ctx1 := context.NewCLIContext(). + ctx1 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom1)). WithCodec(cdc). WithNodeURI(viper.GetString(FlagNode1)). - WithFrom(viper.GetString(FlagFrom1)) + WithBroadcastMode(flags.BroadcastBlock) + q1 := state.NewCLIQuerier(ctx1) - ctx2 := context.NewCLIContext(). + ctx2 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom2)). WithCodec(cdc). WithNodeURI(viper.GetString(FlagNode2)). - WithFrom(viper.GetString(FlagFrom2)) - - conn1id := args[0] - chan1id := args[1] - conn1bz, err := ioutil.ReadFile(args[2]) - if err != nil { - return err + WithBroadcastMode(flags.BroadcastBlock) + q2 := state.NewCLIQuerier(ctx2) + + portid1 := args[0] + chanid1 := args[1] + connid1 := args[2] + portid2 := args[3] + chanid2 := args[4] + connid2 := args[5] + + chan1 := channel.Channel{ + Counterparty: chanid2, + CounterpartyPort: portid2, + ConnectionHops: []string{connid1}, } - var conn1 channel.Channel - if err := cdc.UnmarshalJSON(conn1bz, &conn1); err != nil { - return err + + chan2 := channel.Channel{ + Counterparty: chanid1, + CounterpartyPort: portid1, + ConnectionHops: []string{connid2}, } - obj1, err := handshake(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) + obj1, err := handshake(q1, cdc, storeKey, version.DefaultPrefix(), portid1, chanid1) if err != nil { return err } - conn2id := args[3] - chan2id := args[4] - conn2bz, err := ioutil.ReadFile(args[5]) + obj2, err := handshake(q2, cdc, storeKey, version.DefaultPrefix(), portid2, chanid2) if err != nil { return err } - var conn2 channel.Channel - if err := cdc.UnmarshalJSON(conn2bz, &conn2); err != nil { - return err - } - obj2, err := handshake(ctx2, cdc, storeKey, ibc.Version, conn1id, chan1id) + conn1, _, err := obj1.OriginConnection().ConnectionCLI(q1) if err != nil { return err } + clientid1 := conn1.Client - // TODO: check state and if not Idle continue existing process - height, err := lastheight(ctx2) + conn2, _, err := obj2.OriginConnection().ConnectionCLI(q2) if err != nil { return err } - nextTimeout := height + 1000 // TODO: parameterize + clientid2 := conn2.Client + + // TODO: check state and if not Idle continue existing process msginit := channel.MsgOpenInit{ - ConnectionID: conn1id, - ChannelID: chan1id, - Channel: conn1, - NextTimeout: nextTimeout, - Signer: ctx1.GetFromAddress(), + PortID: portid1, + ChannelID: chanid1, + Channel: chan1, + Signer: ctx1.GetFromAddress(), } err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msginit}) @@ -105,33 +270,44 @@ func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - timeout := nextTimeout - height, err = lastheight(ctx1) + // Another block has to be passed after msginit is commited + // to retrieve the correct proofs + time.Sleep(8 * time.Second) + + header, err := getHeader(ctx1) if err != nil { return err } - nextTimeout = height + 1000 - _, pconn, err := obj1.ChannelCLI(ctx1) - if err != nil { - return err + + msgupdate := client.MsgUpdateClient{ + ClientID: clientid2, + Header: header, + Signer: ctx2.GetFromAddress(), } - _, pstate, err := obj1.StateCLI(ctx1) + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + + fmt.Printf("updated apphash to %X\n", header.AppHash) + + q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) + fmt.Printf("querying from %d\n", header.Height-1) + + _, pchan, err := obj1.ChannelCLI(q1) if err != nil { return err } - _, ptimeout, err := obj1.NextTimeoutCLI(ctx1) + _, pstate, err := obj1.StateCLI(q1) if err != nil { return err } msgtry := channel.MsgOpenTry{ - ConnectionID: conn2id, - ChannelID: chan2id, - Channel: conn2, - Timeout: timeout, - NextTimeout: nextTimeout, - Proofs: []commitment.Proof{pconn, pstate, ptimeout}, - Signer: ctx2.GetFromAddress(), + PortID: portid2, + ChannelID: chanid2, + Channel: chan2, + Proofs: []commitment.Proof{pchan, pstate}, + Height: uint64(header.Height), + Signer: ctx2.GetFromAddress(), } err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) @@ -139,31 +315,40 @@ func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - timeout = nextTimeout - height, err = lastheight(ctx2) + // Another block has to be passed after msginit is commited + // to retrieve the correct proofs + time.Sleep(8 * time.Second) + + header, err = getHeader(ctx2) if err != nil { return err } - nextTimeout = height + 1000 - _, pconn, err = obj2.Channel(ctx2) - if err != nil { - return err + + msgupdate = client.MsgUpdateClient{ + ClientID: clientid1, + Header: header, + Signer: ctx1.GetFromAddress(), } - _, pstate, err = obj2.State(ctx2) + + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgupdate}) + + q2 = state.NewCLIQuerier(ctx2.WithHeight(header.Height - 1)) + + _, pchan, err = obj2.ChannelCLI(q2) if err != nil { return err } - _, ptimeout, err = obj2.NextTimeout(ctx2) + _, pstate, err = obj2.StateCLI(q2) if err != nil { return err } msgack := channel.MsgOpenAck{ - ConnectionID: conn1id, - ChannelID: chan1id, - Timeout: timeout, - Proofs: []commitment.Proof{pconn, pstate, ptimeout}, - Signer: ctx1.GetFromAddress(), + PortID: portid1, + ChannelID: chanid1, + Proofs: []commitment.Proof{pchan, pstate}, + Height: uint64(header.Height), + Signer: ctx1.GetFromAddress(), } err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgack}) @@ -171,21 +356,34 @@ func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - timeout = nextTimeout - _, pstate, err = obj1.State(ctx1) + // Another block has to be passed after msginit is commited + // to retrieve the correct proofs + time.Sleep(8 * time.Second) + + header, err = getHeader(ctx1) if err != nil { return err } - _, ptimeout, err = obj1.NextTimeout(ctx1) + + msgupdate = client.MsgUpdateClient{ + ClientID: clientid2, + Header: header, + Signer: ctx2.GetFromAddress(), + } + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + + q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) + + _, pstate, err = obj1.StateCLI(q1) if err != nil { return err } - msgconfirm := channel.MsgOpenConfirm{ - ConnectionID: conn2id, - ChannelID: chan2id, - Timeout: timeout, - Proofs: []commitment.Proof{pstate, ptimeout}, + msgconfirm := connection.MsgOpenConfirm{ + ConnectionID: connid2, + Proofs: []commitment.Proof{pstate}, + Height: uint64(header.Height), Signer: ctx2.GetFromAddress(), } @@ -198,87 +396,13 @@ func GetCmdChannelHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { }, } - return cmd -} - -func GetCmdRelay(storeKey string, cdc *codec.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "relay", - Short: "relay pakcets between two channels", - Args: cobra.ExactArgs(4), - // Args: []string{connid1, chanid1, chanfilepath1, connid2, chanid2, chanfilepath2} - RunE: func(cmd *cobra.Command, args []string) error { - ctx1 := context.NewCLIContext(). - WithCodec(cdc). - WithNodeURI(viper.GetString(FlagNode1)). - WithFrom(viper.GetString(FlagFrom1)) - - ctx2 := context.NewCLIContext(). - WithCodec(cdc). - WithNodeURI(viper.GetString(FlagNode2)). - WithFrom(viper.GetString(FlagFrom2)) - - conn1id, chan1id, conn2id, chan2id := args[0], args[1], args[2], args[3] - - obj1 := object(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) - obj2 := object(ctx2, cdc, storeKey, ibc.Version, conn2id, chan2id) + cmd.Flags().String(FlagNode1, "tcp://localhost:26657", "") + cmd.Flags().String(FlagNode2, "tcp://localhost:26657", "") + cmd.Flags().String(FlagFrom1, "", "") + cmd.Flags().String(FlagFrom2, "", "") - return relayLoop(cdc, ctx1, ctx2, obj1, obj2, conn1id, chan1id, conn2id, chan2id) - }, - } + cmd.MarkFlagRequired(FlagFrom1) + cmd.MarkFlagRequired(FlagFrom2) return cmd } - -func relayLoop(cdc *codec.Codec, - ctx1, ctx2 context.CLIContext, - obj1, obj2 channel.CLIObject, - conn1id, chan1id, conn2id, chan2id string, -) error { - for { - // TODO: relay() should be goroutine and return error by channel - err := relay(cdc, ctx1, ctx2, obj1, obj2, conn2id, chan2id) - // TODO: relayBetween() should retry several times before halt - if err != nil { - return err - } - time.Sleep(1 * time.Second) - } -} - -func relay(cdc *codec.Codec, ctxFrom, ctxTo context.CLIContext, objFrom, objTo channel.CLIObject, connidTo, chanidTo string) error { - txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) - - seq, _, err := objTo.SeqRecv(ctxTo) - if err != nil { - return err - } - - sent, _, err := objFrom.SeqSend(ctxFrom) - if err != nil { - return err - } - - for i := seq; i <= sent; i++ { - packet, proof, err := objFrom.Packet(ctxFrom, seq) - if err != nil { - return err - } - - msg := channel.MsgReceive{ - ConnectionID: connidTo, - ChannelID: chanidTo, - Packet: packet, - Proofs: []commitment.Proof{proof}, - Signer: ctxTo.GetFromAddress(), - } - - err = utils.GenerateOrBroadcastMsgs(ctxTo, txBldr, []sdk.Msg{msg}) - if err != nil { - return err - } - } - - return nil -} -*/ diff --git a/x/ibc/04-channel/handler.go b/x/ibc/04-channel/handler.go index bb18de6e17e8..0ef8f76a1bfd 100644 --- a/x/ibc/04-channel/handler.go +++ b/x/ibc/04-channel/handler.go @@ -5,7 +5,7 @@ import ( ) func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Result { - _, err := man.OpenInit(ctx, msg.ConnectionID, msg.ChannelID, msg.Channel, msg.NextTimeout) + _, err := man.OpenInit(ctx, msg.PortID, msg.ChannelID, msg.Channel) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 100, "").Result() } @@ -13,7 +13,7 @@ func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Res } func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Result { - _, err := man.OpenTry(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.ChannelID, msg.Channel, msg.Timeout, msg.NextTimeout) + _, err := man.OpenTry(ctx, msg.Proofs, msg.Height, msg.PortID, msg.ChannelID, msg.Channel) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 200, "").Result() } @@ -21,7 +21,7 @@ func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Resul } func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Result { - _, err := man.OpenAck(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.ChannelID, msg.Timeout, msg.NextTimeout) + _, err := man.OpenAck(ctx, msg.Proofs, msg.Height, msg.PortID, msg.ChannelID) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 300, "").Result() } @@ -29,7 +29,7 @@ func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Resul } func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) sdk.Result { - _, err := man.OpenConfirm(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.ChannelID, msg.Timeout) + _, err := man.OpenConfirm(ctx, msg.Proofs, msg.Height, msg.PortID, msg.ChannelID) if err != nil { return sdk.NewError(sdk.CodespaceType("ibc"), 400, "").Result() } diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index d0cb14574c47..fd50dfa64476 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -48,8 +48,7 @@ type CounterpartyHandshaker struct { type HandshakeObject struct { Object - State state.Enum - NextTimeout state.Integer + State state.Enum counterparty CounterHandshakeObject } @@ -57,8 +56,7 @@ type HandshakeObject struct { type CounterHandshakeObject struct { CounterObject - State commitment.Enum - NextTimeout commitment.Integer + State commitment.Enum } // CONTRACT: client and remote must be filled by the caller @@ -68,8 +66,7 @@ func (man Handshaker) object(parent Object) HandshakeObject { return HandshakeObject{ Object: parent, - State: man.protocol.Value([]byte(prefix + "/state")).Enum(), - NextTimeout: man.protocol.Value([]byte(prefix + "/timeout")).Integer(state.Dec), + State: man.protocol.Value([]byte(prefix + "/state")).Enum(), counterparty: man.counterparty.object(parent.counterparty), } @@ -81,8 +78,7 @@ func (man CounterpartyHandshaker) object(parent CounterObject) CounterHandshakeO return CounterHandshakeObject{ CounterObject: man.man.object(parent.portid, parent.chanid), - State: man.man.protocol.Value([]byte(prefix + "/state")).Enum(), - NextTimeout: man.man.protocol.Value([]byte(prefix + "/timeout")).Integer(state.Dec), + State: man.man.protocol.Value([]byte(prefix + "/state")).Enum(), } } @@ -125,7 +121,7 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { // Using proofs: none func (man Handshaker) OpenInit(ctx sdk.Context, - portid, chanid string, channel Channel, nextTimeoutHeight uint64, + portid, chanid string, channel Channel, ) (HandshakeObject, error) { // man.Create() will ensure // assert(connectionHops.length === 2) @@ -140,16 +136,15 @@ func (man Handshaker) OpenInit(ctx sdk.Context, return HandshakeObject{}, err } - obj.NextTimeout.Set(ctx, nextTimeoutHeight) obj.State.Set(ctx, Init) return obj, nil } -// Using proofs: counterparty.{channel,state,nextTimeout} +// Using proofs: counterparty.{channel,state} func (man Handshaker) OpenTry(ctx sdk.Context, proofs []commitment.Proof, height uint64, - portid, chanid string, channel Channel, timeoutHeight, nextTimeoutHeight uint64, + portid, chanid string, channel Channel, ) (obj HandshakeObject, err error) { if len(channel.ConnectionHops) != 1 { return HandshakeObject{}, errors.New("ConnectionHops length must be 1") @@ -164,49 +159,26 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - err = assertTimeout(ctx, timeoutHeight) - if err != nil { - return - } - if !obj.counterparty.State.Is(ctx, Init) { err = errors.New("counterparty state not init") return } if !obj.counterparty.Channel.Is(ctx, Channel{ - Port: channel.CounterpartyPort, Counterparty: chanid, - CounterpartyPort: channel.Port, + CounterpartyPort: portid, ConnectionHops: []string{obj.Connections[0].GetConnection(ctx).Counterparty}, }) { err = errors.New("wrong counterparty connection") return } - if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { - err = errors.New("unexpected counterparty timeout value") - return - } - - // TODO: commented out, need to check whether the stored client is compatible - // make a separate module that manages recent n block headers - // ref #4647 - /* - var expected client.ConsensusState - obj.self.Get(ctx, expheight, &expected) - if !obj.counterparty.client.Is(ctx, expected) { - return errors.New("unexpected counterparty client value") - } - */ - // CONTRACT: OpenTry() should be called after man.Create(), not man.Query(), // which will ensure // assert(get("connections/{desiredIdentifier}") === null) and // set("connections{identifier}", connection) obj.State.Set(ctx, OpenTry) - obj.NextTimeout.Set(ctx, nextTimeoutHeight) return } @@ -214,7 +186,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenAck(ctx sdk.Context, proofs []commitment.Proof, height uint64, - portid, chanid string, timeoutHeight, nextTimeoutHeight uint64, + portid, chanid string, ) (obj HandshakeObject, err error) { obj, err = man.query(ctx, portid, chanid) if err != nil { @@ -231,16 +203,9 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - err = assertTimeout(ctx, timeoutHeight) - if err != nil { - return - } - - channel := obj.GetChannel(ctx) if !obj.counterparty.Channel.Is(ctx, Channel{ - Port: channel.CounterpartyPort, Counterparty: chanid, - CounterpartyPort: channel.Port, + CounterpartyPort: portid, ConnectionHops: []string{obj.Connections[0].GetConnection(ctx).Counterparty}, }) { err = errors.New("wrong counterparty") @@ -252,11 +217,6 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { - err = errors.New("unexpected counterparty timeout value") - return - } - // TODO: commented out, implement in v1 /* var expected client.ConsensusState @@ -266,7 +226,6 @@ func (man Handshaker) OpenAck(ctx sdk.Context, } */ - obj.NextTimeout.Set(ctx, nextTimeoutHeight) obj.Available.Set(ctx, true) return @@ -275,7 +234,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, // Using proofs: counterparty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, proofs []commitment.Proof, height uint64, - portid, chanid string, timeoutHeight uint64) (obj HandshakeObject, err error) { + portid, chanid string) (obj HandshakeObject, err error) { obj, err = man.query(ctx, portid, chanid) if err != nil { return @@ -291,23 +250,12 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - err = assertTimeout(ctx, timeoutHeight) - if err != nil { - return - } - if !obj.counterparty.State.Is(ctx, Open) { err = errors.New("counterparty state not open") return } - if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { - err = errors.New("unexpected counterparty timeout value") - return - } - obj.Available.Set(ctx, true) - obj.NextTimeout.Set(ctx, 0) return } @@ -352,7 +300,7 @@ func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error return nil } -func (obj HandshakeObject) CloseTry(ctx sdk.Context, timeoutHeight, nextTimeoutHeight uint64) error { +func (obj HandshakeObject) CloseTry(ctx sdk.Context, nextTimeoutHeight uint64) error { if !obj.State.Transit(ctx, Open, Closed) { return errors.New("closetry on non-open connection") } diff --git a/x/ibc/04-channel/msgs.go b/x/ibc/04-channel/msgs.go index adb764900798..3fba21f320b4 100644 --- a/x/ibc/04-channel/msgs.go +++ b/x/ibc/04-channel/msgs.go @@ -8,12 +8,10 @@ import ( const Route = "ibc" type MsgOpenInit struct { - ConnectionID string `json:"connection_id"` - ChannelID string `json:"channel_id"` - Channel Channel `json:"channel"` - CounterpartyClient string `json:"counterparty_client"` - NextTimeout uint64 `json:"next_timeout"` - Signer sdk.AccAddress `json:"signer"` + PortID string `json:"port_id"` + ChannelID string `json:"channel_id"` + Channel Channel `json:"channel"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenInit{} @@ -39,15 +37,12 @@ func (msg MsgOpenInit) GetSigners() []sdk.AccAddress { } type MsgOpenTry struct { - ConnectionID string `json:"connection_id"` - ChannelID string `json:"channel_id"` - Channel Channel `json:"channel"` - CounterpartyClient string `json:"counterparty_client"` - Timeout uint64 `json:"timeout"` - NextTimeout uint64 `json:"next_timeout"` - Proofs []commitment.Proof `json:"proofs"` - Height uint64 `json:"height"` - Signer sdk.AccAddress `json:"signer"` + PortID string `json:"port_id"` + ChannelID string `json:"channel_id"` + Channel Channel `json:"channel"` + Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenTry{} @@ -73,13 +68,11 @@ func (msg MsgOpenTry) GetSigners() []sdk.AccAddress { } type MsgOpenAck struct { - ConnectionID string `json:"connection_id"` - ChannelID string `json:"channel_id"` - Timeout uint64 `json:"timeout"` - NextTimeout uint64 `json:"next_timeout"` - Proofs []commitment.Proof `json:"proofs"` - Height uint64 `json:"height"` - Signer sdk.AccAddress `json:"signer"` + PortID string `json:"port_id"` + ChannelID string `json:"channel_id"` + Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenAck{} @@ -105,12 +98,11 @@ func (msg MsgOpenAck) GetSigners() []sdk.AccAddress { } type MsgOpenConfirm struct { - ConnectionID string `json:"connection_id"` - ChannelID string `json:"channel_id"` - Timeout uint64 `json:"timeout"` - Proofs []commitment.Proof `json:"proofs"` - Height uint64 `json:"height"` - Signer sdk.AccAddress `json:"signer"` + PortID string `json:"port_id"` + ChannelID string `json:"channel_id"` + Proofs []commitment.Proof `json:"proofs"` + Height uint64 `json:"height"` + Signer sdk.AccAddress `json:"signer"` } var _ sdk.Msg = MsgOpenConfirm{} diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 1079fccfc8c0..9d159960653b 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -41,14 +41,12 @@ func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { } res.Channel = channel.Channel{ - Port: PortName, Counterparty: res.Counterparty.Name, CounterpartyPort: PortName, ConnectionHops: []string{res.Name}, } res.Counterparty.Channel = channel.Channel{ - Port: PortName, Counterparty: res.Name, CounterpartyPort: PortName, ConnectionHops: []string{res.Counterparty.Name}, @@ -85,7 +83,7 @@ func (node *Node) Manager() channel.Manager { func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenInit(ctx, PortName, node.Name, node.Channel, 100) // TODO: test timeout + obj, err := man.OpenInit(ctx, PortName, node.Name, node.Channel) require.NoError(t, err) require.Equal(t, channel.Init, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -94,7 +92,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { func (node *Node) OpenTry(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenTry(ctx, proofs, height, PortName, node.Name, node.Channel, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenTry(ctx, proofs, height, PortName, node.Name, node.Channel) require.NoError(t, err) require.Equal(t, channel.OpenTry, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -104,7 +102,7 @@ func (node *Node) OpenTry(t *testing.T, height uint64, proofs ...commitment.Proo func (node *Node) OpenAck(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenAck(ctx, proofs, height, PortName, node.Name, 100 /*TODO*/, 100 /*TODO*/) + obj, err := man.OpenAck(ctx, proofs, height, PortName, node.Name) require.NoError(t, err) require.Equal(t, channel.Open, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -114,7 +112,7 @@ func (node *Node) OpenAck(t *testing.T, height uint64, proofs ...commitment.Proo func (node *Node) OpenConfirm(t *testing.T, height uint64, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) - obj, err := man.OpenConfirm(ctx, proofs, height, PortName, node.Name, 100 /*TODO*/) + obj, err := man.OpenConfirm(ctx, proofs, height, PortName, node.Name) require.NoError(t, err) require.Equal(t, channel.Open, obj.State.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) @@ -134,8 +132,7 @@ func (node *Node) Handshake(t *testing.T) { cliobj := node.CLIObject() _, pchan := node.QueryValue(t, cliobj.Channel) _, pstate := node.QueryValue(t, cliobj.State) - _, ptimeout := node.QueryValue(t, cliobj.NextTimeout) - node.Counterparty.OpenTry(t, uint64(header.Height), pchan, pstate, ptimeout) + node.Counterparty.OpenTry(t, uint64(header.Height), pchan, pstate) header = node.Counterparty.Commit() // self.OpenAck @@ -143,16 +140,14 @@ func (node *Node) Handshake(t *testing.T) { cliobj = node.Counterparty.CLIObject() _, pchan = node.Counterparty.QueryValue(t, cliobj.Channel) _, pstate = node.Counterparty.QueryValue(t, cliobj.State) - _, ptimeout = node.Counterparty.QueryValue(t, cliobj.NextTimeout) - node.OpenAck(t, uint64(header.Height), pchan, pstate, ptimeout) + node.OpenAck(t, uint64(header.Height), pchan, pstate) header = node.Commit() // counterparty.OpenConfirm node.Counterparty.UpdateClient(t, header) cliobj = node.CLIObject() _, pstate = node.QueryValue(t, cliobj.State) - _, ptimeout = node.QueryValue(t, cliobj.NextTimeout) - node.Counterparty.OpenConfirm(t, uint64(header.Height), pstate, ptimeout) + node.Counterparty.OpenConfirm(t, uint64(header.Height), pstate) } func (node *Node) Send(t *testing.T, packet channel.Packet) { diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index d186a786bb2d..7714dfe5e24c 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -25,11 +25,10 @@ type Packet interface { ValidateBasic() sdk.Error Timeout() uint64 MarshalAmino() (string, error) // Should exclude PortID/ChannelID info - MarshalJSON() ([]byte, error) // Should exclude PortID/ChannelID info + MarshalJSON() ([]byte, error) // Should exclude PortID/ChannelID info } type Channel struct { - Port string Counterparty string CounterpartyPort string ConnectionHops []string diff --git a/x/ibc/module.go b/x/ibc/module.go index 602930a9525b..4990660b33f4 100644 --- a/x/ibc/module.go +++ b/x/ibc/module.go @@ -19,6 +19,7 @@ import ( connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" conncli "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/client/cli" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + chancli "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/client/cli" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) @@ -75,7 +76,7 @@ func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { cmd.AddCommand( clicli.GetTxCmd(ModuleName, cdc), conncli.GetTxCmd(ModuleName, cdc), - // chancli.GetTxCmd(ModuleName, cdc), + chancli.GetTxCmd(ModuleName, cdc), ) return cmd @@ -90,7 +91,7 @@ func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { cmd.AddCommand( clicli.GetQueryCmd(ModuleName, cdc), conncli.GetQueryCmd(ModuleName, cdc), - // chancli.GetQueryCmd(ModuleName, cdc), + chancli.GetQueryCmd(ModuleName, cdc), ) return cmd From 4b81cb5431d409ef5b23fddfe31e90108ca2b083 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 20 Sep 2019 18:18:33 +0200 Subject: [PATCH 172/182] fix golangci --- x/ibc/03-connection/client/cli/tx.go | 15 ++++++++++++--- x/ibc/mock/handler.go | 5 ++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 0ecb6c97cf61..f1550c85a5a5 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -187,7 +187,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - // Another block has to be passed after msginit is commited + // Another block has to be passed after msginit is committed // to retrieve the correct proofs time.Sleep(8 * time.Second) @@ -203,6 +203,9 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { } err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + if err != nil { + return err + } fmt.Printf("updated apphash to %X\n", header.AppHash) @@ -236,7 +239,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - // Another block has to be passed after msginit is commited + // Another block has to be passed after msginit is committed // to retrieve the correct proofs time.Sleep(8 * time.Second) @@ -252,6 +255,9 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { } err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgupdate}) + if err != nil { + return err + } q2 = state.NewCLIQuerier(ctx2.WithHeight(header.Height - 1)) @@ -280,7 +286,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - // Another block has to be passed after msginit is commited + // Another block has to be passed after msginit is committed // to retrieve the correct proofs time.Sleep(8 * time.Second) @@ -296,6 +302,9 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { } err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + if err != nil { + return err + } q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) diff --git a/x/ibc/mock/handler.go b/x/ibc/mock/handler.go index aa7b8168b62e..4706c58a4ec7 100644 --- a/x/ibc/mock/handler.go +++ b/x/ibc/mock/handler.go @@ -14,9 +14,12 @@ func NewHandler(k Keeper) sdk.Handler { switch packet := msg.Packet.(type) { case types.PacketSequence: return handleMyPacket(ctx, k, packet, msg.ChannelID) + default: + return sdk.ErrUnknownRequest("23331345").Result() } + default: + return sdk.ErrUnknownRequest("21345").Result() } - return sdk.ErrUnknownRequest("21345").Result() } } From 3866942f3343db83097fc51b881b3241e991cec4 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 20 Sep 2019 18:56:39 +0200 Subject: [PATCH 173/182] fix cli --- store/state/integer.go | 4 + x/ibc/03-connection/codec.go | 8 +- x/ibc/04-channel/client/cli/query.go | 13 +-- x/ibc/04-channel/client/cli/tx.go | 129 +++------------------------ x/ibc/04-channel/codec.go | 5 ++ 5 files changed, 31 insertions(+), 128 deletions(-) diff --git a/store/state/integer.go b/store/state/integer.go index 6758d73cc479..938b83fd1f46 100644 --- a/store/state/integer.go +++ b/store/state/integer.go @@ -58,6 +58,10 @@ func (v Integer) Query(q ABCIQuerier) (res uint64, proof *Proof, err error) { if err != nil { return } + if value == nil { + res = 0 + return + } res, err = DecodeInt(value, v.enc) return } diff --git a/x/ibc/03-connection/codec.go b/x/ibc/03-connection/codec.go index 49d5c7678fdd..a3e2284b38a8 100644 --- a/x/ibc/03-connection/codec.go +++ b/x/ibc/03-connection/codec.go @@ -7,10 +7,10 @@ import ( var MsgCdc *codec.Codec func RegisterCodec(cdc *codec.Codec) { - cdc.RegisterConcrete(MsgOpenInit{}, "ibc/client/MsgOpenInit", nil) - cdc.RegisterConcrete(MsgOpenTry{}, "ibc/client/MsgOpenTry", nil) - cdc.RegisterConcrete(MsgOpenAck{}, "ibc/client/MsgOpenAck", nil) - cdc.RegisterConcrete(MsgOpenConfirm{}, "ibc/client/MsgOpenConfirm", nil) + cdc.RegisterConcrete(MsgOpenInit{}, "ibc/connection/MsgOpenInit", nil) + cdc.RegisterConcrete(MsgOpenTry{}, "ibc/connection/MsgOpenTry", nil) + cdc.RegisterConcrete(MsgOpenAck{}, "ibc/connection/MsgOpenAck", nil) + cdc.RegisterConcrete(MsgOpenConfirm{}, "ibc/connection/MsgOpenConfirm", nil) } func SetMsgCodec(cdc *codec.Codec) { diff --git a/x/ibc/04-channel/client/cli/query.go b/x/ibc/04-channel/client/cli/query.go index 9a5c7d4fb9b7..fcf28355d303 100644 --- a/x/ibc/04-channel/client/cli/query.go +++ b/x/ibc/04-channel/client/cli/query.go @@ -23,12 +23,12 @@ const ( FlagProve = "prove" ) -func object(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string, connids []string) channel.Object { +func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.Object, error) { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) connman := connection.NewManager(base, climan) man := channel.NewManager(base, connman) - return man.CLIObject(portid, chanid, connids) + return man.CLIQuery(state.NewCLIQuerier(ctx), portid, chanid) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -87,12 +87,15 @@ func QueryChannel(ctx context.CLIContext, obj channel.Object, prove bool) (res u func GetCmdQueryChannel(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "connection", + Use: "channel", Short: "Query stored connection", - Args: cobra.ExactArgs(3), + Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - obj := object(cdc, storeKey, version.DefaultPrefix(), args[0], args[1], []string{args[2]}) + obj, err := object(ctx, cdc, storeKey, version.DefaultPrefix(), args[0], args[1]) + if err != nil { + return err + } jsonobj, err := QueryChannel(ctx, obj, viper.GetBool(FlagProve)) if err != nil { return err diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index 90696ee9ab6d..476ed72f9313 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -1,101 +1,3 @@ -/* - - -func lastheight(ctx context.CLIContext) (uint64, error) { - node, err := ctx.GetNode() - if err != nil { - return 0, err - } - - info, err := node.ABCIInfo() - if err != nil { - return 0, err - } - - return uint64(info.Response.LastBlockHeight), nil -} - -func GetCmdRelay(storeKey string, cdc *codec.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "relay", - Short: "relay pakcets between two channels", - Args: cobra.ExactArgs(4), - // Args: []string{connid1, chanid1, chanfilepath1, connid2, chanid2, chanfilepath2} - RunE: func(cmd *cobra.Command, args []string) error { - ctx1 := context.NewCLIContext(). - WithCodec(cdc). - WithNodeURI(viper.GetString(FlagNode1)). - WithFrom(viper.GetString(FlagFrom1)) - - ctx2 := context.NewCLIContext(). - WithCodec(cdc). - WithNodeURI(viper.GetString(FlagNode2)). - WithFrom(viper.GetString(FlagFrom2)) - - conn1id, chan1id, conn2id, chan2id := args[0], args[1], args[2], args[3] - - obj1 := object(ctx1, cdc, storeKey, ibc.Version, conn1id, chan1id) - obj2 := object(ctx2, cdc, storeKey, ibc.Version, conn2id, chan2id) - - return relayLoop(cdc, ctx1, ctx2, obj1, obj2, conn1id, chan1id, conn2id, chan2id) - }, - } - - return cmd -} - -func relayLoop(cdc *codec.Codec, - ctx1, ctx2 context.CLIContext, - obj1, obj2 channel.CLIObject, - conn1id, chan1id, conn2id, chan2id string, -) error { - for { - // TODO: relay() should be goroutine and return error by channel - err := relay(cdc, ctx1, ctx2, obj1, obj2, conn2id, chan2id) - // TODO: relayBetween() should retry several times before halt - if err != nil { - return err - } - time.Sleep(1 * time.Second) - } -} - -func relay(cdc *codec.Codec, ctxFrom, ctxTo context.CLIContext, objFrom, objTo channel.CLIObject, connidTo, chanidTo string) error { - txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) - - seq, _, err := objTo.SeqRecv(ctxTo) - if err != nil { - return err - } - - sent, _, err := objFrom.SeqSend(ctxFrom) - if err != nil { - return err - } - - for i := seq; i <= sent; i++ { - packet, proof, err := objFrom.Packet(ctxFrom, seq) - if err != nil { - return err - } - - msg := channel.MsgReceive{ - ConnectionID: connidTo, - ChannelID: chanidTo, - Packet: packet, - Proofs: []commitment.Proof{proof}, - Signer: ctxTo.GetFromAddress(), - } - - err = utils.GenerateOrBroadcastMsgs(ctxTo, txBldr, []sdk.Msg{msg}) - if err != nil { - return err - } - } - - return nil -} -*/ package cli import ( @@ -124,11 +26,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/version" ) -/* -func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { - -} -*/ const ( FlagNode1 = "node1" FlagNode2 = "node2" @@ -136,12 +33,12 @@ const ( FlagFrom2 = "from2" ) -func handshake(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.HandshakeObject, error) { +func handshake(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid, connid string) channel.HandshakeObject { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) connman := connection.NewManager(base, climan) man := channel.NewHandshaker(channel.NewManager(base, connman)) - return man.CLIQuery(q, portid, chanid) + return man.CLIObject(portid, chanid, []string{connid}) } func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -235,15 +132,8 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { ConnectionHops: []string{connid2}, } - obj1, err := handshake(q1, cdc, storeKey, version.DefaultPrefix(), portid1, chanid1) - if err != nil { - return err - } - - obj2, err := handshake(q2, cdc, storeKey, version.DefaultPrefix(), portid2, chanid2) - if err != nil { - return err - } + obj1 := handshake(cdc, storeKey, version.DefaultPrefix(), portid1, chanid1, connid1) + obj2 := handshake(cdc, storeKey, version.DefaultPrefix(), portid2, chanid2, connid2) conn1, _, err := obj1.OriginConnection().ConnectionCLI(q1) if err != nil { @@ -380,11 +270,12 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgconfirm := connection.MsgOpenConfirm{ - ConnectionID: connid2, - Proofs: []commitment.Proof{pstate}, - Height: uint64(header.Height), - Signer: ctx2.GetFromAddress(), + msgconfirm := channel.MsgOpenConfirm{ + PortID: portid2, + ChannelID: chanid2, + Proofs: []commitment.Proof{pstate}, + Height: uint64(header.Height), + Signer: ctx2.GetFromAddress(), } err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgconfirm}) diff --git a/x/ibc/04-channel/codec.go b/x/ibc/04-channel/codec.go index ebf30115d09a..112aedc4c40c 100644 --- a/x/ibc/04-channel/codec.go +++ b/x/ibc/04-channel/codec.go @@ -8,6 +8,11 @@ var msgCdc *codec.Codec func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*Packet)(nil), nil) + + cdc.RegisterConcrete(MsgOpenInit{}, "ibc/channel/MsgOpenInit", nil) + cdc.RegisterConcrete(MsgOpenTry{}, "ibc/channel/MsgOpenTry", nil) + cdc.RegisterConcrete(MsgOpenAck{}, "ibc/channel/MsgOpenAck", nil) + cdc.RegisterConcrete(MsgOpenConfirm{}, "ibc/channel/MsgOpenConfirm", nil) } func SetMsgCodec(cdc *codec.Codec) { From 6e6c186342266a14e16ef3990beeb8c719cf0417 Mon Sep 17 00:00:00 2001 From: Timothy Chen Date: Tue, 24 Sep 2019 22:21:16 -0700 Subject: [PATCH 174/182] Clean up --- x/ibc/02-client/README.md | 2 +- x/ibc/02-client/codec.go | 6 - x/ibc/02-client/manager.go | 2 +- x/ibc/03-connection/cli.go | 24 +-- x/ibc/03-connection/client/cli/query.go | 4 +- x/ibc/03-connection/client/cli/tx.go | 85 +++++---- x/ibc/03-connection/handler.go | 4 + x/ibc/03-connection/handshake.go | 116 ++++++------- x/ibc/03-connection/manager.go | 40 ++--- x/ibc/03-connection/tests/types.go | 6 +- x/ibc/03-connection/types.go | 2 +- x/ibc/04-channel/cli.go | 28 +-- x/ibc/04-channel/client/cli/query.go | 6 +- x/ibc/04-channel/client/cli/tx.go | 70 ++++---- x/ibc/04-channel/codec.go | 6 - x/ibc/04-channel/handshake.go | 219 ++++++------------------ x/ibc/04-channel/manager.go | 169 ++++++------------ x/ibc/04-channel/port.go | 14 +- x/ibc/04-channel/tests/types.go | 6 +- x/ibc/23-commitment/merkle/merkle.go | 1 - x/ibc/23-commitment/store.go | 6 +- x/ibc/23-commitment/value.go | 1 - x/ibc/keeper.go | 6 +- x/ibc/mock/types/msgs.go | 2 +- 24 files changed, 323 insertions(+), 502 deletions(-) diff --git a/x/ibc/02-client/README.md b/x/ibc/02-client/README.md index a9bd6892771b..f8b3fc98d086 100644 --- a/x/ibc/02-client/README.md +++ b/x/ibc/02-client/README.md @@ -46,4 +46,4 @@ each corresponds to `spec: Header.{height, proof, state, root}`. ### manager.go -`spec: interface ClientState` is implemented by `type Object`. // TODO +`spec: interface ClientState` is implemented by `type State`. // TODO diff --git a/x/ibc/02-client/codec.go b/x/ibc/02-client/codec.go index d130e624f476..18dd6da686e8 100644 --- a/x/ibc/02-client/codec.go +++ b/x/ibc/02-client/codec.go @@ -15,11 +15,5 @@ func RegisterCodec(cdc *codec.Codec) { } func SetMsgCodec(cdc *codec.Codec) { - // TODO - /* - if MsgCdc != nil && MsgCdc != cdc { - panic("MsgCdc set more than once") - } - */ MsgCdc = cdc } diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 1a732c6dc824..06927c33d1eb 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -78,7 +78,7 @@ func (man CounterpartyManager) Query(id string) CounterObject { return man.Object(id) } -// Any actor holding the Object can access on and modify that client information +// Any actor holding the Stage can access on and modify that client information type Object struct { id string Roots state.Indexer diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index 7fa3986465d7..ca114e8e2e8c 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -7,55 +7,55 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func (man Manager) CLIObject(connid, clientid string) Object { +func (man Manager) CLIObject(connid, clientid string) State { obj := man.Object(connid) obj.Client = man.client.Object(clientid) return obj } -func (obj Object) prefix() []byte { +func (obj State) prefix() []byte { return bytes.Split(obj.Connection.KeyBytes(), LocalRoot())[0] } -func (obj Object) ConnectionCLI(q state.ABCIQuerier) (res Connection, proof merkle.Proof, err error) { +func (obj State) ConnectionCLI(q state.ABCIQuerier) (res Connection, proof merkle.Proof, err error) { tmproof, err := obj.Connection.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Connection) return } -func (obj Object) AvailableCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { +func (obj State) AvailableCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { res, tmproof, err := obj.Available.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Available) return } -func (obj Object) KindCLI(q state.ABCIQuerier) (res string, proof merkle.Proof, err error) { +func (obj State) KindCLI(q state.ABCIQuerier) (res string, proof merkle.Proof, err error) { res, tmproof, err := obj.Kind.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Kind) return } -func (man Handshaker) CLIObject(connid, clientid string) HandshakeObject { - return man.Object(man.man.CLIObject(connid, clientid)) +func (man Handshaker) CLIObject(connid, clientid string) HandshakeState { + return man.CreateState(man.man.CLIObject(connid, clientid)) } -func (man Handshaker) CLIQuery(q state.ABCIQuerier, connid string) (HandshakeObject, error) { +func (man Handshaker) CLIQuery(q state.ABCIQuerier, connid string) (HandshakeState, error) { obj := man.man.Object(connid) conn, _, err := obj.ConnectionCLI(q) if err != nil { - return HandshakeObject{}, err + return HandshakeState{}, err } obj.Client = man.man.client.Object(conn.Client) - return man.Object(obj), nil + return man.CreateState(obj), nil } -func (obj HandshakeObject) StateCLI(q state.ABCIQuerier) (res byte, proof merkle.Proof, err error) { +func (obj HandshakeState) StateCLI(q state.ABCIQuerier) (res byte, proof merkle.Proof, err error) { res, tmproof, err := obj.State.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) return } -func (obj HandshakeObject) CounterpartyClientCLI(q state.ABCIQuerier) (res string, proof merkle.Proof, err error) { +func (obj HandshakeState) CounterpartyClientCLI(q state.ABCIQuerier) (res string, proof merkle.Proof, err error) { res, tmproof, err := obj.CounterpartyClient.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.CounterpartyClient) return diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index b01280c2fa33..63b563c5d44b 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -22,7 +22,7 @@ const ( FlagProve = "prove" ) -func object(cdc *codec.Codec, storeKey string, prefix []byte, connid, clientid string) connection.Object { +func object(cdc *codec.Codec, storeKey string, prefix []byte, connid, clientid string) connection.State { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) man := connection.NewManager(base, climan) @@ -43,7 +43,7 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { return ibcQueryCmd } -func QueryConnection(ctx context.CLIContext, obj connection.Object, prove bool) (res utils.JSONObject, err error) { +func QueryConnection(ctx context.CLIContext, obj connection.State, prove bool) (res utils.JSONObject, err error) { q := state.NewCLIQuerier(ctx) conn, connp, err := obj.ConnectionCLI(q) diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index f1550c85a5a5..50e1f0ddf661 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -26,11 +26,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/version" ) -/* -func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { - -} -*/ const ( FlagNode1 = "node1" FlagNode2 = "node2" @@ -38,14 +33,14 @@ const ( FlagFrom2 = "from2" ) -func handshake(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, connid string) (connection.HandshakeObject, error) { +func handshake(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, connid string) (connection.HandshakeState, error) { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) - climan := client.NewManager(base) - man := connection.NewHandshaker(connection.NewManager(base, climan)) + clientManager := client.NewManager(base) + man := connection.NewHandshaker(connection.NewManager(base, clientManager)) return man.CLIQuery(q, connid) } -func lastheight(ctx context.CLIContext) (uint64, error) { +func lastHeight(ctx context.CLIContext) (uint64, error) { node, err := ctx.GetNode() if err != nil { return 0, err @@ -116,7 +111,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Use: "handshake", Short: "initiate connection handshake between two chains", Args: cobra.ExactArgs(6), - // Args: []string{connid1, clientid1, path1, connid2, clientid2, connfilepath2} RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom1)). @@ -131,10 +125,10 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { WithBroadcastMode(flags.BroadcastBlock) q2 := state.NewCLIQuerier(ctx2) - connid1 := args[0] - clientid1 := args[1] - connid2 := args[3] - clientid2 := args[4] + connId1 := args[0] + clientId1 := args[1] + connId2 := args[3] + clientId2 := args[4] var path1 commitment.Path path1bz, err := ioutil.ReadFile(args[2]) @@ -145,12 +139,12 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } conn1 := connection.Connection{ - Client: clientid1, - Counterparty: connid2, + Client: clientId1, + Counterparty: connId2, Path: path1, } - obj1, err := handshake(q1, cdc, storeKey, version.DefaultPrefix(), connid1) + obj1, err := handshake(q1, cdc, storeKey, version.DefaultPrefix(), connId1) if err != nil { return err } @@ -164,31 +158,33 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } conn2 := connection.Connection{ - Client: clientid2, - Counterparty: connid1, + Client: clientId2, + Counterparty: connId1, Path: path2, } - obj2, err := handshake(q2, cdc, storeKey, version.DefaultPrefix(), connid2) + obj2, err := handshake(q2, cdc, storeKey, version.DefaultPrefix(), connId2) if err != nil { return err } // TODO: check state and if not Idle continue existing process - msginit := connection.MsgOpenInit{ - ConnectionID: connid1, + msgInit := connection.MsgOpenInit{ + ConnectionID: connId1, Connection: conn1, CounterpartyClient: conn2.Client, Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msginit}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgInit}) if err != nil { return err } - // Another block has to be passed after msginit is committed + // Another block has to be passed after msgInit is committed // to retrieve the correct proofs + // TODO: Modify this to actually check two blocks being processed, and + // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err := getHeader(ctx1) @@ -196,19 +192,17 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgupdate := client.MsgUpdateClient{ + msgUpdate := client.MsgUpdateClient{ ClientID: conn2.Client, Header: header, Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgUpdate}) if err != nil { return err } - fmt.Printf("updated apphash to %X\n", header.AppHash) - q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) fmt.Printf("querying from %d\n", header.Height-1) @@ -225,8 +219,8 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgtry := connection.MsgOpenTry{ - ConnectionID: connid2, + msgTry := connection.MsgOpenTry{ + ConnectionID: connId2, Connection: conn2, CounterpartyClient: conn1.Client, Proofs: []commitment.Proof{pconn, pstate, pcounter}, @@ -234,13 +228,15 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgTry}) if err != nil { return err } - // Another block has to be passed after msginit is committed + // Another block has to be passed after msgInit is committed // to retrieve the correct proofs + // TODO: Modify this to actually check two blocks being processed, and + // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err = getHeader(ctx2) @@ -248,13 +244,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgupdate = client.MsgUpdateClient{ + msgUpdate = client.MsgUpdateClient{ ClientID: conn1.Client, Header: header, Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgupdate}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgUpdate}) if err != nil { return err } @@ -274,20 +270,22 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgack := connection.MsgOpenAck{ - ConnectionID: connid1, + msgAck := connection.MsgOpenAck{ + ConnectionID: connId1, Proofs: []commitment.Proof{pconn, pstate, pcounter}, Height: uint64(header.Height), Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgack}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgAck}) if err != nil { return err } - // Another block has to be passed after msginit is committed + // Another block has to be passed after msgInit is committed // to retrieve the correct proofs + // TODO: Modify this to actually check two blocks being processed, and + // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err = getHeader(ctx1) @@ -295,13 +293,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgupdate = client.MsgUpdateClient{ + msgUpdate = client.MsgUpdateClient{ ClientID: conn2.Client, Header: header, Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgUpdate}) if err != nil { return err } @@ -313,14 +311,14 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgconfirm := connection.MsgOpenConfirm{ - ConnectionID: connid2, + msgConfirm := connection.MsgOpenConfirm{ + ConnectionID: connId2, Proofs: []commitment.Proof{pstate}, Height: uint64(header.Height), Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgconfirm}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgConfirm}) if err != nil { return err } @@ -329,6 +327,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { }, } + // TODO: Provide flag description cmd.Flags().String(FlagNode1, "tcp://localhost:26657", "") cmd.Flags().String(FlagNode2, "tcp://localhost:26657", "") cmd.Flags().String(FlagFrom1, "", "") diff --git a/x/ibc/03-connection/handler.go b/x/ibc/03-connection/handler.go index 8395579663d2..f516c0a5d6df 100644 --- a/x/ibc/03-connection/handler.go +++ b/x/ibc/03-connection/handler.go @@ -7,6 +7,7 @@ import ( func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Result { _, err := man.OpenInit(ctx, msg.ConnectionID, msg.Connection, msg.CounterpartyClient) if err != nil { + // TODO: Define the error code in errors return sdk.NewError(sdk.CodespaceType("ibc"), 100, err.Error()).Result() } return sdk.Result{} @@ -15,6 +16,7 @@ func HandleMsgOpenInit(ctx sdk.Context, msg MsgOpenInit, man Handshaker) sdk.Res func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Result { _, err := man.OpenTry(ctx, msg.Proofs, msg.Height, msg.ConnectionID, msg.Connection, msg.CounterpartyClient) if err != nil { + // TODO: Define the error code in errors return sdk.NewError(sdk.CodespaceType("ibc"), 200, err.Error()).Result() } return sdk.Result{} @@ -23,6 +25,7 @@ func HandleMsgOpenTry(ctx sdk.Context, msg MsgOpenTry, man Handshaker) sdk.Resul func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Result { _, err := man.OpenAck(ctx, msg.Proofs, msg.Height, msg.ConnectionID) if err != nil { + // TODO: Define the error code in errors return sdk.NewError(sdk.CodespaceType("ibc"), 300, err.Error()).Result() } return sdk.Result{} @@ -31,6 +34,7 @@ func HandleMsgOpenAck(ctx sdk.Context, msg MsgOpenAck, man Handshaker) sdk.Resul func HandleMsgOpenConfirm(ctx sdk.Context, msg MsgOpenConfirm, man Handshaker) sdk.Result { _, err := man.OpenConfirm(ctx, msg.Proofs, msg.Height, msg.ConnectionID) if err != nil { + // TODO: Define the error code in errors return sdk.NewError(sdk.CodespaceType("ibc"), 400, err.Error()).Result() } return sdk.Result{} diff --git a/x/ibc/03-connection/handshake.go b/x/ibc/03-connection/handshake.go index 04eb96fc298f..e4c59386d2f6 100644 --- a/x/ibc/03-connection/handshake.go +++ b/x/ibc/03-connection/handshake.go @@ -9,10 +9,10 @@ import ( commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -type State = byte +type HandshakeStage = byte const ( - Idle State = iota + Idle HandshakeStage = iota Init OpenTry Open @@ -25,17 +25,13 @@ const HandshakeKind = "handshake" type Handshaker struct { man Manager - counterparty CounterpartyHandshaker + counterParty CounterpartyHandshaker } -// TODO: ocapify Manager; an actor who holds Manager -// should not be able to construct creaters from it -// or add Seal() method to Manager? func NewHandshaker(man Manager) Handshaker { return Handshaker{ man: man, - - counterparty: CounterpartyHandshaker{man.counterparty}, + counterParty: CounterpartyHandshaker{man.counterparty}, } } @@ -43,92 +39,90 @@ type CounterpartyHandshaker struct { man CounterpartyManager } -type HandshakeObject struct { - Object +type HandshakeState struct { + State - State state.Enum + Stage state.Enum CounterpartyClient state.String - Counterparty CounterHandshakeObject + Counterparty CounterHandshakeState } -type CounterHandshakeObject struct { - CounterObject +type CounterHandshakeState struct { + CounterState - State commitment.Enum + Stage commitment.Enum CounterpartyClient commitment.String } // CONTRACT: client and remote must be filled by the caller -func (man Handshaker) Object(parent Object) HandshakeObject { - return HandshakeObject{ - Object: parent, - - State: man.man.protocol.Value([]byte(parent.id + "/state")).Enum(), +func (man Handshaker) CreateState(parent State) HandshakeState { + return HandshakeState{ + State: parent, + Stage: man.man.protocol.Value([]byte(parent.id + "/state")).Enum(), CounterpartyClient: man.man.protocol.Value([]byte(parent.id + "/counterpartyClient")).String(), - // CONTRACT: counterparty must be filled by the caller + // CONTRACT: counterParty must be filled by the caller } } -func (man CounterpartyHandshaker) Object(id string) CounterHandshakeObject { - return CounterHandshakeObject{ - CounterObject: man.man.Object(id), - - State: man.man.protocol.Value([]byte(id + "/state")).Enum(), +func (man CounterpartyHandshaker) CreateState(id string) CounterHandshakeState { + return CounterHandshakeState{ + CounterState: man.man.CreateState(id), + Stage: man.man.protocol.Value([]byte(id + "/state")).Enum(), CounterpartyClient: man.man.protocol.Value([]byte(id + "/counterpartyClient")).String(), } } -func (man Handshaker) create(ctx sdk.Context, id string, connection Connection, counterpartyClient string) (obj HandshakeObject, err error) { +func (man Handshaker) create(ctx sdk.Context, id string, connection Connection, counterpartyClient string) (obj HandshakeState, err error) { cobj, err := man.man.create(ctx, id, connection, HandshakeKind) if err != nil { return } - obj = man.Object(cobj) + obj = man.CreateState(cobj) obj.CounterpartyClient.Set(ctx, counterpartyClient) - obj.Counterparty = man.counterparty.Object(connection.Counterparty) + obj.Counterparty = man.counterParty.CreateState(connection.Counterparty) return obj, nil } -func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeObject, err error) { +func (man Handshaker) query(ctx sdk.Context, id string) (obj HandshakeState, err error) { cobj, err := man.man.query(ctx, id, HandshakeKind) if err != nil { return } - obj = man.Object(cobj) - obj.Counterparty = man.counterparty.Object(obj.GetConnection(ctx).Counterparty) + obj = man.CreateState(cobj) + obj.Counterparty = man.counterParty.CreateState(obj.GetConnection(ctx).Counterparty) return } -func (obj HandshakeObject) remove(ctx sdk.Context) { - obj.Object.remove(ctx) - obj.State.Delete(ctx) +func (obj HandshakeState) remove(ctx sdk.Context) { + obj.State.remove(ctx) + obj.Stage.Delete(ctx) obj.CounterpartyClient.Delete(ctx) } // Using proofs: none func (man Handshaker) OpenInit(ctx sdk.Context, id string, connection Connection, counterpartyClient string, -) (HandshakeObject, error) { +) (HandshakeState, error) { // man.Create() will ensure // assert(get("connections/{identifier}") === null) and // set("connections{identifier}", connection) obj, err := man.create(ctx, id, connection, counterpartyClient) if err != nil { - return HandshakeObject{}, err + return HandshakeState{}, err } - obj.State.Set(ctx, Init) + obj.Stage.Set(ctx, Init) return obj, nil } -// Using proofs: counterparty.{connection,state,nextTimeout,counterpartyClient, client} +// Using proofs: counterParty.{connection,state,nextTimeout,counterpartyClient, client} func (man Handshaker) OpenTry(ctx sdk.Context, proofs []commitment.Proof, height uint64, id string, connection Connection, counterpartyClient string, -) (obj HandshakeObject, err error) { +) (obj HandshakeState, err error) { obj, err = man.create(ctx, id, connection, counterpartyClient) if err != nil { return @@ -139,8 +133,8 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.Counterparty.State.Is(ctx, Init) { - err = errors.New("counterparty state not init") + if !obj.Counterparty.Stage.Is(ctx, Init) { + err = errors.New("counterParty state not init") return } @@ -149,12 +143,12 @@ func (man Handshaker) OpenTry(ctx sdk.Context, Counterparty: id, Path: obj.path, }) { - err = errors.New("wrong counterparty connection") + err = errors.New("wrong counterParty connection") return } if !obj.Counterparty.CounterpartyClient.Is(ctx, connection.Client) { - err = errors.New("counterparty client not match") + err = errors.New("counterParty client not match") return } @@ -164,8 +158,8 @@ func (man Handshaker) OpenTry(ctx sdk.Context, /* var expected client.ConsensusState obj.self.Get(ctx, expheight, &expected) - if !obj.counterparty.client.Is(ctx, expected) { - return errors.New("unexpected counterparty client value") + if !obj.counterParty.client.Is(ctx, expected) { + return errors.New("unexpected counterParty client value") } */ @@ -174,16 +168,16 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // assert(get("connections/{desiredIdentifier}") === null) and // set("connections{identifier}", connection) - obj.State.Set(ctx, OpenTry) + obj.Stage.Set(ctx, OpenTry) return } -// Using proofs: counterparty.{connection, state, timeout, counterpartyClient, client} +// Using proofs: counterParty.{connection, state, timeout, counterpartyClient, client} func (man Handshaker) OpenAck(ctx sdk.Context, proofs []commitment.Proof, height uint64, id string, -) (obj HandshakeObject, err error) { +) (obj HandshakeState, err error) { obj, err = man.query(ctx, id) if err != nil { return @@ -194,7 +188,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.State.Transit(ctx, Init, Open) { + if !obj.Stage.Transit(ctx, Init, Open) { err = errors.New("ack on non-init connection") return } @@ -204,17 +198,17 @@ func (man Handshaker) OpenAck(ctx sdk.Context, Counterparty: obj.ID(), Path: obj.path, }) { - err = errors.New("wrong counterparty") + err = errors.New("wrong counterParty") return } - if !obj.Counterparty.State.Is(ctx, OpenTry) { - err = errors.New("counterparty state not opentry") + if !obj.Counterparty.Stage.Is(ctx, OpenTry) { + err = errors.New("counterParty state not opentry") return } if !obj.Counterparty.CounterpartyClient.Is(ctx, obj.GetConnection(ctx).Client) { - err = errors.New("counterparty client not match") + err = errors.New("counterParty client not match") return } @@ -222,8 +216,8 @@ func (man Handshaker) OpenAck(ctx sdk.Context, /* var expected client.ConsensusState // obj.self.Get(ctx, expheight, &expected) - if !obj.counterparty.client.Is(ctx, expected) { - // return errors.New("unexpected counterparty client value") + if !obj.counterParty.client.Is(ctx, expected) { + // return errors.New("unexpected counterParty client value") } */ obj.Available.Set(ctx, true) @@ -231,10 +225,10 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } -// Using proofs: counterparty.{connection,state, nextTimeout} +// Using proofs: counterParty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, proofs []commitment.Proof, height uint64, - id string) (obj HandshakeObject, err error) { + id string) (obj HandshakeState, err error) { obj, err = man.query(ctx, id) if err != nil { @@ -246,13 +240,13 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - if !obj.State.Transit(ctx, OpenTry, Open) { + if !obj.Stage.Transit(ctx, OpenTry, Open) { err = errors.New("confirm on non-try connection") return } - if !obj.Counterparty.State.Is(ctx, Open) { - err = errors.New("counterparty state not open") + if !obj.Counterparty.Stage.Is(ctx, Open) { + err = errors.New("counterParty state not open") return } diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index 57e5a3456fea..a1c500af415a 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -47,7 +47,7 @@ func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { } } -type Object struct { +type State struct { id string protocol state.Mapping @@ -61,8 +61,8 @@ type Object struct { path merkle.Path } -func (man Manager) Object(id string) Object { - return Object{ +func (man Manager) Object(id string) State { + return State{ id: id, protocol: man.protocol.Prefix([]byte(id + "/")), @@ -77,7 +77,7 @@ func (man Manager) Object(id string) Object { } } -type CounterObject struct { +type CounterState struct { id string protocol commitment.Mapping @@ -89,8 +89,8 @@ type CounterObject struct { Client client.CounterObject // nolint: unused } -func (man CounterpartyManager) Object(id string) CounterObject { - return CounterObject{ +func (man CounterpartyManager) CreateState(id string) CounterState { + return CounterState{ id: id, protocol: man.protocol.Prefix([]byte(id + "/")), Connection: man.protocol.Value([]byte(id)), @@ -102,7 +102,7 @@ func (man CounterpartyManager) Object(id string) CounterObject { } } -func (obj Object) Context(ctx sdk.Context, height uint64, proofs []commitment.Proof) (sdk.Context, error) { +func (obj State) Context(ctx sdk.Context, height uint64, proofs []commitment.Proof) (sdk.Context, error) { root, err := obj.Client.GetRoot(ctx, height) if err != nil { return ctx, err @@ -120,30 +120,30 @@ func (obj Object) Context(ctx sdk.Context, height uint64, proofs []commitment.Pr return commitment.WithStore(ctx, store), nil } -func (obj Object) ID() string { +func (obj State) ID() string { return obj.id } -func (obj Object) GetConnection(ctx sdk.Context) (res Connection) { +func (obj State) GetConnection(ctx sdk.Context) (res Connection) { obj.Connection.Get(ctx, &res) return } -func (obj Object) Sendable(ctx sdk.Context) bool { +func (obj State) Sendable(ctx sdk.Context) bool { return kinds[obj.Kind.Get(ctx)].Sendable } -func (obj Object) Receivable(ctx sdk.Context) bool { +func (obj State) Receivable(ctx sdk.Context) bool { return kinds[obj.Kind.Get(ctx)].Receivable } -func (obj Object) remove(ctx sdk.Context) { +func (obj State) remove(ctx sdk.Context) { obj.Connection.Delete(ctx) obj.Available.Delete(ctx) obj.Kind.Delete(ctx) } -func (obj Object) exists(ctx sdk.Context) bool { +func (obj State) exists(ctx sdk.Context) bool { return obj.Connection.Exists(ctx) } @@ -151,10 +151,10 @@ func (man Manager) Cdc() *codec.Codec { return man.protocol.Cdc() } -func (man Manager) create(ctx sdk.Context, id string, connection Connection, kind string) (obj Object, err error) { +func (man Manager) create(ctx sdk.Context, id string, connection Connection, kind string) (obj State, err error) { obj = man.Object(id) if obj.exists(ctx) { - err = errors.New("Object already exists") + err = errors.New("Stage already exists") return } obj.Client, err = man.client.Query(ctx, connection.Client) @@ -169,10 +169,10 @@ func (man Manager) create(ctx sdk.Context, id string, connection Connection, kin // query() is used internally by the connection creators // checks connection kind, doesn't check avilability -func (man Manager) query(ctx sdk.Context, id string, kind string) (obj Object, err error) { +func (man Manager) query(ctx sdk.Context, id string, kind string) (obj State, err error) { obj = man.Object(id) if !obj.exists(ctx) { - err = errors.New("Object not exists") + err = errors.New("Stage not exists") return } obj.Client, err = man.client.Query(ctx, obj.GetConnection(ctx).Client) @@ -186,15 +186,15 @@ func (man Manager) query(ctx sdk.Context, id string, kind string) (obj Object, e return } -func (man Manager) Query(ctx sdk.Context, id string) (obj Object, err error) { +func (man Manager) Query(ctx sdk.Context, id string) (obj State, err error) { obj = man.Object(id) if !obj.exists(ctx) { - err = errors.New("Object not exists") + err = errors.New("Stage not exists") return } if !obj.Available.Get(ctx) { - err = errors.New("Object not available") + err = errors.New("Stage not available") return } obj.Client, err = man.client.Query(ctx, obj.GetConnection(ctx).Client) diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 0162b392b494..83ee9543ea56 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -22,7 +22,7 @@ type Node struct { CounterpartyClient string Connection connection.Connection - State connection.State + State connection.HandshakeStage Cdc *codec.Codec } @@ -81,7 +81,7 @@ func (node *Node) UpdateClient(t *testing.T, header client.Header) { require.NoError(t, err) } -func (node *Node) SetState(state connection.State) { +func (node *Node) SetState(state connection.HandshakeStage) { node.State = state node.Counterparty.State = state } @@ -92,7 +92,7 @@ func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Conte return ctx, connection.NewHandshaker(man) } -func (node *Node) CLIObject() connection.HandshakeObject { +func (node *Node) CLIObject() connection.HandshakeState { _, man := node.Manager() return connection.NewHandshaker(man).CLIObject(node.Name, node.Name) } diff --git a/x/ibc/03-connection/types.go b/x/ibc/03-connection/types.go index af5b1c987689..81c1eca05ae4 100644 --- a/x/ibc/03-connection/types.go +++ b/x/ibc/03-connection/types.go @@ -10,7 +10,7 @@ import ( type Connection struct { Client string `json:"client"` - Counterparty string `json:"counterparty"` + Counterparty string `json:"counterParty"` Path commitment.Path `json:"path"` } diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index ebf0f1755890..9dae276d567f 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -7,7 +7,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func (man Manager) CLIObject(portid, chanid string, connids []string) Object { +func (man Manager) CLIObject(portid, chanid string, connids []string) State { obj := man.object(portid, chanid) for _, connid := range connids { obj.Connections = append(obj.Connections, man.connection.Object(connid)) @@ -15,7 +15,7 @@ func (man Manager) CLIObject(portid, chanid string, connids []string) Object { return obj } -func (man Manager) CLIQuery(q state.ABCIQuerier, portid, chanid string) (obj Object, err error) { +func (man Manager) CLIQuery(q state.ABCIQuerier, portid, chanid string) (obj State, err error) { obj = man.object(portid, chanid) channel, _, err := obj.ChannelCLI(q) if err != nil { @@ -27,54 +27,54 @@ func (man Manager) CLIQuery(q state.ABCIQuerier, portid, chanid string) (obj Obj return } -func (obj Object) prefix() []byte { +func (obj State) prefix() []byte { return bytes.Split(obj.Channel.KeyBytes(), LocalRoot())[0] } -func (obj Object) ChannelCLI(q state.ABCIQuerier) (res Channel, proof merkle.Proof, err error) { +func (obj State) ChannelCLI(q state.ABCIQuerier) (res Channel, proof merkle.Proof, err error) { tmproof, err := obj.Channel.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Channel) return } -func (obj Object) AvailableCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { +func (obj State) AvailableCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { res, tmproof, err := obj.Available.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Available) return } -func (obj Object) SeqSendCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { +func (obj State) SeqSendCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { res, tmproof, err := obj.SeqSend.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.SeqSend) return } -func (obj Object) SeqRecvCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { +func (obj State) SeqRecvCLI(q state.ABCIQuerier) (res uint64, proof merkle.Proof, err error) { res, tmproof, err := obj.SeqRecv.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.SeqRecv) return } -func (obj Object) PacketCLI(q state.ABCIQuerier, index uint64) (res Packet, proof merkle.Proof, err error) { +func (obj State) PacketCLI(q state.ABCIQuerier, index uint64) (res Packet, proof merkle.Proof, err error) { packet := obj.Packets.Value(index) tmproof, err := packet.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), packet) return } -func (man Handshaker) CLIQuery(q state.ABCIQuerier, portid, chanid string) (HandshakeObject, error) { +func (man Handshaker) CLIQuery(q state.ABCIQuerier, portid, chanid string) (HandshakeState, error) { obj, err := man.Manager.CLIQuery(q, portid, chanid) if err != nil { - return HandshakeObject{}, err + return HandshakeState{}, err } - return man.object(obj), nil + return man.createState(obj), nil } -func (man Handshaker) CLIObject(portid, chanid string, connids []string) HandshakeObject { - return man.object(man.Manager.CLIObject(portid, chanid, connids)) +func (man Handshaker) CLIObject(portid, chanid string, connids []string) HandshakeState { + return man.createState(man.Manager.CLIObject(portid, chanid, connids)) } -func (obj HandshakeObject) StateCLI(q state.ABCIQuerier) (res State, proof merkle.Proof, err error) { +func (obj HandshakeState) StateCLI(q state.ABCIQuerier) (res HandshakeStage, proof merkle.Proof, err error) { res, tmproof, err := obj.State.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) return diff --git a/x/ibc/04-channel/client/cli/query.go b/x/ibc/04-channel/client/cli/query.go index fcf28355d303..04e3ca0b19be 100644 --- a/x/ibc/04-channel/client/cli/query.go +++ b/x/ibc/04-channel/client/cli/query.go @@ -23,7 +23,7 @@ const ( FlagProve = "prove" ) -func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.Object, error) { +func object(ctx context.CLIContext, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.State, error) { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) connman := connection.NewManager(base, climan) @@ -45,7 +45,7 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { return ibcQueryCmd } -func QueryChannel(ctx context.CLIContext, obj channel.Object, prove bool) (res utils.JSONObject, err error) { +func QueryChannel(ctx context.CLIContext, obj channel.State, prove bool) (res utils.JSONObject, err error) { q := state.NewCLIQuerier(ctx) conn, connp, err := obj.ChannelCLI(q) @@ -113,7 +113,7 @@ func GetCmdQueryChannel(storeKey string, cdc *codec.Codec) *cobra.Command { } /* -func object(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string, connids []string) channel.Object { +func object(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string, connids []string) channel.Stage { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) connman := connection.NewManager(base, climan) diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index 476ed72f9313..81c0cc8022f5 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -33,12 +33,12 @@ const ( FlagFrom2 = "from2" ) -func handshake(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid, connid string) channel.HandshakeObject { +func handshake(cdc *codec.Codec, storeKey string, prefix []byte, portId, chanId, connId string) channel.HandshakeState { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) - climan := client.NewManager(base) - connman := connection.NewManager(base, climan) - man := channel.NewHandshaker(channel.NewManager(base, connman)) - return man.CLIObject(portid, chanid, []string{connid}) + clientManager := client.NewManager(base) + connectionManager := connection.NewManager(base, clientManager) + man := channel.NewHandshaker(channel.NewManager(base, connectionManager)) + return man.CLIObject(portId, chanId, []string{connId}) } func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -67,19 +67,19 @@ func getHeader(ctx context.CLIContext) (res tendermint.Header, err error) { } height := info.Response.LastBlockHeight - prevheight := height - 1 + prevHeight := height - 1 commit, err := node.Commit(&height) if err != nil { return } - validators, err := node.Validators(&prevheight) + validators, err := node.Validators(&prevHeight) if err != nil { return } - nextvalidators, err := node.Validators(&height) + nextValidators, err := node.Validators(&height) if err != nil { return } @@ -87,7 +87,7 @@ func getHeader(ctx context.CLIContext) (res tendermint.Header, err error) { res = tendermint.Header{ SignedHeader: commit.SignedHeader, ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextValidators.Validators), } return @@ -98,7 +98,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Use: "handshake", Short: "initiate connection handshake between two chains", Args: cobra.ExactArgs(6), - // Args: []string{portid1, chanid1, connid1, portid2, chanid2, connid2} RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom1)). @@ -139,29 +138,31 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } - clientid1 := conn1.Client + clientId1 := conn1.Client conn2, _, err := obj2.OriginConnection().ConnectionCLI(q2) if err != nil { return err } - clientid2 := conn2.Client + clientId2 := conn2.Client // TODO: check state and if not Idle continue existing process - msginit := channel.MsgOpenInit{ + msgInit := channel.MsgOpenInit{ PortID: portid1, ChannelID: chanid1, Channel: chan1, Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msginit}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgInit}) if err != nil { return err } - // Another block has to be passed after msginit is commited + // Another block has to be passed after msgInit is commited // to retrieve the correct proofs + // TODO: Modify this to actually check two blocks being processed, and + // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err := getHeader(ctx1) @@ -169,13 +170,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgupdate := client.MsgUpdateClient{ - ClientID: clientid2, + msgUpdate := client.MsgUpdateClient{ + ClientID: clientId2, Header: header, Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgUpdate}) fmt.Printf("updated apphash to %X\n", header.AppHash) @@ -191,7 +192,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgtry := channel.MsgOpenTry{ + msgTry := channel.MsgOpenTry{ PortID: portid2, ChannelID: chanid2, Channel: chan2, @@ -200,13 +201,15 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgTry}) if err != nil { return err } - // Another block has to be passed after msginit is commited + // Another block has to be passed after msgInit is commited // to retrieve the correct proofs + // TODO: Modify this to actually check two blocks being processed, and + // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err = getHeader(ctx2) @@ -214,13 +217,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgupdate = client.MsgUpdateClient{ - ClientID: clientid1, + msgUpdate = client.MsgUpdateClient{ + ClientID: clientId1, Header: header, Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgupdate}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgUpdate}) q2 = state.NewCLIQuerier(ctx2.WithHeight(header.Height - 1)) @@ -233,7 +236,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgack := channel.MsgOpenAck{ + msgAck := channel.MsgOpenAck{ PortID: portid1, ChannelID: chanid1, Proofs: []commitment.Proof{pchan, pstate}, @@ -241,13 +244,15 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgack}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgAck}) if err != nil { return err } - // Another block has to be passed after msginit is commited + // Another block has to be passed after msgInit is commited // to retrieve the correct proofs + // TODO: Modify this to actually check two blocks being processed, and + // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err = getHeader(ctx1) @@ -255,13 +260,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgupdate = client.MsgUpdateClient{ - ClientID: clientid2, + msgUpdate = client.MsgUpdateClient{ + ClientID: clientId2, Header: header, Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgUpdate}) q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) @@ -270,7 +275,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgconfirm := channel.MsgOpenConfirm{ + msgConfirm := channel.MsgOpenConfirm{ PortID: portid2, ChannelID: chanid2, Proofs: []commitment.Proof{pstate}, @@ -278,7 +283,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgconfirm}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgConfirm}) if err != nil { return err } @@ -287,6 +292,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { }, } + // TODO: Create flag description cmd.Flags().String(FlagNode1, "tcp://localhost:26657", "") cmd.Flags().String(FlagNode2, "tcp://localhost:26657", "") cmd.Flags().String(FlagFrom1, "", "") diff --git a/x/ibc/04-channel/codec.go b/x/ibc/04-channel/codec.go index 112aedc4c40c..38654da4e6a9 100644 --- a/x/ibc/04-channel/codec.go +++ b/x/ibc/04-channel/codec.go @@ -16,11 +16,5 @@ func RegisterCodec(cdc *codec.Codec) { } func SetMsgCodec(cdc *codec.Codec) { - // TODO - /* - if msgCdc != nil && msgCdc != cdc { - panic("MsgCdc set more than once") - } - */ msgCdc = cdc } diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index fd50dfa64476..850d97546e9e 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -9,10 +9,10 @@ import ( commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -type State = byte +type HandshakeStage = byte const ( - Idle State = iota + Idle HandshakeStage = iota Init OpenTry Open @@ -23,21 +23,17 @@ const ( type Handshaker struct { Manager - counterparty CounterpartyHandshaker + counterParty CounterpartyHandshaker } func (man Handshaker) Kind() string { return "handshake" } -// TODO: ocapify Manager; an actor who holds Manager -// should not be able to construct creaters from it -// or add Seal() method to Manager? func NewHandshaker(man Manager) Handshaker { return Handshaker{ - Manager: man, - - counterparty: CounterpartyHandshaker{man.counterparty}, + Manager: man, + counterParty: CounterpartyHandshaker{man.counterParty}, } } @@ -45,67 +41,64 @@ type CounterpartyHandshaker struct { man CounterpartyManager } -type HandshakeObject struct { - Object +type HandshakeState struct { + State - State state.Enum + HandshakeStage state.Enum - counterparty CounterHandshakeObject + counterParty CounterHandshakeState } -type CounterHandshakeObject struct { - CounterObject +type CounterHandshakeState struct { + CounterState - State commitment.Enum + Stage commitment.Enum } // CONTRACT: client and remote must be filled by the caller -func (man Handshaker) object(parent Object) HandshakeObject { - prefix := parent.portid + "/channels/" + parent.chanid - - return HandshakeObject{ - Object: parent, +func (man Handshaker) createState(parent State) HandshakeState { + prefix := parent.portId + "/channels/" + parent.chanId - State: man.protocol.Value([]byte(prefix + "/state")).Enum(), - - counterparty: man.counterparty.object(parent.counterparty), + return HandshakeState{ + State: parent, + HandshakeStage: man.protocol.Value([]byte(prefix + "/state")).Enum(), + counterParty: man.counterParty.createState(parent.counterParty), } } -func (man CounterpartyHandshaker) object(parent CounterObject) CounterHandshakeObject { - prefix := parent.portid + "/channels/" + parent.chanid - - return CounterHandshakeObject{ - CounterObject: man.man.object(parent.portid, parent.chanid), +func (man CounterpartyHandshaker) createState(parent CounterState) CounterHandshakeState { + prefix := parent.portId + "/channels/" + parent.chanId - State: man.man.protocol.Value([]byte(prefix + "/state")).Enum(), + return CounterHandshakeState{ + CounterState: man.man.object(parent.portId, parent.chanId), + Stage: man.man.protocol.Value([]byte(prefix + "/state")).Enum(), } } -func (man Handshaker) create(ctx sdk.Context, portid, chanid string, channel Channel) (obj HandshakeObject, err error) { +func (man Handshaker) create(ctx sdk.Context, portid, chanid string, channel Channel) (obj HandshakeState, err error) { cobj, err := man.Manager.create(ctx, portid, chanid, channel) if err != nil { return } - obj = man.object(cobj) + obj = man.createState(cobj) return obj, nil } -func (man Handshaker) query(ctx sdk.Context, portid, chanid string) (obj HandshakeObject, err error) { +func (man Handshaker) query(ctx sdk.Context, portid, chanid string) (obj HandshakeState, err error) { cobj, err := man.Manager.query(ctx, portid, chanid) if err != nil { return } - obj = man.object(cobj) + obj = man.createState(cobj) return obj, nil } /* -func (obj HandshakeObject) remove(ctx sdk.Context) { - obj.Object.remove(ctx) - obj.State.Delete(ctx) +func (obj HandshakeState) remove(ctx sdk.Context) { + obj.Stage.remove(ctx) + obj.HandshakeStage.Delete(ctx) obj.counterpartyClient.Delete(ctx) obj.NextTimeout.Delete(ctx) } @@ -122,32 +115,32 @@ func assertTimeout(ctx sdk.Context, timeoutHeight uint64) error { // Using proofs: none func (man Handshaker) OpenInit(ctx sdk.Context, portid, chanid string, channel Channel, -) (HandshakeObject, error) { +) (HandshakeState, error) { // man.Create() will ensure // assert(connectionHops.length === 2) // assert(get("channels/{identifier}") === null) and // set("channels/{identifier}", connection) if len(channel.ConnectionHops) != 1 { - return HandshakeObject{}, errors.New("ConnectionHops length must be 1") + return HandshakeState{}, errors.New("ConnectionHops length must be 1") } obj, err := man.create(ctx, portid, chanid, channel) if err != nil { - return HandshakeObject{}, err + return HandshakeState{}, err } - obj.State.Set(ctx, Init) + obj.HandshakeStage.Set(ctx, Init) return obj, nil } -// Using proofs: counterparty.{channel,state} +// Using proofs: counterParty.{channel,state} func (man Handshaker) OpenTry(ctx sdk.Context, proofs []commitment.Proof, height uint64, portid, chanid string, channel Channel, -) (obj HandshakeObject, err error) { +) (obj HandshakeState, err error) { if len(channel.ConnectionHops) != 1 { - return HandshakeObject{}, errors.New("ConnectionHops length must be 1") + return HandshakeState{}, errors.New("ConnectionHops length must be 1") } obj, err = man.create(ctx, portid, chanid, channel) if err != nil { @@ -159,17 +152,17 @@ func (man Handshaker) OpenTry(ctx sdk.Context, return } - if !obj.counterparty.State.Is(ctx, Init) { - err = errors.New("counterparty state not init") + if !obj.counterParty.Stage.Is(ctx, Init) { + err = errors.New("counterParty state not init") return } - if !obj.counterparty.Channel.Is(ctx, Channel{ + if !obj.counterParty.Channel.Is(ctx, Channel{ Counterparty: chanid, CounterpartyPort: portid, ConnectionHops: []string{obj.Connections[0].GetConnection(ctx).Counterparty}, }) { - err = errors.New("wrong counterparty connection") + err = errors.New("wrong counterParty connection") return } @@ -178,16 +171,16 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // assert(get("connections/{desiredIdentifier}") === null) and // set("connections{identifier}", connection) - obj.State.Set(ctx, OpenTry) + obj.HandshakeStage.Set(ctx, OpenTry) return } -// Using proofs: counterparty.{handshake,state,nextTimeout,clientid,client} +// Using proofs: counterParty.{handshake,state,nextTimeout,clientid,client} func (man Handshaker) OpenAck(ctx sdk.Context, proofs []commitment.Proof, height uint64, portid, chanid string, -) (obj HandshakeObject, err error) { +) (obj HandshakeState, err error) { obj, err = man.query(ctx, portid, chanid) if err != nil { return @@ -198,22 +191,22 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.State.Transit(ctx, Init, Open) { + if !obj.HandshakeStage.Transit(ctx, Init, Open) { err = errors.New("ack on non-init connection") return } - if !obj.counterparty.Channel.Is(ctx, Channel{ + if !obj.counterParty.Channel.Is(ctx, Channel{ Counterparty: chanid, CounterpartyPort: portid, ConnectionHops: []string{obj.Connections[0].GetConnection(ctx).Counterparty}, }) { - err = errors.New("wrong counterparty") + err = errors.New("wrong counterParty") return } - if !obj.counterparty.State.Is(ctx, OpenTry) { - err = errors.New("counterparty state not opentry") + if !obj.counterParty.Stage.Is(ctx, OpenTry) { + err = errors.New("counterParty state not opentry") return } @@ -221,8 +214,8 @@ func (man Handshaker) OpenAck(ctx sdk.Context, /* var expected client.ConsensusState obj.self.Get(ctx, expheight, &expected) - if !obj.counterparty.client.Is(ctx, expected) { - return errors.New("unexpected counterparty client value") + if !obj.counterParty.client.Is(ctx, expected) { + return errors.New("unexpected counterParty client value") } */ @@ -231,10 +224,10 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } -// Using proofs: counterparty.{connection,state, nextTimeout} +// Using proofs: counterParty.{connection,state, nextTimeout} func (man Handshaker) OpenConfirm(ctx sdk.Context, proofs []commitment.Proof, height uint64, - portid, chanid string) (obj HandshakeObject, err error) { + portid, chanid string) (obj HandshakeState, err error) { obj, err = man.query(ctx, portid, chanid) if err != nil { return @@ -250,8 +243,8 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - if !obj.counterparty.State.Is(ctx, Open) { - err = errors.New("counterparty state not open") + if !obj.counterParty.Stage.Is(ctx, Open) { + err = errors.New("counterParty state not open") return } @@ -262,36 +255,8 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, // TODO /* -func (obj HandshakeObject) OpenTimeout(ctx sdk.Context) error { - if !(obj.connection.Client().ConsensusState(ctx).GetHeight()) > obj.NextTimeout.Get(ctx)) { - return errors.New("timeout height not yet reached") - } - - switch obj.State.Get(ctx) { - case Init: - if !obj.counterparty.connection.Is(ctx, nil) { - return errors.New("counterparty connection exists") - } - case OpenTry: - if !(obj.counterparty.State.Is(ctx, Init) || - obj.counterparty.connection.Is(ctx, nil)) { - return errors.New("counterparty connection state not init") - } - // XXX: check if we need to verify symmetricity for timeout (already proven in OpenTry) - case Open: - if obj.counterparty.State.Is(ctx, OpenTry) { - return errors.New("counterparty connection state not tryopen") - } - } - - obj.remove(ctx) - - return nil -} - - -func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error { - if !obj.State.Transit(ctx, Open, CloseTry) { +func (obj HandshakeState) CloseInit(ctx sdk.Context, nextTimeout uint64) error { + if !obj.HandshakeStage.Transit(ctx, Open, CloseTry) { return errors.New("closeinit on non-open connection") } @@ -299,74 +264,4 @@ func (obj HandshakeObject) CloseInit(ctx sdk.Context, nextTimeout uint64) error return nil } - -func (obj HandshakeObject) CloseTry(ctx sdk.Context, nextTimeoutHeight uint64) error { - if !obj.State.Transit(ctx, Open, Closed) { - return errors.New("closetry on non-open connection") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.counterparty.State.Is(ctx, CloseTry) { - return errors.New("unexpected counterparty state value") - } - - if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { - return errors.New("unexpected counterparty timeout value") - } - - obj.NextTimeout.Set(ctx, nextTimeoutHeight) - - return nil -} - -func (obj HandshakeObject) CloseAck(ctx sdk.Context, timeoutHeight uint64) error { - if !obj.State.Transit(ctx, CloseTry, Closed) { - return errors.New("closeack on non-closetry connection") - } - - err := assertTimeout(ctx, timeoutHeight) - if err != nil { - return err - } - - if !obj.counterparty.State.Is(ctx, Closed) { - return errors.New("unexpected counterparty state value") - } - - if !obj.counterparty.NextTimeout.Is(ctx, timeoutHeight) { - return errors.New("unexpected counterparty timeout value") - } - - obj.NextTimeout.Set(ctx, 0) - - return nil -} - -func (obj HandshakeObject) CloseTimeout(ctx sdk.Context) error { - if !(obj.client.ConsensusState(ctx).GetHeight()) > obj.NextTimeout.Get(ctx)) { - return errors.New("timeout height not yet reached") - } - - // XXX: double check if the user can bypass the verification logic somehow - switch obj.State.Get(ctx) { - case CloseTry: - if !obj.counterparty.State.Is(ctx, Open) { - return errors.New("counterparty connection state not open") - } - case Closed: - if !obj.counterparty.State.Is(ctx, CloseTry) { - return errors.New("counterparty connection state not closetry") - } - } - - obj.State.Set(ctx, Open) - obj.NextTimeout.Set(ctx, 0) - - return nil - -} */ diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 0920e9119e65..88baa957777f 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -18,7 +18,7 @@ type Manager struct { connection connection.Manager - counterparty CounterpartyManager + counterParty CounterpartyManager ports map[string]struct{} } @@ -33,8 +33,7 @@ func NewManager(protocol state.Mapping, connection connection.Manager) Manager { return Manager{ protocol: protocol.Prefix(LocalRoot()), connection: connection, - counterparty: NewCounterpartyManager(protocol.Cdc()), - + counterParty: NewCounterpartyManager(protocol.Cdc()), ports: make(map[string]struct{}), } } @@ -48,45 +47,41 @@ func NewCounterpartyManager(cdc *codec.Codec) CounterpartyManager { } } -// CONTRACT: connection and counterparty must be filled by the caller -func (man Manager) object(portid, chanid string) Object { - key := portid + "/channels/" + chanid - return Object{ - chanid: chanid, - portid: portid, - Channel: man.protocol.Value([]byte(key)), - +// CONTRACT: connection and counterParty must be filled by the caller +func (man Manager) object(portId, chanId string) State { + key := portId + "/channels/" + chanId + return State{ + chanId: chanId, + portId: portId, + Channel: man.protocol.Value([]byte(key)), Available: man.protocol.Value([]byte(key + "/available")).Boolean(), - - SeqSend: man.protocol.Value([]byte(key + "/nextSequenceSend")).Integer(state.Dec), - SeqRecv: man.protocol.Value([]byte(key + "/nextSequenceRecv")).Integer(state.Dec), - Packets: man.protocol.Prefix([]byte(key + "/packets/")).Indexer(state.Dec), + SeqSend: man.protocol.Value([]byte(key + "/nextSequenceSend")).Integer(state.Dec), + SeqRecv: man.protocol.Value([]byte(key + "/nextSequenceRecv")).Integer(state.Dec), + Packets: man.protocol.Prefix([]byte(key + "/packets/")).Indexer(state.Dec), } } -func (man CounterpartyManager) object(portid, chanid string) CounterObject { +func (man CounterpartyManager) object(portid, chanid string) CounterState { key := portid + "/channels/" + chanid - return CounterObject{ - chanid: chanid, - portid: portid, - Channel: man.protocol.Value([]byte(key)), - + return CounterState{ + chanId: chanid, + portId: portid, + Channel: man.protocol.Value([]byte(key)), Available: man.protocol.Value([]byte(key + "/available")).Boolean(), - - SeqSend: man.protocol.Value([]byte(key + "/nextSequenceSend")).Integer(state.Dec), - SeqRecv: man.protocol.Value([]byte(key + "/nextSequenceRecv")).Integer(state.Dec), - Packets: man.protocol.Prefix([]byte(key + "/packets/")).Indexer(state.Dec), + SeqSend: man.protocol.Value([]byte(key + "/nextSequenceSend")).Integer(state.Dec), + SeqRecv: man.protocol.Value([]byte(key + "/nextSequenceRecv")).Integer(state.Dec), + Packets: man.protocol.Prefix([]byte(key + "/packets/")).Indexer(state.Dec), } } -func (man Manager) create(ctx sdk.Context, portid, chanid string, channel Channel) (obj Object, err error) { +func (man Manager) create(ctx sdk.Context, portid, chanid string, channel Channel) (obj State, err error) { obj = man.object(portid, chanid) if obj.exists(ctx) { err = errors.New("channel already exists for the provided id") return } obj.Channel.Set(ctx, channel) - obj.counterparty = man.counterparty.object(channel.CounterpartyPort, channel.Counterparty) + obj.counterParty = man.counterParty.object(channel.CounterpartyPort, channel.Counterparty) for _, hop := range channel.ConnectionHops { connobj, err := man.connection.Query(ctx, hop) @@ -97,15 +92,15 @@ func (man Manager) create(ctx sdk.Context, portid, chanid string, channel Channe } for _, hop := range channel.CounterpartyHops() { - connobj := man.counterparty.connection.Object(hop) - obj.counterparty.Connections = append(obj.counterparty.Connections, connobj) + connobj := man.counterParty.connection.CreateState(hop) + obj.counterParty.Connections = append(obj.counterParty.Connections, connobj) } return } // Does not check availability -func (man Manager) query(ctx sdk.Context, portid, chanid string) (obj Object, err error) { +func (man Manager) query(ctx sdk.Context, portid, chanid string) (obj State, err error) { obj = man.object(portid, chanid) if !obj.exists(ctx) { err = errors.New("channel not exists for the provided id") @@ -113,7 +108,7 @@ func (man Manager) query(ctx sdk.Context, portid, chanid string) (obj Object, er } channel := obj.GetChannel(ctx) - obj.counterparty = man.counterparty.object(channel.CounterpartyPort, channel.Counterparty) + obj.counterParty = man.counterParty.object(channel.CounterpartyPort, channel.Counterparty) for _, hop := range channel.ConnectionHops { connobj, err := man.connection.Query(ctx, hop) if err != nil { @@ -123,73 +118,26 @@ func (man Manager) query(ctx sdk.Context, portid, chanid string) (obj Object, er } for _, hop := range channel.CounterpartyHops() { - connobj := man.counterparty.connection.Object(hop) - obj.counterparty.Connections = append(obj.counterparty.Connections, connobj) + connobj := man.counterParty.connection.CreateState(hop) + obj.counterParty.Connections = append(obj.counterParty.Connections, connobj) } return } -func (man Manager) Query(ctx sdk.Context, portid, chanid string) (obj Object, err error) { +func (man Manager) Query(ctx sdk.Context, portid, chanid string) (obj State, err error) { obj, err = man.query(ctx, portid, chanid) if !obj.Available.Get(ctx) { - err = errors.New("channel not Available") + err = errors.New("channel not available") return } return } -// TODO -/* -func (man Manager) Port(port string, chanid func(string) bool) PortManager { - return PortManager{ - man: man, - port: le, - chanid: chanid, - } -} - -// PortManage is port specific -type PortManager struct { - man Manager - port string - chanid func(string) bool -} - -func (man PortManager) Create(ctx sdk.Context, portid, chanid string, channel Channel) (Object, error) { - if !man.chanid(chanid) { - return Object{}, errors.New("invalid channel id") - } - - if channel.Port != man.port { - return Object{}, errors.New("invalid port") - } - - return man.man.Create(ctx, portid, chanid, channel) -} - -func (man PortManager) Query(ctx sdk.Context, portid, chanid string) (Object, error) { - if !man.chanid(chanid) { - return Object{}, errors.New("invalid channel id") - } - - obj, err := man.man.Query(ctx, portid, chanid) - if err != nil { - return Object{}, err - } - - if obj.Value(ctx).Port != man.port { - return Object{}, errors.New("invalid port") - } - - return obj, nil -} -*/ - -type Object struct { - chanid string - portid string +type State struct { + chanId string + portId string Channel state.Value @@ -199,14 +147,14 @@ type Object struct { Available state.Boolean - Connections []connection.Object + Connections []connection.State - counterparty CounterObject + counterParty CounterState } -type CounterObject struct { - chanid string - portid string +type CounterState struct { + chanId string + portId string Channel commitment.Value @@ -216,54 +164,45 @@ type CounterObject struct { Available commitment.Boolean - Connections []connection.CounterObject + Connections []connection.CounterState } -func (obj Object) OriginConnection() connection.Object { +func (obj State) OriginConnection() connection.State { return obj.Connections[0] } -func (obj Object) Context(ctx sdk.Context, proofs []commitment.Proof, height uint64) (sdk.Context, error) { +func (obj State) Context(ctx sdk.Context, proofs []commitment.Proof, height uint64) (sdk.Context, error) { return obj.OriginConnection().Context(ctx, height, proofs) } -func (obj Object) ChanID() string { - return obj.chanid +func (obj State) ChanID() string { + return obj.chanId } -func (obj Object) GetChannel(ctx sdk.Context) (res Channel) { +func (obj State) GetChannel(ctx sdk.Context) (res Channel) { obj.Channel.Get(ctx, &res) return } -func (obj Object) PacketCommit(ctx sdk.Context, index uint64) []byte { +func (obj State) PacketCommit(ctx sdk.Context, index uint64) []byte { return obj.Packets.Value(index).GetRaw(ctx) } /* -func (obj Object) Sendable(ctx sdk.Context) bool { +func (obj Stage) Sendable(ctx sdk.Context) bool { return obj.connection } -func (obj Object) Receivable(ctx sdk.Context) bool { +func (obj Stage) Receivable(ctx sdk.Context) bool { return kinds[obj.kind.Get(ctx)].Receivable } */ -func (obj Object) exists(ctx sdk.Context) bool { +func (obj State) exists(ctx sdk.Context) bool { return obj.Channel.Exists(ctx) } -func (man Manager) Send(ctx sdk.Context, portid, chanid string, packet Packet) error { - /* - if !obj.Sendable(ctx) { - return errors.New("cannot send Packets on this channel") - } - */ - if portid != packet.SenderPort() { - return errors.New("Invalid portid") - } - - obj, err := man.Query(ctx, portid, chanid) +func (man Manager) Send(ctx sdk.Context, chanId string, packet Packet) error { + obj, err := man.Query(ctx, packet.SenderPort(), chanId) if err != nil { return err } @@ -279,7 +218,7 @@ func (man Manager) Send(ctx sdk.Context, portid, chanid string, packet Packet) e EventTypeSendPacket, sdk.NewAttribute(AttributeKeySenderPort, packet.SenderPort()), sdk.NewAttribute(AttributeKeyReceiverPort, packet.ReceiverPort()), - sdk.NewAttribute(AttributeKeyChannelID, chanid), + sdk.NewAttribute(AttributeKeyChannelID, chanId), sdk.NewAttribute(AttributeKeySequence, strconv.FormatUint(obj.SeqSend.Get(ctx), 10)), ), }) @@ -308,10 +247,8 @@ func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, height ui if err != nil { return err } - - // XXX: increment should happen before verification, reflect on the spec - // TODO: packet should be custom marshalled - if !obj.counterparty.Packets.Value(obj.SeqRecv.Increment(ctx)).Is(ctx, packet) { + + if !obj.counterParty.Packets.Value(obj.SeqRecv.Increment(ctx)).Is(ctx, packet) { return errors.New("verification failed") } diff --git a/x/ibc/04-channel/port.go b/x/ibc/04-channel/port.go index 8c06a1e6f12f..8547d2819163 100644 --- a/x/ibc/04-channel/port.go +++ b/x/ibc/04-channel/port.go @@ -8,7 +8,6 @@ import ( type Port struct { channel Manager id string - valid *bool // once invalid forever invalid } // bindPort, expected to be called only at init time @@ -18,17 +17,24 @@ func (man Manager) Port(id string) Port { panic("port already occupied") } man.ports[id] = struct{}{} - valid := true - return Port{man, id, &valid} + return Port{man, id} } // releasePort func (port Port) Release() { delete(port.channel.ports, port.id) - *port.valid = false +} + +func (man Manager) IsValid(port Port) bool { + _, ok := man.ports[port.id] + return ok } func (port Port) Send(ctx sdk.Context, chanid string, packet Packet) error { + if !port.channel.IsValid(port) { + return errors.New("Port is not in valid state") + } + if packet.SenderPort() != port.id { panic("Packet sent on wrong port") } diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 9d159960653b..5ed8456bcdd4 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -28,15 +28,13 @@ type Node struct { func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res := &Node{ - Node: connection.NewNode(self, counter, cdc), // TODO: test with key prefix - + Node: connection.NewNode(self, counter, cdc), Cdc: cdc, } res.Counterparty = &Node{ Node: res.Node.Counterparty, Counterparty: res, - Cdc: cdc, } @@ -64,7 +62,7 @@ func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Conte return ctx, channel.NewHandshaker(man) } -func (node *Node) CLIObject() channel.HandshakeObject { +func (node *Node) CLIObject() channel.HandshakeState { man := node.Manager() return channel.NewHandshaker(man).CLIObject(PortName, node.Name, []string{node.Name}) } diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index 7ca7579d9eb8..681c8bd56985 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -109,6 +109,5 @@ type Value interface { } func NewProofFromValue(proof *merkle.Proof, prefix []byte, value Value) Proof { - // TODO: check HasPrefix return Proof{proof, bytes.TrimPrefix(value.KeyBytes(), prefix)} } diff --git a/x/ibc/23-commitment/store.go b/x/ibc/23-commitment/store.go index 2894561d316b..1283c05983bd 100644 --- a/x/ibc/23-commitment/store.go +++ b/x/ibc/23-commitment/store.go @@ -3,7 +3,6 @@ package commitment import ( "bytes" "errors" - "fmt" ) // Store proves key-value pairs' inclusion or non-inclusion with @@ -12,7 +11,7 @@ type Store interface { Prove(key, value []byte) bool } -var _ Store = prefix{} // TODO: pointer +var _ Store = prefix{} type prefix struct { store Store @@ -60,7 +59,6 @@ func NewStore(root Root, path Path, proofs []Proof) (res *store, err error) { err = errors.New("proof type not matching with root's") return } - fmt.Println("set", string(proof.GetKey())) res.proofs[string(proof.GetKey())] = proof } @@ -81,12 +79,10 @@ func (store *store) Prove(key, value []byte) bool { } proof, ok := store.proofs[string(key)] if !ok { - fmt.Println(111, string(key)) return false } err := proof.Verify(store.root, store.path, value) if err != nil { - fmt.Println(222, string(key), err) return false } store.verified[string(key)] = value diff --git a/x/ibc/23-commitment/value.go b/x/ibc/23-commitment/value.go index 947d322c06bd..18de5d941600 100644 --- a/x/ibc/23-commitment/value.go +++ b/x/ibc/23-commitment/value.go @@ -66,7 +66,6 @@ func (v Value) Is(ctx sdk.Context, value interface{}) bool { // IsRaw() proves the proof with the Value's key and the provided raw value bytes. func (v Value) IsRaw(ctx sdk.Context, value []byte) bool { - return v.m.store(ctx).Prove(v.key, value) } diff --git a/x/ibc/keeper.go b/x/ibc/keeper.go index 859d909ad82a..dbf8a4b4766f 100644 --- a/x/ibc/keeper.go +++ b/x/ibc/keeper.go @@ -18,11 +18,11 @@ type Keeper struct { func NewKeeper(cdc *codec.Codec, key sdk.StoreKey) Keeper { base := state.NewMapping(key, cdc, version.DefaultPrefix()) - climan := client.NewManager(base) - connman := connection.NewManager(base, climan) + client := client.NewManager(base) + connman := connection.NewManager(base, client) chanman := channel.NewManager(base, connman) return Keeper{ - client: climan, + client: client, connection: connection.NewHandshaker(connman), channel: channel.NewHandshaker(chanman), } diff --git a/x/ibc/mock/types/msgs.go b/x/ibc/mock/types/msgs.go index 1cd26b66a984..09a226b41e63 100644 --- a/x/ibc/mock/types/msgs.go +++ b/x/ibc/mock/types/msgs.go @@ -34,7 +34,7 @@ func (msg MsgSequence) ValidateBasic() sdk.Error { } func (msg MsgSequence) GetSignBytes() []byte { - return cdc.MustMarshalJSON(msg) // TODO + return sdk.MustSortJSON(cdc.MustMarshalJSON(msg)) } func (msg MsgSequence) GetSigners() []sdk.AccAddress { From 025caf1fbb328a66373ac9c98601494512292fa5 Mon Sep 17 00:00:00 2001 From: mossid Date: Wed, 25 Sep 2019 10:08:35 -0700 Subject: [PATCH 175/182] fix mock cli in progress --- x/ibc/04-channel/client/cli/tx.go | 120 ++++++++++++++++++++++++++++++ x/ibc/04-channel/manager.go | 2 +- x/ibc/mock/client/cli/tx.go | 10 +-- x/ibc/mock/handler.go | 9 +++ x/ibc/mock/types/packets.go | 4 +- 5 files changed, 137 insertions(+), 8 deletions(-) diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index 476ed72f9313..9003300df07d 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -1,6 +1,7 @@ package cli import ( + "errors" "fmt" "time" @@ -41,6 +42,14 @@ func handshake(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid, return man.CLIObject(portid, chanid, []string{connid}) } +func flush(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.HandshakeObject, error) { + base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) + climan := client.NewManager(base) + connman := connection.NewManager(base, climan) + man := channel.NewHandshaker(channel.NewManager(base, connman)) + return man.CLIQuery(q, portid, chanid) +} + func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "channel", @@ -297,3 +306,114 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return cmd } + +func GetCmdFlushPackets(storeKey string, cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "flush", + Short: "flush packets on queue", + Args: cobra.ExactArgs(2), + // Args: []string{portid, chanid} + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + ctx1 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom1)). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode1)). + WithBroadcastMode(flags.BroadcastBlock) + q1 := state.NewCLIQuerier(ctx1) + + ctx2 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom2)). + WithCodec(cdc). + WithNodeURI(viper.GetString(FlagNode2)). + WithBroadcastMode(flags.BroadcastBlock) + q2 := state.NewCLIQuerier(ctx2) + + portid1, chanid1 := args[0], args[1] + + obj1, err := flush(q1, cdc, storeKey, version.DefaultPrefix(), portid1, chanid1) + if err != nil { + return err + } + + chan1, _, err := obj1.ChannelCLI(q1) + if err != nil { + return err + } + + portid2, chanid2 := chan1.CounterpartyPort, chan1.Counterparty + + obj2, err := flush(q2, cdc, storeKey, version.DefaultPrefix(), portid2, chanid2) + if err != nil { + return err + } + + chan2, _, err := obj2.ChannelCLI(q2) + if err != nil { + return err + } + + conn2, _, err := chan2.ConnectionCLI(q2) + if err != nil { + return err + } + + client2 := conn2.Client + + portid2, chanid2 := chan1.CounterpartyPort, chan1.Counterparty + + obj2, err := flush(q2, cdc, storeKey, version.DefaultPrefix(), portid2, chanid2) + if err != nil { + return err + } + + seqrecv, _, err := obj2.SeqRecvCLI(q2) + if err != nil { + return err + } + + seqsend, _, err := obj1.SeqSendCLI(q1) + if err != nil { + return err + } + + // SeqRecv is the latest received packet index(0 if not exists) + // SeqSend is the latest sent packet index (0 if not exists) + if !(seqsend > seqrecv) { + return errors.New("no unsent packets") + } + + // TODO: optimize, don't updateclient if already updated + header, err := getHeader(ctx1) + if err != nil { + return err + } + + msgupdate := client.MsgUpdateClient{ + ClientID: client2, + Header: header, + Signer: ctx2.GetFromAddress(), + } + + msgs := []sdk.Msg{msgupdate} + + for i := seqrecv + 1; i <= seqsend; i++ { + packet, proof, err := obj1.PacketCLI(q1, i) + if err != nil { + return err + } + + msg := channel.MsgPacket() + } + }, + } + + cmd.Flags().String(FlagNode1, "tcp://localhost:26657", "") + cmd.Flags().String(FlagNode2, "tcp://localhost:26657", "") + cmd.Flags().String(FlagFrom1, "", "") + cmd.Flags().String(FlagFrom2, "", "") + + cmd.MarkFlagRequired(FlagFrom1) + cmd.MarkFlagRequired(FlagFrom2) + + return cmd + +} diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index 0920e9119e65..ca8596a6a6a4 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -272,7 +272,7 @@ func (man Manager) Send(ctx sdk.Context, portid, chanid string, packet Packet) e return errors.New("timeout height higher than the latest known") } - obj.Packets.Set(ctx, obj.SeqSend.Increment(ctx), packet) + obj.Packets.SetRaw(ctx, obj.SeqSend.Increment(ctx), packet.Commitment()) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( diff --git a/x/ibc/mock/client/cli/tx.go b/x/ibc/mock/client/cli/tx.go index 996baa46dc37..4db71904ba3d 100644 --- a/x/ibc/mock/client/cli/tx.go +++ b/x/ibc/mock/client/cli/tx.go @@ -29,15 +29,15 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { func SequenceTxCmd(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "sequence [from-key-or-address] [channel-id] [sequence]", + Use: "sequence [channel-id] [sequence]", Short: "Send SequencePacket", - Args: cobra.ExactArgs(3), + Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) - ctx := context.NewCLIContextWithFrom(args[0]).WithCodec(cdc) + ctx := context.NewCLIContext().WithCodec(cdc) - chanid := args[1] - seq, err := strconv.ParseUint(args[2], 10, 64) + chanid := args[0] + seq, err := strconv.ParseUint(args[1], 10, 64) if err != nil { return err } diff --git a/x/ibc/mock/handler.go b/x/ibc/mock/handler.go index 4706c58a4ec7..90a459fd3c59 100644 --- a/x/ibc/mock/handler.go +++ b/x/ibc/mock/handler.go @@ -10,6 +10,8 @@ import ( func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { + case MsgSequence: + return handleMsgSequence(ctx, k, msg) case ibc.MsgPacket: switch packet := msg.Packet.(type) { case types.PacketSequence: @@ -23,6 +25,13 @@ func NewHandler(k Keeper) sdk.Handler { } } +func handleMsgSequence(ctx sdk.Context, k Keeper, msg MsgSequence) (res sdk.Result) { + err := k.ibcPort.SendPacket(ctx, msg.ChannelID, types.PacketSequence{msg.Sequence}) + if err != nil { + + } +} + func handleMyPacket(ctx sdk.Context, k Keeper, packet types.PacketSequence, chanid string) (res sdk.Result) { err := k.CheckAndSetSequence(ctx, chanid, packet.Sequence) if err != nil { diff --git a/x/ibc/mock/types/packets.go b/x/ibc/mock/types/packets.go index 5daf0147756b..914454e9e5e9 100644 --- a/x/ibc/mock/types/packets.go +++ b/x/ibc/mock/types/packets.go @@ -43,11 +43,11 @@ func (packet *PacketSequence) UnmarshalJSON(bz []byte) (err error) { } func (PacketSequence) SenderPort() string { - return "ibc-mock" + return "ibcmock" } func (PacketSequence) ReceiverPort() string { - return "ibc-mock" + return "ibcmock" } func (PacketSequence) String() string { From 1cea7e387b6e021636e4fd62508deed2428698dc Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 27 Sep 2019 18:59:16 -0700 Subject: [PATCH 176/182] finalize cleanup, mock cli wip --- x/ibc/02-client/cli.go | 8 +- x/ibc/02-client/client/cli/query.go | 4 +- x/ibc/02-client/manager.go | 44 ++++---- x/ibc/03-connection/cli.go | 32 +++--- x/ibc/03-connection/client/cli/query.go | 8 +- x/ibc/03-connection/client/cli/tx.go | 6 +- x/ibc/03-connection/client/utils/types.go | 14 +-- x/ibc/03-connection/manager.go | 12 +-- x/ibc/03-connection/tests/types.go | 24 ++--- x/ibc/04-channel/cli.go | 16 +-- x/ibc/04-channel/client/cli/query.go | 8 +- x/ibc/04-channel/client/cli/tx.go | 116 +++++++++++++--------- x/ibc/04-channel/client/utils/types.go | 24 ++--- x/ibc/04-channel/handshake.go | 24 ++--- x/ibc/04-channel/manager.go | 8 +- x/ibc/04-channel/port.go | 5 +- x/ibc/04-channel/tests/channel_test.go | 27 +---- x/ibc/04-channel/tests/types.go | 30 +++--- x/ibc/04-channel/types.go | 3 +- x/ibc/mock/client/cli/tx.go | 53 ---------- x/ibc/mock/codec.go | 10 -- x/ibc/mock/{ => recv}/client/cli/query.go | 6 +- x/ibc/mock/{ => recv}/handler.go | 11 +- x/ibc/mock/{ => recv}/keeper.go | 13 ++- x/ibc/mock/recv/module.go | 103 +++++++++++++++++++ x/ibc/mock/send/handler.go | 26 +++++ x/ibc/mock/send/keeper.go | 49 +++++++++ x/ibc/mock/{ => send}/module.go | 7 +- x/ibc/mock/types/codec.go | 9 ++ x/ibc/mock/types/keys.go | 4 +- x/ibc/mock/types/packets.go | 7 ++ 31 files changed, 423 insertions(+), 288 deletions(-) delete mode 100644 x/ibc/mock/client/cli/tx.go delete mode 100644 x/ibc/mock/codec.go rename x/ibc/mock/{ => recv}/client/cli/query.go (86%) rename x/ibc/mock/{ => recv}/handler.go (71%) rename x/ibc/mock/{ => recv}/keeper.go (67%) create mode 100644 x/ibc/mock/recv/module.go create mode 100644 x/ibc/mock/send/handler.go create mode 100644 x/ibc/mock/send/keeper.go rename x/ibc/mock/{ => send}/module.go (92%) create mode 100644 x/ibc/mock/types/codec.go diff --git a/x/ibc/02-client/cli.go b/x/ibc/02-client/cli.go index 29533883c76a..0895bbcc2c38 100644 --- a/x/ibc/02-client/cli.go +++ b/x/ibc/02-client/cli.go @@ -9,24 +9,24 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func (obj Object) prefix() []byte { +func (obj State) prefix() []byte { return bytes.Split(obj.ConsensusState.KeyBytes(), LocalRoot())[0] } -func (obj Object) RootCLI(q state.ABCIQuerier, height uint64) (res commitment.Root, proof merkle.Proof, err error) { +func (obj State) RootCLI(q state.ABCIQuerier, height uint64) (res commitment.Root, proof merkle.Proof, err error) { root := obj.Roots.Value(height) tmproof, err := root.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), root) return } -func (obj Object) ConsensusStateCLI(q state.ABCIQuerier) (res ConsensusState, proof merkle.Proof, err error) { +func (obj State) ConsensusStateCLI(q state.ABCIQuerier) (res ConsensusState, proof merkle.Proof, err error) { tmproof, err := obj.ConsensusState.Query(q, &res) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.ConsensusState) return } -func (obj Object) FrozenCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { +func (obj State) FrozenCLI(q state.ABCIQuerier) (res bool, proof merkle.Proof, err error) { res, tmproof, err := obj.Frozen.Query(q) proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Frozen) return diff --git a/x/ibc/02-client/client/cli/query.go b/x/ibc/02-client/client/cli/query.go index 49a5ac8b65dc..ff0010c82ded 100644 --- a/x/ibc/02-client/client/cli/query.go +++ b/x/ibc/02-client/client/cli/query.go @@ -55,7 +55,7 @@ func GetCmdQueryClient(storeKey string, cdc *codec.Codec) *cobra.Command { man := client.NewManager(mapp) id := args[0] - state, _, err := man.Object(id).ConsensusStateCLI(q) + state, _, err := man.State(id).ConsensusStateCLI(q) if err != nil { return err } @@ -83,7 +83,7 @@ func GetCmdQueryRoot(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - root, _, err := man.Object(id).RootCLI(q, height) + root, _, err := man.State(id).RootCLI(q, height) if err != nil { return err } diff --git a/x/ibc/02-client/manager.go b/x/ibc/02-client/manager.go index 06927c33d1eb..b5efd7bd94c1 100644 --- a/x/ibc/02-client/manager.go +++ b/x/ibc/02-client/manager.go @@ -40,8 +40,8 @@ func (man Manager) RegisterKind(kind Kind, pred ValidityPredicate) Manager { return man } */ -func (man Manager) Object(id string) Object { - return Object{ +func (man Manager) State(id string) State { + return State{ id: id, Roots: man.protocol.Prefix([]byte(id + "/roots/")).Indexer(state.Dec), ConsensusState: man.protocol.Value([]byte(id)), @@ -49,71 +49,71 @@ func (man Manager) Object(id string) Object { } } -func (man Manager) Create(ctx sdk.Context, id string, cs ConsensusState) (Object, error) { - obj := man.Object(id) +func (man Manager) Create(ctx sdk.Context, id string, cs ConsensusState) (State, error) { + obj := man.State(id) if obj.exists(ctx) { - return Object{}, errors.New("Create client on already existing id") + return State{}, errors.New("Create client on already existing id") } obj.Roots.Set(ctx, cs.GetHeight(), cs.GetRoot()) obj.ConsensusState.Set(ctx, cs) return obj, nil } -func (man Manager) Query(ctx sdk.Context, id string) (Object, error) { - res := man.Object(id) +func (man Manager) Query(ctx sdk.Context, id string) (State, error) { + res := man.State(id) if !res.exists(ctx) { - return Object{}, errors.New("client not exists") + return State{}, errors.New("client not exists") } return res, nil } -func (man CounterpartyManager) Object(id string) CounterObject { - return CounterObject{ +func (man CounterpartyManager) State(id string) CounterState { + return CounterState{ id: id, ConsensusState: man.protocol.Value([]byte(id)), } } -func (man CounterpartyManager) Query(id string) CounterObject { - return man.Object(id) +func (man CounterpartyManager) Query(id string) CounterState { + return man.State(id) } // Any actor holding the Stage can access on and modify that client information -type Object struct { +type State struct { id string Roots state.Indexer ConsensusState state.Value // ConsensusState Frozen state.Boolean } -type CounterObject struct { +type CounterState struct { id string ConsensusState commitment.Value } -func (obj Object) ID() string { +func (obj State) ID() string { return obj.id } -func (obj Object) GetConsensusState(ctx sdk.Context) (res ConsensusState) { +func (obj State) GetConsensusState(ctx sdk.Context) (res ConsensusState) { obj.ConsensusState.Get(ctx, &res) return } -func (obj Object) GetRoot(ctx sdk.Context, height uint64) (res commitment.Root, err error) { +func (obj State) GetRoot(ctx sdk.Context, height uint64) (res commitment.Root, err error) { err = obj.Roots.GetSafe(ctx, height, &res) return } -func (obj CounterObject) Is(ctx sdk.Context, client ConsensusState) bool { +func (obj CounterState) Is(ctx sdk.Context, client ConsensusState) bool { return obj.ConsensusState.Is(ctx, client) } -func (obj Object) exists(ctx sdk.Context) bool { +func (obj State) exists(ctx sdk.Context) bool { return obj.ConsensusState.Exists(ctx) } -func (obj Object) Update(ctx sdk.Context, header Header) error { +func (obj State) Update(ctx sdk.Context, header Header) error { if !obj.exists(ctx) { panic("should not update nonexisting client") } @@ -134,7 +134,7 @@ func (obj Object) Update(ctx sdk.Context, header Header) error { return nil } -func (obj Object) Freeze(ctx sdk.Context) error { +func (obj State) Freeze(ctx sdk.Context) error { if !obj.exists(ctx) { panic("should not freeze nonexisting client") } @@ -148,7 +148,7 @@ func (obj Object) Freeze(ctx sdk.Context) error { return nil } -func (obj Object) Delete(ctx sdk.Context) error { +func (obj State) Delete(ctx sdk.Context) error { if !obj.exists(ctx) { panic("should not delete nonexisting client") } diff --git a/x/ibc/03-connection/cli.go b/x/ibc/03-connection/cli.go index ca114e8e2e8c..f4222722332f 100644 --- a/x/ibc/03-connection/cli.go +++ b/x/ibc/03-connection/cli.go @@ -7,12 +7,22 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func (man Manager) CLIObject(connid, clientid string) State { - obj := man.Object(connid) - obj.Client = man.client.Object(clientid) +func (man Manager) CLIState(connid, clientid string) State { + obj := man.State(connid) + obj.Client = man.client.State(clientid) return obj } +func (man Manager) CLIQuery(q state.ABCIQuerier, connid string) (State, error) { + obj := man.State(connid) + conn, _, err := obj.ConnectionCLI(q) + if err != nil { + return State{}, err + } + obj.Client = man.client.State(conn.Client) + return obj, nil +} + func (obj State) prefix() []byte { return bytes.Split(obj.Connection.KeyBytes(), LocalRoot())[0] } @@ -35,23 +45,21 @@ func (obj State) KindCLI(q state.ABCIQuerier) (res string, proof merkle.Proof, e return } -func (man Handshaker) CLIObject(connid, clientid string) HandshakeState { - return man.CreateState(man.man.CLIObject(connid, clientid)) +func (man Handshaker) CLIState(connid, clientid string) HandshakeState { + return man.CreateState(man.man.CLIState(connid, clientid)) } func (man Handshaker) CLIQuery(q state.ABCIQuerier, connid string) (HandshakeState, error) { - obj := man.man.Object(connid) - conn, _, err := obj.ConnectionCLI(q) + state, err := man.man.CLIQuery(q, connid) if err != nil { return HandshakeState{}, err } - obj.Client = man.man.client.Object(conn.Client) - return man.CreateState(obj), nil + return man.CreateState(state), nil } -func (obj HandshakeState) StateCLI(q state.ABCIQuerier) (res byte, proof merkle.Proof, err error) { - res, tmproof, err := obj.State.Query(q) - proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) +func (obj HandshakeState) StageCLI(q state.ABCIQuerier) (res byte, proof merkle.Proof, err error) { + res, tmproof, err := obj.Stage.Query(q) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Stage) return } diff --git a/x/ibc/03-connection/client/cli/query.go b/x/ibc/03-connection/client/cli/query.go index 63b563c5d44b..74c982e9cb52 100644 --- a/x/ibc/03-connection/client/cli/query.go +++ b/x/ibc/03-connection/client/cli/query.go @@ -26,7 +26,7 @@ func object(cdc *codec.Codec, storeKey string, prefix []byte, connid, clientid s base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) man := connection.NewManager(base, climan) - return man.CLIObject(connid, clientid) + return man.CLIState(connid, clientid) } func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { @@ -43,7 +43,7 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { return ibcQueryCmd } -func QueryConnection(ctx context.CLIContext, obj connection.State, prove bool) (res utils.JSONObject, err error) { +func QueryConnection(ctx context.CLIContext, obj connection.State, prove bool) (res utils.JSONState, err error) { q := state.NewCLIQuerier(ctx) conn, connp, err := obj.ConnectionCLI(q) @@ -60,14 +60,14 @@ func QueryConnection(ctx context.CLIContext, obj connection.State, prove bool) ( } if prove { - return utils.NewJSONObject( + return utils.NewJSONState( conn, connp, avail, availp, kind, kindp, ), nil } - return utils.NewJSONObject( + return utils.NewJSONState( conn, nil, avail, nil, kind, nil, diff --git a/x/ibc/03-connection/client/cli/tx.go b/x/ibc/03-connection/client/cli/tx.go index 50e1f0ddf661..43ce9ae810e1 100644 --- a/x/ibc/03-connection/client/cli/tx.go +++ b/x/ibc/03-connection/client/cli/tx.go @@ -210,7 +210,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } - _, pstate, err := obj1.StateCLI(q1) + _, pstate, err := obj1.StageCLI(q1) if err != nil { return err } @@ -261,7 +261,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } - _, pstate, err = obj2.StateCLI(q2) + _, pstate, err = obj2.StageCLI(q2) if err != nil { return err } @@ -306,7 +306,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) - _, pstate, err = obj1.StateCLI(q1) + _, pstate, err = obj1.StageCLI(q1) if err != nil { return err } diff --git a/x/ibc/03-connection/client/utils/types.go b/x/ibc/03-connection/client/utils/types.go index 9ef404879a4b..9e7e2c807b20 100644 --- a/x/ibc/03-connection/client/utils/types.go +++ b/x/ibc/03-connection/client/utils/types.go @@ -5,7 +5,7 @@ import ( commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -type JSONObject struct { +type JSONState struct { Connection connection.Connection `json:"connection"` ConnectionProof commitment.Proof `json:"connection_proof,omitempty"` Available bool `json:"available"` @@ -19,12 +19,12 @@ type JSONObject struct { CounterpartyClientProof commitment.Proof `json:"counterparty_client_proof,omitempty"` } -func NewJSONObject( +func NewJSONState( conn connection.Connection, connp commitment.Proof, avail bool, availp commitment.Proof, kind string, kindp commitment.Proof, -) JSONObject { - return JSONObject{ +) JSONState { + return JSONState{ Connection: conn, ConnectionProof: connp, Available: avail, @@ -34,14 +34,14 @@ func NewJSONObject( } } -func NewHandshakeJSONObject( +func NewHandshakeJSONState( conn connection.Connection, connp commitment.Proof, avail bool, availp commitment.Proof, kind string, kindp commitment.Proof, state byte, statep commitment.Proof, cpclient string, cpclientp commitment.Proof, -) JSONObject { - return JSONObject{ +) JSONState { + return JSONState{ Connection: conn, ConnectionProof: connp, Available: avail, diff --git a/x/ibc/03-connection/manager.go b/x/ibc/03-connection/manager.go index a1c500af415a..ffeaaeef6d5f 100644 --- a/x/ibc/03-connection/manager.go +++ b/x/ibc/03-connection/manager.go @@ -56,12 +56,12 @@ type State struct { Kind state.String - Client client.Object + Client client.State path merkle.Path } -func (man Manager) Object(id string) State { +func (man Manager) State(id string) State { return State{ id: id, @@ -86,7 +86,7 @@ type CounterState struct { Kind commitment.String - Client client.CounterObject // nolint: unused + Client client.CounterState // nolint: unused } func (man CounterpartyManager) CreateState(id string) CounterState { @@ -152,7 +152,7 @@ func (man Manager) Cdc() *codec.Codec { } func (man Manager) create(ctx sdk.Context, id string, connection Connection, kind string) (obj State, err error) { - obj = man.Object(id) + obj = man.State(id) if obj.exists(ctx) { err = errors.New("Stage already exists") return @@ -170,7 +170,7 @@ func (man Manager) create(ctx sdk.Context, id string, connection Connection, kin // query() is used internally by the connection creators // checks connection kind, doesn't check avilability func (man Manager) query(ctx sdk.Context, id string, kind string) (obj State, err error) { - obj = man.Object(id) + obj = man.State(id) if !obj.exists(ctx) { err = errors.New("Stage not exists") return @@ -187,7 +187,7 @@ func (man Manager) query(ctx sdk.Context, id string, kind string) (obj State, er } func (man Manager) Query(ctx sdk.Context, id string) (obj State, err error) { - obj = man.Object(id) + obj = man.State(id) if !obj.exists(ctx) { err = errors.New("Stage not exists") return diff --git a/x/ibc/03-connection/tests/types.go b/x/ibc/03-connection/tests/types.go index 83ee9543ea56..df188acdabf9 100644 --- a/x/ibc/03-connection/tests/types.go +++ b/x/ibc/03-connection/tests/types.go @@ -92,9 +92,9 @@ func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Conte return ctx, connection.NewHandshaker(man) } -func (node *Node) CLIObject() connection.HandshakeState { +func (node *Node) CLIState() connection.HandshakeState { _, man := node.Manager() - return connection.NewHandshaker(man).CLIObject(node.Name, node.Name) + return connection.NewHandshaker(man).CLIState(node.Name, node.Name) } func (node *Node) Mapping() state.Mapping { @@ -112,7 +112,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenInit(ctx, node.Name, node.Connection, node.CounterpartyClient) require.NoError(t, err) - require.Equal(t, connection.Init, obj.State.Get(ctx)) + require.Equal(t, connection.Init, obj.Stage.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient.Get(ctx)) require.False(t, obj.Available.Get(ctx)) @@ -123,7 +123,7 @@ func (node *Node) OpenTry(t *testing.T, height uint64, proofs ...commitment.Proo ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenTry(ctx, proofs, height, node.Name, node.Connection, node.CounterpartyClient) require.NoError(t, err) - require.Equal(t, connection.OpenTry, obj.State.Get(ctx)) + require.Equal(t, connection.OpenTry, obj.Stage.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) require.Equal(t, node.CounterpartyClient, obj.CounterpartyClient.Get(ctx)) require.False(t, obj.Available.Get(ctx)) @@ -134,7 +134,7 @@ func (node *Node) OpenAck(t *testing.T, height uint64, proofs ...commitment.Proo ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenAck(ctx, proofs, height, node.Name) require.NoError(t, err) - require.Equal(t, connection.Open, obj.State.Get(ctx)) + require.Equal(t, connection.Open, obj.Stage.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) require.True(t, obj.Available.Get(ctx)) node.SetState(connection.Open) @@ -144,7 +144,7 @@ func (node *Node) OpenConfirm(t *testing.T, height uint64, proofs ...commitment. ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenConfirm(ctx, proofs, height, node.Name) require.NoError(t, err) - require.Equal(t, connection.Open, obj.State.Get(ctx)) + require.Equal(t, connection.Open, obj.Stage.Get(ctx)) require.Equal(t, node.Connection, obj.GetConnection(ctx)) require.True(t, obj.Available.Get(ctx)) node.SetState(connection.CloseTry) @@ -163,9 +163,9 @@ func (node *Node) Handshake(t *testing.T) { // counterparty.OpenTry node.Counterparty.UpdateClient(t, header) - cliobj := node.CLIObject() + cliobj := node.CLIState() _, pconn := node.QueryValue(t, cliobj.Connection) - _, pstate := node.QueryValue(t, cliobj.State) + _, pstate := node.QueryValue(t, cliobj.Stage) _, pcounterclient := node.QueryValue(t, cliobj.CounterpartyClient) // TODO: implement consensus state checking // _, pclient := node.Query(t, cliobj.Client.ConsensusStateKey) @@ -174,16 +174,16 @@ func (node *Node) Handshake(t *testing.T) { // self.OpenAck node.UpdateClient(t, header) - cliobj = node.Counterparty.CLIObject() + cliobj = node.Counterparty.CLIState() _, pconn = node.Counterparty.QueryValue(t, cliobj.Connection) - _, pstate = node.Counterparty.QueryValue(t, cliobj.State) + _, pstate = node.Counterparty.QueryValue(t, cliobj.Stage) _, pcounterclient = node.Counterparty.QueryValue(t, cliobj.CounterpartyClient) node.OpenAck(t, uint64(header.Height), pconn, pstate, pcounterclient) header = node.Commit() // counterparty.OpenConfirm node.Counterparty.UpdateClient(t, header) - cliobj = node.CLIObject() - _, pstate = node.QueryValue(t, cliobj.State) + cliobj = node.CLIState() + _, pstate = node.QueryValue(t, cliobj.Stage) node.Counterparty.OpenConfirm(t, uint64(header.Height), pstate) } diff --git a/x/ibc/04-channel/cli.go b/x/ibc/04-channel/cli.go index 9dae276d567f..9e5d803d2fea 100644 --- a/x/ibc/04-channel/cli.go +++ b/x/ibc/04-channel/cli.go @@ -7,10 +7,10 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/merkle" ) -func (man Manager) CLIObject(portid, chanid string, connids []string) State { +func (man Manager) CLIState(portid, chanid string, connids []string) State { obj := man.object(portid, chanid) for _, connid := range connids { - obj.Connections = append(obj.Connections, man.connection.Object(connid)) + obj.Connections = append(obj.Connections, man.connection.State(connid)) } return obj } @@ -22,7 +22,7 @@ func (man Manager) CLIQuery(q state.ABCIQuerier, portid, chanid string) (obj Sta return } for _, connid := range channel.ConnectionHops { - obj.Connections = append(obj.Connections, man.connection.Object(connid)) + obj.Connections = append(obj.Connections, man.connection.State(connid)) } return } @@ -70,12 +70,12 @@ func (man Handshaker) CLIQuery(q state.ABCIQuerier, portid, chanid string) (Hand return man.createState(obj), nil } -func (man Handshaker) CLIObject(portid, chanid string, connids []string) HandshakeState { - return man.createState(man.Manager.CLIObject(portid, chanid, connids)) +func (man Handshaker) CLIState(portid, chanid string, connids []string) HandshakeState { + return man.createState(man.Manager.CLIState(portid, chanid, connids)) } -func (obj HandshakeState) StateCLI(q state.ABCIQuerier) (res HandshakeStage, proof merkle.Proof, err error) { - res, tmproof, err := obj.State.Query(q) - proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.State) +func (obj HandshakeState) StageCLI(q state.ABCIQuerier) (res Stage, proof merkle.Proof, err error) { + res, tmproof, err := obj.Stage.Query(q) + proof = merkle.NewProofFromValue(tmproof, obj.prefix(), obj.Stage) return } diff --git a/x/ibc/04-channel/client/cli/query.go b/x/ibc/04-channel/client/cli/query.go index 04e3ca0b19be..aad646c24047 100644 --- a/x/ibc/04-channel/client/cli/query.go +++ b/x/ibc/04-channel/client/cli/query.go @@ -45,7 +45,7 @@ func GetQueryCmd(storeKey string, cdc *codec.Codec) *cobra.Command { return ibcQueryCmd } -func QueryChannel(ctx context.CLIContext, obj channel.State, prove bool) (res utils.JSONObject, err error) { +func QueryChannel(ctx context.CLIContext, obj channel.State, prove bool) (res utils.JSONState, err error) { q := state.NewCLIQuerier(ctx) conn, connp, err := obj.ChannelCLI(q) @@ -68,7 +68,7 @@ func QueryChannel(ctx context.CLIContext, obj channel.State, prove bool) (res ut } if prove { - return utils.NewJSONObject( + return utils.NewJSONState( conn, connp, avail, availp, // kind, kindp, @@ -77,7 +77,7 @@ func QueryChannel(ctx context.CLIContext, obj channel.State, prove bool) (res ut ), nil } - return utils.NewJSONObject( + return utils.NewJSONState( conn, nil, avail, nil, seqsend, nil, @@ -118,7 +118,7 @@ func object(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid str climan := client.NewManager(base) connman := connection.NewManager(base, climan) man := channel.NewManager(base, connman) - return man.CLIObject(portid, chanid, connids) + return man.CLIState(portid, chanid, connids) } */ /* diff --git a/x/ibc/04-channel/client/cli/tx.go b/x/ibc/04-channel/client/cli/tx.go index f85851c11579..7a8dfc792d57 100644 --- a/x/ibc/04-channel/client/cli/tx.go +++ b/x/ibc/04-channel/client/cli/tx.go @@ -34,15 +34,15 @@ const ( FlagFrom2 = "from2" ) -func handshake(cdc *codec.Codec, storeKey string, prefix []byte, portId, chanId, connId string) channel.HandshakeState { +func handshake(cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid, connid string) channel.HandshakeState { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) - clientManager := client.NewManager(base) - connectionManager := connection.NewManager(base, clientManager) - man := channel.NewHandshaker(channel.NewManager(base, connectionManager)) - return man.CLIObject(portId, chanId, []string{connId}) + climan := client.NewManager(base) + connman := connection.NewManager(base, climan) + man := channel.NewHandshaker(channel.NewManager(base, connman)) + return man.CLIState(portid, chanid, []string{connid}) } -func flush(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.HandshakeObject, error) { +func flush(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, portid, chanid string) (channel.HandshakeState, error) { base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) climan := client.NewManager(base) connman := connection.NewManager(base, climan) @@ -50,6 +50,14 @@ func flush(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte return man.CLIQuery(q, portid, chanid) } +// TODO: import from connection/client +func conn(q state.ABCIQuerier, cdc *codec.Codec, storeKey string, prefix []byte, connid string) (connection.State, error) { + base := state.NewMapping(sdk.NewKVStoreKey(storeKey), cdc, prefix) + clientManager := client.NewManager(base) + man := connection.NewManager(base, clientManager) + return man.CLIQuery(q, connid) +} + func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "channel", @@ -58,6 +66,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { cmd.AddCommand( GetCmdHandshake(storeKey, cdc), + GetCmdFlushPackets(storeKey, cdc), ) return cmd @@ -76,19 +85,19 @@ func getHeader(ctx context.CLIContext) (res tendermint.Header, err error) { } height := info.Response.LastBlockHeight - prevHeight := height - 1 + prevheight := height - 1 commit, err := node.Commit(&height) if err != nil { return } - validators, err := node.Validators(&prevHeight) + validators, err := node.Validators(&prevheight) if err != nil { return } - nextValidators, err := node.Validators(&height) + nextvalidators, err := node.Validators(&height) if err != nil { return } @@ -96,7 +105,7 @@ func getHeader(ctx context.CLIContext) (res tendermint.Header, err error) { res = tendermint.Header{ SignedHeader: commit.SignedHeader, ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), - NextValidatorSet: tmtypes.NewValidatorSet(nextValidators.Validators), + NextValidatorSet: tmtypes.NewValidatorSet(nextvalidators.Validators), } return @@ -107,6 +116,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Use: "handshake", Short: "initiate connection handshake between two chains", Args: cobra.ExactArgs(6), + // Args: []string{portid1, chanid1, connid1, portid2, chanid2, connid2} RunE: func(cmd *cobra.Command, args []string) error { txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) ctx1 := context.NewCLIContextWithFrom(viper.GetString(FlagFrom1)). @@ -147,31 +157,29 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } + clientid1 := conn1.Client - clientId1 := conn1.Client conn2, _, err := obj2.OriginConnection().ConnectionCLI(q2) if err != nil { return err } - clientId2 := conn2.Client + clientid2 := conn2.Client // TODO: check state and if not Idle continue existing process - msgInit := channel.MsgOpenInit{ + msginit := channel.MsgOpenInit{ PortID: portid1, ChannelID: chanid1, Channel: chan1, Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgInit}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msginit}) if err != nil { return err } - // Another block has to be passed after msgInit is commited + // Another block has to be passed after msginit is commited // to retrieve the correct proofs - // TODO: Modify this to actually check two blocks being processed, and - // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err := getHeader(ctx1) @@ -179,13 +187,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgUpdate := client.MsgUpdateClient{ - ClientID: clientId2, + msgupdate := client.MsgUpdateClient{ + ClientID: clientid2, Header: header, Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgUpdate}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) fmt.Printf("updated apphash to %X\n", header.AppHash) @@ -196,12 +204,12 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } - _, pstate, err := obj1.StateCLI(q1) + _, pstate, err := obj1.StageCLI(q1) if err != nil { return err } - msgTry := channel.MsgOpenTry{ + msgtry := channel.MsgOpenTry{ PortID: portid2, ChannelID: chanid2, Channel: chan2, @@ -210,15 +218,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgTry}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgtry}) if err != nil { return err } - // Another block has to be passed after msgInit is commited + // Another block has to be passed after msginit is commited // to retrieve the correct proofs - // TODO: Modify this to actually check two blocks being processed, and - // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err = getHeader(ctx2) @@ -226,13 +232,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgUpdate = client.MsgUpdateClient{ - ClientID: clientId1, + msgupdate = client.MsgUpdateClient{ + ClientID: clientid1, Header: header, Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgUpdate}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgupdate}) q2 = state.NewCLIQuerier(ctx2.WithHeight(header.Height - 1)) @@ -240,12 +246,12 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } - _, pstate, err = obj2.StateCLI(q2) + _, pstate, err = obj2.StageCLI(q2) if err != nil { return err } - msgAck := channel.MsgOpenAck{ + msgack := channel.MsgOpenAck{ PortID: portid1, ChannelID: chanid1, Proofs: []commitment.Proof{pchan, pstate}, @@ -253,15 +259,13 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Signer: ctx1.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgAck}) + err = utils.GenerateOrBroadcastMsgs(ctx1, txBldr, []sdk.Msg{msgack}) if err != nil { return err } - // Another block has to be passed after msgInit is commited + // Another block has to be passed after msginit is commited // to retrieve the correct proofs - // TODO: Modify this to actually check two blocks being processed, and - // remove hardcoding this to 8 seconds. time.Sleep(8 * time.Second) header, err = getHeader(ctx1) @@ -269,22 +273,22 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msgUpdate = client.MsgUpdateClient{ - ClientID: clientId2, + msgupdate = client.MsgUpdateClient{ + ClientID: clientid2, Header: header, Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgUpdate}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgupdate}) q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) - _, pstate, err = obj1.StateCLI(q1) + _, pstate, err = obj1.StageCLI(q1) if err != nil { return err } - msgConfirm := channel.MsgOpenConfirm{ + msgconfirm := channel.MsgOpenConfirm{ PortID: portid2, ChannelID: chanid2, Proofs: []commitment.Proof{pstate}, @@ -292,7 +296,7 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { Signer: ctx2.GetFromAddress(), } - err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgConfirm}) + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, []sdk.Msg{msgconfirm}) if err != nil { return err } @@ -301,7 +305,6 @@ func GetCmdHandshake(storeKey string, cdc *codec.Codec) *cobra.Command { }, } - // TODO: Create flag description cmd.Flags().String(FlagNode1, "tcp://localhost:26657", "") cmd.Flags().String(FlagNode2, "tcp://localhost:26657", "") cmd.Flags().String(FlagFrom1, "", "") @@ -357,20 +360,18 @@ func GetCmdFlushPackets(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - conn2, _, err := chan2.ConnectionCLI(q2) + connobj2, err := conn(q2, cdc, storeKey, version.DefaultPrefix(), chan2.ConnectionHops[0]) if err != nil { return err } - client2 := conn2.Client - - portid2, chanid2 := chan1.CounterpartyPort, chan1.Counterparty - - obj2, err := flush(q2, cdc, storeKey, version.DefaultPrefix(), portid2, chanid2) + conn2, _, err := connobj2.ConnectionCLI(q2) if err != nil { return err } + client2 := conn2.Client + seqrecv, _, err := obj2.SeqRecvCLI(q2) if err != nil { return err @@ -393,6 +394,8 @@ func GetCmdFlushPackets(storeKey string, cdc *codec.Codec) *cobra.Command { return err } + q1 = state.NewCLIQuerier(ctx1.WithHeight(header.Height - 1)) + msgupdate := client.MsgUpdateClient{ ClientID: client2, Header: header, @@ -407,8 +410,23 @@ func GetCmdFlushPackets(storeKey string, cdc *codec.Codec) *cobra.Command { return err } - msg := channel.MsgPacket() + msg := channel.MsgPacket{ + packet, + chanid2, + []commitment.Proof{proof}, + uint64(header.Height), + ctx2.GetFromAddress(), + } + + msgs = append(msgs, msg) } + + err = utils.GenerateOrBroadcastMsgs(ctx2, txBldr, msgs) + if err != nil { + return err + } + + return nil }, } diff --git a/x/ibc/04-channel/client/utils/types.go b/x/ibc/04-channel/client/utils/types.go index 4006e7bacebb..579cead225c8 100644 --- a/x/ibc/04-channel/client/utils/types.go +++ b/x/ibc/04-channel/client/utils/types.go @@ -1,11 +1,11 @@ package utils import ( - "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" - "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" + channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -type JSONObject struct { +type JSONState struct { Channel channel.Channel `json:"channel"` ChannelProof commitment.Proof `json:"channel_proof,omitempty"` Available bool `json:"available"` @@ -18,14 +18,14 @@ type JSONObject struct { // KindProof commitment.Proof `json:"kind_proof,omitempty"` } -func NewJSONObject( +func NewJSONState( channel channel.Channel, channelp commitment.Proof, avail bool, availp commitment.Proof, // kind string, kindp commitment.Proof, seqsend uint64, seqsendp commitment.Proof, seqrecv uint64, seqrecvp commitment.Proof, -) JSONObject { - return JSONObject{ +) JSONState { + return JSONState{ Channel: channel, ChannelProof: channelp, Available: avail, @@ -35,8 +35,8 @@ func NewJSONObject( } } -type HandshakeJSONObject struct { - JSONObject `json:"channel"` +type HandshakeJSONState struct { + JSONState `json:"channel"` State byte `json:"state"` StateProof commitment.Proof `json:"state_proof,omitempty"` CounterpartyClient string `json:"counterparty_client"` @@ -45,7 +45,7 @@ type HandshakeJSONObject struct { NextTimeoutProof commitment.Proof `json:"next_timeout_proof,omitempty"` } -func NewHandshakeJSONObject( +func NewHandshakeJSONState( channel channel.Channel, channelp commitment.Proof, avail bool, availp commitment.Proof, // kind string, kindp commitment.Proof, @@ -54,9 +54,9 @@ func NewHandshakeJSONObject( state byte, statep commitment.Proof, timeout uint64, timeoutp commitment.Proof, -) HandshakeJSONObject { - return HandshakeJSONObject{ - JSONObject: NewJSONObject(channel, channelp, avail, availp, seqsend, seqsendp, seqrecv, seqrecvp), +) HandshakeJSONState { + return HandshakeJSONState{ + JSONState: NewJSONState(channel, channelp, avail, availp, seqsend, seqsendp, seqrecv, seqrecvp), State: state, StateProof: statep, NextTimeout: timeout, diff --git a/x/ibc/04-channel/handshake.go b/x/ibc/04-channel/handshake.go index 850d97546e9e..23f34d16eec5 100644 --- a/x/ibc/04-channel/handshake.go +++ b/x/ibc/04-channel/handshake.go @@ -9,10 +9,10 @@ import ( commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) -type HandshakeStage = byte +type Stage = byte const ( - Idle HandshakeStage = iota + Idle Stage = iota Init OpenTry Open @@ -44,7 +44,7 @@ type CounterpartyHandshaker struct { type HandshakeState struct { State - HandshakeStage state.Enum + Stage state.Enum counterParty CounterHandshakeState } @@ -60,9 +60,9 @@ func (man Handshaker) createState(parent State) HandshakeState { prefix := parent.portId + "/channels/" + parent.chanId return HandshakeState{ - State: parent, - HandshakeStage: man.protocol.Value([]byte(prefix + "/state")).Enum(), - counterParty: man.counterParty.createState(parent.counterParty), + State: parent, + Stage: man.protocol.Value([]byte(prefix + "/state")).Enum(), + counterParty: man.counterParty.createState(parent.counterParty), } } @@ -98,7 +98,7 @@ func (man Handshaker) query(ctx sdk.Context, portid, chanid string) (obj Handsha /* func (obj HandshakeState) remove(ctx sdk.Context) { obj.Stage.remove(ctx) - obj.HandshakeStage.Delete(ctx) + obj.Stage.Delete(ctx) obj.counterpartyClient.Delete(ctx) obj.NextTimeout.Delete(ctx) } @@ -129,7 +129,7 @@ func (man Handshaker) OpenInit(ctx sdk.Context, return HandshakeState{}, err } - obj.HandshakeStage.Set(ctx, Init) + obj.Stage.Set(ctx, Init) return obj, nil } @@ -171,7 +171,7 @@ func (man Handshaker) OpenTry(ctx sdk.Context, // assert(get("connections/{desiredIdentifier}") === null) and // set("connections{identifier}", connection) - obj.HandshakeStage.Set(ctx, OpenTry) + obj.Stage.Set(ctx, OpenTry) return } @@ -191,7 +191,7 @@ func (man Handshaker) OpenAck(ctx sdk.Context, return } - if !obj.HandshakeStage.Transit(ctx, Init, Open) { + if !obj.Stage.Transit(ctx, Init, Open) { err = errors.New("ack on non-init connection") return } @@ -238,7 +238,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, return } - if !obj.State.Transit(ctx, OpenTry, Open) { + if !obj.Stage.Transit(ctx, OpenTry, Open) { err = errors.New("confirm on non-try connection") return } @@ -256,7 +256,7 @@ func (man Handshaker) OpenConfirm(ctx sdk.Context, // TODO /* func (obj HandshakeState) CloseInit(ctx sdk.Context, nextTimeout uint64) error { - if !obj.HandshakeStage.Transit(ctx, Open, CloseTry) { + if !obj.Stage.Transit(ctx, Open, CloseTry) { return errors.New("closeinit on non-open connection") } diff --git a/x/ibc/04-channel/manager.go b/x/ibc/04-channel/manager.go index dd0e077c8501..7bd358152303 100644 --- a/x/ibc/04-channel/manager.go +++ b/x/ibc/04-channel/manager.go @@ -34,7 +34,7 @@ func NewManager(protocol state.Mapping, connection connection.Manager) Manager { protocol: protocol.Prefix(LocalRoot()), connection: connection, counterParty: NewCounterpartyManager(protocol.Cdc()), - ports: make(map[string]struct{}), + ports: make(map[string]struct{}), } } @@ -211,7 +211,7 @@ func (man Manager) Send(ctx sdk.Context, chanId string, packet Packet) error { return errors.New("timeout height higher than the latest known") } - obj.Packets.SetRaw(ctx, obj.SeqSend.Increment(ctx), packet.Commitment()) + obj.Packets.SetRaw(ctx, obj.SeqSend.Increment(ctx), packet.Marshal()) ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( @@ -247,8 +247,8 @@ func (man Manager) Receive(ctx sdk.Context, proofs []commitment.Proof, height ui if err != nil { return err } - - if !obj.counterParty.Packets.Value(obj.SeqRecv.Increment(ctx)).Is(ctx, packet) { + + if !obj.counterParty.Packets.Value(obj.SeqRecv.Increment(ctx)).IsRaw(ctx, packet.Marshal()) { return errors.New("verification failed") } diff --git a/x/ibc/04-channel/port.go b/x/ibc/04-channel/port.go index 8547d2819163..033b932e0e7a 100644 --- a/x/ibc/04-channel/port.go +++ b/x/ibc/04-channel/port.go @@ -1,6 +1,8 @@ package channel import ( + "errors" + sdk "github.com/cosmos/cosmos-sdk/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -38,7 +40,8 @@ func (port Port) Send(ctx sdk.Context, chanid string, packet Packet) error { if packet.SenderPort() != port.id { panic("Packet sent on wrong port") } - return port.channel.Send(ctx, port.id, chanid, packet) + + return port.channel.Send(ctx, chanid, packet) } func (port Port) Receive(ctx sdk.Context, proof []commitment.Proof, height uint64, chanid string, packet Packet) error { diff --git a/x/ibc/04-channel/tests/channel_test.go b/x/ibc/04-channel/tests/channel_test.go index 432709585414..1bd8edb8d443 100644 --- a/x/ibc/04-channel/tests/channel_test.go +++ b/x/ibc/04-channel/tests/channel_test.go @@ -1,7 +1,6 @@ package channel import ( - "errors" "testing" "github.com/cosmos/cosmos-sdk/codec" @@ -62,26 +61,10 @@ func (MyPacket) ValidateBasic() sdk.Error { return nil } -func (packet MyPacket) MarshalAmino() (string, error) { - return "mp-" + packet.Message, nil -} - -func (packet *MyPacket) UnmarshalAmino(text string) error { - if text[:3] != "mp-" { - return errors.New("Invalid text for MyPacket") - } - packet.Message = text[3:] - return nil -} - -func (packet MyPacket) MarshalJSON() ([]byte, error) { - res, _ := packet.MarshalAmino() - return []byte("\"" + res + "\""), nil -} - -func (packet *MyPacket) UnmarshalJSON(bz []byte) error { - bz = bz[1 : len(bz)-1] - return packet.UnmarshalAmino(string(bz)) +func (packet MyPacket) Marshal() []byte { + cdc := codec.New() + registerCodec(cdc) + return cdc.MustMarshalBinaryBare(packet) } func TestPacket(t *testing.T) { @@ -96,7 +79,7 @@ func TestPacket(t *testing.T) { header := node.Commit() node.Counterparty.UpdateClient(t, header) - cliobj := node.CLIObject() + cliobj := node.CLIState() _, ppacket := node.QueryValue(t, cliobj.Packets.Value(1)) node.Counterparty.Receive(t, MyPacket{"ping"}, uint64(header.Height), ppacket) } diff --git a/x/ibc/04-channel/tests/types.go b/x/ibc/04-channel/tests/types.go index 5ed8456bcdd4..32221079fb3d 100644 --- a/x/ibc/04-channel/tests/types.go +++ b/x/ibc/04-channel/tests/types.go @@ -29,13 +29,13 @@ type Node struct { func NewNode(self, counter tendermint.MockValidators, cdc *codec.Codec) *Node { res := &Node{ Node: connection.NewNode(self, counter, cdc), - Cdc: cdc, + Cdc: cdc, } res.Counterparty = &Node{ Node: res.Node.Counterparty, Counterparty: res, - Cdc: cdc, + Cdc: cdc, } res.Channel = channel.Channel{ @@ -62,9 +62,9 @@ func (node *Node) Handshaker(t *testing.T, proofs []commitment.Proof) (sdk.Conte return ctx, channel.NewHandshaker(man) } -func (node *Node) CLIObject() channel.HandshakeState { +func (node *Node) CLIState() channel.HandshakeState { man := node.Manager() - return channel.NewHandshaker(man).CLIObject(PortName, node.Name, []string{node.Name}) + return channel.NewHandshaker(man).CLIState(PortName, node.Name, []string{node.Name}) } func base(cdc *codec.Codec, key sdk.StoreKey) (state.Mapping, state.Mapping) { @@ -83,7 +83,7 @@ func (node *Node) OpenInit(t *testing.T, proofs ...commitment.Proof) { ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenInit(ctx, PortName, node.Name, node.Channel) require.NoError(t, err) - require.Equal(t, channel.Init, obj.State.Get(ctx)) + require.Equal(t, channel.Init, obj.Stage.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) require.False(t, obj.Available.Get(ctx)) } @@ -92,7 +92,7 @@ func (node *Node) OpenTry(t *testing.T, height uint64, proofs ...commitment.Proo ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenTry(ctx, proofs, height, PortName, node.Name, node.Channel) require.NoError(t, err) - require.Equal(t, channel.OpenTry, obj.State.Get(ctx)) + require.Equal(t, channel.OpenTry, obj.Stage.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) require.False(t, obj.Available.Get(ctx)) node.SetState(channel.OpenTry) @@ -102,7 +102,7 @@ func (node *Node) OpenAck(t *testing.T, height uint64, proofs ...commitment.Proo ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenAck(ctx, proofs, height, PortName, node.Name) require.NoError(t, err) - require.Equal(t, channel.Open, obj.State.Get(ctx)) + require.Equal(t, channel.Open, obj.Stage.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) require.True(t, obj.Available.Get(ctx)) node.SetState(channel.Open) @@ -112,7 +112,7 @@ func (node *Node) OpenConfirm(t *testing.T, height uint64, proofs ...commitment. ctx, man := node.Handshaker(t, proofs) obj, err := man.OpenConfirm(ctx, proofs, height, PortName, node.Name) require.NoError(t, err) - require.Equal(t, channel.Open, obj.State.Get(ctx)) + require.Equal(t, channel.Open, obj.Stage.Get(ctx)) require.Equal(t, node.Channel, obj.GetChannel(ctx)) require.True(t, obj.Available.Get(ctx)) node.SetState(channel.CloseTry) @@ -127,24 +127,24 @@ func (node *Node) Handshake(t *testing.T) { // counterparty.OpenTry node.Counterparty.UpdateClient(t, header) - cliobj := node.CLIObject() + cliobj := node.CLIState() _, pchan := node.QueryValue(t, cliobj.Channel) - _, pstate := node.QueryValue(t, cliobj.State) + _, pstate := node.QueryValue(t, cliobj.Stage) node.Counterparty.OpenTry(t, uint64(header.Height), pchan, pstate) header = node.Counterparty.Commit() // self.OpenAck node.UpdateClient(t, header) - cliobj = node.Counterparty.CLIObject() + cliobj = node.Counterparty.CLIState() _, pchan = node.Counterparty.QueryValue(t, cliobj.Channel) - _, pstate = node.Counterparty.QueryValue(t, cliobj.State) + _, pstate = node.Counterparty.QueryValue(t, cliobj.Stage) node.OpenAck(t, uint64(header.Height), pchan, pstate) header = node.Commit() // counterparty.OpenConfirm node.Counterparty.UpdateClient(t, header) - cliobj = node.CLIObject() - _, pstate = node.QueryValue(t, cliobj.State) + cliobj = node.CLIState() + _, pstate = node.QueryValue(t, cliobj.Stage) node.Counterparty.OpenConfirm(t, uint64(header.Height), pstate) } @@ -153,7 +153,7 @@ func (node *Node) Send(t *testing.T, packet channel.Packet) { obj, err := man.Query(ctx, PortName, node.Name) require.NoError(t, err) seq := obj.SeqSend.Get(ctx) - err = man.Send(ctx, PortName, node.Name, packet) + err = man.Send(ctx, node.Name, packet) require.NoError(t, err) require.Equal(t, seq+1, obj.SeqSend.Get(ctx)) require.Equal(t, node.Cdc.MustMarshalBinaryBare(packet), obj.PacketCommit(ctx, seq+1)) diff --git a/x/ibc/04-channel/types.go b/x/ibc/04-channel/types.go index 7714dfe5e24c..43688edaa92f 100644 --- a/x/ibc/04-channel/types.go +++ b/x/ibc/04-channel/types.go @@ -24,8 +24,7 @@ type Packet interface { Type() string ValidateBasic() sdk.Error Timeout() uint64 - MarshalAmino() (string, error) // Should exclude PortID/ChannelID info - MarshalJSON() ([]byte, error) // Should exclude PortID/ChannelID info + Marshal() []byte // Should exclude PortID/ChannelID info } type Channel struct { diff --git a/x/ibc/mock/client/cli/tx.go b/x/ibc/mock/client/cli/tx.go deleted file mode 100644 index 4db71904ba3d..000000000000 --- a/x/ibc/mock/client/cli/tx.go +++ /dev/null @@ -1,53 +0,0 @@ -package cli - -import ( - "strconv" - - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" -) - -func GetTxCmd(cdc *codec.Codec) *cobra.Command { - txCmd := &cobra.Command{ - Use: "ibctypes", - Short: "IBC types module transaction subcommands", - RunE: client.ValidateCmd, - } - txCmd.AddCommand( - SequenceTxCmd(cdc), - ) - - return txCmd -} - -func SequenceTxCmd(cdc *codec.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "sequence [channel-id] [sequence]", - Short: "Send SequencePacket", - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) - ctx := context.NewCLIContext().WithCodec(cdc) - - chanid := args[0] - seq, err := strconv.ParseUint(args[1], 10, 64) - if err != nil { - return err - } - - msg := types.NewMsgSequence(ctx.GetFromAddress(), chanid, seq) - return utils.GenerateOrBroadcastMsgs(ctx, txBldr, []sdk.Msg{msg}) - }, - } - - cmd = client.PostCommands(cmd)[0] - - return cmd -} diff --git a/x/ibc/mock/codec.go b/x/ibc/mock/codec.go deleted file mode 100644 index 20812bf738e8..000000000000 --- a/x/ibc/mock/codec.go +++ /dev/null @@ -1,10 +0,0 @@ -package mock - -import ( - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" -) - -func RegisterCodec(cdc *codec.Codec) { - cdc.RegisterConcrete(types.PacketSequence{}, "ibcmock/types.PacketSequence", nil) -} diff --git a/x/ibc/mock/client/cli/query.go b/x/ibc/mock/recv/client/cli/query.go similarity index 86% rename from x/ibc/mock/client/cli/query.go rename to x/ibc/mock/recv/client/cli/query.go index a3817350902a..627027ddea54 100644 --- a/x/ibc/mock/client/cli/query.go +++ b/x/ibc/mock/recv/client/cli/query.go @@ -14,8 +14,8 @@ import ( func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { queryCmd := &cobra.Command{ - Use: "ibcmock", - Short: "Querying commands for the ibcmock module", + Use: "ibcmockrecv", + Short: "Querying commands for the ibcmockrecv module", RunE: client.ValidateCmd, } @@ -34,7 +34,7 @@ func GetCmdQuerySequence(storeName string, cdc *codec.Codec) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { ctx := context.NewCLIContext().WithCodec(cdc) - val, _, err := ctx.QueryStore(types.SequenceKey, storeName) + val, _, err := ctx.QueryStore(types.SequenceKey(args[0]), storeName) if err != nil { return err } diff --git a/x/ibc/mock/handler.go b/x/ibc/mock/recv/handler.go similarity index 71% rename from x/ibc/mock/handler.go rename to x/ibc/mock/recv/handler.go index 90a459fd3c59..e095d1ad6987 100644 --- a/x/ibc/mock/handler.go +++ b/x/ibc/mock/recv/handler.go @@ -10,8 +10,6 @@ import ( func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { - case MsgSequence: - return handleMsgSequence(ctx, k, msg) case ibc.MsgPacket: switch packet := msg.Packet.(type) { case types.PacketSequence: @@ -25,15 +23,8 @@ func NewHandler(k Keeper) sdk.Handler { } } -func handleMsgSequence(ctx sdk.Context, k Keeper, msg MsgSequence) (res sdk.Result) { - err := k.ibcPort.SendPacket(ctx, msg.ChannelID, types.PacketSequence{msg.Sequence}) - if err != nil { - - } -} - func handleMyPacket(ctx sdk.Context, k Keeper, packet types.PacketSequence, chanid string) (res sdk.Result) { - err := k.CheckAndSetSequence(ctx, chanid, packet.Sequence) + err := k.UpdateSequence(ctx, chanid, packet.Sequence) if err != nil { res.Log = "Invalid sequence" // should not return error, set only log } diff --git a/x/ibc/mock/keeper.go b/x/ibc/mock/recv/keeper.go similarity index 67% rename from x/ibc/mock/keeper.go rename to x/ibc/mock/recv/keeper.go index 953dc889cf32..7fcb5ad544da 100644 --- a/x/ibc/mock/keeper.go +++ b/x/ibc/mock/recv/keeper.go @@ -1,8 +1,6 @@ package mock import ( - "errors" - "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc" @@ -25,8 +23,8 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, port ibc.Port) Keeper { func (k Keeper) GetSequence(ctx sdk.Context, chanid string) (res uint64) { store := ctx.KVStore(k.key) - if store.Has(types.SequenceKey) { - k.cdc.MustUnmarshalBinaryBare(store.Get(types.SequenceKey), &res) + if store.Has(types.SequenceKey(chanid)) { + k.cdc.MustUnmarshalBinaryBare(store.Get(types.SequenceKey(chanid)), &res) } else { res = 0 } @@ -36,12 +34,13 @@ func (k Keeper) GetSequence(ctx sdk.Context, chanid string) (res uint64) { func (k Keeper) SetSequence(ctx sdk.Context, chanid string, seq uint64) { store := ctx.KVStore(k.key) - store.Set(types.SequenceKey, k.cdc.MustMarshalBinaryBare(seq)) + store.Set(types.SequenceKey(chanid), k.cdc.MustMarshalBinaryBare(seq)) } -func (k Keeper) CheckAndSetSequence(ctx sdk.Context, chanid string, seq uint64) error { +func (k Keeper) UpdateSequence(ctx sdk.Context, chanid string, seq uint64) sdk.Error { if k.GetSequence(ctx, chanid)+1 != seq { - return errors.New("fjidow;af") + // TODO: proper error + return sdk.NewError(sdk.CodespaceType("ibcmock"), 800, "") } k.SetSequence(ctx, chanid, seq) return nil diff --git a/x/ibc/mock/recv/module.go b/x/ibc/mock/recv/module.go new file mode 100644 index 000000000000..9e142a855baf --- /dev/null +++ b/x/ibc/mock/recv/module.go @@ -0,0 +1,103 @@ +package mock + +import ( + "encoding/json" + + "github.com/gorilla/mux" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/recv/client/cli" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" +) + +const ( + ModuleName = "ibcmockrecv" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +type AppModuleBasic struct{} + +var _ module.AppModuleBasic = AppModuleBasic{} + +func (AppModuleBasic) Name() string { + return ModuleName +} + +func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { + types.RegisterCodec(cdc) +} + +func (AppModuleBasic) DefaultGenesis() json.RawMessage { + return nil +} + +func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { + return nil +} + +func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) { + //noop +} + +func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { + return nil +} + +func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { + return cli.GetQueryCmd(ModuleName, cdc) +} + +type AppModule struct { + AppModuleBasic + k Keeper +} + +func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + +} + +func (AppModule) Name() string { + return ModuleName +} + +func (AppModule) Route() string { + return ModuleName +} + +func (am AppModule) NewHandler() sdk.Handler { + return NewHandler(am.k) +} + +func (am AppModule) QuerierRoute() string { + return ModuleName +} + +func (am AppModule) NewQuerierHandler() sdk.Querier { + return nil +} + +func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage { + return nil +} + +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { + +} + +func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} diff --git a/x/ibc/mock/send/handler.go b/x/ibc/mock/send/handler.go new file mode 100644 index 000000000000..e78e97714675 --- /dev/null +++ b/x/ibc/mock/send/handler.go @@ -0,0 +1,26 @@ +package mock + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" +) + +func NewHandler(k Keeper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + switch msg := msg.(type) { + case types.MsgSequence: + return handleMsgSequence(ctx, k, msg) + default: + return sdk.ErrUnknownRequest("21345").Result() + } + } +} + +func handleMsgSequence(ctx sdk.Context, k Keeper, msg types.MsgSequence) (res sdk.Result) { + err := k.UpdateSequence(ctx, msg.ChannelID, msg.Sequence) + if err != nil { + return err.Result() + } + return res +} diff --git a/x/ibc/mock/send/keeper.go b/x/ibc/mock/send/keeper.go new file mode 100644 index 000000000000..150e1a5f7ee5 --- /dev/null +++ b/x/ibc/mock/send/keeper.go @@ -0,0 +1,49 @@ +package mock + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" +) + +type Keeper struct { + cdc *codec.Codec + key sdk.StoreKey + port ibc.Port +} + +func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, port ibc.Port) Keeper { + return Keeper{ + cdc: cdc, + key: key, + port: port, + } +} + +func (k Keeper) UpdateSequence(ctx sdk.Context, chanid string, seq uint64) sdk.Error { + stored := k.GetSequence(ctx, chanid) + if seq != stored+1 { + // TODO: use proper error + return sdk.NewError(sdk.CodespaceType("ibcmocksend"), 600, "invalid sequence") + } + k.SetSequence(ctx, chanid, seq) + k.port.Send(ctx, chanid, types.PacketSequence{seq}) + return nil +} + +func (k Keeper) GetSequence(ctx sdk.Context, chanid string) (res uint64) { + store := ctx.KVStore(k.key) + if store.Has(types.SequenceKey(chanid)) { + k.cdc.MustUnmarshalBinaryBare(store.Get(types.SequenceKey(chanid)), &res) + } else { + res = 0 + } + + return +} + +func (k Keeper) SetSequence(ctx sdk.Context, chanid string, seq uint64) { + store := ctx.KVStore(k.key) + store.Set(types.SequenceKey(chanid), k.cdc.MustMarshalBinaryBare(seq)) +} diff --git a/x/ibc/mock/module.go b/x/ibc/mock/send/module.go similarity index 92% rename from x/ibc/mock/module.go rename to x/ibc/mock/send/module.go index 79aab119570d..19309e13bd69 100644 --- a/x/ibc/mock/module.go +++ b/x/ibc/mock/send/module.go @@ -12,11 +12,12 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - "github.com/cosmos/cosmos-sdk/x/ibc/mock/client/cli" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/send/client/cli" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" ) const ( - ModuleName = "ibcmock" + ModuleName = "ibcmocksend" ) var ( @@ -33,7 +34,7 @@ func (AppModuleBasic) Name() string { } func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { - RegisterCodec(cdc) + types.RegisterCodec(cdc) } func (AppModuleBasic) DefaultGenesis() json.RawMessage { diff --git a/x/ibc/mock/types/codec.go b/x/ibc/mock/types/codec.go new file mode 100644 index 000000000000..2c1dfe7b2a65 --- /dev/null +++ b/x/ibc/mock/types/codec.go @@ -0,0 +1,9 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +func RegisterCodec(cdc *codec.Codec) { + cdc.RegisterConcrete(PacketSequence{}, "ibcmock/PacketSequence", nil) +} diff --git a/x/ibc/mock/types/keys.go b/x/ibc/mock/types/keys.go index 2e69fd34755e..3134a5ad511a 100644 --- a/x/ibc/mock/types/keys.go +++ b/x/ibc/mock/types/keys.go @@ -1,3 +1,5 @@ package types -var SequenceKey = []byte("sequence") +func SequenceKey(chanid string) []byte { + return []byte("sequence/" + chanid) +} diff --git a/x/ibc/mock/types/packets.go b/x/ibc/mock/types/packets.go index 914454e9e5e9..11fdfc88c370 100644 --- a/x/ibc/mock/types/packets.go +++ b/x/ibc/mock/types/packets.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc" ) @@ -29,6 +30,12 @@ func (packet *PacketSequence) UnmarshalAmino(text string) (err error) { return } +func (packet PacketSequence) Marshal() []byte { + cdc := codec.New() + RegisterCodec(cdc) + return cdc.MustMarshalBinaryBare(packet) +} + func (packet PacketSequence) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf("\"sequence-packet-%d\"", packet.Sequence)), nil } From 45dcdb324958d81dd92c5a9d17f3b16ba5859eb1 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 27 Sep 2019 19:02:25 -0700 Subject: [PATCH 177/182] add cli for mocksend --- x/ibc/mock/send/client/cli/query.go | 53 +++++++++++++++++++++++++++++ x/ibc/mock/send/client/cli/tx.go | 53 +++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 x/ibc/mock/send/client/cli/query.go create mode 100644 x/ibc/mock/send/client/cli/tx.go diff --git a/x/ibc/mock/send/client/cli/query.go b/x/ibc/mock/send/client/cli/query.go new file mode 100644 index 000000000000..2a68794f8587 --- /dev/null +++ b/x/ibc/mock/send/client/cli/query.go @@ -0,0 +1,53 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" +) + +func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { + queryCmd := &cobra.Command{ + Use: "ibcmocksend", + Short: "Querying commands for the ibcmocksend module", + RunE: client.ValidateCmd, + } + + queryCmd.AddCommand(client.GetCommands( + GetCmdQuerySequence(queryRoute, cdc), + )...) + + return queryCmd +} + +func GetCmdQuerySequence(storeName string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "sequence [channel-id]", + Short: "Query the current sequence for the channel", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.NewCLIContext().WithCodec(cdc) + + val, _, err := ctx.QueryStore(types.SequenceKey(args[0]), storeName) + if err != nil { + return err + } + + var res uint64 + if val == nil { + res = 0 + } else { + cdc.MustUnmarshalBinaryBare(val, &res) + } + fmt.Println(res) + + return nil + }, + } +} diff --git a/x/ibc/mock/send/client/cli/tx.go b/x/ibc/mock/send/client/cli/tx.go new file mode 100644 index 000000000000..f59a2c67906a --- /dev/null +++ b/x/ibc/mock/send/client/cli/tx.go @@ -0,0 +1,53 @@ +package cli + +import ( + "strconv" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + "github.com/cosmos/cosmos-sdk/x/ibc/mock/types" +) + +func GetTxCmd(cdc *codec.Codec) *cobra.Command { + txCmd := &cobra.Command{ + Use: "ibcmocksend", + Short: "IBC mocksend module transaction subcommands", + RunE: client.ValidateCmd, + } + txCmd.AddCommand( + SequenceTxCmd(cdc), + ) + + return txCmd +} + +func SequenceTxCmd(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "sequence [channel-id] [sequence]", + Short: "Send SequencePacket", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) + ctx := context.NewCLIContext().WithCodec(cdc) + + chanid := args[0] + seq, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + msg := types.NewMsgSequence(ctx.GetFromAddress(), chanid, seq) + return utils.GenerateOrBroadcastMsgs(ctx, txBldr, []sdk.Msg{msg}) + }, + } + + cmd = client.PostCommands(cmd)[0] + + return cmd +} From 56be11e4ed0352b1e1ab55d8aef5bb9478f1ece2 Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 28 Sep 2019 10:38:13 -0700 Subject: [PATCH 178/182] fix handler --- x/ibc/mock/send/handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/mock/send/handler.go b/x/ibc/mock/send/handler.go index e78e97714675..dfc92719bc61 100644 --- a/x/ibc/mock/send/handler.go +++ b/x/ibc/mock/send/handler.go @@ -1,4 +1,4 @@ -package mock +package mocksend import ( sdk "github.com/cosmos/cosmos-sdk/types" From 10bf523fd7e0015d836a73bfe014ada9ab551201 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 30 Sep 2019 21:28:00 -0700 Subject: [PATCH 179/182] rename mock packages --- x/ibc/mock/recv/handler.go | 2 +- x/ibc/mock/recv/keeper.go | 2 +- x/ibc/mock/recv/module.go | 2 +- x/ibc/mock/send/keeper.go | 2 +- x/ibc/mock/send/module.go | 2 +- x/ibc/mock/types/packets.go | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/x/ibc/mock/recv/handler.go b/x/ibc/mock/recv/handler.go index e095d1ad6987..d992f799fcb1 100644 --- a/x/ibc/mock/recv/handler.go +++ b/x/ibc/mock/recv/handler.go @@ -1,4 +1,4 @@ -package mock +package mockrecv import ( sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/x/ibc/mock/recv/keeper.go b/x/ibc/mock/recv/keeper.go index 7fcb5ad544da..99ce5d2e9746 100644 --- a/x/ibc/mock/recv/keeper.go +++ b/x/ibc/mock/recv/keeper.go @@ -1,4 +1,4 @@ -package mock +package mockrecv import ( "github.com/cosmos/cosmos-sdk/codec" diff --git a/x/ibc/mock/recv/module.go b/x/ibc/mock/recv/module.go index 9e142a855baf..e4dcb5f7d2d6 100644 --- a/x/ibc/mock/recv/module.go +++ b/x/ibc/mock/recv/module.go @@ -1,4 +1,4 @@ -package mock +package mockrecv import ( "encoding/json" diff --git a/x/ibc/mock/send/keeper.go b/x/ibc/mock/send/keeper.go index 150e1a5f7ee5..ce88988093e3 100644 --- a/x/ibc/mock/send/keeper.go +++ b/x/ibc/mock/send/keeper.go @@ -1,4 +1,4 @@ -package mock +package mocksend import ( "github.com/cosmos/cosmos-sdk/codec" diff --git a/x/ibc/mock/send/module.go b/x/ibc/mock/send/module.go index 19309e13bd69..1749d57ed1d9 100644 --- a/x/ibc/mock/send/module.go +++ b/x/ibc/mock/send/module.go @@ -1,4 +1,4 @@ -package mock +package mocksend import ( "encoding/json" diff --git a/x/ibc/mock/types/packets.go b/x/ibc/mock/types/packets.go index 11fdfc88c370..745adef2188c 100644 --- a/x/ibc/mock/types/packets.go +++ b/x/ibc/mock/types/packets.go @@ -50,11 +50,11 @@ func (packet *PacketSequence) UnmarshalJSON(bz []byte) (err error) { } func (PacketSequence) SenderPort() string { - return "ibcmock" + return "ibcmocksend" } func (PacketSequence) ReceiverPort() string { - return "ibcmock" + return "ibcmockrecv" } func (PacketSequence) String() string { From fea2ba628ccd4a374cf7a33b0a10a5099f19bfc6 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 30 Sep 2019 22:47:05 -0700 Subject: [PATCH 180/182] fix interface for gaia --- x/ibc/keeper.go | 4 ++++ x/ibc/mock/recv/module.go | 8 ++++++++ x/ibc/mock/send/module.go | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/x/ibc/keeper.go b/x/ibc/keeper.go index dbf8a4b4766f..df1d2bde063e 100644 --- a/x/ibc/keeper.go +++ b/x/ibc/keeper.go @@ -27,3 +27,7 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey) Keeper { channel: channel.NewHandshaker(chanman), } } + +func (k Keeper) Port(id string) channel.Port { + return k.channel.Port(id) +} diff --git a/x/ibc/mock/recv/module.go b/x/ibc/mock/recv/module.go index e4dcb5f7d2d6..89c8ce099a0a 100644 --- a/x/ibc/mock/recv/module.go +++ b/x/ibc/mock/recv/module.go @@ -62,6 +62,14 @@ type AppModule struct { k Keeper } +func NewAppModule(k Keeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + + k: k, + } +} + func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { } diff --git a/x/ibc/mock/send/module.go b/x/ibc/mock/send/module.go index 1749d57ed1d9..8e45118fe495 100644 --- a/x/ibc/mock/send/module.go +++ b/x/ibc/mock/send/module.go @@ -62,6 +62,14 @@ type AppModule struct { k Keeper } +func NewAppModule(k Keeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + + k: k, + } +} + func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { } From 5cd8c4032468792cc9e88c8bdcbfcee4b90b5de7 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 1 Oct 2019 13:47:38 +0200 Subject: [PATCH 181/182] fixes --- x/ibc/23-commitment/merkle/merkle.go | 8 ++++++-- x/ibc/23-commitment/merkle/merkle_test.go | 2 +- x/ibc/23-commitment/merkle/utils.go | 4 ---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index 9787412fee99..50c47b937f10 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -51,8 +51,8 @@ type Prefix struct { KeyPrefix []byte `json:"key_prefix"` } -// NewPath() constructs new Prefix -func NewPath(keypath [][]byte, keyprefix []byte) Prefix { +// NewPrefix constructs new Prefix instance +func NewPrefix(keypath [][]byte, keyprefix []byte) Prefix { return Prefix{ KeyPath: keypath, KeyPrefix: keyprefix, @@ -64,6 +64,10 @@ func (Prefix) CommitmentKind() string { return merkleKind } +func (path Prefix) Key(key []byte) []byte { + return join(path.KeyPrefix, key) +} + var _ commitment.Proof = Proof{} // Proof is Merkle proof with the key information. diff --git a/x/ibc/23-commitment/merkle/merkle_test.go b/x/ibc/23-commitment/merkle/merkle_test.go index c652289caf34..fd550d43da53 100644 --- a/x/ibc/23-commitment/merkle/merkle_test.go +++ b/x/ibc/23-commitment/merkle/merkle_test.go @@ -45,7 +45,7 @@ func TestStore(t *testing.T) { storeName := k.Name() prefix := []byte{0x01, 0x03, 0x05, 0xAA, 0xBB} mapp := state.NewMapping(k, cdc, prefix) - path := NewPath([][]byte{[]byte(storeName)}, prefix) + path := NewPrefix([][]byte{[]byte(storeName)}, prefix) m := make(map[string][]byte) kvpn := 10 diff --git a/x/ibc/23-commitment/merkle/utils.go b/x/ibc/23-commitment/merkle/utils.go index 5a15a72af62a..ec933af09748 100644 --- a/x/ibc/23-commitment/merkle/utils.go +++ b/x/ibc/23-commitment/merkle/utils.go @@ -32,10 +32,6 @@ func RequestQueryMultiStore(storeName string, prefix []byte, key []byte) abci.Re } } -func (path Path) Key(key []byte) []byte { - return join(path.KeyPrefix, key) -} - func join(a, b []byte) (res []byte) { res = make([]byte, len(a)+len(b)) copy(res, a) From c717b1237edc05b478a28ba5887d39702a1f22bc Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 1 Oct 2019 13:48:45 +0200 Subject: [PATCH 182/182] rename --- x/ibc/23-commitment/merkle/merkle.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/ibc/23-commitment/merkle/merkle.go b/x/ibc/23-commitment/merkle/merkle.go index 50c47b937f10..f310ac948151 100644 --- a/x/ibc/23-commitment/merkle/merkle.go +++ b/x/ibc/23-commitment/merkle/merkle.go @@ -64,8 +64,8 @@ func (Prefix) CommitmentKind() string { return merkleKind } -func (path Prefix) Key(key []byte) []byte { - return join(path.KeyPrefix, key) +func (prefix Prefix) Key(key []byte) []byte { + return join(prefix.KeyPrefix, key) } var _ commitment.Proof = Proof{}