Skip to content

Commit

Permalink
fix: genesis import/export for CSR module
Browse files Browse the repository at this point in the history
  • Loading branch information
poorphd committed Aug 24, 2023
1 parent 513900c commit d5fd1e4
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 12 deletions.
3 changes: 3 additions & 0 deletions proto/canto/csr/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package canto.csr.v1;

import "gogoproto/gogo.proto";
import "canto/csr/v1/params.proto";
import "canto/csr/v1/csr.proto";

option go_package = "github.com/Canto-Network/Canto/v7/x/csr/types";

// GenesisState defines the csr module's genesis state.
message GenesisState {
// params defines all of the parameters of the module
Params params = 1 [ (gogoproto.nullable) = false ];
repeated CSR csrs = 2 [ (gogoproto.nullable) = false ];
bytes turnstile_address = 3;
}
21 changes: 21 additions & 0 deletions x/csr/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ import (
"github.com/Canto-Network/Canto/v7/x/csr/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/ethereum/go-ethereum/common"
)

// InitGenesis initializes the capability module's state from a provided genesis
// state.
func InitGenesis(ctx sdk.Context, k keeper.Keeper, accountKeeper authkeeper.AccountKeeper, genState types.GenesisState) {
// this line is used by starport scaffolding # genesis/module/init
k.SetParams(ctx, genState.Params)
for _, csr := range genState.Csrs {
k.SetCSR(ctx, csr)
}
if genState.TurnstileAddress != nil {
k.SetTurnstile(ctx, common.BytesToAddress(genState.TurnstileAddress))
}
// make sure that the csr module account is set on genesis
if acc := accountKeeper.GetModuleAccount(ctx, types.ModuleName); acc == nil {
// NOTE: shouldn't occur
Expand All @@ -23,6 +30,20 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, accountKeeper authkeeper.Acco
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
genesis := types.DefaultGenesis()
genesis.Params = k.GetParams(ctx)
csrs := k.GetAllCSRs(ctx)

if len(csrs) == 0 {
genesis.Csrs = []types.CSR{}
} else {
genesis.Csrs = csrs
}

turnstileAddress, found := k.GetTurnstile(ctx)
if found {
genesis.TurnstileAddress = turnstileAddress.Bytes()
} else {
genesis.TurnstileAddress = nil
}

return genesis
}
21 changes: 21 additions & 0 deletions x/csr/keeper/csr.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,27 @@ func (k Keeper) GetCSR(ctx sdk.Context, nftId uint64) (*types.CSR, bool) {
return csr, true
}

func (k Keeper) IterateAllCSRs(ctx sdk.Context, cb func(csr types.CSR) (stop bool)) {
store := ctx.KVStore(k.storeKey)
iter := sdk.KVStorePrefixIterator(store, types.KeyPrefixCSR)
defer iter.Close()
for ; iter.Valid(); iter.Next() {
var csr types.CSR
k.cdc.MustUnmarshal(iter.Value(), &csr)
if cb(csr) {
break
}
}
}

func (k Keeper) GetAllCSRs(ctx sdk.Context) (csrs []types.CSR) {
k.IterateAllCSRs(ctx, func(csr types.CSR) (stop bool) {
csrs = append(csrs, csr)
return false
})
return
}

// Returns the NFT ID associated with a smart contract address. If the smart contract address
// entered does belong to some NFT, then it will return (id, true), otherwise (0, false).
func (k Keeper) GetNFTByContract(ctx sdk.Context, address string) (uint64, bool) {
Expand Down
95 changes: 95 additions & 0 deletions x/csr/keeper/genesis_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package keeper_test

import (
"time"

"github.com/Canto-Network/Canto/v7/x/csr"
"github.com/Canto-Network/Canto/v7/x/csr/types"
"github.com/evmos/ethermint/tests"
)

func (suite *KeeperTestSuite) TestDefaultGenesis() {
genState := types.DefaultGenesis()

csr.InitGenesis(suite.ctx, suite.app.CSRKeeper, suite.app.AccountKeeper, *genState)
got := csr.ExportGenesis(suite.ctx, suite.app.CSRKeeper)
suite.Require().Equal(genState, got)
}

func (suite *KeeperTestSuite) TestImportExportGenesisEmpty() {
_, found := suite.app.CSRKeeper.GetTurnstile(suite.ctx)
suite.Require().False(found)
csrs := suite.app.CSRKeeper.GetAllCSRs(suite.ctx)
suite.Require().Empty(csrs)

genState := csr.ExportGenesis(suite.ctx, suite.app.CSRKeeper)
suite.Require().Nil(genState.TurnstileAddress)
suite.Require().Empty(genState.Csrs)

// Copy genState to genState2 and init with it
var genState2 types.GenesisState
bz := suite.app.AppCodec().MustMarshalJSON(genState)
suite.app.AppCodec().MustUnmarshalJSON(bz, &genState2)
csr.InitGenesis(suite.ctx, suite.app.CSRKeeper, suite.app.AccountKeeper, genState2)

_, found = suite.app.CSRKeeper.GetTurnstile(suite.ctx)
suite.Require().False(found)
csrs = suite.app.CSRKeeper.GetAllCSRs(suite.ctx)
suite.Require().Empty(csrs)
genState3 := csr.ExportGenesis(suite.ctx, suite.app.CSRKeeper)
suite.Equal(*genState, genState2)
suite.Equal(genState2, *genState3)
suite.Require().Nil(genState3.TurnstileAddress)
suite.Require().Empty(genState3.Csrs)
}

func (suite *KeeperTestSuite) TestInitExportGenesis() {
expGenesis := types.DefaultGenesis()

csr.InitGenesis(suite.ctx, suite.app.CSRKeeper, suite.app.AccountKeeper, *expGenesis)
genState := csr.ExportGenesis(suite.ctx, suite.app.CSRKeeper)
suite.Require().Equal(expGenesis, genState)

bz := suite.app.AppCodec().MustMarshalJSON(genState)

var genState2 types.GenesisState
suite.app.AppCodec().MustUnmarshalJSON(bz, &genState2)
csr.InitGenesis(suite.ctx, suite.app.CSRKeeper, suite.app.AccountKeeper, genState2)
genState3 := csr.ExportGenesis(suite.ctx, suite.app.CSRKeeper)

suite.Require().Equal(*genState, genState2)
suite.Require().Equal(genState2, *genState3)
}

func (suite *KeeperTestSuite) TestImportExportGenesis() {
t, _ := time.Parse(time.RFC3339, "2022-01-01T00:00:00Z")
suite.ctx = suite.ctx.WithBlockHeight(1).WithBlockTime(t)

numberCSRs := 10
csrs := GenerateCSRs(numberCSRs)
for _, csr := range csrs {
suite.app.CSRKeeper.SetCSR(suite.ctx, csr)
}

turnstileAddress := tests.GenerateAddress()
suite.app.CSRKeeper.SetTurnstile(suite.ctx, turnstileAddress)

genState := csr.ExportGenesis(suite.ctx, suite.app.CSRKeeper)
bz := suite.app.AppCodec().MustMarshalJSON(genState)

// Copy genState to genState2 and init with it
var genState2 types.GenesisState
suite.app.AppCodec().MustUnmarshalJSON(bz, &genState2)
csr.InitGenesis(suite.ctx, suite.app.CSRKeeper, suite.app.AccountKeeper, genState2)
exported := csr.ExportGenesis(suite.ctx, suite.app.CSRKeeper)
suite.Equal(*genState, *exported)

suite.ctx = suite.ctx.WithBlockHeight(1).WithBlockTime(t)

c := suite.app.CSRKeeper.GetAllCSRs(suite.ctx)
suite.Equal(csrs, c)

ta, found := suite.app.CSRKeeper.GetTurnstile(suite.ctx)
suite.True(found)
suite.Equal(turnstileAddress, ta)
}
8 changes: 7 additions & 1 deletion x/csr/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ const DefaultIndex uint64 = 1

// DefaultGenesis returns the default Capability genesis state
func DefaultGenesis() *GenesisState {
return NewGenesisState(DefaultParams(), []CSR{}, nil)
}

func NewGenesisState(params Params, csrs []CSR, turnstileAddress []byte) *GenesisState {
return &GenesisState{
Params: DefaultParams(),
Params: params,
Csrs: csrs,
TurnstileAddress: turnstileAddress,
}
}

Expand Down
141 changes: 130 additions & 11 deletions x/csr/types/genesis.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d5fd1e4

Please sign in to comment.