Skip to content

Commit

Permalink
feat(rollapp): create gov prop for updating genesis info (#1570)
Browse files Browse the repository at this point in the history
  • Loading branch information
mtsitrin authored Nov 28, 2024
1 parent 31fd2d5 commit 81a984c
Show file tree
Hide file tree
Showing 9 changed files with 1,450 additions and 828 deletions.
39 changes: 0 additions & 39 deletions proto/dymensionxyz/dymension/rollapp/fraud_proposal.proto

This file was deleted.

57 changes: 57 additions & 0 deletions proto/dymensionxyz/dymension/rollapp/proposals.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
syntax = "proto3";
package dymensionxyz.dymension.rollapp;

import "gogoproto/gogo.proto";
import "cosmos/msg/v1/msg.proto";
import "dymensionxyz/dymension/rollapp/genesis_info.proto";

option go_package = "github.com/dymensionxyz/dymension/v3/x/rollapp/types";

service ProposalMsg {
rpc SubmitRollappFraud(MsgRollappFraudProposal) returns (MsgRollappFraudProposalResponse);
rpc ForceGenesisInfoChange(MsgForceGenesisInfoChange) returns (MsgForceGenesisInfoChangeResponse);
}

message MsgRollappFraudProposal {
option (cosmos.msg.v1.signer) = "authority";

// Authority is the authority address.
string authority = 1;

// RollappID is the rollapp id.
string rollapp_id = 2;

// The height of the fraudulent block
uint64 fraud_height = 4;
// Revision of fraudulent block
uint64 fraud_revision = 3;

// sequencer address to punish. optional
string punish_sequencer_address = 6;

// rewardAddr is bech32 for sdk acc addr
string rewardee = 7;
}

message MsgRollappFraudProposalResponse {
}

// MsgForceGenesisInfoChange defines the Msg/ForceGenesisInfoChange request type
message MsgForceGenesisInfoChange {
option (cosmos.msg.v1.signer) = "authority";

// Authority is the address that controls the module (defaults to x/gov unless overwritten).
string authority = 1;

// RollappID is the unique identifier of the rollapp whose genesis info will be changed
string rollapp_id = 2;

// NewGenesisInfo contains the new genesis information that will replace the existing one
GenesisInfo new_genesis_info = 3 [(gogoproto.nullable) = false];
}

// MsgForceGenesisInfoChangeResponse defines the Msg/ForceGenesisInfoChange response type
message MsgForceGenesisInfoChangeResponse {
}

// TODO: add slashing only proposal (e.g for double signing)
43 changes: 43 additions & 0 deletions x/rollapp/keeper/msg_server_update_rollapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@ package keeper

import (
"context"
"errors"
"fmt"

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/dymensionxyz/gerr-cosmos/gerrc"
"github.com/dymensionxyz/sdk-utils/utils/uevent"

"github.com/dymensionxyz/dymension/v3/x/rollapp/types"
)

// UpdateRollappInformation updates the rollapp information
// It allows to change:
// - the rollapp metadata
// - the genesis info (in case the genesis info is not sealed)
// - the initial sequencer (in case the rollapp is not launched)
func (k msgServer) UpdateRollappInformation(goCtx context.Context, msg *types.MsgUpdateRollappInformation) (*types.MsgUpdateRollappInformationResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

Expand All @@ -26,3 +34,38 @@ func (k msgServer) UpdateRollappInformation(goCtx context.Context, msg *types.Ms

return &types.MsgUpdateRollappInformationResponse{}, nil
}

// ForceGenesisInfoChange allows the gov module to force a genesis info change, even if the genesis info is already sealed
func (k Keeper) ForceGenesisInfoChange(goCtx context.Context, msg *types.MsgForceGenesisInfoChange) (*types.MsgForceGenesisInfoChangeResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

if msg.Authority != k.authority {
err := errorsmod.Wrap(gerrc.ErrUnauthenticated, "only the gov module can submit proposals")
ctx.Logger().Error("force genesis info change.", err)
return nil, err
}

// validateBasic check that the new genesis info is valid and contains all the necessary fields
if err := msg.ValidateBasic(); err != nil {
err = errors.Join(gerrc.ErrInvalidArgument, err)
ctx.Logger().Error("force genesis info change.", err)
return nil, err
}

rollapp, found := k.GetRollapp(ctx, msg.RollappId)
if !found {
err := errorsmod.Wrapf(types.ErrRollappNotFound, "rollapp not found: %s", msg.RollappId)
ctx.Logger().Error("force genesis info change.", err)
return nil, err
}

rollapp.GenesisInfo = msg.NewGenesisInfo
rollapp.GenesisInfo.Sealed = true
k.SetRollapp(ctx, rollapp)

if err := uevent.EmitTypedEvent(ctx, msg); err != nil {
return nil, fmt.Errorf("emit event: %w", err)
}

return &types.MsgForceGenesisInfoChangeResponse{}, nil
}
93 changes: 93 additions & 0 deletions x/rollapp/keeper/msg_server_update_rollapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/dymensionxyz/gerr-cosmos/gerrc"
"github.com/dymensionxyz/sdk-utils/utils/uptr"

Expand Down Expand Up @@ -439,3 +441,94 @@ func (s *RollappTestSuite) TestCreateAndUpdateRollapp() {
s.Require().NoError(err)
s.Require().Equal(metadata, initSeq.Metadata)
}

func (s *RollappTestSuite) TestForceGenesisInfoChange() {
govModuleAccount := authtypes.NewModuleAddress(govtypes.ModuleName).String()

tests := []struct {
name string
msg *types.MsgForceGenesisInfoChange
expError error
}{
{
name: "happy path - valid genesis info change",
msg: &types.MsgForceGenesisInfoChange{
Authority: govModuleAccount,
NewGenesisInfo: types.GenesisInfo{
Bech32Prefix: "new",
GenesisChecksum: "new_checksum",
InitialSupply: sdk.NewInt(2000),
NativeDenom: types.DenomMetadata{
Display: "NEW",
Base: "anew",
Exponent: 18,
},
},
},
expError: nil,
},
{
name: "missing bech32 prefix",
msg: &types.MsgForceGenesisInfoChange{
Authority: govModuleAccount,
NewGenesisInfo: types.GenesisInfo{
GenesisChecksum: "new_checksum",
InitialSupply: sdk.NewInt(2000),
NativeDenom: types.DenomMetadata{
Display: "NEW",
Base: "anew",
Exponent: 18,
},
},
},
expError: gerrc.ErrInvalidArgument,
},
{
name: "missing native denom",
msg: &types.MsgForceGenesisInfoChange{
Authority: govModuleAccount,
NewGenesisInfo: types.GenesisInfo{
Bech32Prefix: "new",
GenesisChecksum: "new_checksum",
InitialSupply: sdk.NewInt(2000),
},
},
expError: gerrc.ErrInvalidArgument,
},
}

for _, tc := range tests {
s.Run(tc.name, func() {
s.SetupTest()
rollappId, _ := s.CreateDefaultRollappAndProposer()
tc.msg.RollappId = rollappId

// Verify rollapp was created with sealed genesis info
rollapp, found := s.App.RollappKeeper.GetRollapp(s.Ctx, rollappId)
s.Require().True(found)
s.Require().True(rollapp.GenesisInfo.Sealed)

// Execute the message
_, err := s.App.RollappKeeper.ForceGenesisInfoChange(s.Ctx, tc.msg)

if tc.expError != nil {
s.Require().Error(err)
s.Require().ErrorIs(err, tc.expError)
return
}

s.Require().NoError(err)

// Verify genesis info was changed correctly
rollapp, found = s.App.RollappKeeper.GetRollapp(s.Ctx, tc.msg.RollappId)
s.Require().True(found)
s.Require().Equal(tc.msg.NewGenesisInfo.Bech32Prefix, rollapp.GenesisInfo.Bech32Prefix)
s.Require().Equal(tc.msg.NewGenesisInfo.GenesisChecksum, rollapp.GenesisInfo.GenesisChecksum)
s.Require().Equal(tc.msg.NewGenesisInfo.InitialSupply, rollapp.GenesisInfo.InitialSupply)
s.Require().Equal(tc.msg.NewGenesisInfo.NativeDenom.Display, rollapp.GenesisInfo.NativeDenom.Display)
s.Require().Equal(tc.msg.NewGenesisInfo.NativeDenom.Base, rollapp.GenesisInfo.NativeDenom.Base)
s.Require().Equal(tc.msg.NewGenesisInfo.NativeDenom.Exponent, rollapp.GenesisInfo.NativeDenom.Exponent)
s.Require().True(rollapp.GenesisInfo.Sealed)
})
}
}
2 changes: 2 additions & 0 deletions x/rollapp/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func RegisterCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgRemoveApp{}, "rollapp/RemoveApp", nil)
cdc.RegisterConcrete(&MsgRollappFraudProposal{}, "rollapp/RollappFraudProposal", nil)
cdc.RegisterConcrete(&MsgMarkObsoleteRollapps{}, "rollapp/MarkObsoleteRollapps", nil)
cdc.RegisterConcrete(&MsgForceGenesisInfoChange{}, "rollapp/ForceGenesisInfoChange", nil)
}

func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
Expand All @@ -31,6 +32,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) {
&MsgRemoveApp{},
&MsgRollappFraudProposal{},
&MsgMarkObsoleteRollapps{},
&MsgForceGenesisInfoChange{},
)
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
}
Expand Down
Loading

0 comments on commit 81a984c

Please sign in to comment.