Skip to content

Commit

Permalink
feat(hard-fork): Implement rollapp hard fork (#1354)
Browse files Browse the repository at this point in the history
Co-authored-by: keruch <53012408+keruch@users.noreply.github.com>
Co-authored-by: zale144 <aleksandar.sukovic@gmail.com>
Co-authored-by: Daniel T <30197399+danwt@users.noreply.github.com>
Co-authored-by: Omri <omritoptix@gmail.com>
Co-authored-by: Sergi Rene <sergi@dymension.xyz>
Co-authored-by: Itzhak Bokris <jzak300@gmail.com>
  • Loading branch information
7 people authored Nov 14, 2024
1 parent 80a53c7 commit 5deae85
Show file tree
Hide file tree
Showing 154 changed files with 3,802 additions and 2,850 deletions.
3 changes: 2 additions & 1 deletion app/ante/reject_msgs.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ante

import (
"errors"
"fmt"

errorsmod "cosmossdk.io/errors"
Expand Down Expand Up @@ -59,7 +60,7 @@ func (rmd RejectMessagesDecorator) AnteHandle(
next sdk.AnteHandler,
) (sdk.Context, error) {
if err := rmd.checkMsgs(ctx, tx.GetMsgs(), 0); err != nil {
return ctx, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, err.Error())
return ctx, errors.Join(sdkerrors.ErrUnauthorized, err)
}
return next(ctx, tx, simulate)
}
Expand Down
2 changes: 1 addition & 1 deletion app/apptesting/delayedack.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func GenerateTestPacket(t *testing.T, sequence uint64) *channeltypes.Packet {
func GenerateRollappPackets(t *testing.T, rollappId string, num uint64) []commontypes.RollappPacket {
t.Helper()
var packets []commontypes.RollappPacket
for i := uint64(0); i < num; i++ {
for i := uint64(1); i <= num; i++ {
packets = append(packets, commontypes.RollappPacket{
RollappId: rollappId,
Packet: GenerateTestPacket(t, i),
Expand Down
4 changes: 2 additions & 2 deletions app/apptesting/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (s *KeeperTestHelper) CreateRollappByName(name string) {

s.FundForAliasRegistration(msgCreateRollapp)

msgServer := rollappkeeper.NewMsgServerImpl(*s.App.RollappKeeper)
msgServer := rollappkeeper.NewMsgServerImpl(s.App.RollappKeeper)
_, err := msgServer.CreateRollapp(s.Ctx, &msgCreateRollapp)
s.Require().NoError(err)
}
Expand Down Expand Up @@ -135,7 +135,7 @@ func (s *KeeperTestHelper) PostStateUpdateWithDRSVersion(ctx sdk.Context, rollap
BDs: bds,
Last: false,
}
msgServer := rollappkeeper.NewMsgServerImpl(*s.App.RollappKeeper)
msgServer := rollappkeeper.NewMsgServerImpl(s.App.RollappKeeper)
_, err = msgServer.UpdateState(ctx, &updateState)
return startHeight + numOfBlocks, err
}
Expand Down
17 changes: 8 additions & 9 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ import (
lightclientmoduletypes "github.com/dymensionxyz/dymension/v3/x/lightclient/types"
lockupkeeper "github.com/dymensionxyz/dymension/v3/x/lockup/keeper"
lockuptypes "github.com/dymensionxyz/dymension/v3/x/lockup/types"
rollappmodule "github.com/dymensionxyz/dymension/v3/x/rollapp"
"github.com/dymensionxyz/dymension/v3/x/rollapp/genesisbridge"
rollappmodulekeeper "github.com/dymensionxyz/dymension/v3/x/rollapp/keeper"
rollappmoduletypes "github.com/dymensionxyz/dymension/v3/x/rollapp/types"
Expand Down Expand Up @@ -348,17 +347,11 @@ func (a *AppKeepers) InitKeepers(
a.ScopedIBCKeeper,
)

a.DenomMetadataKeeper = denommetadatamodulekeeper.NewKeeper(
a.BankKeeper,
)

a.RollappKeeper = rollappmodulekeeper.NewKeeper(
appCodec,
a.keys[rollappmoduletypes.StoreKey],
a.GetSubspace(rollappmoduletypes.ModuleName),
a.AccountKeeper,
a.IBCKeeper.ChannelKeeper,
a.IBCKeeper.ClientKeeper,
nil,
a.BankKeeper,
a.TransferKeeper,
Expand Down Expand Up @@ -403,6 +396,11 @@ func (a *AppKeepers) InitKeepers(
a.RollappKeeper.SetSequencerKeeper(a.SequencerKeeper)
a.RollappKeeper.SetCanonicalClientKeeper(a.LightClientKeeper)

a.DenomMetadataKeeper = denommetadatamodulekeeper.NewKeeper(
a.BankKeeper,
a.RollappKeeper,
)

a.IncentivesKeeper = incentiveskeeper.NewKeeper(
a.keys[incentivestypes.StoreKey],
a.GetSubspace(incentivestypes.ModuleName),
Expand Down Expand Up @@ -484,6 +482,7 @@ func (a *AppKeepers) InitKeepers(
a.DelayedAckKeeper = *delayedackkeeper.NewKeeper(
appCodec,
a.keys[delayedacktypes.StoreKey],
a.keys[ibcexported.StoreKey],
a.GetSubspace(delayedacktypes.ModuleName),
a.RollappKeeper,
a.IBCKeeper.ChannelKeeper,
Expand All @@ -503,7 +502,6 @@ func (a *AppKeepers) InitKeepers(
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(a.UpgradeKeeper)).
AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(a.IBCKeeper.ClientKeeper)).
AddRoute(streamermoduletypes.RouterKey, streamermodule.NewStreamerProposalHandler(a.StreamerKeeper)).
AddRoute(rollappmoduletypes.RouterKey, rollappmodule.NewRollappProposalHandler(a.RollappKeeper)).
AddRoute(denommetadatamoduletypes.RouterKey, denommetadatamodule.NewDenomMetadataProposalHandler(a.DenomMetadataKeeper)).
AddRoute(dymnstypes.RouterKey, dymnsmodule.NewDymNsProposalHandler(a.DymNSKeeper)).
AddRoute(evmtypes.RouterKey, evm.NewEvmProposalHandler(a.EvmKeeper))
Expand Down Expand Up @@ -628,11 +626,12 @@ func (a *AppKeepers) SetupHooks() {
a.RollappKeeper.SetHooks(rollappmoduletypes.NewMultiRollappHooks(
// insert rollapp hooks receivers here
a.SequencerKeeper.RollappHooks(),
a.delayedAckMiddleware,
a.DelayedAckKeeper,
a.StreamerKeeper.Hooks(),
a.DymNSKeeper.GetRollAppHooks(),
a.LightClientKeeper.RollappHooks(),
a.IROKeeper,
a.DenomMetadataKeeper.RollappHooks(),
))
}

Expand Down
2 changes: 0 additions & 2 deletions app/keepers/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ import (
lightclientmodule "github.com/dymensionxyz/dymension/v3/x/lightclient"
lightclientmoduletypes "github.com/dymensionxyz/dymension/v3/x/lightclient/types"
"github.com/dymensionxyz/dymension/v3/x/rollapp"
rollappmoduleclient "github.com/dymensionxyz/dymension/v3/x/rollapp/client"
rollappmoduletypes "github.com/dymensionxyz/dymension/v3/x/rollapp/types"
"github.com/dymensionxyz/dymension/v3/x/sequencer"
sequencertypes "github.com/dymensionxyz/dymension/v3/x/sequencer/types"
Expand Down Expand Up @@ -130,7 +129,6 @@ var ModuleBasics = module.NewBasicManager(
streamermoduleclient.TerminateStreamHandler,
streamermoduleclient.ReplaceStreamHandler,
streamermoduleclient.UpdateStreamHandler,
rollappmoduleclient.SubmitFraudHandler,
denommetadatamoduleclient.CreateDenomMetadataHandler,
denommetadatamoduleclient.UpdateDenomMetadataHandler,
dymnsmoduleclient.MigrateChainIdsProposalHandler,
Expand Down
3 changes: 2 additions & 1 deletion app/upgrades/v4/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,6 @@ func ConvertOldRollappToNew(oldRollapp rollapptypes.Rollapp) rollapptypes.Rollap
Owner: oldRollapp.Owner,
GenesisState: oldRollapp.GenesisState,
ChannelId: oldRollapp.ChannelId,
Frozen: oldRollapp.Frozen,
Metadata: &rollapptypes.RollappMetadata{ // Can be updated in runtime
Website: "",
Description: "",
Expand All @@ -336,6 +335,8 @@ func ConvertOldRollappToNew(oldRollapp rollapptypes.Rollapp) rollapptypes.Rollap
PreLaunchTime: nil, // We can just let it be zero. Existing rollapps are already launched.
LivenessEventHeight: 0, // Filled lazily in runtime
LastStateUpdateHeight: 0, // Filled lazily in runtime
RevisionNumber: 0,
RevisionStartHeight: 0,
}
}

Expand Down
5 changes: 5 additions & 0 deletions ibctesting/bridging_fee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ func TestBridgingFeeTestSuite(t *testing.T) {
suite.Run(t, new(bridgingFeeSuite))
}

func (s *bridgingFeeSuite) SetupTest() {
s.utilSuite.SetupTest()
s.hubApp().LightClientKeeper.SetEnabled(false)
}

func (s *bridgingFeeSuite) TestNotRollappNoBridgingFee() {
// setup between cosmosChain and hubChain
path := s.newTransferPath(s.hubChain(), s.cosmosChain())
Expand Down
114 changes: 114 additions & 0 deletions ibctesting/delayed_ack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/ibc-go/v7/modules/apps/transfer/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"
ibcmerkle "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types"
host "github.com/cosmos/ibc-go/v7/modules/core/24-host"
ibctesting "github.com/cosmos/ibc-go/v7/testing"
"github.com/cosmos/ibc-go/v7/testing/simapp"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)

Expand All @@ -25,6 +30,8 @@ func TestDelayedAckTestSuite(t *testing.T) {

func (s *delayedAckSuite) SetupTest() {
s.utilSuite.SetupTest()
s.hubApp().LightClientKeeper.SetEnabled(false)

s.hubApp().BankKeeper.SetDenomMetaData(s.hubCtx(), banktypes.Metadata{
Base: sdk.DefaultBondDenom,
})
Expand Down Expand Up @@ -235,3 +242,110 @@ func (s *delayedAckSuite) TestHubToRollappTimeout() {
postFinalizeBalance := bankKeeper.GetBalance(s.hubCtx(), senderAccount, sdk.DefaultBondDenom)
s.Require().Equal(preSendBalance.Amount, postFinalizeBalance.Amount)
}

// TestHardFork tests the hard fork handling for outgoing packets from the hub to the rollapp.
// we assert the packets commitments are restored and the pending packets are ackable after the hard fork.
func (s *delayedAckSuite) TestHardFork_HubToRollapp() {
path := s.newTransferPath(s.hubChain(), s.rollappChain())
s.coordinator.Setup(path)

// Setup endpoints
var (
hubEndpoint = path.EndpointA
hubIBCKeeper = s.hubChain().App.GetIBCKeeper()
senderAccount = s.hubChain().SenderAccount.GetAddress()
receiverAccount = s.rollappChain().SenderAccount.GetAddress()

amount, _ = sdk.NewIntFromString("1000000000000000000") // 1DYM
coinToSendToB = sdk.NewCoin(sdk.DefaultBondDenom, amount)
timeoutHeight = clienttypes.Height{RevisionNumber: 1, RevisionHeight: 50}
)

// Create rollapp and update its initial state
s.createRollappWithFinishedGenesis(path.EndpointA.ChannelID)
s.setRollappLightClientID(s.rollappCtx().ChainID(), path.EndpointA.ClientID)
s.registerSequencer()
s.updateRollappState(uint64(s.rollappCtx().BlockHeight()))

// send from hubChain to rollappChain
balanceBefore := s.hubApp().BankKeeper.GetBalance(s.hubCtx(), senderAccount, sdk.DefaultBondDenom)
msg := types.NewMsgTransfer(hubEndpoint.ChannelConfig.PortID, hubEndpoint.ChannelID, coinToSendToB, senderAccount.String(), receiverAccount.String(), timeoutHeight, disabledTimeoutTimestamp, "")
res, err := s.hubChain().SendMsgs(msg)
s.Require().NoError(err)
packet, err := ibctesting.ParsePacketFromEvents(res.GetEvents())
s.Require().NoError(err)

// assert commitments are created
found := hubIBCKeeper.ChannelKeeper.HasPacketCommitment(s.hubCtx(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
s.Require().True(found)

// Update the client
err = hubEndpoint.UpdateClient()
s.Require().NoError(err)

err = path.RelayPacket(packet)
s.Require().NoError(err) // expecting error as no AcknowledgePacket expected to return

// progress the rollapp chain
s.coordinator.CommitNBlocks(s.rollappChain(), 110)

// Update the client
err = hubEndpoint.UpdateClient()
s.Require().NoError(err)

// write ack optimistically
err = path.EndpointA.AcknowledgePacket(packet, []byte{0x1})
s.Require().NoError(err)

// assert commitments are no longer available
found = hubIBCKeeper.ChannelKeeper.HasPacketCommitment(s.hubCtx(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
s.Require().False(found)

// timeout the packet, can't check for error (ErrNoOp). we assert the balance refund
err = path.EndpointA.TimeoutPacket(packet)
s.Require().NoError(err)
balanceAfter := s.hubApp().BankKeeper.GetBalance(s.hubCtx(), senderAccount, sdk.DefaultBondDenom)
s.Require().NotEqual(balanceBefore.String(), balanceAfter.String())

// hard fork
err = s.hubApp().DelayedAckKeeper.OnHardFork(s.hubCtx(), s.rollappCtx().ChainID(), 5)
s.Require().NoError(err)

// assert commitments are created again
found = hubIBCKeeper.ChannelKeeper.HasPacketCommitment(s.hubCtx(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
s.Require().True(found)

// Update the client
err = hubEndpoint.UpdateClient()
s.Require().NoError(err)

// timeout the packet. we expect for verification error
timeoutMsg := getTimeOutPacket(hubEndpoint, packet)
_, _, err = simapp.SignAndDeliver(
path.EndpointA.Chain.T,
path.EndpointA.Chain.TxConfig,
path.EndpointA.Chain.App.GetBaseApp(),
path.EndpointA.Chain.GetContext().BlockHeader(),
[]sdk.Msg{timeoutMsg},
path.EndpointA.Chain.ChainID,
[]uint64{path.EndpointA.Chain.SenderAccount.GetAccountNumber()},
[]uint64{path.EndpointA.Chain.SenderAccount.GetSequence()},
true, false, path.EndpointA.Chain.SenderPrivKey,
)
s.Require().ErrorIs(err, ibcmerkle.ErrInvalidProof)
}

func getTimeOutPacket(endpoint *ibctesting.Endpoint, packet channeltypes.Packet) *channeltypes.MsgTimeout {
packetKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
counterparty := endpoint.Counterparty
proof, proofHeight := counterparty.QueryProof(packetKey)
nextSeqRecv, found := counterparty.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(counterparty.Chain.GetContext(), counterparty.ChannelConfig.PortID, counterparty.ChannelID)
require.True(endpoint.Chain.T, found)

timeoutMsg := channeltypes.NewMsgTimeout(
packet, nextSeqRecv,
proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String(),
)

return timeoutMsg
}
2 changes: 2 additions & 0 deletions ibctesting/eibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ func TestEIBCTestSuite(t *testing.T) {

func (s *eibcSuite) SetupTest() {
s.utilSuite.SetupTest()
s.hubApp().LightClientKeeper.SetEnabled(false)

s.hubApp().BankKeeper.SetDenomMetaData(s.hubCtx(), banktypes.Metadata{
Base: sdk.DefaultBondDenom,
})
Expand Down
7 changes: 2 additions & 5 deletions ibctesting/genesis_bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ func TestTransferGenesisTestSuite(t *testing.T) {

func (s *transferGenesisSuite) SetupTest() {
s.utilSuite.SetupTest()
s.hubApp().LightClientKeeper.SetEnabled(false)

path := s.newTransferPath(s.hubChain(), s.rollappChain())
s.coordinator.SetupConnections(path)
s.createRollapp(false, nil) // genesis protocol is not finished yet
Expand All @@ -45,11 +47,6 @@ func (s *transferGenesisSuite) SetupTest() {
iroFee := sdk.NewCoin(appparams.BaseDenom, s.hubApp().IROKeeper.GetParams(s.hubCtx()).CreationFee)
apptesting.FundAccount(s.hubApp(), s.hubCtx(), s.hubChain().SenderAccount.GetAddress(), sdk.NewCoins(iroFee))

// FIXME: remove?
// fund the iro module account for pool creation fee
poolFee := s.hubApp().GAMMKeeper.GetParams(s.hubCtx()).PoolCreationFee
apptesting.FundAccount(s.hubApp(), s.hubCtx(), sdk.MustAccAddressFromBech32(s.hubApp().IROKeeper.GetModuleAccountAddress()), poolFee)

// set the canonical client before creating channels
s.path = path
s.hubApp().LightClientKeeper.SetCanonicalClient(s.hubCtx(), rollappChainID(), s.path.EndpointA.ClientID)
Expand Down
Loading

0 comments on commit 5deae85

Please sign in to comment.