Skip to content

Commit

Permalink
feat: instantiate chan paths on path processors, keep connection ID a…
Browse files Browse the repository at this point in the history
…round, reverse dst hop path ends
  • Loading branch information
Giuseppe Valente committed Apr 19, 2023
1 parent 128ede3 commit 0f7b19c
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 56 deletions.
2 changes: 1 addition & 1 deletion relayer/chains/cosmos/message_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cosmos
import (
"context"
"encoding/hex"

conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types"
chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
"github.com/cosmos/relayer/v2/relayer/processor"
Expand Down Expand Up @@ -82,6 +81,7 @@ func (ccp *CosmosChainProcessor) handleChannelMessage(eventType string, ci provi
Open: false,
ConnectionHops: ci.ConnectionHops(),
})

}
} else {
switch eventType {
Expand Down
5 changes: 2 additions & 3 deletions relayer/chains/cosmos/multihop.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types"
"github.com/cosmos/ibc-go/v7/modules/core/exported"
"github.com/cosmos/ibc-go/v7/modules/core/multihop"
"github.com/cosmos/relayer/v2/relayer/provider"
)

var _ multihop.Endpoint = (*endpoint)(nil)
Expand Down Expand Up @@ -148,9 +147,9 @@ func (e endpoint) Counterparty() multihop.Endpoint {
return e.counterparty
}

func newEndpoint(provider provider.ChainProvider, clientID, connectionID string) multihop.Endpoint {
func (cc *CosmosProvider) newEndpoint(clientID, connectionID string) multihop.Endpoint {
return &endpoint{
provider: provider.(*CosmosProvider),
provider: cc,
clientID: clientID,
connectionID: connectionID,
}
Expand Down
16 changes: 12 additions & 4 deletions relayer/chains/cosmos/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (pc CosmosProviderConfig) NewProvider(log *zap.Logger, homepath string, deb
// TODO: this is a bit of a hack, we should probably have a better way to inject modules
Cdc: MakeCodec(pc.Modules, pc.ExtraCodecs),

chanPaths: map[string]*multihop.ChanPath{},
chanPaths: map[string]multihop.ChanPath{},
}

return cp, nil
Expand Down Expand Up @@ -126,14 +126,22 @@ type CosmosProvider struct {
cometLegacyEncoding bool

// chanPaths tracks paths for multi-hop proofs
chanPaths map[string]*multihop.ChanPath
chanPaths map[string]multihop.ChanPath
}

func (cc *CosmosProvider) AddChanPath(connectionHops []string, chanPath *multihop.ChanPath) {
func (cc *CosmosProvider) MultihopEndpoint(clientID, connectionID string) multihop.Endpoint {
return cc.newEndpoint(clientID, connectionID)
}

func (cc *CosmosProvider) SetMultihopCounterparty(ep, counterparty multihop.Endpoint) {
ep.(*endpoint).counterparty = counterparty.(*endpoint)
}

func (cc *CosmosProvider) AddChanPath(connectionHops []string, chanPath multihop.ChanPath) {
cc.chanPaths[chantypes.FormatConnectionID(connectionHops)] = chanPath
}

func (cc *CosmosProvider) GetChanPath(connectionHops []string) *multihop.ChanPath {
func (cc *CosmosProvider) GetChanPath(connectionHops []string) multihop.ChanPath {
return cc.chanPaths[chantypes.FormatConnectionID(connectionHops)]
}

Expand Down
37 changes: 22 additions & 15 deletions relayer/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,30 @@ import (
"go.uber.org/zap"
)

func newPathEnd(pathName, chainID, clientID string) processor.PathEnd {
return processor.NewPathEnd(pathName, chainID, clientID, "", []processor.ChainChannelKey{})
func newPathEnd(pathName, chainID, clientID, connectionID string) processor.PathEnd {
return processor.NewPathEnd(pathName, chainID, clientID, connectionID, "", []processor.ChainChannelKey{})
}

func newRelayPathEnds(pathName string, hops []*Chain) ([]*processor.PathEnd, []*processor.PathEnd) {
relayPathEndsSrcToDst := make([]*processor.PathEnd, len(hops))
relayPathEndsDstToSrc := make([]*processor.PathEnd, len(hops))
// RelayPathEnds are set in user friendly order so they're just listed as they appear left to right without
// acounting for directionality. So for a 1 hop case they would look like this:
// A -> B (BA, BC) -> C
// Here we want to account for directionality left to right so we want to return:
// BC, BA
// Hence the index reversal in the call to newPathEnd().
for i, hop := range hops {
pathEnd1 := newPathEnd(pathName, hop.RelayPathEnds[1].ChainID, hop.RelayPathEnds[1].ClientID)
pathEnd2 := newPathEnd(pathName, hop.RelayPathEnds[0].ChainID, hop.RelayPathEnds[0].ClientID)
relayPath1 := hop.RelayPathEnds[1]
pathEnd1 := newPathEnd(pathName, relayPath1.ChainID, relayPath1.ClientID, relayPath1.ConnectionID)
relayPathEndsSrcToDst[i] = &pathEnd1
relayPathEndsDstToSrc[i] = &pathEnd2
}
var relayPathEndsDstToSrc []*processor.PathEnd
// TODO: is it ok to reverse here?
for i := len(hops) - 1; i >= 0; i-- {
hop := hops[i]
relayPath2 := hop.RelayPathEnds[0]
pathEnd2 := newPathEnd(pathName, relayPath2.ChainID, relayPath2.ClientID, relayPath2.ConnectionID)
relayPathEndsDstToSrc = append(relayPathEndsDstToSrc, &pathEnd2)
}
return relayPathEndsSrcToDst, relayPathEndsDstToSrc
}
Expand Down Expand Up @@ -74,11 +80,17 @@ func (c *Chain) CreateOpenChannels(
ctx, cancel := context.WithTimeout(ctx, processorTimeout)
defer cancel()

hopConnectionIDs := make([]string, len(hops)+1)
hopConnectionIDs[0] = c.PathEnd.ConnectionID
for i, hop := range hops {
hopConnectionIDs[i+1] = hop.RelayPathEnds[1].ConnectionID
}

relayPathEndsSrcToDst, relayPathEndsDstToSrc := newRelayPathEnds(pathName, hops)
pp := processor.NewPathProcessor(
c.log,
newPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID),
newPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID),
newPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, c.PathEnd.ConnectionID),
newPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, dst.PathEnd.ConnectionID),
relayPathEndsSrcToDst,
relayPathEndsDstToSrc,
nil,
Expand All @@ -93,11 +105,6 @@ func (c *Chain) CreateOpenChannels(
zap.String("dst_chain_id", dst.PathEnd.ChainID),
zap.String("dst_port_id", dstPortID),
)
hopConnectionIDs := make([]string, len(hops)+1)
hopConnectionIDs[0] = c.PathEnd.ConnectionID
for i, hop := range hops {
hopConnectionIDs[i+1] = hop.RelayPathEnds[1].ConnectionID
}
connectionHops := chantypes.FormatConnectionID(hopConnectionIDs)
openInitMsg := &processor.ChannelMessage{
ChainID: c.PathEnd.ChainID,
Expand Down Expand Up @@ -170,8 +177,8 @@ func (c *Chain) CloseChannel(
WithChainProcessors(chainProcessors...).
WithPathProcessors(processor.NewPathProcessor(
c.log,
newPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID),
newPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID),
newPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, c.PathEnd.ConnectionID),
newPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, dst.PathEnd.ConnectionID),
relayPathEndsSrcToDst,
relayPathEndsDstToSrc,
nil,
Expand Down
5 changes: 2 additions & 3 deletions relayer/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@ func (c *Chain) CreateOpenConnections(
ctx, cancel := context.WithTimeout(ctx, processorTimeout)
defer cancel()

// TODO: account for hops
pp := processor.NewPathProcessor(
c.log,
processor.NewPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, "", []processor.ChainChannelKey{}),
processor.NewPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, "", []processor.ChainChannelKey{}),
processor.NewPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, "", "", []processor.ChainChannelKey{}),
processor.NewPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, "", "", []processor.ChainChannelKey{}),
nil,
nil,
nil,
Expand Down
1 change: 0 additions & 1 deletion relayer/processor/message_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ func (mp *messageProcessor) shouldUpdateClientNow(ctx context.Context, src, dst
func (mp *messageProcessor) assembleMessages(ctx context.Context, messages pathEndMessages, src, dst *pathEndRuntime) {
var wg sync.WaitGroup

// TODO: instantiate ChanPath on chain providers before getting here
mp.connMsgs = make([]connectionMessageToTrack, len(messages.connectionMessages))
for i, msg := range messages.connectionMessages {
wg.Add(1)
Expand Down
15 changes: 9 additions & 6 deletions relayer/processor/path_end.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ type PathEnd struct {
ChainID string
ClientID string
// ConnectionIDs are tracked by pathEndRuntime in PathProcessor for known connections on this client
// TODO: we are tracking connection IDs here to create multihop channel paths, check that it isn't a problem
ConnectionID string

// Can be either "allowlist" or "denylist"
Rule string
Expand All @@ -20,13 +22,14 @@ type ChainChannelKey struct {
}

// NewPathEnd constructs a PathEnd, validating initial parameters.
func NewPathEnd(pathName string, chainID string, clientID string, rule string, filterList []ChainChannelKey) PathEnd {
func NewPathEnd(pathName, chainID, clientID, connectionID, rule string, filterList []ChainChannelKey) PathEnd {
return PathEnd{
PathName: pathName,
ChainID: chainID,
ClientID: clientID,
Rule: rule,
FilterList: filterList,
PathName: pathName,
ChainID: chainID,
ClientID: clientID,
ConnectionID: connectionID,
Rule: rule,
FilterList: filterList,
}
}

Expand Down
54 changes: 54 additions & 0 deletions relayer/processor/path_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package processor
import (
"context"
"fmt"
"github.com/cosmos/ibc-go/v7/modules/core/multihop"
"reflect"
"time"

Expand Down Expand Up @@ -428,8 +429,61 @@ func (pp *PathProcessor) processAvailableSignals(ctx context.Context, cancel fun
return false
}

func (pp *PathProcessor) setChanPaths() error {
if len(pp.hopsPathEnd1to2) == 0 {
return nil
}
paths1 := make([]*multihop.Path, 0, len(pp.hopsPathEnd1to2))
// We start with src and proceed with the corresponding path ends
hopA := pp.pathEnd1
connectionHops1 := make([]string, 0, len(pp.hopsPathEnd1to2))
for i, hopB := range append(pp.hopsPathEnd2to1, pp.pathEnd2) {
connectionHops1[i] = hopB.info.ConnectionID
endpointA := hopA.chainProvider.MultihopEndpoint(hopA.info.ClientID, hopA.info.ConnectionID)
endpointB := hopB.chainProvider.MultihopEndpoint(hopB.info.ClientID, hopB.info.ConnectionID)
hopA.chainProvider.SetMultihopCounterparty(endpointA, endpointB)
hopB.chainProvider.SetMultihopCounterparty(endpointB, endpointA)
paths1 = append(paths1, &multihop.Path{
EndpointA: endpointA,
EndpointB: endpointB,
})
if i < len(pp.hopsPathEnd1to2) {
hopA = pp.hopsPathEnd1to2[i]
}
}
paths2 := make([]*multihop.Path, 0, len(pp.hopsPathEnd2to1))
connectionHops2 := make([]string, 0, len(pp.hopsPathEnd2to1))
// We start with dst and go in reverse order (path ends in hopsPathEnd2to1 are already reversed)
for i, hopA := range append([]*pathEndRuntime{pp.pathEnd2}, pp.hopsPathEnd2to1...) {
connectionHops2[i] = hopA.info.ConnectionID
endpointA := hopA.chainProvider.MultihopEndpoint(hopA.info.ClientID, hopA.info.ConnectionID)
hopB := pp.pathEnd1
if i < len(pp.hopsPathEnd1to2) {
hopB = pp.hopsPathEnd1to2[i]
}
endpointB := hopB.chainProvider.MultihopEndpoint(hopB.info.ClientID, hopB.info.ConnectionID)
hopA.chainProvider.SetMultihopCounterparty(endpointA, endpointB)
hopB.chainProvider.SetMultihopCounterparty(endpointB, endpointA)
paths2 = append(paths2, &multihop.Path{
EndpointA: endpointA,
EndpointB: endpointB,
})
}
chanPath1 := multihop.NewChanPath(paths1)
chanPath2 := multihop.NewChanPath(paths2)
// We need to key channel paths by the opposite connection hops as each chain needs to use the counterparty to
// generate a proof
pp.pathEnd1.chainProvider.AddChanPath(connectionHops2, chanPath1)
pp.pathEnd2.chainProvider.AddChanPath(connectionHops1, chanPath2)
return nil
}

// Run executes the main path process.
func (pp *PathProcessor) Run(ctx context.Context, cancel func()) {
if err := pp.setChanPaths(); err != nil {
panic(err)
}

var retryTimer *time.Timer

pp.flushTicker = time.NewTicker(pp.flushInterval)
Expand Down
19 changes: 8 additions & 11 deletions relayer/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,17 @@ type ChainProvider interface {

Init(ctx context.Context) error

// MultihopEndpoint returns a multihop endpoint for the chain to be used for multihop proofs
MultihopEndpoint(clientID, connectionID string) multihop.Endpoint

// SetMultihopCounterparty sets the multihop counterparty for the chain
SetMultihopCounterparty(endpoint, counterparty multihop.Endpoint)

// AddChanPath adds multihop channel path to a destination chain
AddChanPath(connectionHops []string, chanPath *multihop.ChanPath)
AddChanPath(connectionHops []string, chanPath multihop.ChanPath)

// GetChanPath gets multihop channel path to a destination chain
GetChanPath(connectionHops []string) *multihop.ChanPath
GetChanPath(connectionHops []string) multihop.ChanPath

// [Begin] Client IBC message assembly functions
NewClientState(dstChainID string, dstIBCHeader IBCHeader, dstTrustingPeriod, dstUbdPeriod time.Duration, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool) (ibcexported.ClientState, error)
Expand Down Expand Up @@ -591,12 +597,3 @@ func (c *ClientOutdatedError) Error() string {
return fmt.Sprintf("client for chain %q on chain %q is outdated (required: %d, actual: %d)", c.srcChainID,
c.dstChainID, c.height, c.requiredHeight)
}

func NewClientOutdatedError(srcChainID, dstChainID string, height, requiredHeight uint64) *ClientOutdatedError {
return &ClientOutdatedError{
srcChainID: srcChainID,
dstChainID: dstChainID,
height: height,
requiredHeight: requiredHeight,
}
}
38 changes: 26 additions & 12 deletions relayer/strategies.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,27 @@ const (
DefaultFlushInterval = 5 * time.Minute
)

func hopPathEnds(p *Path, pathName string, filterSrc, filterDst []processor.ChainChannelKey) ([]*processor.PathEnd,
[]*processor.PathEnd) {
hopsSrcToDst := make([]*processor.PathEnd, len(p.Hops))
for j, hop := range p.Hops {
pathEnd := hop.PathEnds[1]
srcToDst := processor.NewPathEnd(pathName, hop.ChainID, pathEnd.ClientID, pathEnd.ConnectionID,
p.Filter.Rule, filterSrc)
hopsSrcToDst[j] = &srcToDst
}
var hopsDstToSrc []*processor.PathEnd
// TODO: is it ok to reverse here?
for i := len(p.Hops) - 1; i >= 0; i-- {
hop := p.Hops[i]
pathEnd := hop.PathEnds[0]
dstToSrc := processor.NewPathEnd(pathName, hop.ChainID, pathEnd.ClientID, pathEnd.ConnectionID,
p.Filter.Rule, filterDst)
hopsDstToSrc = append(hopsDstToSrc, &dstToSrc)
}
return hopsSrcToDst, hopsDstToSrc
}

// StartRelayer starts the main relaying loop and returns a channel that will contain any control-flow related errors.
func StartRelayer(
ctx context.Context,
Expand Down Expand Up @@ -67,19 +88,12 @@ func StartRelayer(
filterSrc = append(filterSrc, ruleSrc)
filterDst = append(filterDst, ruleDst)
}
hopsSrcToDst := make([]*processor.PathEnd, len(p.Hops))
hopsDstToSrc := make([]*processor.PathEnd, len(p.Hops))
for j, hop := range p.Hops {
srcToDst := processor.NewPathEnd(pathName, hop.ChainID, hop.PathEnds[1].ClientID, filter.Rule,
filterSrc)
hopsSrcToDst[j] = &srcToDst
dstToSrc := processor.NewPathEnd(pathName, hop.ChainID, hop.PathEnds[0].ClientID, filter.Rule,
filterSrc)
hopsDstToSrc[j] = &dstToSrc
}
hopsSrcToDst, hopsDstToSrc := hopPathEnds(p, pathName, filterSrc, filterDst)
ePaths[i] = path{
src: processor.NewPathEnd(pathName, p.Src.ChainID, p.Src.ClientID, filter.Rule, filterSrc),
dst: processor.NewPathEnd(pathName, p.Dst.ChainID, p.Dst.ClientID, filter.Rule, filterDst),
src: processor.NewPathEnd(pathName, p.Src.ChainID, p.Src.ClientID, p.Src.ConnectionID,
filter.Rule, filterSrc),
dst: processor.NewPathEnd(pathName, p.Dst.ChainID, p.Dst.ClientID, p.Dst.ConnectionID,
filter.Rule, filterDst),
hopsSrcToDst: hopsSrcToDst,
hopsDstToSrc: hopsDstToSrc,
}
Expand Down

0 comments on commit 0f7b19c

Please sign in to comment.