Skip to content

Commit

Permalink
feat: add MsgBridgeCallClaim to crosschain (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
zakir-code committed Feb 18, 2024
1 parent 0ecb53f commit 9d00cdf
Show file tree
Hide file tree
Showing 15 changed files with 1,265 additions and 210 deletions.
4 changes: 2 additions & 2 deletions app/encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ func TestMakeEncodingConfig_RegisterInterfaces(t *testing.T) {
count3++
t.Log(typeURLMap.Key())
}
assert.Equal(t, 262, count3)
assert.Equal(t, 264, count3)

govContent := encodingConfig.InterfaceRegistry.ListImplementations("cosmos.gov.v1beta1.Content")
assert.Equal(t, 14, len(govContent))

msgImplementations := encodingConfig.InterfaceRegistry.ListImplementations(sdk.MsgInterfaceProtoName)
assert.Equal(t, 101, len(msgImplementations))
assert.Equal(t, 102, len(msgImplementations))

type govProposalMsg interface {
GetAuthority() string
Expand Down
21 changes: 21 additions & 0 deletions proto/fx/crosschain/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ service Msg {
rpc BridgeTokenClaim(MsgBridgeTokenClaim) returns (MsgBridgeTokenClaimResponse);

rpc SendToFxClaim(MsgSendToFxClaim) returns (MsgSendToFxClaimResponse);
rpc BridgeCallClaim(MsgBridgeCallClaim) returns (MsgBridgeCallClaimResponse);

rpc SendToExternal(MsgSendToExternal) returns (MsgSendToExternalResponse);
rpc CancelSendToExternal(MsgCancelSendToExternal) returns (MsgCancelSendToExternalResponse);
Expand Down Expand Up @@ -150,6 +151,26 @@ message MsgSendToFxClaim {

message MsgSendToFxClaimResponse {}

message MsgBridgeCallClaim {
string dst_chain_id = 1;
uint64 event_nonce = 2;
string sender = 3;
string receiver = 4;
string asset = 5;
string to = 6;
string message = 7;
string value = 8 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
uint64 gasLimit = 9;
uint64 block_height = 10;
string bridger_address = 11;
string chain_name = 12;
}

message MsgBridgeCallClaimResponse {}

// MsgSendToExternal
// This is the message that a user calls when they want to bridge an asset
// it will later be removed when it is included in a batch and successfully
Expand Down
4 changes: 2 additions & 2 deletions proto/fx/staking/v1beta1/tx.proto
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
syntax = "proto3";
package fx.staking.v1;

import "google/protobuf/any.proto";
import "cosmos_proto/cosmos.proto";
import "google/protobuf/any.proto";

option go_package = "github.com/functionx/fx-core/x/staking/types";

Expand Down Expand Up @@ -30,4 +30,4 @@ message MsgEditConsensusPubKey {
google.protobuf.Any pubkey = 3 [(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey"];
}

message MsgEditConsensusPubKeyResponse{}
message MsgEditConsensusPubKeyResponse {}
21 changes: 21 additions & 0 deletions types/address.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package types

import (
"errors"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/bech32"
"github.com/ethereum/go-ethereum/common"
)

func ParseAddress(addr string) (accAddr sdk.AccAddress, isEvmAddr bool, err error) {
_, bytes, decodeErr := bech32.DecodeAndConvert(addr)
if decodeErr == nil {
return bytes, false, nil
}
ethAddrError := ValidateEthereumAddress(addr)
if ethAddrError == nil {
return common.HexToAddress(addr).Bytes(), true, nil
}
return nil, false, errors.Join(decodeErr, ethAddrError)
}
8 changes: 8 additions & 0 deletions x/crosschain/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,14 @@ func (s MsgServer) SendToFxClaim(c context.Context, msg *types.MsgSendToFxClaim)
return &types.MsgSendToFxClaimResponse{}, nil
}

func (s MsgServer) BridgeCallClaim(c context.Context, msg *types.MsgBridgeCallClaim) (*types.MsgBridgeCallClaimResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
if err := s.claimHandlerCommon(ctx, msg); err != nil {
return nil, err
}
return &types.MsgBridgeCallClaimResponse{}, nil
}

func (s MsgServer) BridgeTokenClaim(c context.Context, msg *types.MsgBridgeTokenClaim) (*types.MsgBridgeTokenClaimResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
if err := s.claimHandlerCommon(ctx, msg); err != nil {
Expand Down
8 changes: 8 additions & 0 deletions x/crosschain/keeper/msg_server_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ func (k msgServer) SendToFxClaim(ctx context.Context, msg *types.MsgSendToFxClai
}
}

func (k msgServer) BridgeCallClaim(ctx context.Context, msg *types.MsgBridgeCallClaim) (*types.MsgBridgeCallClaimResponse, error) {
if queryServer, err := k.getMsgServerByChainName(msg.GetChainName()); err != nil {
return nil, err
} else {
return queryServer.BridgeCallClaim(ctx, msg)
}
}

func (k msgServer) SendToExternal(ctx context.Context, msg *types.MsgSendToExternal) (*types.MsgSendToExternalResponse, error) {
if queryServer, err := k.getMsgServerByChainName(msg.GetChainName()); err != nil {
return nil, err
Expand Down
58 changes: 58 additions & 0 deletions x/crosschain/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1095,3 +1095,61 @@ func (suite *KeeperTestSuite) TestMsgUpdateChainOracles() {
_, err = suite.MsgServer().UpdateChainOracles(suite.ctx, updateOracle)
require.Error(suite.T(), err)
}

func (suite *KeeperTestSuite) TestBridgeCallClaim() {
normalMsg := &types.MsgBondedOracle{
OracleAddress: suite.oracleAddrs[0].String(),
BridgerAddress: suite.bridgerAddrs[0].String(),
ExternalAddress: suite.PubKeyToExternalAddr(suite.externalPris[0].PublicKey),
ValidatorAddress: suite.valAddrs[0].String(),
DelegateAmount: types.NewDelegateAmount(sdkmath.NewInt((tmrand.Int63n(5) + 1) * 10_000).MulRaw(1e18)),
ChainName: suite.chainName,
}
_, err := suite.MsgServer().BondedOracle(sdk.WrapSDKContext(suite.ctx), normalMsg)
require.NoError(suite.T(), err)

oracleLastEventNonce := suite.Keeper().GetLastEventNonceByOracle(suite.ctx, suite.oracleAddrs[0])
require.EqualValues(suite.T(), 0, oracleLastEventNonce)

sender := helpers.GenerateAddress().String()
if suite.chainName == trontypes.ModuleName {
sender = trontypes.AddressFromHex(sender)
}

testMsgs := []struct {
name string
msg *types.MsgBridgeCallClaim
err error
errReason string
}{
{
name: "success",
msg: &types.MsgBridgeCallClaim{
DstChainId: "123",
EventNonce: oracleLastEventNonce + 1,
Sender: sender,
Asset: "123",
Receiver: helpers.GenerateAddress().String(),
To: helpers.GenerateAddress().String(),
Message: "123",
Value: sdkmath.NewInt(0),
BlockHeight: 1,
BridgerAddress: suite.bridgerAddrs[0].String(),
ChainName: suite.chainName,
},
err: nil,
errReason: "",
},
}

for _, testData := range testMsgs {
err = testData.msg.ValidateBasic()
require.NoError(suite.T(), err)
_, err = suite.MsgServer().BridgeCallClaim(sdk.WrapSDKContext(suite.ctx), testData.msg)
require.ErrorIs(suite.T(), err, testData.err, testData.name)
if err == nil {
continue
}
require.EqualValues(suite.T(), testData.errReason, err.Error(), testData.name)
}
}
3 changes: 3 additions & 0 deletions x/crosschain/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
&MsgBridgeTokenClaim{},

&MsgSendToFxClaim{},
&MsgBridgeCallClaim{},

&MsgSendToExternal{},
&MsgCancelSendToExternal{},
Expand All @@ -58,6 +59,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
(*ExternalClaim)(nil),
&MsgSendToExternalClaim{},
&MsgSendToFxClaim{},
&MsgBridgeCallClaim{},
&MsgBridgeTokenClaim{},
&MsgOracleSetUpdatedClaim{},
)
Expand Down Expand Up @@ -87,6 +89,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgBridgeTokenClaim{}, fmt.Sprintf("%s/%s", ModuleName, "MsgBridgeTokenClaim"), nil)

cdc.RegisterConcrete(&MsgSendToFxClaim{}, fmt.Sprintf("%s/%s", ModuleName, "MsgSendToFxClaim"), nil)
cdc.RegisterConcrete(&MsgBridgeCallClaim{}, fmt.Sprintf("%s/%s", ModuleName, "MsgBridgeCallClaim"), nil)

cdc.RegisterConcrete(&MsgSendToExternal{}, fmt.Sprintf("%s/%s", ModuleName, "MsgSendToExternal"), nil)
cdc.RegisterConcrete(&MsgCancelSendToExternal{}, fmt.Sprintf("%s/%s", ModuleName, "MsgCancelSendToExternal"), nil)
Expand Down
28 changes: 28 additions & 0 deletions x/crosschain/types/msg_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,34 @@ func (b MsgValidate) MsgSendToFxClaimValidate(m *MsgSendToFxClaim) (err error) {
return nil
}

func (b MsgValidate) MsgBridgeCallClaimValidate(m *MsgBridgeCallClaim) (err error) {
if _, err = sdk.AccAddressFromBech32(m.BridgerAddress); err != nil {
return errortypes.ErrInvalidAddress.Wrapf("invalid bridger address: %s", err)
}
if m.DstChainId == "" {
return errortypes.ErrInvalidRequest.Wrap("empty dst chain id")
}
if err = fxtypes.ValidateEthereumAddress(m.Sender); err != nil {
return errortypes.ErrInvalidAddress.Wrapf("invalid sender address: %s", err)
}
if err = fxtypes.ValidateEthereumAddress(m.To); err != nil {
return errortypes.ErrInvalidAddress.Wrapf("invalid to contract: %s", err)
}
if _, _, err := fxtypes.ParseAddress(m.Receiver); err != nil {
return errortypes.ErrInvalidAddress.Wrapf("invalid receiver address: %s", err)
}
if m.Value.IsNil() || m.Value.IsNegative() {
return errortypes.ErrInvalidRequest.Wrap("invalid value")
}
if m.EventNonce == 0 {
return errortypes.ErrInvalidRequest.Wrap("zero event nonce")
}
if m.BlockHeight == 0 {
return errortypes.ErrInvalidRequest.Wrap("zero block height")
}
return nil
}

func (b MsgValidate) MsgSendToExternalValidate(m *MsgSendToExternal) (err error) {
if _, err = sdk.AccAddressFromBech32(m.Sender); err != nil {
return errortypes.ErrInvalidAddress.Wrapf("invalid sender address: %s", err)
Expand Down
52 changes: 51 additions & 1 deletion x/crosschain/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const (

TypeMsgBridgeTokenClaim = "bridge_token_claim"

TypeMsgSendToFxClaim = "send_to_fx_claim"
TypeMsgSendToFxClaim = "send_to_fx_claim"
TypeMsgBridgeCallClaim = "bridge_call_claim"

TypeMsgSendToExternal = "send_to_external"
TypeMsgCancelSendToExternal = "cancel_send_to_external"
Expand Down Expand Up @@ -74,6 +75,8 @@ var (

_ sdk.Msg = &MsgSendToFxClaim{}
_ CrossChainMsg = &MsgSendToFxClaim{}
_ sdk.Msg = &MsgBridgeCallClaim{}
_ CrossChainMsg = &MsgBridgeCallClaim{}

_ sdk.Msg = &MsgSendToExternal{}
_ CrossChainMsg = &MsgSendToExternal{}
Expand Down Expand Up @@ -110,6 +113,7 @@ type MsgValidateBasic interface {
MsgSendToExternalClaimValidate(m *MsgSendToExternalClaim) (err error)

MsgSendToFxClaimValidate(m *MsgSendToFxClaim) (err error)
MsgBridgeCallClaimValidate(m *MsgBridgeCallClaim) (err error)
MsgSendToExternalValidate(m *MsgSendToExternal) (err error)

MsgCancelSendToExternalValidate(m *MsgCancelSendToExternal) (err error)
Expand Down Expand Up @@ -526,6 +530,7 @@ type ExternalClaim interface {

var (
_ ExternalClaim = &MsgSendToFxClaim{}
_ ExternalClaim = &MsgBridgeCallClaim{}
_ ExternalClaim = &MsgBridgeTokenClaim{}
_ ExternalClaim = &MsgSendToExternalClaim{}
_ ExternalClaim = &MsgOracleSetUpdatedClaim{}
Expand Down Expand Up @@ -582,6 +587,51 @@ func (m *MsgSendToFxClaim) ClaimHash() []byte {
return tmhash.Sum([]byte(path))
}

// MsgBridgeCallClaim

// GetType returns the type of the claim
func (m *MsgBridgeCallClaim) GetType() ClaimType {
return CLAIM_TYPE_SEND_TO_FX
}

// ValidateBasic performs stateless checks
func (m *MsgBridgeCallClaim) ValidateBasic() (err error) {
if err = ValidateModuleName(m.ChainName); err != nil {
return errortypes.ErrInvalidRequest.Wrap("invalid chain name")
}
if router, ok := msgValidateBasicRouter[m.ChainName]; !ok {
return errortypes.ErrInvalidRequest.Wrap("unrecognized cross chain name")
} else {
return router.MsgBridgeCallClaimValidate(m)
}
}

// GetSignBytes encodes the message for signing
func (m *MsgBridgeCallClaim) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(m))
}

func (m *MsgBridgeCallClaim) GetClaimer() sdk.AccAddress {
return sdk.MustAccAddressFromBech32(m.BridgerAddress)
}

// GetSigners defines whose signature is required
func (m *MsgBridgeCallClaim) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{sdk.MustAccAddressFromBech32(m.BridgerAddress)}
}

// Type should return the action
func (m *MsgBridgeCallClaim) Type() string { return TypeMsgBridgeCallClaim }

// Route should return the name of the module
func (m *MsgBridgeCallClaim) Route() string { return RouterKey }

// ClaimHash Hash implements BridgeSendToExternal.Hash
func (m *MsgBridgeCallClaim) ClaimHash() []byte {
path := fmt.Sprintf("%d/%d/%s/%s/%s/%s/%s/%s/%s/%d", m.BlockHeight, m.EventNonce, m.DstChainId, m.Sender, m.Receiver, m.To, m.Asset, m.Message, m.Value.String(), m.GasLimit)
return tmhash.Sum([]byte(path))
}

// MsgSendToExternalClaim

// GetType returns the claim type
Expand Down
Loading

0 comments on commit 9d00cdf

Please sign in to comment.