Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Tunnel] Add Router route #495

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
1,540 changes: 1,461 additions & 79 deletions api/band/tunnel/v1beta1/route.pulsar.go

Large diffs are not rendered by default.

4,174 changes: 2,087 additions & 2,087 deletions api/band/tunnel/v1beta1/tunnel.pulsar.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ func NewAppKeeper(
appKeepers.IBCFeeKeeper,
appKeepers.IBCKeeper.PortKeeper,
appKeepers.ScopedTunnelKeeper,
appKeepers.TransferKeeper,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

Expand Down
34 changes: 34 additions & 0 deletions proto/band/tunnel/v1beta1/route.proto
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
syntax = "proto3";
package band.tunnel.v1beta1;

import "amino/amino.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
import "gogoproto/gogo.proto";

import "band/feeds/v1beta1/encoder.proto";
Expand Down Expand Up @@ -49,6 +51,38 @@ message IBCPacketReceipt {
uint64 sequence = 1;
}

// RouterRoute is the type for a router route
message RouterRoute {
option (cosmos_proto.implements_interface) = "RouteI";

// channel_id is the IBC channel ID
string channel_id = 1 [(gogoproto.customname) = "ChannelID"];
// fund is the fund allocated for the Router fee.
cosmos.base.v1beta1.Coin fund = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin",
(amino.dont_omitempty) = true
];
// bridge_contract_address is the bridge contract address on router chain
string bridge_contract_address = 3;
// dest_chain_id is the destination chain ID
string dest_chain_id = 4 [(gogoproto.customname) = "DestChainID"];
// dest_contract_address is the destination contract address
string dest_contract_address = 5;
// dest_gas_limit is the destination gas limit
uint64 dest_gas_limit = 6;
// dest_gas_price is the destination gas price
uint64 dest_gas_price = 7;
}

// RouterPacketReceipt represents a receipt for a Router packet and implements the PacketReceiptI interface.
message RouterPacketReceipt {
option (cosmos_proto.implements_interface) = "PacketReceiptI";

// sequence is representing the sequence of the IBC packet.
uint64 sequence = 1;
}

// TunnelPricesPacketData represents the IBC packet payload for the tunnel packet.
message TunnelPricesPacketData {
// tunnel_id is the tunnel ID
Expand Down
56 changes: 28 additions & 28 deletions proto/band/tunnel/v1beta1/tunnel.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,34 @@ import "band/feeds/v1beta1/feeds.proto";
option go_package = "github.com/bandprotocol/chain/v3/x/tunnel/types";
option (gogoproto.equal_all) = true;

// SignalDeviation is the type for a signal with soft and hard deviation
message SignalDeviation {
option (gogoproto.equal) = true;

// signal_id is the signal ID
string signal_id = 1 [(gogoproto.customname) = "SignalID"];
// soft_deviation_bps is the soft deviation in basis points
uint64 soft_deviation_bps = 2 [(gogoproto.customname) = "SoftDeviationBPS"];
// hard_deviation_bps is the hard deviation in basis points
uint64 hard_deviation_bps = 3 [(gogoproto.customname) = "HardDeviationBPS"];
}

// Deposit defines an amount deposited by an account address to the tunnel.
message Deposit {
option (gogoproto.equal) = true;

// tunnel_id defines the unique id of the tunnel.
uint64 tunnel_id = 1 [(gogoproto.customname) = "TunnelID"];
// depositor defines the deposit addresses from the proposals.
string depositor = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// amount to be deposited by depositor.
repeated cosmos.base.v1beta1.Coin amount = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(amino.dont_omitempty) = true
];
}

// Tunnel contains the information of the tunnel that is created by the user
message Tunnel {
option (gogoproto.equal) = true;
Expand Down Expand Up @@ -84,34 +112,6 @@ message Packet {
int64 created_at = 7;
}

// Deposit defines an amount deposited by an account address to the tunnel.
message Deposit {
option (gogoproto.equal) = true;

// tunnel_id defines the unique id of the tunnel.
uint64 tunnel_id = 1 [(gogoproto.customname) = "TunnelID"];
// depositor defines the deposit addresses from the proposals.
string depositor = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// amount to be deposited by depositor.
repeated cosmos.base.v1beta1.Coin amount = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(amino.dont_omitempty) = true
];
}

// SignalDeviation is the type for a signal with soft and hard deviation
message SignalDeviation {
option (gogoproto.equal) = true;

// signal_id is the signal ID
string signal_id = 1 [(gogoproto.customname) = "SignalID"];
// soft_deviation_bps is the soft deviation in basis points
uint64 soft_deviation_bps = 2 [(gogoproto.customname) = "SoftDeviationBPS"];
// hard_deviation_bps is the hard deviation in basis points
uint64 hard_deviation_bps = 3 [(gogoproto.customname) = "HardDeviationBPS"];
}

// TunnelSignatureOrder defines a general signature order for sending signature to tss group.
message TunnelSignatureOrder {
option (gogoproto.goproto_getters) = false;
Expand Down
1 change: 1 addition & 0 deletions scripts/tunnel/create_router_tunnel.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bandd tx tunnel create-tunnel router channel-0 1uband router17c2txg2px6vna8a6v4ql4eh4ruvprerhytxvwt2ugp4qr473pajsyj9pgm 17000 0xDFCfEbF22e85193eDc37b8b136d4F3394987d1AE 300000 10000000 1000000000uband 1000 ./scripts/tunnel/signal_deviations.json --from requester --keyring-backend test --gas-prices 0.0025uband -y --chain-id bandchain
73 changes: 73 additions & 0 deletions x/tunnel/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func GetTxCmdCreateTunnel() *cobra.Command {
txCmd.AddCommand(
GetTxCmdCreateTSSTunnel(),
GetTxCmdCreateIBCTunnel(),
GetTxCmdCreateRouterTunnel(),
)

return txCmd
Expand Down Expand Up @@ -155,6 +156,78 @@ func GetTxCmdCreateIBCTunnel() *cobra.Command {
return cmd
}

func GetTxCmdCreateRouterTunnel() *cobra.Command {
cmd := &cobra.Command{
Use: "router [channel-id] [fund] [bridge-contract-address] [dest-chain-id] [dest-contract-address] [dest-gas-limit] [dest-gas-price] [initial-deposit] [interval] [signalDeviations-json-file]",
Short: "Create a new router tunnel",
Args: cobra.ExactArgs(10),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

channelID := args[0]

fund, err := sdk.ParseCoinNormalized(args[1])
if err != nil {
return err
}

bridgeContractAddr := args[2]
destChainID := args[3]
destContractAddr := args[4]

destGasLimit, err := strconv.ParseUint(args[5], 10, 64)
if err != nil {
return err
}

destGasPrice, err := strconv.ParseUint(args[6], 10, 64)
if err != nil {
return err
}

initialDeposit, err := sdk.ParseCoinsNormalized(args[7])
if err != nil {
return err
}

interval, err := strconv.ParseUint(args[8], 10, 64)
if err != nil {
return err
}

signalDeviations, err := parseSignalDeviations(args[9])
if err != nil {
return err
}

msg, err := types.NewMsgCreateRouterTunnel(
signalDeviations.ToSignalDeviations(),
interval,
channelID,
fund,
bridgeContractAddr,
destChainID,
destContractAddr,
destGasLimit,
destGasPrice,
initialDeposit,
clientCtx.GetFromAddress().String(),
)
if err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)
return cmd
}

func GetTxCmdUpdateRoute() *cobra.Command {
txCmd := &cobra.Command{
Use: "update-route",
Expand Down
41 changes: 22 additions & 19 deletions x/tunnel/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ type Keeper struct {
cdc codec.BinaryCodec
storeKey storetypes.StoreKey

authKeeper types.AccountKeeper
bankKeeper types.BankKeeper
feedsKeeper types.FeedsKeeper
bandtssKeeper types.BandtssKeeper
channelKeeper types.ChannelKeeper
ics4Wrapper types.ICS4Wrapper
portKeeper types.PortKeeper
scopedKeeper types.ScopedKeeper
authKeeper types.AccountKeeper
bankKeeper types.BankKeeper
feedsKeeper types.FeedsKeeper
bandtssKeeper types.BandtssKeeper
channelKeeper types.ChannelKeeper
ics4Wrapper types.ICS4Wrapper
portKeeper types.PortKeeper
scopedKeeper types.ScopedKeeper
transferKeeper types.TransferKeeper

authority string
}
Expand All @@ -40,6 +41,7 @@ func NewKeeper(
ics4Wrapper types.ICS4Wrapper,
portKeeper types.PortKeeper,
scopedKeeper types.ScopedKeeper,
transferKeeper types.TransferKeeper,
authority string,
) Keeper {
// ensure tunnel module account is set
Expand All @@ -53,17 +55,18 @@ func NewKeeper(
}

return Keeper{
cdc: cdc,
storeKey: key,
authKeeper: authKeeper,
bankKeeper: bankKeeper,
feedsKeeper: feedsKeeper,
bandtssKeeper: bandtssKeeper,
channelKeeper: channelKeeper,
ics4Wrapper: ics4Wrapper,
portKeeper: portKeeper,
scopedKeeper: scopedKeeper,
authority: authority,
cdc: cdc,
storeKey: key,
authKeeper: authKeeper,
bankKeeper: bankKeeper,
feedsKeeper: feedsKeeper,
bandtssKeeper: bandtssKeeper,
channelKeeper: channelKeeper,
ics4Wrapper: ics4Wrapper,
portKeeper: portKeeper,
scopedKeeper: scopedKeeper,
transferKeeper: transferKeeper,
authority: authority,
}
}

Expand Down
2 changes: 2 additions & 0 deletions x/tunnel/keeper/keeper_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ func (k Keeper) SendPacket(ctx sdk.Context, packet types.Packet) (err error) {
)
case *types.IBCRoute:
receipt, err = k.SendIBCPacket(ctx, r, packet, tunnel.Interval)
case *types.RouterRoute:
receipt, err = k.SendRouterPacket(ctx, r, packet, sdk.MustAccAddressFromBech32(tunnel.FeePayer), tunnel.Interval)
default:
return types.ErrInvalidRoute.Wrapf("no route found for tunnel ID: %d", tunnel.ID)
}
Expand Down
60 changes: 60 additions & 0 deletions x/tunnel/keeper/keeper_packet_router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package keeper

import (
"encoding/base64"
"time"

ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/bandprotocol/chain/v3/x/tunnel/types"
)

// SendRouterPacket sends Router packet
func (k Keeper) SendRouterPacket(
ctx sdk.Context,
route *types.RouterRoute,
packet types.Packet,
feePayer sdk.AccAddress,
interval uint64,
) (types.PacketReceiptI, error) {
relayPacket, err := types.EncodingRouter(packet)
if err != nil {
return nil, err
}

// create memo string for ibc transfer
memoStr, err := types.NewRouterMemo(
route.BridgeContractAddress,
route.DestChainID,
route.DestContractAddress,
route.DestGasLimit,
route.DestGasPrice,
base64.StdEncoding.EncodeToString(relayPacket),
0,
"",
).String()
if err != nil {
return nil, err
}

msg := ibctransfertypes.NewMsgTransfer(
ibctransfertypes.PortID,
route.ChannelID,
route.Fund,
feePayer.String(),
route.BridgeContractAddress,
clienttypes.ZeroHeight(),
uint64(ctx.BlockTime().UnixNano())+interval*uint64(time.Second)*2,
memoStr,
)

res, err := k.transferKeeper.Transfer(ctx, msg)
if err != nil {
return nil, err
}

return types.NewRouterPacketReceipt(res.Sequence), nil
}
Loading
Loading