Skip to content

Commit

Permalink
impl bridge transfer tx/query
Browse files Browse the repository at this point in the history
  • Loading branch information
tkxkd0159 committed Apr 29, 2024
1 parent 82e8936 commit e336960
Show file tree
Hide file tree
Showing 17 changed files with 599 additions and 120 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
6 changes: 3 additions & 3 deletions proto/lbm/fbridge/v1/fbridge.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -142,6 +145,7 @@ var (
tokenmodule.AppModuleBasic{},
collectionmodule.AppModuleBasic{},
fswap.AppModuleBasic{},
fbridgemodule.AppModuleBasic{},
)

// module account permissions
Expand All @@ -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,
}
)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -422,6 +433,7 @@ func NewSimApp(
token.ModuleName,
collection.ModuleName,
fswaptypes.ModuleName,
fbridgetypes.ModuleName,
)
app.mm.SetOrderEndBlockers(
crisistypes.ModuleName,
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down
9 changes: 8 additions & 1 deletion x/fbridge/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ import (
)

func (k Keeper) InitGenesis(ctx sdk.Context, gs *types.GenesisState) error {
k.setNextSequence(ctx, gs.SendingState.NextSeq)

Check warning on line 9 in x/fbridge/keeper/genesis.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/genesis.go#L9

Added line #L9 was not covered by tests

return nil
}

func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
return nil

return &types.GenesisState{
SendingState: types.SendingState{
NextSeq: k.GetNextSequence(ctx),
},

Check warning on line 19 in x/fbridge/keeper/genesis.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/genesis.go#L16-L19

Added lines #L16 - L19 were not covered by tests
}
}
9 changes: 6 additions & 3 deletions x/fbridge/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package keeper

import (
"context"

Check failure on line 4 in x/fbridge/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/Finschia/finschia-sdk) --custom-order (gci)

sdk "github.com/Finschia/finschia-sdk/types"
"github.com/Finschia/finschia-sdk/x/fbridge/types"
)

Expand All @@ -12,8 +12,11 @@ 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, request *types.QueryNextSeqSendRequest) (*types.QueryNextSeqSendResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
seq := k.GetNextSequence(ctx)

Check warning on line 17 in x/fbridge/keeper/grpc_query.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/grpc_query.go#L15-L17

Added lines #L15 - L17 were not covered by tests

return &types.QueryNextSeqSendResponse{Seq: seq}, nil

Check warning on line 19 in x/fbridge/keeper/grpc_query.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/grpc_query.go#L19

Added line #L19 was not covered by tests
}

func (k Keeper) GreatestSeqByOperator(ctx context.Context, request *types.QueryGreatestSeqByOperatorRequest) (*types.QueryGreatestSeqByOperatorResponse, error) {
Expand Down
60 changes: 59 additions & 1 deletion x/fbridge/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,61 @@
package keeper

type Keeper struct{}
import (
"errors"

Check failure on line 4 in x/fbridge/keeper/keeper.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/Finschia/finschia-sdk) --custom-order (gci)

"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"

Check failure on line 11 in x/fbridge/keeper/keeper.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/Finschia/finschia-sdk) --custom-order (gci)
)

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"))

Check warning on line 38 in x/fbridge/keeper/keeper.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/keeper.go#L38

Added line #L38 was not covered by tests
}

if strings.TrimSpace(authority) == "" {
panic(errors.New("authority address cannot be empty"))

Check warning on line 42 in x/fbridge/keeper/keeper.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/keeper.go#L42

Added line #L42 was not covered by tests
}

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)

Check warning on line 56 in x/fbridge/keeper/keeper.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/keeper.go#L55-L56

Added lines #L55 - L56 were not covered by tests
}

func (k Keeper) GetAuthority() string {
return k.authority

Check warning on line 60 in x/fbridge/keeper/keeper.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/keeper.go#L59-L60

Added lines #L59 - L60 were not covered by tests
}
49 changes: 38 additions & 11 deletions x/fbridge/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package keeper

import (
"context"

Check failure on line 4 in x/fbridge/keeper/msg_server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/Finschia/finschia-sdk) --custom-order (gci)
sdk "github.com/Finschia/finschia-sdk/types"
sdkerrors "github.com/Finschia/finschia-sdk/types/errors"

"github.com/Finschia/finschia-sdk/x/fbridge/types"
)
Expand All @@ -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)

Check warning on line 22 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L21-L22

Added lines #L21 - L22 were not covered by tests

from, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address (%s)", err)

Check warning on line 26 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L24-L26

Added lines #L24 - L26 were not covered by tests
}

if !IsValidEthereumAddress(msg.Receiver) {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid recipient address (%s)", msg.Receiver)

Check warning on line 30 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L29-L30

Added lines #L29 - L30 were not covered by tests
}

seq, err := m.handleBridgeTransfer(ctx, from, msg.Amount)
if err != nil {
return nil, err

Check warning on line 35 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L33-L35

Added lines #L33 - L35 were not covered by tests
}

if err := ctx.EventManager().EmitTypedEvent(&types.EventTransfer{
Sender: msg.Sender,
Receiver: msg.Receiver,
Amount: msg.Amount.String(),
Seq: seq,
}); err != nil {
panic(err)

Check warning on line 44 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L38-L44

Added lines #L38 - L44 were not covered by tests
}

return &types.MsgTransferResponse{}, nil

Check warning on line 47 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L47

Added line #L47 was not covered by tests
}

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) {

Check warning on line 50 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L50

Added line #L50 was not covered by tests
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) {

Check warning on line 54 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L54

Added line #L54 was not covered by tests
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) {

Check warning on line 58 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L58

Added line #L58 was not covered by tests
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) {

Check warning on line 62 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L62

Added line #L62 was not covered by tests
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) {

Check warning on line 66 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L66

Added line #L66 was not covered by tests
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) {

Check warning on line 70 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L70

Added line #L70 was not covered by tests
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) {

Check warning on line 74 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L74

Added line #L74 was not covered by tests
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) {

Check warning on line 78 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L78

Added line #L78 was not covered by tests
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) {

Check warning on line 82 in x/fbridge/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/msg_server.go#L82

Added line #L82 was not covered by tests
panic("implement me")
}

Expand Down
78 changes: 78 additions & 0 deletions x/fbridge/keeper/transfer.go
Original file line number Diff line number Diff line change
@@ -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)

Check warning on line 21 in x/fbridge/keeper/transfer.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/transfer.go#L21

Added line #L21 was not covered by tests
}

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))

Check warning on line 25 in x/fbridge/keeper/transfer.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/transfer.go#L25

Added line #L25 was not covered by tests
}

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"))

Check warning on line 38 in x/fbridge/keeper/transfer.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/transfer.go#L38

Added line #L38 was not covered by tests
}

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

Check warning on line 54 in x/fbridge/keeper/transfer.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/transfer.go#L54

Added line #L54 was not covered by tests
}

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)

Check warning on line 68 in x/fbridge/keeper/transfer.go

View check run for this annotation

Codecov / codecov/patch

x/fbridge/keeper/transfer.go#L68

Added line #L68 was not covered by tests
}
if c < 8 {
checksumAddress += string(addressLower[i])
} else {
checksumAddress += strings.ToUpper(string(addressLower[i]))
}
}

return address == checksumAddress
}
Loading

0 comments on commit e336960

Please sign in to comment.