diff --git a/app/ante/handlers.go b/app/ante/handlers.go index f07485696..8897891ae 100644 --- a/app/ante/handlers.go +++ b/app/ante/handlers.go @@ -5,13 +5,13 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/ante" ibcclienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" ibcante "github.com/cosmos/ibc-go/v7/modules/core/ante" + "github.com/dymensionxyz/dymension/v3/x/common/types" ethante "github.com/evmos/ethermint/app/ante" txfeesante "github.com/osmosis-labs/osmosis/v15/x/txfees/ante" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" evmtypes "github.com/evmos/ethermint/x/evm/types" - "github.com/dymensionxyz/dymension/v3/x/delayedack" lightclientante "github.com/dymensionxyz/dymension/v3/x/lightclient/ante" ) @@ -79,7 +79,7 @@ func newLegacyCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler { NewLegacyEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), ante.NewIncrementSequenceDecorator(options.AccountKeeper), lightclientante.NewIBCMessagesDecorator(*options.LightClientKeeper, options.IBCKeeper.ClientKeeper, options.IBCKeeper.ChannelKeeper, options.RollappKeeper), - delayedack.NewIBCProofHeightDecorator(), + types.NewIBCProofHeightDecorator(), ibcante.NewRedundantRelayDecorator(options.IBCKeeper), ethante.NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper), ) @@ -119,7 +119,7 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler { ante.NewSigGasConsumeDecorator(options.AccountKeeper, ethante.DefaultSigVerificationGasConsumer), ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), ante.NewIncrementSequenceDecorator(options.AccountKeeper), - delayedack.NewIBCProofHeightDecorator(), + types.NewIBCProofHeightDecorator(), lightclientante.NewIBCMessagesDecorator(*options.LightClientKeeper, options.IBCKeeper.ClientKeeper, options.IBCKeeper.ChannelKeeper, options.RollappKeeper), ibcante.NewRedundantRelayDecorator(options.IBCKeeper), ethante.NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper), diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index d148e5526..822317e6c 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -339,10 +339,14 @@ func ConvertOldRollappToNew(oldRollapp rollapptypes.Rollapp) rollapptypes.Rollap genesisInfo = crynuxGenesisInfo } + genesisState := oldRollapp.GenesisState + // min(nim=813701, mande=1332619) on Dec 2nd : a sufficient and safe number + genesisState.TransferProofHeight = 813701 + return rollapptypes.Rollapp{ RollappId: oldRollapp.RollappId, Owner: oldRollapp.Owner, - GenesisState: oldRollapp.GenesisState, + GenesisState: genesisState, ChannelId: oldRollapp.ChannelId, Metadata: &rollapptypes.RollappMetadata{ // Can be updated in runtime Website: "", diff --git a/ibctesting/genesis_bridge_test.go b/ibctesting/genesis_bridge_test.go index a850b91f7..4f42b0d05 100644 --- a/ibctesting/genesis_bridge_test.go +++ b/ibctesting/genesis_bridge_test.go @@ -77,7 +77,7 @@ func (s *transferGenesisSuite) TestHappyPath_NoGenesisAccounts() { rollapp = s.hubApp().RollappKeeper.MustGetRollapp(s.hubCtx(), rollappChainID()) // assert the transfers are enabled - s.Require().True(rollapp.GenesisState.TransfersEnabled) + s.Require().True(rollapp.GenesisState.IsTransferEnabled()) // assert denom registered expectedIBCdenom := types.ParseDenomTrace(types.GetPrefixedDenom(s.path.EndpointB.ChannelConfig.PortID, s.path.EndpointB.ChannelID, rollapp.GenesisInfo.NativeDenom.Base)).IBCDenom() @@ -160,7 +160,7 @@ func (s *transferGenesisSuite) TestIRO() { // assert the transfers are enabled rollapp = s.hubApp().RollappKeeper.MustGetRollapp(s.hubCtx(), rollappChainID()) - s.Require().True(rollapp.GenesisState.TransfersEnabled) + s.Require().True(rollapp.GenesisState.IsTransferEnabled()) // the iro plan should be settled plan, found := s.hubApp().IROKeeper.GetPlanByRollapp(s.hubCtx(), rollappChainID()) @@ -346,7 +346,7 @@ func (s *transferGenesisSuite) TestBridgeDisabledEnabled() { // assert the transfers are enabled rollapp = s.hubApp().RollappKeeper.MustGetRollapp(s.hubCtx(), rollappChainID()) - s.Require().True(rollapp.GenesisState.TransfersEnabled) + s.Require().True(rollapp.GenesisState.IsTransferEnabled()) // assert the transfer now goes through res, err = s.rollappChain().SendMsgs(msg) diff --git a/ibctesting/transfers_enabled_test.go b/ibctesting/transfers_enabled_test.go index bafd00f09..3dfb050ec 100644 --- a/ibctesting/transfers_enabled_test.go +++ b/ibctesting/transfers_enabled_test.go @@ -37,7 +37,7 @@ func (s *transfersEnabledSuite) SetupTest() { // manually set the rollapp to have transfers disabled by default // (rollapp is setup correctly, meaning transfer channel is canonical) ra := s.hubApp().RollappKeeper.MustGetRollapp(s.hubCtx(), rollappChainID()) - ra.GenesisState.TransfersEnabled = false + ra.GenesisState.TransferProofHeight = 0 ra.ChannelId = s.path.EndpointA.ChannelID s.hubApp().RollappKeeper.SetRollapp(s.hubCtx(), ra) s.hubApp().LightClientKeeper.SetCanonicalClient(s.hubCtx(), rollappChainID(), s.path.EndpointA.ClientID) @@ -88,7 +88,7 @@ func (s *transfersEnabledSuite) TestHubToRollappDisabled() { s.Require().True(errorsmod.IsOf(err, gerrc.ErrFailedPrecondition)) ra := s.hubApp().RollappKeeper.MustGetRollapp(s.hubCtx(), rollappChainID()) ra.ChannelId = s.path.EndpointA.ChannelID - ra.GenesisState.TransfersEnabled = true + ra.GenesisState.TransferProofHeight = 1 // enable s.hubApp().RollappKeeper.SetRollapp(s.hubCtx(), ra) } else { s.Require().NoError(err) diff --git a/ibctesting/utils_test.go b/ibctesting/utils_test.go index afca541de..93cc84066 100644 --- a/ibctesting/utils_test.go +++ b/ibctesting/utils_test.go @@ -168,7 +168,10 @@ func (s *utilSuite) createRollapp(transfersEnabled bool, channelID *string) { a := s.hubApp() ra := a.RollappKeeper.MustGetRollapp(s.hubCtx(), rollappChainID()) ra.ChannelId = *channelID - ra.GenesisState.TransfersEnabled = transfersEnabled + ra.GenesisState.TransferProofHeight = 0 + if transfersEnabled { + ra.GenesisState.TransferProofHeight = 1 + } a.RollappKeeper.SetRollapp(s.hubCtx(), ra) } } diff --git a/proto/dymensionxyz/dymension/rollapp/rollapp.proto b/proto/dymensionxyz/dymension/rollapp/rollapp.proto index e46196a73..ec670db9d 100644 --- a/proto/dymensionxyz/dymension/rollapp/rollapp.proto +++ b/proto/dymensionxyz/dymension/rollapp/rollapp.proto @@ -14,15 +14,14 @@ import "dymensionxyz/dymension/rollapp/genesis_info.proto"; // RollappGenesisState is a partial repr of the state the hub can expect the // rollapp to be in upon genesis message RollappGenesisState { - reserved 1; - // If true, then full usage of the canonical ibc transfer channel is enabled. - // Note: in v3.1.0 and prior this field marked the completion of the 'genesis - // event' Keeping and renaming the field enables a seamless upgrade - // https://www.notion.so/dymension/ADR-x-Genesis-Bridge-Phase-2-89769aa551b5440b9ed403a101775ce1?pvs=4#89698384d815435b87393dbe45bc5a74 - // to the new genesis transfer protocol - // Note: if this field is false, ibc transfers may still be allowed in one or - // either direction. - bool transfers_enabled = 2; + reserved 1,2; + + + // 0 means unpopulated + // If populated, it's the proof height that the hub received the genesis transfer + // packet from the rollapp. If populated, the bridge is considered open. It's not allowed + // to fork to a height prior to this height. + uint64 transfer_proof_height = 3; } // Rollapp defines a rollapp object. First, the RollApp is created and then diff --git a/x/bridgingfee/ibc_module.go b/x/bridgingfee/ibc_module.go index 901c8994e..00275f66b 100644 --- a/x/bridgingfee/ibc_module.go +++ b/x/bridgingfee/ibc_module.go @@ -14,7 +14,6 @@ import ( "github.com/osmosis-labs/osmosis/v15/osmoutils" txfeeskeeper "github.com/osmosis-labs/osmosis/v15/x/txfees/keeper" - commontypes "github.com/dymensionxyz/dymension/v3/x/common/types" delayedackkeeper "github.com/dymensionxyz/dymension/v3/x/delayedack/keeper" rollappkeeper "github.com/dymensionxyz/dymension/v3/x/rollapp/keeper" ) @@ -73,10 +72,6 @@ func (w IBCModule) logger( func (w IBCModule) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) exported.Acknowledgement { l := w.logger(ctx, packet, "OnRecvPacket") - if commontypes.SkipRollappMiddleware(ctx) { - return w.IBCModule.OnRecvPacket(ctx, packet, relayer) - } - transfer, err := w.rollappKeeper.GetValidTransfer(ctx, packet.GetData(), packet.GetDestPort(), packet.GetDestChannel()) if err != nil { l.Error("Get valid transfer.", "err", err) diff --git a/x/common/types/rollapp_packet.go b/x/common/types/rollapp_packet.go index 83ddf80ee..41db929d2 100644 --- a/x/common/types/rollapp_packet.go +++ b/x/common/types/rollapp_packet.go @@ -4,9 +4,12 @@ import ( "fmt" "strconv" + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + ibctypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + "github.com/dymensionxyz/gerr-cosmos/gerrc" ) func (r RollappPacket) LogString() string { @@ -120,3 +123,95 @@ func (r RollappPacket) RestoreOriginalTransferTarget() RollappPacket { } return r } + +const ( + // proofHeightCtxKey is a context key to pass the proof height from the msg to the IBC middleware + proofHeightCtxKey = "ibc_proof_height" +) + +func CtxWithPacketProofHeight(ctx sdk.Context, packetId PacketUID, height ibctypes.Height) sdk.Context { + key := fmt.Sprintf("%s_%s", proofHeightCtxKey, packetId.String()) + return ctx.WithValue(key, height) +} + +func PacketProofHeightFromCtx(ctx sdk.Context, packetId PacketUID) (ibctypes.Height, bool) { + key := fmt.Sprintf("%s_%s", proofHeightCtxKey, packetId.String()) + u, ok := ctx.Value(key).(ibctypes.Height) + return u, ok +} + +type IBCProofHeightDecorator struct{} + +func NewIBCProofHeightDecorator() IBCProofHeightDecorator { + return IBCProofHeightDecorator{} +} + +func (rrd IBCProofHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { + for _, m := range tx.GetMsgs() { + var ( + height ibctypes.Height + packetId PacketUID + ) + switch msg := m.(type) { + case *channeltypes.MsgRecvPacket: + height = msg.ProofHeight + packetId = NewPacketUID( + RollappPacket_ON_RECV, + msg.Packet.DestinationPort, + msg.Packet.DestinationChannel, + msg.Packet.Sequence, + ) + + case *channeltypes.MsgAcknowledgement: + height = msg.ProofHeight + packetId = NewPacketUID( + RollappPacket_ON_ACK, + msg.Packet.SourcePort, + msg.Packet.SourceChannel, + msg.Packet.Sequence, + ) + + case *channeltypes.MsgTimeout: + height = msg.ProofHeight + packetId = NewPacketUID( + RollappPacket_ON_TIMEOUT, + msg.Packet.SourcePort, + msg.Packet.SourceChannel, + msg.Packet.Sequence, + ) + default: + continue + } + + ctx = CtxWithPacketProofHeight(ctx, packetId, height) + } + return next(ctx, tx, simulate) +} + +func PacketHubPortChan(packetType RollappPacket_Type, packet channeltypes.Packet) (string, string) { + var port string + var channel string + + switch packetType { + case RollappPacket_ON_RECV: + port, channel = packet.GetDestPort(), packet.GetDestChannel() + case RollappPacket_ON_TIMEOUT, RollappPacket_ON_ACK: + port, channel = packet.GetSourcePort(), packet.GetSourceChannel() + } + return port, channel +} + +func UnpackPacketProofHeight( + ctx sdk.Context, + packet channeltypes.Packet, + packetType RollappPacket_Type, +) (uint64, error) { + port, channel := PacketHubPortChan(packetType, packet) + + packetID := NewPacketUID(packetType, port, channel, packet.Sequence) + height, ok := PacketProofHeightFromCtx(ctx, packetID) + if !ok { + return 0, errorsmod.Wrapf(gerrc.ErrInternal, "get proof height from context: packetID: %s", packetID) + } + return height.RevisionHeight, nil +} diff --git a/x/common/types/skip_middleware.go b/x/common/types/skip_middleware.go deleted file mode 100644 index a793b8b77..000000000 --- a/x/common/types/skip_middleware.go +++ /dev/null @@ -1,17 +0,0 @@ -package types - -import sdk "github.com/cosmos/cosmos-sdk/types" - -type ctxKeySkipRollappMiddlewares struct{} - -// SkipRollappMiddlewareContext returns a context which can be passed -// to dymension ibc middlewares related to rollapp logic to skip the middleware. -func SkipRollappMiddlewareContext(ctx sdk.Context) sdk.Context { - return ctx.WithValue(ctxKeySkipRollappMiddlewares{}, true) -} - -// SkipRollappMiddleware returns if the context contains the SkipRollappMiddleware directive -func SkipRollappMiddleware(ctx sdk.Context) bool { - val, ok := ctx.Value(ctxKeySkipRollappMiddlewares{}).(bool) - return ok && val -} diff --git a/x/delayedack/ibc_middleware.go b/x/delayedack/ibc_middleware.go index ed4036c92..929af8eb7 100644 --- a/x/delayedack/ibc_middleware.go +++ b/x/delayedack/ibc_middleware.go @@ -86,11 +86,6 @@ func (w IBCMiddleware) OnRecvPacket( ) exported.Acknowledgement { l := w.logger(ctx, packet, "OnRecvPacket") - if commontypes.SkipRollappMiddleware(ctx) { - l.Debug("Skipping because of skip delay ctx.") - return w.IBCModule.OnRecvPacket(ctx, packet, relayer) - } - transfer, err := w.GetValidTransferWithFinalizationInfo(ctx, packet, commontypes.RollappPacket_ON_RECV) if err != nil { l.Error("Get valid rollapp and transfer.", "err", err) diff --git a/x/delayedack/keeper/transfer.go b/x/delayedack/keeper/transfer.go index fbb8cc6b8..468f28ea6 100644 --- a/x/delayedack/keeper/transfer.go +++ b/x/delayedack/keeper/transfer.go @@ -16,15 +16,14 @@ func (k Keeper) GetValidTransferWithFinalizationInfo( packet channeltypes.Packet, packetType commontypes.RollappPacket_Type, ) (data types.TransferDataWithFinalization, err error) { - var port string - var channel string + port, channel := commontypes.PacketHubPortChan(packetType, packet) - switch packetType { - case commontypes.RollappPacket_ON_RECV: - port, channel = packet.GetDestPort(), packet.GetDestChannel() - case commontypes.RollappPacket_ON_TIMEOUT, commontypes.RollappPacket_ON_ACK: - port, channel = packet.GetSourcePort(), packet.GetSourceChannel() + height, err := commontypes.UnpackPacketProofHeight(ctx, packet, packetType) + if err != nil { + err = errorsmod.Wrap(err, "unpack packet proof height") + return } + data.ProofHeight = height data.TransferData, err = k.rollappKeeper.GetValidTransfer(ctx, packet.GetData(), port, channel) if err != nil { @@ -32,15 +31,6 @@ func (k Keeper) GetValidTransferWithFinalizationInfo( return } - packetID := commontypes.NewPacketUID(packetType, port, channel, packet.Sequence) - height, ok := types.PacketProofHeightFromCtx(ctx, packetID) - if !ok { - // TODO: should probably be a panic - err = errorsmod.Wrapf(gerrc.ErrNotFound, "get proof height from context: packetID: %s", packetID) - return - } - data.ProofHeight = height.RevisionHeight - if !data.IsRollapp() { return } diff --git a/x/delayedack/proof_height_ante.go b/x/delayedack/proof_height_ante.go deleted file mode 100644 index b58d0ba45..000000000 --- a/x/delayedack/proof_height_ante.go +++ /dev/null @@ -1,59 +0,0 @@ -package delayedack - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - - commontypes "github.com/dymensionxyz/dymension/v3/x/common/types" - delayedacktypes "github.com/dymensionxyz/dymension/v3/x/delayedack/types" -) - -type IBCProofHeightDecorator struct{} - -func NewIBCProofHeightDecorator() IBCProofHeightDecorator { - return IBCProofHeightDecorator{} -} - -func (rrd IBCProofHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { - for _, m := range tx.GetMsgs() { - var ( - height clienttypes.Height - packetId commontypes.PacketUID - ) - switch msg := m.(type) { - case *channeltypes.MsgRecvPacket: - height = msg.ProofHeight - packetId = commontypes.NewPacketUID( - commontypes.RollappPacket_ON_RECV, - msg.Packet.DestinationPort, - msg.Packet.DestinationChannel, - msg.Packet.Sequence, - ) - - case *channeltypes.MsgAcknowledgement: - height = msg.ProofHeight - packetId = commontypes.NewPacketUID( - commontypes.RollappPacket_ON_ACK, - msg.Packet.SourcePort, - msg.Packet.SourceChannel, - msg.Packet.Sequence, - ) - - case *channeltypes.MsgTimeout: - height = msg.ProofHeight - packetId = commontypes.NewPacketUID( - commontypes.RollappPacket_ON_TIMEOUT, - msg.Packet.SourcePort, - msg.Packet.SourceChannel, - msg.Packet.Sequence, - ) - default: - continue - } - - ctx = delayedacktypes.CtxWithPacketProofHeight(ctx, packetId, height) - } - return next(ctx, tx, simulate) -} diff --git a/x/delayedack/types/proof_height_context.go b/x/delayedack/types/proof_height_context.go deleted file mode 100644 index 78fef60ae..000000000 --- a/x/delayedack/types/proof_height_context.go +++ /dev/null @@ -1,26 +0,0 @@ -package types - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - commontypes "github.com/dymensionxyz/dymension/v3/x/common/types" -) - -const ( - // proofHeightCtxKey is a context key to pass the proof height from the msg to the IBC middleware - proofHeightCtxKey = "ibc_proof_height" -) - -func CtxWithPacketProofHeight(ctx sdk.Context, packetId commontypes.PacketUID, height clienttypes.Height) sdk.Context { - key := fmt.Sprintf("%s_%s", proofHeightCtxKey, packetId.String()) - return ctx.WithValue(key, height) -} - -func PacketProofHeightFromCtx(ctx sdk.Context, packetId commontypes.PacketUID) (clienttypes.Height, bool) { - key := fmt.Sprintf("%s_%s", proofHeightCtxKey, packetId.String()) - u, ok := ctx.Value(key).(clienttypes.Height) - return u, ok -} diff --git a/x/denommetadata/ibc_middleware.go b/x/denommetadata/ibc_middleware.go index d4d2e2498..54e850c07 100644 --- a/x/denommetadata/ibc_middleware.go +++ b/x/denommetadata/ibc_middleware.go @@ -15,7 +15,6 @@ import ( "github.com/dymensionxyz/sdk-utils/utils/uevent" "github.com/dymensionxyz/sdk-utils/utils/uibc" - commontypes "github.com/dymensionxyz/dymension/v3/x/common/types" "github.com/dymensionxyz/dymension/v3/x/denommetadata/types" ) @@ -51,10 +50,6 @@ func (im IBCModule) OnRecvPacket( packet channeltypes.Packet, relayer sdk.AccAddress, ) exported.Acknowledgement { - if commontypes.SkipRollappMiddleware(ctx) { - return im.IBCModule.OnRecvPacket(ctx, packet, relayer) - } - transferData, err := im.rollappKeeper.GetValidTransfer(ctx, packet.Data, packet.DestinationPort, packet.DestinationChannel) if err != nil { return uevent.NewErrorAcknowledgement(ctx, err) diff --git a/x/rollapp/genesisbridge/ibc_module.go b/x/rollapp/genesisbridge/ibc_module.go index 3faede4c0..78658b96e 100644 --- a/x/rollapp/genesisbridge/ibc_module.go +++ b/x/rollapp/genesisbridge/ibc_module.go @@ -9,6 +9,7 @@ import ( channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" "github.com/cosmos/ibc-go/v7/modules/core/exported" + commontypes "github.com/dymensionxyz/dymension/v3/x/common/types" "github.com/dymensionxyz/sdk-utils/utils/uevent" "github.com/dymensionxyz/dymension/v3/x/rollapp/types" @@ -124,7 +125,7 @@ func (w IBCModule) OnRecvPacket( } } - err = w.EnableTransfers(ctx, ra, denom.Base) + err = w.EnableTransfers(ctx, packet, ra, denom.Base) if err != nil { l.Error("Enable transfers.", "err", err) return uevent.NewErrorAcknowledgement(ctx, errorsmod.Wrap(err, "transfer genesis: enable transfers")) @@ -144,13 +145,18 @@ func (w IBCModule) OnRecvPacket( // EnableTransfers marks the end of the genesis bridge phase. // It sets the transfers enabled flag on the rollapp. // It also calls the after transfers enabled hook. -func (w IBCModule) EnableTransfers(ctx sdk.Context, ra *types.Rollapp, rollappIBCtrace string) error { - ra.GenesisState.TransfersEnabled = true +func (w IBCModule) EnableTransfers(ctx sdk.Context, packet channeltypes.Packet, ra *types.Rollapp, rollappIBCtrace string) error { + height, err := commontypes.UnpackPacketProofHeight(ctx, packet, commontypes.RollappPacket_ON_RECV) + if err != nil { + return errorsmod.Wrap(err, "unpack packet proof height") + } + + ra.GenesisState.TransferProofHeight = height w.rollappKeeper.SetRollapp(ctx, *ra) // call the after transfers enabled hook // currently, used for IRO settlement - err := w.rollappKeeper.GetHooks().AfterTransfersEnabled(ctx, ra.RollappId, rollappIBCtrace) + err = w.rollappKeeper.GetHooks().AfterTransfersEnabled(ctx, ra.RollappId, rollappIBCtrace) if err != nil { return errorsmod.Wrap(err, "after transfers enabled hook") } diff --git a/x/rollapp/genesisbridge/ics4_wrapper.go b/x/rollapp/genesisbridge/ics4_wrapper.go index 090bd834b..f866b2725 100644 --- a/x/rollapp/genesisbridge/ics4_wrapper.go +++ b/x/rollapp/genesisbridge/ics4_wrapper.go @@ -72,7 +72,7 @@ func (w *ICS4Wrapper) transferAllowed(ctx sdk.Context, sourcePort string, source } return errorsmod.Wrap(err, "rollapp by port chan") } - if !ra.GenesisState.TransfersEnabled { + if !ra.GenesisState.IsTransferEnabled() { return gerrc.ErrFailedPrecondition.Wrap("transfers disabled for rollapp") } return nil diff --git a/x/rollapp/keeper/fraud_proposal.go b/x/rollapp/keeper/fraud_proposal.go index f2a6b6f9d..4f2234485 100644 --- a/x/rollapp/keeper/fraud_proposal.go +++ b/x/rollapp/keeper/fraud_proposal.go @@ -43,13 +43,6 @@ func (k Keeper) SubmitRollappFraud(goCtx context.Context, msg *types.MsgRollappF return nil, err } - // validate the rollapp is past its genesis bridge phase - if !rollapp.IsTransferEnabled() { - err := errorsmod.Wrap(gerrc.ErrFailedPrecondition, "rollapp is not past genesis bridge phase") - ctx.Logger().Error("Fraud proposal.", err) - return nil, err - } - // punish the sequencer if needed if msg.PunishSequencerAddress != "" { err := k.SequencerK.PunishSequencer(ctx, msg.PunishSequencerAddress, msg.MustRewardee()) diff --git a/x/rollapp/keeper/fraud_proposal_test.go b/x/rollapp/keeper/fraud_proposal_test.go index eb1fcd558..68efba3da 100644 --- a/x/rollapp/keeper/fraud_proposal_test.go +++ b/x/rollapp/keeper/fraud_proposal_test.go @@ -53,7 +53,7 @@ func (s *RollappTestSuite) TestSubmitRollappFraud() { // set transferEnabled to true rollapp := s.k().MustGetRollapp(s.Ctx, rollappId) - rollapp.GenesisState.TransfersEnabled = true + rollapp.GenesisState.TransferProofHeight = 1 s.k().SetRollapp(s.Ctx, rollapp) var ( diff --git a/x/rollapp/keeper/hard_fork.go b/x/rollapp/keeper/hard_fork.go index db19ff82e..de500eeba 100644 --- a/x/rollapp/keeper/hard_fork.go +++ b/x/rollapp/keeper/hard_fork.go @@ -19,6 +19,10 @@ func (k Keeper) HardFork(ctx sdk.Context, rollappID string, lastValidHeight uint return gerrc.ErrNotFound } + if !k.ForkAllowed(ctx, rollappID, lastValidHeight) { + return gerrc.ErrFailedPrecondition.Wrap("fork not allowed") + } + lastValidHeight, err := k.RevertPendingStates(ctx, rollappID, lastValidHeight+1) if err != nil { return errorsmod.Wrap(err, "revert pending states") @@ -203,3 +207,18 @@ func (k Keeper) IsFirstHeightOfLatestFork(ctx sdk.Context, rollappId string, rev latest := rollapp.LatestRevision().Number return rollapp.DidFork() && rollapp.IsRevisionStartHeight(revision, height) && revision == latest } + +// is forking to the latest height going to violate assumptions? +func (k Keeper) ForkLatestAllowed(ctx sdk.Context, rollapp string) bool { + lastHeight, ok := k.GetLatestHeight(ctx, rollapp) + if !ok { + return false + } + return k.ForkAllowed(ctx, rollapp, lastHeight) +} + +// is the rollback fork going to violate assumptions? +func (k Keeper) ForkAllowed(ctx sdk.Context, rollapp string, lastValidHeight uint64) bool { + ra := k.MustGetRollapp(ctx, rollapp) + return 0 < ra.GenesisState.TransferProofHeight && ra.GenesisState.TransferProofHeight <= lastValidHeight +} diff --git a/x/rollapp/keeper/hard_fork_test.go b/x/rollapp/keeper/hard_fork_test.go index b664affc6..8c8390a20 100644 --- a/x/rollapp/keeper/hard_fork_test.go +++ b/x/rollapp/keeper/hard_fork_test.go @@ -61,6 +61,10 @@ func (s *RollappTestSuite) TestHardFork() { _ = s.CreateDefaultSequencer(s.Ctx, rollappId) } + ra := s.k().MustGetRollapp(s.Ctx, rollappId) + ra.GenesisState.TransferProofHeight = 1 + s.k().SetRollapp(s.Ctx, ra) + // send state updates lastHeight = 1 for i := uint64(0); i < tc.statesCommitted; i++ { diff --git a/x/rollapp/keeper/liveness_test.go b/x/rollapp/keeper/liveness_test.go index b83801fe4..5ade3cbcf 100644 --- a/x/rollapp/keeper/liveness_test.go +++ b/x/rollapp/keeper/liveness_test.go @@ -158,7 +158,7 @@ func (s *RollappTestSuite) TestLivenessFlow() { s.k().SetSequencerKeeper(tracker) for _, ra := range rollapps { s.k().SetRollapp(s.Ctx, types.NewRollapp("", ra, "", - types.Rollapp_Unspecified, nil, types.GenesisInfo{}, false)) + types.Rollapp_Unspecified, nil, types.GenesisInfo{})) } hClockStart := map[string]int64{} diff --git a/x/rollapp/keeper/msg_server_mark_obsolete_rollapps_test.go b/x/rollapp/keeper/msg_server_mark_obsolete_rollapps_test.go index b98ed3a9e..f97f22504 100644 --- a/x/rollapp/keeper/msg_server_mark_obsolete_rollapps_test.go +++ b/x/rollapp/keeper/msg_server_mark_obsolete_rollapps_test.go @@ -120,6 +120,9 @@ func (s *RollappTestSuite) TestMarkObsoleteRollapps() { for _, ra := range tc.rollapps { // create a rollapp s.CreateRollappByName(ra.name) + raObj := s.k().MustGetRollapp(s.Ctx, ra.name) + raObj.GenesisState.TransferProofHeight = 1 + s.k().SetRollapp(s.Ctx, raObj) // create a sequencer proposer := s.CreateDefaultSequencer(s.Ctx, ra.name) diff --git a/x/rollapp/types/message_create_rollapp.go b/x/rollapp/types/message_create_rollapp.go index 516b721f5..c90949a7f 100644 --- a/x/rollapp/types/message_create_rollapp.go +++ b/x/rollapp/types/message_create_rollapp.go @@ -65,7 +65,6 @@ func (msg *MsgCreateRollapp) GetRollapp() Rollapp { msg.VmType, msg.Metadata, genInfo, - false, ) } diff --git a/x/rollapp/types/rollapp.go b/x/rollapp/types/rollapp.go index 4492d719e..5f257a6ef 100644 --- a/x/rollapp/types/rollapp.go +++ b/x/rollapp/types/rollapp.go @@ -49,7 +49,6 @@ func NewRollapp( vmType Rollapp_VMType, metadata *RollappMetadata, genInfo GenesisInfo, - transfersEnabled bool, ) Rollapp { return Rollapp{ RollappId: rollappId, @@ -58,9 +57,7 @@ func NewRollapp( VmType: vmType, Metadata: metadata, GenesisInfo: genInfo, - GenesisState: RollappGenesisState{ - TransfersEnabled: transfersEnabled, - }, + GenesisState: RollappGenesisState{}, Revisions: []Revision{{ Number: 0, StartHeight: 0, @@ -107,7 +104,11 @@ func (r Rollapp) ValidateBasic() error { } func (r Rollapp) IsTransferEnabled() bool { - return r.GenesisState.TransfersEnabled + return r.GenesisState.IsTransferEnabled() +} + +func (s RollappGenesisState) IsTransferEnabled() bool { + return s.TransferProofHeight != 0 } func (r Rollapp) AllImmutableFieldsAreSet() bool { diff --git a/x/rollapp/types/rollapp.pb.go b/x/rollapp/types/rollapp.pb.go index 4e90a5533..1b234c7db 100644 --- a/x/rollapp/types/rollapp.pb.go +++ b/x/rollapp/types/rollapp.pb.go @@ -59,14 +59,11 @@ func (Rollapp_VMType) EnumDescriptor() ([]byte, []int) { // RollappGenesisState is a partial repr of the state the hub can expect the // rollapp to be in upon genesis type RollappGenesisState struct { - // If true, then full usage of the canonical ibc transfer channel is enabled. - // Note: in v3.1.0 and prior this field marked the completion of the 'genesis - // event' Keeping and renaming the field enables a seamless upgrade - // https://www.notion.so/dymension/ADR-x-Genesis-Bridge-Phase-2-89769aa551b5440b9ed403a101775ce1?pvs=4#89698384d815435b87393dbe45bc5a74 - // to the new genesis transfer protocol - // Note: if this field is false, ibc transfers may still be allowed in one or - // either direction. - TransfersEnabled bool `protobuf:"varint,2,opt,name=transfers_enabled,json=transfersEnabled,proto3" json:"transfers_enabled,omitempty"` + // 0 means unpopulated + // If populated, it's the proof height that the hub received the genesis transfer + // packet from the rollapp. If populated, the bridge is considered open. It's not allowed + // to fork to a height prior to this height. + TransferProofHeight uint64 `protobuf:"varint,3,opt,name=transfer_proof_height,json=transferProofHeight,proto3" json:"transfer_proof_height,omitempty"` } func (m *RollappGenesisState) Reset() { *m = RollappGenesisState{} } @@ -102,11 +99,11 @@ func (m *RollappGenesisState) XXX_DiscardUnknown() { var xxx_messageInfo_RollappGenesisState proto.InternalMessageInfo -func (m *RollappGenesisState) GetTransfersEnabled() bool { +func (m *RollappGenesisState) GetTransferProofHeight() uint64 { if m != nil { - return m.TransfersEnabled + return m.TransferProofHeight } - return false + return 0 } // Rollapp defines a rollapp object. First, the RollApp is created and then @@ -424,56 +421,57 @@ func init() { } var fileDescriptor_d4ef2bec3aea5528 = []byte{ - // 781 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xcd, 0x6e, 0xdb, 0x46, - 0x10, 0x16, 0x2d, 0x46, 0xa2, 0x86, 0xb2, 0xcd, 0xac, 0x9d, 0x96, 0x15, 0x12, 0x59, 0xd5, 0x89, - 0x40, 0x52, 0x12, 0xb1, 0xf3, 0x02, 0x75, 0xa1, 0xc6, 0x76, 0xe3, 0x1e, 0x28, 0x37, 0x05, 0x72, - 0x28, 0x41, 0x89, 0x2b, 0x6a, 0x01, 0x72, 0x97, 0xe5, 0xae, 0x14, 0x2b, 0x4f, 0x91, 0x97, 0x2a, - 0x90, 0x63, 0xd0, 0x53, 0x4f, 0x6d, 0x61, 0xbf, 0x48, 0xc1, 0xe5, 0x92, 0x52, 0x9a, 0xa4, 0x32, - 0x7a, 0x5a, 0xce, 0x7c, 0x33, 0xdf, 0xfc, 0xec, 0x7e, 0x84, 0x27, 0xd1, 0x2a, 0xc5, 0x94, 0x13, - 0x46, 0xaf, 0x57, 0x6f, 0xbc, 0xda, 0xf0, 0x72, 0x96, 0x24, 0x61, 0x96, 0x55, 0xa7, 0x9b, 0xe5, - 0x4c, 0x30, 0xd4, 0xdf, 0x8c, 0x76, 0x6b, 0xc3, 0x55, 0x51, 0xbd, 0xc3, 0x98, 0xc5, 0x4c, 0x86, - 0x7a, 0xc5, 0x57, 0x99, 0xd5, 0x3b, 0x8a, 0x19, 0x8b, 0x13, 0xec, 0x49, 0x6b, 0xb2, 0x98, 0x79, - 0x82, 0xa4, 0x98, 0x8b, 0x30, 0x55, 0xb4, 0xbd, 0x2f, 0xa7, 0x8c, 0xa7, 0x8c, 0x7b, 0x29, 0x8f, - 0xbd, 0xe5, 0xd3, 0xe2, 0x50, 0x80, 0xb7, 0xa5, 0x3b, 0x2e, 0x42, 0x81, 0x03, 0x42, 0x67, 0x55, - 0xa9, 0x6f, 0xb6, 0x24, 0xa4, 0x58, 0x84, 0x51, 0x28, 0x42, 0x15, 0xfe, 0x74, 0x4b, 0x78, 0x8c, - 0x29, 0xe6, 0x84, 0x6f, 0x54, 0x18, 0x9e, 0xc1, 0x81, 0x5f, 0xa2, 0xcf, 0x4b, 0x70, 0x5c, 0xf4, - 0x80, 0x1e, 0xc3, 0x7d, 0x91, 0x87, 0x94, 0xcf, 0x70, 0xce, 0x03, 0x4c, 0xc3, 0x49, 0x82, 0x23, - 0x7b, 0x67, 0xa0, 0x39, 0x86, 0x6f, 0xd5, 0xc0, 0xa8, 0xf4, 0x5f, 0xe8, 0x86, 0x66, 0xed, 0x0c, - 0x7f, 0x6b, 0x41, 0x5b, 0x51, 0xa1, 0x47, 0x00, 0xaa, 0x66, 0x40, 0x22, 0x5b, 0x1b, 0x68, 0x4e, - 0xc7, 0xef, 0x28, 0xcf, 0x79, 0x84, 0x0e, 0xe1, 0x1e, 0x7b, 0x4d, 0x71, 0x2e, 0x19, 0x3b, 0x7e, - 0x69, 0xa0, 0x5f, 0x60, 0xb7, 0x6a, 0x50, 0x2e, 0xc2, 0x6e, 0x0f, 0x34, 0xc7, 0x3c, 0x3e, 0x71, - 0xff, 0xfb, 0x96, 0xdc, 0x4f, 0xf4, 0x7f, 0xaa, 0xbf, 0xfb, 0xf3, 0xa8, 0xe1, 0x77, 0xe3, 0xcd, - 0x99, 0x1e, 0x01, 0x4c, 0xe7, 0x21, 0xa5, 0x38, 0x29, 0x9a, 0x32, 0xca, 0xa6, 0x94, 0xe7, 0x3c, - 0x42, 0x3f, 0x80, 0x51, 0xad, 0xd3, 0x36, 0x65, 0x65, 0xef, 0x8e, 0x95, 0x2f, 0x55, 0x9a, 0x5f, - 0x13, 0xa0, 0x2b, 0xe8, 0x6e, 0x2e, 0xdb, 0xee, 0x4a, 0xc2, 0xc7, 0xdb, 0x08, 0xd5, 0x0c, 0xe7, - 0x74, 0xc6, 0xd4, 0x08, 0x66, 0xbc, 0x76, 0x15, 0xb7, 0x42, 0x28, 0x11, 0x24, 0x4c, 0x02, 0x8e, - 0x7f, 0x5d, 0x60, 0x3a, 0xc5, 0xb9, 0xbd, 0x2b, 0x07, 0xb1, 0x14, 0x30, 0xae, 0xfc, 0xe8, 0x39, - 0xb4, 0x97, 0x69, 0x20, 0x56, 0x19, 0xb6, 0xf7, 0x06, 0x9a, 0xb3, 0x77, 0xec, 0xde, 0x71, 0x1c, - 0xf7, 0xe5, 0xe5, 0xd5, 0x2a, 0xc3, 0x7e, 0x6b, 0x99, 0x16, 0x27, 0xea, 0x81, 0x91, 0x84, 0x0b, - 0x3a, 0x9d, 0xe3, 0xc8, 0xde, 0x97, 0x4f, 0xa0, 0xb6, 0xd1, 0x19, 0xec, 0x67, 0x39, 0x0e, 0x4a, - 0x3b, 0x28, 0x84, 0x60, 0x5b, 0x72, 0xd4, 0x9e, 0x5b, 0xaa, 0xc4, 0xad, 0x54, 0xe2, 0x5e, 0x55, - 0x2a, 0x39, 0xd5, 0xdf, 0xfe, 0x75, 0xa4, 0xf9, 0xbb, 0x59, 0x8e, 0x5f, 0xc8, 0xbc, 0x02, 0x41, - 0xc7, 0xf0, 0x20, 0x21, 0xcb, 0x62, 0x58, 0x1e, 0xe0, 0x25, 0xa6, 0x22, 0x98, 0x63, 0x12, 0xcf, - 0x85, 0x7d, 0x7f, 0xa0, 0x39, 0x4d, 0xff, 0xa0, 0x02, 0x47, 0x05, 0x76, 0x26, 0x21, 0x34, 0x82, - 0xa3, 0x3a, 0x67, 0xca, 0x16, 0x54, 0x44, 0xec, 0x35, 0x2d, 0x1e, 0x4f, 0x5e, 0x67, 0x23, 0x99, - 0xfd, 0xb0, 0x0a, 0xfb, 0xae, 0x8a, 0x1a, 0x17, 0x41, 0x8a, 0xe6, 0x05, 0x74, 0x72, 0xbc, 0x24, - 0xc5, 0x2e, 0xb8, 0x7d, 0x30, 0x68, 0x3a, 0xe6, 0xb1, 0xb3, 0x75, 0x57, 0x2a, 0x41, 0x5d, 0xd3, - 0x9a, 0x60, 0xf8, 0x04, 0x5a, 0xe5, 0x02, 0xd1, 0x3e, 0x98, 0x3f, 0x51, 0x9e, 0xe1, 0x29, 0x99, - 0x11, 0x1c, 0x59, 0x0d, 0xd4, 0x86, 0xe6, 0xe8, 0xe5, 0xa5, 0xa5, 0x21, 0x03, 0xf4, 0x9f, 0xbf, - 0x1d, 0x5f, 0x5a, 0x3b, 0x17, 0xba, 0xd1, 0xb4, 0xda, 0x17, 0xba, 0xd1, 0xb1, 0xe0, 0x42, 0x37, - 0xc0, 0x32, 0x87, 0x23, 0x30, 0x2a, 0x72, 0xf4, 0x05, 0xb4, 0xe8, 0x22, 0x9d, 0xe0, 0xdc, 0x3e, - 0x18, 0x68, 0x8e, 0xee, 0x2b, 0x0b, 0x7d, 0x0d, 0xdd, 0x0f, 0xa6, 0x3c, 0x94, 0xa8, 0xc9, 0xd7, - 0x43, 0x0d, 0x7f, 0xdf, 0x81, 0x3d, 0x75, 0xa1, 0xe3, 0x45, 0x9a, 0x86, 0xf9, 0x0a, 0x3d, 0x84, - 0xb5, 0x06, 0x3f, 0x16, 0xe5, 0x2b, 0xb0, 0x92, 0x50, 0x60, 0x2e, 0xa4, 0x5a, 0xce, 0x69, 0x84, - 0xaf, 0xa5, 0x3e, 0xcd, 0xed, 0x0f, 0x47, 0x65, 0xcc, 0x98, 0xcc, 0xf2, 0x3f, 0xe2, 0x41, 0x09, - 0x7c, 0x55, 0xfa, 0xbe, 0x27, 0x34, 0x4c, 0xc8, 0x1b, 0x1c, 0x6d, 0x14, 0x69, 0xfe, 0xaf, 0x22, - 0x9f, 0x27, 0x44, 0x43, 0xe8, 0x96, 0x60, 0xb9, 0x0a, 0x5b, 0x97, 0xdb, 0xf9, 0xc0, 0x87, 0x9e, - 0xc1, 0x83, 0x7f, 0x11, 0xa8, 0xe0, 0x7b, 0x32, 0xf8, 0xd3, 0xe0, 0xe9, 0x8f, 0xef, 0x6e, 0xfa, - 0xda, 0xfb, 0x9b, 0xbe, 0xf6, 0xf7, 0x4d, 0x5f, 0x7b, 0x7b, 0xdb, 0x6f, 0xbc, 0xbf, 0xed, 0x37, - 0xfe, 0xb8, 0xed, 0x37, 0x5e, 0x3d, 0x8b, 0x89, 0x98, 0x2f, 0x26, 0xee, 0x94, 0xa5, 0x9f, 0xfb, - 0xcb, 0x2f, 0x4f, 0xbc, 0xeb, 0xfa, 0x57, 0x5c, 0xe8, 0x92, 0x4f, 0x5a, 0x52, 0x1d, 0x27, 0xff, - 0x04, 0x00, 0x00, 0xff, 0xff, 0x11, 0x26, 0x3f, 0x1d, 0xb7, 0x06, 0x00, 0x00, + // 786 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xdd, 0x6e, 0xdb, 0x36, + 0x14, 0xb6, 0x62, 0xd5, 0x56, 0x8e, 0x9c, 0x44, 0xa5, 0xd3, 0x4d, 0x33, 0x5a, 0xc7, 0xf3, 0x95, + 0x80, 0x76, 0x12, 0x9a, 0xf4, 0x05, 0x96, 0x21, 0x6b, 0xed, 0xd5, 0xc3, 0x20, 0xa7, 0x1d, 0xd0, + 0x8b, 0x09, 0xb2, 0x45, 0xcb, 0x04, 0x24, 0x52, 0x13, 0x69, 0x37, 0xee, 0x53, 0xf4, 0xa5, 0x06, + 0xf4, 0xb2, 0xd8, 0xd5, 0xae, 0xb6, 0x21, 0x79, 0x91, 0x41, 0x14, 0x65, 0xbb, 0x6b, 0x3b, 0x07, + 0xbb, 0xa2, 0xce, 0xf9, 0xce, 0xf9, 0xce, 0x0f, 0xf9, 0x09, 0x1e, 0x45, 0xab, 0x14, 0x53, 0x4e, + 0x18, 0xbd, 0x5a, 0xbd, 0xf1, 0xd6, 0x86, 0x97, 0xb3, 0x24, 0x09, 0xb3, 0xac, 0x3a, 0xdd, 0x2c, + 0x67, 0x82, 0xa1, 0xee, 0x76, 0xb4, 0xbb, 0x36, 0x5c, 0x15, 0xd5, 0x39, 0x8e, 0x59, 0xcc, 0x64, + 0xa8, 0x57, 0x7c, 0x95, 0x59, 0x9d, 0x93, 0x98, 0xb1, 0x38, 0xc1, 0x9e, 0xb4, 0x26, 0x8b, 0x99, + 0x27, 0x48, 0x8a, 0xb9, 0x08, 0x53, 0x45, 0xdb, 0xf9, 0x72, 0xca, 0x78, 0xca, 0xb8, 0x97, 0xf2, + 0xd8, 0x5b, 0x3e, 0x2e, 0x0e, 0x05, 0x78, 0x3b, 0xba, 0xe3, 0x22, 0x14, 0x38, 0x20, 0x74, 0x56, + 0x95, 0xfa, 0x66, 0x47, 0x42, 0x8a, 0x45, 0x18, 0x85, 0x22, 0x54, 0xe1, 0x8f, 0x77, 0x84, 0xc7, + 0x98, 0x62, 0x4e, 0xf8, 0x56, 0x85, 0xfe, 0x0b, 0x68, 0xfb, 0x25, 0xfa, 0xb4, 0x04, 0xc7, 0x45, + 0x0f, 0xe8, 0x14, 0xee, 0x89, 0x3c, 0xa4, 0x7c, 0x86, 0xf3, 0x20, 0xcb, 0x19, 0x9b, 0x05, 0x73, + 0x4c, 0xe2, 0xb9, 0xb0, 0xeb, 0x3d, 0xcd, 0xd1, 0xfd, 0x76, 0x05, 0xfe, 0x54, 0x60, 0xcf, 0x24, + 0x34, 0xd4, 0x0d, 0xcd, 0xda, 0x1b, 0xea, 0xc6, 0x9e, 0x55, 0xef, 0xff, 0xd6, 0x80, 0xa6, 0xe2, + 0x45, 0x0f, 0x00, 0x54, 0x03, 0x01, 0x89, 0x6c, 0xad, 0xa7, 0x39, 0xfb, 0xfe, 0xbe, 0xf2, 0x0c, + 0x22, 0x74, 0x0c, 0x77, 0xd8, 0x6b, 0x8a, 0x73, 0x7b, 0x4f, 0x22, 0xa5, 0x81, 0x7e, 0x81, 0x83, + 0xaa, 0x5b, 0xb9, 0x15, 0xbb, 0xd9, 0xd3, 0x1c, 0xf3, 0xf4, 0xcc, 0xfd, 0xef, 0x2b, 0x73, 0x3f, + 0x31, 0xcc, 0xb9, 0xfe, 0xee, 0xcf, 0x93, 0x9a, 0xdf, 0x8a, 0xb7, 0x07, 0x7c, 0x00, 0x30, 0x9d, + 0x87, 0x94, 0xe2, 0xa4, 0x68, 0xca, 0x28, 0x9b, 0x52, 0x9e, 0x41, 0x84, 0x7e, 0x00, 0xa3, 0xda, + 0xad, 0x6d, 0xca, 0xca, 0xde, 0x2d, 0x2b, 0x8f, 0x54, 0x9a, 0xbf, 0x26, 0x40, 0x97, 0xd0, 0xda, + 0xde, 0xbc, 0xdd, 0x92, 0x84, 0x0f, 0x77, 0x11, 0xaa, 0x19, 0x06, 0x74, 0xc6, 0xd4, 0x08, 0x66, + 0xbc, 0x71, 0xa1, 0x87, 0x70, 0x97, 0x50, 0x22, 0x48, 0x98, 0x04, 0x1c, 0xff, 0xba, 0xc0, 0x74, + 0x8a, 0x73, 0xfb, 0x40, 0x0e, 0x62, 0x29, 0x60, 0x5c, 0xf9, 0xd1, 0x53, 0x68, 0x2e, 0xd3, 0x40, + 0xac, 0x32, 0x6c, 0x1f, 0xf6, 0x34, 0xe7, 0xf0, 0xd4, 0xbd, 0xe5, 0x38, 0xee, 0xcb, 0xd1, 0xe5, + 0x2a, 0xc3, 0x7e, 0x63, 0x99, 0x16, 0x27, 0xea, 0x80, 0x91, 0x84, 0x0b, 0x3a, 0x9d, 0xe3, 0xc8, + 0x3e, 0xea, 0x69, 0x8e, 0xe1, 0xaf, 0x6d, 0xf4, 0x0c, 0x8e, 0xb2, 0x1c, 0x07, 0xa5, 0x1d, 0x14, + 0xaa, 0xb0, 0x2d, 0x39, 0x6a, 0xc7, 0x2d, 0x25, 0xe3, 0x56, 0x92, 0x71, 0x2f, 0x2b, 0xc9, 0x9c, + 0xeb, 0x6f, 0xff, 0x3a, 0xd1, 0xfc, 0x83, 0x2c, 0xc7, 0xcf, 0x65, 0x5e, 0x81, 0x14, 0xcf, 0x2f, + 0x21, 0xcb, 0x62, 0x58, 0x1e, 0xe0, 0x25, 0xa6, 0xa2, 0x7a, 0x7e, 0x77, 0x7b, 0x9a, 0x53, 0xf7, + 0xdb, 0x15, 0x78, 0x51, 0x60, 0xe5, 0xf3, 0x43, 0x17, 0x70, 0xb2, 0xce, 0x99, 0xb2, 0x05, 0x15, + 0x11, 0x7b, 0x4d, 0x8b, 0xc7, 0x93, 0xaf, 0xb3, 0x91, 0xcc, 0xbe, 0x5f, 0x85, 0x7d, 0x57, 0x45, + 0x8d, 0x8b, 0x20, 0x45, 0xf3, 0x1c, 0xf6, 0x73, 0xbc, 0x24, 0xc5, 0x2e, 0xb8, 0xdd, 0xee, 0xd5, + 0x1d, 0xf3, 0xd4, 0xd9, 0xb9, 0x2b, 0x95, 0xa0, 0xae, 0x69, 0x43, 0xd0, 0x7f, 0x04, 0x8d, 0x72, + 0x81, 0xe8, 0x08, 0xcc, 0x17, 0x94, 0x67, 0x78, 0x4a, 0x66, 0x04, 0x47, 0x56, 0x0d, 0x35, 0xa1, + 0x7e, 0xf1, 0x72, 0x64, 0x69, 0xc8, 0x00, 0xfd, 0xe7, 0x6f, 0xc7, 0x23, 0xa9, 0x9d, 0xba, 0xd5, + 0x1c, 0xea, 0xc6, 0xbe, 0x05, 0x43, 0xdd, 0x00, 0xcb, 0xec, 0x5f, 0x80, 0x51, 0x91, 0xa3, 0x2f, + 0xa0, 0x41, 0x17, 0xe9, 0x04, 0xe7, 0x76, 0x5b, 0x8a, 0x50, 0x59, 0xe8, 0x6b, 0x68, 0x7d, 0x30, + 0xe5, 0xb1, 0x44, 0x4d, 0xbe, 0x19, 0xaa, 0xff, 0xfb, 0x1e, 0x1c, 0xaa, 0x0b, 0x1d, 0x2f, 0xd2, + 0x34, 0xcc, 0x57, 0xe8, 0x3e, 0x6c, 0x34, 0xf8, 0xb1, 0x28, 0x5f, 0x81, 0x95, 0x84, 0x02, 0x73, + 0x21, 0xd5, 0x32, 0xa0, 0x11, 0xbe, 0x92, 0xfa, 0x34, 0x77, 0x3f, 0x1c, 0x95, 0x31, 0x63, 0x32, + 0xcb, 0xff, 0x88, 0x07, 0x25, 0xf0, 0x55, 0xe9, 0xfb, 0x9e, 0xd0, 0x30, 0x21, 0x6f, 0x70, 0xb4, + 0x55, 0xa4, 0xfe, 0xbf, 0x8a, 0x7c, 0x9e, 0x10, 0xf5, 0xa1, 0x55, 0x82, 0xe5, 0x2a, 0x6c, 0x5d, + 0x6e, 0xe7, 0x03, 0x1f, 0x7a, 0x02, 0xf7, 0xfe, 0x45, 0xa0, 0x82, 0xef, 0xc8, 0xe0, 0x4f, 0x83, + 0xe7, 0x3f, 0xbe, 0xbb, 0xee, 0x6a, 0xef, 0xaf, 0xbb, 0xda, 0xdf, 0xd7, 0x5d, 0xed, 0xed, 0x4d, + 0xb7, 0xf6, 0xfe, 0xa6, 0x5b, 0xfb, 0xe3, 0xa6, 0x5b, 0x7b, 0xf5, 0x24, 0x26, 0x62, 0xbe, 0x98, + 0xb8, 0x53, 0x96, 0x7e, 0xee, 0x97, 0xbf, 0x3c, 0xf3, 0xae, 0xd6, 0xff, 0xe5, 0x42, 0x97, 0x7c, + 0xd2, 0x90, 0xea, 0x38, 0xfb, 0x27, 0x00, 0x00, 0xff, 0xff, 0x04, 0x5c, 0xa5, 0xfe, 0xc4, 0x06, + 0x00, 0x00, } func (m *RollappGenesisState) Marshal() (dAtA []byte, err error) { @@ -496,15 +494,10 @@ func (m *RollappGenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.TransfersEnabled { - i-- - if m.TransfersEnabled { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } + if m.TransferProofHeight != 0 { + i = encodeVarintRollapp(dAtA, i, uint64(m.TransferProofHeight)) i-- - dAtA[i] = 0x10 + dAtA[i] = 0x18 } return len(dAtA) - i, nil } @@ -767,8 +760,8 @@ func (m *RollappGenesisState) Size() (n int) { } var l int _ = l - if m.TransfersEnabled { - n += 2 + if m.TransferProofHeight != 0 { + n += 1 + sovRollapp(uint64(m.TransferProofHeight)) } return n } @@ -905,11 +898,11 @@ func (m *RollappGenesisState) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: RollappGenesisState: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 2: + case 3: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TransfersEnabled", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TransferProofHeight", wireType) } - var v int + m.TransferProofHeight = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowRollapp @@ -919,12 +912,11 @@ func (m *RollappGenesisState) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + m.TransferProofHeight |= uint64(b&0x7F) << shift if b < 0x80 { break } } - m.TransfersEnabled = bool(v != 0) default: iNdEx = preIndex skippy, err := skipRollapp(dAtA[iNdEx:]) diff --git a/x/sequencer/handler.go b/x/sequencer/handler.go deleted file mode 100644 index da57555b7..000000000 --- a/x/sequencer/handler.go +++ /dev/null @@ -1,41 +0,0 @@ -package sequencer - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/dymensionxyz/gerr-cosmos/gerrc" - - "github.com/dymensionxyz/dymension/v3/x/sequencer/keeper" - "github.com/dymensionxyz/dymension/v3/x/sequencer/types" -) - -// NewHandler ... -func NewHandler(k *keeper.Keeper) sdk.Handler { - msgServer := keeper.NewMsgServerImpl(k) - - return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { - ctx = ctx.WithEventManager(sdk.NewEventManager()) - - switch msg := msg.(type) { - case *types.MsgCreateSequencer: - res, err := msgServer.CreateSequencer(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - case *types.MsgUpdateSequencerInformation: - res, err := msgServer.UpdateSequencerInformation(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - case *types.MsgUnbond: - res, err := msgServer.Unbond(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - case *types.MsgIncreaseBond: - res, err := msgServer.IncreaseBond(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - case *types.MsgDecreaseBond: - res, err := msgServer.DecreaseBond(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - default: - errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) - return nil, gerrc.ErrInvalidArgument.Wrap(errMsg) - } - } -} diff --git a/x/sequencer/keeper/fraud.go b/x/sequencer/keeper/fraud.go index 5d0b9ecc6..3e3530355 100644 --- a/x/sequencer/keeper/fraud.go +++ b/x/sequencer/keeper/fraud.go @@ -12,6 +12,10 @@ import ( // TryKickProposer tries to remove the incumbent proposer. It requires the incumbent // proposer to be below a threshold of bond. The caller must also be bonded and opted in. func (k Keeper) TryKickProposer(ctx sdk.Context, kicker types.Sequencer) error { + if !kicker.IsPotentialProposer() { + return errorsmod.Wrap(gerrc.ErrFailedPrecondition, "kicker is not a potential proposer") + } + ra := kicker.RollappId proposer := k.GetProposer(ctx, ra) diff --git a/x/sequencer/keeper/fraud_test.go b/x/sequencer/keeper/fraud_test.go index 1047bbf7f..e9f94f400 100644 --- a/x/sequencer/keeper/fraud_test.go +++ b/x/sequencer/keeper/fraud_test.go @@ -96,6 +96,7 @@ func (s *SequencerTestSuite) TestFraudFullFlowDuringRotation() { s.createSequencerWithBond(s.Ctx, ra.RollappId, charlie, ucoin.SimpleMul(bond, 1)) s.Require().True(s.k().IsProposer(s.Ctx, s.seq(alice))) s.Require().False(s.k().IsSuccessor(s.Ctx, s.seq(bob))) + s.submitAFewRollappStates(ra.RollappId) // proposer tries to unbond mUnbond := &types.MsgUnbond{Creator: pkAddr(alice)} diff --git a/x/sequencer/keeper/msg_server_bond.go b/x/sequencer/keeper/msg_server_bond.go index d718f14c4..d02fece7e 100644 --- a/x/sequencer/keeper/msg_server_bond.go +++ b/x/sequencer/keeper/msg_server_bond.go @@ -76,6 +76,9 @@ func (k msgServer) Unbond(goCtx context.Context, msg *types.MsgUnbond) (*types.M // now we know they are proposer // avoid starting another notice unnecessarily if k.IsProposer(ctx, seq) { + if !k.rollappKeeper.ForkLatestAllowed(ctx, seq.RollappId) { + return nil, gerrc.ErrFailedPrecondition.Wrap("rotation could cause fork before genesis transfer") + } if seq.NoticeInProgress(ctx.BlockTime()) { return nil, gerrc.ErrFailedPrecondition.Wrap("notice period in progress") } diff --git a/x/sequencer/keeper/msg_server_bond_test.go b/x/sequencer/keeper/msg_server_bond_test.go index 5383c939e..2303dc09e 100644 --- a/x/sequencer/keeper/msg_server_bond_test.go +++ b/x/sequencer/keeper/msg_server_bond_test.go @@ -97,6 +97,7 @@ func (s *SequencerTestSuite) TestDecreaseBondRestrictions() { currBond := ucoin.SimpleMul(bond, 3) seq := s.createSequencerWithBond(s.Ctx, ra.RollappId, bob, currBond) s.k().SetProposer(s.Ctx, ra.RollappId, seq.Address) + s.submitAFewRollappStates(ra.RollappId) m := &types.MsgDecreaseBond{ Creator: seq.Address, DecreaseAmount: bond, @@ -157,6 +158,7 @@ func (s *SequencerTestSuite) TestUnbondRestrictions() { s.Run("proposer - start notice", func() { seq := s.createSequencerWithBond(s.Ctx, ra.RollappId, bob, bond) s.k().SetProposer(s.Ctx, ra.RollappId, seq.Address) + s.submitAFewRollappStates(ra.RollappId) m := &types.MsgUnbond{ Creator: seq.Address, } diff --git a/x/sequencer/keeper/msg_server_kick_proposer.go b/x/sequencer/keeper/msg_server_kick_proposer.go index af7fe3aa9..3f5b23b94 100644 --- a/x/sequencer/keeper/msg_server_kick_proposer.go +++ b/x/sequencer/keeper/msg_server_kick_proposer.go @@ -3,18 +3,16 @@ package keeper import ( "context" - errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/dymensionxyz/dymension/v3/x/sequencer/types" - "github.com/dymensionxyz/gerr-cosmos/gerrc" ) func (k msgServer) KickProposer(goCtx context.Context, msg *types.MsgKickProposer) (*types.MsgKickProposerResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - kicker := k.GetSequencer(ctx, msg.GetCreator()) - if !kicker.IsPotentialProposer() { - return nil, errorsmod.Wrap(gerrc.ErrFailedPrecondition, "kicker is not a potential proposer") + kicker, err := k.RealSequencer(ctx, msg.GetCreator()) + if err != nil { + return nil, err } if err := k.Keeper.TryKickProposer(ctx, kicker); err != nil { diff --git a/x/sequencer/keeper/msg_server_kick_proposer_test.go b/x/sequencer/keeper/msg_server_kick_proposer_test.go index 0a904cbe3..eb901d05d 100644 --- a/x/sequencer/keeper/msg_server_kick_proposer_test.go +++ b/x/sequencer/keeper/msg_server_kick_proposer_test.go @@ -11,14 +11,12 @@ func (s *SequencerTestSuite) TestKickProposerBasicFlow() { ra := s.createRollapp() seqAlice := s.createSequencerWithBond(s.Ctx, ra.RollappId, alice, bond) s.Require().True(s.k().IsProposer(s.Ctx, seqAlice)) - - _, err := s.PostStateUpdate(s.Ctx, ra.RollappId, seqAlice.Address, 1, 10) - s.Require().NoError(err) + s.submitAFewRollappStates(ra.RollappId) // bob tries to kick alice but he doesn't have a sequencer m := &types.MsgKickProposer{Creator: pkAddr(bob)} - _, err = s.msgServer.KickProposer(s.Ctx, m) - utest.IsErr(s.Require(), err, gerrc.ErrFailedPrecondition) + _, err := s.msgServer.KickProposer(s.Ctx, m) + utest.IsErr(s.Require(), err, gerrc.ErrNotFound) // bob creates a sequencer seqBob := s.createSequencerWithBond(s.Ctx, ra.RollappId, bob, bond) diff --git a/x/sequencer/keeper/rotation_test.go b/x/sequencer/keeper/rotation_test.go index fb53d41f1..4141881f6 100644 --- a/x/sequencer/keeper/rotation_test.go +++ b/x/sequencer/keeper/rotation_test.go @@ -15,6 +15,7 @@ func (s *SequencerTestSuite) TestRotationHappyFlow() { s.createSequencerWithBond(s.Ctx, ra.RollappId, bob, bond) s.Require().True(s.k().IsProposer(s.Ctx, s.seq(alice))) s.Require().False(s.k().IsSuccessor(s.Ctx, s.seq(bob))) + s.submitAFewRollappStates(ra.RollappId) // proposer tries to unbond mUnbond := &types.MsgUnbond{Creator: pkAddr(alice)} @@ -56,6 +57,7 @@ func (s *SequencerTestSuite) TestRotationReOptInFlow() { s.createSequencerWithBond(s.Ctx, ra.RollappId, charlie, ucoin.SimpleMul(bond, 1)) s.Require().True(s.k().IsProposer(s.Ctx, s.seq(alice))) s.Require().False(s.k().IsSuccessor(s.Ctx, s.seq(bob))) + s.submitAFewRollappStates(ra.RollappId) prop := alice succ := bob @@ -103,9 +105,7 @@ func (s *SequencerTestSuite) TestRotationNoSuccessor() { s.createSequencerWithBond(s.Ctx, ra.RollappId, alice, bond) s.Require().True(s.k().IsProposer(s.Ctx, s.seq(alice))) s.Require().True(s.k().IsSuccessor(s.Ctx, s.k().SentinelSequencer(s.Ctx))) - - _, err := s.PostStateUpdate(s.Ctx, ra.RollappId, s.seq(alice).Address, 1, 10) - s.Require().NoError(err) + s.submitAFewRollappStates(ra.RollappId) // proposer tries to unbond mUnbond := &types.MsgUnbond{Creator: pkAddr(alice)} @@ -138,6 +138,7 @@ func (s *SequencerTestSuite) TestRotationProposerAndSuccessorBothUnbond() { s.createSequencerWithBond(s.Ctx, ra.RollappId, charlie, ucoin.SimpleMul(bond, 1)) s.Require().True(s.k().IsProposer(s.Ctx, s.seq(alice))) s.Require().False(s.k().IsSuccessor(s.Ctx, s.seq(bob))) + s.submitAFewRollappStates(ra.RollappId) // proposer tries to unbond mUnbond := &types.MsgUnbond{Creator: pkAddr(alice)} diff --git a/x/sequencer/keeper/util_test.go b/x/sequencer/keeper/util_test.go index 088d33d80..c2f79800d 100644 --- a/x/sequencer/keeper/util_test.go +++ b/x/sequencer/keeper/util_test.go @@ -135,9 +135,17 @@ func (s *SequencerTestSuite) createRollappWithInitialSeqConstraint(initSeq strin InitialSupply: sdk.NewInt(1000), }, InitialSequencer: initSeq, + GenesisState: rollapptypes.RollappGenesisState{TransferProofHeight: 1}, } s.raK().SetRollapp(s.Ctx, rollapp) - return rollapp + return s.raK().MustGetRollapp(s.Ctx, rollapp.RollappId) +} + +func (s *SequencerTestSuite) submitAFewRollappStates(rollapp string) { + p := s.k().GetProposer(s.Ctx, rollapp) + h, _ := s.App.RollappKeeper.GetLatestHeight(s.Ctx, rollapp) + _, err := s.KeeperTestHelper.PostStateUpdate(s.Ctx, rollapp, p.Address, h, 10) + s.Require().NoError(err) } // Note: this method doesn't really mimic real usage diff --git a/x/sequencer/types/expected_keepers.go b/x/sequencer/types/expected_keepers.go index d0f263c03..19ca4ef93 100644 --- a/x/sequencer/types/expected_keepers.go +++ b/x/sequencer/types/expected_keepers.go @@ -14,6 +14,7 @@ type RollappKeeper interface { GetAllRollapps(ctx sdk.Context) (list []rollapptypes.Rollapp) SetRollappAsLaunched(ctx sdk.Context, rollapp *rollapptypes.Rollapp) error HardForkToLatest(ctx sdk.Context, rollappId string) error + ForkLatestAllowed(ctx sdk.Context, rollappId string) bool } // AccountKeeper defines the expected account keeper used for simulations (noalias)