Skip to content

Commit

Permalink
feat: support cross chain for multiple blockchains (#242)
Browse files Browse the repository at this point in the history
  • Loading branch information
yutianwu committed Jul 12, 2023
1 parent 2dd8c5b commit 5645161
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 144 deletions.
5 changes: 3 additions & 2 deletions types/cross_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ type CrossChainApplication interface {
}

type CrossChainAppContext struct {
Sequence uint64
Header *PackageHeader
SrcChainId ChainID
Sequence uint64
Header *PackageHeader
}

type ExecuteResult struct {
Expand Down
4 changes: 2 additions & 2 deletions x/crosschain/keeper/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import sdk "github.com/cosmos/cosmos-sdk/types"

type crossChainConfig struct {
srcChainID sdk.ChainID
destChainId sdk.ChainID
destBscChainId sdk.ChainID
nameToChannelID map[string]sdk.ChannelID
channelIDToName map[sdk.ChannelID]string
channelIDToApp map[sdk.ChannelID]sdk.CrossChainApplication
Expand All @@ -13,7 +13,7 @@ type crossChainConfig struct {
func newCrossChainCfg() *crossChainConfig {
config := &crossChainConfig{
srcChainID: 0,
destChainId: 0,
destBscChainId: 0,
nameToChannelID: make(map[string]sdk.ChannelID),
channelIDToName: make(map[sdk.ChannelID]string),
channelIDToApp: make(map[sdk.ChannelID]sdk.CrossChainApplication),
Expand Down
6 changes: 3 additions & 3 deletions x/crosschain/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (k Keeper) CrossChainPackage(c context.Context, req *types.QueryCrossChainP
}

ctx := sdk.UnwrapSDKContext(c)
pack, err := k.GetCrossChainPackage(ctx, sdk.ChannelID(req.ChannelId), req.Sequence)
pack, err := k.GetCrossChainPackage(ctx, k.GetDestBscChainID(), sdk.ChannelID(req.ChannelId), req.Sequence)
if err != nil {
return nil, err
}
Expand All @@ -42,7 +42,7 @@ func (k Keeper) SendSequence(c context.Context, req *types.QuerySendSequenceRequ
}

ctx := sdk.UnwrapSDKContext(c)
sequence := k.GetSendSequence(ctx, sdk.ChannelID(req.ChannelId))
sequence := k.GetSendSequence(ctx, k.GetDestBscChainID(), sdk.ChannelID(req.ChannelId))

return &types.QuerySendSequenceResponse{
Sequence: sequence,
Expand All @@ -56,7 +56,7 @@ func (k Keeper) ReceiveSequence(c context.Context, req *types.QueryReceiveSequen
}

ctx := sdk.UnwrapSDKContext(c)
sequence := k.GetReceiveSequence(ctx, sdk.ChannelID(req.ChannelId))
sequence := k.GetReceiveSequence(ctx, k.GetDestBscChainID(), sdk.ChannelID(req.ChannelId))

return &types.QueryReceiveSequenceResponse{
Sequence: sequence,
Expand Down
42 changes: 21 additions & 21 deletions x/crosschain/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error {
}

// CreateRawIBCPackageWithFee creates a cross chain package with given cross chain fee
func (k Keeper) CreateRawIBCPackageWithFee(ctx sdk.Context, channelID sdk.ChannelID,
func (k Keeper) CreateRawIBCPackageWithFee(ctx sdk.Context, destChainId sdk.ChainID, channelID sdk.ChannelID,
packageType sdk.CrossChainPackageType, packageLoad []byte, relayerFee, ackRelayerFee *big.Int,
) (uint64, error) {
if packageType == sdk.SynCrossChainPackageType && k.GetChannelSendPermission(ctx, k.GetDestChainID(), channelID) != sdk.ChannelAllow {
if packageType == sdk.SynCrossChainPackageType && k.GetChannelSendPermission(ctx, destChainId, channelID) != sdk.ChannelAllow {
return 0, fmt.Errorf("channel %d is not allowed to write syn package", channelID)
}

sequence := k.GetSendSequence(ctx, channelID)
key := types.BuildCrossChainPackageKey(k.GetSrcChainID(), k.GetDestChainID(), channelID, sequence)
sequence := k.GetSendSequence(ctx, destChainId, channelID)
key := types.BuildCrossChainPackageKey(k.GetSrcChainID(), destChainId, channelID, sequence)
kvStore := ctx.KVStore(k.storeKey)
if kvStore.Has(key) {
return 0, fmt.Errorf("duplicated sequence")
Expand All @@ -116,11 +116,11 @@ func (k Keeper) CreateRawIBCPackageWithFee(ctx sdk.Context, channelID sdk.Channe

kvStore.Set(key, append(packageHeader, packageLoad...))

k.IncrSendSequence(ctx, channelID)
k.IncrSendSequence(ctx, destChainId, channelID)

err := ctx.EventManager().EmitTypedEvent(&types.EventCrossChain{
SrcChainId: uint32(k.GetSrcChainID()),
DestChainId: uint32(k.GetDestChainID()),
DestChainId: uint32(destChainId),
ChannelId: uint32(channelID),
Sequence: sequence,
PackageType: uint32(packageType),
Expand Down Expand Up @@ -157,7 +157,7 @@ func (k Keeper) RegisterChannel(name string, id sdk.ChannelID, app sdk.CrossChai

// IsDestChainSupported returns the support status of a dest chain
func (k Keeper) IsDestChainSupported(chainID sdk.ChainID) bool {
return chainID == k.cfg.destChainId
return chainID == k.cfg.destBscChainId
}

// SetChannelSendPermission sets the channel send permission
Expand Down Expand Up @@ -188,39 +188,39 @@ func (k Keeper) GetSrcChainID() sdk.ChainID {

// SetDestChainID sets the destination chain id
func (k Keeper) SetDestChainID(destChainId sdk.ChainID) {
k.cfg.destChainId = destChainId
k.cfg.destBscChainId = destChainId
}

// GetDestChainID gets the destination chain id
func (k Keeper) GetDestChainID() sdk.ChainID {
return k.cfg.destChainId
// GetDestBscChainID gets the destination chain id of bsc
func (k Keeper) GetDestBscChainID() sdk.ChainID {
return k.cfg.destBscChainId
}

// GetCrossChainPackage returns the ibc package by sequence
func (k Keeper) GetCrossChainPackage(ctx sdk.Context, channelId sdk.ChannelID, sequence uint64) ([]byte, error) {
func (k Keeper) GetCrossChainPackage(ctx sdk.Context, destChainId sdk.ChainID, channelId sdk.ChannelID, sequence uint64) ([]byte, error) {
kvStore := ctx.KVStore(k.storeKey)
key := types.BuildCrossChainPackageKey(k.GetSrcChainID(), k.GetDestChainID(), channelId, sequence)
key := types.BuildCrossChainPackageKey(k.GetSrcChainID(), destChainId, channelId, sequence)
return kvStore.Get(key), nil
}

// GetSendSequence returns the sending sequence of the channel
func (k Keeper) GetSendSequence(ctx sdk.Context, channelID sdk.ChannelID) uint64 {
return k.getSequence(ctx, k.GetDestChainID(), channelID, types.PrefixForSendSequenceKey)
func (k Keeper) GetSendSequence(ctx sdk.Context, destChainId sdk.ChainID, channelID sdk.ChannelID) uint64 {
return k.getSequence(ctx, destChainId, channelID, types.PrefixForSendSequenceKey)
}

// IncrSendSequence increases the sending sequence of the channel
func (k Keeper) IncrSendSequence(ctx sdk.Context, channelID sdk.ChannelID) {
k.incrSequence(ctx, k.GetDestChainID(), channelID, types.PrefixForSendSequenceKey)
func (k Keeper) IncrSendSequence(ctx sdk.Context, destChainId sdk.ChainID, channelID sdk.ChannelID) {
k.incrSequence(ctx, destChainId, channelID, types.PrefixForSendSequenceKey)
}

// GetReceiveSequence returns the receiving sequence of the channel
func (k Keeper) GetReceiveSequence(ctx sdk.Context, channelID sdk.ChannelID) uint64 {
return k.getSequence(ctx, k.GetDestChainID(), channelID, types.PrefixForReceiveSequenceKey)
func (k Keeper) GetReceiveSequence(ctx sdk.Context, destChainId sdk.ChainID, channelID sdk.ChannelID) uint64 {
return k.getSequence(ctx, destChainId, channelID, types.PrefixForReceiveSequenceKey)
}

// IncrReceiveSequence increases the receiving sequence of the channel
func (k Keeper) IncrReceiveSequence(ctx sdk.Context, channelID sdk.ChannelID) {
k.incrSequence(ctx, k.GetDestChainID(), channelID, types.PrefixForReceiveSequenceKey)
func (k Keeper) IncrReceiveSequence(ctx sdk.Context, destChainId sdk.ChainID, channelID sdk.ChannelID) {
k.incrSequence(ctx, destChainId, channelID, types.PrefixForReceiveSequenceKey)
}

// getSequence returns the sequence with a prefix
Expand Down
12 changes: 6 additions & 6 deletions x/crosschain/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,21 @@ func TestTestSuite(t *testing.T) {
}

func (s *TestSuite) TestIncrSendSequence() {
beforeSequence := s.crossChainKeeper.GetSendSequence(s.ctx, sdk.ChannelID(1))
beforeSequence := s.crossChainKeeper.GetSendSequence(s.ctx, sdk.ChainID(1), sdk.ChannelID(1))

s.crossChainKeeper.IncrSendSequence(s.ctx, sdk.ChannelID(1))
s.crossChainKeeper.IncrSendSequence(s.ctx, sdk.ChainID(1), sdk.ChannelID(1))

afterSequence := s.crossChainKeeper.GetSendSequence(s.ctx, sdk.ChannelID(1))
afterSequence := s.crossChainKeeper.GetSendSequence(s.ctx, sdk.ChainID(1), sdk.ChannelID(1))

s.Require().EqualValues(afterSequence, beforeSequence+1)
}

func (s *TestSuite) TestIncrReceiveSequence() {
beforeSequence := s.crossChainKeeper.GetReceiveSequence(s.ctx, sdk.ChannelID(1))
beforeSequence := s.crossChainKeeper.GetReceiveSequence(s.ctx, sdk.ChainID(1), sdk.ChannelID(1))

s.crossChainKeeper.IncrReceiveSequence(s.ctx, sdk.ChannelID(1))
s.crossChainKeeper.IncrReceiveSequence(s.ctx, sdk.ChainID(1), sdk.ChannelID(1))

afterSequence := s.crossChainKeeper.GetReceiveSequence(s.ctx, sdk.ChannelID(1))
afterSequence := s.crossChainKeeper.GetReceiveSequence(s.ctx, sdk.ChainID(1), sdk.ChannelID(1))

s.Require().EqualValues(afterSequence, beforeSequence+1)
}
Expand Down
5 changes: 0 additions & 5 deletions x/crosschain/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ const (

MaxSideChainIdLength = 20
SequenceLength = 8

GovChannelId = sdk.ChannelID(9)
)

var (
Expand Down Expand Up @@ -58,9 +56,6 @@ func (c *ChannelPermissionSetting) Check() error {
if len(c.DestChainId) == 0 || len(c.DestChainId) > MaxSideChainIdLength {
return fmt.Errorf("invalid dest chain id")
}
if c.ChannelId == GovChannelId {
return fmt.Errorf("gov channel id is forbidden to set")
}
if c.Permission != sdk.ChannelAllow && c.Permission != sdk.ChannelForbidden {
return fmt.Errorf("permission %d is invalid", c.Permission)
}
Expand Down
3 changes: 2 additions & 1 deletion x/gov/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ func setupGovKeeper(t *testing.T) (
govKeeper.SetLegacyRouter(govRouter)
govKeeper.SetParams(ctx, v1.DefaultParams())

crossChainKeeper.EXPECT().CreateRawIBCPackageWithFee(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(0), nil).AnyTimes()
crossChainKeeper.EXPECT().GetDestBscChainID().Return(sdk.ChainID(714)).AnyTimes()
crossChainKeeper.EXPECT().CreateRawIBCPackageWithFee(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(0), nil).AnyTimes()

// Register all handlers for the MegServiceRouter.
msr.SetInterfaceRegistry(encCfg.InterfaceRegistry)
Expand Down
1 change: 1 addition & 0 deletions x/gov/keeper/crosschain.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func (k Keeper) SyncParams(ctx sdk.Context, cpc govv1.CrossChainParamsChange) er

_, err := k.crossChainKeeper.CreateRawIBCPackageWithFee(
ctx,
k.crossChainKeeper.GetDestBscChainID(),
types.SyncParamsChannelID,
sdk.SynCrossChainPackageType,
encodedPackage,
Expand Down
7 changes: 4 additions & 3 deletions x/gov/testutil/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ type StakingKeeper interface {

// CrossChainKeeper defines the expected crossChain keeper
type CrossChainKeeper interface {
RegisterChannel(name string, id sdk.ChannelID, app sdk.CrossChainApplication) error

CreateRawIBCPackageWithFee(ctx sdk.Context, channelID sdk.ChannelID, packageType sdk.CrossChainPackageType,
GetDestBscChainID() sdk.ChainID
CreateRawIBCPackageWithFee(ctx sdk.Context, destChainId sdk.ChainID, channelID sdk.ChannelID, packageType sdk.CrossChainPackageType,
packageLoad []byte, relayerFee, ackRelayerFee *big.Int,
) (uint64, error)

RegisterChannel(name string, id sdk.ChannelID, app sdk.CrossChainApplication) error
}
23 changes: 18 additions & 5 deletions x/gov/testutil/expected_keepers_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion x/gov/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ type BankKeeper interface {
}

type CrossChainKeeper interface {
CreateRawIBCPackageWithFee(ctx sdk.Context, channelID sdk.ChannelID, packageType sdk.CrossChainPackageType,
GetDestBscChainID() sdk.ChainID
CreateRawIBCPackageWithFee(ctx sdk.Context, destChainId sdk.ChainID, channelID sdk.ChannelID, packageType sdk.CrossChainPackageType,
packageLoad []byte, relayerFee, ackRelayerFee *big.Int,
) (uint64, error)

Expand Down
30 changes: 17 additions & 13 deletions x/oracle/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (k msgServer) Claim(goCtx context.Context, req *types.MsgClaim) (*types.Msg
return nil, sdkerrors.Wrapf(types.ErrInvalidSrcChainId, "src chain id(%d) is not supported", req.SrcChainId)
}

sequence := k.CrossChainKeeper.GetReceiveSequence(ctx, types.RelayPackagesChannelId)
sequence := k.CrossChainKeeper.GetReceiveSequence(ctx, sdk.ChainID(req.SrcChainId), types.RelayPackagesChannelId)
if sequence != req.Sequence {
return nil, sdkerrors.Wrapf(types.ErrInvalidReceiveSequence, "current sequence of channel %d is %d", types.RelayPackagesChannelId, sequence)
}
Expand Down Expand Up @@ -92,15 +92,15 @@ func (k msgServer) Claim(goCtx context.Context, req *types.MsgClaim) (*types.Msg
totalRelayerFee = totalRelayerFee.Add(relayerFee)

// increase channel sequence
k.CrossChainKeeper.IncrReceiveSequence(ctx, pack.ChannelId)
k.CrossChainKeeper.IncrReceiveSequence(ctx, sdk.ChainID(req.SrcChainId), pack.ChannelId)
}

err = k.distributeReward(ctx, relayer, signedRelayers, totalRelayerFee)
if err != nil {
return nil, err
}

k.CrossChainKeeper.IncrReceiveSequence(ctx, types.RelayPackagesChannelId)
k.CrossChainKeeper.IncrReceiveSequence(ctx, sdk.ChainID(req.SrcChainId), types.RelayPackagesChannelId)

err = ctx.EventManager().EmitTypedEvents(events...)
if err != nil {
Expand Down Expand Up @@ -179,7 +179,7 @@ func (k Keeper) handlePackage(
return sdkmath.ZeroInt(), nil, sdkerrors.Wrapf(types.ErrChannelNotRegistered, "channel %d not registered", pack.ChannelId)
}

sequence := k.CrossChainKeeper.GetReceiveSequence(ctx, pack.ChannelId)
sequence := k.CrossChainKeeper.GetReceiveSequence(ctx, sdk.ChainID(srcChainId), pack.ChannelId)
if sequence != pack.Sequence {
return sdkmath.ZeroInt(), nil, sdkerrors.Wrapf(types.ErrInvalidReceiveSequence,
"current sequence of channel %d is %d", pack.ChannelId, sequence)
Expand All @@ -201,7 +201,7 @@ func (k Keeper) handlePackage(
}

cacheCtx, write := ctx.CacheContext()
crash, result := executeClaim(cacheCtx, crossChainApp, sequence, pack.Payload, &packageHeader)
crash, result := executeClaim(cacheCtx, crossChainApp, srcChainId, sequence, pack.Payload, &packageHeader)
if result.IsOk() {
write()
}
Expand All @@ -216,15 +216,15 @@ func (k Keeper) handlePackage(
return sdkmath.ZeroInt(), nil, sdkerrors.Wrapf(types.ErrInvalidPackage, "payload without header")
}

sendSeq, ibcErr := k.CrossChainKeeper.CreateRawIBCPackageWithFee(ctx, pack.ChannelId,
sendSeq, ibcErr := k.CrossChainKeeper.CreateRawIBCPackageWithFee(ctx, sdk.ChainID(srcChainId), pack.ChannelId,
sdk.FailAckCrossChainPackageType, pack.Payload[sdk.SynPackageHeaderLength:], packageHeader.AckRelayerFee, sdk.NilAckRelayerFee)
if ibcErr != nil {
logger.Error("failed to write FailAckCrossChainPackage", "err", err)
return sdkmath.ZeroInt(), nil, ibcErr
}
sendSequence = int64(sendSeq)
} else if len(result.Payload) != 0 {
sendSeq, err := k.CrossChainKeeper.CreateRawIBCPackageWithFee(ctx, pack.ChannelId,
sendSeq, err := k.CrossChainKeeper.CreateRawIBCPackageWithFee(ctx, sdk.ChainID(srcChainId), pack.ChannelId,
sdk.AckCrossChainPackageType, result.Payload, packageHeader.AckRelayerFee, sdk.NilAckRelayerFee)
if err != nil {
logger.Error("failed to write AckCrossChainPackage", "err", err)
Expand Down Expand Up @@ -253,6 +253,7 @@ func (k Keeper) handlePackage(
func executeClaim(
ctx sdk.Context,
app sdk.CrossChainApplication,
srcChainId uint32,
sequence uint64,
payload []byte,
header *sdk.PackageHeader,
Expand All @@ -272,18 +273,21 @@ func executeClaim(
switch header.PackageType {
case sdk.SynCrossChainPackageType:
result = app.ExecuteSynPackage(ctx, &sdk.CrossChainAppContext{
Sequence: sequence,
Header: header,
SrcChainId: sdk.ChainID(srcChainId),
Sequence: sequence,
Header: header,
}, payload[sdk.SynPackageHeaderLength:])
case sdk.AckCrossChainPackageType:
result = app.ExecuteAckPackage(ctx, &sdk.CrossChainAppContext{
Sequence: sequence,
Header: header,
SrcChainId: sdk.ChainID(srcChainId),
Sequence: sequence,
Header: header,
}, payload[sdk.AckPackageHeaderLength:])
case sdk.FailAckCrossChainPackageType:
result = app.ExecuteFailAckPackage(ctx, &sdk.CrossChainAppContext{
Sequence: sequence,
Header: header,
SrcChainId: sdk.ChainID(srcChainId),
Sequence: sequence,
Header: header,
}, payload[sdk.AckPackageHeaderLength:])
default:
panic(fmt.Sprintf("receive unexpected package type %d", header.PackageType))
Expand Down
Loading

0 comments on commit 5645161

Please sign in to comment.