diff --git a/Makefile b/Makefile index fdd954145c..8504265a2a 100644 --- a/Makefile +++ b/Makefile @@ -145,6 +145,7 @@ mocks: $(MOCKS_DIR) mockgen -package mocks -destination tests/mocks/tendermint_tendermint_libs_log_DB.go github.com/tendermint/tendermint/libs/log Logger mockgen -source=x/stakingplus/expected_keepers.go -package testutil -destination x/stakingplus/testutil/expected_keepers_mocks.go mockgen -source=x/fswap/types/expected_keepers.go -package testutil -destination x/fswap/testutil/expected_keepers_mocks.go + mockgen -source=x/fbridge/types/expected_keepers.go -package testutil -destination x/fbridge/testutil/expected_keepers_mocks.go .PHONY: mocks $(MOCKS_DIR): diff --git a/proto/lbm/fbridge/v1/fbridge.proto b/proto/lbm/fbridge/v1/fbridge.proto index 58b1054ef3..6db9506e53 100644 --- a/proto/lbm/fbridge/v1/fbridge.proto +++ b/proto/lbm/fbridge/v1/fbridge.proto @@ -7,11 +7,11 @@ import "gogoproto/gogo.proto"; message Params { // ratio of how many operators' confirmations are needed to be valid. - Fraction operator_trust_level = 1; + Fraction operator_trust_level = 1 [(gogoproto.nullable) = false]; // ratio of how many guardians' confirmations are needed to be valid. - Fraction guardian_trust_level = 2; + Fraction guardian_trust_level = 2 [(gogoproto.nullable) = false]; // ratio of how many judges' confirmations are needed to be valid. - Fraction judge_trust_level = 3; + Fraction judge_trust_level = 3 [(gogoproto.nullable) = false]; // default timelock period for each provision (unix timestamp) uint64 timelock_period = 4; // default period of the proposal to update the role diff --git a/simapp/app.go b/simapp/app.go index 148cdbc50c..f6ce763cdd 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -65,6 +65,9 @@ import ( "github.com/Finschia/finschia-sdk/x/evidence" evidencekeeper "github.com/Finschia/finschia-sdk/x/evidence/keeper" evidencetypes "github.com/Finschia/finschia-sdk/x/evidence/types" + fbridgekeeper "github.com/Finschia/finschia-sdk/x/fbridge/keeper" + fbridgemodule "github.com/Finschia/finschia-sdk/x/fbridge/module" + fbridgetypes "github.com/Finschia/finschia-sdk/x/fbridge/types" "github.com/Finschia/finschia-sdk/x/feegrant" feegrantkeeper "github.com/Finschia/finschia-sdk/x/feegrant/keeper" feegrantmodule "github.com/Finschia/finschia-sdk/x/feegrant/module" @@ -142,6 +145,7 @@ var ( tokenmodule.AppModuleBasic{}, collectionmodule.AppModuleBasic{}, fswap.AppModuleBasic{}, + fbridgemodule.AppModuleBasic{}, ) // module account permissions @@ -154,11 +158,13 @@ var ( stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, + fbridgetypes.ModuleName: {authtypes.Burner}, } // module accounts that are allowed to receive tokens allowedReceivingModAcc = map[string]bool{ // govtypes.ModuleName: true, // TODO: uncomment it when authority is ready + fbridgetypes.ModuleName: true, } ) @@ -202,6 +208,7 @@ type SimApp struct { TokenKeeper tokenkeeper.Keeper CollectionKeeper collectionkeeper.Keeper FswapKeeper fswapkeeper.Keeper + FbridgeKeeper fbridgekeeper.Keeper // the module manager mm *module.Manager @@ -256,6 +263,7 @@ func NewSimApp( collection.StoreKey, authzkeeper.StoreKey, fswaptypes.StoreKey, + fbridgetypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) // NOTE: The testingkey is just mounted for testing purposes. Actual applications should @@ -362,6 +370,8 @@ func NewSimApp( fswapConfig := fswaptypes.DefaultConfig() app.FswapKeeper = fswapkeeper.NewKeeper(appCodec, keys[fswaptypes.StoreKey], app.AccountKeeper, app.BankKeeper, fswapConfig) + app.FbridgeKeeper = fbridgekeeper.NewKeeper(appCodec, keys[fbridgetypes.StoreKey], app.AccountKeeper, app.BankKeeper, "stake", authtypes.NewModuleAddress(govtypes.ModuleName).String()) + /**** Module Options ****/ // NOTE: we may consider parsing `appOpts` inside module constructors. For the moment @@ -394,6 +404,7 @@ func NewSimApp( collectionmodule.NewAppModule(appCodec, app.CollectionKeeper), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), fswap.NewAppModule(appCodec, app.FswapKeeper, app.AccountKeeper, app.BankKeeper), + fbridgemodule.NewAppModule(appCodec, app.FbridgeKeeper), ) // During begin block slashing happens after distr.BeginBlocker so that @@ -422,6 +433,7 @@ func NewSimApp( token.ModuleName, collection.ModuleName, fswaptypes.ModuleName, + fbridgetypes.ModuleName, ) app.mm.SetOrderEndBlockers( crisistypes.ModuleName, @@ -444,6 +456,7 @@ func NewSimApp( token.ModuleName, collection.ModuleName, fswaptypes.ModuleName, + fbridgetypes.ModuleName, ) // NOTE: The genutils module must occur after staking so that pools are @@ -472,6 +485,7 @@ func NewSimApp( token.ModuleName, collection.ModuleName, fswaptypes.ModuleName, + fbridgetypes.ModuleName, ) // Uncomment if you want to set a custom migration order here. diff --git a/x/fbridge/keeper/genesis.go b/x/fbridge/keeper/genesis.go index 42ffc544d4..e979d44970 100644 --- a/x/fbridge/keeper/genesis.go +++ b/x/fbridge/keeper/genesis.go @@ -6,9 +6,16 @@ import ( ) func (k Keeper) InitGenesis(ctx sdk.Context, gs *types.GenesisState) error { + k.setNextSequence(ctx, gs.SendingState.NextSeq) + return nil } func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { - return nil + + return &types.GenesisState{ + SendingState: types.SendingState{ + NextSeq: k.GetNextSequence(ctx), + }, + } } diff --git a/x/fbridge/keeper/grpc_query.go b/x/fbridge/keeper/grpc_query.go index c157e03e30..4fbb4058cd 100644 --- a/x/fbridge/keeper/grpc_query.go +++ b/x/fbridge/keeper/grpc_query.go @@ -2,8 +2,10 @@ package keeper import ( "context" - + sdk "github.com/Finschia/finschia-sdk/types" "github.com/Finschia/finschia-sdk/x/fbridge/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) var _ types.QueryServer = Keeper{} @@ -12,8 +14,15 @@ func (k Keeper) Params(ctx context.Context, request *types.QueryParamsRequest) ( panic("implement me") } -func (k Keeper) NextSeqSend(ctx context.Context, request *types.QueryNextSeqSendRequest) (*types.QueryNextSeqSendResponse, error) { - panic("implement me") +func (k Keeper) NextSeqSend(goCtx context.Context, req *types.QueryNextSeqSendRequest) (*types.QueryNextSeqSendResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + seq := k.GetNextSequence(ctx) + + return &types.QueryNextSeqSendResponse{Seq: seq}, nil } func (k Keeper) GreatestSeqByOperator(ctx context.Context, request *types.QueryGreatestSeqByOperatorRequest) (*types.QueryGreatestSeqByOperatorResponse, error) { diff --git a/x/fbridge/keeper/keeper.go b/x/fbridge/keeper/keeper.go index d22a739529..53d392bad6 100644 --- a/x/fbridge/keeper/keeper.go +++ b/x/fbridge/keeper/keeper.go @@ -1,3 +1,61 @@ package keeper -type Keeper struct{} +import ( + "errors" + + "github.com/tendermint/tendermint/libs/log" + + "github.com/Finschia/finschia-sdk/codec" + sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/x/fbridge/types" + "strings" +) + +type Keeper struct { + storeKey sdk.StoreKey + cdc codec.BinaryCodec + authKeeper types.AccountKeeper + bankKeeper types.BankKeeper + + // the target denom for the bridge + targetDenom string + + // the authority address that can execute privileged operations only if the guardian group is not set + // - UpdateParams + // - SuggestRole + authority string +} + +func NewKeeper( + cdc codec.BinaryCodec, + key sdk.StoreKey, + authKeeper types.AccountKeeper, + bankKeeper types.BankKeeper, + targetDenom string, + authority string, +) Keeper { + if addr := authKeeper.GetModuleAddress(types.ModuleName); addr == nil { + panic(errors.New("fbridge module account has not been set")) + } + + if strings.TrimSpace(authority) == "" { + panic(errors.New("authority address cannot be empty")) + } + + return Keeper{ + storeKey: key, + cdc: cdc, + authKeeper: authKeeper, + bankKeeper: bankKeeper, + targetDenom: targetDenom, + authority: authority, + } +} + +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", "x/"+types.ModuleName) +} + +func (k Keeper) GetAuthority() string { + return k.authority +} diff --git a/x/fbridge/keeper/msg_server.go b/x/fbridge/keeper/msg_server.go index 58d79ed1b1..255fadb877 100644 --- a/x/fbridge/keeper/msg_server.go +++ b/x/fbridge/keeper/msg_server.go @@ -2,6 +2,8 @@ package keeper import ( "context" + sdk "github.com/Finschia/finschia-sdk/types" + sdkerrors "github.com/Finschia/finschia-sdk/types/errors" "github.com/Finschia/finschia-sdk/x/fbridge/types" ) @@ -16,43 +18,68 @@ func NewMsgServer(k Keeper) types.MsgServer { return &msgServer{k} } -func (m msgServer) Transfer(ctx context.Context, transfer *types.MsgTransfer) (*types.MsgTransferResponse, error) { - panic("implement me") +func (m msgServer) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + from, err := sdk.AccAddressFromBech32(msg.Sender) + if err != nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address (%s)", err) + } + + if !IsValidEthereumAddress(msg.Receiver) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid recipient address (%s)", msg.Receiver) + } + + seq, err := m.handleBridgeTransfer(ctx, from, msg.Amount) + if err != nil { + return nil, err + } + + if err := ctx.EventManager().EmitTypedEvent(&types.EventTransfer{ + Sender: msg.Sender, + Receiver: msg.Receiver, + Amount: msg.Amount.String(), + Seq: seq, + }); err != nil { + panic(err) + } + + return &types.MsgTransferResponse{}, nil } -func (m msgServer) Provision(ctx context.Context, provision *types.MsgProvision) (*types.MsgProvisionResponse, error) { +func (m msgServer) Provision(ctx context.Context, msg *types.MsgProvision) (*types.MsgProvisionResponse, error) { panic("implement me") } -func (m msgServer) HoldTransfer(ctx context.Context, transfer *types.MsgHoldTransfer) (*types.MsgHoldTransferResponse, error) { +func (m msgServer) HoldTransfer(ctx context.Context, msg *types.MsgHoldTransfer) (*types.MsgHoldTransferResponse, error) { panic("implement me") } -func (m msgServer) ReleaseTransfer(ctx context.Context, transfer *types.MsgReleaseTransfer) (*types.MsgReleaseTransferResponse, error) { +func (m msgServer) ReleaseTransfer(ctx context.Context, msg *types.MsgReleaseTransfer) (*types.MsgReleaseTransferResponse, error) { panic("implement me") } -func (m msgServer) RemoveProvision(ctx context.Context, provision *types.MsgRemoveProvision) (*types.MsgRemoveProvisionResponse, error) { +func (m msgServer) RemoveProvision(ctx context.Context, msg *types.MsgRemoveProvision) (*types.MsgRemoveProvisionResponse, error) { panic("implement me") } -func (m msgServer) ClaimBatch(ctx context.Context, batch *types.MsgClaimBatch) (*types.MsgClaimBatchResponse, error) { +func (m msgServer) ClaimBatch(ctx context.Context, msg *types.MsgClaimBatch) (*types.MsgClaimBatchResponse, error) { panic("implement me") } -func (m msgServer) Claim(ctx context.Context, claim *types.MsgClaim) (*types.MsgClaimResponse, error) { +func (m msgServer) Claim(ctx context.Context, msg *types.MsgClaim) (*types.MsgClaimResponse, error) { panic("implement me") } -func (m msgServer) SuggestRole(ctx context.Context, role *types.MsgSuggestRole) (*types.MsgSuggestRoleResponse, error) { +func (m msgServer) SuggestRole(ctx context.Context, msg *types.MsgSuggestRole) (*types.MsgSuggestRoleResponse, error) { panic("implement me") } -func (m msgServer) AddVoteForRole(ctx context.Context, role *types.MsgAddVoteForRole) (*types.MsgAddVoteForRoleResponse, error) { +func (m msgServer) AddVoteForRole(ctx context.Context, msg *types.MsgAddVoteForRole) (*types.MsgAddVoteForRoleResponse, error) { panic("implement me") } -func (m msgServer) Halt(ctx context.Context, halt *types.MsgHalt) (*types.MsgHaltResponse, error) { +func (m msgServer) Halt(ctx context.Context, msg *types.MsgHalt) (*types.MsgHaltResponse, error) { panic("implement me") } diff --git a/x/fbridge/keeper/transfer.go b/x/fbridge/keeper/transfer.go new file mode 100644 index 0000000000..318704975f --- /dev/null +++ b/x/fbridge/keeper/transfer.go @@ -0,0 +1,78 @@ +package keeper + +import ( + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "regexp" + "strconv" + "strings" + + "golang.org/x/crypto/sha3" + + sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/x/fbridge/types" +) + +func (k Keeper) handleBridgeTransfer(ctx sdk.Context, sender sdk.AccAddress, amount sdk.Int) (uint64, error) { + token := sdk.Coins{sdk.Coin{Denom: k.targetDenom, Amount: amount}} + if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, token); err != nil { + panic(err) + } + + if err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, token); err != nil { + panic(fmt.Errorf("cannot burn coins after a successful send to a module account: %v", err)) + } + + nextSeq := k.GetNextSequence(ctx) + 1 + k.setNextSequence(ctx, nextSeq) + + return nextSeq, nil +} + +func (k Keeper) GetNextSequence(ctx sdk.Context) uint64 { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.KeyNextSeqSend) + if len(bz) == 0 { + panic(errors.New("sending next sequence should have been set")) + } + + return binary.BigEndian.Uint64(bz) +} + +func (k Keeper) setNextSequence(ctx sdk.Context, seq uint64) { + store := ctx.KVStore(k.storeKey) + bz := make([]byte, 8) + binary.BigEndian.PutUint64(bz, seq) + store.Set(types.KeyNextSeqSend, bz) +} + +func IsValidEthereumAddress(address string) bool { + matched, err := regexp.MatchString(`^0x[a-fA-F0-9]{40}$`, address) + if err != nil || !matched { + return false + } + + address = address[2:] + addressLower := strings.ToLower(address) + + hasher := sha3.NewLegacyKeccak256() + hasher.Write([]byte(addressLower)) + addressHash := hex.EncodeToString(hasher.Sum(nil)) + + checksumAddress := "" + for i := 0; i < len(addressLower); i++ { + c, err := strconv.ParseUint(string(addressHash[i]), 16, 4) + if err != nil { + panic(err) + } + if c < 8 { + checksumAddress += string(addressLower[i]) + } else { + checksumAddress += strings.ToUpper(string(addressLower[i])) + } + } + + return address == checksumAddress +} diff --git a/x/fbridge/keeper/transfer_test.go b/x/fbridge/keeper/transfer_test.go new file mode 100644 index 0000000000..0d52f31afa --- /dev/null +++ b/x/fbridge/keeper/transfer_test.go @@ -0,0 +1,60 @@ +package keeper + +import ( + "encoding/binary" + authtypes "github.com/Finschia/finschia-sdk/x/auth/types" + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/x/fbridge/testutil" + "github.com/Finschia/finschia-sdk/x/fbridge/types" +) + +func TestHandleBridgeTransfer(t *testing.T) { + key, ctx, encCfg, authKeeper, bankKeeper := testutil.PrepareFbridgeTest(t) + + sender := sdk.AccAddress("test") + amt := sdk.NewInt(1000000) + denom := "stake" + token := sdk.Coins{sdk.Coin{Denom: denom, Amount: amt}} + + bridge := authtypes.NewEmptyModuleAccount("bridge") + authKeeper.EXPECT().GetModuleAddress(types.ModuleName).Return(bridge.GetAddress()).AnyTimes() + authKeeper.EXPECT().GetModuleAccount(ctx, types.ModuleName).Return(bridge).AnyTimes() + bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, token).Return(nil) + bankKeeper.EXPECT().BurnCoins(ctx, types.ModuleName, token).Return(nil) + + k := NewKeeper(encCfg.Codec, key, authKeeper, bankKeeper, denom, "gov") + beforeSeq := uint64(2) + bz := make([]byte, 8) + binary.BigEndian.PutUint64(bz, beforeSeq) + ctx.KVStore(key).Set(types.KeyNextSeqSend, bz) + + afterSeq, err := k.handleBridgeTransfer(ctx, sender, amt) + require.NoError(t, err) + require.Equal(t, beforeSeq+1, afterSeq) +} + +func TestIsValidEthereumAddress(t *testing.T) { + tcs := map[string]struct { + valid bool + address string + }{ + "valid": { + valid: true, + address: "0xf7bAc63fc7CEaCf0589F25454Ecf5C2ce904997c", + }, + "invalid": { + valid: false, + address: "0xf7bAc63fc7CEaCf0589F25454Ecf5C2ce905997c", + }, + } + + for name, tc := range tcs { + t.Run(name, func(t *testing.T) { + require.Equal(t, tc.valid, IsValidEthereumAddress(tc.address)) + }) + } +} diff --git a/x/fbridge/module/module.go b/x/fbridge/module/module.go index e7f7cfc28c..4df91c701f 100644 --- a/x/fbridge/module/module.go +++ b/x/fbridge/module/module.go @@ -7,6 +7,7 @@ import ( "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" sdkclient "github.com/Finschia/finschia-sdk/client" diff --git a/x/fbridge/testutil/expected_keepers_mocks.go b/x/fbridge/testutil/expected_keepers_mocks.go new file mode 100644 index 0000000000..afd91382a1 --- /dev/null +++ b/x/fbridge/testutil/expected_keepers_mocks.go @@ -0,0 +1,143 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: x/fbridge/types/expected_keepers.go + +// Package testutil is a generated GoMock package. +package testutil + +import ( + reflect "reflect" + + types "github.com/Finschia/finschia-sdk/types" + types0 "github.com/Finschia/finschia-sdk/x/auth/types" + gomock "github.com/golang/mock/gomock" +) + +// MockAccountKeeper is a mock of AccountKeeper interface. +type MockAccountKeeper struct { + ctrl *gomock.Controller + recorder *MockAccountKeeperMockRecorder +} + +// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper. +type MockAccountKeeperMockRecorder struct { + mock *MockAccountKeeper +} + +// NewMockAccountKeeper creates a new mock instance. +func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper { + mock := &MockAccountKeeper{ctrl: ctrl} + mock.recorder = &MockAccountKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder { + return m.recorder +} + +// GetModuleAccount mocks base method. +func (m *MockAccountKeeper) GetModuleAccount(ctx types.Context, moduleName string) types0.ModuleAccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetModuleAccount", ctx, moduleName) + ret0, _ := ret[0].(types0.ModuleAccountI) + return ret0 +} + +// GetModuleAccount indicates an expected call of GetModuleAccount. +func (mr *MockAccountKeeperMockRecorder) GetModuleAccount(ctx, moduleName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAccount), ctx, moduleName) +} + +// GetModuleAddress mocks base method. +func (m *MockAccountKeeper) GetModuleAddress(moduleName string) types.AccAddress { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetModuleAddress", moduleName) + ret0, _ := ret[0].(types.AccAddress) + return ret0 +} + +// GetModuleAddress indicates an expected call of GetModuleAddress. +func (mr *MockAccountKeeperMockRecorder) GetModuleAddress(moduleName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAddress", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAddress), moduleName) +} + +// MockBankKeeper is a mock of BankKeeper interface. +type MockBankKeeper struct { + ctrl *gomock.Controller + recorder *MockBankKeeperMockRecorder +} + +// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. +type MockBankKeeperMockRecorder struct { + mock *MockBankKeeper +} + +// NewMockBankKeeper creates a new mock instance. +func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper { + mock := &MockBankKeeper{ctrl: ctrl} + mock.recorder = &MockBankKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { + return m.recorder +} + +// BurnCoins mocks base method. +func (m *MockBankKeeper) BurnCoins(ctx types.Context, moduleName string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BurnCoins", ctx, moduleName, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// BurnCoins indicates an expected call of BurnCoins. +func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, moduleName, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*MockBankKeeper)(nil).BurnCoins), ctx, moduleName, amt) +} + +// GetBalance mocks base method. +func (m *MockBankKeeper) GetBalance(ctx types.Context, addr types.AccAddress, denom string) types.Coin { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBalance", ctx, addr, denom) + ret0, _ := ret[0].(types.Coin) + return ret0 +} + +// GetBalance indicates an expected call of GetBalance. +func (mr *MockBankKeeperMockRecorder) GetBalance(ctx, addr, denom interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*MockBankKeeper)(nil).GetBalance), ctx, addr, denom) +} + +// IsSendEnabledCoin mocks base method. +func (m *MockBankKeeper) IsSendEnabledCoin(ctx types.Context, coin types.Coin) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSendEnabledCoin", ctx, coin) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSendEnabledCoin indicates an expected call of IsSendEnabledCoin. +func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoin(ctx, coin interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoin", reflect.TypeOf((*MockBankKeeper)(nil).IsSendEnabledCoin), ctx, coin) +} + +// SendCoinsFromAccountToModule mocks base method. +func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx types.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) +} diff --git a/x/fbridge/testutil/setup.go b/x/fbridge/testutil/setup.go new file mode 100644 index 0000000000..5fb55e38a9 --- /dev/null +++ b/x/fbridge/testutil/setup.go @@ -0,0 +1,74 @@ +package testutil + +import ( + "github.com/golang/mock/gomock" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + + "github.com/Finschia/finschia-sdk/client" + "github.com/Finschia/finschia-sdk/codec" + codectypes "github.com/Finschia/finschia-sdk/codec/types" + "github.com/Finschia/finschia-sdk/std" + "github.com/Finschia/finschia-sdk/store" + storetypes "github.com/Finschia/finschia-sdk/store/types" + sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/x/auth/tx" + "github.com/Finschia/finschia-sdk/x/fbridge/types" +) + +func DefaultContextWithDB(tb testing.TB, key, tkey storetypes.StoreKey) sdk.Context { + tb.Helper() + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, storetypes.StoreTypeIAVL, db) + cms.MountStoreWithDB(tkey, storetypes.StoreTypeTransient, db) + err := cms.LoadLatestVersion() + assert.NoError(tb, err) + + ctx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()) + + return ctx +} + +type TestEncodingConfig struct { + InterfaceRegistry codectypes.InterfaceRegistry + Codec codec.Codec + TxConfig client.TxConfig + Amino *codec.LegacyAmino +} + +func MakeTestEncodingConfig() TestEncodingConfig { + cdc := codec.NewLegacyAmino() + interfaceRegistry := codectypes.NewInterfaceRegistry() + marshaler := codec.NewProtoCodec(interfaceRegistry) + + encCfg := TestEncodingConfig{ + InterfaceRegistry: interfaceRegistry, + Codec: marshaler, + TxConfig: tx.NewTxConfig(marshaler, tx.DefaultSignModes), + Amino: cdc, + } + + std.RegisterLegacyAminoCodec(encCfg.Amino) + std.RegisterInterfaces(encCfg.InterfaceRegistry) + types.RegisterLegacyAminoCodec(encCfg.Amino) + types.RegisterInterfaces(encCfg.InterfaceRegistry) + return encCfg +} + +func PrepareFbridgeTest(t testing.TB) (*sdk.KVStoreKey, sdk.Context, TestEncodingConfig, *MockAccountKeeper, *MockBankKeeper) { + ctrl := gomock.NewController(t) + key := storetypes.NewKVStoreKey(types.StoreKey) + ctx := DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test")) + encCfg := MakeTestEncodingConfig() + + authKeeper := NewMockAccountKeeper(ctrl) + bankKeeper := NewMockBankKeeper(ctrl) + + return key, ctx, encCfg, authKeeper, bankKeeper +} diff --git a/x/fbridge/types/expected_keepers.go b/x/fbridge/types/expected_keepers.go index ab1254f4c2..12e633070a 100644 --- a/x/fbridge/types/expected_keepers.go +++ b/x/fbridge/types/expected_keepers.go @@ -1 +1,18 @@ package types + +import ( + sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/x/auth/types" +) + +type AccountKeeper interface { + GetModuleAddress(moduleName string) sdk.AccAddress + GetModuleAccount(ctx sdk.Context, moduleName string) types.ModuleAccountI +} + +type BankKeeper interface { + GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool + BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error +} diff --git a/x/fbridge/types/fbridge.pb.go b/x/fbridge/types/fbridge.pb.go index 9ca2c7a57a..a9b8197a74 100644 --- a/x/fbridge/types/fbridge.pb.go +++ b/x/fbridge/types/fbridge.pb.go @@ -58,11 +58,11 @@ func (Role) EnumDescriptor() ([]byte, []int) { type Params struct { // ratio of how many operators' confirmations are needed to be valid. - OperatorTrustLevel *Fraction `protobuf:"bytes,1,opt,name=operator_trust_level,json=operatorTrustLevel,proto3" json:"operator_trust_level,omitempty"` + OperatorTrustLevel Fraction `protobuf:"bytes,1,opt,name=operator_trust_level,json=operatorTrustLevel,proto3" json:"operator_trust_level"` // ratio of how many guardians' confirmations are needed to be valid. - GuardianTrustLevel *Fraction `protobuf:"bytes,2,opt,name=guardian_trust_level,json=guardianTrustLevel,proto3" json:"guardian_trust_level,omitempty"` + GuardianTrustLevel Fraction `protobuf:"bytes,2,opt,name=guardian_trust_level,json=guardianTrustLevel,proto3" json:"guardian_trust_level"` // ratio of how many judges' confirmations are needed to be valid. - JudgeTrustLevel *Fraction `protobuf:"bytes,3,opt,name=judge_trust_level,json=judgeTrustLevel,proto3" json:"judge_trust_level,omitempty"` + JudgeTrustLevel Fraction `protobuf:"bytes,3,opt,name=judge_trust_level,json=judgeTrustLevel,proto3" json:"judge_trust_level"` // default timelock period for each provision (unix timestamp) TimelockPeriod uint64 `protobuf:"varint,4,opt,name=timelock_period,json=timelockPeriod,proto3" json:"timelock_period,omitempty"` // default period of the proposal to update the role @@ -102,25 +102,25 @@ func (m *Params) XXX_DiscardUnknown() { var xxx_messageInfo_Params proto.InternalMessageInfo -func (m *Params) GetOperatorTrustLevel() *Fraction { +func (m *Params) GetOperatorTrustLevel() Fraction { if m != nil { return m.OperatorTrustLevel } - return nil + return Fraction{} } -func (m *Params) GetGuardianTrustLevel() *Fraction { +func (m *Params) GetGuardianTrustLevel() Fraction { if m != nil { return m.GuardianTrustLevel } - return nil + return Fraction{} } -func (m *Params) GetJudgeTrustLevel() *Fraction { +func (m *Params) GetJudgeTrustLevel() Fraction { if m != nil { return m.JudgeTrustLevel } - return nil + return Fraction{} } func (m *Params) GetTimelockPeriod() uint64 { @@ -418,46 +418,46 @@ func init() { func init() { proto.RegisterFile("lbm/fbridge/v1/fbridge.proto", fileDescriptor_62374d75fc6aa1ba) } var fileDescriptor_62374d75fc6aa1ba = []byte{ - // 610 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x54, 0x41, 0x4f, 0xdb, 0x30, - 0x14, 0x6e, 0x4a, 0xa9, 0x9a, 0x57, 0x68, 0x3b, 0x0b, 0x4d, 0x08, 0xb1, 0xc2, 0x2a, 0x4d, 0x43, - 0x48, 0x6b, 0x07, 0xbb, 0x4f, 0x2a, 0xb4, 0xa0, 0x56, 0x13, 0x54, 0x06, 0x2e, 0xbb, 0x44, 0x6e, - 0x62, 0x82, 0x47, 0x62, 0x67, 0xb6, 0x53, 0xb1, 0xfd, 0x8a, 0xdd, 0x77, 0xda, 0xbf, 0xd8, 0x4f, - 0xe0, 0xc8, 0x71, 0xda, 0x01, 0x4d, 0xf0, 0x47, 0x26, 0x3b, 0x49, 0x07, 0xbb, 0x70, 0x7b, 0xef, - 0xf3, 0xf7, 0x3e, 0xbf, 0xf7, 0xf9, 0x25, 0xb0, 0x1e, 0x4d, 0xe3, 0xde, 0xf9, 0x54, 0xb2, 0x20, - 0xa4, 0xbd, 0xd9, 0x4e, 0x11, 0x76, 0x13, 0x29, 0xb4, 0x40, 0x8d, 0x68, 0x1a, 0x77, 0x0b, 0x68, - 0xb6, 0xb3, 0xb6, 0x12, 0x8a, 0x50, 0xd8, 0xa3, 0x9e, 0x89, 0x32, 0x56, 0xe7, 0x67, 0x19, 0xaa, - 0x13, 0x22, 0x49, 0xac, 0xd0, 0x18, 0x56, 0x44, 0x42, 0x25, 0xd1, 0x42, 0x7a, 0x5a, 0xa6, 0x4a, - 0x7b, 0x11, 0x9d, 0xd1, 0x68, 0xd5, 0xd9, 0x74, 0xb6, 0xea, 0xbb, 0xab, 0xdd, 0xc7, 0x7a, 0xdd, - 0x03, 0x49, 0x7c, 0xcd, 0x04, 0xc7, 0xa8, 0xa8, 0x3a, 0x35, 0x45, 0x1f, 0x4c, 0x8d, 0xd1, 0x0a, - 0x53, 0x22, 0x03, 0x46, 0xf8, 0x23, 0xad, 0xf2, 0x53, 0x5a, 0x45, 0xd5, 0x03, 0xad, 0x01, 0x3c, - 0xfb, 0x94, 0x06, 0x21, 0x7d, 0x24, 0xb4, 0xf0, 0x84, 0x50, 0xd3, 0x96, 0x3c, 0x50, 0x79, 0x0d, - 0x4d, 0xcd, 0x62, 0x1a, 0x09, 0xff, 0xd2, 0x4b, 0xa8, 0x64, 0x22, 0x58, 0xad, 0x6c, 0x3a, 0x5b, - 0x15, 0xdc, 0x28, 0xe0, 0x89, 0x45, 0x0d, 0x31, 0x91, 0x22, 0x11, 0x8a, 0x44, 0x05, 0x71, 0x31, - 0x23, 0x16, 0x70, 0x46, 0xec, 0xfc, 0x70, 0x60, 0x79, 0x22, 0xc5, 0x8c, 0x29, 0x26, 0xf8, 0x80, - 0x68, 0x82, 0x5a, 0xb0, 0xa0, 0xe8, 0x67, 0x6b, 0x58, 0x05, 0x9b, 0x10, 0x8d, 0xa1, 0x4a, 0x62, - 0x91, 0x72, 0x6d, 0x27, 0x77, 0xf7, 0x76, 0xaf, 0x6f, 0x37, 0x4a, 0xbf, 0x6f, 0x37, 0xb6, 0x43, - 0xa6, 0x2f, 0xd2, 0x69, 0xd7, 0x17, 0x71, 0xef, 0x80, 0x71, 0xe5, 0x5f, 0x30, 0xd2, 0x3b, 0xcf, - 0x83, 0x37, 0x2a, 0xb8, 0xec, 0xe9, 0x2f, 0x09, 0x55, 0xdd, 0x11, 0xd7, 0x38, 0x57, 0x40, 0xcf, - 0xa1, 0xaa, 0x28, 0x0f, 0xa8, 0xb4, 0xc3, 0xbb, 0x38, 0xcf, 0xd0, 0x1a, 0xd4, 0x24, 0xf5, 0x29, - 0x9b, 0x51, 0x69, 0x47, 0x72, 0xf1, 0x3c, 0xef, 0x7c, 0x85, 0xe6, 0xbc, 0xc5, 0x13, 0x4d, 0x74, - 0xaa, 0xd0, 0x4b, 0x58, 0x9a, 0x1b, 0x41, 0x79, 0x90, 0x77, 0x5b, 0x2f, 0xb0, 0x21, 0x0f, 0xd0, - 0x2b, 0x68, 0xf8, 0x82, 0x9f, 0x33, 0x19, 0x7b, 0xbe, 0xb9, 0x5a, 0xd9, 0xee, 0x17, 0xf1, 0x72, - 0x8e, 0xee, 0x5b, 0x10, 0xbd, 0x00, 0x60, 0xca, 0xf3, 0x23, 0xc2, 0x62, 0x1a, 0xd8, 0xa6, 0x6a, - 0xd8, 0x65, 0x6a, 0x3f, 0x03, 0x3a, 0x63, 0xa8, 0x15, 0xcf, 0x81, 0xd6, 0xc1, 0xe5, 0x69, 0x9c, - 0xad, 0x49, 0x7e, 0xe3, 0x3f, 0x00, 0x6d, 0x42, 0x3d, 0xa0, 0x5c, 0xc4, 0x8c, 0xdb, 0xf3, 0x72, - 0xd6, 0xd1, 0x03, 0xa8, 0xf3, 0xdd, 0x81, 0x25, 0x2c, 0x22, 0x3a, 0xc9, 0x9f, 0x00, 0x35, 0xa0, - 0xcc, 0x8a, 0xde, 0xcb, 0x2c, 0x30, 0x26, 0x64, 0xcf, 0x43, 0xb3, 0x7a, 0x17, 0xcf, 0x73, 0x63, - 0x9c, 0x26, 0x32, 0xa4, 0xba, 0x30, 0x2e, 0xcb, 0xd0, 0x16, 0x54, 0xa4, 0x88, 0xa8, 0x35, 0xad, - 0xb1, 0xbb, 0xf2, 0xff, 0x2e, 0x99, 0xfb, 0xb0, 0x65, 0x98, 0x49, 0xe9, 0x55, 0xc2, 0x24, 0x0d, - 0x3c, 0xa2, 0xf3, 0x75, 0x70, 0x73, 0xa4, 0xaf, 0xb7, 0xdf, 0x43, 0xc5, 0x90, 0x51, 0x13, 0xea, - 0x67, 0x47, 0x27, 0x93, 0xe1, 0xfe, 0xe8, 0x60, 0x34, 0x1c, 0xb4, 0x4a, 0x68, 0x09, 0x6a, 0x87, - 0x67, 0x7d, 0x3c, 0x18, 0xf5, 0x8f, 0x5a, 0x8e, 0xc9, 0x8e, 0x27, 0x43, 0xdc, 0x3f, 0x3d, 0xc6, - 0xad, 0x32, 0x72, 0x61, 0x71, 0x7c, 0x36, 0x38, 0x1c, 0xb6, 0x16, 0xf6, 0xc6, 0xd7, 0x77, 0x6d, - 0xe7, 0xe6, 0xae, 0xed, 0xfc, 0xb9, 0x6b, 0x3b, 0xdf, 0xee, 0xdb, 0xa5, 0x9b, 0xfb, 0x76, 0xe9, - 0xd7, 0x7d, 0xbb, 0xf4, 0xf1, 0xed, 0x93, 0x7b, 0x72, 0x35, 0xff, 0x03, 0xd8, 0x8d, 0x99, 0x56, - 0xed, 0x77, 0xfd, 0xee, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x61, 0x80, 0x22, 0x79, 0x1d, 0x04, - 0x00, 0x00, + // 614 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x41, 0x4f, 0x1b, 0x3d, + 0x10, 0xcd, 0x86, 0x10, 0x65, 0x27, 0x90, 0xe4, 0xb3, 0xd0, 0x27, 0x84, 0x68, 0xa0, 0x91, 0xaa, + 0x22, 0xa4, 0x26, 0x85, 0xde, 0x2b, 0x05, 0x12, 0x50, 0xa2, 0x0a, 0x56, 0x06, 0x2e, 0xbd, 0x44, + 0xce, 0xae, 0x59, 0x5c, 0x76, 0xed, 0xad, 0xed, 0x8d, 0x68, 0x7f, 0x45, 0xef, 0x3d, 0xf5, 0xdf, + 0xa0, 0x9e, 0x38, 0x56, 0x3d, 0xa0, 0x0a, 0xfe, 0x48, 0x65, 0xef, 0x6e, 0x0a, 0xbd, 0x94, 0xdb, + 0xcc, 0xdb, 0x37, 0xcf, 0xcf, 0xcf, 0x93, 0xc0, 0x7a, 0x34, 0x8d, 0x7b, 0xe7, 0x53, 0xc9, 0x82, + 0x90, 0xf6, 0x66, 0x3b, 0x45, 0xd9, 0x4d, 0xa4, 0xd0, 0x02, 0x35, 0xa2, 0x69, 0xdc, 0x2d, 0xa0, + 0xd9, 0xce, 0xda, 0x4a, 0x28, 0x42, 0x61, 0x3f, 0xf5, 0x4c, 0x95, 0xb1, 0x3a, 0xdf, 0xcb, 0x50, + 0xf5, 0x88, 0x24, 0xb1, 0x42, 0x1e, 0xac, 0x88, 0x84, 0x4a, 0xa2, 0x85, 0x9c, 0x68, 0x99, 0x2a, + 0x3d, 0x89, 0xe8, 0x8c, 0x46, 0xab, 0xce, 0xa6, 0xb3, 0x55, 0xdf, 0x5d, 0xed, 0x3e, 0xd6, 0xeb, + 0x1e, 0x48, 0xe2, 0x6b, 0x26, 0xf8, 0x5e, 0xe5, 0xfa, 0x76, 0xa3, 0x84, 0x51, 0x31, 0x7b, 0x6a, + 0x46, 0xdf, 0x99, 0x49, 0xa3, 0x18, 0xa6, 0x44, 0x06, 0x8c, 0xf0, 0x47, 0x8a, 0xe5, 0xa7, 0x29, + 0x16, 0xb3, 0x0f, 0x14, 0xc7, 0xf0, 0xdf, 0x87, 0x34, 0x08, 0xe9, 0x23, 0xb9, 0x85, 0x27, 0xc9, + 0x35, 0xed, 0xe0, 0x03, 0xad, 0x97, 0xd0, 0xd4, 0x2c, 0xa6, 0x91, 0xf0, 0x2f, 0x27, 0x09, 0x95, + 0x4c, 0x04, 0xab, 0x95, 0x4d, 0x67, 0xab, 0x82, 0x1b, 0x05, 0xec, 0x59, 0xd4, 0x10, 0x13, 0x29, + 0x12, 0xa1, 0x48, 0x54, 0x10, 0x17, 0x33, 0x62, 0x01, 0x67, 0xc4, 0xce, 0x37, 0x07, 0x96, 0x3d, + 0x29, 0x66, 0x4c, 0x31, 0xc1, 0x07, 0x44, 0x13, 0xd4, 0x82, 0x05, 0x45, 0x3f, 0xda, 0x08, 0x2b, + 0xd8, 0x94, 0x68, 0x0c, 0x55, 0x12, 0x8b, 0x94, 0x6b, 0x9b, 0x82, 0xbb, 0xb7, 0x6b, 0xcc, 0xfd, + 0xbc, 0xdd, 0xd8, 0x0e, 0x99, 0xbe, 0x48, 0xa7, 0x5d, 0x5f, 0xc4, 0xbd, 0x03, 0xc6, 0x95, 0x7f, + 0xc1, 0x48, 0xef, 0x3c, 0x2f, 0x5e, 0xa9, 0xe0, 0xb2, 0xa7, 0x3f, 0x25, 0x54, 0x75, 0x47, 0x5c, + 0xe3, 0x5c, 0x01, 0xfd, 0x0f, 0x55, 0x45, 0x79, 0x40, 0xa5, 0x8d, 0xc0, 0xc5, 0x79, 0x87, 0xd6, + 0xa0, 0x26, 0xa9, 0x4f, 0xd9, 0x8c, 0x4a, 0x7b, 0x25, 0x17, 0xcf, 0xfb, 0xce, 0x67, 0x68, 0xce, + 0x2d, 0x9e, 0x68, 0xa2, 0x53, 0x85, 0x9e, 0xc3, 0xd2, 0x3c, 0x08, 0xca, 0x83, 0xdc, 0x6d, 0xbd, + 0xc0, 0x86, 0x3c, 0x40, 0x2f, 0xa0, 0xe1, 0x0b, 0x7e, 0xce, 0x64, 0x3c, 0xf1, 0xcd, 0xd1, 0xca, + 0xba, 0x5f, 0xc4, 0xcb, 0x39, 0xba, 0x6f, 0x41, 0xf4, 0x0c, 0x80, 0xa9, 0x89, 0x1f, 0x11, 0x16, + 0xd3, 0xc0, 0x9a, 0xaa, 0x61, 0x97, 0xa9, 0xfd, 0x0c, 0xe8, 0x8c, 0xa1, 0x56, 0x3c, 0x0a, 0x5a, + 0x07, 0x97, 0xa7, 0x71, 0xb6, 0x32, 0xf9, 0x89, 0x7f, 0x00, 0xb4, 0x09, 0xf5, 0x80, 0x72, 0x11, + 0x33, 0x6e, 0xbf, 0x97, 0x33, 0x47, 0x0f, 0xa0, 0xce, 0x57, 0x07, 0x96, 0xb0, 0x88, 0xa8, 0x97, + 0x3f, 0x01, 0x6a, 0x40, 0x99, 0x15, 0xde, 0xcb, 0x2c, 0x30, 0x21, 0x64, 0xcf, 0x43, 0xb3, 0x79, + 0x17, 0xcf, 0x7b, 0x13, 0x9c, 0x26, 0x32, 0xa4, 0xba, 0x08, 0x2e, 0xeb, 0xd0, 0x16, 0x54, 0xa4, + 0x88, 0xa8, 0x0d, 0xad, 0xb1, 0xbb, 0xf2, 0xf7, 0x46, 0x99, 0xf3, 0xb0, 0x65, 0x98, 0x9b, 0xd2, + 0xab, 0x84, 0x49, 0x1a, 0x4c, 0x88, 0xce, 0xd7, 0xc1, 0xcd, 0x91, 0xbe, 0xde, 0x7e, 0x0b, 0x15, + 0x43, 0x46, 0x4d, 0xa8, 0x9f, 0x1d, 0x9d, 0x78, 0xc3, 0xfd, 0xd1, 0xc1, 0x68, 0x38, 0x68, 0x95, + 0xd0, 0x12, 0xd4, 0x0e, 0xcf, 0xfa, 0x78, 0x30, 0xea, 0x1f, 0xb5, 0x1c, 0xd3, 0x1d, 0x7b, 0x43, + 0xdc, 0x3f, 0x3d, 0xc6, 0xad, 0x32, 0x72, 0x61, 0x71, 0x7c, 0x36, 0x38, 0x1c, 0xb6, 0x16, 0xf6, + 0xc6, 0xd7, 0x77, 0x6d, 0xe7, 0xe6, 0xae, 0xed, 0xfc, 0xba, 0x6b, 0x3b, 0x5f, 0xee, 0xdb, 0xa5, + 0x9b, 0xfb, 0x76, 0xe9, 0xc7, 0x7d, 0xbb, 0xf4, 0xfe, 0xf5, 0x3f, 0xf7, 0xe4, 0x6a, 0xfe, 0x9f, + 0x60, 0x37, 0x66, 0x5a, 0xb5, 0xbf, 0xf4, 0x37, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x74, 0xf3, + 0xa0, 0x53, 0x2f, 0x04, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -490,42 +490,36 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x20 } - if m.JudgeTrustLevel != nil { - { - size, err := m.JudgeTrustLevel.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintFbridge(dAtA, i, uint64(size)) + { + size, err := m.JudgeTrustLevel.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0x1a + i -= size + i = encodeVarintFbridge(dAtA, i, uint64(size)) } - if m.GuardianTrustLevel != nil { - { - size, err := m.GuardianTrustLevel.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintFbridge(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + { + size, err := m.GuardianTrustLevel.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0x12 + i -= size + i = encodeVarintFbridge(dAtA, i, uint64(size)) } - if m.OperatorTrustLevel != nil { - { - size, err := m.OperatorTrustLevel.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintFbridge(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + { + size, err := m.OperatorTrustLevel.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0xa + i -= size + i = encodeVarintFbridge(dAtA, i, uint64(size)) } + i-- + dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -726,18 +720,12 @@ func (m *Params) Size() (n int) { } var l int _ = l - if m.OperatorTrustLevel != nil { - l = m.OperatorTrustLevel.Size() - n += 1 + l + sovFbridge(uint64(l)) - } - if m.GuardianTrustLevel != nil { - l = m.GuardianTrustLevel.Size() - n += 1 + l + sovFbridge(uint64(l)) - } - if m.JudgeTrustLevel != nil { - l = m.JudgeTrustLevel.Size() - n += 1 + l + sovFbridge(uint64(l)) - } + l = m.OperatorTrustLevel.Size() + n += 1 + l + sovFbridge(uint64(l)) + l = m.GuardianTrustLevel.Size() + n += 1 + l + sovFbridge(uint64(l)) + l = m.JudgeTrustLevel.Size() + n += 1 + l + sovFbridge(uint64(l)) if m.TimelockPeriod != 0 { n += 1 + sovFbridge(uint64(m.TimelockPeriod)) } @@ -892,9 +880,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.OperatorTrustLevel == nil { - m.OperatorTrustLevel = &Fraction{} - } if err := m.OperatorTrustLevel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -928,9 +913,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.GuardianTrustLevel == nil { - m.GuardianTrustLevel = &Fraction{} - } if err := m.GuardianTrustLevel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -964,9 +946,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.JudgeTrustLevel == nil { - m.JudgeTrustLevel = &Fraction{} - } if err := m.JudgeTrustLevel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } diff --git a/x/fbridge/types/genesis.go b/x/fbridge/types/genesis.go index 58322550d4..43afde2bc9 100644 --- a/x/fbridge/types/genesis.go +++ b/x/fbridge/types/genesis.go @@ -1,9 +1,20 @@ package types +import "errors" + func DefaultGenesisState() *GenesisState { - return &GenesisState{} + return &GenesisState{ + SendingState: SendingState{ + NextSeq: 1, + }, + ReceivingState: ReceivingState{}, + } } func ValidateGenesis(data GenesisState) error { + if data.SendingState.NextSeq < 1 { + panic(errors.New("next sequence must be positive")) + } + return nil } diff --git a/x/fbridge/types/keys.go b/x/fbridge/types/keys.go index db369517f7..03179de065 100644 --- a/x/fbridge/types/keys.go +++ b/x/fbridge/types/keys.go @@ -7,3 +7,8 @@ const ( // StoreKey is the store key string for distribution StoreKey = ModuleName ) + +var ( + KeyParams = []byte{0x01} // key for fbridge module params + KeyNextSeqSend = []byte{0x02} // key for the next bridge send sequence +) diff --git a/x/fbridge/types/params.go b/x/fbridge/types/params.go new file mode 100644 index 0000000000..ab1254f4c2 --- /dev/null +++ b/x/fbridge/types/params.go @@ -0,0 +1 @@ +package types