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

feat: implement cross-chain mechanism between op and greenfield #266

Merged
merged 4 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
181 changes: 120 additions & 61 deletions api/cosmos/gov/v1/tx.pulsar.go

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion proto/cosmos/gov/v1/gov.proto
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,3 @@ message CrossChainParamsChange {
// targets defines a slice of addresses string in hex format
repeated string targets = 3;
}

2 changes: 2 additions & 0 deletions proto/cosmos/gov/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ message MsgUpdateCrossChainParams {

// for cross chain param change or contract upgrade
CrossChainParamsChange params = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];

uint32 dest_chain_id = 3;
}

// MsgUpdateCrossChainParamsResponse defines the response structure for executing a MsgUpdateCrossChainParams message.
Expand Down
7 changes: 5 additions & 2 deletions x/crosschain/keeper/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package keeper
import sdk "github.com/cosmos/cosmos-sdk/types"

type crossChainConfig struct {
srcChainID sdk.ChainID
destBscChainId sdk.ChainID
srcChainID sdk.ChainID
destBscChainId sdk.ChainID
destOpChainId sdk.ChainID

nameToChannelID map[string]sdk.ChannelID
channelIDToName map[sdk.ChannelID]string
channelIDToApp map[sdk.ChannelID]sdk.CrossChainApplication
Expand All @@ -14,6 +16,7 @@ func newCrossChainCfg() *crossChainConfig {
config := &crossChainConfig{
srcChainID: 0,
destBscChainId: 0,
destOpChainId: 0,
nameToChannelID: make(map[string]sdk.ChannelID),
channelIDToName: make(map[sdk.ChannelID]string),
channelIDToApp: make(map[sdk.ChannelID]sdk.CrossChainApplication),
Expand Down
22 changes: 19 additions & 3 deletions x/crosschain/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,13 @@ func (k Keeper) RegisterChannel(name string, id sdk.ChannelID, app sdk.CrossChai

// IsDestChainSupported returns the support status of a dest chain
func (k Keeper) IsDestChainSupported(chainID sdk.ChainID) bool {
return chainID == k.cfg.destBscChainId
if chainID == k.cfg.destBscChainId {
yutianwu marked this conversation as resolved.
Show resolved Hide resolved
return true
}
if k.cfg.destOpChainId != 0 && chainID == k.cfg.destOpChainId {
return true
}
return false
}

// IsChannelSupported returns the support status of a channel
Expand Down Expand Up @@ -210,8 +216,8 @@ func (k Keeper) GetSrcChainID() sdk.ChainID {
return k.cfg.srcChainID
}

// SetDestChainID sets the destination chain id
func (k Keeper) SetDestChainID(destChainId sdk.ChainID) {
// SetDestBscChainID sets the destination chain id
func (k Keeper) SetDestBscChainID(destChainId sdk.ChainID) {
k.cfg.destBscChainId = destChainId
}

Expand All @@ -220,6 +226,16 @@ func (k Keeper) GetDestBscChainID() sdk.ChainID {
return k.cfg.destBscChainId
}

// SetDestOpChainID sets the destination chain id of op chain
func (k Keeper) SetDestOpChainID(destChainId sdk.ChainID) {
k.cfg.destOpChainId = destChainId
}

// GetDestOpChainID gets the destination chain id of op chain
func (k Keeper) GetDestOpChainID() sdk.ChainID {
return k.cfg.destOpChainId
}

// GetCrossChainPackage returns the ibc package by sequence
func (k Keeper) GetCrossChainPackage(ctx sdk.Context, destChainId sdk.ChainID, channelId sdk.ChannelID, sequence uint64) ([]byte, error) {
kvStore := ctx.KVStore(k.storeKey)
Expand Down
2 changes: 1 addition & 1 deletion x/crosschain/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (s *TestSuite) TestSetChannelSendPermission() {

func (s *TestSuite) TestUpdateChannelPermission() {
s.crossChainKeeper.RegisterChannel("test", 1, &testutil2.MockCrossChainApplication{})
s.crossChainKeeper.SetDestChainID(1)
s.crossChainKeeper.SetDestBscChainID(1)

s.crossChainKeeper.SetChannelSendPermission(s.ctx, sdk.ChainID(1), sdk.ChannelID(1), sdk.ChannelAllow)

Expand Down
1 change: 1 addition & 0 deletions x/gov/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func setupGovKeeper(t *testing.T) (

crossChainKeeper.EXPECT().GetDestBscChainID().Return(sdk.ChainID(714)).AnyTimes()
crossChainKeeper.EXPECT().CreateRawIBCPackageWithFee(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(0), nil).AnyTimes()
crossChainKeeper.EXPECT().IsDestChainSupported(gomock.Any()).Return(true).AnyTimes()

// Register all handlers for the MegServiceRouter.
msr.SetInterfaceRegistry(encCfg.InterfaceRegistry)
Expand Down
48 changes: 30 additions & 18 deletions x/gov/keeper/crosschain.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,33 @@ import (
)

func (k Keeper) RegisterCrossChainSyncParamsApp() error {
return k.crossChainKeeper.RegisterChannel(types.SyncParamsChannel, types.SyncParamsChannelID, k)
if err := k.crossChainKeeper.RegisterChannel(types.SyncParamsChannel, types.SyncParamsChannelID, SyncParamsApp{keeper: k}); err != nil {
return err
}

return nil
}

func (k Keeper) SyncParams(ctx sdk.Context, cpc govv1.CrossChainParamsChange) error {
type SyncParamsApp struct {
keeper Keeper
}

func (app SyncParamsApp) ExecuteSynPackage(ctx sdk.Context, _ *sdk.CrossChainAppContext, payload []byte) sdk.ExecuteResult {
app.keeper.Logger(ctx).Error("received sync params sync package", "payload", hex.EncodeToString(payload))
return sdk.ExecuteResult{}
}

func (app SyncParamsApp) ExecuteAckPackage(ctx sdk.Context, _ *sdk.CrossChainAppContext, payload []byte) sdk.ExecuteResult {
app.keeper.Logger(ctx).Error("received sync params in ack package", "payload", hex.EncodeToString(payload))
return sdk.ExecuteResult{}
}

func (app SyncParamsApp) ExecuteFailAckPackage(ctx sdk.Context, _ *sdk.CrossChainAppContext, payload []byte) sdk.ExecuteResult {
app.keeper.Logger(ctx).Error("received sync params fail ack package", "payload", hex.EncodeToString(payload))
return sdk.ExecuteResult{}
}

func (k Keeper) SyncParams(ctx sdk.Context, destChainId sdk.ChainID, cpc govv1.CrossChainParamsChange) error {
if err := cpc.ValidateBasic(); err != nil {
return err
}
Expand Down Expand Up @@ -45,9 +68,13 @@ func (k Keeper) SyncParams(ctx sdk.Context, cpc govv1.CrossChainParamsChange) er

encodedPackage := pack.MustSerialize()

if !k.crossChainKeeper.IsDestChainSupported(destChainId) {
return sdkerrors.Wrapf(types.ErrChainNotSupported, "destination chain (%d) is not supported", destChainId)
}

_, err := k.crossChainKeeper.CreateRawIBCPackageWithFee(
ctx,
k.crossChainKeeper.GetDestBscChainID(),
destChainId,
types.SyncParamsChannelID,
sdk.SynCrossChainPackageType,
encodedPackage,
Expand All @@ -56,18 +83,3 @@ func (k Keeper) SyncParams(ctx sdk.Context, cpc govv1.CrossChainParamsChange) er
)
return err
}

func (k Keeper) ExecuteSynPackage(ctx sdk.Context, _ *sdk.CrossChainAppContext, payload []byte) sdk.ExecuteResult {
k.Logger(ctx).Error("received sync params sync package", "payload", hex.EncodeToString(payload))
return sdk.ExecuteResult{}
}

func (k Keeper) ExecuteAckPackage(ctx sdk.Context, _ *sdk.CrossChainAppContext, payload []byte) sdk.ExecuteResult {
k.Logger(ctx).Error("received sync params in ack package", "payload", hex.EncodeToString(payload))
return sdk.ExecuteResult{}
}

func (k Keeper) ExecuteFailAckPackage(ctx sdk.Context, _ *sdk.CrossChainAppContext, payload []byte) sdk.ExecuteResult {
k.Logger(ctx).Error("received sync params fail ack package", "payload", hex.EncodeToString(payload))
return sdk.ExecuteResult{}
}
70 changes: 35 additions & 35 deletions x/gov/keeper/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@ import (
)

// GetDeposit gets the deposit of a specific depositor on a specific proposal
func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) (deposit v1.Deposit, found bool) {
store := ctx.KVStore(keeper.storeKey)
func (k Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) (deposit v1.Deposit, found bool) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.DepositKey(proposalID, depositorAddr))
if bz == nil {
return deposit, false
}

keeper.cdc.MustUnmarshal(bz, &deposit)
k.cdc.MustUnmarshal(bz, &deposit)

return deposit, true
}

// SetDeposit sets a Deposit to the gov store
func (keeper Keeper) SetDeposit(ctx sdk.Context, deposit v1.Deposit) {
store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshal(&deposit)
func (k Keeper) SetDeposit(ctx sdk.Context, deposit v1.Deposit) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshal(&deposit)
depositor := sdk.MustAccAddressFromHex(deposit.Depositor)

store.Set(types.DepositKey(deposit.ProposalId, depositor), bz)
}

// GetAllDeposits returns all the deposits from the store
func (keeper Keeper) GetAllDeposits(ctx sdk.Context) (deposits v1.Deposits) {
keeper.IterateAllDeposits(ctx, func(deposit v1.Deposit) bool {
func (k Keeper) GetAllDeposits(ctx sdk.Context) (deposits v1.Deposits) {
k.IterateAllDeposits(ctx, func(deposit v1.Deposit) bool {
deposits = append(deposits, &deposit)
return false
})
Expand All @@ -42,8 +42,8 @@ func (keeper Keeper) GetAllDeposits(ctx sdk.Context) (deposits v1.Deposits) {
}

// GetDeposits returns all the deposits of a proposal
func (keeper Keeper) GetDeposits(ctx sdk.Context, proposalID uint64) (deposits v1.Deposits) {
keeper.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) bool {
func (k Keeper) GetDeposits(ctx sdk.Context, proposalID uint64) (deposits v1.Deposits) {
k.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) bool {
deposits = append(deposits, &deposit)
return false
})
Expand All @@ -52,11 +52,11 @@ func (keeper Keeper) GetDeposits(ctx sdk.Context, proposalID uint64) (deposits v
}

// DeleteAndBurnDeposits deletes and burns all the deposits on a specific proposal.
func (keeper Keeper) DeleteAndBurnDeposits(ctx sdk.Context, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
func (k Keeper) DeleteAndBurnDeposits(ctx sdk.Context, proposalID uint64) {
store := ctx.KVStore(k.storeKey)

keeper.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) bool {
err := keeper.bankKeeper.BurnCoins(ctx, types.ModuleName, deposit.Amount)
k.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) bool {
err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, deposit.Amount)
if err != nil {
panic(err)
}
Expand All @@ -69,16 +69,16 @@ func (keeper Keeper) DeleteAndBurnDeposits(ctx sdk.Context, proposalID uint64) {
}

// IterateAllDeposits iterates over all the stored deposits and performs a callback function.
func (keeper Keeper) IterateAllDeposits(ctx sdk.Context, cb func(deposit v1.Deposit) (stop bool)) {
store := ctx.KVStore(keeper.storeKey)
func (k Keeper) IterateAllDeposits(ctx sdk.Context, cb func(deposit v1.Deposit) (stop bool)) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, types.DepositsKeyPrefix)

defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
var deposit v1.Deposit

keeper.cdc.MustUnmarshal(iterator.Value(), &deposit)
k.cdc.MustUnmarshal(iterator.Value(), &deposit)

if cb(deposit) {
break
Expand All @@ -87,16 +87,16 @@ func (keeper Keeper) IterateAllDeposits(ctx sdk.Context, cb func(deposit v1.Depo
}

// IterateDeposits iterates over all the proposals deposits and performs a callback function
func (keeper Keeper) IterateDeposits(ctx sdk.Context, proposalID uint64, cb func(deposit v1.Deposit) (stop bool)) {
store := ctx.KVStore(keeper.storeKey)
func (k Keeper) IterateDeposits(ctx sdk.Context, proposalID uint64, cb func(deposit v1.Deposit) (stop bool)) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, types.DepositsKey(proposalID))

defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
var deposit v1.Deposit

keeper.cdc.MustUnmarshal(iterator.Value(), &deposit)
k.cdc.MustUnmarshal(iterator.Value(), &deposit)

if cb(deposit) {
break
Expand All @@ -106,9 +106,9 @@ func (keeper Keeper) IterateDeposits(ctx sdk.Context, proposalID uint64, cb func

// AddDeposit adds or updates a deposit of a specific depositor on a specific proposal.
// Activates voting period when appropriate and returns true in that case, else returns false.
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (bool, error) {
func (k Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (bool, error) {
// Checks to see if proposal exists
proposal, ok := keeper.GetProposal(ctx, proposalID)
proposal, ok := k.GetProposal(ctx, proposalID)
if !ok {
return false, sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID)
}
Expand All @@ -119,26 +119,26 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAdd
}

// update the governance module's account coins pool
err := keeper.bankKeeper.SendCoinsFromAccountToModule(ctx, depositorAddr, types.ModuleName, depositAmount)
err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, depositorAddr, types.ModuleName, depositAmount)
if err != nil {
return false, err
}

// Update proposal
proposal.TotalDeposit = sdk.NewCoins(proposal.TotalDeposit...).Add(depositAmount...)
keeper.SetProposal(ctx, proposal)
k.SetProposal(ctx, proposal)

// Check if deposit has provided sufficient total funds to transition the proposal into the voting period
activatedVotingPeriod := false

if proposal.Status == v1.StatusDepositPeriod && sdk.NewCoins(proposal.TotalDeposit...).IsAllGTE(keeper.GetParams(ctx).MinDeposit) {
keeper.ActivateVotingPeriod(ctx, proposal)
if proposal.Status == v1.StatusDepositPeriod && sdk.NewCoins(proposal.TotalDeposit...).IsAllGTE(k.GetParams(ctx).MinDeposit) {
k.ActivateVotingPeriod(ctx, proposal)

activatedVotingPeriod = true
}

// Add or update deposit object
deposit, found := keeper.GetDeposit(ctx, proposalID, depositorAddr)
deposit, found := k.GetDeposit(ctx, proposalID, depositorAddr)

if found {
deposit.Amount = sdk.NewCoins(deposit.Amount...).Add(depositAmount...)
Expand All @@ -147,7 +147,7 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAdd
}

// called when deposit has been added to a proposal, however the proposal may not be active
keeper.Hooks().AfterProposalDeposit(ctx, proposalID, depositorAddr)
k.Hooks().AfterProposalDeposit(ctx, proposalID, depositorAddr)

ctx.EventManager().EmitEvent(
sdk.NewEvent(
Expand All @@ -157,19 +157,19 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAdd
),
)

keeper.SetDeposit(ctx, deposit)
k.SetDeposit(ctx, deposit)

return activatedVotingPeriod, nil
}

// RefundAndDeleteDeposits refunds and deletes all the deposits on a specific proposal.
func (keeper Keeper) RefundAndDeleteDeposits(ctx sdk.Context, proposalID uint64) {
store := ctx.KVStore(keeper.storeKey)
func (k Keeper) RefundAndDeleteDeposits(ctx sdk.Context, proposalID uint64) {
store := ctx.KVStore(k.storeKey)

keeper.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) bool {
k.IterateDeposits(ctx, proposalID, func(deposit v1.Deposit) bool {
depositor := sdk.MustAccAddressFromHex(deposit.Depositor)

err := keeper.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, depositor, deposit.Amount)
err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, depositor, deposit.Amount)
if err != nil {
panic(err)
}
Expand All @@ -182,8 +182,8 @@ func (keeper Keeper) RefundAndDeleteDeposits(ctx sdk.Context, proposalID uint64)
// validateInitialDeposit validates if initial deposit is greater than or equal to the minimum
// required at the time of proposal submission. This threshold amount is determined by
// the deposit parameters. Returns nil on success, error otherwise.
func (keeper Keeper) validateInitialDeposit(ctx sdk.Context, initialDeposit sdk.Coins) error {
params := keeper.GetParams(ctx)
func (k Keeper) validateInitialDeposit(ctx sdk.Context, initialDeposit sdk.Coins) error {
params := k.GetParams(ctx)
minInitialDepositRatio, err := sdk.NewDecFromStr(params.MinInitialDepositRatio)
if err != nil {
return err
Expand Down
Loading