Cosmos SDK Interview Questions - Medium
Medium-level Cosmos SDK interview questions covering advanced module development, SDK internals, and Ignite customization.
Q1: How do you implement custom state transitions and state machines in a module?
Answer:
State Machine Pattern:
1package keeper
2
3import (
4 sdk "github.com/cosmos/cosmos-sdk/types"
5)
6
7// OrderState represents order state
8type OrderState uint8
9
10const (
11 OrderStatePending OrderState = iota
12 OrderStateConfirmed
13 OrderStateShipped
14 OrderStateDelivered
15 OrderStateCancelled
16)
17
18// Order represents an order
19type Order struct {
20 Id uint64
21 State OrderState
22 Buyer sdk.AccAddress
23 Seller sdk.AccAddress
24 Amount sdk.Coins
25}
26
27// StateMachine manages order state transitions
28type StateMachine struct {
29 keeper Keeper
30}
31
32// Transition validates and executes state transition
33func (sm StateMachine) Transition(ctx sdk.Context, orderId uint64, newState OrderState) error {
34 order, found := sm.keeper.GetOrder(ctx, orderId)
35 if !found {
36 return sdkerrors.Wrap(types.ErrOrderNotFound, fmt.Sprintf("order %d not found", orderId))
37 }
38
39 // Validate transition
40 if !sm.isValidTransition(order.State, newState) {
41 return sdkerrors.Wrap(
42 types.ErrInvalidStateTransition,
43 fmt.Sprintf("cannot transition from %d to %d", order.State, newState),
44 )
45 }
46
47 // Execute transition
48 order.State = newState
49 sm.keeper.SetOrder(ctx, order)
50
51 // Emit event
52 ctx.EventManager().EmitEvent(
53 sdk.NewEvent(
54 types.EventTypeOrderStateChanged,
55 sdk.NewAttribute(types.AttributeKeyOrderId, fmt.Sprintf("%d", orderId)),
56 sdk.NewAttribute(types.AttributeKeyOldState, fmt.Sprintf("%d", order.State)),
57 sdk.NewAttribute(types.AttributeKeyNewState, fmt.Sprintf("%d", newState)),
58 ),
59 )
60
61 return nil
62}
63
64// isValidTransition checks if transition is allowed
65func (sm StateMachine) isValidTransition(current, next OrderState) bool {
66 transitions := map[OrderState][]OrderState{
67 OrderStatePending: {OrderStateConfirmed, OrderStateCancelled},
68 OrderStateConfirmed: {OrderStateShipped, OrderStateCancelled},
69 OrderStateShipped: {OrderStateDelivered},
70 OrderStateDelivered: {},
71 OrderStateCancelled: {},
72 }
73
74 allowed, exists := transitions[current]
75 if !exists {
76 return false
77 }
78
79 for _, state := range allowed {
80 if state == next {
81 return true
82 }
83 }
84
85 return false
86}
Usage:
1// In handler
2func (k Keeper) ConfirmOrder(ctx sdk.Context, orderId uint64) error {
3 sm := StateMachine{keeper: k}
4 return sm.Transition(ctx, orderId, OrderStateConfirmed)
5}
Q2: How do you implement custom authentication and authorization in Cosmos SDK?
Answer:
Custom AnteHandler:
1package ante
2
3import (
4 sdk "github.com/cosmos/cosmos-sdk/types"
5 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
6 "github.com/cosmos/cosmos-sdk/x/auth/ante"
7)
8
9// CustomAnteHandler implements custom authentication
10type CustomAnteHandler struct {
11 accountKeeper ante.AccountKeeper
12 signer SignerVerifier
13}
14
15// NewAnteHandler creates a new ante handler
16func NewAnteHandler(
17 ak ante.AccountKeeper,
18 signer SignerVerifier,
19) sdk.AnteHandler {
20 return sdk.ChainAnteDecorators(
21 ante.NewSetUpContextDecorator(),
22 ante.NewRejectExtensionOptionsDecorator(),
23 ante.NewMempoolFeeDecorator(),
24 ante.NewValidateBasicDecorator(),
25 ante.NewTxTimeoutHeightDecorator(),
26 ante.NewValidateSigCountDecorator(ak),
27 ante.NewDeductFeeDecorator(ak),
28 NewCustomAuthDecorator(ak, signer),
29 ante.NewSetPubKeyDecorator(ak),
30 ante.NewValidateSigDecorator(ak),
31 ante.NewIncrementSequenceDecorator(ak),
32 )
33}
34
35// CustomAuthDecorator performs custom authentication
36type CustomAuthDecorator struct {
37 accountKeeper ante.AccountKeeper
38 signer SignerVerifier
39}
40
41func NewCustomAuthDecorator(ak ante.AccountKeeper, signer SignerVerifier) CustomAuthDecorator {
42 return CustomAuthDecorator{
43 accountKeeper: ak,
44 signer: signer,
45 }
46}
47
48// AnteHandle performs authentication
49func (cad CustomAuthDecorator) AnteHandle(
50 ctx sdk.Context,
51 tx sdk.Tx,
52 simulate bool,
53 next sdk.AnteHandler,
54) (sdk.Context, error) {
55 sigTx, ok := tx.(authsigning.SigVerifiableTx)
56 if !ok {
57 return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
58 }
59
60 // Get signers
61 signers := sigTx.GetSigners()
62
63 // Verify each signer
64 for _, signer := range signers {
65 // Check if signer is authorized
66 if !cad.signer.IsAuthorized(ctx, signer) {
67 return ctx, sdkerrors.Wrap(
68 sdkerrors.ErrUnauthorized,
69 fmt.Sprintf("signer %s is not authorized", signer.String()),
70 )
71 }
72
73 // Additional custom checks
74 if err := cad.signer.VerifySignature(ctx, signer, sigTx); err != nil {
75 return ctx, err
76 }
77 }
78
79 return next(ctx, tx, simulate)
80}
Role-Based Access Control:
1package keeper
2
3// Role represents user role
4type Role uint8
5
6const (
7 RoleUser Role = iota
8 RoleAdmin
9 RoleModerator
10)
11
12// HasRole checks if account has role
13func (k Keeper) HasRole(ctx sdk.Context, addr sdk.AccAddress, role Role) bool {
14 accountRole := k.GetAccountRole(ctx, addr)
15 return accountRole >= role
16}
17
18// RequireRole ensures account has required role
19func (k Keeper) RequireRole(ctx sdk.Context, addr sdk.AccAddress, role Role) error {
20 if !k.HasRole(ctx, addr, role) {
21 return sdkerrors.Wrap(
22 sdkerrors.ErrUnauthorized,
23 fmt.Sprintf("account %s does not have required role", addr.String()),
24 )
25 }
26 return nil
27}
28
29// In handler
30func (k Keeper) AdminAction(ctx sdk.Context, msg types.MsgAdminAction) error {
31 // Check admin role
32 if err := k.RequireRole(ctx, msg.Signer, RoleAdmin); err != nil {
33 return err
34 }
35
36 // Perform admin action
37 return k.DoAdminAction(ctx, msg)
38}
Q3: How do you implement custom fee models and fee distribution?
Answer:
Custom Fee Decorator:
1package ante
2
3import (
4 sdk "github.com/cosmos/cosmos-sdk/types"
5 "github.com/cosmos/cosmos-sdk/x/auth/ante"
6)
7
8// CustomFeeDecorator implements custom fee logic
9type CustomFeeDecorator struct {
10 accountKeeper ante.AccountKeeper
11 bankKeeper BankKeeper
12 feeKeeper FeeKeeper
13}
14
15func NewCustomFeeDecorator(ak ante.AccountKeeper, bk BankKeeper, fk FeeKeeper) CustomFeeDecorator {
16 return CustomFeeDecorator{
17 accountKeeper: ak,
18 bankKeeper: bk,
19 feeKeeper: fk,
20 }
21}
22
23func (cfd CustomFeeDecorator) AnteHandle(
24 ctx sdk.Context,
25 tx sdk.Tx,
26 simulate bool,
27 next sdk.AnteHandler,
28) (sdk.Context, error) {
29 feeTx, ok := tx.(sdk.FeeTx)
30 if !ok {
31 return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
32 }
33
34 // Get fee
35 fee := feeTx.GetFee()
36
37 // Calculate custom fee based on message type
38 customFee := cfd.calculateCustomFee(ctx, tx)
39
40 // Use higher of standard or custom fee
41 if customFee.IsAllGT(fee) {
42 fee = customFee
43 }
44
45 // Get payer
46 payer := feeTx.FeePayer()
47 if payer == nil {
48 payer = feeTx.GetSigners()[0]
49 }
50
51 // Deduct fee
52 if err := cfd.bankKeeper.SendCoinsFromAccountToModule(
53 ctx,
54 payer,
55 types.FeeCollectorName,
56 fee,
57 ); err != nil {
58 return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fee: %s", err)
59 }
60
61 // Distribute fee
62 cfd.feeKeeper.DistributeFee(ctx, fee, tx)
63
64 return next(ctx, tx, simulate)
65}
66
67func (cfd CustomFeeDecorator) calculateCustomFee(ctx sdk.Context, tx sdk.Tx) sdk.Coins {
68 // Calculate fee based on message types
69 var totalFee sdk.Coins
70
71 for _, msg := range tx.GetMsgs() {
72 switch m := msg.(type) {
73 case *types.MsgComplexOperation:
74 // Higher fee for complex operations
75 totalFee = totalFee.Add(sdk.NewCoin("stake", sdk.NewInt(1000)))
76 case *types.MsgSimpleOperation:
77 // Lower fee for simple operations
78 totalFee = totalFee.Add(sdk.NewCoin("stake", sdk.NewInt(100)))
79 default:
80 // Default fee
81 totalFee = totalFee.Add(sdk.NewCoin("stake", sdk.NewInt(500)))
82 }
83 }
84
85 return totalFee
86}
Fee Distribution:
1package keeper
2
3// DistributeFee distributes fees to validators and treasury
4func (k Keeper) DistributeFee(ctx sdk.Context, fee sdk.Coins, tx sdk.Tx) {
5 // Get distribution parameters
6 params := k.GetParams(ctx)
7
8 // Calculate shares
9 validatorShare := fee.MulInt(sdk.NewIntFromUint64(params.ValidatorFeeShare))
10 treasuryShare := fee.MulInt(sdk.NewIntFromUint64(params.TreasuryFeeShare))
11
12 // Distribute to validators
13 k.distributeToValidators(ctx, validatorShare)
14
15 // Send to treasury
16 k.bankKeeper.SendCoinsFromModuleToModule(
17 ctx,
18 types.FeeCollectorName,
19 types.TreasuryModuleName,
20 treasuryShare,
21 )
22}
Q4: How do you implement custom query pagination and filtering?
Answer:
Pagination:
1package keeper
2
3import (
4 "github.com/cosmos/cosmos-sdk/store/prefix"
5 "github.com/cosmos/cosmos-sdk/types/query"
6)
7
8// QueryAllPosts with pagination
9func (k Keeper) QueryAllPosts(
10 ctx sdk.Context,
11 req *types.QueryAllPostsRequest,
12) (*types.QueryAllPostsResponse, error) {
13 if req == nil {
14 return nil, status.Error(codes.InvalidArgument, "invalid request")
15 }
16
17 var posts []types.Post
18 store := ctx.KVStore(k.storeKey)
19 postStore := prefix.NewStore(store, types.PostKeyPrefix)
20
21 // Parse pagination
22 pageRes, err := query.Paginate(postStore, req.Pagination, func(key []byte, value []byte) error {
23 var post types.Post
24 if err := k.cdc.Unmarshal(value, &post); err != nil {
25 return err
26 }
27
28 // Apply filters
29 if req.Filter != nil {
30 if !k.matchesFilter(post, req.Filter) {
31 return nil // Skip this post
32 }
33 }
34
35 posts = append(posts, post)
36 return nil
37 })
38
39 if err != nil {
40 return nil, status.Error(codes.Internal, err.Error())
41 }
42
43 return &types.QueryAllPostsResponse{
44 Posts: posts,
45 Pagination: pageRes,
46 }, nil
47}
48
49// matchesFilter checks if post matches filter criteria
50func (k Keeper) matchesFilter(post types.Post, filter *types.PostFilter) bool {
51 if filter == nil {
52 return true
53 }
54
55 // Filter by creator
56 if filter.Creator != "" {
57 if post.Creator != filter.Creator {
58 return false
59 }
60 }
61
62 // Filter by title contains
63 if filter.TitleContains != "" {
64 if !strings.Contains(strings.ToLower(post.Title), strings.ToLower(filter.TitleContains)) {
65 return false
66 }
67 }
68
69 // Filter by date range
70 if filter.CreatedAfter != nil {
71 if post.CreatedAt.Before(*filter.CreatedAfter) {
72 return false
73 }
74 }
75
76 if filter.CreatedBefore != nil {
77 if post.CreatedAt.After(*filter.CreatedBefore) {
78 return false
79 }
80 }
81
82 return true
83}
Index-Based Queries:
1// Create index for efficient queries
2func (k Keeper) IndexPostsByCreator(ctx sdk.Context) {
3 store := ctx.KVStore(k.storeKey)
4 postStore := prefix.NewStore(store, types.PostKeyPrefix)
5
6 iterator := sdk.KVStorePrefixIterator(postStore, []byte{})
7 defer iterator.Close()
8
9 for ; iterator.Valid(); iterator.Next() {
10 var post types.Post
11 k.cdc.MustUnmarshal(iterator.Value(), &post)
12
13 // Store in creator index
14 creatorKey := types.GetPostByCreatorKey(post.Creator, post.Id)
15 store.Set(creatorKey, iterator.Key())
16 }
17}
18
19// QueryPostsByCreator uses index
20func (k Keeper) QueryPostsByCreator(
21 ctx sdk.Context,
22 creator string,
23 pagination *query.PageRequest,
24) ([]types.Post, *query.PageResponse, error) {
25 store := ctx.KVStore(k.storeKey)
26 creatorStore := prefix.NewStore(store, types.GetPostByCreatorKeyPrefix(creator))
27
28 var posts []types.Post
29
30 pageRes, err := query.Paginate(creatorStore, pagination, func(key []byte, value []byte) error {
31 // Get actual post key from index
32 postKey := value
33
34 // Get post
35 postBytes := store.Get(postKey)
36 var post types.Post
37 k.cdc.MustUnmarshal(postBytes, &post)
38 posts = append(posts, post)
39 return nil
40 })
41
42 return posts, pageRes, err
43}
Q5: How do you implement upgrade handlers and migration logic?
Answer:
Upgrade Handler:
1package app
2
3import (
4 "github.com/cosmos/cosmos-sdk/types/module"
5 upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
6)
7
8// RegisterUpgradeHandlers registers upgrade handlers
9func (app *App) RegisterUpgradeHandlers() {
10 app.UpgradeKeeper.SetUpgradeHandler("v2", func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
11 // Perform migrations
12 return app.mm.RunMigrations(ctx, app.configurator, vm)
13 })
14}
15
16// Custom migration
17func (app *App) migrateV1ToV2(ctx sdk.Context) error {
18 // Migrate state
19 store := ctx.KVStore(app.keys[types.StoreKey])
20
21 // Example: Migrate old format to new format
22 iterator := sdk.KVStorePrefixIterator(store, []byte("old_prefix"))
23 defer iterator.Close()
24
25 for ; iterator.Valid(); iterator.Next() {
26 key := iterator.Key()
27 value := iterator.Value()
28
29 // Transform data
30 newKey := migrateKey(key)
31 newValue := migrateValue(value)
32
33 // Store in new format
34 store.Set(newKey, newValue)
35
36 // Delete old key
37 store.Delete(key)
38 }
39
40 return nil
41}
42
43// Version-specific upgrade
44func (app *App) RegisterUpgradeHandlers() {
45 app.UpgradeKeeper.SetUpgradeHandler("v2.0.0", func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
46 // Run module migrations
47 return app.mm.RunMigrations(ctx, app.configurator, vm)
48 })
49
50 app.UpgradeKeeper.SetUpgradeHandler("v2.1.0", func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
51 // Custom migration logic
52 if err := app.migrateV1ToV2(ctx); err != nil {
53 return vm, err
54 }
55
56 // Continue with module migrations
57 return app.mm.RunMigrations(ctx, app.configurator, vm)
58 })
59}
Module Migration:
1package keeper
2
3// RegisterStoreDecoder registers migration decoders
4func (k Keeper) RegisterStoreDecoder(store sdk.StoreDecoderRegistry) {
5 store[types.StoreKey] = func(version uint64) func(sdk.KVStore) error {
6 switch version {
7 case 0:
8 return migrateV0ToV1
9 case 1:
10 return migrateV1ToV2
11 default:
12 return nil
13 }
14 }
15}
16
17func migrateV0ToV1(store sdk.KVStore) error {
18 // Migration logic
19 return nil
20}
Q6: How do you implement event indexing and event queries?
Answer:
Event Emission:
1package keeper
2
3// EmitOrderEvent emits order-related events
4func (k Keeper) EmitOrderEvent(
5 ctx sdk.Context,
6 eventType string,
7 orderId uint64,
8 attributes map[string]string,
9) {
10 event := sdk.NewEvent(
11 eventType,
12 sdk.NewAttribute(types.AttributeKeyOrderId, fmt.Sprintf("%d", orderId)),
13 )
14
15 // Add custom attributes
16 for key, value := range attributes {
17 event = event.AppendAttributes(sdk.NewAttribute(key, value))
18 }
19
20 ctx.EventManager().EmitEvent(event)
21}
22
23// EmitTypedEvent emits typed events (better for indexing)
24func (k Keeper) EmitTypedEvent(ctx sdk.Context, event proto.Message) {
25 ctx.EventManager().EmitTypedEvent(event)
26}
Event Querying:
1package keeper
2
3// QueryEvents queries events by type and attributes
4func (k Keeper) QueryEvents(
5 ctx sdk.Context,
6 eventType string,
7 attributes map[string]string,
8 pagination *query.PageRequest,
9) (*types.QueryEventsResponse, error) {
10 // Query events from event store
11 events := k.eventStore.QueryEvents(
12 ctx,
13 eventType,
14 attributes,
15 pagination,
16 )
17
18 return &types.QueryEventsResponse{
19 Events: events,
20 Pagination: pagination,
21 }, nil
22}
Event Indexing:
1// Index events for efficient querying
2type EventIndexer struct {
3 store sdk.KVStore
4}
5
6func (ei EventIndexer) IndexEvent(event sdk.Event) {
7 // Index by event type
8 typeKey := types.GetEventTypeKey(event.Type)
9 ei.store.Set(typeKey, []byte{1})
10
11 // Index by attributes
12 for _, attr := range event.Attributes {
13 attrKey := types.GetEventAttributeKey(event.Type, attr.Key, attr.Value)
14 ei.store.Set(attrKey, []byte{1})
15 }
16}
Q7: How do you implement custom transaction validation and ordering?
Answer:
Custom Mempool:
1package mempool
2
3import (
4 "github.com/cosmos/cosmos-sdk/types"
5 "github.com/cosmos/cosmos-sdk/types/mempool"
6)
7
8// PriorityMempool implements priority-based ordering
9type PriorityMempool struct {
10 transactions []sdk.Tx
11 priorityFunc func(sdk.Tx) int64
12}
13
14func NewPriorityMempool(priorityFunc func(sdk.Tx) int64) *PriorityMempool {
15 return &PriorityMempool{
16 transactions: make([]sdk.Tx, 0),
17 priorityFunc: priorityFunc,
18 }
19}
20
21func (mp *PriorityMempool) Insert(ctx sdk.Context, tx sdk.Tx) error {
22 // Calculate priority
23 priority := mp.priorityFunc(tx)
24
25 // Insert in sorted order
26 inserted := false
27 for i, existingTx := range mp.transactions {
28 if mp.priorityFunc(existingTx) < priority {
29 // Insert here
30 mp.transactions = append(
31 mp.transactions[:i],
32 append([]sdk.Tx{tx}, mp.transactions[i:]...)...,
33 )
34 inserted = true
35 break
36 }
37 }
38
39 if !inserted {
40 mp.transactions = append(mp.transactions, tx)
41 }
42
43 return nil
44}
45
46func (mp *PriorityMempool) Select(ctx sdk.Context, maxTxs [][]byte) [][]byte {
47 selected := make([][]byte, 0, len(maxTxs))
48
49 for i, tx := range mp.transactions {
50 if i >= len(maxTxs) {
51 break
52 }
53 selected = append(selected, tx.GetSigners()[0].Bytes())
54 }
55
56 return selected
57}
58
59// Custom validation
60func (mp *PriorityMempool) ValidateTx(ctx sdk.Context, tx sdk.Tx) error {
61 // Custom validation logic
62 if err := mp.validateNonce(ctx, tx); err != nil {
63 return err
64 }
65
66 if err := mp.validateGas(ctx, tx); err != nil {
67 return err
68 }
69
70 return nil
71}
Q8: How do you implement inter-module communication and hooks?
Answer:
Hooks Interface:
1package types
2
3// Hooks defines module hooks
4type Hooks interface {
5 AfterOrderCreated(ctx sdk.Context, orderId uint64)
6 AfterOrderCancelled(ctx sdk.Context, orderId uint64)
7 AfterOrderCompleted(ctx sdk.Context, orderId uint64)
8}
9
10var _ Hooks = Hooks{}
11
12// Hooks is a wrapper struct
13type Hooks struct{}
14
15func (Hooks) AfterOrderCreated(ctx sdk.Context, orderId uint64) {}
16func (Hooks) AfterOrderCancelled(ctx sdk.Context, orderId uint64) {}
17func (Hooks) AfterOrderCompleted(ctx sdk.Context, orderId uint64) {}
Keeper with Hooks:
1package keeper
2
3type Keeper struct {
4 storeKey sdk.StoreKey
5 hooks types.Hooks
6}
7
8// SetHooks sets hooks
9func (k *Keeper) SetHooks(hooks types.Hooks) {
10 if k.hooks != nil {
11 panic("cannot set hooks twice")
12 }
13 k.hooks = hooks
14}
15
16// CreateOrder with hooks
17func (k Keeper) CreateOrder(ctx sdk.Context, order types.Order) error {
18 // Create order
19 k.SetOrder(ctx, order)
20
21 // Call hooks
22 if k.hooks != nil {
23 k.hooks.AfterOrderCreated(ctx, order.Id)
24 }
25
26 return nil
27}
Module Using Hooks:
1package keeper
2
3type NotificationKeeper struct {
4 orderKeeper types.OrderKeeper
5}
6
7// Implement hooks
8func (nk NotificationKeeper) AfterOrderCreated(ctx sdk.Context, orderId uint64) {
9 // Send notification
10 order, _ := nk.orderKeeper.GetOrder(ctx, orderId)
11 nk.SendNotification(ctx, order.Buyer, "Order created")
12}
13
14// Register hooks
15func (app *App) SetupHooks() {
16 orderKeeper := app.OrderKeeper
17 notificationKeeper := app.NotificationKeeper
18
19 orderKeeper.SetHooks(notificationKeeper)
20}
Q9: How do you implement custom consensus parameters and governance?
Answer:
Custom Parameters:
1package types
2
3// Params defines module parameters
4type Params struct {
5 MaxOrderAmount sdk.Int
6 MinOrderAmount sdk.Int
7 OrderTimeout time.Duration
8 FeePercentage sdk.Dec
9}
10
11// DefaultParams returns default parameters
12func DefaultParams() Params {
13 return Params{
14 MaxOrderAmount: sdk.NewInt(1000000),
15 MinOrderAmount: sdk.NewInt(100),
16 OrderTimeout: 24 * time.Hour,
17 FeePercentage: sdk.NewDecWithPrec(1, 2), // 1%
18 }
19}
Parameter Management:
1package keeper
2
3// GetParams gets parameters
4func (k Keeper) GetParams(ctx sdk.Context) types.Params {
5 store := ctx.KVStore(k.storeKey)
6 bz := store.Get(types.ParamsKey)
7 if bz == nil {
8 return types.DefaultParams()
9 }
10
11 var params types.Params
12 k.cdc.MustUnmarshal(bz, ¶ms)
13 return params
14}
15
16// SetParams sets parameters
17func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
18 store := ctx.KVStore(k.storeKey)
19 bz := k.cdc.MustMarshal(¶ms)
20 store.Set(types.ParamsKey, bz)
21}
Governance Proposal:
1package types
2
3// UpdateParamsProposal is a governance proposal
4type UpdateParamsProposal struct {
5 Title string
6 Description string
7 Params Params
8}
9
10// ValidateBasic validates proposal
11func (p UpdateParamsProposal) ValidateBasic() error {
12 if p.Title == "" {
13 return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "title cannot be empty")
14 }
15 if p.Description == "" {
16 return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "description cannot be empty")
17 }
18 return p.Params.Validate()
19}
20
21// Handler for proposal
22func (k Keeper) HandleUpdateParamsProposal(ctx sdk.Context, p UpdateParamsProposal) error {
23 k.SetParams(ctx, p.Params)
24 return nil
25}
Q10: How do you optimize gas usage in Cosmos SDK transactions?
Answer:
Gas Optimization Techniques:
- Use uint64 instead of string for IDs:
1// Bad: Uses more gas
2type Post struct {
3 Id string // Expensive
4 Title string
5}
6
7// Good: Uses less gas
8type Post struct {
9 Id uint64 // Cheap
10 Title string
11}
- Pack structs efficiently:
1// Bad: Wastes storage
2type Order struct {
3 Id uint64 // 8 bytes
4 Status uint8 // 1 byte (but takes 8 bytes due to alignment)
5 Amount sdk.Int
6}
7
8// Good: Packed efficiently
9type Order struct {
10 Id uint64
11 Status uint8
12 _ [7]byte // Padding
13 Amount sdk.Int
14}
- Use iterator instead of loading all:
1// Bad: Loads all into memory
2func (k Keeper) GetAllOrders(ctx sdk.Context) []Order {
3 store := ctx.KVStore(k.storeKey)
4 iterator := sdk.KVStorePrefixIterator(store, []byte{})
5 defer iterator.Close()
6
7 var orders []Order
8 for ; iterator.Valid(); iterator.Next() {
9 var order Order
10 k.cdc.MustUnmarshal(iterator.Value(), &order)
11 orders = append(orders, order) // Expensive append
12 }
13 return orders
14}
15
16// Good: Process one at a time
17func (k Keeper) ProcessOrders(ctx sdk.Context, processor func(Order) error) error {
18 store := ctx.KVStore(k.storeKey)
19 iterator := sdk.KVStorePrefixIterator(store, []byte{})
20 defer iterator.Close()
21
22 for ; iterator.Valid(); iterator.Next() {
23 var order Order
24 k.cdc.MustUnmarshal(iterator.Value(), &order)
25 if err := processor(order); err != nil {
26 return err
27 }
28 }
29 return nil
30}
- Cache expensive computations:
1// Cache computed values
2type Keeper struct {
3 storeKey sdk.StoreKey
4 cache map[string]interface{}
5}
6
7func (k Keeper) GetExpensiveValue(ctx sdk.Context, key string) sdk.Int {
8 // Check cache first
9 if cached, exists := k.cache[key]; exists {
10 return cached.(sdk.Int)
11 }
12
13 // Compute
14 value := k.computeExpensiveValue(ctx, key)
15
16 // Cache
17 k.cache[key] = value
18
19 return value
20}
- Use events instead of storing redundant data:
1// Bad: Store redundant data
2type Order struct {
3 Id uint64
4 CreatedAt time.Time
5 UpdatedAt time.Time // Redundant if we can derive from events
6}
7
8// Good: Use events for history
9func (k Keeper) CreateOrder(ctx sdk.Context, order Order) {
10 k.SetOrder(ctx, order)
11
12 // Emit event (cheaper than storing)
13 ctx.EventManager().EmitEvent(
14 sdk.NewEvent(
15 types.EventTypeOrderCreated,
16 sdk.NewAttribute(types.AttributeKeyOrderId, fmt.Sprintf("%d", order.Id)),
17 sdk.NewAttribute(types.AttributeKeyTimestamp, ctx.BlockTime().String()),
18 ),
19 )
20}
Related Snippets
- Bitcoin (Nakamoto) Consensus Interview Questions
Bitcoin consensus algorithm interview questions covering Proof-of-Work (PoW) and … - Byzantine Fault Tolerance (BFT) Consensus Interview Questions
Byzantine Fault Tolerance (BFT) consensus algorithm interview questions covering … - Cardano Interview Questions - Easy
Easy-level Cardano interview questions covering blockchain basics, Plutus, and … - Cardano Interview Questions - Hard
Hard-level Cardano interview questions covering advanced optimization and formal … - Cardano Interview Questions - Medium
Medium-level Cardano interview questions covering advanced Plutus development … - Consensus Algorithms Comparison Interview Questions
Consensus algorithm comparison and general implementation interview questions. … - Cosmos Chain Operations Interview Questions - Easy
Easy-level Cosmos chain operation interview questions covering chain operations, … - Cosmos Chain Operations Interview Questions - Hard
Hard-level Cosmos chain operation questions covering advanced algorithms, … - Cosmos Chain Operations Interview Questions - Medium
Medium-level Cosmos chain operation questions covering advanced chain … - Cosmos SDK Interview Questions - Easy
Easy-level Cosmos SDK interview questions covering chain code, SDK basics, and … - Cosmos SDK Interview Questions - Hard
Hard-level Cosmos SDK interview questions covering advanced SDK internals, … - Ethereum Proof-of-Stake Consensus Interview Questions
Ethereum Proof-of-Stake consensus algorithm interview questions covering Casper … - Ouroboros (Cardano) Consensus Interview Questions
Ouroboros consensus algorithm interview questions covering Cardano's … - Paxos Consensus Interview Questions
Paxos consensus algorithm interview questions covering the classic distributed … - Polkadot (NPoS) Consensus Interview Questions
Polkadot consensus algorithm interview questions covering Nominated … - Polkadot Interview Questions - Easy
Easy-level Polkadot interview questions covering blockchain basics, Substrate, … - Polkadot Interview Questions - Hard
Hard-level Polkadot interview questions covering advanced optimization and … - Polkadot Interview Questions - Medium
Medium-level Polkadot interview questions covering advanced Substrate … - Solana Interview Questions - Easy
Easy-level Solana interview questions covering blockchain basics, programs, and … - Solana Interview Questions - Hard
Hard-level Solana interview questions covering advanced optimization, security, … - Solana Interview Questions - Medium
Medium-level Solana interview questions covering advanced program development, … - Solana Proof of History Consensus Interview Questions
Solana consensus algorithm interview questions covering Proof of History (PoH) … - Tendermint Consensus Interview Questions
Tendermint consensus algorithm interview questions covering the Byzantine Fault … - Web3 Interview Questions - Easy
Easy-level Web3 interview questions covering blockchain fundamentals, Ethereum, … - Web3 Interview Questions - Hard
Hard-level Web3 interview questions covering MEV, zero-knowledge proofs, … - Web3 Interview Questions - Medium
Medium-level Web3 interview questions covering DeFi, advanced Solidity, …