Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/static/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51008,6 +51008,11 @@ paths:
withdraw_enabled:
type: boolean
title: Indicates if withdrawal is enabled
non_btc_relayers:
type: array
items:
type: string
title: Authorized relayers for non-btc asset deposit
vaults:
type: array
items:
Expand Down Expand Up @@ -82863,6 +82868,11 @@ definitions:
description: >-
MsgSubmitWithdrawTransactionResponse defines the
Msg/SubmitWithdrawTransaction response type.
side.btcbridge.MsgUpdateNonBtcRelayersResponse:
type: object
description: >-
MsgUpdateNonBtcRelayersResponse defines the Msg/UpdateNonBtcRelayers
response type.
side.btcbridge.MsgUpdateParamsResponse:
type: object
description: |-
Expand Down Expand Up @@ -82898,6 +82908,11 @@ definitions:
withdraw_enabled:
type: boolean
title: Indicates if withdrawal is enabled
non_btc_relayers:
type: array
items:
type: string
title: Authorized relayers for non-btc asset deposit
vaults:
type: array
items:
Expand Down Expand Up @@ -83336,6 +83351,11 @@ definitions:
withdraw_enabled:
type: boolean
title: Indicates if withdrawal is enabled
non_btc_relayers:
type: array
items:
type: string
title: Authorized relayers for non-btc asset deposit
vaults:
type: array
items:
Expand Down
10 changes: 6 additions & 4 deletions proto/side/btcbridge/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ message Params {
bool deposit_enabled = 4;
// Indicates if withdrawal is enabled
bool withdraw_enabled = 5;
// Authorized relayers for non-btc asset deposit
repeated string non_btc_relayers = 6;
// Asset vaults
repeated Vault vaults = 6;
repeated Vault vaults = 7;
// Protocol limitations
ProtocolLimits protocol_limits = 7 [(gogoproto.nullable) = false];
ProtocolLimits protocol_limits = 8 [(gogoproto.nullable) = false];
// Protocol fees
ProtocolFees protocol_fees = 8 [(gogoproto.nullable) = false];
ProtocolFees protocol_fees = 9 [(gogoproto.nullable) = false];
// TSS params
TSSParams tss_params = 9 [(gogoproto.nullable) = false];
TSSParams tss_params = 10 [(gogoproto.nullable) = false];
}

// AssetType defines the type of asset
Expand Down
12 changes: 12 additions & 0 deletions proto/side/btcbridge/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ option go_package = "github.com/sideprotocol/side/x/btcbridge/types";
service Msg {
// SubmitBlockHeaders submits bitcoin block headers to the side chain.
rpc SubmitBlockHeaders (MsgSubmitBlockHeaders) returns (MsgSubmitBlockHeadersResponse);
// UpdateNonBtcRelayers updates the authorized non-btc asset relayers.
rpc UpdateNonBtcRelayers (MsgUpdateNonBtcRelayers) returns (MsgUpdateNonBtcRelayersResponse);
// SubmitDepositTransaction submits bitcoin transaction to the side chain.
rpc SubmitDepositTransaction (MsgSubmitDepositTransaction) returns (MsgSubmitDepositTransactionResponse);
// SubmitWithdrawalTransaction submits bitcoin transaction to the side chain.
Expand Down Expand Up @@ -41,6 +43,16 @@ message MsgSubmitBlockHeaders {
message MsgSubmitBlockHeadersResponse {
}

// MsgUpdateNonBtcRelayers defines the Msg/UpdateNonBtcRelayers request type.
message MsgUpdateNonBtcRelayers {
string sender = 1;
repeated string relayers = 2;
}

// MsgUpdateNonBtcRelayersResponse defines the Msg/UpdateNonBtcRelayers response type.
message MsgUpdateNonBtcRelayersResponse {
}

// MsgSubmitDepositTransaction defines the Msg/SubmitDepositTransaction request type.
message MsgSubmitDepositTransaction {
// this is the relayer address who submits the bitcoin transaction to the side chain
Expand Down
30 changes: 30 additions & 0 deletions x/btcbridge/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func GetTxCmd() *cobra.Command {
}

cmd.AddCommand(CmdSubmitBlocks())
cmd.AddCommand(CmdUpdateNonBtcRelayers())
cmd.AddCommand(CmdWithdrawToBitcoin())
cmd.AddCommand(CmdSubmitWithdrawSignatures())
cmd.AddCommand(CmdCompleteDKG())
Expand Down Expand Up @@ -79,6 +80,35 @@ func CmdSubmitBlocks() *cobra.Command {
return cmd
}

func CmdUpdateNonBtcRelayers() *cobra.Command {
cmd := &cobra.Command{
Use: "update-non-btc-relayers [relayers]",
Short: "Update non-btc asset relayers",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

msg := types.NewMsgUpdateNonBtcRelayers(
clientCtx.GetFromAddress().String(),
strings.Split(args[0], listSeparator),
)

if err := msg.ValidateBasic(); err != nil {
return err
}

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

flags.AddTxFlagsToCmd(cmd)

return cmd
}

// Withdraw To Bitcoin
func CmdWithdrawToBitcoin() *cobra.Command {
cmd := &cobra.Command{
Expand Down
9 changes: 7 additions & 2 deletions x/btcbridge/keeper/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg
return nil, nil, err
}

recipient, err := k.Mint(ctx, tx, prevTx, k.GetBlockHeader(ctx, msg.Blockhash).Height)
recipient, err := k.Mint(ctx, msg.Sender, tx, prevTx, k.GetBlockHeader(ctx, msg.Blockhash).Height)
if err != nil {
return nil, nil, err
}
Expand All @@ -30,7 +30,7 @@ func (k Keeper) ProcessBitcoinDepositTransaction(ctx sdk.Context, msg *types.Msg
}

// Mint performs the minting operation of the voucher token
func (k Keeper) Mint(ctx sdk.Context, tx *btcutil.Tx, prevTx *btcutil.Tx, height uint64) (btcutil.Address, error) {
func (k Keeper) Mint(ctx sdk.Context, sender string, tx *btcutil.Tx, prevTx *btcutil.Tx, height uint64) (btcutil.Address, error) {
hash := tx.Hash().String()
if k.existsInHistory(ctx, hash) {
return nil, types.ErrTransactionAlreadyMinted
Expand All @@ -51,6 +51,11 @@ func (k Keeper) Mint(ctx sdk.Context, tx *btcutil.Tx, prevTx *btcutil.Tx, height

isRunes := edict != nil

// check if the sender is authorized to relay runes deposit
if isRunes && !k.IsAuthorizedNonBtcRelayer(ctx, sender) {
return nil, types.ErrUnauthorizedNonBtcRelayer
}

// extract the recipient for minting voucher token
recipient, err := types.ExtractRecipientAddr(tx.MsgTx(), prevTx.MsgTx(), params.Vaults, isRunes, chainCfg)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion x/btcbridge/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (suite *KeeperTestSuite) TestMintRunes() {
balanceBefore := suite.app.BankKeeper.GetBalance(suite.ctx, sdk.MustAccAddressFromBech32(suite.sender), denom)
suite.True(balanceBefore.Amount.IsZero(), "%s balance before mint should be zero", denom)

recipient, err := suite.app.BtcBridgeKeeper.Mint(suite.ctx, btcutil.NewTx(tx), btcutil.NewTx(tx), 0)
recipient, err := suite.app.BtcBridgeKeeper.Mint(suite.ctx, suite.sender, btcutil.NewTx(tx), btcutil.NewTx(tx), 0)
suite.NoError(err)
suite.Equal(suite.sender, recipient.EncodeAddress(), "incorrect recipient")

Expand Down
20 changes: 20 additions & 0 deletions x/btcbridge/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@ func (m msgServer) SubmitBlockHeaders(goCtx context.Context, msg *types.MsgSubmi
return &types.MsgSubmitBlockHeadersResponse{}, nil
}

// UpdateNonBtcRelayers implements types.MsgServer.
func (m msgServer) UpdateNonBtcRelayers(goCtx context.Context, msg *types.MsgUpdateNonBtcRelayers) (*types.MsgUpdateNonBtcRelayersResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

if err := msg.ValidateBasic(); err != nil {
return nil, err
}

if !m.IsAuthorizedNonBtcRelayer(ctx, msg.Sender) {
return nil, types.ErrUnauthorizedNonBtcRelayer
}

// update non-btc relayers
params := m.GetParams(ctx)
params.NonBtcRelayers = msg.Relayers
m.SetParams(ctx, params)

return &types.MsgUpdateNonBtcRelayersResponse{}, nil
}

// SubmitDepositTransaction implements types.MsgServer.
// No Permission check required for this message
// Since everyone can submit a transaction to mint voucher tokens
Expand Down
11 changes: 11 additions & 0 deletions x/btcbridge/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,14 @@ func (k Keeper) ProtocolDepositFeeEnabled(ctx sdk.Context) bool {
func (k Keeper) ProtocolWithdrawFeeEnabled(ctx sdk.Context) bool {
return k.GetParams(ctx).ProtocolFees.WithdrawFee > 0
}

// IsAuthorizedNonBtcRelayer returns true if the given address is an authorized non-btc relayer, false otherwise
func (k Keeper) IsAuthorizedNonBtcRelayer(ctx sdk.Context, addr string) bool {
for _, relayer := range k.GetParams(ctx).NonBtcRelayers {
if relayer == addr {
return true
}
}

return false
}
4 changes: 3 additions & 1 deletion x/btcbridge/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var (
ErrInvalidDepositTransaction = errorsmod.Register(ModuleName, 2108, "invalid deposit transaction")
ErrInvalidDepositAmount = errorsmod.Register(ModuleName, 2109, "invalid deposit amount")
ErrDepositNotEnabled = errorsmod.Register(ModuleName, 2110, "deposit not enabled")
ErrUnauthorizedNonBtcRelayer = errorsmod.Register(ModuleName, 2111, "unauthorized non btc relayer")

ErrInvalidAmount = errorsmod.Register(ModuleName, 3100, "invalid amount")
ErrInvalidFeeRate = errorsmod.Register(ModuleName, 3101, "invalid fee rate")
Expand All @@ -43,7 +44,8 @@ var (
ErrInvalidRunes = errorsmod.Register(ModuleName, 5100, "invalid runes")
ErrInvalidRuneId = errorsmod.Register(ModuleName, 5101, "invalid rune id")

ErrInvalidParams = errorsmod.Register(ModuleName, 6100, "invalid module params")
ErrInvalidParams = errorsmod.Register(ModuleName, 6100, "invalid module params")
ErrInvalidRelayers = errorsmod.Register(ModuleName, 6101, "invalid relayers")

ErrInvalidDKGParams = errorsmod.Register(ModuleName, 7100, "invalid dkg params")
ErrDKGRequestDoesNotExist = errorsmod.Register(ModuleName, 7101, "dkg request does not exist")
Expand Down
59 changes: 59 additions & 0 deletions x/btcbridge/types/message_update_non_btc_relayers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package types

import (
sdkerrors "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
)

const TypeMsgUpdateNonBtcRelayers = "update_non_btc_relayers"

func NewMsgUpdateNonBtcRelayers(
sender string,
relayers []string,
) *MsgUpdateNonBtcRelayers {
return &MsgUpdateNonBtcRelayers{
Sender: sender,
Relayers: relayers,
}
}

func (msg *MsgUpdateNonBtcRelayers) Route() string {
return RouterKey
}

func (msg *MsgUpdateNonBtcRelayers) Type() string {
return TypeMsgUpdateNonBtcRelayers
}

func (msg *MsgUpdateNonBtcRelayers) GetSigners() []sdk.AccAddress {
Sender, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
panic(err)
}
return []sdk.AccAddress{Sender}
}

func (msg *MsgUpdateNonBtcRelayers) GetSignBytes() []byte {
bz := ModuleCdc.MustMarshalJSON(msg)
return sdk.MustSortJSON(bz)
}

func (msg *MsgUpdateNonBtcRelayers) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return sdkerrors.Wrapf(err, "invalid sender address (%s)", err)
}

if len(msg.Relayers) == 0 {
return sdkerrors.Wrapf(ErrInvalidRelayers, "relayers can not be empty")
}

for _, relayer := range msg.Relayers {
_, err := sdk.AccAddressFromBech32(relayer)
if err != nil {
return sdkerrors.Wrapf(err, "invalid relayer address (%s)", err)
}
}

return nil
}
19 changes: 19 additions & 0 deletions x/btcbridge/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ func (p Params) Validate() error {
return err
}

if err := validateNonBtcRelayers(p.NonBtcRelayers); err != nil {
return err
}

if err := validateVaults(p.Vaults); err != nil {
return err
}
Expand Down Expand Up @@ -129,6 +133,21 @@ func SelectVaultByPkScript(vaults []*Vault, pkScript []byte) *Vault {
return nil
}

func validateNonBtcRelayers(relayers []string) error {
if len(relayers) == 0 {
return ErrInvalidParams
}

for _, relayer := range relayers {
_, err := sdk.AccAddressFromBech32(relayer)
if err != nil {
return ErrInvalidParams
}
}

return nil
}

// validateVaults validates the given vaults
func validateVaults(vaults []*Vault) error {
vaultMap := make(map[string]bool)
Expand Down
Loading