From 9a2d81e6da98928b2a321503c243053d132ee83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Thu, 16 Apr 2026 11:17:45 +0200 Subject: [PATCH 01/17] feat(poa): added minting and burning messages --- go.mod | 4 +- go.sum | 4 + proto/poa/tx.proto | 29 +++ x/poa/keeper/keeper.go | 58 +++++ x/poa/keeper/keeper_test.go | 2 +- x/poa/keeper/msg_server_burn.go | 24 ++ x/poa/keeper/msg_server_burn_test.go | 141 +++++++++++ x/poa/keeper/msg_server_mint.go | 24 ++ x/poa/keeper/msg_server_mint_test.go | 141 +++++++++++ x/poa/types/codec.go | 8 + x/poa/types/errors.go | 1 + x/poa/types/events.go | 4 + x/poa/types/message_burn.go | 15 ++ x/poa/types/message_mint.go | 15 ++ x/poa/types/tx.pb.go | 147 ++++++++--- x/poa/types/tx_burn.go | 364 +++++++++++++++++++++++++++ x/poa/types/tx_mint.go | 364 +++++++++++++++++++++++++++ 17 files changed, 1310 insertions(+), 35 deletions(-) create mode 100644 x/poa/keeper/msg_server_burn.go create mode 100644 x/poa/keeper/msg_server_burn_test.go create mode 100644 x/poa/keeper/msg_server_mint.go create mode 100644 x/poa/keeper/msg_server_mint_test.go create mode 100644 x/poa/types/message_burn.go create mode 100644 x/poa/types/message_mint.go create mode 100644 x/poa/types/tx_burn.go create mode 100644 x/poa/types/tx_mint.go diff --git a/go.mod b/go.mod index 15b1cc81..ecb9a087 100644 --- a/go.mod +++ b/go.mod @@ -72,8 +72,8 @@ require ( github.com/btcsuite/btcd/btcutil v1.1.6 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic v1.14.2 // indirect - github.com/bytedance/sonic/loader v0.4.0 // indirect + github.com/bytedance/sonic v1.15.0 // indirect + github.com/bytedance/sonic/loader v0.5.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect diff --git a/go.sum b/go.sum index 545617dc..f4a5e076 100644 --- a/go.sum +++ b/go.sum @@ -763,8 +763,12 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1 github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE= github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= +github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= diff --git a/proto/poa/tx.proto b/proto/poa/tx.proto index 8024f37d..0c7c7e2c 100644 --- a/proto/poa/tx.proto +++ b/proto/poa/tx.proto @@ -5,6 +5,7 @@ import "gogoproto/gogo.proto"; import "cosmos_proto/cosmos.proto"; import "cosmos/msg/v1/msg.proto"; import "cosmos/staking/v1beta1/staking.proto"; +import "cosmos/base/v1beta1/coin.proto"; import "google/protobuf/any.proto"; import "amino/amino.proto"; @@ -18,6 +19,10 @@ service Msg { rpc AddValidator(MsgAddValidator) returns (MsgAddValidatorResponse); // Removes an existing validator from the authority rpc RemoveValidator(MsgRemoveValidator) returns (MsgRemoveValidatorResponse); + // Mints tokens and sends them to an address + rpc Mint(MsgMint) returns (MsgMintResponse); + // Burns tokens from an address + rpc Burn(MsgBurn) returns (MsgBurnResponse); } // MsgAddValidator defines a message for adding a new validator @@ -46,3 +51,27 @@ message MsgRemoveValidator { // MsgRemoveValidatorResponse defines the response for removing an existing // validator message MsgRemoveValidatorResponse {} + +// MsgMint defines a message to mint tokens and send them to an address +message MsgMint { + option (cosmos.msg.v1.signer) = "authority"; + + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + cosmos.base.v1beta1.Coin amount = 3 + [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; +} +// MsgMintResponse defines the response for minting tokens +message MsgMintResponse {} + +// MsgBurn defines a message to burn tokens from an address +message MsgBurn { + option (cosmos.msg.v1.signer) = "authority"; + + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + cosmos.base.v1beta1.Coin amount = 3 + [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; +} +// MsgBurnResponse defines the response for burning tokens +message MsgBurnResponse {} diff --git a/x/poa/keeper/keeper.go b/x/poa/keeper/keeper.go index e80da420..3950bc7e 100644 --- a/x/poa/keeper/keeper.go +++ b/x/poa/keeper/keeper.go @@ -206,6 +206,64 @@ func (k Keeper) ExecuteAddValidator(ctx sdk.Context, msg *types.MsgAddValidator) return nil } +func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) error { + if !amount.IsPositive() { + return types.ErrInvalidAmount + } + + toAddr, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + + coins := sdk.NewCoins(amount) + if err := k.bk.MintCoins(ctx, types.ModuleName, coins); err != nil { + return err + } + if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, toAddr, coins); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeMint, + sdk.NewAttribute(types.AttributeAddress, address), + sdk.NewAttribute(types.AttributeAmount, amount.String()), + ), + ) + + return nil +} + +func (k Keeper) ExecuteBurn(ctx sdk.Context, address string, amount sdk.Coin) error { + if !amount.IsPositive() { + return types.ErrInvalidAmount + } + + fromAddr, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + + coins := sdk.NewCoins(amount) + if err := k.bk.SendCoinsFromAccountToModule(ctx, fromAddr, types.ModuleName, coins); err != nil { + return err + } + if err := k.bk.BurnCoins(ctx, types.ModuleName, coins); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeBurn, + sdk.NewAttribute(types.AttributeAddress, address), + sdk.NewAttribute(types.AttributeAmount, amount.String()), + ), + ) + + return nil +} + func (k Keeper) ExecuteRemoveValidator(ctx sdk.Context, validatorAddress string) error { valAddress, err := sdk.ValAddressFromBech32(validatorAddress) if err != nil { diff --git a/x/poa/keeper/keeper_test.go b/x/poa/keeper/keeper_test.go index d1fc9718..d1796c2f 100644 --- a/x/poa/keeper/keeper_test.go +++ b/x/poa/keeper/keeper_test.go @@ -43,7 +43,7 @@ func poaKeeperTestSetup(t *testing.T) (*Keeper, sdk.Context) { }).AnyTimes() bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - bankKeeper.EXPECT().BurnCoins(ctx, stakingtypes.BondedPoolName, gomock.Any()).Return(nil).AnyTimes() + bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() } diff --git a/x/poa/keeper/msg_server_burn.go b/x/poa/keeper/msg_server_burn.go new file mode 100644 index 00000000..e6187435 --- /dev/null +++ b/x/poa/keeper/msg_server_burn.go @@ -0,0 +1,24 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + gov "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/peersyst/cbdc-node/x/poa/types" +) + +func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnResponse, error) { + if k.authority != msg.Authority { + return nil, errors.Wrapf(gov.ErrInvalidSigner, "expected %s got %s", k.authority, msg.Authority) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.ExecuteBurn(ctx, msg.Address, msg.Amount); err != nil { + return nil, err + } + + return &types.MsgBurnResponse{}, nil +} diff --git a/x/poa/keeper/msg_server_burn_test.go b/x/poa/keeper/msg_server_burn_test.go new file mode 100644 index 00000000..f960578c --- /dev/null +++ b/x/poa/keeper/msg_server_burn_test.go @@ -0,0 +1,141 @@ +package keeper + +import ( + "errors" + "testing" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/golang/mock/gomock" + "github.com/peersyst/cbdc-node/x/poa/testutil" + "github.com/peersyst/cbdc-node/x/poa/types" + "github.com/stretchr/testify/require" +) + +func TestMsgServer_Burn(t *testing.T) { + poaKeeper, ctx := poaKeeperTestSetup(t) + msgServer := NewMsgServerImpl(*poaKeeper) + + tt := []struct { + name string + authority string + address string + amount sdk.Coin + expectedErr error + }{ + { + name: "should fail - invalid authority", + authority: "invalidauthority", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + expectedErr: govtypes.ErrInvalidSigner, + }, + { + name: "should fail - invalid address", + authority: poaKeeper.GetAuthority(), + address: "invalidaddress", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + expectedErr: errors.New("decoding bech32 failed"), + }, + { + name: "should fail - zero amount", + authority: poaKeeper.GetAuthority(), + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(0)), + expectedErr: types.ErrInvalidAmount, + }, + { + name: "should pass", + authority: poaKeeper.GetAuthority(), + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + msg := &types.MsgBurn{ + Authority: tc.authority, + Address: tc.address, + Amount: tc.amount, + } + + _, err := msgServer.Burn(ctx, msg) + if tc.expectedErr != nil { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedErr.Error()) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestKeeper_ExecuteBurn(t *testing.T) { + tt := []struct { + name string + address string + amount sdk.Coin + bankMocks func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) + expectedError error + }{ + { + name: "should fail - zero amount", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(0)), + bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, + expectedError: types.ErrInvalidAmount, + }, + { + name: "should fail - invalid address", + address: "invalidaddress", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, + expectedError: errors.New("decoding bech32 failed"), + }, + { + name: "should fail - SendCoinsFromAccountToModule returns error", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("bank send error")) + }, + expectedError: errors.New("bank send error"), + }, + { + name: "should fail - BurnCoins returns error", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(errors.New("bank burn error")) + }, + expectedError: errors.New("bank burn error"), + }, + { + name: "should pass", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + coins := sdk.NewCoins(sdk.NewCoin("XRP", math.NewInt(100))) + bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), types.ModuleName, coins).Return(nil) + bankKeeper.EXPECT().BurnCoins(ctx, types.ModuleName, coins).Return(nil) + }, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + keeper, ctx := setupPoaKeeper(t, func(_ sdk.Context, _ *testutil.MockStakingKeeper) {}, tc.bankMocks) + + err := keeper.ExecuteBurn(ctx, tc.address, tc.amount) + if tc.expectedError != nil { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedError.Error()) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/poa/keeper/msg_server_mint.go b/x/poa/keeper/msg_server_mint.go new file mode 100644 index 00000000..f177480d --- /dev/null +++ b/x/poa/keeper/msg_server_mint.go @@ -0,0 +1,24 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + gov "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/peersyst/cbdc-node/x/poa/types" +) + +func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMintResponse, error) { + if k.authority != msg.Authority { + return nil, errors.Wrapf(gov.ErrInvalidSigner, "expected %s got %s", k.authority, msg.Authority) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.ExecuteMint(ctx, msg.Address, msg.Amount); err != nil { + return nil, err + } + + return &types.MsgMintResponse{}, nil +} diff --git a/x/poa/keeper/msg_server_mint_test.go b/x/poa/keeper/msg_server_mint_test.go new file mode 100644 index 00000000..96aac495 --- /dev/null +++ b/x/poa/keeper/msg_server_mint_test.go @@ -0,0 +1,141 @@ +package keeper + +import ( + "errors" + "testing" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/golang/mock/gomock" + "github.com/peersyst/cbdc-node/x/poa/testutil" + "github.com/peersyst/cbdc-node/x/poa/types" + "github.com/stretchr/testify/require" +) + +func TestMsgServer_Mint(t *testing.T) { + poaKeeper, ctx := poaKeeperTestSetup(t) + msgServer := NewMsgServerImpl(*poaKeeper) + + tt := []struct { + name string + authority string + address string + amount sdk.Coin + expectedErr error + }{ + { + name: "should fail - invalid authority", + authority: "invalidauthority", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + expectedErr: govtypes.ErrInvalidSigner, + }, + { + name: "should fail - invalid recipient address", + authority: poaKeeper.GetAuthority(), + address: "invalidaddress", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + expectedErr: errors.New("decoding bech32 failed"), + }, + { + name: "should fail - zero amount", + authority: poaKeeper.GetAuthority(), + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(0)), + expectedErr: types.ErrInvalidAmount, + }, + { + name: "should pass", + authority: poaKeeper.GetAuthority(), + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + msg := &types.MsgMint{ + Authority: tc.authority, + Address: tc.address, + Amount: tc.amount, + } + + _, err := msgServer.Mint(ctx, msg) + if tc.expectedErr != nil { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedErr.Error()) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestKeeper_ExecuteMint(t *testing.T) { + tt := []struct { + name string + address string + amount sdk.Coin + bankMocks func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) + expectedError error + }{ + { + name: "should fail - zero amount", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(0)), + bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, + expectedError: types.ErrInvalidAmount, + }, + { + name: "should fail - invalid address", + address: "invalidaddress", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, + expectedError: errors.New("decoding bech32 failed"), + }, + { + name: "should fail - MintCoins returns error", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(errors.New("bank mint error")) + }, + expectedError: errors.New("bank mint error"), + }, + { + name: "should fail - SendCoinsFromModuleToAccount returns error", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(nil) + bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("bank send error")) + }, + expectedError: errors.New("bank send error"), + }, + { + name: "should pass", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("XRP", math.NewInt(100)), + bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + coins := sdk.NewCoins(sdk.NewCoin("XRP", math.NewInt(100))) + bankKeeper.EXPECT().MintCoins(ctx, types.ModuleName, coins).Return(nil) + bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, types.ModuleName, gomock.Any(), coins).Return(nil) + }, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + keeper, ctx := setupPoaKeeper(t, func(_ sdk.Context, _ *testutil.MockStakingKeeper) {}, tc.bankMocks) + + err := keeper.ExecuteMint(ctx, tc.address, tc.amount) + if tc.expectedError != nil { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedError.Error()) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/poa/types/codec.go b/x/poa/types/codec.go index 77d089cc..34768d0c 100644 --- a/x/poa/types/codec.go +++ b/x/poa/types/codec.go @@ -11,6 +11,8 @@ import ( func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgAddValidator{}, "poa/AddValidator", nil) cdc.RegisterConcrete(&MsgRemoveValidator{}, "poa/RemoveValidator", nil) + cdc.RegisterConcrete(&MsgMint{}, "poa/Mint", nil) + cdc.RegisterConcrete(&MsgBurn{}, "poa/Burn", nil) // this line is used by starport scaffolding # 2 } @@ -21,6 +23,12 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgRemoveValidator{}, ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgMint{}, + ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgBurn{}, + ) registry.RegisterImplementations( (*govtypes.Content)(nil), ) diff --git a/x/poa/types/errors.go b/x/poa/types/errors.go index af388423..738c2aaa 100644 --- a/x/poa/types/errors.go +++ b/x/poa/types/errors.go @@ -15,4 +15,5 @@ var ( ErrInvalidValidatorStatus = sdkerrors.Register(ModuleName, 5, "invalid validator status") ErrAddressIsNotAValidator = sdkerrors.Register(ModuleName, 6, "address is not a validator") ErrMaxValidatorsReached = sdkerrors.Register(ModuleName, 7, "maximum number of validators reached") + ErrInvalidAmount = sdkerrors.Register(ModuleName, 8, "amount must be positive") ) diff --git a/x/poa/types/events.go b/x/poa/types/events.go index b81d174f..00b3ac49 100644 --- a/x/poa/types/events.go +++ b/x/poa/types/events.go @@ -3,8 +3,12 @@ package types const ( EventTypeAddValidator = "add_validator" EventTypeRemoveValidator = "remove_validator" + EventTypeMint = "mint" + EventTypeBurn = "burn" AttributeValidator = "address" AttributeHeight = "height" AttributeStakingTokens = "staking_tokens" AttributeBankTokens = "bank_tokens" + AttributeAddress = "address" + AttributeAmount = "amount" ) diff --git a/x/poa/types/message_burn.go b/x/poa/types/message_burn.go new file mode 100644 index 00000000..32071bc5 --- /dev/null +++ b/x/poa/types/message_burn.go @@ -0,0 +1,15 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ sdk.Msg = &MsgBurn{} + +func NewMsgBurn(authority string, address string, amount sdk.Coin) *MsgBurn { + return &MsgBurn{ + Authority: authority, + Address: address, + Amount: amount, + } +} diff --git a/x/poa/types/message_mint.go b/x/poa/types/message_mint.go new file mode 100644 index 00000000..6e342e71 --- /dev/null +++ b/x/poa/types/message_mint.go @@ -0,0 +1,15 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ sdk.Msg = &MsgMint{} + +func NewMsgMint(authority string, address string, amount sdk.Coin) *MsgMint { + return &MsgMint{ + Authority: authority, + Address: address, + Amount: amount, + } +} diff --git a/x/poa/types/tx.pb.go b/x/poa/types/tx.pb.go index baa307ef..1ef73165 100644 --- a/x/poa/types/tx.pb.go +++ b/x/poa/types/tx.pb.go @@ -240,38 +240,45 @@ func init() { func init() { proto.RegisterFile("poa/tx.proto", fileDescriptor_8ac16a0aed23c2e2) } var fileDescriptor_8ac16a0aed23c2e2 = []byte{ - // 493 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0x3f, 0x6f, 0xd3, 0x40, - 0x18, 0xc6, 0xe3, 0x06, 0x2a, 0xe5, 0x5a, 0x51, 0x6a, 0x45, 0x8a, 0x6b, 0x15, 0xb7, 0x0a, 0x0c, - 0xa5, 0x52, 0xef, 0xd4, 0x22, 0x31, 0xb0, 0xc5, 0xfc, 0x19, 0xa8, 0x22, 0x55, 0x46, 0x62, 0x60, - 0xa9, 0xce, 0xf6, 0x71, 0xb5, 0x5a, 0xfb, 0x3d, 0xf9, 0xce, 0x51, 0xbd, 0x21, 0x3e, 0x01, 0x5f, - 0x80, 0x89, 0x85, 0xb1, 0x03, 0x3b, 0x6b, 0xc5, 0x54, 0x31, 0x31, 0x21, 0x94, 0x0c, 0xfd, 0x1a, - 0xc8, 0xf6, 0x1d, 0x81, 0x84, 0x4c, 0x5d, 0x12, 0xbf, 0xf7, 0x7b, 0x9f, 0x47, 0xef, 0xfb, 0xf8, - 0x8c, 0x56, 0x05, 0x50, 0xa2, 0xce, 0xb1, 0xc8, 0x41, 0x81, 0xdd, 0x16, 0x40, 0xdd, 0x2e, 0x07, - 0x0e, 0x75, 0x4d, 0xaa, 0xa7, 0x06, 0xb9, 0x1b, 0x11, 0xc8, 0x14, 0xe4, 0x71, 0x03, 0x9a, 0x42, - 0xa3, 0x5e, 0x53, 0x91, 0x54, 0x72, 0x32, 0xda, 0xaf, 0xfe, 0x34, 0x78, 0xa0, 0x81, 0x54, 0xf4, - 0x34, 0xc9, 0x2a, 0x18, 0x32, 0x45, 0xf7, 0x4d, 0x6d, 0x9c, 0x39, 0x00, 0x3f, 0x63, 0xa4, 0xae, - 0xc2, 0xe2, 0x2d, 0xa1, 0x59, 0xa9, 0xd1, 0x3a, 0x4d, 0x93, 0x0c, 0x48, 0xfd, 0xdb, 0x1c, 0xf5, - 0xbf, 0x2e, 0xa1, 0xb5, 0xa1, 0xe4, 0x83, 0x38, 0x7e, 0x4d, 0xcf, 0x92, 0x98, 0x2a, 0xc8, 0xed, - 0xc7, 0xa8, 0x43, 0x0b, 0x75, 0x02, 0x79, 0xa2, 0x4a, 0xc7, 0xda, 0xb6, 0x76, 0x3a, 0xbe, 0xf3, - 0xfd, 0xcb, 0x5e, 0x57, 0x4f, 0x39, 0x88, 0xe3, 0x9c, 0x49, 0xf9, 0x4a, 0xe5, 0x49, 0xc6, 0x83, - 0x69, 0xab, 0xfd, 0x12, 0xad, 0x8f, 0x8c, 0xc9, 0x31, 0x6d, 0xba, 0x9c, 0xa5, 0x5a, 0x7f, 0x6f, - 0x91, 0xfe, 0xf3, 0xf5, 0xc5, 0x6e, 0x2b, 0xb8, 0xfb, 0x47, 0xa7, 0xa1, 0x7d, 0x84, 0x56, 0x62, - 0x26, 0xa3, 0x3c, 0x11, 0x2a, 0x81, 0xcc, 0x69, 0x6f, 0x5b, 0x3b, 0x2b, 0x07, 0xf7, 0xb1, 0xb6, - 0x30, 0x1b, 0xeb, 0x04, 0xf0, 0xb3, 0x69, 0xab, 0xdf, 0xb9, 0xfc, 0xb9, 0xd5, 0xaa, 0x6c, 0xad, - 0xe0, 0x6f, 0x0b, 0xfb, 0x05, 0x5a, 0x16, 0x45, 0x78, 0xca, 0x4a, 0xe7, 0x56, 0x6d, 0xd6, 0xc5, - 0x4d, 0x50, 0xd8, 0x04, 0x85, 0x07, 0x59, 0xe9, 0x3b, 0xdf, 0xa6, 0x83, 0x46, 0x79, 0x29, 0x14, - 0xe0, 0xa3, 0x22, 0x3c, 0x64, 0x65, 0xa0, 0xd5, 0x4f, 0xee, 0xbc, 0xbf, 0xbe, 0xd8, 0x9d, 0x6e, - 0xdd, 0xdf, 0x40, 0xbd, 0x99, 0x00, 0x03, 0x26, 0x05, 0x64, 0x92, 0xf5, 0x3f, 0x59, 0xc8, 0x1e, - 0x4a, 0x1e, 0xb0, 0x14, 0x46, 0xec, 0xe6, 0xf9, 0x3e, 0x5f, 0x9c, 0xef, 0x62, 0xfd, 0x5c, 0xb4, - 0x73, 0x0b, 0x6c, 0x22, 0x77, 0x7e, 0x48, 0xb3, 0xc3, 0xc1, 0x47, 0x0b, 0xb5, 0x87, 0x92, 0xdb, - 0x3e, 0x5a, 0xfd, 0xe7, 0x92, 0x74, 0xb1, 0x00, 0x8a, 0x67, 0x36, 0x77, 0x37, 0xff, 0x77, 0x6a, - 0xbc, 0xec, 0x43, 0xb4, 0x36, 0x9b, 0x45, 0xcf, 0x08, 0x66, 0x80, 0xbb, 0xb5, 0x00, 0x18, 0x33, - 0xf7, 0xf6, 0xbb, 0xea, 0x1d, 0xfb, 0x4f, 0x2f, 0xc7, 0x9e, 0x75, 0x35, 0xf6, 0xac, 0x5f, 0x63, - 0xcf, 0xfa, 0x30, 0xf1, 0x5a, 0x57, 0x13, 0xaf, 0xf5, 0x63, 0xe2, 0xb5, 0xde, 0x3c, 0xe4, 0x89, - 0x3a, 0x29, 0x42, 0x1c, 0x41, 0x4a, 0x04, 0x63, 0xb9, 0x2c, 0xa5, 0x22, 0x51, 0x18, 0x47, 0x7b, - 0x19, 0xc4, 0x8c, 0x9c, 0x93, 0xfa, 0x5b, 0x2d, 0x05, 0x93, 0xe1, 0x72, 0x7d, 0x07, 0x1e, 0xfd, - 0x0e, 0x00, 0x00, 0xff, 0xff, 0x77, 0xf0, 0x55, 0x34, 0xbf, 0x03, 0x00, 0x00, + // 593 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xbc, 0x54, 0xb1, 0x6f, 0xd3, 0x4e, + 0x14, 0x8e, 0xdb, 0xfe, 0x5a, 0xe5, 0x1a, 0xfd, 0x4a, 0xac, 0x48, 0x71, 0xac, 0xe0, 0x56, 0x81, + 0xa1, 0x44, 0xaa, 0xad, 0x14, 0x89, 0x81, 0x2d, 0x2e, 0x30, 0x50, 0x45, 0xaa, 0x8c, 0xc4, 0xc0, + 0x52, 0x9d, 0xed, 0xc3, 0xb5, 0x5a, 0xdf, 0xb3, 0x7c, 0xe7, 0xa8, 0xde, 0x10, 0x7f, 0x01, 0xff, + 0x03, 0x0b, 0x63, 0x07, 0x76, 0xd6, 0x8a, 0xa9, 0x62, 0x62, 0x42, 0x28, 0x19, 0xfa, 0x17, 0xb0, + 0x23, 0xdb, 0x77, 0x4e, 0x9a, 0x90, 0x09, 0x89, 0x25, 0xc9, 0xe7, 0xef, 0xbd, 0xcf, 0xdf, 0xfb, + 0xee, 0x5d, 0x50, 0x23, 0x06, 0x6c, 0xf1, 0x4b, 0x33, 0x4e, 0x80, 0x83, 0xba, 0x1e, 0x03, 0xd6, + 0x5b, 0x01, 0x04, 0x50, 0x60, 0x2b, 0xff, 0x55, 0x52, 0x7a, 0xc7, 0x03, 0x16, 0x01, 0x3b, 0x2d, + 0x89, 0x12, 0x08, 0xaa, 0x5d, 0x22, 0x2b, 0x62, 0x81, 0x35, 0x1e, 0xe4, 0x5f, 0x82, 0x78, 0x28, + 0x08, 0xc6, 0xf1, 0x79, 0x48, 0x73, 0xd2, 0x25, 0x1c, 0x0f, 0x24, 0x96, 0xca, 0x01, 0x40, 0x70, + 0x41, 0xac, 0x02, 0xb9, 0xe9, 0x5b, 0x0b, 0xd3, 0x4c, 0x50, 0x4d, 0x1c, 0x85, 0x14, 0xac, 0xe2, + 0x53, 0x3c, 0x32, 0x84, 0xa6, 0x8b, 0x19, 0xa9, 0x04, 0x3d, 0x08, 0x69, 0xc9, 0xf7, 0xbe, 0xac, + 0xa1, 0x9d, 0x11, 0x0b, 0x86, 0xbe, 0xff, 0x1a, 0x5f, 0x84, 0x3e, 0xe6, 0x90, 0xa8, 0x4f, 0x50, + 0x1d, 0xa7, 0xfc, 0x0c, 0x92, 0x90, 0x67, 0x9a, 0xb2, 0xa7, 0xec, 0xd7, 0x6d, 0xed, 0xdb, 0xe7, + 0x83, 0x96, 0x98, 0x62, 0xe8, 0xfb, 0x09, 0x61, 0xec, 0x15, 0x4f, 0x42, 0x1a, 0x38, 0xb3, 0x52, + 0xf5, 0x25, 0x6a, 0x8e, 0xa5, 0xc8, 0x29, 0x2e, 0xab, 0xb4, 0xb5, 0xa2, 0xff, 0xfe, 0xaa, 0xfe, + 0x4f, 0xb7, 0x57, 0xfd, 0x9a, 0x73, 0xaf, 0xea, 0x13, 0xa4, 0x7a, 0x82, 0xb6, 0x7d, 0xc2, 0xbc, + 0x24, 0x8c, 0x79, 0x08, 0x54, 0x5b, 0xdf, 0x53, 0xf6, 0xb7, 0x0f, 0x1f, 0x98, 0x42, 0x42, 0x26, + 0x22, 0x06, 0x32, 0x9f, 0xcd, 0x4a, 0xed, 0xfa, 0xf5, 0x8f, 0xdd, 0x5a, 0x2e, 0xab, 0x38, 0xf3, + 0x12, 0xea, 0x0b, 0xb4, 0x19, 0xa7, 0xee, 0x39, 0xc9, 0xb4, 0x8d, 0x42, 0xac, 0x65, 0x96, 0x41, + 0x9a, 0x32, 0x48, 0x73, 0x48, 0x33, 0x5b, 0xfb, 0x3a, 0x33, 0xea, 0x25, 0x59, 0xcc, 0xc1, 0x3c, + 0x49, 0xdd, 0x63, 0x92, 0x39, 0xa2, 0xfb, 0xe9, 0xff, 0xef, 0x6f, 0xaf, 0xfa, 0xb3, 0xa9, 0x7b, + 0x1d, 0xd4, 0x5e, 0x08, 0xd0, 0x21, 0x2c, 0x06, 0xca, 0x48, 0xef, 0xa3, 0x82, 0xd4, 0x11, 0x0b, + 0x1c, 0x12, 0xc1, 0x98, 0xfc, 0x7d, 0xbe, 0xcf, 0x57, 0xe7, 0xbb, 0xba, 0x7f, 0x29, 0xda, 0xa5, + 0x01, 0xba, 0x48, 0x5f, 0x36, 0x59, 0xcd, 0xc0, 0xd1, 0xd6, 0x88, 0x05, 0xa3, 0x90, 0x72, 0xb5, + 0xbb, 0xe4, 0x7b, 0xde, 0x9d, 0x86, 0xb6, 0xee, 0x78, 0x72, 0x24, 0x54, 0x07, 0x68, 0x13, 0x47, + 0x90, 0x52, 0x2e, 0x8e, 0xb1, 0x23, 0x8f, 0x31, 0x5f, 0xca, 0xea, 0x0c, 0x8f, 0x20, 0xa4, 0x8e, + 0x28, 0xec, 0x35, 0x8b, 0xad, 0xcc, 0xdf, 0xba, 0x60, 0xc4, 0x4e, 0x13, 0xfa, 0xef, 0x8d, 0xe4, + 0x6f, 0x95, 0x46, 0x0e, 0x7f, 0x29, 0x68, 0x7d, 0xc4, 0x02, 0xd5, 0x46, 0x8d, 0x3b, 0xd7, 0xa6, + 0x65, 0xc6, 0x80, 0xcd, 0x85, 0x5d, 0xd0, 0xbb, 0x7f, 0x7a, 0x2a, 0xb5, 0xd4, 0x63, 0xb4, 0xb3, + 0xb8, 0x1d, 0x6d, 0xd9, 0xb0, 0x40, 0xe8, 0xbb, 0x2b, 0x88, 0x4a, 0xac, 0x8f, 0x36, 0x8a, 0x73, + 0x6a, 0xc8, 0xc2, 0x1c, 0xe9, 0xad, 0x79, 0x34, 0x5f, 0x5b, 0x44, 0x59, 0xd5, 0xe6, 0x68, 0x56, + 0x3b, 0x3f, 0xb0, 0xfe, 0xdf, 0xbb, 0xfc, 0x36, 0xd9, 0x47, 0x6f, 0x1e, 0x05, 0x21, 0x3f, 0x4b, + 0x5d, 0xd3, 0x83, 0xc8, 0x8a, 0x09, 0x49, 0x58, 0xc6, 0xb8, 0xe5, 0xb9, 0xbe, 0x77, 0x40, 0xc1, + 0x27, 0xd6, 0xa5, 0x55, 0xfc, 0x3b, 0x66, 0x31, 0x61, 0xd7, 0x13, 0x43, 0xb9, 0x99, 0x18, 0xca, + 0xcf, 0x89, 0xa1, 0x7c, 0x98, 0x1a, 0xb5, 0x9b, 0xa9, 0x51, 0xfb, 0x3e, 0x35, 0x6a, 0xee, 0x66, + 0x71, 0xdb, 0x1e, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x92, 0x1c, 0xb0, 0xb2, 0x49, 0x05, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -290,6 +297,10 @@ type MsgClient interface { AddValidator(ctx context.Context, in *MsgAddValidator, opts ...grpc.CallOption) (*MsgAddValidatorResponse, error) // Removes an existing validator from the authority RemoveValidator(ctx context.Context, in *MsgRemoveValidator, opts ...grpc.CallOption) (*MsgRemoveValidatorResponse, error) + // Mints tokens and sends them to an address + Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) + // Burns tokens from an address + Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) } type msgClient struct { @@ -318,12 +329,34 @@ func (c *msgClient) RemoveValidator(ctx context.Context, in *MsgRemoveValidator, return out, nil } +func (c *msgClient) Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) { + out := new(MsgMintResponse) + err := c.cc.Invoke(ctx, "/poa.Msg/Mint", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) { + out := new(MsgBurnResponse) + err := c.cc.Invoke(ctx, "/poa.Msg/Burn", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // Adds a new validator into the authority AddValidator(context.Context, *MsgAddValidator) (*MsgAddValidatorResponse, error) // Removes an existing validator from the authority RemoveValidator(context.Context, *MsgRemoveValidator) (*MsgRemoveValidatorResponse, error) + // Mints tokens and sends them to an address + Mint(context.Context, *MsgMint) (*MsgMintResponse, error) + // Burns tokens from an address + Burn(context.Context, *MsgBurn) (*MsgBurnResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -336,6 +369,12 @@ func (*UnimplementedMsgServer) AddValidator(ctx context.Context, req *MsgAddVali func (*UnimplementedMsgServer) RemoveValidator(ctx context.Context, req *MsgRemoveValidator) (*MsgRemoveValidatorResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveValidator not implemented") } +func (*UnimplementedMsgServer) Mint(ctx context.Context, req *MsgMint) (*MsgMintResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Mint not implemented") +} +func (*UnimplementedMsgServer) Burn(ctx context.Context, req *MsgBurn) (*MsgBurnResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Burn not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -377,6 +416,42 @@ func _Msg_RemoveValidator_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _Msg_Mint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgMint) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Mint(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/poa.Msg/Mint", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Mint(ctx, req.(*MsgMint)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_Burn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgBurn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Burn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/poa.Msg/Burn", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Burn(ctx, req.(*MsgBurn)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "poa.Msg", HandlerType: (*MsgServer)(nil), @@ -389,6 +464,14 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "RemoveValidator", Handler: _Msg_RemoveValidator_Handler, }, + { + MethodName: "Mint", + Handler: _Msg_Mint_Handler, + }, + { + MethodName: "Burn", + Handler: _Msg_Burn_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "poa/tx.proto", diff --git a/x/poa/types/tx_burn.go b/x/poa/types/tx_burn.go new file mode 100644 index 00000000..165c9a7e --- /dev/null +++ b/x/poa/types/tx_burn.go @@ -0,0 +1,364 @@ +// Manually implemented proto-compatible types for MsgBurn. +// These follow the same encoding conventions as the protoc-gen-gogo output in tx.pb.go. +// Run `make proto-gen` after updating proto/poa/tx.proto to regenerate instead. +package types + +import ( + "fmt" + "io" + + sdk "github.com/cosmos/cosmos-sdk/types" + proto "github.com/cosmos/gogoproto/proto" +) + +// MsgBurn defines a message to burn tokens from an address. +type MsgBurn struct { + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Amount sdk.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` +} + +func (m *MsgBurn) Reset() { *m = MsgBurn{} } +func (m *MsgBurn) String() string { return proto.CompactTextString(m) } +func (*MsgBurn) ProtoMessage() {} + +func (m *MsgBurn) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgBurn) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgBurn) GetAmount() sdk.Coin { + if m != nil { + return m.Amount + } + return sdk.Coin{} +} + +// MsgBurnResponse defines the response for burning tokens. +type MsgBurnResponse struct{} + +func (m *MsgBurnResponse) Reset() { *m = MsgBurnResponse{} } +func (m *MsgBurnResponse) String() string { return proto.CompactTextString(m) } +func (*MsgBurnResponse) ProtoMessage() {} + +func init() { + proto.RegisterType((*MsgBurn)(nil), "poa.MsgBurn") + proto.RegisterType((*MsgBurnResponse)(nil), "poa.MsgBurnResponse") +} + +// --------------------------------------------------------------------------- +// Marshal / MarshalTo / MarshalToSizedBuffer +// --------------------------------------------------------------------------- + +func (m *MsgBurn) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgBurn) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBurn) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + // field 3: amount (sdk.Coin, always written – non-nullable) + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + // field 2: address + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + // field 1: authority + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgBurnResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgBurnResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBurnResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +// --------------------------------------------------------------------------- +// Size +// --------------------------------------------------------------------------- + +func (m *MsgBurn) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgBurnResponse) Size() (n int) { + if m == nil { + return 0 + } + return n +} + +// --------------------------------------------------------------------------- +// Unmarshal +// --------------------------------------------------------------------------- + +func (m *MsgBurn) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgBurn: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBurn: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: // Authority + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: // Address + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: // Amount + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} + +func (m *MsgBurnResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgBurnResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBurnResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/x/poa/types/tx_mint.go b/x/poa/types/tx_mint.go new file mode 100644 index 00000000..58485c25 --- /dev/null +++ b/x/poa/types/tx_mint.go @@ -0,0 +1,364 @@ +// Manually implemented proto-compatible types for MsgMint. +// These follow the same encoding conventions as the protoc-gen-gogo output in tx.pb.go. +// Run `make proto-gen` after updating proto/poa/tx.proto to regenerate instead. +package types + +import ( + "fmt" + "io" + + sdk "github.com/cosmos/cosmos-sdk/types" + proto "github.com/cosmos/gogoproto/proto" +) + +// MsgMint defines a message to mint tokens and send them to an address. +type MsgMint struct { + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Amount sdk.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` +} + +func (m *MsgMint) Reset() { *m = MsgMint{} } +func (m *MsgMint) String() string { return proto.CompactTextString(m) } +func (*MsgMint) ProtoMessage() {} + +func (m *MsgMint) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgMint) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgMint) GetAmount() sdk.Coin { + if m != nil { + return m.Amount + } + return sdk.Coin{} +} + +// MsgMintResponse defines the response for minting tokens. +type MsgMintResponse struct{} + +func (m *MsgMintResponse) Reset() { *m = MsgMintResponse{} } +func (m *MsgMintResponse) String() string { return proto.CompactTextString(m) } +func (*MsgMintResponse) ProtoMessage() {} + +func init() { + proto.RegisterType((*MsgMint)(nil), "poa.MsgMint") + proto.RegisterType((*MsgMintResponse)(nil), "poa.MsgMintResponse") +} + +// --------------------------------------------------------------------------- +// Marshal / MarshalTo / MarshalToSizedBuffer +// --------------------------------------------------------------------------- + +func (m *MsgMint) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMint) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMint) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + // field 3: amount (sdk.Coin, always written – non-nullable) + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + // field 2: address + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + // field 1: authority + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgMintResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMintResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMintResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +// --------------------------------------------------------------------------- +// Size +// --------------------------------------------------------------------------- + +func (m *MsgMint) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgMintResponse) Size() (n int) { + if m == nil { + return 0 + } + return n +} + +// --------------------------------------------------------------------------- +// Unmarshal +// --------------------------------------------------------------------------- + +func (m *MsgMint) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMint: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMint: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: // Authority + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: // Address + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: // Amount + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} + +func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMintResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMintResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} From 798109a52e419bab8f3bf1614eb18f853408c68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Thu, 30 Apr 2026 14:47:21 +0200 Subject: [PATCH 02/17] fix(minting): correct linting error --- app/app.go | 1 + x/poa/keeper/common_test.go | 2 + x/poa/keeper/keeper.go | 13 + x/poa/keeper/msg_server_burn_test.go | 36 +- x/poa/keeper/msg_server_mint_test.go | 36 +- x/poa/types/errors.go | 1 + x/poa/types/tx.pb.go | 889 +++++++++++++++++++++++++-- x/poa/types/tx_burn.go | 364 ----------- x/poa/types/tx_mint.go | 364 ----------- 9 files changed, 907 insertions(+), 799 deletions(-) delete mode 100644 x/poa/types/tx_burn.go delete mode 100644 x/poa/types/tx_mint.go diff --git a/app/app.go b/app/app.go index c92e3fe4..abd2faef 100644 --- a/app/app.go +++ b/app/app.go @@ -469,6 +469,7 @@ func New( app.BankKeeper, app.StakingKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(), + BaseDenom, ) // Ethermint keepers diff --git a/x/poa/keeper/common_test.go b/x/poa/keeper/common_test.go index e90d77e1..0ee4b673 100644 --- a/x/poa/keeper/common_test.go +++ b/x/poa/keeper/common_test.go @@ -22,6 +22,7 @@ import ( const ( accountAddressPrefix = "ethm" bip44CoinType = 60 + testCBDCDenom = "acbdc" ) func setupSdkConfig() { @@ -83,6 +84,7 @@ func getMockedPoAKeeper(t *testing.T, key *storetypes.KVStoreKey, tsKey *storety bankKeeper, stakingKeeper, "ethm1wunfhl05vc8r8xxnnp8gt62wa54r6y52pg03zq", + testCBDCDenom, ) poaKeeper.SetParams(ctx, types.DefaultParams()) types.RegisterMsgServer(msr, NewMsgServerImpl(*poaKeeper)) diff --git a/x/poa/keeper/keeper.go b/x/poa/keeper/keeper.go index 3950bc7e..b97f9a70 100644 --- a/x/poa/keeper/keeper.go +++ b/x/poa/keeper/keeper.go @@ -38,6 +38,7 @@ type ( router *baseapp.MsgServiceRouter // Msg server router bk types.BankKeeper sk types.StakingKeeper + cbdcDenom string // the only denom that can be minted/burned via this module } ) @@ -48,6 +49,7 @@ func NewKeeper( bk types.BankKeeper, sk types.StakingKeeper, authority string, + cbdcDenom string, ) *Keeper { // set KeyTable if it has not already been set if !ps.HasKeyTable() { @@ -59,6 +61,10 @@ func NewKeeper( panic(err) } + if err := sdk.ValidateDenom(cbdcDenom); err != nil { + panic(err) + } + return &Keeper{ cdc: cdc, paramstore: ps, @@ -66,6 +72,7 @@ func NewKeeper( router: router, bk: bk, sk: sk, + cbdcDenom: cbdcDenom, } } @@ -207,6 +214,9 @@ func (k Keeper) ExecuteAddValidator(ctx sdk.Context, msg *types.MsgAddValidator) } func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) error { + if amount.Denom != k.cbdcDenom { + return types.ErrInvalidDenom + } if !amount.IsPositive() { return types.ErrInvalidAmount } @@ -236,6 +246,9 @@ func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) er } func (k Keeper) ExecuteBurn(ctx sdk.Context, address string, amount sdk.Coin) error { + if amount.Denom != k.cbdcDenom { + return types.ErrInvalidDenom + } if !amount.IsPositive() { return types.ErrInvalidAmount } diff --git a/x/poa/keeper/msg_server_burn_test.go b/x/poa/keeper/msg_server_burn_test.go index f960578c..60662956 100644 --- a/x/poa/keeper/msg_server_burn_test.go +++ b/x/poa/keeper/msg_server_burn_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestMsgServer_Burn(t *testing.T) { +func TestMsgServer_Burn(t *testing.T) { //nolint:dupl poaKeeper, ctx := poaKeeperTestSetup(t) msgServer := NewMsgServerImpl(*poaKeeper) @@ -28,28 +28,35 @@ func TestMsgServer_Burn(t *testing.T) { name: "should fail - invalid authority", authority: "invalidauthority", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), expectedErr: govtypes.ErrInvalidSigner, }, { name: "should fail - invalid address", authority: poaKeeper.GetAuthority(), address: "invalidaddress", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), expectedErr: errors.New("decoding bech32 failed"), }, { name: "should fail - zero amount", authority: poaKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(0)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), expectedErr: types.ErrInvalidAmount, }, + { + name: "should fail - wrong denom", + authority: poaKeeper.GetAuthority(), + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("axrp", math.NewInt(100)), + expectedErr: types.ErrInvalidDenom, + }, { name: "should pass", authority: poaKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), }, } @@ -83,21 +90,28 @@ func TestKeeper_ExecuteBurn(t *testing.T) { { name: "should fail - zero amount", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(0)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: types.ErrInvalidAmount, }, + { + name: "should fail - wrong denom", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("axrp", math.NewInt(100)), + bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, + expectedError: types.ErrInvalidDenom, + }, { name: "should fail - invalid address", address: "invalidaddress", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: errors.New("decoding bech32 failed"), }, { name: "should fail - SendCoinsFromAccountToModule returns error", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("bank send error")) }, @@ -106,7 +120,7 @@ func TestKeeper_ExecuteBurn(t *testing.T) { { name: "should fail - BurnCoins returns error", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(errors.New("bank burn error")) @@ -116,9 +130,9 @@ func TestKeeper_ExecuteBurn(t *testing.T) { { name: "should pass", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { - coins := sdk.NewCoins(sdk.NewCoin("XRP", math.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin(testCBDCDenom, math.NewInt(100))) bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), types.ModuleName, coins).Return(nil) bankKeeper.EXPECT().BurnCoins(ctx, types.ModuleName, coins).Return(nil) }, diff --git a/x/poa/keeper/msg_server_mint_test.go b/x/poa/keeper/msg_server_mint_test.go index 96aac495..4cd29159 100644 --- a/x/poa/keeper/msg_server_mint_test.go +++ b/x/poa/keeper/msg_server_mint_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestMsgServer_Mint(t *testing.T) { +func TestMsgServer_Mint(t *testing.T) { //nolint:dupl poaKeeper, ctx := poaKeeperTestSetup(t) msgServer := NewMsgServerImpl(*poaKeeper) @@ -28,28 +28,35 @@ func TestMsgServer_Mint(t *testing.T) { name: "should fail - invalid authority", authority: "invalidauthority", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), expectedErr: govtypes.ErrInvalidSigner, }, { name: "should fail - invalid recipient address", authority: poaKeeper.GetAuthority(), address: "invalidaddress", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), expectedErr: errors.New("decoding bech32 failed"), }, { name: "should fail - zero amount", authority: poaKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(0)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), expectedErr: types.ErrInvalidAmount, }, + { + name: "should fail - wrong denom", + authority: poaKeeper.GetAuthority(), + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("axrp", math.NewInt(100)), + expectedErr: types.ErrInvalidDenom, + }, { name: "should pass", authority: poaKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), }, } @@ -83,21 +90,28 @@ func TestKeeper_ExecuteMint(t *testing.T) { { name: "should fail - zero amount", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(0)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: types.ErrInvalidAmount, }, + { + name: "should fail - wrong denom", + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.NewCoin("axrp", math.NewInt(100)), + bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, + expectedError: types.ErrInvalidDenom, + }, { name: "should fail - invalid address", address: "invalidaddress", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: errors.New("decoding bech32 failed"), }, { name: "should fail - MintCoins returns error", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(errors.New("bank mint error")) }, @@ -106,7 +120,7 @@ func TestKeeper_ExecuteMint(t *testing.T) { { name: "should fail - SendCoinsFromModuleToAccount returns error", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(nil) bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("bank send error")) @@ -116,9 +130,9 @@ func TestKeeper_ExecuteMint(t *testing.T) { { name: "should pass", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", - amount: sdk.NewCoin("XRP", math.NewInt(100)), + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { - coins := sdk.NewCoins(sdk.NewCoin("XRP", math.NewInt(100))) + coins := sdk.NewCoins(sdk.NewCoin(testCBDCDenom, math.NewInt(100))) bankKeeper.EXPECT().MintCoins(ctx, types.ModuleName, coins).Return(nil) bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, types.ModuleName, gomock.Any(), coins).Return(nil) }, diff --git a/x/poa/types/errors.go b/x/poa/types/errors.go index 738c2aaa..4ab15ef9 100644 --- a/x/poa/types/errors.go +++ b/x/poa/types/errors.go @@ -16,4 +16,5 @@ var ( ErrAddressIsNotAValidator = sdkerrors.Register(ModuleName, 6, "address is not a validator") ErrMaxValidatorsReached = sdkerrors.Register(ModuleName, 7, "maximum number of validators reached") ErrInvalidAmount = sdkerrors.Register(ModuleName, 8, "amount must be positive") + ErrInvalidDenom = sdkerrors.Register(ModuleName, 9, "amount denom must match the configured CBDC denom") ) diff --git a/x/poa/types/tx.pb.go b/x/poa/types/tx.pb.go index 1ef73165..949c5a7f 100644 --- a/x/poa/types/tx.pb.go +++ b/x/poa/types/tx.pb.go @@ -8,6 +8,7 @@ import ( fmt "fmt" _ "github.com/cosmos/cosmos-proto" types1 "github.com/cosmos/cosmos-sdk/codec/types" + types2 "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" types "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -230,55 +231,255 @@ func (m *MsgRemoveValidatorResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgRemoveValidatorResponse proto.InternalMessageInfo +// MsgMint defines a message to mint tokens and send them to an address +type MsgMint struct { + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Amount types2.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` +} + +func (m *MsgMint) Reset() { *m = MsgMint{} } +func (m *MsgMint) String() string { return proto.CompactTextString(m) } +func (*MsgMint) ProtoMessage() {} +func (*MsgMint) Descriptor() ([]byte, []int) { + return fileDescriptor_8ac16a0aed23c2e2, []int{4} +} +func (m *MsgMint) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMint.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgMint) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMint.Merge(m, src) +} +func (m *MsgMint) XXX_Size() int { + return m.Size() +} +func (m *MsgMint) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMint.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMint proto.InternalMessageInfo + +func (m *MsgMint) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgMint) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgMint) GetAmount() types2.Coin { + if m != nil { + return m.Amount + } + return types2.Coin{} +} + +// MsgMintResponse defines the response for minting tokens +type MsgMintResponse struct { +} + +func (m *MsgMintResponse) Reset() { *m = MsgMintResponse{} } +func (m *MsgMintResponse) String() string { return proto.CompactTextString(m) } +func (*MsgMintResponse) ProtoMessage() {} +func (*MsgMintResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_8ac16a0aed23c2e2, []int{5} +} +func (m *MsgMintResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMintResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMintResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgMintResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMintResponse.Merge(m, src) +} +func (m *MsgMintResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgMintResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMintResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMintResponse proto.InternalMessageInfo + +// MsgBurn defines a message to burn tokens from an address +type MsgBurn struct { + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Amount types2.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` +} + +func (m *MsgBurn) Reset() { *m = MsgBurn{} } +func (m *MsgBurn) String() string { return proto.CompactTextString(m) } +func (*MsgBurn) ProtoMessage() {} +func (*MsgBurn) Descriptor() ([]byte, []int) { + return fileDescriptor_8ac16a0aed23c2e2, []int{6} +} +func (m *MsgBurn) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgBurn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgBurn.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgBurn) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBurn.Merge(m, src) +} +func (m *MsgBurn) XXX_Size() int { + return m.Size() +} +func (m *MsgBurn) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBurn.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgBurn proto.InternalMessageInfo + +func (m *MsgBurn) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgBurn) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgBurn) GetAmount() types2.Coin { + if m != nil { + return m.Amount + } + return types2.Coin{} +} + +// MsgBurnResponse defines the response for burning tokens +type MsgBurnResponse struct { +} + +func (m *MsgBurnResponse) Reset() { *m = MsgBurnResponse{} } +func (m *MsgBurnResponse) String() string { return proto.CompactTextString(m) } +func (*MsgBurnResponse) ProtoMessage() {} +func (*MsgBurnResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_8ac16a0aed23c2e2, []int{7} +} +func (m *MsgBurnResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgBurnResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgBurnResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgBurnResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBurnResponse.Merge(m, src) +} +func (m *MsgBurnResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgBurnResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBurnResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgBurnResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgAddValidator)(nil), "poa.MsgAddValidator") proto.RegisterType((*MsgAddValidatorResponse)(nil), "poa.MsgAddValidatorResponse") proto.RegisterType((*MsgRemoveValidator)(nil), "poa.MsgRemoveValidator") proto.RegisterType((*MsgRemoveValidatorResponse)(nil), "poa.MsgRemoveValidatorResponse") + proto.RegisterType((*MsgMint)(nil), "poa.MsgMint") + proto.RegisterType((*MsgMintResponse)(nil), "poa.MsgMintResponse") + proto.RegisterType((*MsgBurn)(nil), "poa.MsgBurn") + proto.RegisterType((*MsgBurnResponse)(nil), "poa.MsgBurnResponse") } func init() { proto.RegisterFile("poa/tx.proto", fileDescriptor_8ac16a0aed23c2e2) } var fileDescriptor_8ac16a0aed23c2e2 = []byte{ - // 593 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xbc, 0x54, 0xb1, 0x6f, 0xd3, 0x4e, - 0x14, 0x8e, 0xdb, 0xfe, 0x5a, 0xe5, 0x1a, 0xfd, 0x4a, 0xac, 0x48, 0x71, 0xac, 0xe0, 0x56, 0x81, - 0xa1, 0x44, 0xaa, 0xad, 0x14, 0x89, 0x81, 0x2d, 0x2e, 0x30, 0x50, 0x45, 0xaa, 0x8c, 0xc4, 0xc0, - 0x52, 0x9d, 0xed, 0xc3, 0xb5, 0x5a, 0xdf, 0xb3, 0x7c, 0xe7, 0xa8, 0xde, 0x10, 0x7f, 0x01, 0xff, - 0x03, 0x0b, 0x63, 0x07, 0x76, 0xd6, 0x8a, 0xa9, 0x62, 0x62, 0x42, 0x28, 0x19, 0xfa, 0x17, 0xb0, - 0x23, 0xdb, 0x77, 0x4e, 0x9a, 0x90, 0x09, 0x89, 0x25, 0xc9, 0xe7, 0xef, 0xbd, 0xcf, 0xdf, 0xfb, - 0xee, 0x5d, 0x50, 0x23, 0x06, 0x6c, 0xf1, 0x4b, 0x33, 0x4e, 0x80, 0x83, 0xba, 0x1e, 0x03, 0xd6, - 0x5b, 0x01, 0x04, 0x50, 0x60, 0x2b, 0xff, 0x55, 0x52, 0x7a, 0xc7, 0x03, 0x16, 0x01, 0x3b, 0x2d, - 0x89, 0x12, 0x08, 0xaa, 0x5d, 0x22, 0x2b, 0x62, 0x81, 0x35, 0x1e, 0xe4, 0x5f, 0x82, 0x78, 0x28, - 0x08, 0xc6, 0xf1, 0x79, 0x48, 0x73, 0xd2, 0x25, 0x1c, 0x0f, 0x24, 0x96, 0xca, 0x01, 0x40, 0x70, - 0x41, 0xac, 0x02, 0xb9, 0xe9, 0x5b, 0x0b, 0xd3, 0x4c, 0x50, 0x4d, 0x1c, 0x85, 0x14, 0xac, 0xe2, - 0x53, 0x3c, 0x32, 0x84, 0xa6, 0x8b, 0x19, 0xa9, 0x04, 0x3d, 0x08, 0x69, 0xc9, 0xf7, 0xbe, 0xac, - 0xa1, 0x9d, 0x11, 0x0b, 0x86, 0xbe, 0xff, 0x1a, 0x5f, 0x84, 0x3e, 0xe6, 0x90, 0xa8, 0x4f, 0x50, - 0x1d, 0xa7, 0xfc, 0x0c, 0x92, 0x90, 0x67, 0x9a, 0xb2, 0xa7, 0xec, 0xd7, 0x6d, 0xed, 0xdb, 0xe7, - 0x83, 0x96, 0x98, 0x62, 0xe8, 0xfb, 0x09, 0x61, 0xec, 0x15, 0x4f, 0x42, 0x1a, 0x38, 0xb3, 0x52, - 0xf5, 0x25, 0x6a, 0x8e, 0xa5, 0xc8, 0x29, 0x2e, 0xab, 0xb4, 0xb5, 0xa2, 0xff, 0xfe, 0xaa, 0xfe, - 0x4f, 0xb7, 0x57, 0xfd, 0x9a, 0x73, 0xaf, 0xea, 0x13, 0xa4, 0x7a, 0x82, 0xb6, 0x7d, 0xc2, 0xbc, - 0x24, 0x8c, 0x79, 0x08, 0x54, 0x5b, 0xdf, 0x53, 0xf6, 0xb7, 0x0f, 0x1f, 0x98, 0x42, 0x42, 0x26, - 0x22, 0x06, 0x32, 0x9f, 0xcd, 0x4a, 0xed, 0xfa, 0xf5, 0x8f, 0xdd, 0x5a, 0x2e, 0xab, 0x38, 0xf3, - 0x12, 0xea, 0x0b, 0xb4, 0x19, 0xa7, 0xee, 0x39, 0xc9, 0xb4, 0x8d, 0x42, 0xac, 0x65, 0x96, 0x41, - 0x9a, 0x32, 0x48, 0x73, 0x48, 0x33, 0x5b, 0xfb, 0x3a, 0x33, 0xea, 0x25, 0x59, 0xcc, 0xc1, 0x3c, - 0x49, 0xdd, 0x63, 0x92, 0x39, 0xa2, 0xfb, 0xe9, 0xff, 0xef, 0x6f, 0xaf, 0xfa, 0xb3, 0xa9, 0x7b, - 0x1d, 0xd4, 0x5e, 0x08, 0xd0, 0x21, 0x2c, 0x06, 0xca, 0x48, 0xef, 0xa3, 0x82, 0xd4, 0x11, 0x0b, - 0x1c, 0x12, 0xc1, 0x98, 0xfc, 0x7d, 0xbe, 0xcf, 0x57, 0xe7, 0xbb, 0xba, 0x7f, 0x29, 0xda, 0xa5, - 0x01, 0xba, 0x48, 0x5f, 0x36, 0x59, 0xcd, 0xc0, 0xd1, 0xd6, 0x88, 0x05, 0xa3, 0x90, 0x72, 0xb5, - 0xbb, 0xe4, 0x7b, 0xde, 0x9d, 0x86, 0xb6, 0xee, 0x78, 0x72, 0x24, 0x54, 0x07, 0x68, 0x13, 0x47, - 0x90, 0x52, 0x2e, 0x8e, 0xb1, 0x23, 0x8f, 0x31, 0x5f, 0xca, 0xea, 0x0c, 0x8f, 0x20, 0xa4, 0x8e, - 0x28, 0xec, 0x35, 0x8b, 0xad, 0xcc, 0xdf, 0xba, 0x60, 0xc4, 0x4e, 0x13, 0xfa, 0xef, 0x8d, 0xe4, - 0x6f, 0x95, 0x46, 0x0e, 0x7f, 0x29, 0x68, 0x7d, 0xc4, 0x02, 0xd5, 0x46, 0x8d, 0x3b, 0xd7, 0xa6, - 0x65, 0xc6, 0x80, 0xcd, 0x85, 0x5d, 0xd0, 0xbb, 0x7f, 0x7a, 0x2a, 0xb5, 0xd4, 0x63, 0xb4, 0xb3, - 0xb8, 0x1d, 0x6d, 0xd9, 0xb0, 0x40, 0xe8, 0xbb, 0x2b, 0x88, 0x4a, 0xac, 0x8f, 0x36, 0x8a, 0x73, - 0x6a, 0xc8, 0xc2, 0x1c, 0xe9, 0xad, 0x79, 0x34, 0x5f, 0x5b, 0x44, 0x59, 0xd5, 0xe6, 0x68, 0x56, - 0x3b, 0x3f, 0xb0, 0xfe, 0xdf, 0xbb, 0xfc, 0x36, 0xd9, 0x47, 0x6f, 0x1e, 0x05, 0x21, 0x3f, 0x4b, - 0x5d, 0xd3, 0x83, 0xc8, 0x8a, 0x09, 0x49, 0x58, 0xc6, 0xb8, 0xe5, 0xb9, 0xbe, 0x77, 0x40, 0xc1, - 0x27, 0xd6, 0xa5, 0x55, 0xfc, 0x3b, 0x66, 0x31, 0x61, 0xd7, 0x13, 0x43, 0xb9, 0x99, 0x18, 0xca, - 0xcf, 0x89, 0xa1, 0x7c, 0x98, 0x1a, 0xb5, 0x9b, 0xa9, 0x51, 0xfb, 0x3e, 0x35, 0x6a, 0xee, 0x66, - 0x71, 0xdb, 0x1e, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x92, 0x1c, 0xb0, 0xb2, 0x49, 0x05, 0x00, - 0x00, + // 595 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0x31, 0x6f, 0xd3, 0x40, + 0x14, 0x8e, 0x9b, 0x92, 0x2a, 0xd7, 0x88, 0x12, 0x2b, 0x52, 0x1c, 0xab, 0xb8, 0x55, 0x60, 0x28, + 0x91, 0x6a, 0xab, 0x41, 0x62, 0x40, 0x2c, 0x71, 0x81, 0x81, 0x2a, 0x52, 0x65, 0x24, 0x06, 0x96, + 0xea, 0x6c, 0x1f, 0xae, 0xd5, 0xfa, 0x9e, 0xe5, 0x3b, 0x47, 0xf5, 0x86, 0xf8, 0x05, 0xfc, 0x07, + 0x16, 0xc6, 0x0e, 0xec, 0x0c, 0x2c, 0x15, 0x53, 0xc5, 0xc4, 0x84, 0x50, 0x32, 0xf4, 0x17, 0xb0, + 0x23, 0xdb, 0x67, 0x27, 0x4d, 0x88, 0x84, 0x60, 0xea, 0x92, 0xe4, 0xf3, 0xf7, 0xbd, 0x97, 0xfb, + 0xbe, 0xf7, 0x7c, 0xa8, 0x11, 0x02, 0x36, 0xf8, 0x99, 0x1e, 0x46, 0xc0, 0x41, 0xae, 0x86, 0x80, + 0xd5, 0x96, 0x07, 0x1e, 0x64, 0xd8, 0x48, 0x7f, 0xe5, 0x94, 0xda, 0x71, 0x80, 0x05, 0xc0, 0x8e, + 0x72, 0x22, 0x07, 0x82, 0x6a, 0xe7, 0xc8, 0x08, 0x98, 0x67, 0x8c, 0xf6, 0xd2, 0x2f, 0x41, 0xdc, + 0x17, 0x04, 0xe3, 0xf8, 0xc4, 0xa7, 0x29, 0x69, 0x13, 0x8e, 0xf7, 0x0a, 0x2c, 0x54, 0x9a, 0x50, + 0xd9, 0x98, 0x91, 0x52, 0xe2, 0x80, 0x4f, 0x8b, 0x7f, 0xf6, 0x00, 0xbc, 0x53, 0x62, 0x64, 0xc8, + 0x8e, 0xdf, 0x18, 0x98, 0x26, 0x82, 0x6a, 0xe2, 0xc0, 0xa7, 0x60, 0x64, 0x9f, 0xf9, 0xa3, 0xee, + 0xe7, 0x15, 0xb4, 0x31, 0x64, 0xde, 0xc0, 0x75, 0x5f, 0xe1, 0x53, 0xdf, 0xc5, 0x1c, 0x22, 0xf9, + 0x11, 0xaa, 0xe3, 0x98, 0x1f, 0x43, 0xe4, 0xf3, 0x44, 0x91, 0xb6, 0xa5, 0x9d, 0xba, 0xa9, 0x7c, + 0xfb, 0xb4, 0xdb, 0x12, 0x2e, 0x06, 0xae, 0x1b, 0x11, 0xc6, 0x5e, 0xf2, 0xc8, 0xa7, 0x9e, 0x35, + 0x95, 0xca, 0x2f, 0x50, 0x73, 0x54, 0x34, 0x39, 0xc2, 0xb9, 0x4a, 0x59, 0xc9, 0xea, 0xef, 0x2e, + 0xab, 0xff, 0x78, 0x75, 0xde, 0xab, 0x58, 0x77, 0xca, 0x3a, 0x41, 0xca, 0x87, 0x68, 0xdd, 0x25, + 0xcc, 0x89, 0xfc, 0x90, 0xfb, 0x40, 0x95, 0xea, 0xb6, 0xb4, 0xb3, 0xde, 0xbf, 0xa7, 0x8b, 0x16, + 0x45, 0x22, 0xc2, 0xbe, 0xfe, 0x74, 0x2a, 0x35, 0xeb, 0x17, 0x3f, 0xb6, 0x2a, 0x69, 0x5b, 0xc9, + 0x9a, 0x6d, 0x21, 0x3f, 0x47, 0xb5, 0x30, 0xb6, 0x4f, 0x48, 0xa2, 0xac, 0x66, 0xcd, 0x5a, 0x7a, + 0x1e, 0x94, 0x5e, 0x04, 0xa5, 0x0f, 0x68, 0x62, 0x2a, 0x5f, 0xa7, 0x07, 0x75, 0xa2, 0x24, 0xe4, + 0xa0, 0x1f, 0xc6, 0xf6, 0x01, 0x49, 0x2c, 0x51, 0xfd, 0xf8, 0xf6, 0xbb, 0xab, 0xf3, 0xde, 0xd4, + 0x75, 0xb7, 0x83, 0xda, 0x73, 0x01, 0x5a, 0x84, 0x85, 0x40, 0x19, 0xe9, 0x7e, 0x90, 0x90, 0x3c, + 0x64, 0x9e, 0x45, 0x02, 0x18, 0x91, 0xff, 0xcf, 0xf7, 0xd9, 0xf2, 0x7c, 0x97, 0xd7, 0x2f, 0x44, + 0xbb, 0x60, 0x60, 0x13, 0xa9, 0x8b, 0x87, 0x2c, 0x3d, 0x7c, 0x91, 0xd0, 0xda, 0x90, 0x79, 0x43, + 0x9f, 0xf2, 0x7f, 0x3e, 0x78, 0x1f, 0xad, 0xfd, 0xed, 0x71, 0x0b, 0xa1, 0xfc, 0x04, 0xd5, 0x70, + 0x00, 0x31, 0xe5, 0x62, 0xf6, 0x9d, 0x62, 0xf6, 0xe9, 0xde, 0x97, 0x83, 0xdf, 0x07, 0xff, 0xda, + 0xc4, 0x45, 0xcd, 0x82, 0xc7, 0x66, 0xb6, 0xe5, 0xa9, 0x89, 0x79, 0x63, 0x66, 0x1c, 0xd1, 0x1b, + 0x6f, 0x2c, 0x35, 0x51, 0x18, 0xeb, 0xff, 0x92, 0x50, 0x75, 0xc8, 0x3c, 0xd9, 0x44, 0x8d, 0x6b, + 0xaf, 0x75, 0x4b, 0x0f, 0x01, 0xeb, 0x73, 0xbb, 0xaa, 0x6e, 0xfe, 0xe9, 0x69, 0xd1, 0x4b, 0x3e, + 0x40, 0x1b, 0xf3, 0xdb, 0xdb, 0x2e, 0x0a, 0xe6, 0x08, 0x75, 0x6b, 0x09, 0x51, 0x36, 0xeb, 0xa1, + 0xd5, 0x6c, 0x8d, 0x1a, 0x85, 0x30, 0x45, 0x6a, 0x6b, 0x16, 0xcd, 0x6a, 0xb3, 0xc9, 0x94, 0xda, + 0x14, 0x4d, 0xb5, 0xb3, 0x86, 0xd5, 0x5b, 0x6f, 0xd3, 0x88, 0xcc, 0xfd, 0x8b, 0xb1, 0x26, 0x5d, + 0x8e, 0x35, 0xe9, 0xe7, 0x58, 0x93, 0xde, 0x4f, 0xb4, 0xca, 0xe5, 0x44, 0xab, 0x7c, 0x9f, 0x68, + 0x95, 0xd7, 0x0f, 0x3c, 0x9f, 0x1f, 0xc7, 0xb6, 0xee, 0x40, 0x60, 0x84, 0x84, 0x44, 0x2c, 0x61, + 0xdc, 0x70, 0x6c, 0xd7, 0xd9, 0xa5, 0xe0, 0x12, 0xe3, 0xcc, 0xc8, 0x6e, 0xf5, 0x24, 0x24, 0xcc, + 0xae, 0x65, 0xb7, 0xc1, 0xc3, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x32, 0x36, 0x18, 0xa5, 0xe9, + 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -619,6 +820,146 @@ func (m *MsgRemoveValidatorResponse) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } +func (m *MsgMint) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMint) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMint) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgMintResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMintResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMintResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgBurn) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgBurn) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBurn) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgBurnResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgBurnResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBurnResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -688,17 +1029,73 @@ func (m *MsgRemoveValidatorResponse) Size() (n int) { return n } -func sovTx(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozTx(x uint64) (n int) { - return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +func (m *MsgMint) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + return n } -func (m *MsgAddValidator) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx + +func (m *MsgMintResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgBurn) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgBurnResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgAddValidator) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { @@ -1091,6 +1488,400 @@ func (m *MsgRemoveValidatorResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgMint) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMint: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMint: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMintResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMintResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgBurn) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgBurn: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBurn: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgBurnResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgBurnResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBurnResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/poa/types/tx_burn.go b/x/poa/types/tx_burn.go deleted file mode 100644 index 165c9a7e..00000000 --- a/x/poa/types/tx_burn.go +++ /dev/null @@ -1,364 +0,0 @@ -// Manually implemented proto-compatible types for MsgBurn. -// These follow the same encoding conventions as the protoc-gen-gogo output in tx.pb.go. -// Run `make proto-gen` after updating proto/poa/tx.proto to regenerate instead. -package types - -import ( - "fmt" - "io" - - sdk "github.com/cosmos/cosmos-sdk/types" - proto "github.com/cosmos/gogoproto/proto" -) - -// MsgBurn defines a message to burn tokens from an address. -type MsgBurn struct { - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` - Amount sdk.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` -} - -func (m *MsgBurn) Reset() { *m = MsgBurn{} } -func (m *MsgBurn) String() string { return proto.CompactTextString(m) } -func (*MsgBurn) ProtoMessage() {} - -func (m *MsgBurn) GetAuthority() string { - if m != nil { - return m.Authority - } - return "" -} - -func (m *MsgBurn) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *MsgBurn) GetAmount() sdk.Coin { - if m != nil { - return m.Amount - } - return sdk.Coin{} -} - -// MsgBurnResponse defines the response for burning tokens. -type MsgBurnResponse struct{} - -func (m *MsgBurnResponse) Reset() { *m = MsgBurnResponse{} } -func (m *MsgBurnResponse) String() string { return proto.CompactTextString(m) } -func (*MsgBurnResponse) ProtoMessage() {} - -func init() { - proto.RegisterType((*MsgBurn)(nil), "poa.MsgBurn") - proto.RegisterType((*MsgBurnResponse)(nil), "poa.MsgBurnResponse") -} - -// --------------------------------------------------------------------------- -// Marshal / MarshalTo / MarshalToSizedBuffer -// --------------------------------------------------------------------------- - -func (m *MsgBurn) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgBurn) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgBurn) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - // field 3: amount (sdk.Coin, always written – non-nullable) - { - size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - // field 2: address - if len(m.Address) > 0 { - i -= len(m.Address) - copy(dAtA[i:], m.Address) - i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) - i-- - dAtA[i] = 0x12 - } - // field 1: authority - if len(m.Authority) > 0 { - i -= len(m.Authority) - copy(dAtA[i:], m.Authority) - i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgBurnResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgBurnResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgBurnResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -// --------------------------------------------------------------------------- -// Size -// --------------------------------------------------------------------------- - -func (m *MsgBurn) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Authority) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Address) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Amount.Size() - n += 1 + l + sovTx(uint64(l)) - return n -} - -func (m *MsgBurnResponse) Size() (n int) { - if m == nil { - return 0 - } - return n -} - -// --------------------------------------------------------------------------- -// Unmarshal -// --------------------------------------------------------------------------- - -func (m *MsgBurn) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgBurn: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgBurn: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: // Authority - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Authority = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: // Address - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Address = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: // Amount - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} - -func (m *MsgBurnResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgBurnResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgBurnResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} diff --git a/x/poa/types/tx_mint.go b/x/poa/types/tx_mint.go deleted file mode 100644 index 58485c25..00000000 --- a/x/poa/types/tx_mint.go +++ /dev/null @@ -1,364 +0,0 @@ -// Manually implemented proto-compatible types for MsgMint. -// These follow the same encoding conventions as the protoc-gen-gogo output in tx.pb.go. -// Run `make proto-gen` after updating proto/poa/tx.proto to regenerate instead. -package types - -import ( - "fmt" - "io" - - sdk "github.com/cosmos/cosmos-sdk/types" - proto "github.com/cosmos/gogoproto/proto" -) - -// MsgMint defines a message to mint tokens and send them to an address. -type MsgMint struct { - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` - Amount sdk.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` -} - -func (m *MsgMint) Reset() { *m = MsgMint{} } -func (m *MsgMint) String() string { return proto.CompactTextString(m) } -func (*MsgMint) ProtoMessage() {} - -func (m *MsgMint) GetAuthority() string { - if m != nil { - return m.Authority - } - return "" -} - -func (m *MsgMint) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *MsgMint) GetAmount() sdk.Coin { - if m != nil { - return m.Amount - } - return sdk.Coin{} -} - -// MsgMintResponse defines the response for minting tokens. -type MsgMintResponse struct{} - -func (m *MsgMintResponse) Reset() { *m = MsgMintResponse{} } -func (m *MsgMintResponse) String() string { return proto.CompactTextString(m) } -func (*MsgMintResponse) ProtoMessage() {} - -func init() { - proto.RegisterType((*MsgMint)(nil), "poa.MsgMint") - proto.RegisterType((*MsgMintResponse)(nil), "poa.MsgMintResponse") -} - -// --------------------------------------------------------------------------- -// Marshal / MarshalTo / MarshalToSizedBuffer -// --------------------------------------------------------------------------- - -func (m *MsgMint) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgMint) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgMint) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - // field 3: amount (sdk.Coin, always written – non-nullable) - { - size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - // field 2: address - if len(m.Address) > 0 { - i -= len(m.Address) - copy(dAtA[i:], m.Address) - i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) - i-- - dAtA[i] = 0x12 - } - // field 1: authority - if len(m.Authority) > 0 { - i -= len(m.Authority) - copy(dAtA[i:], m.Authority) - i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgMintResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgMintResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgMintResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -// --------------------------------------------------------------------------- -// Size -// --------------------------------------------------------------------------- - -func (m *MsgMint) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Authority) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Address) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Amount.Size() - n += 1 + l + sovTx(uint64(l)) - return n -} - -func (m *MsgMintResponse) Size() (n int) { - if m == nil { - return 0 - } - return n -} - -// --------------------------------------------------------------------------- -// Unmarshal -// --------------------------------------------------------------------------- - -func (m *MsgMint) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgMint: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgMint: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: // Authority - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Authority = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: // Address - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Address = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: // Amount - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} - -func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgMintResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgMintResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} From c9f63179f6c10f9ef1d5787b90e9b95dc63ba081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Thu, 30 Apr 2026 15:09:38 +0200 Subject: [PATCH 03/17] fix(poa): change address declaration --- x/poa/keeper/keeper.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/poa/keeper/keeper.go b/x/poa/keeper/keeper.go index b97f9a70..e662d726 100644 --- a/x/poa/keeper/keeper.go +++ b/x/poa/keeper/keeper.go @@ -237,7 +237,7 @@ func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) er ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeMint, - sdk.NewAttribute(types.AttributeAddress, address), + sdk.NewAttribute(types.AttributeAddress, toAddr.String()), sdk.NewAttribute(types.AttributeAmount, amount.String()), ), ) @@ -269,7 +269,7 @@ func (k Keeper) ExecuteBurn(ctx sdk.Context, address string, amount sdk.Coin) er ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeBurn, - sdk.NewAttribute(types.AttributeAddress, address), + sdk.NewAttribute(types.AttributeAddress, fromAddr.String()), sdk.NewAttribute(types.AttributeAmount, amount.String()), ), ) From 14c3b7c16544d01f8fb75649231a4f5cf6672427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Tue, 5 May 2026 10:19:40 +0200 Subject: [PATCH 04/17] feat: ensure gas price is 0 --- local-node.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/local-node.sh b/local-node.sh index e9888d6d..fc34d0f3 100755 --- a/local-node.sh +++ b/local-node.sh @@ -47,6 +47,7 @@ jq '.app_state["staking"]["params"]["bond_denom"]="apoa"' "$GENESIS" >"$TMP_GENE jq '.app_state["staking"]["params"]["unbonding_time"]="60s"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state["feemarket"]["params"]["base_fee"]="'${BASEFEE}'"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state["feemarket"]["params"]["no_base_fee"]=true' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" +jq '.app_state["feemarket"]["params"]["min_gas_price"]="0.000000000000000000"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state.bank.denom_metadata=[{"description":"XRP is the gas token","denom_units":[{"denom":"axrp"},{"denom":"xrp","exponent":18}],"base":"axrp","display":"xrp","name":"XRP","symbol":"XRP"}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" @@ -63,7 +64,7 @@ bin/cbdcd --home "$HOMEDIR" genesis add-genesis-account "$(bin/cbdcd --home "$HO bin/cbdcd --home "$HOMEDIR" genesis add-genesis-account "ethm1zrxl239wa6ad5xge3gs68rt98227xgnjq0xyw2" 1000000000000000000000000000axrp --keyring-backend "$KEYRING" -bin/cbdcd --home "$HOMEDIR" genesis gentx alice 1000000apoa --gas-prices ${BASEFEE}axrp --keyring-backend "$KEYRING" --chain-id "$CHAINID" +bin/cbdcd --home "$HOMEDIR" genesis gentx alice 1000000apoa --fees ${BASEFEE}axrp --gas 1000000 --keyring-backend "$KEYRING" --chain-id "$CHAINID" bin/cbdcd --home "$HOMEDIR" genesis collect-gentxs From 5e777f00ee22f51a3a4a3e3b06ace45bacbcddb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Wed, 6 May 2026 08:54:43 +0200 Subject: [PATCH 05/17] fix: extract mint and burn into separate package --- app/app.go | 17 +- proto/cbdc/genesis.proto | 10 + proto/cbdc/params.proto | 7 + proto/cbdc/query.proto | 25 + proto/cbdc/tx.proto | 44 + proto/poa/tx.proto | 29 - scripts/mockgen.sh | 3 +- x/cbdc/keeper/common_test.go | 91 ++ x/cbdc/keeper/genesis.go | 19 + x/cbdc/keeper/keeper.go | 132 ++ x/cbdc/keeper/msg_server.go | 17 + x/{poa => cbdc}/keeper/msg_server_burn.go | 2 +- .../keeper/msg_server_burn_test.go | 18 +- x/{poa => cbdc}/keeper/msg_server_mint.go | 2 +- .../keeper/msg_server_mint_test.go | 18 +- x/cbdc/keeper/params.go | 16 + x/cbdc/keeper/query.go | 7 + x/cbdc/keeper/query_params.go | 19 + x/cbdc/module.go | 123 ++ x/cbdc/module_simulation.go | 42 + x/cbdc/testutil/expected_keepers_mock.go | 143 +++ x/cbdc/types/codec.go | 33 + x/cbdc/types/errors.go | 13 + x/cbdc/types/events.go | 8 + x/cbdc/types/expected_keepers.go | 21 + x/cbdc/types/genesis.go | 17 + x/cbdc/types/genesis.pb.go | 320 +++++ x/cbdc/types/keys.go | 19 + x/{poa => cbdc}/types/message_burn.go | 0 x/{poa => cbdc}/types/message_mint.go | 0 x/cbdc/types/params.go | 32 + x/cbdc/types/params.pb.go | 262 ++++ x/cbdc/types/query.pb.go | 534 ++++++++ x/cbdc/types/query.pb.gw.go | 153 +++ x/cbdc/types/tx.pb.go | 1078 ++++++++++++++++ x/poa/keeper/common_test.go | 2 - x/poa/keeper/keeper.go | 71 -- x/poa/types/codec.go | 8 - x/poa/types/errors.go | 2 - x/poa/types/events.go | 4 - x/poa/types/tx.pb.go | 1130 ++--------------- 41 files changed, 3351 insertions(+), 1140 deletions(-) create mode 100644 proto/cbdc/genesis.proto create mode 100644 proto/cbdc/params.proto create mode 100644 proto/cbdc/query.proto create mode 100644 proto/cbdc/tx.proto create mode 100644 x/cbdc/keeper/common_test.go create mode 100644 x/cbdc/keeper/genesis.go create mode 100644 x/cbdc/keeper/keeper.go create mode 100644 x/cbdc/keeper/msg_server.go rename x/{poa => cbdc}/keeper/msg_server_burn.go (92%) rename x/{poa => cbdc}/keeper/msg_server_burn_test.go (91%) rename x/{poa => cbdc}/keeper/msg_server_mint.go (92%) rename x/{poa => cbdc}/keeper/msg_server_mint_test.go (91%) create mode 100644 x/cbdc/keeper/params.go create mode 100644 x/cbdc/keeper/query.go create mode 100644 x/cbdc/keeper/query_params.go create mode 100644 x/cbdc/module.go create mode 100644 x/cbdc/module_simulation.go create mode 100644 x/cbdc/testutil/expected_keepers_mock.go create mode 100644 x/cbdc/types/codec.go create mode 100644 x/cbdc/types/errors.go create mode 100644 x/cbdc/types/events.go create mode 100644 x/cbdc/types/expected_keepers.go create mode 100644 x/cbdc/types/genesis.go create mode 100644 x/cbdc/types/genesis.pb.go create mode 100644 x/cbdc/types/keys.go rename x/{poa => cbdc}/types/message_burn.go (100%) rename x/{poa => cbdc}/types/message_mint.go (100%) create mode 100644 x/cbdc/types/params.go create mode 100644 x/cbdc/types/params.pb.go create mode 100644 x/cbdc/types/query.pb.go create mode 100644 x/cbdc/types/query.pb.gw.go create mode 100644 x/cbdc/types/tx.pb.go diff --git a/app/app.go b/app/app.go index abd2faef..8d7d99d8 100644 --- a/app/app.go +++ b/app/app.go @@ -127,6 +127,9 @@ import ( ibckeeper "github.com/cosmos/ibc-go/v10/modules/core/keeper" "github.com/peersyst/cbdc-node/docs" + "github.com/peersyst/cbdc-node/x/cbdc" + cbdckeeper "github.com/peersyst/cbdc-node/x/cbdc/keeper" + cbdctypes "github.com/peersyst/cbdc-node/x/cbdc/types" poakeeper "github.com/peersyst/cbdc-node/x/poa/keeper" poatypes "github.com/peersyst/cbdc-node/x/poa/types" @@ -172,6 +175,7 @@ var ( ratelimittypes.ModuleName: nil, feemarkettypes.ModuleName: nil, poatypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + cbdctypes.ModuleName: {authtypes.Minter, authtypes.Burner}, } ) @@ -247,7 +251,8 @@ type App struct { Erc20Keeper erc20keeper.Keeper // cbdc keepers - PoaKeeper poakeeper.Keeper + PoaKeeper poakeeper.Keeper + CbdcKeeper cbdckeeper.Keeper // mm is the module manager mm *module.Manager @@ -469,6 +474,13 @@ func New( app.BankKeeper, app.StakingKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + + app.CbdcKeeper = *cbdckeeper.NewKeeper( + appCodec, + app.GetSubspace(cbdctypes.ModuleName), + app.BankKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), BaseDenom, ) @@ -684,6 +696,7 @@ func New( // cbdc app modules poa.NewAppModule(appCodec, app.PoaKeeper, app.BankKeeper, app.StakingKeeper, app.AccountKeeper, app.interfaceRegistry), + cbdc.NewAppModule(appCodec, app.CbdcKeeper, app.BankKeeper, app.AccountKeeper, app.interfaceRegistry), ) // BasicModuleManager defines the module BasicManager which is in charge of setting up basic, @@ -737,6 +750,7 @@ func New( govtypes.ModuleName, stakingtypes.ModuleName, poatypes.ModuleName, + cbdctypes.ModuleName, evmtypes.ModuleName, feemarkettypes.ModuleName, erc20types.ModuleName, @@ -770,6 +784,7 @@ func New( // Evmos erc20types.ModuleName, poatypes.ModuleName, + cbdctypes.ModuleName, crisistypes.ModuleName, ratelimittypes.ModuleName, } diff --git a/proto/cbdc/genesis.proto b/proto/cbdc/genesis.proto new file mode 100644 index 00000000..73bf0155 --- /dev/null +++ b/proto/cbdc/genesis.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package cbdc; + +import "gogoproto/gogo.proto"; +import "cbdc/params.proto"; + +option go_package = "github.com/peersyst/cbdc-node/x/cbdc/types"; + +// GenesisState defines the cbdc module's genesis state. +message GenesisState { Params params = 1 [ (gogoproto.nullable) = false ]; } diff --git a/proto/cbdc/params.proto b/proto/cbdc/params.proto new file mode 100644 index 00000000..20a1eb91 --- /dev/null +++ b/proto/cbdc/params.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; +package cbdc; + +option go_package = "github.com/peersyst/cbdc-node/x/cbdc/types"; + +// Params defines the parameters for the module. +message Params {} diff --git a/proto/cbdc/query.proto b/proto/cbdc/query.proto new file mode 100644 index 00000000..2b3422b3 --- /dev/null +++ b/proto/cbdc/query.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +package cbdc; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "cbdc/params.proto"; + +option go_package = "github.com/peersyst/cbdc-node/x/cbdc/types"; + +// Query defines the gRPC querier service. +service Query { + // Parameters queries the parameters of the module. + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/cbdc/cbdc/params"; + } +} + +// QueryParamsRequest is request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is response type for the Query/Params RPC method. +message QueryParamsResponse { + // params holds all the parameters of this module. + Params params = 1 [ (gogoproto.nullable) = false ]; +} diff --git a/proto/cbdc/tx.proto b/proto/cbdc/tx.proto new file mode 100644 index 00000000..ce229263 --- /dev/null +++ b/proto/cbdc/tx.proto @@ -0,0 +1,44 @@ +syntax = "proto3"; +package cbdc; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/msg/v1/msg.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "amino/amino.proto"; + +option go_package = "github.com/peersyst/cbdc-node/x/cbdc/types"; + +// Msg defines the Msg service. +service Msg { + option (cosmos.msg.v1.service) = true; + + // Mints CBDC tokens and sends them to an address + rpc Mint(MsgMint) returns (MsgMintResponse); + // Burns CBDC tokens from an address + rpc Burn(MsgBurn) returns (MsgBurnResponse); +} + +// MsgMint defines a message to mint CBDC tokens and send them to an address +message MsgMint { + option (cosmos.msg.v1.signer) = "authority"; + + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + cosmos.base.v1beta1.Coin amount = 3 + [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; +} +// MsgMintResponse defines the response for minting CBDC tokens +message MsgMintResponse {} + +// MsgBurn defines a message to burn CBDC tokens from an address +message MsgBurn { + option (cosmos.msg.v1.signer) = "authority"; + + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + cosmos.base.v1beta1.Coin amount = 3 + [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; +} +// MsgBurnResponse defines the response for burning CBDC tokens +message MsgBurnResponse {} diff --git a/proto/poa/tx.proto b/proto/poa/tx.proto index 0c7c7e2c..8024f37d 100644 --- a/proto/poa/tx.proto +++ b/proto/poa/tx.proto @@ -5,7 +5,6 @@ import "gogoproto/gogo.proto"; import "cosmos_proto/cosmos.proto"; import "cosmos/msg/v1/msg.proto"; import "cosmos/staking/v1beta1/staking.proto"; -import "cosmos/base/v1beta1/coin.proto"; import "google/protobuf/any.proto"; import "amino/amino.proto"; @@ -19,10 +18,6 @@ service Msg { rpc AddValidator(MsgAddValidator) returns (MsgAddValidatorResponse); // Removes an existing validator from the authority rpc RemoveValidator(MsgRemoveValidator) returns (MsgRemoveValidatorResponse); - // Mints tokens and sends them to an address - rpc Mint(MsgMint) returns (MsgMintResponse); - // Burns tokens from an address - rpc Burn(MsgBurn) returns (MsgBurnResponse); } // MsgAddValidator defines a message for adding a new validator @@ -51,27 +46,3 @@ message MsgRemoveValidator { // MsgRemoveValidatorResponse defines the response for removing an existing // validator message MsgRemoveValidatorResponse {} - -// MsgMint defines a message to mint tokens and send them to an address -message MsgMint { - option (cosmos.msg.v1.signer) = "authority"; - - string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - cosmos.base.v1beta1.Coin amount = 3 - [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; -} -// MsgMintResponse defines the response for minting tokens -message MsgMintResponse {} - -// MsgBurn defines a message to burn tokens from an address -message MsgBurn { - option (cosmos.msg.v1.signer) = "authority"; - - string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - cosmos.base.v1beta1.Coin amount = 3 - [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; -} -// MsgBurnResponse defines the response for burning tokens -message MsgBurnResponse {} diff --git a/scripts/mockgen.sh b/scripts/mockgen.sh index 727dfb8b..c4021305 100755 --- a/scripts/mockgen.sh +++ b/scripts/mockgen.sh @@ -4,4 +4,5 @@ mockgen -source=x/poa/types/expected_keepers.go -package testutil -destination=x mockgen -source=x/poa/testutil/tx.go -package testutil -destination=x/poa/testutil/tx_mock.go mockgen -source=x/poa/testutil/keys.go -package testutil -destination=x/poa/testutil/keys_mock.go mockgen -source=x/poa/testutil/expected_msg_server.go -package testutil -destination=x/poa/testutil/expected_msg_server_mock.go -mockgen -source=x/poa/testutil/staking_hooks.go -package testutil -destination=x/poa/testutil/staking_hooks_mock.go \ No newline at end of file +mockgen -source=x/poa/testutil/staking_hooks.go -package testutil -destination=x/poa/testutil/staking_hooks_mock.go +mockgen -source=x/cbdc/types/expected_keepers.go -package testutil -destination=x/cbdc/testutil/expected_keepers_mock.go \ No newline at end of file diff --git a/x/cbdc/keeper/common_test.go b/x/cbdc/keeper/common_test.go new file mode 100644 index 00000000..707d02d5 --- /dev/null +++ b/x/cbdc/keeper/common_test.go @@ -0,0 +1,91 @@ +package keeper + +import ( + "testing" + "time" + + storetypes "cosmossdk.io/store/types" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/golang/mock/gomock" + "github.com/peersyst/cbdc-node/x/cbdc/testutil" + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +const ( + accountAddressPrefix = "ethm" + bip44CoinType = 60 + testCBDCDenom = "acbdc" +) + +func setupSdkConfig() { + accountPubKeyPrefix := accountAddressPrefix + "pub" + validatorAddressPrefix := accountAddressPrefix + "valoper" + validatorPubKeyPrefix := accountAddressPrefix + "valoperpub" + consNodeAddressPrefix := accountAddressPrefix + "valcons" + consNodePubKeyPrefix := accountAddressPrefix + "valconspub" + + config := sdk.GetConfig() + config.SetBech32PrefixForAccount(accountAddressPrefix, accountPubKeyPrefix) + config.SetBech32PrefixForValidator(validatorAddressPrefix, validatorPubKeyPrefix) + config.SetBech32PrefixForConsensusNode(consNodeAddressPrefix, consNodePubKeyPrefix) + config.SetCoinType(bip44CoinType) + config.SetPurpose(sdk.Purpose) +} + +func getBankKeeperMock(t *testing.T, ctx sdk.Context, setExpectations func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper)) *testutil.MockBankKeeper { + ctrl := gomock.NewController(t) + bankKeeper := testutil.NewMockBankKeeper(ctrl) + setExpectations(ctx, bankKeeper) + return bankKeeper +} + +func getCtxMock(t *testing.T, key *storetypes.KVStoreKey, tsKey *storetypes.TransientStoreKey) sdk.Context { + setupSdkConfig() + + testCtx := sdktestutil.DefaultContextWithDB(t, key, tsKey) + ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()}) + return ctx +} + +func getMockedCbdcKeeper(_ *testing.T, key *storetypes.KVStoreKey, tsKey *storetypes.TransientStoreKey, ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) *Keeper { + encCfg := moduletestutil.MakeTestEncodingConfig() + + types.RegisterInterfaces(encCfg.InterfaceRegistry) + + cbdcKeeper := NewKeeper( + encCfg.Codec, + paramtypes.NewSubspace(encCfg.Codec, encCfg.Amino, key, tsKey, "cbdc"), + bankKeeper, + "ethm1wunfhl05vc8r8xxnnp8gt62wa54r6y52pg03zq", + testCBDCDenom, + ) + cbdcKeeper.SetParams(ctx, types.DefaultParams()) + + return cbdcKeeper +} + +func setupCbdcKeeper(t *testing.T, setBankExpectations func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper)) (*Keeper, sdk.Context) { + key := storetypes.NewKVStoreKey(types.StoreKey) + tsKey := storetypes.NewTransientStoreKey("test") + + ctx := getCtxMock(t, key, tsKey) + bankKeeper := getBankKeeperMock(t, ctx, setBankExpectations) + + return getMockedCbdcKeeper(t, key, tsKey, ctx, bankKeeper), ctx +} + +func cbdcKeeperTestSetup(t *testing.T) (*Keeper, sdk.Context) { + bankExpectations := func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + } + + return setupCbdcKeeper(t, bankExpectations) +} diff --git a/x/cbdc/keeper/genesis.go b/x/cbdc/keeper/genesis.go new file mode 100644 index 00000000..3f8ffba4 --- /dev/null +++ b/x/cbdc/keeper/genesis.go @@ -0,0 +1,19 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +// InitGenesis initializes the module's state from a provided genesis state. +func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { + k.SetParams(ctx, genState.Params) +} + +// ExportGenesis returns the module's exported genesis +func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { + genesis := types.DefaultGenesis() + genesis.Params = k.GetParams(ctx) + + return genesis +} diff --git a/x/cbdc/keeper/keeper.go b/x/cbdc/keeper/keeper.go new file mode 100644 index 00000000..d5fd1b76 --- /dev/null +++ b/x/cbdc/keeper/keeper.go @@ -0,0 +1,132 @@ +package keeper + +import ( + "fmt" + + "cosmossdk.io/log" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +var _ types.QueryServer = Querier{} + +type Querier struct { + Keeper +} + +func NewQuerier(keeper Keeper) Querier { + return Querier{Keeper: keeper} +} + +type ( + Keeper struct { + cdc codec.Codec + paramstore paramtypes.Subspace + authority string // the address capable of executing a cbdc mint/burn. Usually the gov module account + bk types.BankKeeper + cbdcDenom string // the only denom that can be minted/burned via this module + } +) + +func NewKeeper( + cdc codec.Codec, + ps paramtypes.Subspace, + bk types.BankKeeper, + authority string, + cbdcDenom string, +) *Keeper { + if !ps.HasKeyTable() { + ps = ps.WithKeyTable(types.ParamKeyTable()) + } + + if _, err := sdk.AccAddressFromBech32(authority); err != nil { + panic(err) + } + + if err := sdk.ValidateDenom(cbdcDenom); err != nil { + panic(err) + } + + return &Keeper{ + cdc: cdc, + paramstore: ps, + authority: authority, + bk: bk, + cbdcDenom: cbdcDenom, + } +} + +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +func (k Keeper) GetAuthority() string { + return k.authority +} + +func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) error { + if amount.Denom != k.cbdcDenom { + return types.ErrInvalidDenom + } + if !amount.IsPositive() { + return types.ErrInvalidAmount + } + + toAddr, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + + coins := sdk.NewCoins(amount) + if err := k.bk.MintCoins(ctx, types.ModuleName, coins); err != nil { + return err + } + if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, toAddr, coins); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeMint, + sdk.NewAttribute(types.AttributeAddress, toAddr.String()), + sdk.NewAttribute(types.AttributeAmount, amount.String()), + ), + ) + + return nil +} + +func (k Keeper) ExecuteBurn(ctx sdk.Context, address string, amount sdk.Coin) error { + if amount.Denom != k.cbdcDenom { + return types.ErrInvalidDenom + } + if !amount.IsPositive() { + return types.ErrInvalidAmount + } + + fromAddr, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + + coins := sdk.NewCoins(amount) + if err := k.bk.SendCoinsFromAccountToModule(ctx, fromAddr, types.ModuleName, coins); err != nil { + return err + } + if err := k.bk.BurnCoins(ctx, types.ModuleName, coins); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeBurn, + sdk.NewAttribute(types.AttributeAddress, fromAddr.String()), + sdk.NewAttribute(types.AttributeAmount, amount.String()), + ), + ) + + return nil +} diff --git a/x/cbdc/keeper/msg_server.go b/x/cbdc/keeper/msg_server.go new file mode 100644 index 00000000..ff38f803 --- /dev/null +++ b/x/cbdc/keeper/msg_server.go @@ -0,0 +1,17 @@ +package keeper + +import ( + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +var _ types.MsgServer = msgServer{} diff --git a/x/poa/keeper/msg_server_burn.go b/x/cbdc/keeper/msg_server_burn.go similarity index 92% rename from x/poa/keeper/msg_server_burn.go rename to x/cbdc/keeper/msg_server_burn.go index e6187435..88031005 100644 --- a/x/poa/keeper/msg_server_burn.go +++ b/x/cbdc/keeper/msg_server_burn.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" gov "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/peersyst/cbdc-node/x/poa/types" + "github.com/peersyst/cbdc-node/x/cbdc/types" ) func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnResponse, error) { diff --git a/x/poa/keeper/msg_server_burn_test.go b/x/cbdc/keeper/msg_server_burn_test.go similarity index 91% rename from x/poa/keeper/msg_server_burn_test.go rename to x/cbdc/keeper/msg_server_burn_test.go index 60662956..9f16fd97 100644 --- a/x/poa/keeper/msg_server_burn_test.go +++ b/x/cbdc/keeper/msg_server_burn_test.go @@ -8,14 +8,14 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/golang/mock/gomock" - "github.com/peersyst/cbdc-node/x/poa/testutil" - "github.com/peersyst/cbdc-node/x/poa/types" + "github.com/peersyst/cbdc-node/x/cbdc/testutil" + "github.com/peersyst/cbdc-node/x/cbdc/types" "github.com/stretchr/testify/require" ) func TestMsgServer_Burn(t *testing.T) { //nolint:dupl - poaKeeper, ctx := poaKeeperTestSetup(t) - msgServer := NewMsgServerImpl(*poaKeeper) + cbdcKeeper, ctx := cbdcKeeperTestSetup(t) + msgServer := NewMsgServerImpl(*cbdcKeeper) tt := []struct { name string @@ -33,28 +33,28 @@ func TestMsgServer_Burn(t *testing.T) { //nolint:dupl }, { name: "should fail - invalid address", - authority: poaKeeper.GetAuthority(), + authority: cbdcKeeper.GetAuthority(), address: "invalidaddress", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), expectedErr: errors.New("decoding bech32 failed"), }, { name: "should fail - zero amount", - authority: poaKeeper.GetAuthority(), + authority: cbdcKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), expectedErr: types.ErrInvalidAmount, }, { name: "should fail - wrong denom", - authority: poaKeeper.GetAuthority(), + authority: cbdcKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin("axrp", math.NewInt(100)), expectedErr: types.ErrInvalidDenom, }, { name: "should pass", - authority: poaKeeper.GetAuthority(), + authority: cbdcKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), }, @@ -141,7 +141,7 @@ func TestKeeper_ExecuteBurn(t *testing.T) { for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - keeper, ctx := setupPoaKeeper(t, func(_ sdk.Context, _ *testutil.MockStakingKeeper) {}, tc.bankMocks) + keeper, ctx := setupCbdcKeeper(t, tc.bankMocks) err := keeper.ExecuteBurn(ctx, tc.address, tc.amount) if tc.expectedError != nil { diff --git a/x/poa/keeper/msg_server_mint.go b/x/cbdc/keeper/msg_server_mint.go similarity index 92% rename from x/poa/keeper/msg_server_mint.go rename to x/cbdc/keeper/msg_server_mint.go index f177480d..3ad31437 100644 --- a/x/poa/keeper/msg_server_mint.go +++ b/x/cbdc/keeper/msg_server_mint.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" gov "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/peersyst/cbdc-node/x/poa/types" + "github.com/peersyst/cbdc-node/x/cbdc/types" ) func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMintResponse, error) { diff --git a/x/poa/keeper/msg_server_mint_test.go b/x/cbdc/keeper/msg_server_mint_test.go similarity index 91% rename from x/poa/keeper/msg_server_mint_test.go rename to x/cbdc/keeper/msg_server_mint_test.go index 4cd29159..26053f39 100644 --- a/x/poa/keeper/msg_server_mint_test.go +++ b/x/cbdc/keeper/msg_server_mint_test.go @@ -8,14 +8,14 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/golang/mock/gomock" - "github.com/peersyst/cbdc-node/x/poa/testutil" - "github.com/peersyst/cbdc-node/x/poa/types" + "github.com/peersyst/cbdc-node/x/cbdc/testutil" + "github.com/peersyst/cbdc-node/x/cbdc/types" "github.com/stretchr/testify/require" ) func TestMsgServer_Mint(t *testing.T) { //nolint:dupl - poaKeeper, ctx := poaKeeperTestSetup(t) - msgServer := NewMsgServerImpl(*poaKeeper) + cbdcKeeper, ctx := cbdcKeeperTestSetup(t) + msgServer := NewMsgServerImpl(*cbdcKeeper) tt := []struct { name string @@ -33,28 +33,28 @@ func TestMsgServer_Mint(t *testing.T) { //nolint:dupl }, { name: "should fail - invalid recipient address", - authority: poaKeeper.GetAuthority(), + authority: cbdcKeeper.GetAuthority(), address: "invalidaddress", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), expectedErr: errors.New("decoding bech32 failed"), }, { name: "should fail - zero amount", - authority: poaKeeper.GetAuthority(), + authority: cbdcKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), expectedErr: types.ErrInvalidAmount, }, { name: "should fail - wrong denom", - authority: poaKeeper.GetAuthority(), + authority: cbdcKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin("axrp", math.NewInt(100)), expectedErr: types.ErrInvalidDenom, }, { name: "should pass", - authority: poaKeeper.GetAuthority(), + authority: cbdcKeeper.GetAuthority(), address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), }, @@ -141,7 +141,7 @@ func TestKeeper_ExecuteMint(t *testing.T) { for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - keeper, ctx := setupPoaKeeper(t, func(_ sdk.Context, _ *testutil.MockStakingKeeper) {}, tc.bankMocks) + keeper, ctx := setupCbdcKeeper(t, tc.bankMocks) err := keeper.ExecuteMint(ctx, tc.address, tc.amount) if tc.expectedError != nil { diff --git a/x/cbdc/keeper/params.go b/x/cbdc/keeper/params.go new file mode 100644 index 00000000..50227db6 --- /dev/null +++ b/x/cbdc/keeper/params.go @@ -0,0 +1,16 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +// GetParams get all parameters as types.Params +func (k Keeper) GetParams(_ sdk.Context) types.Params { + return types.NewParams() +} + +// SetParams set the params +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramstore.SetParamSet(ctx, ¶ms) +} diff --git a/x/cbdc/keeper/query.go b/x/cbdc/keeper/query.go new file mode 100644 index 00000000..97c94714 --- /dev/null +++ b/x/cbdc/keeper/query.go @@ -0,0 +1,7 @@ +package keeper + +import ( + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +var _ types.QueryServer = Keeper{} diff --git a/x/cbdc/keeper/query_params.go b/x/cbdc/keeper/query_params.go new file mode 100644 index 00000000..f36f5a2a --- /dev/null +++ b/x/cbdc/keeper/query_params.go @@ -0,0 +1,19 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/peersyst/cbdc-node/x/cbdc/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (k Keeper) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := sdk.UnwrapSDKContext(goCtx) + + return &types.QueryParamsResponse{Params: k.GetParams(ctx)}, nil +} diff --git a/x/cbdc/module.go b/x/cbdc/module.go new file mode 100644 index 00000000..68743e64 --- /dev/null +++ b/x/cbdc/module.go @@ -0,0 +1,123 @@ +package cbdc + +import ( + "context" + "encoding/json" + "fmt" + + "cosmossdk.io/core/appmodule" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/peersyst/cbdc-node/x/cbdc/keeper" + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +var ( + _ module.AppModuleBasic = (*AppModule)(nil) + _ module.AppModuleSimulation = (*AppModule)(nil) + _ module.HasGenesis = (*AppModule)(nil) + _ appmodule.AppModule = (*AppModule)(nil) +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +type AppModuleBasic struct { + cdc codec.BinaryCodec +} + +func NewAppModuleBasic(cdc codec.BinaryCodec) AppModuleBasic { + return AppModuleBasic{cdc: cdc} +} + +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterCodec(cdc) +} + +func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(reg) +} + +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + var genState types.GenesisState + if err := cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + return genState.Validate() +} + +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- + +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper + bk types.BankKeeper + ak types.AccountKeeper + registry cdctypes.InterfaceRegistry +} + +func NewAppModule( + cdc codec.Codec, + keeper keeper.Keeper, + bk types.BankKeeper, + ak types.AccountKeeper, + registry cdctypes.InterfaceRegistry, +) AppModule { + return AppModule{ + AppModuleBasic: NewAppModuleBasic(cdc), + keeper: keeper, + bk: bk, + ak: ak, + registry: registry, + } +} + +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) { + var genState types.GenesisState + cdc.MustUnmarshalJSON(gs, &genState) + + am.keeper.InitGenesis(ctx, genState) + + // To create module account + am.ak.GetModuleAccount(ctx, am.Name()) +} + +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + genState := am.keeper.ExportGenesis(ctx) + return cdc.MustMarshalJSON(genState) +} + +func (AppModule) ConsensusVersion() uint64 { return 1 } + +func (am AppModule) IsOnePerModuleType() {} + +func (am AppModule) IsAppModule() {} diff --git a/x/cbdc/module_simulation.go b/x/cbdc/module_simulation.go new file mode 100644 index 00000000..01c01902 --- /dev/null +++ b/x/cbdc/module_simulation.go @@ -0,0 +1,42 @@ +package cbdc + +import ( + "math/rand" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/peersyst/cbdc-node/testutil/sample" + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +// avoid unused import issue +var ( + _ = sample.AccAddress + _ = simulation.MsgEntryKind + _ = baseapp.Paramspace + _ = rand.Rand{} +) + +// GenerateGenesisState creates a randomized GenState of the module +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + cbdcGenesis := types.GenesisState{ + Params: types.DefaultParams(), + } + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&cbdcGenesis) +} + +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (am AppModule) ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg { + return []simtypes.WeightedProposalMsg{} +} + +// RegisterStoreDecoder registers a decoder +func (am AppModule) RegisterStoreDecoder(_ simtypes.StoreDecoderRegistry) {} + +// WeightedOperations returns the all the gov module operations with their respective weights. +func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { + return []simtypes.WeightedOperation{} +} diff --git a/x/cbdc/testutil/expected_keepers_mock.go b/x/cbdc/testutil/expected_keepers_mock.go new file mode 100644 index 00000000..7eb66082 --- /dev/null +++ b/x/cbdc/testutil/expected_keepers_mock.go @@ -0,0 +1,143 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: x/cbdc/types/expected_keepers.go + +// Package testutil is a generated GoMock package. +package testutil + +import ( + context "context" + reflect "reflect" + + types "github.com/cosmos/cosmos-sdk/types" + gomock "github.com/golang/mock/gomock" +) + +// MockAccountKeeper is a mock of AccountKeeper interface. +type MockAccountKeeper struct { + ctrl *gomock.Controller + recorder *MockAccountKeeperMockRecorder +} + +// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper. +type MockAccountKeeperMockRecorder struct { + mock *MockAccountKeeper +} + +// NewMockAccountKeeper creates a new mock instance. +func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper { + mock := &MockAccountKeeper{ctrl: ctrl} + mock.recorder = &MockAccountKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder { + return m.recorder +} + +// GetAccount mocks base method. +func (m *MockAccountKeeper) GetAccount(ctx context.Context, addr types.AccAddress) types.AccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAccount", ctx, addr) + ret0, _ := ret[0].(types.AccountI) + return ret0 +} + +// GetAccount indicates an expected call of GetAccount. +func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr) +} + +// GetModuleAccount mocks base method. +func (m *MockAccountKeeper) GetModuleAccount(ctx context.Context, moduleName string) types.ModuleAccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetModuleAccount", ctx, moduleName) + ret0, _ := ret[0].(types.ModuleAccountI) + return ret0 +} + +// GetModuleAccount indicates an expected call of GetModuleAccount. +func (mr *MockAccountKeeperMockRecorder) GetModuleAccount(ctx, moduleName interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAccount), ctx, moduleName) +} + +// MockBankKeeper is a mock of BankKeeper interface. +type MockBankKeeper struct { + ctrl *gomock.Controller + recorder *MockBankKeeperMockRecorder +} + +// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. +type MockBankKeeperMockRecorder struct { + mock *MockBankKeeper +} + +// NewMockBankKeeper creates a new mock instance. +func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper { + mock := &MockBankKeeper{ctrl: ctrl} + mock.recorder = &MockBankKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { + return m.recorder +} + +// BurnCoins mocks base method. +func (m *MockBankKeeper) BurnCoins(ctx context.Context, moduleName string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BurnCoins", ctx, moduleName, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// BurnCoins indicates an expected call of BurnCoins. +func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, moduleName, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*MockBankKeeper)(nil).BurnCoins), ctx, moduleName, amt) +} + +// MintCoins mocks base method. +func (m *MockBankKeeper) MintCoins(ctx context.Context, moduleName string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MintCoins", ctx, moduleName, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// MintCoins indicates an expected call of MintCoins. +func (mr *MockBankKeeperMockRecorder) MintCoins(ctx, moduleName, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MintCoins", reflect.TypeOf((*MockBankKeeper)(nil).MintCoins), ctx, moduleName, amt) +} + +// SendCoinsFromAccountToModule mocks base method. +func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) +} + +// SendCoinsFromModuleToAccount mocks base method. +func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromModuleToAccount indicates an expected call of SendCoinsFromModuleToAccount. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) +} diff --git a/x/cbdc/types/codec.go b/x/cbdc/types/codec.go new file mode 100644 index 00000000..f7506e6c --- /dev/null +++ b/x/cbdc/types/codec.go @@ -0,0 +1,33 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" +) + +func RegisterCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgMint{}, "cbdc/Mint", nil) + cdc.RegisterConcrete(&MsgBurn{}, "cbdc/Burn", nil) +} + +func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgMint{}, + ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgBurn{}, + ) + registry.RegisterImplementations( + (*govtypes.Content)(nil), + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + Amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) +) diff --git a/x/cbdc/types/errors.go b/x/cbdc/types/errors.go new file mode 100644 index 00000000..0c4b914f --- /dev/null +++ b/x/cbdc/types/errors.go @@ -0,0 +1,13 @@ +package types + +// DONTCOVER + +import ( + sdkerrors "cosmossdk.io/errors" +) + +// x/cbdc module sentinel errors +var ( + ErrInvalidAmount = sdkerrors.Register(ModuleName, 1, "amount must be positive") + ErrInvalidDenom = sdkerrors.Register(ModuleName, 2, "amount denom must match the configured CBDC denom") +) diff --git a/x/cbdc/types/events.go b/x/cbdc/types/events.go new file mode 100644 index 00000000..b96bfedc --- /dev/null +++ b/x/cbdc/types/events.go @@ -0,0 +1,8 @@ +package types + +const ( + EventTypeMint = "mint" + EventTypeBurn = "burn" + AttributeAddress = "address" + AttributeAmount = "amount" +) diff --git a/x/cbdc/types/expected_keepers.go b/x/cbdc/types/expected_keepers.go new file mode 100644 index 00000000..0eb4ba84 --- /dev/null +++ b/x/cbdc/types/expected_keepers.go @@ -0,0 +1,21 @@ +package types + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// AccountKeeper defines the expected account keeper used for simulations (noalias) +type AccountKeeper interface { + GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + GetModuleAccount(ctx context.Context, moduleName string) sdk.ModuleAccountI +} + +// BankKeeper defines the expected interface needed to mint/burn and move CBDC tokens. +type BankKeeper interface { + MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error + BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error +} diff --git a/x/cbdc/types/genesis.go b/x/cbdc/types/genesis.go new file mode 100644 index 00000000..bdb9f415 --- /dev/null +++ b/x/cbdc/types/genesis.go @@ -0,0 +1,17 @@ +package types + +// DefaultIndex is the default global index +const DefaultIndex uint64 = 1 + +// DefaultGenesis returns the default genesis state +func DefaultGenesis() *GenesisState { + return &GenesisState{ + Params: DefaultParams(), + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + return gs.Params.Validate() +} diff --git a/x/cbdc/types/genesis.pb.go b/x/cbdc/types/genesis.pb.go new file mode 100644 index 00000000..c602a64e --- /dev/null +++ b/x/cbdc/types/genesis.pb.go @@ -0,0 +1,320 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cbdc/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the cbdc module's genesis state. +type GenesisState struct { + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_0d964c5314bda519, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "cbdc.GenesisState") +} + +func init() { proto.RegisterFile("cbdc/genesis.proto", fileDescriptor_0d964c5314bda519) } + +var fileDescriptor_0d964c5314bda519 = []byte{ + // 185 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4a, 0x4e, 0x4a, 0x49, + 0xd6, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, + 0x01, 0x89, 0x49, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x05, 0xf4, 0x41, 0x2c, 0x88, 0x9c, 0x94, + 0x20, 0x58, 0x7d, 0x41, 0x62, 0x51, 0x62, 0x2e, 0x54, 0xb9, 0x92, 0x15, 0x17, 0x8f, 0x3b, 0x44, + 0x7f, 0x70, 0x49, 0x62, 0x49, 0xaa, 0x90, 0x16, 0x17, 0x1b, 0x44, 0x5e, 0x82, 0x51, 0x81, 0x51, + 0x83, 0xdb, 0x88, 0x47, 0x0f, 0xa4, 0x47, 0x2f, 0x00, 0x2c, 0xe6, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, + 0x43, 0x10, 0x54, 0x85, 0x93, 0xcb, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, + 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, + 0x69, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x17, 0xa4, 0xa6, 0x16, + 0x15, 0x57, 0x16, 0x97, 0xe8, 0x83, 0x0c, 0xd2, 0xcd, 0xcb, 0x4f, 0x49, 0xd5, 0xaf, 0x00, 0xb3, + 0xf5, 0x4b, 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x0e, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff, + 0xff, 0x59, 0xd8, 0xb4, 0xf9, 0xcd, 0x00, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/cbdc/types/keys.go b/x/cbdc/types/keys.go new file mode 100644 index 00000000..731000b0 --- /dev/null +++ b/x/cbdc/types/keys.go @@ -0,0 +1,19 @@ +package types + +const ( + // ModuleName defines the module name + ModuleName = "cbdc" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + // RouterKey defines the module's message routing key + RouterKey = ModuleName + + // MemStoreKey defines the in-memory store key + MemStoreKey = "mem_" + ModuleName +) + +func KeyPrefix(p string) []byte { + return []byte(p) +} diff --git a/x/poa/types/message_burn.go b/x/cbdc/types/message_burn.go similarity index 100% rename from x/poa/types/message_burn.go rename to x/cbdc/types/message_burn.go diff --git a/x/poa/types/message_mint.go b/x/cbdc/types/message_mint.go similarity index 100% rename from x/poa/types/message_mint.go rename to x/cbdc/types/message_mint.go diff --git a/x/cbdc/types/params.go b/x/cbdc/types/params.go new file mode 100644 index 00000000..e562ff79 --- /dev/null +++ b/x/cbdc/types/params.go @@ -0,0 +1,32 @@ +package types + +import ( + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" +) + +var _ paramtypes.ParamSet = (*Params)(nil) + +// ParamKeyTable the param key table for launch module +func ParamKeyTable() paramtypes.KeyTable { + return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) +} + +// NewParams creates a new Params instance +func NewParams() Params { + return Params{} +} + +// DefaultParams returns a default set of parameters +func DefaultParams() Params { + return NewParams() +} + +// ParamSetPairs get the params.ParamSet +func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { + return paramtypes.ParamSetPairs{} +} + +// Validate validates the set of params +func (p *Params) Validate() error { + return nil +} diff --git a/x/cbdc/types/params.pb.go b/x/cbdc/types/params.pb.go new file mode 100644 index 00000000..2338f8cd --- /dev/null +++ b/x/cbdc/types/params.pb.go @@ -0,0 +1,262 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cbdc/params.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Params defines the parameters for the module. +type Params struct { +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_a383b166b3425dd0, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func init() { + proto.RegisterType((*Params)(nil), "cbdc.Params") +} + +func init() { proto.RegisterFile("cbdc/params.proto", fileDescriptor_a383b166b3425dd0) } + +var fileDescriptor_a383b166b3425dd0 = []byte{ + // 125 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4c, 0x4e, 0x4a, 0x49, + 0xd6, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, + 0x09, 0x29, 0x71, 0x70, 0xb1, 0x05, 0x80, 0x45, 0x9d, 0x5c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, + 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, + 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x2b, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, + 0xbf, 0x20, 0x35, 0xb5, 0xa8, 0xb8, 0xb2, 0xb8, 0x44, 0x1f, 0xa4, 0x5b, 0x37, 0x2f, 0x3f, 0x25, + 0x55, 0xbf, 0x02, 0xcc, 0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x1b, 0x6e, 0x0c, + 0x08, 0x00, 0x00, 0xff, 0xff, 0x33, 0x29, 0xdc, 0x86, 0x71, 0x00, 0x00, 0x00, +} + +func (m *Params) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintParams(dAtA []byte, offset int, v uint64) int { + offset -= sovParams(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovParams(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozParams(x uint64) (n int) { + return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipParams(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthParams + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupParams + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthParams + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowParams = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/cbdc/types/query.pb.go b/x/cbdc/types/query.pb.go new file mode 100644 index 00000000..2d16e85c --- /dev/null +++ b/x/cbdc/types/query.pb.go @@ -0,0 +1,534 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cbdc/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryParamsRequest is request type for the Query/Params RPC method. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f2e227b7bbe96573, []int{0} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryParamsResponse is response type for the Query/Params RPC method. +type QueryParamsResponse struct { + // params holds all the parameters of this module. + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f2e227b7bbe96573, []int{1} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*QueryParamsRequest)(nil), "cbdc.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "cbdc.QueryParamsResponse") +} + +func init() { proto.RegisterFile("cbdc/query.proto", fileDescriptor_f2e227b7bbe96573) } + +var fileDescriptor_f2e227b7bbe96573 = []byte{ + // 263 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x48, 0x4e, 0x4a, 0x49, + 0xd6, 0x2f, 0x2c, 0x4d, 0x2d, 0xaa, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0x89, + 0x48, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x05, 0xf4, 0x41, 0x2c, 0x88, 0x9c, 0x94, 0x4c, 0x7a, + 0x7e, 0x7e, 0x7a, 0x4e, 0xaa, 0x7e, 0x62, 0x41, 0xa6, 0x7e, 0x62, 0x5e, 0x5e, 0x7e, 0x49, 0x62, + 0x49, 0x66, 0x7e, 0x5e, 0x31, 0x54, 0x56, 0x10, 0x6c, 0x56, 0x41, 0x62, 0x51, 0x62, 0x2e, 0x54, + 0x48, 0x49, 0x84, 0x4b, 0x28, 0x10, 0x64, 0x76, 0x00, 0x58, 0x30, 0x28, 0xb5, 0xb0, 0x34, 0xb5, + 0xb8, 0x44, 0xc9, 0x91, 0x4b, 0x18, 0x45, 0xb4, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0x55, 0x48, 0x8b, + 0x8b, 0x0d, 0xa2, 0x59, 0x82, 0x51, 0x81, 0x51, 0x83, 0xdb, 0x88, 0x47, 0x0f, 0x64, 0xa0, 0x1e, + 0x44, 0x95, 0x13, 0xcb, 0x89, 0x7b, 0xf2, 0x0c, 0x41, 0x50, 0x15, 0x46, 0x89, 0x5c, 0xac, 0x60, + 0x23, 0x84, 0x22, 0xb8, 0xd8, 0x20, 0x0a, 0x84, 0x24, 0x20, 0xca, 0x31, 0xed, 0x93, 0x92, 0xc4, + 0x22, 0x03, 0xb1, 0x53, 0x49, 0xb2, 0xe9, 0xf2, 0x93, 0xc9, 0x4c, 0xc2, 0x42, 0x82, 0xfa, 0x60, + 0xc7, 0x23, 0xf9, 0xc0, 0xc9, 0xe5, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, + 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, + 0xb4, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x0b, 0x52, 0x53, 0x8b, + 0x8a, 0x2b, 0x8b, 0x4b, 0xc0, 0x5a, 0x75, 0xf3, 0xf2, 0x53, 0x52, 0xf5, 0x2b, 0x20, 0xc6, 0x94, + 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0x03, 0xc2, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x37, + 0x2f, 0x66, 0x0d, 0x69, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Parameters queries the parameters of the module. + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/cbdc.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Parameters queries the parameters of the module. + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cbdc.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cbdc.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cbdc/query.proto", +} + +func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/cbdc/types/query.pb.gw.go b/x/cbdc/types/query.pb.gw.go new file mode 100644 index 00000000..bdd186d5 --- /dev/null +++ b/x/cbdc/types/query.pb.gw.go @@ -0,0 +1,153 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: cbdc/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1}, []string{"cbdc", "params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage +) diff --git a/x/cbdc/types/tx.pb.go b/x/cbdc/types/tx.pb.go new file mode 100644 index 00000000..ac1ebda2 --- /dev/null +++ b/x/cbdc/types/tx.pb.go @@ -0,0 +1,1078 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cbdc/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgMint defines a message to mint CBDC tokens and send them to an address +type MsgMint struct { + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` +} + +func (m *MsgMint) Reset() { *m = MsgMint{} } +func (m *MsgMint) String() string { return proto.CompactTextString(m) } +func (*MsgMint) ProtoMessage() {} +func (*MsgMint) Descriptor() ([]byte, []int) { + return fileDescriptor_870101f11584fe74, []int{0} +} +func (m *MsgMint) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMint.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgMint) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMint.Merge(m, src) +} +func (m *MsgMint) XXX_Size() int { + return m.Size() +} +func (m *MsgMint) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMint.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMint proto.InternalMessageInfo + +func (m *MsgMint) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgMint) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgMint) GetAmount() types.Coin { + if m != nil { + return m.Amount + } + return types.Coin{} +} + +// MsgMintResponse defines the response for minting CBDC tokens +type MsgMintResponse struct { +} + +func (m *MsgMintResponse) Reset() { *m = MsgMintResponse{} } +func (m *MsgMintResponse) String() string { return proto.CompactTextString(m) } +func (*MsgMintResponse) ProtoMessage() {} +func (*MsgMintResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_870101f11584fe74, []int{1} +} +func (m *MsgMintResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgMintResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgMintResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgMintResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgMintResponse.Merge(m, src) +} +func (m *MsgMintResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgMintResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgMintResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgMintResponse proto.InternalMessageInfo + +// MsgBurn defines a message to burn CBDC tokens from an address +type MsgBurn struct { + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` +} + +func (m *MsgBurn) Reset() { *m = MsgBurn{} } +func (m *MsgBurn) String() string { return proto.CompactTextString(m) } +func (*MsgBurn) ProtoMessage() {} +func (*MsgBurn) Descriptor() ([]byte, []int) { + return fileDescriptor_870101f11584fe74, []int{2} +} +func (m *MsgBurn) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgBurn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgBurn.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgBurn) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBurn.Merge(m, src) +} +func (m *MsgBurn) XXX_Size() int { + return m.Size() +} +func (m *MsgBurn) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBurn.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgBurn proto.InternalMessageInfo + +func (m *MsgBurn) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgBurn) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgBurn) GetAmount() types.Coin { + if m != nil { + return m.Amount + } + return types.Coin{} +} + +// MsgBurnResponse defines the response for burning CBDC tokens +type MsgBurnResponse struct { +} + +func (m *MsgBurnResponse) Reset() { *m = MsgBurnResponse{} } +func (m *MsgBurnResponse) String() string { return proto.CompactTextString(m) } +func (*MsgBurnResponse) ProtoMessage() {} +func (*MsgBurnResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_870101f11584fe74, []int{3} +} +func (m *MsgBurnResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgBurnResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgBurnResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgBurnResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgBurnResponse.Merge(m, src) +} +func (m *MsgBurnResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgBurnResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgBurnResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgBurnResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgMint)(nil), "cbdc.MsgMint") + proto.RegisterType((*MsgMintResponse)(nil), "cbdc.MsgMintResponse") + proto.RegisterType((*MsgBurn)(nil), "cbdc.MsgBurn") + proto.RegisterType((*MsgBurnResponse)(nil), "cbdc.MsgBurnResponse") +} + +func init() { proto.RegisterFile("cbdc/tx.proto", fileDescriptor_870101f11584fe74) } + +var fileDescriptor_870101f11584fe74 = []byte{ + // 380 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x52, 0x3f, 0x4f, 0xfa, 0x40, + 0x18, 0xee, 0xfd, 0xe0, 0x07, 0xe1, 0x0c, 0x1a, 0x1a, 0x8c, 0xa5, 0x43, 0x25, 0x4c, 0x84, 0x48, + 0x2f, 0x60, 0xe2, 0x60, 0x5c, 0xac, 0xae, 0x2c, 0xb8, 0xb9, 0x98, 0xfe, 0xb9, 0x94, 0x0e, 0xbd, + 0x6b, 0x7a, 0x57, 0x02, 0x9b, 0xf1, 0x13, 0xf8, 0x31, 0x1c, 0x19, 0xfc, 0x06, 0x2e, 0x8c, 0xc4, + 0xc9, 0xc9, 0x18, 0x18, 0xf8, 0x1a, 0xe6, 0x7a, 0xd7, 0x80, 0x93, 0xb3, 0x4b, 0xdb, 0xe7, 0x7d, + 0x9e, 0xb7, 0xef, 0xf3, 0xdc, 0xbd, 0xb0, 0xee, 0x7b, 0x81, 0x8f, 0xf8, 0xcc, 0x4e, 0x52, 0xca, + 0xa9, 0x5e, 0x16, 0xd0, 0x6c, 0x86, 0x34, 0xa4, 0x79, 0x01, 0x89, 0x2f, 0xc9, 0x99, 0x2d, 0x9f, + 0xb2, 0x98, 0xb2, 0x07, 0x49, 0x48, 0xa0, 0xa8, 0x13, 0x89, 0x50, 0xcc, 0x42, 0x34, 0x1d, 0x88, + 0x97, 0x22, 0x2c, 0x45, 0x78, 0x2e, 0xc3, 0x68, 0x3a, 0xf0, 0x30, 0x77, 0x07, 0xc8, 0xa7, 0x11, + 0x51, 0x7c, 0xc3, 0x8d, 0x23, 0x42, 0x51, 0xfe, 0x94, 0xa5, 0xce, 0x1b, 0x80, 0xd5, 0x11, 0x0b, + 0x47, 0x11, 0xe1, 0xfa, 0x05, 0xac, 0xb9, 0x19, 0x9f, 0xd0, 0x34, 0xe2, 0x73, 0x03, 0xb4, 0x41, + 0xb7, 0xe6, 0x18, 0xef, 0xaf, 0xfd, 0xa6, 0x1a, 0x7e, 0x1d, 0x04, 0x29, 0x66, 0xec, 0x8e, 0xa7, + 0x11, 0x09, 0xc7, 0x3b, 0xa9, 0x3e, 0x84, 0x55, 0x57, 0x72, 0xc6, 0xbf, 0x5f, 0xba, 0x0a, 0xa1, + 0x7e, 0x05, 0x2b, 0x6e, 0x4c, 0x33, 0xc2, 0x8d, 0x52, 0x1b, 0x74, 0x0f, 0x86, 0x2d, 0x5b, 0xe9, + 0x85, 0x77, 0x5b, 0x79, 0xb7, 0x6f, 0x68, 0x44, 0x9c, 0xda, 0xf2, 0xf3, 0x54, 0x7b, 0xd9, 0x2e, + 0x7a, 0x60, 0xac, 0x7a, 0x2e, 0x0f, 0x9f, 0xb6, 0x8b, 0xde, 0xce, 0x41, 0xa7, 0x01, 0x8f, 0x54, + 0x88, 0x31, 0x66, 0x09, 0x25, 0x0c, 0x17, 0xc1, 0x9c, 0x2c, 0x25, 0x7f, 0x3e, 0x98, 0x08, 0x51, + 0x04, 0x1b, 0x4e, 0x60, 0x69, 0xc4, 0x42, 0xfd, 0x0c, 0x96, 0xf3, 0x4b, 0xab, 0xdb, 0x62, 0x89, + 0x6c, 0x15, 0xdf, 0x3c, 0xfe, 0x01, 0x8b, 0x26, 0xa1, 0xce, 0x4f, 0x62, 0xa7, 0x16, 0x70, 0x4f, + 0xbd, 0x3f, 0xc2, 0xfc, 0xff, 0x28, 0x4c, 0x39, 0xb7, 0xcb, 0xb5, 0x05, 0x56, 0x6b, 0x0b, 0x7c, + 0xad, 0x2d, 0xf0, 0xbc, 0xb1, 0xb4, 0xd5, 0xc6, 0xd2, 0x3e, 0x36, 0x96, 0x76, 0xdf, 0x0b, 0x23, + 0x3e, 0xc9, 0x3c, 0xdb, 0xa7, 0x31, 0x4a, 0x30, 0x4e, 0xd9, 0x9c, 0x71, 0x24, 0x7e, 0xd5, 0x27, + 0x34, 0xc0, 0x68, 0x86, 0xe4, 0x9e, 0xcf, 0x13, 0xcc, 0xbc, 0x4a, 0xbe, 0x68, 0xe7, 0xdf, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x54, 0x85, 0xf9, 0xf9, 0xfc, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // Mints CBDC tokens and sends them to an address + Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) + // Burns CBDC tokens from an address + Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) { + out := new(MsgMintResponse) + err := c.cc.Invoke(ctx, "/cbdc.Msg/Mint", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) { + out := new(MsgBurnResponse) + err := c.cc.Invoke(ctx, "/cbdc.Msg/Burn", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // Mints CBDC tokens and sends them to an address + Mint(context.Context, *MsgMint) (*MsgMintResponse, error) + // Burns CBDC tokens from an address + Burn(context.Context, *MsgBurn) (*MsgBurnResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) Mint(ctx context.Context, req *MsgMint) (*MsgMintResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Mint not implemented") +} +func (*UnimplementedMsgServer) Burn(ctx context.Context, req *MsgBurn) (*MsgBurnResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Burn not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_Mint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgMint) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Mint(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cbdc.Msg/Mint", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Mint(ctx, req.(*MsgMint)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_Burn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgBurn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Burn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cbdc.Msg/Burn", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Burn(ctx, req.(*MsgBurn)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cbdc.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Mint", + Handler: _Msg_Mint_Handler, + }, + { + MethodName: "Burn", + Handler: _Msg_Burn_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cbdc/tx.proto", +} + +func (m *MsgMint) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMint) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMint) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgMintResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgMintResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgMintResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgBurn) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgBurn) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBurn) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgBurnResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgBurnResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgBurnResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgMint) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgMintResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgBurn) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgBurnResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgMint) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMint: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMint: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgMintResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgMintResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgBurn) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgBurn: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBurn: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgBurnResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgBurnResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgBurnResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/poa/keeper/common_test.go b/x/poa/keeper/common_test.go index 0ee4b673..e90d77e1 100644 --- a/x/poa/keeper/common_test.go +++ b/x/poa/keeper/common_test.go @@ -22,7 +22,6 @@ import ( const ( accountAddressPrefix = "ethm" bip44CoinType = 60 - testCBDCDenom = "acbdc" ) func setupSdkConfig() { @@ -84,7 +83,6 @@ func getMockedPoAKeeper(t *testing.T, key *storetypes.KVStoreKey, tsKey *storety bankKeeper, stakingKeeper, "ethm1wunfhl05vc8r8xxnnp8gt62wa54r6y52pg03zq", - testCBDCDenom, ) poaKeeper.SetParams(ctx, types.DefaultParams()) types.RegisterMsgServer(msr, NewMsgServerImpl(*poaKeeper)) diff --git a/x/poa/keeper/keeper.go b/x/poa/keeper/keeper.go index e662d726..e80da420 100644 --- a/x/poa/keeper/keeper.go +++ b/x/poa/keeper/keeper.go @@ -38,7 +38,6 @@ type ( router *baseapp.MsgServiceRouter // Msg server router bk types.BankKeeper sk types.StakingKeeper - cbdcDenom string // the only denom that can be minted/burned via this module } ) @@ -49,7 +48,6 @@ func NewKeeper( bk types.BankKeeper, sk types.StakingKeeper, authority string, - cbdcDenom string, ) *Keeper { // set KeyTable if it has not already been set if !ps.HasKeyTable() { @@ -61,10 +59,6 @@ func NewKeeper( panic(err) } - if err := sdk.ValidateDenom(cbdcDenom); err != nil { - panic(err) - } - return &Keeper{ cdc: cdc, paramstore: ps, @@ -72,7 +66,6 @@ func NewKeeper( router: router, bk: bk, sk: sk, - cbdcDenom: cbdcDenom, } } @@ -213,70 +206,6 @@ func (k Keeper) ExecuteAddValidator(ctx sdk.Context, msg *types.MsgAddValidator) return nil } -func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) error { - if amount.Denom != k.cbdcDenom { - return types.ErrInvalidDenom - } - if !amount.IsPositive() { - return types.ErrInvalidAmount - } - - toAddr, err := sdk.AccAddressFromBech32(address) - if err != nil { - return err - } - - coins := sdk.NewCoins(amount) - if err := k.bk.MintCoins(ctx, types.ModuleName, coins); err != nil { - return err - } - if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, toAddr, coins); err != nil { - return err - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeMint, - sdk.NewAttribute(types.AttributeAddress, toAddr.String()), - sdk.NewAttribute(types.AttributeAmount, amount.String()), - ), - ) - - return nil -} - -func (k Keeper) ExecuteBurn(ctx sdk.Context, address string, amount sdk.Coin) error { - if amount.Denom != k.cbdcDenom { - return types.ErrInvalidDenom - } - if !amount.IsPositive() { - return types.ErrInvalidAmount - } - - fromAddr, err := sdk.AccAddressFromBech32(address) - if err != nil { - return err - } - - coins := sdk.NewCoins(amount) - if err := k.bk.SendCoinsFromAccountToModule(ctx, fromAddr, types.ModuleName, coins); err != nil { - return err - } - if err := k.bk.BurnCoins(ctx, types.ModuleName, coins); err != nil { - return err - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeBurn, - sdk.NewAttribute(types.AttributeAddress, fromAddr.String()), - sdk.NewAttribute(types.AttributeAmount, amount.String()), - ), - ) - - return nil -} - func (k Keeper) ExecuteRemoveValidator(ctx sdk.Context, validatorAddress string) error { valAddress, err := sdk.ValAddressFromBech32(validatorAddress) if err != nil { diff --git a/x/poa/types/codec.go b/x/poa/types/codec.go index 34768d0c..77d089cc 100644 --- a/x/poa/types/codec.go +++ b/x/poa/types/codec.go @@ -11,8 +11,6 @@ import ( func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgAddValidator{}, "poa/AddValidator", nil) cdc.RegisterConcrete(&MsgRemoveValidator{}, "poa/RemoveValidator", nil) - cdc.RegisterConcrete(&MsgMint{}, "poa/Mint", nil) - cdc.RegisterConcrete(&MsgBurn{}, "poa/Burn", nil) // this line is used by starport scaffolding # 2 } @@ -23,12 +21,6 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgRemoveValidator{}, ) - registry.RegisterImplementations((*sdk.Msg)(nil), - &MsgMint{}, - ) - registry.RegisterImplementations((*sdk.Msg)(nil), - &MsgBurn{}, - ) registry.RegisterImplementations( (*govtypes.Content)(nil), ) diff --git a/x/poa/types/errors.go b/x/poa/types/errors.go index 4ab15ef9..af388423 100644 --- a/x/poa/types/errors.go +++ b/x/poa/types/errors.go @@ -15,6 +15,4 @@ var ( ErrInvalidValidatorStatus = sdkerrors.Register(ModuleName, 5, "invalid validator status") ErrAddressIsNotAValidator = sdkerrors.Register(ModuleName, 6, "address is not a validator") ErrMaxValidatorsReached = sdkerrors.Register(ModuleName, 7, "maximum number of validators reached") - ErrInvalidAmount = sdkerrors.Register(ModuleName, 8, "amount must be positive") - ErrInvalidDenom = sdkerrors.Register(ModuleName, 9, "amount denom must match the configured CBDC denom") ) diff --git a/x/poa/types/events.go b/x/poa/types/events.go index 00b3ac49..b81d174f 100644 --- a/x/poa/types/events.go +++ b/x/poa/types/events.go @@ -3,12 +3,8 @@ package types const ( EventTypeAddValidator = "add_validator" EventTypeRemoveValidator = "remove_validator" - EventTypeMint = "mint" - EventTypeBurn = "burn" AttributeValidator = "address" AttributeHeight = "height" AttributeStakingTokens = "staking_tokens" AttributeBankTokens = "bank_tokens" - AttributeAddress = "address" - AttributeAmount = "amount" ) diff --git a/x/poa/types/tx.pb.go b/x/poa/types/tx.pb.go index 949c5a7f..baa307ef 100644 --- a/x/poa/types/tx.pb.go +++ b/x/poa/types/tx.pb.go @@ -8,7 +8,6 @@ import ( fmt "fmt" _ "github.com/cosmos/cosmos-proto" types1 "github.com/cosmos/cosmos-sdk/codec/types" - types2 "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" types "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -231,255 +230,48 @@ func (m *MsgRemoveValidatorResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgRemoveValidatorResponse proto.InternalMessageInfo -// MsgMint defines a message to mint tokens and send them to an address -type MsgMint struct { - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` - Amount types2.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` -} - -func (m *MsgMint) Reset() { *m = MsgMint{} } -func (m *MsgMint) String() string { return proto.CompactTextString(m) } -func (*MsgMint) ProtoMessage() {} -func (*MsgMint) Descriptor() ([]byte, []int) { - return fileDescriptor_8ac16a0aed23c2e2, []int{4} -} -func (m *MsgMint) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgMint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgMint.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgMint) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgMint.Merge(m, src) -} -func (m *MsgMint) XXX_Size() int { - return m.Size() -} -func (m *MsgMint) XXX_DiscardUnknown() { - xxx_messageInfo_MsgMint.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgMint proto.InternalMessageInfo - -func (m *MsgMint) GetAuthority() string { - if m != nil { - return m.Authority - } - return "" -} - -func (m *MsgMint) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *MsgMint) GetAmount() types2.Coin { - if m != nil { - return m.Amount - } - return types2.Coin{} -} - -// MsgMintResponse defines the response for minting tokens -type MsgMintResponse struct { -} - -func (m *MsgMintResponse) Reset() { *m = MsgMintResponse{} } -func (m *MsgMintResponse) String() string { return proto.CompactTextString(m) } -func (*MsgMintResponse) ProtoMessage() {} -func (*MsgMintResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_8ac16a0aed23c2e2, []int{5} -} -func (m *MsgMintResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgMintResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgMintResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgMintResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgMintResponse.Merge(m, src) -} -func (m *MsgMintResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgMintResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgMintResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgMintResponse proto.InternalMessageInfo - -// MsgBurn defines a message to burn tokens from an address -type MsgBurn struct { - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` - Amount types2.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` -} - -func (m *MsgBurn) Reset() { *m = MsgBurn{} } -func (m *MsgBurn) String() string { return proto.CompactTextString(m) } -func (*MsgBurn) ProtoMessage() {} -func (*MsgBurn) Descriptor() ([]byte, []int) { - return fileDescriptor_8ac16a0aed23c2e2, []int{6} -} -func (m *MsgBurn) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgBurn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgBurn.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgBurn) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgBurn.Merge(m, src) -} -func (m *MsgBurn) XXX_Size() int { - return m.Size() -} -func (m *MsgBurn) XXX_DiscardUnknown() { - xxx_messageInfo_MsgBurn.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgBurn proto.InternalMessageInfo - -func (m *MsgBurn) GetAuthority() string { - if m != nil { - return m.Authority - } - return "" -} - -func (m *MsgBurn) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *MsgBurn) GetAmount() types2.Coin { - if m != nil { - return m.Amount - } - return types2.Coin{} -} - -// MsgBurnResponse defines the response for burning tokens -type MsgBurnResponse struct { -} - -func (m *MsgBurnResponse) Reset() { *m = MsgBurnResponse{} } -func (m *MsgBurnResponse) String() string { return proto.CompactTextString(m) } -func (*MsgBurnResponse) ProtoMessage() {} -func (*MsgBurnResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_8ac16a0aed23c2e2, []int{7} -} -func (m *MsgBurnResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgBurnResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgBurnResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgBurnResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgBurnResponse.Merge(m, src) -} -func (m *MsgBurnResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgBurnResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgBurnResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgBurnResponse proto.InternalMessageInfo - func init() { proto.RegisterType((*MsgAddValidator)(nil), "poa.MsgAddValidator") proto.RegisterType((*MsgAddValidatorResponse)(nil), "poa.MsgAddValidatorResponse") proto.RegisterType((*MsgRemoveValidator)(nil), "poa.MsgRemoveValidator") proto.RegisterType((*MsgRemoveValidatorResponse)(nil), "poa.MsgRemoveValidatorResponse") - proto.RegisterType((*MsgMint)(nil), "poa.MsgMint") - proto.RegisterType((*MsgMintResponse)(nil), "poa.MsgMintResponse") - proto.RegisterType((*MsgBurn)(nil), "poa.MsgBurn") - proto.RegisterType((*MsgBurnResponse)(nil), "poa.MsgBurnResponse") } func init() { proto.RegisterFile("poa/tx.proto", fileDescriptor_8ac16a0aed23c2e2) } var fileDescriptor_8ac16a0aed23c2e2 = []byte{ - // 595 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0x31, 0x6f, 0xd3, 0x40, - 0x14, 0x8e, 0x9b, 0x92, 0x2a, 0xd7, 0x88, 0x12, 0x2b, 0x52, 0x1c, 0xab, 0xb8, 0x55, 0x60, 0x28, - 0x91, 0x6a, 0xab, 0x41, 0x62, 0x40, 0x2c, 0x71, 0x81, 0x81, 0x2a, 0x52, 0x65, 0x24, 0x06, 0x96, - 0xea, 0x6c, 0x1f, 0xae, 0xd5, 0xfa, 0x9e, 0xe5, 0x3b, 0x47, 0xf5, 0x86, 0xf8, 0x05, 0xfc, 0x07, - 0x16, 0xc6, 0x0e, 0xec, 0x0c, 0x2c, 0x15, 0x53, 0xc5, 0xc4, 0x84, 0x50, 0x32, 0xf4, 0x17, 0xb0, - 0x23, 0xdb, 0x67, 0x27, 0x4d, 0x88, 0x84, 0x60, 0xea, 0x92, 0xe4, 0xf3, 0xf7, 0xbd, 0x97, 0xfb, - 0xbe, 0xf7, 0x7c, 0xa8, 0x11, 0x02, 0x36, 0xf8, 0x99, 0x1e, 0x46, 0xc0, 0x41, 0xae, 0x86, 0x80, - 0xd5, 0x96, 0x07, 0x1e, 0x64, 0xd8, 0x48, 0x7f, 0xe5, 0x94, 0xda, 0x71, 0x80, 0x05, 0xc0, 0x8e, - 0x72, 0x22, 0x07, 0x82, 0x6a, 0xe7, 0xc8, 0x08, 0x98, 0x67, 0x8c, 0xf6, 0xd2, 0x2f, 0x41, 0xdc, - 0x17, 0x04, 0xe3, 0xf8, 0xc4, 0xa7, 0x29, 0x69, 0x13, 0x8e, 0xf7, 0x0a, 0x2c, 0x54, 0x9a, 0x50, - 0xd9, 0x98, 0x91, 0x52, 0xe2, 0x80, 0x4f, 0x8b, 0x7f, 0xf6, 0x00, 0xbc, 0x53, 0x62, 0x64, 0xc8, - 0x8e, 0xdf, 0x18, 0x98, 0x26, 0x82, 0x6a, 0xe2, 0xc0, 0xa7, 0x60, 0x64, 0x9f, 0xf9, 0xa3, 0xee, - 0xe7, 0x15, 0xb4, 0x31, 0x64, 0xde, 0xc0, 0x75, 0x5f, 0xe1, 0x53, 0xdf, 0xc5, 0x1c, 0x22, 0xf9, - 0x11, 0xaa, 0xe3, 0x98, 0x1f, 0x43, 0xe4, 0xf3, 0x44, 0x91, 0xb6, 0xa5, 0x9d, 0xba, 0xa9, 0x7c, - 0xfb, 0xb4, 0xdb, 0x12, 0x2e, 0x06, 0xae, 0x1b, 0x11, 0xc6, 0x5e, 0xf2, 0xc8, 0xa7, 0x9e, 0x35, - 0x95, 0xca, 0x2f, 0x50, 0x73, 0x54, 0x34, 0x39, 0xc2, 0xb9, 0x4a, 0x59, 0xc9, 0xea, 0xef, 0x2e, - 0xab, 0xff, 0x78, 0x75, 0xde, 0xab, 0x58, 0x77, 0xca, 0x3a, 0x41, 0xca, 0x87, 0x68, 0xdd, 0x25, - 0xcc, 0x89, 0xfc, 0x90, 0xfb, 0x40, 0x95, 0xea, 0xb6, 0xb4, 0xb3, 0xde, 0xbf, 0xa7, 0x8b, 0x16, - 0x45, 0x22, 0xc2, 0xbe, 0xfe, 0x74, 0x2a, 0x35, 0xeb, 0x17, 0x3f, 0xb6, 0x2a, 0x69, 0x5b, 0xc9, - 0x9a, 0x6d, 0x21, 0x3f, 0x47, 0xb5, 0x30, 0xb6, 0x4f, 0x48, 0xa2, 0xac, 0x66, 0xcd, 0x5a, 0x7a, - 0x1e, 0x94, 0x5e, 0x04, 0xa5, 0x0f, 0x68, 0x62, 0x2a, 0x5f, 0xa7, 0x07, 0x75, 0xa2, 0x24, 0xe4, - 0xa0, 0x1f, 0xc6, 0xf6, 0x01, 0x49, 0x2c, 0x51, 0xfd, 0xf8, 0xf6, 0xbb, 0xab, 0xf3, 0xde, 0xd4, - 0x75, 0xb7, 0x83, 0xda, 0x73, 0x01, 0x5a, 0x84, 0x85, 0x40, 0x19, 0xe9, 0x7e, 0x90, 0x90, 0x3c, - 0x64, 0x9e, 0x45, 0x02, 0x18, 0x91, 0xff, 0xcf, 0xf7, 0xd9, 0xf2, 0x7c, 0x97, 0xd7, 0x2f, 0x44, - 0xbb, 0x60, 0x60, 0x13, 0xa9, 0x8b, 0x87, 0x2c, 0x3d, 0x7c, 0x91, 0xd0, 0xda, 0x90, 0x79, 0x43, - 0x9f, 0xf2, 0x7f, 0x3e, 0x78, 0x1f, 0xad, 0xfd, 0xed, 0x71, 0x0b, 0xa1, 0xfc, 0x04, 0xd5, 0x70, - 0x00, 0x31, 0xe5, 0x62, 0xf6, 0x9d, 0x62, 0xf6, 0xe9, 0xde, 0x97, 0x83, 0xdf, 0x07, 0xff, 0xda, - 0xc4, 0x45, 0xcd, 0x82, 0xc7, 0x66, 0xb6, 0xe5, 0xa9, 0x89, 0x79, 0x63, 0x66, 0x1c, 0xd1, 0x1b, - 0x6f, 0x2c, 0x35, 0x51, 0x18, 0xeb, 0xff, 0x92, 0x50, 0x75, 0xc8, 0x3c, 0xd9, 0x44, 0x8d, 0x6b, - 0xaf, 0x75, 0x4b, 0x0f, 0x01, 0xeb, 0x73, 0xbb, 0xaa, 0x6e, 0xfe, 0xe9, 0x69, 0xd1, 0x4b, 0x3e, - 0x40, 0x1b, 0xf3, 0xdb, 0xdb, 0x2e, 0x0a, 0xe6, 0x08, 0x75, 0x6b, 0x09, 0x51, 0x36, 0xeb, 0xa1, - 0xd5, 0x6c, 0x8d, 0x1a, 0x85, 0x30, 0x45, 0x6a, 0x6b, 0x16, 0xcd, 0x6a, 0xb3, 0xc9, 0x94, 0xda, - 0x14, 0x4d, 0xb5, 0xb3, 0x86, 0xd5, 0x5b, 0x6f, 0xd3, 0x88, 0xcc, 0xfd, 0x8b, 0xb1, 0x26, 0x5d, - 0x8e, 0x35, 0xe9, 0xe7, 0x58, 0x93, 0xde, 0x4f, 0xb4, 0xca, 0xe5, 0x44, 0xab, 0x7c, 0x9f, 0x68, - 0x95, 0xd7, 0x0f, 0x3c, 0x9f, 0x1f, 0xc7, 0xb6, 0xee, 0x40, 0x60, 0x84, 0x84, 0x44, 0x2c, 0x61, - 0xdc, 0x70, 0x6c, 0xd7, 0xd9, 0xa5, 0xe0, 0x12, 0xe3, 0xcc, 0xc8, 0x6e, 0xf5, 0x24, 0x24, 0xcc, - 0xae, 0x65, 0xb7, 0xc1, 0xc3, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x32, 0x36, 0x18, 0xa5, 0xe9, - 0x05, 0x00, 0x00, + // 493 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0x3f, 0x6f, 0xd3, 0x40, + 0x18, 0xc6, 0xe3, 0x06, 0x2a, 0xe5, 0x5a, 0x51, 0x6a, 0x45, 0x8a, 0x6b, 0x15, 0xb7, 0x0a, 0x0c, + 0xa5, 0x52, 0xef, 0xd4, 0x22, 0x31, 0xb0, 0xc5, 0xfc, 0x19, 0xa8, 0x22, 0x55, 0x46, 0x62, 0x60, + 0xa9, 0xce, 0xf6, 0x71, 0xb5, 0x5a, 0xfb, 0x3d, 0xf9, 0xce, 0x51, 0xbd, 0x21, 0x3e, 0x01, 0x5f, + 0x80, 0x89, 0x85, 0xb1, 0x03, 0x3b, 0x6b, 0xc5, 0x54, 0x31, 0x31, 0x21, 0x94, 0x0c, 0xfd, 0x1a, + 0xc8, 0xf6, 0x1d, 0x81, 0x84, 0x4c, 0x5d, 0x12, 0xbf, 0xf7, 0x7b, 0x9f, 0x47, 0xef, 0xfb, 0xf8, + 0x8c, 0x56, 0x05, 0x50, 0xa2, 0xce, 0xb1, 0xc8, 0x41, 0x81, 0xdd, 0x16, 0x40, 0xdd, 0x2e, 0x07, + 0x0e, 0x75, 0x4d, 0xaa, 0xa7, 0x06, 0xb9, 0x1b, 0x11, 0xc8, 0x14, 0xe4, 0x71, 0x03, 0x9a, 0x42, + 0xa3, 0x5e, 0x53, 0x91, 0x54, 0x72, 0x32, 0xda, 0xaf, 0xfe, 0x34, 0x78, 0xa0, 0x81, 0x54, 0xf4, + 0x34, 0xc9, 0x2a, 0x18, 0x32, 0x45, 0xf7, 0x4d, 0x6d, 0x9c, 0x39, 0x00, 0x3f, 0x63, 0xa4, 0xae, + 0xc2, 0xe2, 0x2d, 0xa1, 0x59, 0xa9, 0xd1, 0x3a, 0x4d, 0x93, 0x0c, 0x48, 0xfd, 0xdb, 0x1c, 0xf5, + 0xbf, 0x2e, 0xa1, 0xb5, 0xa1, 0xe4, 0x83, 0x38, 0x7e, 0x4d, 0xcf, 0x92, 0x98, 0x2a, 0xc8, 0xed, + 0xc7, 0xa8, 0x43, 0x0b, 0x75, 0x02, 0x79, 0xa2, 0x4a, 0xc7, 0xda, 0xb6, 0x76, 0x3a, 0xbe, 0xf3, + 0xfd, 0xcb, 0x5e, 0x57, 0x4f, 0x39, 0x88, 0xe3, 0x9c, 0x49, 0xf9, 0x4a, 0xe5, 0x49, 0xc6, 0x83, + 0x69, 0xab, 0xfd, 0x12, 0xad, 0x8f, 0x8c, 0xc9, 0x31, 0x6d, 0xba, 0x9c, 0xa5, 0x5a, 0x7f, 0x6f, + 0x91, 0xfe, 0xf3, 0xf5, 0xc5, 0x6e, 0x2b, 0xb8, 0xfb, 0x47, 0xa7, 0xa1, 0x7d, 0x84, 0x56, 0x62, + 0x26, 0xa3, 0x3c, 0x11, 0x2a, 0x81, 0xcc, 0x69, 0x6f, 0x5b, 0x3b, 0x2b, 0x07, 0xf7, 0xb1, 0xb6, + 0x30, 0x1b, 0xeb, 0x04, 0xf0, 0xb3, 0x69, 0xab, 0xdf, 0xb9, 0xfc, 0xb9, 0xd5, 0xaa, 0x6c, 0xad, + 0xe0, 0x6f, 0x0b, 0xfb, 0x05, 0x5a, 0x16, 0x45, 0x78, 0xca, 0x4a, 0xe7, 0x56, 0x6d, 0xd6, 0xc5, + 0x4d, 0x50, 0xd8, 0x04, 0x85, 0x07, 0x59, 0xe9, 0x3b, 0xdf, 0xa6, 0x83, 0x46, 0x79, 0x29, 0x14, + 0xe0, 0xa3, 0x22, 0x3c, 0x64, 0x65, 0xa0, 0xd5, 0x4f, 0xee, 0xbc, 0xbf, 0xbe, 0xd8, 0x9d, 0x6e, + 0xdd, 0xdf, 0x40, 0xbd, 0x99, 0x00, 0x03, 0x26, 0x05, 0x64, 0x92, 0xf5, 0x3f, 0x59, 0xc8, 0x1e, + 0x4a, 0x1e, 0xb0, 0x14, 0x46, 0xec, 0xe6, 0xf9, 0x3e, 0x5f, 0x9c, 0xef, 0x62, 0xfd, 0x5c, 0xb4, + 0x73, 0x0b, 0x6c, 0x22, 0x77, 0x7e, 0x48, 0xb3, 0xc3, 0xc1, 0x47, 0x0b, 0xb5, 0x87, 0x92, 0xdb, + 0x3e, 0x5a, 0xfd, 0xe7, 0x92, 0x74, 0xb1, 0x00, 0x8a, 0x67, 0x36, 0x77, 0x37, 0xff, 0x77, 0x6a, + 0xbc, 0xec, 0x43, 0xb4, 0x36, 0x9b, 0x45, 0xcf, 0x08, 0x66, 0x80, 0xbb, 0xb5, 0x00, 0x18, 0x33, + 0xf7, 0xf6, 0xbb, 0xea, 0x1d, 0xfb, 0x4f, 0x2f, 0xc7, 0x9e, 0x75, 0x35, 0xf6, 0xac, 0x5f, 0x63, + 0xcf, 0xfa, 0x30, 0xf1, 0x5a, 0x57, 0x13, 0xaf, 0xf5, 0x63, 0xe2, 0xb5, 0xde, 0x3c, 0xe4, 0x89, + 0x3a, 0x29, 0x42, 0x1c, 0x41, 0x4a, 0x04, 0x63, 0xb9, 0x2c, 0xa5, 0x22, 0x51, 0x18, 0x47, 0x7b, + 0x19, 0xc4, 0x8c, 0x9c, 0x93, 0xfa, 0x5b, 0x2d, 0x05, 0x93, 0xe1, 0x72, 0x7d, 0x07, 0x1e, 0xfd, + 0x0e, 0x00, 0x00, 0xff, 0xff, 0x77, 0xf0, 0x55, 0x34, 0xbf, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -498,10 +290,6 @@ type MsgClient interface { AddValidator(ctx context.Context, in *MsgAddValidator, opts ...grpc.CallOption) (*MsgAddValidatorResponse, error) // Removes an existing validator from the authority RemoveValidator(ctx context.Context, in *MsgRemoveValidator, opts ...grpc.CallOption) (*MsgRemoveValidatorResponse, error) - // Mints tokens and sends them to an address - Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) - // Burns tokens from an address - Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) } type msgClient struct { @@ -530,34 +318,12 @@ func (c *msgClient) RemoveValidator(ctx context.Context, in *MsgRemoveValidator, return out, nil } -func (c *msgClient) Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) { - out := new(MsgMintResponse) - err := c.cc.Invoke(ctx, "/poa.Msg/Mint", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) { - out := new(MsgBurnResponse) - err := c.cc.Invoke(ctx, "/poa.Msg/Burn", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // MsgServer is the server API for Msg service. type MsgServer interface { // Adds a new validator into the authority AddValidator(context.Context, *MsgAddValidator) (*MsgAddValidatorResponse, error) // Removes an existing validator from the authority RemoveValidator(context.Context, *MsgRemoveValidator) (*MsgRemoveValidatorResponse, error) - // Mints tokens and sends them to an address - Mint(context.Context, *MsgMint) (*MsgMintResponse, error) - // Burns tokens from an address - Burn(context.Context, *MsgBurn) (*MsgBurnResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -570,12 +336,6 @@ func (*UnimplementedMsgServer) AddValidator(ctx context.Context, req *MsgAddVali func (*UnimplementedMsgServer) RemoveValidator(ctx context.Context, req *MsgRemoveValidator) (*MsgRemoveValidatorResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveValidator not implemented") } -func (*UnimplementedMsgServer) Mint(ctx context.Context, req *MsgMint) (*MsgMintResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Mint not implemented") -} -func (*UnimplementedMsgServer) Burn(ctx context.Context, req *MsgBurn) (*MsgBurnResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Burn not implemented") -} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -617,42 +377,6 @@ func _Msg_RemoveValidator_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } -func _Msg_Mint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgMint) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).Mint(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/poa.Msg/Mint", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).Mint(ctx, req.(*MsgMint)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_Burn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgBurn) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).Burn(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/poa.Msg/Burn", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).Burn(ctx, req.(*MsgBurn)) - } - return interceptor(ctx, in, info, handler) -} - var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "poa.Msg", HandlerType: (*MsgServer)(nil), @@ -665,14 +389,6 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "RemoveValidator", Handler: _Msg_RemoveValidator_Handler, }, - { - MethodName: "Mint", - Handler: _Msg_Mint_Handler, - }, - { - MethodName: "Burn", - Handler: _Msg_Burn_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "poa/tx.proto", @@ -820,511 +536,82 @@ func (m *MsgRemoveValidatorResponse) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } -func (m *MsgMint) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgMint) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgMint) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Address) > 0 { - i -= len(m.Address) - copy(dAtA[i:], m.Address) - i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) - i-- - dAtA[i] = 0x12 - } - if len(m.Authority) > 0 { - i -= len(m.Authority) - copy(dAtA[i:], m.Authority) - i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgMintResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgMintResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgMintResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgBurn) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ } - return dAtA[:n], nil -} - -func (m *MsgBurn) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) + dAtA[offset] = uint8(v) + return base } - -func (m *MsgBurn) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Address) > 0 { - i -= len(m.Address) - copy(dAtA[i:], m.Address) - i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) - i-- - dAtA[i] = 0x12 +func (m *MsgAddValidator) Size() (n int) { + if m == nil { + return 0 } - if len(m.Authority) > 0 { - i -= len(m.Authority) - copy(dAtA[i:], m.Authority) - i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgBurnResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgBurnResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgBurnResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func encodeVarintTx(dAtA []byte, offset int, v uint64) int { - offset -= sovTx(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *MsgAddValidator) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Authority) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ValidatorAddress) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Description.Size() - n += 1 + l + sovTx(uint64(l)) - if m.Pubkey != nil { - l = m.Pubkey.Size() - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgAddValidatorResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgRemoveValidator) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Authority) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ValidatorAddress) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgRemoveValidatorResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgMint) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Authority) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Address) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Amount.Size() - n += 1 + l + sovTx(uint64(l)) - return n -} - -func (m *MsgMintResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgBurn) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Authority) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Address) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Amount.Size() - n += 1 + l + sovTx(uint64(l)) - return n -} - -func (m *MsgBurnResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func sovTx(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozTx(x uint64) (n int) { - return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *MsgAddValidator) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgAddValidator: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAddValidator: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Authority = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ValidatorAddress = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Description.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pubkey", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Pubkey == nil { - m.Pubkey = &types1.Any{} - } - if err := m.Pubkey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgAddValidatorResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgAddValidatorResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAddValidatorResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Description.Size() + n += 1 + l + sovTx(uint64(l)) + if m.Pubkey != nil { + l = m.Pubkey.Size() + n += 1 + l + sovTx(uint64(l)) } + return n +} - if iNdEx > l { - return io.ErrUnexpectedEOF +func (m *MsgAddValidatorResponse) Size() (n int) { + if m == nil { + return 0 } - return nil + var l int + _ = l + return n } -func (m *MsgRemoveValidator) Unmarshal(dAtA []byte) error { + +func (m *MsgRemoveValidator) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRemoveValidatorResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgAddValidator) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1347,10 +634,10 @@ func (m *MsgRemoveValidator) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgRemoveValidator: wiretype end group for non-group") + return fmt.Errorf("proto: MsgAddValidator: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRemoveValidator: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgAddValidator: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1417,111 +704,11 @@ func (m *MsgRemoveValidator) Unmarshal(dAtA []byte) error { } m.ValidatorAddress = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgRemoveValidatorResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgRemoveValidatorResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRemoveValidatorResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgMint) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgMint: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgMint: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTx @@ -1531,59 +718,28 @@ func (m *MsgMint) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthTx } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthTx } if postIndex > l { return io.ErrUnexpectedEOF } - m.Authority = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF + if err := m.Description.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.Address = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Pubkey", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1610,7 +766,10 @@ func (m *MsgMint) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.Pubkey == nil { + m.Pubkey = &types1.Any{} + } + if err := m.Pubkey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1635,7 +794,7 @@ func (m *MsgMint) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { +func (m *MsgAddValidatorResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1658,10 +817,10 @@ func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgMintResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgAddValidatorResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgMintResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgAddValidatorResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -1685,7 +844,7 @@ func (m *MsgMintResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgBurn) Unmarshal(dAtA []byte) error { +func (m *MsgRemoveValidator) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1708,10 +867,10 @@ func (m *MsgBurn) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgBurn: wiretype end group for non-group") + return fmt.Errorf("proto: MsgRemoveValidator: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgBurn: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgRemoveValidator: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1748,7 +907,7 @@ func (m *MsgBurn) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1776,40 +935,7 @@ func (m *MsgBurn) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Address = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.ValidatorAddress = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -1832,7 +958,7 @@ func (m *MsgBurn) Unmarshal(dAtA []byte) error { } return nil } -func (m *MsgBurnResponse) Unmarshal(dAtA []byte) error { +func (m *MsgRemoveValidatorResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1855,10 +981,10 @@ func (m *MsgBurnResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MsgBurnResponse: wiretype end group for non-group") + return fmt.Errorf("proto: MsgRemoveValidatorResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MsgBurnResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: MsgRemoveValidatorResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: From d5857c3a1fd8e93dfac3ffbe6cde3eb759465baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Tue, 2 Jun 2026 11:58:03 +0200 Subject: [PATCH 06/17] fix(cbdc): guard against nil amount in mint/burn --- x/cbdc/keeper/keeper.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x/cbdc/keeper/keeper.go b/x/cbdc/keeper/keeper.go index d5fd1b76..83d80a2b 100644 --- a/x/cbdc/keeper/keeper.go +++ b/x/cbdc/keeper/keeper.go @@ -68,6 +68,9 @@ func (k Keeper) GetAuthority() string { } func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) error { + if err := amount.Validate(); err != nil { + return err + } if amount.Denom != k.cbdcDenom { return types.ErrInvalidDenom } @@ -100,6 +103,9 @@ func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) er } func (k Keeper) ExecuteBurn(ctx sdk.Context, address string, amount sdk.Coin) error { + if err := amount.Validate(); err != nil { + return err + } if amount.Denom != k.cbdcDenom { return types.ErrInvalidDenom } From 10929493e479e77d38ed27d8922819733afc27ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Wed, 3 Jun 2026 08:29:06 +0200 Subject: [PATCH 07/17] fix(cbdc): address review feedback on mint/burn module --- app/app.go | 5 +- proto/cbdc/tx.proto | 8 +-- x/cbdc/keeper/burn.go | 43 ++++++++++++ x/cbdc/keeper/keeper.go | 80 ---------------------- x/cbdc/keeper/mint.go | 43 ++++++++++++ x/cbdc/keeper/msg_server.go | 31 +++++++++ x/cbdc/keeper/msg_server_burn.go | 24 ------- x/cbdc/keeper/msg_server_burn_test.go | 19 ++++-- x/cbdc/keeper/msg_server_mint.go | 24 ------- x/cbdc/keeper/msg_server_mint_test.go | 19 ++++-- x/cbdc/keeper/params.go | 5 +- x/cbdc/keeper/query.go | 14 +++- x/cbdc/keeper/query_params.go | 4 +- x/cbdc/module.go | 25 +++++-- x/cbdc/types/codec.go | 4 -- x/cbdc/types/errors.go | 1 + x/cbdc/types/events.go | 5 +- x/cbdc/types/genesis.go | 3 - x/cbdc/types/message_burn.go | 28 ++++++-- x/cbdc/types/message_burn_test.go | 55 +++++++++++++++ x/cbdc/types/message_mint.go | 28 ++++++-- x/cbdc/types/message_mint_test.go | 55 +++++++++++++++ x/cbdc/types/tx.pb.go | 98 +++++++++++++-------------- x/poa/keeper/keeper_test.go | 9 +-- 24 files changed, 404 insertions(+), 226 deletions(-) create mode 100644 x/cbdc/keeper/burn.go create mode 100644 x/cbdc/keeper/mint.go delete mode 100644 x/cbdc/keeper/msg_server_burn.go delete mode 100644 x/cbdc/keeper/msg_server_mint.go create mode 100644 x/cbdc/types/message_burn_test.go create mode 100644 x/cbdc/types/message_mint_test.go diff --git a/app/app.go b/app/app.go index 8d7d99d8..54f4dea9 100644 --- a/app/app.go +++ b/app/app.go @@ -696,7 +696,7 @@ func New( // cbdc app modules poa.NewAppModule(appCodec, app.PoaKeeper, app.BankKeeper, app.StakingKeeper, app.AccountKeeper, app.interfaceRegistry), - cbdc.NewAppModule(appCodec, app.CbdcKeeper, app.BankKeeper, app.AccountKeeper, app.interfaceRegistry), + cbdc.NewAppModule(appCodec, app.CbdcKeeper, app.AccountKeeper, app.interfaceRegistry), ) // BasicModuleManager defines the module BasicManager which is in charge of setting up basic, @@ -750,7 +750,6 @@ func New( govtypes.ModuleName, stakingtypes.ModuleName, poatypes.ModuleName, - cbdctypes.ModuleName, evmtypes.ModuleName, feemarkettypes.ModuleName, erc20types.ModuleName, @@ -1172,6 +1171,8 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(feemarkettypes.ModuleName) paramsKeeper.Subspace(erc20types.ModuleName) + paramsKeeper.Subspace(cbdctypes.ModuleName) + return paramsKeeper } diff --git a/proto/cbdc/tx.proto b/proto/cbdc/tx.proto index ce229263..4b3fa68e 100644 --- a/proto/cbdc/tx.proto +++ b/proto/cbdc/tx.proto @@ -21,9 +21,9 @@ service Msg { // MsgMint defines a message to mint CBDC tokens and send them to an address message MsgMint { - option (cosmos.msg.v1.signer) = "authority"; + option (cosmos.msg.v1.signer) = "owner"; - string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + string owner = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; cosmos.base.v1beta1.Coin amount = 3 [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; @@ -33,9 +33,9 @@ message MsgMintResponse {} // MsgBurn defines a message to burn CBDC tokens from an address message MsgBurn { - option (cosmos.msg.v1.signer) = "authority"; + option (cosmos.msg.v1.signer) = "owner"; - string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + string owner = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; cosmos.base.v1beta1.Coin amount = 3 [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; diff --git a/x/cbdc/keeper/burn.go b/x/cbdc/keeper/burn.go new file mode 100644 index 00000000..47ac9ad5 --- /dev/null +++ b/x/cbdc/keeper/burn.go @@ -0,0 +1,43 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +func (k Keeper) executeBurn(ctx sdk.Context, owner string, address string, amount sdk.Coin) error { + if err := amount.Validate(); err != nil { + return err + } + if amount.Denom != k.cbdcDenom { + return types.ErrInvalidDenom + } + if !amount.IsPositive() { + return types.ErrInvalidAmount + } + + fromAddr, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + + coins := sdk.NewCoins(amount) + if err := k.bk.SendCoinsFromAccountToModule(ctx, fromAddr, types.ModuleName, coins); err != nil { + return err + } + if err := k.bk.BurnCoins(ctx, types.ModuleName, coins); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeBurn, + sdk.NewAttribute(types.AttributeOwner, owner), + sdk.NewAttribute(types.AttributeAddress, fromAddr.String()), + sdk.NewAttribute(types.AttributeAmount, amount.String()), + ), + ) + + return nil +} diff --git a/x/cbdc/keeper/keeper.go b/x/cbdc/keeper/keeper.go index 83d80a2b..b67564b4 100644 --- a/x/cbdc/keeper/keeper.go +++ b/x/cbdc/keeper/keeper.go @@ -11,16 +11,6 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -var _ types.QueryServer = Querier{} - -type Querier struct { - Keeper -} - -func NewQuerier(keeper Keeper) Querier { - return Querier{Keeper: keeper} -} - type ( Keeper struct { cdc codec.Codec @@ -66,73 +56,3 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { func (k Keeper) GetAuthority() string { return k.authority } - -func (k Keeper) ExecuteMint(ctx sdk.Context, address string, amount sdk.Coin) error { - if err := amount.Validate(); err != nil { - return err - } - if amount.Denom != k.cbdcDenom { - return types.ErrInvalidDenom - } - if !amount.IsPositive() { - return types.ErrInvalidAmount - } - - toAddr, err := sdk.AccAddressFromBech32(address) - if err != nil { - return err - } - - coins := sdk.NewCoins(amount) - if err := k.bk.MintCoins(ctx, types.ModuleName, coins); err != nil { - return err - } - if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, toAddr, coins); err != nil { - return err - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeMint, - sdk.NewAttribute(types.AttributeAddress, toAddr.String()), - sdk.NewAttribute(types.AttributeAmount, amount.String()), - ), - ) - - return nil -} - -func (k Keeper) ExecuteBurn(ctx sdk.Context, address string, amount sdk.Coin) error { - if err := amount.Validate(); err != nil { - return err - } - if amount.Denom != k.cbdcDenom { - return types.ErrInvalidDenom - } - if !amount.IsPositive() { - return types.ErrInvalidAmount - } - - fromAddr, err := sdk.AccAddressFromBech32(address) - if err != nil { - return err - } - - coins := sdk.NewCoins(amount) - if err := k.bk.SendCoinsFromAccountToModule(ctx, fromAddr, types.ModuleName, coins); err != nil { - return err - } - if err := k.bk.BurnCoins(ctx, types.ModuleName, coins); err != nil { - return err - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeBurn, - sdk.NewAttribute(types.AttributeAddress, fromAddr.String()), - sdk.NewAttribute(types.AttributeAmount, amount.String()), - ), - ) - - return nil -} diff --git a/x/cbdc/keeper/mint.go b/x/cbdc/keeper/mint.go new file mode 100644 index 00000000..5f60c1a8 --- /dev/null +++ b/x/cbdc/keeper/mint.go @@ -0,0 +1,43 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/peersyst/cbdc-node/x/cbdc/types" +) + +func (k Keeper) executeMint(ctx sdk.Context, owner string, address string, amount sdk.Coin) error { + if err := amount.Validate(); err != nil { + return err + } + if amount.Denom != k.cbdcDenom { + return types.ErrInvalidDenom + } + if !amount.IsPositive() { + return types.ErrInvalidAmount + } + + toAddr, err := sdk.AccAddressFromBech32(address) + if err != nil { + return err + } + + coins := sdk.NewCoins(amount) + if err := k.bk.MintCoins(ctx, types.ModuleName, coins); err != nil { + return err + } + if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, toAddr, coins); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeMint, + sdk.NewAttribute(types.AttributeOwner, owner), + sdk.NewAttribute(types.AttributeAddress, toAddr.String()), + sdk.NewAttribute(types.AttributeAmount, amount.String()), + ), + ) + + return nil +} diff --git a/x/cbdc/keeper/msg_server.go b/x/cbdc/keeper/msg_server.go index ff38f803..1dbc20c7 100644 --- a/x/cbdc/keeper/msg_server.go +++ b/x/cbdc/keeper/msg_server.go @@ -1,6 +1,11 @@ package keeper import ( + "context" + + "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/peersyst/cbdc-node/x/cbdc/types" ) @@ -15,3 +20,29 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer { } var _ types.MsgServer = msgServer{} + +func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMintResponse, error) { + if k.authority != msg.Owner { + return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", k.authority, msg.Owner) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.executeMint(ctx, msg.Owner, msg.Address, msg.Amount); err != nil { + return nil, err + } + + return &types.MsgMintResponse{}, nil +} + +func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnResponse, error) { + if k.authority != msg.Owner { + return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", k.authority, msg.Owner) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.executeBurn(ctx, msg.Owner, msg.Address, msg.Amount); err != nil { + return nil, err + } + + return &types.MsgBurnResponse{}, nil +} diff --git a/x/cbdc/keeper/msg_server_burn.go b/x/cbdc/keeper/msg_server_burn.go deleted file mode 100644 index 88031005..00000000 --- a/x/cbdc/keeper/msg_server_burn.go +++ /dev/null @@ -1,24 +0,0 @@ -package keeper - -import ( - "context" - - "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" - gov "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/peersyst/cbdc-node/x/cbdc/types" -) - -func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnResponse, error) { - if k.authority != msg.Authority { - return nil, errors.Wrapf(gov.ErrInvalidSigner, "expected %s got %s", k.authority, msg.Authority) - } - - ctx := sdk.UnwrapSDKContext(goCtx) - if err := k.ExecuteBurn(ctx, msg.Address, msg.Amount); err != nil { - return nil, err - } - - return &types.MsgBurnResponse{}, nil -} diff --git a/x/cbdc/keeper/msg_server_burn_test.go b/x/cbdc/keeper/msg_server_burn_test.go index 9f16fd97..303950d7 100644 --- a/x/cbdc/keeper/msg_server_burn_test.go +++ b/x/cbdc/keeper/msg_server_burn_test.go @@ -6,7 +6,6 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/golang/mock/gomock" "github.com/peersyst/cbdc-node/x/cbdc/testutil" "github.com/peersyst/cbdc-node/x/cbdc/types" @@ -29,7 +28,7 @@ func TestMsgServer_Burn(t *testing.T) { //nolint:dupl authority: "invalidauthority", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), - expectedErr: govtypes.ErrInvalidSigner, + expectedErr: types.ErrUnauthorized, }, { name: "should fail - invalid address", @@ -45,6 +44,14 @@ func TestMsgServer_Burn(t *testing.T) { //nolint:dupl amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), expectedErr: types.ErrInvalidAmount, }, + { + // struct literal bypasses sdk.NewCoin, which panics on negatives + name: "should fail - negative amount", + authority: cbdcKeeper.GetAuthority(), + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.Coin{Denom: testCBDCDenom, Amount: math.NewInt(-100)}, + expectedErr: errors.New("negative coin amount"), + }, { name: "should fail - wrong denom", authority: cbdcKeeper.GetAuthority(), @@ -63,9 +70,9 @@ func TestMsgServer_Burn(t *testing.T) { //nolint:dupl for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { msg := &types.MsgBurn{ - Authority: tc.authority, - Address: tc.address, - Amount: tc.amount, + Owner: tc.authority, + Address: tc.address, + Amount: tc.amount, } _, err := msgServer.Burn(ctx, msg) @@ -143,7 +150,7 @@ func TestKeeper_ExecuteBurn(t *testing.T) { t.Run(tc.name, func(t *testing.T) { keeper, ctx := setupCbdcKeeper(t, tc.bankMocks) - err := keeper.ExecuteBurn(ctx, tc.address, tc.amount) + err := keeper.executeBurn(ctx, keeper.GetAuthority(), tc.address, tc.amount) if tc.expectedError != nil { require.Error(t, err) require.Contains(t, err.Error(), tc.expectedError.Error()) diff --git a/x/cbdc/keeper/msg_server_mint.go b/x/cbdc/keeper/msg_server_mint.go deleted file mode 100644 index 3ad31437..00000000 --- a/x/cbdc/keeper/msg_server_mint.go +++ /dev/null @@ -1,24 +0,0 @@ -package keeper - -import ( - "context" - - "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" - gov "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/peersyst/cbdc-node/x/cbdc/types" -) - -func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMintResponse, error) { - if k.authority != msg.Authority { - return nil, errors.Wrapf(gov.ErrInvalidSigner, "expected %s got %s", k.authority, msg.Authority) - } - - ctx := sdk.UnwrapSDKContext(goCtx) - if err := k.ExecuteMint(ctx, msg.Address, msg.Amount); err != nil { - return nil, err - } - - return &types.MsgMintResponse{}, nil -} diff --git a/x/cbdc/keeper/msg_server_mint_test.go b/x/cbdc/keeper/msg_server_mint_test.go index 26053f39..1d19a171 100644 --- a/x/cbdc/keeper/msg_server_mint_test.go +++ b/x/cbdc/keeper/msg_server_mint_test.go @@ -6,7 +6,6 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/golang/mock/gomock" "github.com/peersyst/cbdc-node/x/cbdc/testutil" "github.com/peersyst/cbdc-node/x/cbdc/types" @@ -29,7 +28,7 @@ func TestMsgServer_Mint(t *testing.T) { //nolint:dupl authority: "invalidauthority", address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), - expectedErr: govtypes.ErrInvalidSigner, + expectedErr: types.ErrUnauthorized, }, { name: "should fail - invalid recipient address", @@ -45,6 +44,14 @@ func TestMsgServer_Mint(t *testing.T) { //nolint:dupl amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), expectedErr: types.ErrInvalidAmount, }, + { + // struct literal bypasses sdk.NewCoin, which panics on negatives + name: "should fail - negative amount", + authority: cbdcKeeper.GetAuthority(), + address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + amount: sdk.Coin{Denom: testCBDCDenom, Amount: math.NewInt(-100)}, + expectedErr: errors.New("negative coin amount"), + }, { name: "should fail - wrong denom", authority: cbdcKeeper.GetAuthority(), @@ -63,9 +70,9 @@ func TestMsgServer_Mint(t *testing.T) { //nolint:dupl for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { msg := &types.MsgMint{ - Authority: tc.authority, - Address: tc.address, - Amount: tc.amount, + Owner: tc.authority, + Address: tc.address, + Amount: tc.amount, } _, err := msgServer.Mint(ctx, msg) @@ -143,7 +150,7 @@ func TestKeeper_ExecuteMint(t *testing.T) { t.Run(tc.name, func(t *testing.T) { keeper, ctx := setupCbdcKeeper(t, tc.bankMocks) - err := keeper.ExecuteMint(ctx, tc.address, tc.amount) + err := keeper.executeMint(ctx, keeper.GetAuthority(), tc.address, tc.amount) if tc.expectedError != nil { require.Error(t, err) require.Contains(t, err.Error(), tc.expectedError.Error()) diff --git a/x/cbdc/keeper/params.go b/x/cbdc/keeper/params.go index 50227db6..52ec7454 100644 --- a/x/cbdc/keeper/params.go +++ b/x/cbdc/keeper/params.go @@ -6,8 +6,9 @@ import ( ) // GetParams get all parameters as types.Params -func (k Keeper) GetParams(_ sdk.Context) types.Params { - return types.NewParams() +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + k.paramstore.GetParamSet(ctx, ¶ms) + return params } // SetParams set the params diff --git a/x/cbdc/keeper/query.go b/x/cbdc/keeper/query.go index 97c94714..c49b1743 100644 --- a/x/cbdc/keeper/query.go +++ b/x/cbdc/keeper/query.go @@ -4,4 +4,16 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -var _ types.QueryServer = Keeper{} +var _ types.QueryServer = Querier{} + +// Querier is the gRPC query server for the cbdc module. It holds the keeper as +// an unexported field (rather than embedding it) so the read API stays +// decoupled from the keeper's state-mutating methods. +type Querier struct { + k Keeper +} + +// NewQuerier returns a Querier for the provided Keeper. +func NewQuerier(k Keeper) Querier { + return Querier{k: k} +} diff --git a/x/cbdc/keeper/query_params.go b/x/cbdc/keeper/query_params.go index f36f5a2a..f56172a8 100644 --- a/x/cbdc/keeper/query_params.go +++ b/x/cbdc/keeper/query_params.go @@ -9,11 +9,11 @@ import ( "google.golang.org/grpc/status" ) -func (k Keeper) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { +func (q Querier) Params(goCtx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } ctx := sdk.UnwrapSDKContext(goCtx) - return &types.QueryParamsResponse{Params: k.GetParams(ctx)}, nil + return &types.QueryParamsResponse{Params: q.k.GetParams(ctx)}, nil } diff --git a/x/cbdc/module.go b/x/cbdc/module.go index 68743e64..700f218d 100644 --- a/x/cbdc/module.go +++ b/x/cbdc/module.go @@ -12,6 +12,7 @@ import ( cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/peersyst/cbdc-node/x/cbdc/keeper" "github.com/peersyst/cbdc-node/x/cbdc/types" @@ -73,7 +74,6 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *r type AppModule struct { AppModuleBasic keeper keeper.Keeper - bk types.BankKeeper ak types.AccountKeeper registry cdctypes.InterfaceRegistry } @@ -81,14 +81,12 @@ type AppModule struct { func NewAppModule( cdc codec.Codec, keeper keeper.Keeper, - bk types.BankKeeper, ak types.AccountKeeper, registry cdctypes.InterfaceRegistry, ) AppModule { return AppModule{ AppModuleBasic: NewAppModuleBasic(cdc), keeper: keeper, - bk: bk, ak: ak, registry: registry, } @@ -96,10 +94,27 @@ func NewAppModule( func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) - types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(am.keeper)) } -func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + ir.RegisterRoute(types.ModuleName, "module-account-exists", am.moduleAccountInvariant()) +} + +// moduleAccountInvariant checks that the cbdc module account still exists. +// If it were ever wiped, MintCoins/BurnCoins would fail at runtime, so this +// halts the chain instead. The account is created in InitGenesis. +func (am AppModule) moduleAccountInvariant() sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + addr := authtypes.NewModuleAddress(types.ModuleName) + broken := am.ak.GetAccount(ctx, addr) == nil + return sdk.FormatInvariant( + types.ModuleName, + "module-account-exists", + fmt.Sprintf("cbdc module account %s does not exist\n", addr), + ), broken + } +} func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) { var genState types.GenesisState diff --git a/x/cbdc/types/codec.go b/x/cbdc/types/codec.go index f7506e6c..4873c469 100644 --- a/x/cbdc/types/codec.go +++ b/x/cbdc/types/codec.go @@ -5,7 +5,6 @@ import ( cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" ) func RegisterCodec(cdc *codec.LegacyAmino) { @@ -20,9 +19,6 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgBurn{}, ) - registry.RegisterImplementations( - (*govtypes.Content)(nil), - ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/cbdc/types/errors.go b/x/cbdc/types/errors.go index 0c4b914f..87c52b8a 100644 --- a/x/cbdc/types/errors.go +++ b/x/cbdc/types/errors.go @@ -10,4 +10,5 @@ import ( var ( ErrInvalidAmount = sdkerrors.Register(ModuleName, 1, "amount must be positive") ErrInvalidDenom = sdkerrors.Register(ModuleName, 2, "amount denom must match the configured CBDC denom") + ErrUnauthorized = sdkerrors.Register(ModuleName, 3, "unauthorized signer") ) diff --git a/x/cbdc/types/events.go b/x/cbdc/types/events.go index b96bfedc..908f9b7e 100644 --- a/x/cbdc/types/events.go +++ b/x/cbdc/types/events.go @@ -1,8 +1,9 @@ package types const ( - EventTypeMint = "mint" - EventTypeBurn = "burn" + EventTypeMint = "cbdc_mint" + EventTypeBurn = "cbdc_burn" + AttributeOwner = "owner" AttributeAddress = "address" AttributeAmount = "amount" ) diff --git a/x/cbdc/types/genesis.go b/x/cbdc/types/genesis.go index bdb9f415..9d633ecd 100644 --- a/x/cbdc/types/genesis.go +++ b/x/cbdc/types/genesis.go @@ -1,8 +1,5 @@ package types -// DefaultIndex is the default global index -const DefaultIndex uint64 = 1 - // DefaultGenesis returns the default genesis state func DefaultGenesis() *GenesisState { return &GenesisState{ diff --git a/x/cbdc/types/message_burn.go b/x/cbdc/types/message_burn.go index 32071bc5..e06e68b0 100644 --- a/x/cbdc/types/message_burn.go +++ b/x/cbdc/types/message_burn.go @@ -1,15 +1,35 @@ package types import ( + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" ) var _ sdk.Msg = &MsgBurn{} -func NewMsgBurn(authority string, address string, amount sdk.Coin) *MsgBurn { +func NewMsgBurn(owner string, address string, amount sdk.Coin) *MsgBurn { return &MsgBurn{ - Authority: authority, - Address: address, - Amount: amount, + Owner: owner, + Address: address, + Amount: amount, } } + +// ValidateBasic performs stateless validation of the message. The amount denom +// is only checked for well-formedness here; the match against the configured +// CBDC denom is stateful and stays in the keeper. +func (msg *MsgBurn) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Owner); err != nil { + return errorsmod.Wrapf(err, "invalid owner address (%s)", msg.Owner) + } + if _, err := sdk.AccAddressFromBech32(msg.Address); err != nil { + return errorsmod.Wrapf(err, "invalid address (%s)", msg.Address) + } + if err := msg.Amount.Validate(); err != nil { + return err + } + if !msg.Amount.IsPositive() { + return ErrInvalidAmount + } + return nil +} diff --git a/x/cbdc/types/message_burn_test.go b/x/cbdc/types/message_burn_test.go new file mode 100644 index 00000000..82c8d29b --- /dev/null +++ b/x/cbdc/types/message_burn_test.go @@ -0,0 +1,55 @@ +package types + +import ( + "testing" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/peersyst/cbdc-node/testutil/sample" + "github.com/stretchr/testify/require" +) + +func TestMsgBurn_ValidateBasic(t *testing.T) { //nolint:dupl + tt := []struct { + name string + msg MsgBurn + expectErr bool + }{ + { + name: "valid", + msg: MsgBurn{Owner: sample.AccAddress(), Address: sample.AccAddress(), Amount: sdk.NewCoin("acbdc", math.NewInt(100))}, + }, + { + name: "invalid owner", + msg: MsgBurn{Owner: "invalid", Address: sample.AccAddress(), Amount: sdk.NewCoin("acbdc", math.NewInt(100))}, + expectErr: true, + }, + { + name: "invalid address", + msg: MsgBurn{Owner: sample.AccAddress(), Address: "invalid", Amount: sdk.NewCoin("acbdc", math.NewInt(100))}, + expectErr: true, + }, + { + name: "zero amount", + msg: MsgBurn{Owner: sample.AccAddress(), Address: sample.AccAddress(), Amount: sdk.NewCoin("acbdc", math.NewInt(0))}, + expectErr: true, + }, + { + // struct literal bypasses sdk.NewCoin, which panics on negatives + name: "negative amount", + msg: MsgBurn{Owner: sample.AccAddress(), Address: sample.AccAddress(), Amount: sdk.Coin{Denom: "acbdc", Amount: math.NewInt(-100)}}, + expectErr: true, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/cbdc/types/message_mint.go b/x/cbdc/types/message_mint.go index 6e342e71..65a6f6e6 100644 --- a/x/cbdc/types/message_mint.go +++ b/x/cbdc/types/message_mint.go @@ -1,15 +1,35 @@ package types import ( + errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" ) var _ sdk.Msg = &MsgMint{} -func NewMsgMint(authority string, address string, amount sdk.Coin) *MsgMint { +func NewMsgMint(owner string, address string, amount sdk.Coin) *MsgMint { return &MsgMint{ - Authority: authority, - Address: address, - Amount: amount, + Owner: owner, + Address: address, + Amount: amount, } } + +// ValidateBasic performs stateless validation of the message. The amount denom +// is only checked for well-formedness here; the match against the configured +// CBDC denom is stateful and stays in the keeper. +func (msg *MsgMint) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Owner); err != nil { + return errorsmod.Wrapf(err, "invalid owner address (%s)", msg.Owner) + } + if _, err := sdk.AccAddressFromBech32(msg.Address); err != nil { + return errorsmod.Wrapf(err, "invalid recipient address (%s)", msg.Address) + } + if err := msg.Amount.Validate(); err != nil { + return err + } + if !msg.Amount.IsPositive() { + return ErrInvalidAmount + } + return nil +} diff --git a/x/cbdc/types/message_mint_test.go b/x/cbdc/types/message_mint_test.go new file mode 100644 index 00000000..9c4ee83b --- /dev/null +++ b/x/cbdc/types/message_mint_test.go @@ -0,0 +1,55 @@ +package types + +import ( + "testing" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/peersyst/cbdc-node/testutil/sample" + "github.com/stretchr/testify/require" +) + +func TestMsgMint_ValidateBasic(t *testing.T) { //nolint:dupl + tt := []struct { + name string + msg MsgMint + expectErr bool + }{ + { + name: "valid", + msg: MsgMint{Owner: sample.AccAddress(), Address: sample.AccAddress(), Amount: sdk.NewCoin("acbdc", math.NewInt(100))}, + }, + { + name: "invalid owner", + msg: MsgMint{Owner: "invalid", Address: sample.AccAddress(), Amount: sdk.NewCoin("acbdc", math.NewInt(100))}, + expectErr: true, + }, + { + name: "invalid recipient address", + msg: MsgMint{Owner: sample.AccAddress(), Address: "invalid", Amount: sdk.NewCoin("acbdc", math.NewInt(100))}, + expectErr: true, + }, + { + name: "zero amount", + msg: MsgMint{Owner: sample.AccAddress(), Address: sample.AccAddress(), Amount: sdk.NewCoin("acbdc", math.NewInt(0))}, + expectErr: true, + }, + { + // struct literal bypasses sdk.NewCoin, which panics on negatives + name: "negative amount", + msg: MsgMint{Owner: sample.AccAddress(), Address: sample.AccAddress(), Amount: sdk.Coin{Denom: "acbdc", Amount: math.NewInt(-100)}}, + expectErr: true, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if tc.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/cbdc/types/tx.pb.go b/x/cbdc/types/tx.pb.go index ac1ebda2..0cb8e1ab 100644 --- a/x/cbdc/types/tx.pb.go +++ b/x/cbdc/types/tx.pb.go @@ -34,9 +34,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // MsgMint defines a message to mint CBDC tokens and send them to an address type MsgMint struct { - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` - Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` + Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` } func (m *MsgMint) Reset() { *m = MsgMint{} } @@ -72,9 +72,9 @@ func (m *MsgMint) XXX_DiscardUnknown() { var xxx_messageInfo_MsgMint proto.InternalMessageInfo -func (m *MsgMint) GetAuthority() string { +func (m *MsgMint) GetOwner() string { if m != nil { - return m.Authority + return m.Owner } return "" } @@ -132,9 +132,9 @@ var xxx_messageInfo_MsgMintResponse proto.InternalMessageInfo // MsgBurn defines a message to burn CBDC tokens from an address type MsgBurn struct { - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` - Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` + Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Amount types.Coin `protobuf:"bytes,3,opt,name=amount,proto3" json:"amount"` } func (m *MsgBurn) Reset() { *m = MsgBurn{} } @@ -170,9 +170,9 @@ func (m *MsgBurn) XXX_DiscardUnknown() { var xxx_messageInfo_MsgBurn proto.InternalMessageInfo -func (m *MsgBurn) GetAuthority() string { +func (m *MsgBurn) GetOwner() string { if m != nil { - return m.Authority + return m.Owner } return "" } @@ -238,31 +238,31 @@ func init() { func init() { proto.RegisterFile("cbdc/tx.proto", fileDescriptor_870101f11584fe74) } var fileDescriptor_870101f11584fe74 = []byte{ - // 380 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x52, 0x3f, 0x4f, 0xfa, 0x40, - 0x18, 0xee, 0xfd, 0xe0, 0x07, 0xe1, 0x0c, 0x1a, 0x1a, 0x8c, 0xa5, 0x43, 0x25, 0x4c, 0x84, 0x48, - 0x2f, 0x60, 0xe2, 0x60, 0x5c, 0xac, 0xae, 0x2c, 0xb8, 0xb9, 0x98, 0xfe, 0xb9, 0x94, 0x0e, 0xbd, - 0x6b, 0x7a, 0x57, 0x02, 0x9b, 0xf1, 0x13, 0xf8, 0x31, 0x1c, 0x19, 0xfc, 0x06, 0x2e, 0x8c, 0xc4, - 0xc9, 0xc9, 0x18, 0x18, 0xf8, 0x1a, 0xe6, 0x7a, 0xd7, 0x80, 0x93, 0xb3, 0x4b, 0xdb, 0xe7, 0x7d, - 0x9e, 0xb7, 0xef, 0xf3, 0xdc, 0xbd, 0xb0, 0xee, 0x7b, 0x81, 0x8f, 0xf8, 0xcc, 0x4e, 0x52, 0xca, - 0xa9, 0x5e, 0x16, 0xd0, 0x6c, 0x86, 0x34, 0xa4, 0x79, 0x01, 0x89, 0x2f, 0xc9, 0x99, 0x2d, 0x9f, - 0xb2, 0x98, 0xb2, 0x07, 0x49, 0x48, 0xa0, 0xa8, 0x13, 0x89, 0x50, 0xcc, 0x42, 0x34, 0x1d, 0x88, - 0x97, 0x22, 0x2c, 0x45, 0x78, 0x2e, 0xc3, 0x68, 0x3a, 0xf0, 0x30, 0x77, 0x07, 0xc8, 0xa7, 0x11, - 0x51, 0x7c, 0xc3, 0x8d, 0x23, 0x42, 0x51, 0xfe, 0x94, 0xa5, 0xce, 0x1b, 0x80, 0xd5, 0x11, 0x0b, - 0x47, 0x11, 0xe1, 0xfa, 0x05, 0xac, 0xb9, 0x19, 0x9f, 0xd0, 0x34, 0xe2, 0x73, 0x03, 0xb4, 0x41, - 0xb7, 0xe6, 0x18, 0xef, 0xaf, 0xfd, 0xa6, 0x1a, 0x7e, 0x1d, 0x04, 0x29, 0x66, 0xec, 0x8e, 0xa7, - 0x11, 0x09, 0xc7, 0x3b, 0xa9, 0x3e, 0x84, 0x55, 0x57, 0x72, 0xc6, 0xbf, 0x5f, 0xba, 0x0a, 0xa1, - 0x7e, 0x05, 0x2b, 0x6e, 0x4c, 0x33, 0xc2, 0x8d, 0x52, 0x1b, 0x74, 0x0f, 0x86, 0x2d, 0x5b, 0xe9, - 0x85, 0x77, 0x5b, 0x79, 0xb7, 0x6f, 0x68, 0x44, 0x9c, 0xda, 0xf2, 0xf3, 0x54, 0x7b, 0xd9, 0x2e, - 0x7a, 0x60, 0xac, 0x7a, 0x2e, 0x0f, 0x9f, 0xb6, 0x8b, 0xde, 0xce, 0x41, 0xa7, 0x01, 0x8f, 0x54, - 0x88, 0x31, 0x66, 0x09, 0x25, 0x0c, 0x17, 0xc1, 0x9c, 0x2c, 0x25, 0x7f, 0x3e, 0x98, 0x08, 0x51, - 0x04, 0x1b, 0x4e, 0x60, 0x69, 0xc4, 0x42, 0xfd, 0x0c, 0x96, 0xf3, 0x4b, 0xab, 0xdb, 0x62, 0x89, - 0x6c, 0x15, 0xdf, 0x3c, 0xfe, 0x01, 0x8b, 0x26, 0xa1, 0xce, 0x4f, 0x62, 0xa7, 0x16, 0x70, 0x4f, - 0xbd, 0x3f, 0xc2, 0xfc, 0xff, 0x28, 0x4c, 0x39, 0xb7, 0xcb, 0xb5, 0x05, 0x56, 0x6b, 0x0b, 0x7c, - 0xad, 0x2d, 0xf0, 0xbc, 0xb1, 0xb4, 0xd5, 0xc6, 0xd2, 0x3e, 0x36, 0x96, 0x76, 0xdf, 0x0b, 0x23, - 0x3e, 0xc9, 0x3c, 0xdb, 0xa7, 0x31, 0x4a, 0x30, 0x4e, 0xd9, 0x9c, 0x71, 0x24, 0x7e, 0xd5, 0x27, - 0x34, 0xc0, 0x68, 0x86, 0xe4, 0x9e, 0xcf, 0x13, 0xcc, 0xbc, 0x4a, 0xbe, 0x68, 0xe7, 0xdf, 0x01, - 0x00, 0x00, 0xff, 0xff, 0x54, 0x85, 0xf9, 0xf9, 0xfc, 0x02, 0x00, 0x00, + // 374 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x52, 0xbd, 0x4e, 0xeb, 0x30, + 0x18, 0x8d, 0x6f, 0xff, 0x54, 0x5f, 0x55, 0x57, 0x8d, 0x7a, 0x45, 0x9a, 0x21, 0x54, 0x9d, 0xaa, + 0x8a, 0xda, 0x6a, 0xd9, 0x10, 0x0b, 0x81, 0xb5, 0x4b, 0xd9, 0x58, 0x50, 0x7e, 0xac, 0x34, 0x43, + 0xec, 0x28, 0x76, 0x4b, 0xbb, 0x21, 0x9e, 0x80, 0xc7, 0x60, 0xec, 0x80, 0xc4, 0x2b, 0x74, 0xac, + 0x98, 0x98, 0x10, 0x6a, 0x87, 0xbe, 0x06, 0x72, 0xec, 0x88, 0x32, 0x31, 0xb3, 0x24, 0x3e, 0xdf, + 0x39, 0x9f, 0xbf, 0x73, 0xe4, 0x0f, 0x36, 0x02, 0x3f, 0x0c, 0xb0, 0x58, 0xa0, 0x34, 0x63, 0x82, + 0x99, 0x65, 0x09, 0xed, 0x56, 0xc4, 0x22, 0x96, 0x17, 0xb0, 0x3c, 0x29, 0xce, 0x6e, 0x07, 0x8c, + 0x27, 0x8c, 0xdf, 0x2a, 0x42, 0x01, 0x4d, 0x1d, 0x29, 0x84, 0x13, 0x1e, 0xe1, 0xf9, 0x50, 0xfe, + 0x34, 0xe1, 0x68, 0xc2, 0xf7, 0x38, 0xc1, 0xf3, 0xa1, 0x4f, 0x84, 0x37, 0xc4, 0x01, 0x8b, 0xa9, + 0xe6, 0x9b, 0x5e, 0x12, 0x53, 0x86, 0xf3, 0xaf, 0x2a, 0x75, 0x5f, 0x00, 0xac, 0x8d, 0x79, 0x34, + 0x8e, 0xa9, 0x30, 0x11, 0xac, 0xb0, 0x3b, 0x4a, 0x32, 0x0b, 0x74, 0x40, 0xaf, 0xee, 0x5a, 0xaf, + 0xcf, 0x83, 0x96, 0x1e, 0x7c, 0x11, 0x86, 0x19, 0xe1, 0xfc, 0x5a, 0x64, 0x31, 0x8d, 0x26, 0x4a, + 0x66, 0x8e, 0x60, 0xcd, 0x53, 0x75, 0xeb, 0xcf, 0x0f, 0x1d, 0x85, 0xd0, 0x3c, 0x87, 0x55, 0x2f, + 0x61, 0x33, 0x2a, 0xac, 0x52, 0x07, 0xf4, 0xfe, 0x8e, 0xda, 0x48, 0xeb, 0xa5, 0x67, 0xa4, 0x3d, + 0xa3, 0x4b, 0x16, 0x53, 0xb7, 0xbe, 0x7e, 0x3f, 0x36, 0x9e, 0xf6, 0xab, 0x3e, 0x98, 0xe8, 0x9e, + 0x33, 0xf8, 0xb0, 0x5f, 0xf5, 0xd5, 0xf4, 0x6e, 0x13, 0xfe, 0xd3, 0xc6, 0x27, 0x84, 0xa7, 0x8c, + 0x72, 0x52, 0x84, 0x71, 0x67, 0x19, 0xfd, 0x95, 0x61, 0xa4, 0xf1, 0x22, 0xcc, 0x68, 0x0a, 0x4b, + 0x63, 0x1e, 0x99, 0x27, 0xb0, 0x9c, 0x3f, 0x4e, 0x03, 0xc9, 0x65, 0x41, 0x3a, 0xb2, 0xfd, 0xff, + 0x1b, 0x2c, 0x9a, 0xa4, 0x3a, 0x4f, 0xff, 0xa5, 0x96, 0xf0, 0x40, 0x7d, 0x38, 0xc2, 0xae, 0xdc, + 0x4b, 0x43, 0xee, 0xd5, 0x7a, 0xeb, 0x80, 0xcd, 0xd6, 0x01, 0x1f, 0x5b, 0x07, 0x3c, 0xee, 0x1c, + 0x63, 0xb3, 0x73, 0x8c, 0xb7, 0x9d, 0x63, 0xdc, 0xf4, 0xa3, 0x58, 0x4c, 0x67, 0x3e, 0x0a, 0x58, + 0x82, 0x53, 0x42, 0x32, 0xbe, 0xe4, 0x02, 0xcb, 0xab, 0x06, 0x94, 0x85, 0x04, 0x2f, 0xb0, 0xda, + 0xe7, 0x65, 0x4a, 0xb8, 0x5f, 0xcd, 0x17, 0xea, 0xf4, 0x33, 0x00, 0x00, 0xff, 0xff, 0xc3, 0xea, + 0xd2, 0x3d, 0xe4, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -422,10 +422,10 @@ func (m *MsgMint) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - if len(m.Authority) > 0 { - i -= len(m.Authority) - copy(dAtA[i:], m.Authority) - i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + if len(m.Owner) > 0 { + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) + i = encodeVarintTx(dAtA, i, uint64(len(m.Owner))) i-- dAtA[i] = 0xa } @@ -492,10 +492,10 @@ func (m *MsgBurn) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - if len(m.Authority) > 0 { - i -= len(m.Authority) - copy(dAtA[i:], m.Authority) - i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + if len(m.Owner) > 0 { + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) + i = encodeVarintTx(dAtA, i, uint64(len(m.Owner))) i-- dAtA[i] = 0xa } @@ -542,7 +542,7 @@ func (m *MsgMint) Size() (n int) { } var l int _ = l - l = len(m.Authority) + l = len(m.Owner) if l > 0 { n += 1 + l + sovTx(uint64(l)) } @@ -570,7 +570,7 @@ func (m *MsgBurn) Size() (n int) { } var l int _ = l - l = len(m.Authority) + l = len(m.Owner) if l > 0 { n += 1 + l + sovTx(uint64(l)) } @@ -629,7 +629,7 @@ func (m *MsgMint) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -657,7 +657,7 @@ func (m *MsgMint) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Authority = string(dAtA[iNdEx:postIndex]) + m.Owner = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { @@ -826,7 +826,7 @@ func (m *MsgBurn) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -854,7 +854,7 @@ func (m *MsgBurn) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Authority = string(dAtA[iNdEx:postIndex]) + m.Owner = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { diff --git a/x/poa/keeper/keeper_test.go b/x/poa/keeper/keeper_test.go index d1796c2f..501e1334 100644 --- a/x/poa/keeper/keeper_test.go +++ b/x/poa/keeper/keeper_test.go @@ -43,7 +43,8 @@ func poaKeeperTestSetup(t *testing.T) (*Keeper, sdk.Context) { }).AnyTimes() bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + bankKeeper.EXPECT().BurnCoins(ctx, stakingtypes.BondedPoolName, gomock.Any()).Return(nil).AnyTimes() + bankKeeper.EXPECT().BurnCoins(ctx, stakingtypes.NotBondedPoolName, gomock.Any()).Return(nil).AnyTimes() bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() } @@ -559,7 +560,7 @@ func TestKeeper_ExecuteRemoveValidator(t *testing.T) { ) }, bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { - bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(errors.New("bank keeper burn coins error")) + bankKeeper.EXPECT().BurnCoins(ctx, stakingtypes.BondedPoolName, gomock.Any()).Return(errors.New("bank keeper burn coins error")) }, }, //nolint:dupl @@ -590,7 +591,7 @@ func TestKeeper_ExecuteRemoveValidator(t *testing.T) { ) }, bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { - bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(errors.New("bank keeper burn coins error")) + bankKeeper.EXPECT().BurnCoins(ctx, stakingtypes.NotBondedPoolName, gomock.Any()).Return(errors.New("bank keeper burn coins error")) }, }, { @@ -651,7 +652,7 @@ func TestKeeper_ExecuteRemoveValidator(t *testing.T) { ) }, bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { - bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(nil) + bankKeeper.EXPECT().BurnCoins(ctx, stakingtypes.BondedPoolName, gomock.Any()).Return(nil) }, }, } From 46ae86f220ea9c09076bd9fb5a16ac2db2d61c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Wed, 3 Jun 2026 14:50:41 +0200 Subject: [PATCH 08/17] fix: lint error --- x/cbdc/types/message_burn_test.go | 4 ++-- x/cbdc/types/message_mint_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x/cbdc/types/message_burn_test.go b/x/cbdc/types/message_burn_test.go index 82c8d29b..b06cbf5f 100644 --- a/x/cbdc/types/message_burn_test.go +++ b/x/cbdc/types/message_burn_test.go @@ -1,4 +1,4 @@ -package types +package types //nolint:dupl // mint/burn tests are structurally similar by design import ( "testing" @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestMsgBurn_ValidateBasic(t *testing.T) { //nolint:dupl +func TestMsgBurn_ValidateBasic(t *testing.T) { tt := []struct { name string msg MsgBurn diff --git a/x/cbdc/types/message_mint_test.go b/x/cbdc/types/message_mint_test.go index 9c4ee83b..d8f9cc61 100644 --- a/x/cbdc/types/message_mint_test.go +++ b/x/cbdc/types/message_mint_test.go @@ -1,4 +1,4 @@ -package types +package types //nolint:dupl // mint/burn tests are structurally similar by design import ( "testing" @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestMsgMint_ValidateBasic(t *testing.T) { //nolint:dupl +func TestMsgMint_ValidateBasic(t *testing.T) { tt := []struct { name string msg MsgMint From 74dd1d0d01bee9c5cd6630753c1f4c1873bb019f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 10:00:09 +0200 Subject: [PATCH 09/17] fix: change address type for burn and mint --- x/cbdc/keeper/burn.go | 11 +++-------- x/cbdc/keeper/mint.go | 11 +++-------- x/cbdc/keeper/msg_server.go | 14 ++++++++++++-- x/cbdc/keeper/msg_server_burn_test.go | 21 ++++++++------------- x/cbdc/keeper/msg_server_mint_test.go | 21 ++++++++------------- 5 files changed, 34 insertions(+), 44 deletions(-) diff --git a/x/cbdc/keeper/burn.go b/x/cbdc/keeper/burn.go index 47ac9ad5..47cd9628 100644 --- a/x/cbdc/keeper/burn.go +++ b/x/cbdc/keeper/burn.go @@ -6,7 +6,7 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -func (k Keeper) executeBurn(ctx sdk.Context, owner string, address string, amount sdk.Coin) error { +func (k Keeper) executeBurn(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { if err := amount.Validate(); err != nil { return err } @@ -17,13 +17,8 @@ func (k Keeper) executeBurn(ctx sdk.Context, owner string, address string, amoun return types.ErrInvalidAmount } - fromAddr, err := sdk.AccAddressFromBech32(address) - if err != nil { - return err - } - coins := sdk.NewCoins(amount) - if err := k.bk.SendCoinsFromAccountToModule(ctx, fromAddr, types.ModuleName, coins); err != nil { + if err := k.bk.SendCoinsFromAccountToModule(ctx, address, types.ModuleName, coins); err != nil { return err } if err := k.bk.BurnCoins(ctx, types.ModuleName, coins); err != nil { @@ -34,7 +29,7 @@ func (k Keeper) executeBurn(ctx sdk.Context, owner string, address string, amoun sdk.NewEvent( types.EventTypeBurn, sdk.NewAttribute(types.AttributeOwner, owner), - sdk.NewAttribute(types.AttributeAddress, fromAddr.String()), + sdk.NewAttribute(types.AttributeAddress, address.String()), sdk.NewAttribute(types.AttributeAmount, amount.String()), ), ) diff --git a/x/cbdc/keeper/mint.go b/x/cbdc/keeper/mint.go index 5f60c1a8..bbe4b221 100644 --- a/x/cbdc/keeper/mint.go +++ b/x/cbdc/keeper/mint.go @@ -6,7 +6,7 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -func (k Keeper) executeMint(ctx sdk.Context, owner string, address string, amount sdk.Coin) error { +func (k Keeper) executeMint(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { if err := amount.Validate(); err != nil { return err } @@ -17,16 +17,11 @@ func (k Keeper) executeMint(ctx sdk.Context, owner string, address string, amoun return types.ErrInvalidAmount } - toAddr, err := sdk.AccAddressFromBech32(address) - if err != nil { - return err - } - coins := sdk.NewCoins(amount) if err := k.bk.MintCoins(ctx, types.ModuleName, coins); err != nil { return err } - if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, toAddr, coins); err != nil { + if err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, address, coins); err != nil { return err } @@ -34,7 +29,7 @@ func (k Keeper) executeMint(ctx sdk.Context, owner string, address string, amoun sdk.NewEvent( types.EventTypeMint, sdk.NewAttribute(types.AttributeOwner, owner), - sdk.NewAttribute(types.AttributeAddress, toAddr.String()), + sdk.NewAttribute(types.AttributeAddress, address.String()), sdk.NewAttribute(types.AttributeAmount, amount.String()), ), ) diff --git a/x/cbdc/keeper/msg_server.go b/x/cbdc/keeper/msg_server.go index 1dbc20c7..f270aac5 100644 --- a/x/cbdc/keeper/msg_server.go +++ b/x/cbdc/keeper/msg_server.go @@ -26,8 +26,13 @@ func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMi return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", k.authority, msg.Owner) } + address, err := sdk.AccAddressFromBech32(msg.Address) + if err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(goCtx) - if err := k.executeMint(ctx, msg.Owner, msg.Address, msg.Amount); err != nil { + if err := k.executeMint(ctx, msg.Owner, address, msg.Amount); err != nil { return nil, err } @@ -39,8 +44,13 @@ func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBu return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", k.authority, msg.Owner) } + address, err := sdk.AccAddressFromBech32(msg.Address) + if err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(goCtx) - if err := k.executeBurn(ctx, msg.Owner, msg.Address, msg.Amount); err != nil { + if err := k.executeBurn(ctx, msg.Owner, address, msg.Amount); err != nil { return nil, err } diff --git a/x/cbdc/keeper/msg_server_burn_test.go b/x/cbdc/keeper/msg_server_burn_test.go index 303950d7..e46dd0d9 100644 --- a/x/cbdc/keeper/msg_server_burn_test.go +++ b/x/cbdc/keeper/msg_server_burn_test.go @@ -87,37 +87,32 @@ func TestMsgServer_Burn(t *testing.T) { //nolint:dupl } func TestKeeper_ExecuteBurn(t *testing.T) { + address := sdk.MustAccAddressFromBech32("ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp") + tt := []struct { name string - address string + address sdk.AccAddress amount sdk.Coin bankMocks func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) expectedError error }{ { name: "should fail - zero amount", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: types.ErrInvalidAmount, }, { name: "should fail - wrong denom", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin("axrp", math.NewInt(100)), bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: types.ErrInvalidDenom, }, - { - name: "should fail - invalid address", - address: "invalidaddress", - amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), - bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, - expectedError: errors.New("decoding bech32 failed"), - }, { name: "should fail - SendCoinsFromAccountToModule returns error", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("bank send error")) @@ -126,7 +121,7 @@ func TestKeeper_ExecuteBurn(t *testing.T) { }, { name: "should fail - BurnCoins returns error", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { bankKeeper.EXPECT().SendCoinsFromAccountToModule(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) @@ -136,7 +131,7 @@ func TestKeeper_ExecuteBurn(t *testing.T) { }, { name: "should pass", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { coins := sdk.NewCoins(sdk.NewCoin(testCBDCDenom, math.NewInt(100))) diff --git a/x/cbdc/keeper/msg_server_mint_test.go b/x/cbdc/keeper/msg_server_mint_test.go index 1d19a171..089b1a39 100644 --- a/x/cbdc/keeper/msg_server_mint_test.go +++ b/x/cbdc/keeper/msg_server_mint_test.go @@ -87,37 +87,32 @@ func TestMsgServer_Mint(t *testing.T) { //nolint:dupl } func TestKeeper_ExecuteMint(t *testing.T) { + address := sdk.MustAccAddressFromBech32("ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp") + tt := []struct { name string - address string + address sdk.AccAddress amount sdk.Coin bankMocks func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) expectedError error }{ { name: "should fail - zero amount", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: types.ErrInvalidAmount, }, { name: "should fail - wrong denom", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin("axrp", math.NewInt(100)), bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: types.ErrInvalidDenom, }, - { - name: "should fail - invalid address", - address: "invalidaddress", - amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), - bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, - expectedError: errors.New("decoding bech32 failed"), - }, { name: "should fail - MintCoins returns error", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(errors.New("bank mint error")) @@ -126,7 +121,7 @@ func TestKeeper_ExecuteMint(t *testing.T) { }, { name: "should fail - SendCoinsFromModuleToAccount returns error", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(nil) @@ -136,7 +131,7 @@ func TestKeeper_ExecuteMint(t *testing.T) { }, { name: "should pass", - address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", + address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { coins := sdk.NewCoins(sdk.NewCoin(testCBDCDenom, math.NewInt(100))) From 059a5ce657e40382d8cfa7be806974649885d6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 10:16:55 +0200 Subject: [PATCH 10/17] refactor: rename mint and burn operations --- x/cbdc/keeper/burn.go | 2 +- x/cbdc/keeper/mint.go | 2 +- x/cbdc/keeper/msg_server.go | 4 ++-- x/cbdc/keeper/msg_server_burn_test.go | 4 ++-- x/cbdc/keeper/msg_server_mint_test.go | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/x/cbdc/keeper/burn.go b/x/cbdc/keeper/burn.go index 47cd9628..a982d8c5 100644 --- a/x/cbdc/keeper/burn.go +++ b/x/cbdc/keeper/burn.go @@ -6,7 +6,7 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -func (k Keeper) executeBurn(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { +func (k Keeper) BurnCoins(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { if err := amount.Validate(); err != nil { return err } diff --git a/x/cbdc/keeper/mint.go b/x/cbdc/keeper/mint.go index bbe4b221..40958826 100644 --- a/x/cbdc/keeper/mint.go +++ b/x/cbdc/keeper/mint.go @@ -6,7 +6,7 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -func (k Keeper) executeMint(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { +func (k Keeper) MintCoins(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { if err := amount.Validate(); err != nil { return err } diff --git a/x/cbdc/keeper/msg_server.go b/x/cbdc/keeper/msg_server.go index f270aac5..8ac04424 100644 --- a/x/cbdc/keeper/msg_server.go +++ b/x/cbdc/keeper/msg_server.go @@ -32,7 +32,7 @@ func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMi } ctx := sdk.UnwrapSDKContext(goCtx) - if err := k.executeMint(ctx, msg.Owner, address, msg.Amount); err != nil { + if err := k.MintCoins(ctx, msg.Owner, address, msg.Amount); err != nil { return nil, err } @@ -50,7 +50,7 @@ func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBu } ctx := sdk.UnwrapSDKContext(goCtx) - if err := k.executeBurn(ctx, msg.Owner, address, msg.Amount); err != nil { + if err := k.BurnCoins(ctx, msg.Owner, address, msg.Amount); err != nil { return nil, err } diff --git a/x/cbdc/keeper/msg_server_burn_test.go b/x/cbdc/keeper/msg_server_burn_test.go index e46dd0d9..362e08d3 100644 --- a/x/cbdc/keeper/msg_server_burn_test.go +++ b/x/cbdc/keeper/msg_server_burn_test.go @@ -86,7 +86,7 @@ func TestMsgServer_Burn(t *testing.T) { //nolint:dupl } } -func TestKeeper_ExecuteBurn(t *testing.T) { +func TestKeeper_BurnCoins(t *testing.T) { address := sdk.MustAccAddressFromBech32("ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp") tt := []struct { @@ -145,7 +145,7 @@ func TestKeeper_ExecuteBurn(t *testing.T) { t.Run(tc.name, func(t *testing.T) { keeper, ctx := setupCbdcKeeper(t, tc.bankMocks) - err := keeper.executeBurn(ctx, keeper.GetAuthority(), tc.address, tc.amount) + err := keeper.BurnCoins(ctx, keeper.GetAuthority(), tc.address, tc.amount) if tc.expectedError != nil { require.Error(t, err) require.Contains(t, err.Error(), tc.expectedError.Error()) diff --git a/x/cbdc/keeper/msg_server_mint_test.go b/x/cbdc/keeper/msg_server_mint_test.go index 089b1a39..7989beba 100644 --- a/x/cbdc/keeper/msg_server_mint_test.go +++ b/x/cbdc/keeper/msg_server_mint_test.go @@ -86,7 +86,7 @@ func TestMsgServer_Mint(t *testing.T) { //nolint:dupl } } -func TestKeeper_ExecuteMint(t *testing.T) { +func TestKeeper_MintCoins(t *testing.T) { address := sdk.MustAccAddressFromBech32("ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp") tt := []struct { @@ -145,7 +145,7 @@ func TestKeeper_ExecuteMint(t *testing.T) { t.Run(tc.name, func(t *testing.T) { keeper, ctx := setupCbdcKeeper(t, tc.bankMocks) - err := keeper.executeMint(ctx, keeper.GetAuthority(), tc.address, tc.amount) + err := keeper.MintCoins(ctx, keeper.GetAuthority(), tc.address, tc.amount) if tc.expectedError != nil { require.Error(t, err) require.Contains(t, err.Error(), tc.expectedError.Error()) From 2c5bd07588504c4769904dcbc60c794523699369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 10:47:32 +0200 Subject: [PATCH 11/17] feat(cbdc): make mint/burn owner an on-chain rotatable param --- proto/cbdc/params.proto | 8 +- proto/cbdc/tx.proto | 17 + x/cbdc/keeper/common_test.go | 8 +- x/cbdc/keeper/keeper.go | 2 +- x/cbdc/keeper/msg_server.go | 29 +- x/cbdc/keeper/msg_server_burn_test.go | 12 +- x/cbdc/keeper/msg_server_mint_test.go | 12 +- .../keeper/msg_server_update_params_test.go | 64 +++ x/cbdc/types/codec.go | 4 + x/cbdc/types/errors.go | 1 + x/cbdc/types/message_update_params.go | 23 + x/cbdc/types/params.go | 30 +- x/cbdc/types/params.pb.go | 72 ++- x/cbdc/types/tx.pb.go | 441 +++++++++++++++++- 14 files changed, 665 insertions(+), 58 deletions(-) create mode 100644 x/cbdc/keeper/msg_server_update_params_test.go create mode 100644 x/cbdc/types/message_update_params.go diff --git a/proto/cbdc/params.proto b/proto/cbdc/params.proto index 20a1eb91..d3571f26 100644 --- a/proto/cbdc/params.proto +++ b/proto/cbdc/params.proto @@ -1,7 +1,13 @@ syntax = "proto3"; package cbdc; +import "cosmos_proto/cosmos.proto"; + option go_package = "github.com/peersyst/cbdc-node/x/cbdc/types"; // Params defines the parameters for the module. -message Params {} +message Params { + // owner is the address allowed to mint/burn CBDC tokens. It can be rotated + // on-chain via a governance MsgUpdateParams proposal. + string owner = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; +} diff --git a/proto/cbdc/tx.proto b/proto/cbdc/tx.proto index 4b3fa68e..3fd25a0b 100644 --- a/proto/cbdc/tx.proto +++ b/proto/cbdc/tx.proto @@ -6,6 +6,7 @@ import "cosmos_proto/cosmos.proto"; import "cosmos/msg/v1/msg.proto"; import "cosmos/base/v1beta1/coin.proto"; import "amino/amino.proto"; +import "cbdc/params.proto"; option go_package = "github.com/peersyst/cbdc-node/x/cbdc/types"; @@ -17,6 +18,8 @@ service Msg { rpc Mint(MsgMint) returns (MsgMintResponse); // Burns CBDC tokens from an address rpc Burn(MsgBurn) returns (MsgBurnResponse); + // Updates the module params. Only the governance authority can call it. + rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); } // MsgMint defines a message to mint CBDC tokens and send them to an address @@ -42,3 +45,17 @@ message MsgBurn { } // MsgBurnResponse defines the response for burning CBDC tokens message MsgBurnResponse {} + +// MsgUpdateParams defines a message to update the module params +message MsgUpdateParams { + option (cosmos.msg.v1.signer) = "authority"; + + // authority is the address that controls the module params (defaults to the + // gov module account) + string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + // params defines the module parameters to update + Params params = 2 + [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; +} +// MsgUpdateParamsResponse defines the response for updating the module params +message MsgUpdateParamsResponse {} diff --git a/x/cbdc/keeper/common_test.go b/x/cbdc/keeper/common_test.go index 707d02d5..8cbebc91 100644 --- a/x/cbdc/keeper/common_test.go +++ b/x/cbdc/keeper/common_test.go @@ -20,6 +20,10 @@ const ( accountAddressPrefix = "ethm" bip44CoinType = 60 testCBDCDenom = "acbdc" + // testGovAuthority is the params updater (gov module account stand-in). + testGovAuthority = "ethm1wunfhl05vc8r8xxnnp8gt62wa54r6y52pg03zq" + // testOwner is the mint/burn owner stored in params. + testOwner = "ethm1j2arnn0sajut2w8gnaxumrlkkem2c9vz5sfj6k" ) func setupSdkConfig() { @@ -61,10 +65,10 @@ func getMockedCbdcKeeper(_ *testing.T, key *storetypes.KVStoreKey, tsKey *storet encCfg.Codec, paramtypes.NewSubspace(encCfg.Codec, encCfg.Amino, key, tsKey, "cbdc"), bankKeeper, - "ethm1wunfhl05vc8r8xxnnp8gt62wa54r6y52pg03zq", + testGovAuthority, testCBDCDenom, ) - cbdcKeeper.SetParams(ctx, types.DefaultParams()) + cbdcKeeper.SetParams(ctx, types.NewParams(testOwner)) return cbdcKeeper } diff --git a/x/cbdc/keeper/keeper.go b/x/cbdc/keeper/keeper.go index b67564b4..cbf97a6d 100644 --- a/x/cbdc/keeper/keeper.go +++ b/x/cbdc/keeper/keeper.go @@ -15,7 +15,7 @@ type ( Keeper struct { cdc codec.Codec paramstore paramtypes.Subspace - authority string // the address capable of executing a cbdc mint/burn. Usually the gov module account + authority string // the address capable of updating module params (e.g. rotating the mint/burn owner). Usually the gov module account bk types.BankKeeper cbdcDenom string // the only denom that can be minted/burned via this module } diff --git a/x/cbdc/keeper/msg_server.go b/x/cbdc/keeper/msg_server.go index 8ac04424..031a80c0 100644 --- a/x/cbdc/keeper/msg_server.go +++ b/x/cbdc/keeper/msg_server.go @@ -22,8 +22,10 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer { var _ types.MsgServer = msgServer{} func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMintResponse, error) { - if k.authority != msg.Owner { - return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", k.authority, msg.Owner) + ctx := sdk.UnwrapSDKContext(goCtx) + + if owner := k.GetParams(ctx).Owner; owner != msg.Owner { + return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", owner, msg.Owner) } address, err := sdk.AccAddressFromBech32(msg.Address) @@ -31,7 +33,6 @@ func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMi return nil, err } - ctx := sdk.UnwrapSDKContext(goCtx) if err := k.MintCoins(ctx, msg.Owner, address, msg.Amount); err != nil { return nil, err } @@ -40,8 +41,10 @@ func (k msgServer) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMi } func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnResponse, error) { - if k.authority != msg.Owner { - return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", k.authority, msg.Owner) + ctx := sdk.UnwrapSDKContext(goCtx) + + if owner := k.GetParams(ctx).Owner; owner != msg.Owner { + return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", owner, msg.Owner) } address, err := sdk.AccAddressFromBech32(msg.Address) @@ -49,10 +52,24 @@ func (k msgServer) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBu return nil, err } - ctx := sdk.UnwrapSDKContext(goCtx) if err := k.BurnCoins(ctx, msg.Owner, address, msg.Amount); err != nil { return nil, err } return &types.MsgBurnResponse{}, nil } + +func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + if k.authority != msg.Authority { + return nil, errors.Wrapf(types.ErrUnauthorized, "expected %s got %s", k.authority, msg.Authority) + } + + if err := msg.Params.Validate(); err != nil { + return nil, err + } + + ctx := sdk.UnwrapSDKContext(goCtx) + k.SetParams(ctx, msg.Params) + + return &types.MsgUpdateParamsResponse{}, nil +} diff --git a/x/cbdc/keeper/msg_server_burn_test.go b/x/cbdc/keeper/msg_server_burn_test.go index 362e08d3..2ad53416 100644 --- a/x/cbdc/keeper/msg_server_burn_test.go +++ b/x/cbdc/keeper/msg_server_burn_test.go @@ -32,14 +32,14 @@ func TestMsgServer_Burn(t *testing.T) { //nolint:dupl }, { name: "should fail - invalid address", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "invalidaddress", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), expectedErr: errors.New("decoding bech32 failed"), }, { name: "should fail - zero amount", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), expectedErr: types.ErrInvalidAmount, @@ -47,21 +47,21 @@ func TestMsgServer_Burn(t *testing.T) { //nolint:dupl { // struct literal bypasses sdk.NewCoin, which panics on negatives name: "should fail - negative amount", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.Coin{Denom: testCBDCDenom, Amount: math.NewInt(-100)}, expectedErr: errors.New("negative coin amount"), }, { name: "should fail - wrong denom", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin("axrp", math.NewInt(100)), expectedErr: types.ErrInvalidDenom, }, { name: "should pass", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), }, @@ -145,7 +145,7 @@ func TestKeeper_BurnCoins(t *testing.T) { t.Run(tc.name, func(t *testing.T) { keeper, ctx := setupCbdcKeeper(t, tc.bankMocks) - err := keeper.BurnCoins(ctx, keeper.GetAuthority(), tc.address, tc.amount) + err := keeper.BurnCoins(ctx, testOwner, tc.address, tc.amount) if tc.expectedError != nil { require.Error(t, err) require.Contains(t, err.Error(), tc.expectedError.Error()) diff --git a/x/cbdc/keeper/msg_server_mint_test.go b/x/cbdc/keeper/msg_server_mint_test.go index 7989beba..3138f35c 100644 --- a/x/cbdc/keeper/msg_server_mint_test.go +++ b/x/cbdc/keeper/msg_server_mint_test.go @@ -32,14 +32,14 @@ func TestMsgServer_Mint(t *testing.T) { //nolint:dupl }, { name: "should fail - invalid recipient address", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "invalidaddress", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), expectedErr: errors.New("decoding bech32 failed"), }, { name: "should fail - zero amount", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(0)), expectedErr: types.ErrInvalidAmount, @@ -47,21 +47,21 @@ func TestMsgServer_Mint(t *testing.T) { //nolint:dupl { // struct literal bypasses sdk.NewCoin, which panics on negatives name: "should fail - negative amount", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.Coin{Denom: testCBDCDenom, Amount: math.NewInt(-100)}, expectedErr: errors.New("negative coin amount"), }, { name: "should fail - wrong denom", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin("axrp", math.NewInt(100)), expectedErr: types.ErrInvalidDenom, }, { name: "should pass", - authority: cbdcKeeper.GetAuthority(), + authority: testOwner, address: "ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp", amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), }, @@ -145,7 +145,7 @@ func TestKeeper_MintCoins(t *testing.T) { t.Run(tc.name, func(t *testing.T) { keeper, ctx := setupCbdcKeeper(t, tc.bankMocks) - err := keeper.MintCoins(ctx, keeper.GetAuthority(), tc.address, tc.amount) + err := keeper.MintCoins(ctx, testOwner, tc.address, tc.amount) if tc.expectedError != nil { require.Error(t, err) require.Contains(t, err.Error(), tc.expectedError.Error()) diff --git a/x/cbdc/keeper/msg_server_update_params_test.go b/x/cbdc/keeper/msg_server_update_params_test.go new file mode 100644 index 00000000..b86cf4a5 --- /dev/null +++ b/x/cbdc/keeper/msg_server_update_params_test.go @@ -0,0 +1,64 @@ +package keeper + +import ( + "testing" + + "github.com/peersyst/cbdc-node/x/cbdc/types" + "github.com/stretchr/testify/require" +) + +func TestMsgServer_UpdateParams(t *testing.T) { + newOwner := "ethm1ef8ep2et20ja5s6r99tafld67kph72h7e0577u" + + tt := []struct { + name string + authority string + params types.Params + expectedErr error + }{ + { + name: "should fail - unauthorized authority", + authority: testOwner, + params: types.NewParams(newOwner), + expectedErr: types.ErrUnauthorized, + }, + { + name: "should fail - invalid owner", + authority: testGovAuthority, + params: types.NewParams("invalidowner"), + expectedErr: types.ErrInvalidOwner, + }, + { + name: "should pass - rotate owner", + authority: testGovAuthority, + params: types.NewParams(newOwner), + }, + { + name: "should pass - clear owner", + authority: testGovAuthority, + params: types.NewParams(""), + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + cbdcKeeper, ctx := cbdcKeeperTestSetup(t) + msgServer := NewMsgServerImpl(*cbdcKeeper) + + msg := &types.MsgUpdateParams{ + Authority: tc.authority, + Params: tc.params, + } + + _, err := msgServer.UpdateParams(ctx, msg) + if tc.expectedErr != nil { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedErr.Error()) + return + } + + require.NoError(t, err) + require.Equal(t, tc.params.Owner, cbdcKeeper.GetParams(ctx).Owner) + }) + } +} diff --git a/x/cbdc/types/codec.go b/x/cbdc/types/codec.go index 4873c469..3e2d58a5 100644 --- a/x/cbdc/types/codec.go +++ b/x/cbdc/types/codec.go @@ -10,6 +10,7 @@ import ( func RegisterCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgMint{}, "cbdc/Mint", nil) cdc.RegisterConcrete(&MsgBurn{}, "cbdc/Burn", nil) + cdc.RegisterConcrete(&MsgUpdateParams{}, "cbdc/UpdateParams", nil) } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { @@ -19,6 +20,9 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgBurn{}, ) + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgUpdateParams{}, + ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/cbdc/types/errors.go b/x/cbdc/types/errors.go index 87c52b8a..5d462eec 100644 --- a/x/cbdc/types/errors.go +++ b/x/cbdc/types/errors.go @@ -11,4 +11,5 @@ var ( ErrInvalidAmount = sdkerrors.Register(ModuleName, 1, "amount must be positive") ErrInvalidDenom = sdkerrors.Register(ModuleName, 2, "amount denom must match the configured CBDC denom") ErrUnauthorized = sdkerrors.Register(ModuleName, 3, "unauthorized signer") + ErrInvalidOwner = sdkerrors.Register(ModuleName, 4, "invalid owner address") ) diff --git a/x/cbdc/types/message_update_params.go b/x/cbdc/types/message_update_params.go new file mode 100644 index 00000000..6c965203 --- /dev/null +++ b/x/cbdc/types/message_update_params.go @@ -0,0 +1,23 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ sdk.Msg = &MsgUpdateParams{} + +func NewMsgUpdateParams(authority string, params Params) *MsgUpdateParams { + return &MsgUpdateParams{ + Authority: authority, + Params: params, + } +} + +// ValidateBasic performs stateless validation of the message. +func (msg *MsgUpdateParams) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return errorsmod.Wrapf(err, "invalid authority address (%s)", msg.Authority) + } + return msg.Params.Validate() +} diff --git a/x/cbdc/types/params.go b/x/cbdc/types/params.go index e562ff79..fd6ee165 100644 --- a/x/cbdc/types/params.go +++ b/x/cbdc/types/params.go @@ -1,32 +1,54 @@ package types import ( + sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) var _ paramtypes.ParamSet = (*Params)(nil) +// KeyOwner is the param store key for the mint/burn owner address. +var KeyOwner = []byte("Owner") + // ParamKeyTable the param key table for launch module func ParamKeyTable() paramtypes.KeyTable { return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) } // NewParams creates a new Params instance -func NewParams() Params { - return Params{} +func NewParams(owner string) Params { + return Params{Owner: owner} } // DefaultParams returns a default set of parameters func DefaultParams() Params { - return NewParams() + return NewParams("") } // ParamSetPairs get the params.ParamSet func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { - return paramtypes.ParamSetPairs{} + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair(KeyOwner, &p.Owner, validateOwner), + } } // Validate validates the set of params func (p *Params) Validate() error { + return validateOwner(p.Owner) +} + +// validateOwner accepts an empty owner (mint/burn stays disabled until gov sets +// one) or a well-formed bech32 address. +func validateOwner(i interface{}) error { + owner, ok := i.(string) + if !ok { + return ErrInvalidOwner.Wrapf("invalid parameter type: %T", i) + } + if owner == "" { + return nil + } + if _, err := sdk.AccAddressFromBech32(owner); err != nil { + return ErrInvalidOwner.Wrapf("invalid owner address (%s): %s", owner, err) + } return nil } diff --git a/x/cbdc/types/params.pb.go b/x/cbdc/types/params.pb.go index 2338f8cd..981e4018 100644 --- a/x/cbdc/types/params.pb.go +++ b/x/cbdc/types/params.pb.go @@ -5,6 +5,7 @@ package types import ( fmt "fmt" + _ "github.com/cosmos/cosmos-proto" proto "github.com/cosmos/gogoproto/proto" io "io" math "math" @@ -24,6 +25,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Params defines the parameters for the module. type Params struct { + // owner is the address allowed to mint/burn CBDC tokens. It can be rotated + // on-chain via a governance MsgUpdateParams proposal. + Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -59,6 +63,13 @@ func (m *Params) XXX_DiscardUnknown() { var xxx_messageInfo_Params proto.InternalMessageInfo +func (m *Params) GetOwner() string { + if m != nil { + return m.Owner + } + return "" +} + func init() { proto.RegisterType((*Params)(nil), "cbdc.Params") } @@ -66,15 +77,19 @@ func init() { func init() { proto.RegisterFile("cbdc/params.proto", fileDescriptor_a383b166b3425dd0) } var fileDescriptor_a383b166b3425dd0 = []byte{ - // 125 bytes of a gzipped FileDescriptorProto + // 181 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4c, 0x4e, 0x4a, 0x49, 0xd6, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, - 0x09, 0x29, 0x71, 0x70, 0xb1, 0x05, 0x80, 0x45, 0x9d, 0x5c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, - 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, - 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x2b, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, - 0xbf, 0x20, 0x35, 0xb5, 0xa8, 0xb8, 0xb2, 0xb8, 0x44, 0x1f, 0xa4, 0x5b, 0x37, 0x2f, 0x3f, 0x25, - 0x55, 0xbf, 0x02, 0xcc, 0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x1b, 0x6e, 0x0c, - 0x08, 0x00, 0x00, 0xff, 0xff, 0x33, 0x29, 0xdc, 0x86, 0x71, 0x00, 0x00, 0x00, + 0x09, 0x49, 0x49, 0x26, 0xe7, 0x17, 0xe7, 0xe6, 0x17, 0xc7, 0x83, 0xc5, 0xf4, 0x21, 0x1c, 0x88, + 0x02, 0x25, 0x0b, 0x2e, 0xb6, 0x00, 0xb0, 0x06, 0x21, 0x3d, 0x2e, 0xd6, 0xfc, 0xf2, 0xbc, 0xd4, + 0x22, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x4e, 0x27, 0x89, 0x4b, 0x5b, 0x74, 0x45, 0xa0, 0x4a, 0x1d, + 0x53, 0x52, 0x8a, 0x52, 0x8b, 0x8b, 0x83, 0x4b, 0x8a, 0x32, 0xf3, 0xd2, 0x83, 0x20, 0xca, 0x9c, + 0x5c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, + 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x2b, 0x3d, 0xb3, 0x24, + 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0xbf, 0x20, 0x35, 0xb5, 0xa8, 0xb8, 0xb2, 0xb8, 0x44, + 0x1f, 0xe4, 0x10, 0xdd, 0xbc, 0xfc, 0x94, 0x54, 0xfd, 0x0a, 0x30, 0x5b, 0xbf, 0xa4, 0xb2, 0x20, + 0xb5, 0x38, 0x89, 0x0d, 0xec, 0x0c, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd2, 0xf2, 0x07, + 0xbe, 0xbc, 0x00, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -97,6 +112,13 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Owner) > 0 { + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) + i = encodeVarintParams(dAtA, i, uint64(len(m.Owner))) + i-- + dAtA[i] = 0xa + } return len(dAtA) - i, nil } @@ -117,6 +139,10 @@ func (m *Params) Size() (n int) { } var l int _ = l + l = len(m.Owner) + if l > 0 { + n += 1 + l + sovParams(uint64(l)) + } return n } @@ -155,6 +181,38 @@ func (m *Params) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Owner = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/cbdc/types/tx.pb.go b/x/cbdc/types/tx.pb.go index 0cb8e1ab..e1bd5b83 100644 --- a/x/cbdc/types/tx.pb.go +++ b/x/cbdc/types/tx.pb.go @@ -228,41 +228,142 @@ func (m *MsgBurnResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgBurnResponse proto.InternalMessageInfo +// MsgUpdateParams defines a message to update the module params +type MsgUpdateParams struct { + // authority is the address that controls the module params (defaults to the + // gov module account) + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // params defines the module parameters to update + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` +} + +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_870101f11584fe74, []int{4} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +func (m *MsgUpdateParams) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgUpdateParams) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// MsgUpdateParamsResponse defines the response for updating the module params +type MsgUpdateParamsResponse struct { +} + +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_870101f11584fe74, []int{5} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgMint)(nil), "cbdc.MsgMint") proto.RegisterType((*MsgMintResponse)(nil), "cbdc.MsgMintResponse") proto.RegisterType((*MsgBurn)(nil), "cbdc.MsgBurn") proto.RegisterType((*MsgBurnResponse)(nil), "cbdc.MsgBurnResponse") + proto.RegisterType((*MsgUpdateParams)(nil), "cbdc.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "cbdc.MsgUpdateParamsResponse") } func init() { proto.RegisterFile("cbdc/tx.proto", fileDescriptor_870101f11584fe74) } var fileDescriptor_870101f11584fe74 = []byte{ - // 374 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x52, 0xbd, 0x4e, 0xeb, 0x30, - 0x18, 0x8d, 0x6f, 0xff, 0x54, 0x5f, 0x55, 0x57, 0x8d, 0x7a, 0x45, 0x9a, 0x21, 0x54, 0x9d, 0xaa, - 0x8a, 0xda, 0x6a, 0xd9, 0x10, 0x0b, 0x81, 0xb5, 0x4b, 0xd9, 0x58, 0x50, 0x7e, 0xac, 0x34, 0x43, - 0xec, 0x28, 0x76, 0x4b, 0xbb, 0x21, 0x9e, 0x80, 0xc7, 0x60, 0xec, 0x80, 0xc4, 0x2b, 0x74, 0xac, - 0x98, 0x98, 0x10, 0x6a, 0x87, 0xbe, 0x06, 0x72, 0xec, 0x88, 0x32, 0x31, 0xb3, 0x24, 0x3e, 0xdf, - 0x39, 0x9f, 0xbf, 0x73, 0xe4, 0x0f, 0x36, 0x02, 0x3f, 0x0c, 0xb0, 0x58, 0xa0, 0x34, 0x63, 0x82, - 0x99, 0x65, 0x09, 0xed, 0x56, 0xc4, 0x22, 0x96, 0x17, 0xb0, 0x3c, 0x29, 0xce, 0x6e, 0x07, 0x8c, - 0x27, 0x8c, 0xdf, 0x2a, 0x42, 0x01, 0x4d, 0x1d, 0x29, 0x84, 0x13, 0x1e, 0xe1, 0xf9, 0x50, 0xfe, - 0x34, 0xe1, 0x68, 0xc2, 0xf7, 0x38, 0xc1, 0xf3, 0xa1, 0x4f, 0x84, 0x37, 0xc4, 0x01, 0x8b, 0xa9, - 0xe6, 0x9b, 0x5e, 0x12, 0x53, 0x86, 0xf3, 0xaf, 0x2a, 0x75, 0x5f, 0x00, 0xac, 0x8d, 0x79, 0x34, - 0x8e, 0xa9, 0x30, 0x11, 0xac, 0xb0, 0x3b, 0x4a, 0x32, 0x0b, 0x74, 0x40, 0xaf, 0xee, 0x5a, 0xaf, - 0xcf, 0x83, 0x96, 0x1e, 0x7c, 0x11, 0x86, 0x19, 0xe1, 0xfc, 0x5a, 0x64, 0x31, 0x8d, 0x26, 0x4a, - 0x66, 0x8e, 0x60, 0xcd, 0x53, 0x75, 0xeb, 0xcf, 0x0f, 0x1d, 0x85, 0xd0, 0x3c, 0x87, 0x55, 0x2f, - 0x61, 0x33, 0x2a, 0xac, 0x52, 0x07, 0xf4, 0xfe, 0x8e, 0xda, 0x48, 0xeb, 0xa5, 0x67, 0xa4, 0x3d, - 0xa3, 0x4b, 0x16, 0x53, 0xb7, 0xbe, 0x7e, 0x3f, 0x36, 0x9e, 0xf6, 0xab, 0x3e, 0x98, 0xe8, 0x9e, - 0x33, 0xf8, 0xb0, 0x5f, 0xf5, 0xd5, 0xf4, 0x6e, 0x13, 0xfe, 0xd3, 0xc6, 0x27, 0x84, 0xa7, 0x8c, - 0x72, 0x52, 0x84, 0x71, 0x67, 0x19, 0xfd, 0x95, 0x61, 0xa4, 0xf1, 0x22, 0xcc, 0x68, 0x0a, 0x4b, - 0x63, 0x1e, 0x99, 0x27, 0xb0, 0x9c, 0x3f, 0x4e, 0x03, 0xc9, 0x65, 0x41, 0x3a, 0xb2, 0xfd, 0xff, - 0x1b, 0x2c, 0x9a, 0xa4, 0x3a, 0x4f, 0xff, 0xa5, 0x96, 0xf0, 0x40, 0x7d, 0x38, 0xc2, 0xae, 0xdc, - 0x4b, 0x43, 0xee, 0xd5, 0x7a, 0xeb, 0x80, 0xcd, 0xd6, 0x01, 0x1f, 0x5b, 0x07, 0x3c, 0xee, 0x1c, - 0x63, 0xb3, 0x73, 0x8c, 0xb7, 0x9d, 0x63, 0xdc, 0xf4, 0xa3, 0x58, 0x4c, 0x67, 0x3e, 0x0a, 0x58, - 0x82, 0x53, 0x42, 0x32, 0xbe, 0xe4, 0x02, 0xcb, 0xab, 0x06, 0x94, 0x85, 0x04, 0x2f, 0xb0, 0xda, - 0xe7, 0x65, 0x4a, 0xb8, 0x5f, 0xcd, 0x17, 0xea, 0xf4, 0x33, 0x00, 0x00, 0xff, 0xff, 0xc3, 0xea, - 0xd2, 0x3d, 0xe4, 0x02, 0x00, 0x00, + // 465 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x53, 0x3f, 0x6f, 0xd4, 0x30, + 0x1c, 0x3d, 0xd3, 0xf6, 0xaa, 0x73, 0x5b, 0x50, 0xad, 0xa2, 0xde, 0x45, 0x22, 0x54, 0x37, 0x55, + 0x27, 0x6a, 0xeb, 0x82, 0xc4, 0x50, 0xb1, 0x10, 0xba, 0x9e, 0x84, 0x0e, 0xb1, 0xb0, 0x20, 0x27, + 0xb1, 0xd2, 0x0c, 0xb1, 0x23, 0xdb, 0x29, 0xbd, 0x0d, 0x31, 0x32, 0xf1, 0x31, 0x98, 0x50, 0x07, + 0x24, 0xbe, 0x42, 0xc7, 0x8a, 0x89, 0x09, 0xa1, 0xbb, 0xa1, 0x5f, 0x03, 0xf9, 0x4f, 0xc8, 0x1d, + 0x42, 0xba, 0xb9, 0x4b, 0x92, 0xdf, 0xef, 0x3d, 0xbf, 0xbc, 0xe7, 0x9f, 0x0d, 0xf7, 0xd2, 0x24, + 0x4b, 0x89, 0xbe, 0xc4, 0x95, 0x14, 0x5a, 0xa0, 0x4d, 0x53, 0x06, 0x07, 0xb9, 0xc8, 0x85, 0x6d, + 0x10, 0xf3, 0xe5, 0xb0, 0x60, 0x90, 0x0a, 0x55, 0x0a, 0xf5, 0xce, 0x01, 0xae, 0xf0, 0xd0, 0xa1, + 0xab, 0x48, 0xa9, 0x72, 0x72, 0x31, 0x36, 0x2f, 0x0f, 0x84, 0x1e, 0x48, 0xa8, 0x62, 0xe4, 0x62, + 0x9c, 0x30, 0x4d, 0xc7, 0x24, 0x15, 0x05, 0xf7, 0xf8, 0x3e, 0x2d, 0x0b, 0x2e, 0x88, 0x7d, 0x36, + 0x2d, 0xeb, 0xa8, 0xa2, 0x92, 0x96, 0x5e, 0x7e, 0xf8, 0x1d, 0xc0, 0xed, 0x89, 0xca, 0x27, 0x05, + 0xd7, 0x08, 0xc3, 0x2d, 0xf1, 0x9e, 0x33, 0xd9, 0x07, 0x47, 0xe0, 0xb8, 0x17, 0xf7, 0x7f, 0x7c, + 0x3b, 0x39, 0xf0, 0x5e, 0x5e, 0x64, 0x99, 0x64, 0x4a, 0xbd, 0xd6, 0xb2, 0xe0, 0xf9, 0xd4, 0xd1, + 0x50, 0x04, 0xb7, 0xa9, 0xeb, 0xf7, 0xef, 0xad, 0x59, 0xd1, 0x10, 0xd1, 0x73, 0xd8, 0xa5, 0xa5, + 0xa8, 0xb9, 0xee, 0x6f, 0x1c, 0x81, 0xe3, 0x9d, 0x68, 0x80, 0x3d, 0xdf, 0xc4, 0xc0, 0x3e, 0x06, + 0x7e, 0x29, 0x0a, 0x1e, 0xf7, 0xae, 0x7f, 0x3d, 0xee, 0x7c, 0xb9, 0xbd, 0x1a, 0x81, 0xa9, 0x5f, + 0x73, 0x0a, 0x3f, 0xde, 0x5e, 0x8d, 0xdc, 0xdf, 0x87, 0xfb, 0xf0, 0x81, 0x37, 0x3e, 0x65, 0xaa, + 0x12, 0x5c, 0xb1, 0x26, 0x4c, 0x5c, 0x4b, 0x7e, 0x27, 0xc3, 0x18, 0xe3, 0x7f, 0xc3, 0x7c, 0x02, + 0xb6, 0xf7, 0xa6, 0xca, 0xa8, 0x66, 0xaf, 0xec, 0xcc, 0xd0, 0x33, 0xd8, 0xa3, 0xb5, 0x3e, 0x17, + 0xb2, 0xd0, 0xb3, 0xb5, 0xc1, 0x5a, 0x2a, 0x22, 0xb0, 0xeb, 0xa6, 0x6e, 0xb3, 0xed, 0x44, 0xbb, + 0xd8, 0x9c, 0x04, 0xec, 0x54, 0x57, 0xbc, 0x39, 0xda, 0xe9, 0x7d, 0xe3, 0xad, 0x15, 0x18, 0x0e, + 0xe0, 0xe1, 0x3f, 0x5e, 0x1a, 0x9f, 0xd1, 0x57, 0x00, 0x37, 0x26, 0x2a, 0x47, 0x4f, 0xe0, 0xa6, + 0x3d, 0x45, 0x7b, 0x4e, 0xdb, 0xcf, 0x26, 0x78, 0xb8, 0x52, 0x36, 0xab, 0x0c, 0xdb, 0x8e, 0xa9, + 0x65, 0x9b, 0x72, 0x89, 0xbd, 0xbc, 0x17, 0xe8, 0x0c, 0xee, 0xae, 0xec, 0x43, 0x4b, 0x5b, 0x6e, + 0x07, 0x8f, 0xfe, 0xdb, 0x6e, 0x54, 0x82, 0xad, 0x0f, 0x26, 0x63, 0x7c, 0x76, 0x3d, 0x0f, 0xc1, + 0xcd, 0x3c, 0x04, 0xbf, 0xe7, 0x21, 0xf8, 0xbc, 0x08, 0x3b, 0x37, 0x8b, 0xb0, 0xf3, 0x73, 0x11, + 0x76, 0xde, 0x8e, 0xf2, 0x42, 0x9f, 0xd7, 0x09, 0x4e, 0x45, 0x49, 0x2a, 0xc6, 0xa4, 0x9a, 0x29, + 0x4d, 0x8c, 0xe4, 0x09, 0x17, 0x19, 0x23, 0x97, 0xc4, 0xdd, 0xe8, 0x59, 0xc5, 0x54, 0xd2, 0xb5, + 0xf7, 0xe7, 0xe9, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x81, 0x9a, 0x1b, 0xe6, 0xe6, 0x03, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -281,6 +382,8 @@ type MsgClient interface { Mint(ctx context.Context, in *MsgMint, opts ...grpc.CallOption) (*MsgMintResponse, error) // Burns CBDC tokens from an address Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOption) (*MsgBurnResponse, error) + // Updates the module params. Only the governance authority can call it. + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) } type msgClient struct { @@ -309,12 +412,23 @@ func (c *msgClient) Burn(ctx context.Context, in *MsgBurn, opts ...grpc.CallOpti return out, nil } +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/cbdc.Msg/UpdateParams", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // Mints CBDC tokens and sends them to an address Mint(context.Context, *MsgMint) (*MsgMintResponse, error) // Burns CBDC tokens from an address Burn(context.Context, *MsgBurn) (*MsgBurnResponse, error) + // Updates the module params. Only the governance authority can call it. + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -327,6 +441,9 @@ func (*UnimplementedMsgServer) Mint(ctx context.Context, req *MsgMint) (*MsgMint func (*UnimplementedMsgServer) Burn(ctx context.Context, req *MsgBurn) (*MsgBurnResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Burn not implemented") } +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -368,6 +485,24 @@ func _Msg_Burn_Handler(srv interface{}, ctx context.Context, dec func(interface{ return interceptor(ctx, in, info, handler) } +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cbdc.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "cbdc.Msg", HandlerType: (*MsgServer)(nil), @@ -380,6 +515,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "Burn", Handler: _Msg_Burn_Handler, }, + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "cbdc/tx.proto", @@ -525,6 +664,69 @@ func (m *MsgBurnResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -592,6 +794,30 @@ func (m *MsgBurnResponse) Size() (n int) { return n } +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -992,6 +1218,171 @@ func (m *MsgBurnResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From 9136339f9a888eecd303646560973e2c610ce5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 11:07:29 +0200 Subject: [PATCH 12/17] feat(cbdc): add owner-valid invariant for params owner --- x/cbdc/module.go | 16 ++++++++++++++++ x/cbdc/types/params_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 x/cbdc/types/params_test.go diff --git a/x/cbdc/module.go b/x/cbdc/module.go index 700f218d..c69bf5ce 100644 --- a/x/cbdc/module.go +++ b/x/cbdc/module.go @@ -99,6 +99,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { ir.RegisterRoute(types.ModuleName, "module-account-exists", am.moduleAccountInvariant()) + ir.RegisterRoute(types.ModuleName, "owner-valid", am.ownerValidInvariant()) } // moduleAccountInvariant checks that the cbdc module account still exists. @@ -116,6 +117,21 @@ func (am AppModule) moduleAccountInvariant() sdk.Invariant { } } +// ownerValidInvariant checks that the stored mint/burn owner is well-formed +// (empty, meaning disabled, or a valid bech32 address). It catches state +// corruption at a block boundary instead of at the next mint/burn attempt. +func (am AppModule) ownerValidInvariant() sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + params := am.keeper.GetParams(ctx) + broken := params.Validate() != nil + return sdk.FormatInvariant( + types.ModuleName, + "owner-valid", + fmt.Sprintf("cbdc params owner %q is not a valid address\n", params.Owner), + ), broken + } +} + func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) { var genState types.GenesisState cdc.MustUnmarshalJSON(gs, &genState) diff --git a/x/cbdc/types/params_test.go b/x/cbdc/types/params_test.go new file mode 100644 index 00000000..093da6c8 --- /dev/null +++ b/x/cbdc/types/params_test.go @@ -0,0 +1,32 @@ +package types + +import ( + "testing" + + "github.com/peersyst/cbdc-node/testutil/sample" + "github.com/stretchr/testify/require" +) + +func TestParams_Validate(t *testing.T) { + tt := []struct { + name string + owner string + expectErr bool + }{ + {name: "empty owner is allowed", owner: "", expectErr: false}, + {name: "valid bech32 owner", owner: sample.AccAddress(), expectErr: false}, + {name: "malformed owner", owner: "not-an-address", expectErr: true}, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + params := NewParams(tc.owner) + err := params.Validate() + if tc.expectErr { + require.ErrorIs(t, err, ErrInvalidOwner) + } else { + require.NoError(t, err) + } + }) + } +} From 153912522b44a2d8d67361c48177a4877247cacd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 11:32:28 +0200 Subject: [PATCH 13/17] feat(cbdc): guard mint with BlockedAddr and IsSendEnabledCoin checks --- x/cbdc/keeper/common_test.go | 2 ++ x/cbdc/keeper/mint.go | 6 +++++ x/cbdc/keeper/msg_server_mint_test.go | 25 +++++++++++++++++++++ x/cbdc/testutil/expected_keepers_mock.go | 28 ++++++++++++++++++++++++ x/cbdc/types/errors.go | 2 ++ x/cbdc/types/expected_keepers.go | 2 ++ 6 files changed, 65 insertions(+) diff --git a/x/cbdc/keeper/common_test.go b/x/cbdc/keeper/common_test.go index 8cbebc91..11b2e3e5 100644 --- a/x/cbdc/keeper/common_test.go +++ b/x/cbdc/keeper/common_test.go @@ -85,6 +85,8 @@ func setupCbdcKeeper(t *testing.T, setBankExpectations func(ctx sdk.Context, ban func cbdcKeeperTestSetup(t *testing.T) (*Keeper, sdk.Context) { bankExpectations := func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().BlockedAddr(gomock.Any()).Return(false).AnyTimes() + bankKeeper.EXPECT().IsSendEnabledCoin(ctx, gomock.Any()).Return(true).AnyTimes() bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() bankKeeper.EXPECT().BurnCoins(ctx, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() diff --git a/x/cbdc/keeper/mint.go b/x/cbdc/keeper/mint.go index 40958826..ed146e32 100644 --- a/x/cbdc/keeper/mint.go +++ b/x/cbdc/keeper/mint.go @@ -16,6 +16,12 @@ func (k Keeper) MintCoins(ctx sdk.Context, owner string, address sdk.AccAddress, if !amount.IsPositive() { return types.ErrInvalidAmount } + if k.bk.BlockedAddr(address) { + return types.ErrBlockedAddr.Wrap(address.String()) + } + if !k.bk.IsSendEnabledCoin(ctx, amount) { + return types.ErrSendDisabled.Wrap(amount.Denom) + } coins := sdk.NewCoins(amount) if err := k.bk.MintCoins(ctx, types.ModuleName, coins); err != nil { diff --git a/x/cbdc/keeper/msg_server_mint_test.go b/x/cbdc/keeper/msg_server_mint_test.go index 3138f35c..e1137d18 100644 --- a/x/cbdc/keeper/msg_server_mint_test.go +++ b/x/cbdc/keeper/msg_server_mint_test.go @@ -110,11 +110,32 @@ func TestKeeper_MintCoins(t *testing.T) { bankMocks: func(_ sdk.Context, _ *testutil.MockBankKeeper) {}, expectedError: types.ErrInvalidDenom, }, + { + name: "should fail - blocked recipient address", + address: address, + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), + bankMocks: func(_ sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().BlockedAddr(address).Return(true) + }, + expectedError: types.ErrBlockedAddr, + }, + { + name: "should fail - send disabled for denom", + address: address, + amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), + bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().BlockedAddr(address).Return(false) + bankKeeper.EXPECT().IsSendEnabledCoin(ctx, gomock.Any()).Return(false) + }, + expectedError: types.ErrSendDisabled, + }, { name: "should fail - MintCoins returns error", address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().BlockedAddr(address).Return(false) + bankKeeper.EXPECT().IsSendEnabledCoin(ctx, gomock.Any()).Return(true) bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(errors.New("bank mint error")) }, expectedError: errors.New("bank mint error"), @@ -124,6 +145,8 @@ func TestKeeper_MintCoins(t *testing.T) { address: address, amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { + bankKeeper.EXPECT().BlockedAddr(address).Return(false) + bankKeeper.EXPECT().IsSendEnabledCoin(ctx, gomock.Any()).Return(true) bankKeeper.EXPECT().MintCoins(ctx, gomock.Any(), gomock.Any()).Return(nil) bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("bank send error")) }, @@ -135,6 +158,8 @@ func TestKeeper_MintCoins(t *testing.T) { amount: sdk.NewCoin(testCBDCDenom, math.NewInt(100)), bankMocks: func(ctx sdk.Context, bankKeeper *testutil.MockBankKeeper) { coins := sdk.NewCoins(sdk.NewCoin(testCBDCDenom, math.NewInt(100))) + bankKeeper.EXPECT().BlockedAddr(address).Return(false) + bankKeeper.EXPECT().IsSendEnabledCoin(ctx, gomock.Any()).Return(true) bankKeeper.EXPECT().MintCoins(ctx, types.ModuleName, coins).Return(nil) bankKeeper.EXPECT().SendCoinsFromModuleToAccount(ctx, types.ModuleName, gomock.Any(), coins).Return(nil) }, diff --git a/x/cbdc/testutil/expected_keepers_mock.go b/x/cbdc/testutil/expected_keepers_mock.go index 7eb66082..c67005ac 100644 --- a/x/cbdc/testutil/expected_keepers_mock.go +++ b/x/cbdc/testutil/expected_keepers_mock.go @@ -86,6 +86,20 @@ func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { return m.recorder } +// BlockedAddr mocks base method. +func (m *MockBankKeeper) BlockedAddr(addr types.AccAddress) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlockedAddr", addr) + ret0, _ := ret[0].(bool) + return ret0 +} + +// BlockedAddr indicates an expected call of BlockedAddr. +func (mr *MockBankKeeperMockRecorder) BlockedAddr(addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockedAddr", reflect.TypeOf((*MockBankKeeper)(nil).BlockedAddr), addr) +} + // BurnCoins mocks base method. func (m *MockBankKeeper) BurnCoins(ctx context.Context, moduleName string, amt types.Coins) error { m.ctrl.T.Helper() @@ -100,6 +114,20 @@ func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, moduleName, amt interface{} return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*MockBankKeeper)(nil).BurnCoins), ctx, moduleName, amt) } +// IsSendEnabledCoin mocks base method. +func (m *MockBankKeeper) IsSendEnabledCoin(ctx context.Context, coin types.Coin) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSendEnabledCoin", ctx, coin) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSendEnabledCoin indicates an expected call of IsSendEnabledCoin. +func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoin(ctx, coin interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoin", reflect.TypeOf((*MockBankKeeper)(nil).IsSendEnabledCoin), ctx, coin) +} + // MintCoins mocks base method. func (m *MockBankKeeper) MintCoins(ctx context.Context, moduleName string, amt types.Coins) error { m.ctrl.T.Helper() diff --git a/x/cbdc/types/errors.go b/x/cbdc/types/errors.go index 5d462eec..1cbcfc28 100644 --- a/x/cbdc/types/errors.go +++ b/x/cbdc/types/errors.go @@ -12,4 +12,6 @@ var ( ErrInvalidDenom = sdkerrors.Register(ModuleName, 2, "amount denom must match the configured CBDC denom") ErrUnauthorized = sdkerrors.Register(ModuleName, 3, "unauthorized signer") ErrInvalidOwner = sdkerrors.Register(ModuleName, 4, "invalid owner address") + ErrBlockedAddr = sdkerrors.Register(ModuleName, 5, "address is blocked from receiving funds") + ErrSendDisabled = sdkerrors.Register(ModuleName, 6, "transfers are disabled for the CBDC denom") ) diff --git a/x/cbdc/types/expected_keepers.go b/x/cbdc/types/expected_keepers.go index 0eb4ba84..ddfe1fc1 100644 --- a/x/cbdc/types/expected_keepers.go +++ b/x/cbdc/types/expected_keepers.go @@ -18,4 +18,6 @@ type BankKeeper interface { BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + BlockedAddr(addr sdk.AccAddress) bool + IsSendEnabledCoin(ctx context.Context, coin sdk.Coin) bool } From f1048d3c0e7ca64f1ca8cf400b248e2e2639d21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 12:04:06 +0200 Subject: [PATCH 14/17] feat(cbdc): require non-empty mint/burn owner in params --- local-node.sh | 4 ++++ testutil/integration/cbdc/integration/setup.go | 11 +++++++++++ x/cbdc/keeper/msg_server_update_params_test.go | 11 ++++++----- x/cbdc/module_simulation.go | 3 +-- x/cbdc/types/params.go | 11 +++++++---- x/cbdc/types/params_test.go | 2 +- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/local-node.sh b/local-node.sh index fc34d0f3..93b3abec 100755 --- a/local-node.sh +++ b/local-node.sh @@ -60,6 +60,10 @@ jq '.app_state.erc20.token_pairs=[{contract_owner:1,erc20_address:"0xeeeeeeeeeee jq '.app_state["slashing"]["params"]["slash_fraction_double_sign"]="0"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state["slashing"]["params"]["slash_fraction_downtime"]="0"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" +# the cbdc mint/burn owner is required (empty owner fails InitChain); use the dev key +CBDC_OWNER=$(bin/cbdcd --home "$HOMEDIR" keys show "$KEY_NAME" -a --keyring-backend "$KEYRING") +jq '.app_state["cbdc"]["params"]["owner"]="'${CBDC_OWNER}'"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + bin/cbdcd --home "$HOMEDIR" genesis add-genesis-account "$(bin/cbdcd --home "$HOMEDIR" keys show "$KEY_NAME" -a --keyring-backend "$KEYRING")" 1000000apoa,1000000000000000000000000000axrp --keyring-backend "$KEYRING" bin/cbdcd --home "$HOMEDIR" genesis add-genesis-account "ethm1zrxl239wa6ad5xge3gs68rt98227xgnjq0xyw2" 1000000000000000000000000000axrp --keyring-backend "$KEYRING" diff --git a/testutil/integration/cbdc/integration/setup.go b/testutil/integration/cbdc/integration/setup.go index 20050773..6c289502 100644 --- a/testutil/integration/cbdc/integration/setup.go +++ b/testutil/integration/cbdc/integration/setup.go @@ -31,6 +31,7 @@ import ( evmtypes "github.com/cosmos/evm/x/vm/types" cbdccommon "github.com/peersyst/cbdc-node/testutil/integration/cbdc/common" + cbdctypes "github.com/peersyst/cbdc-node/x/cbdc/types" "github.com/peersyst/cbdc-node/app" ) @@ -427,6 +428,15 @@ func setDefaultErc20GenesisState(app *app.App, genesisState testutil.GenesisStat return genesisState } +// setDefaultCbdcGenesisState sets a valid mint/burn owner, since the module's +// default params leave it empty (which fails InitChain by design). +func setDefaultCbdcGenesisState(app *app.App, genesisState testutil.GenesisState) testutil.GenesisState { + cbdcGen := cbdctypes.DefaultGenesis() + cbdcGen.Params = cbdctypes.NewParams(authtypes.NewModuleAddress(govtypes.ModuleName).String()) + genesisState[cbdctypes.ModuleName] = app.AppCodec().MustMarshalJSON(cbdcGen) + return genesisState +} + // defaultAuthGenesisState sets the default genesis state // for the testing setup func newDefaultGenesisState(app *app.App, params defaultGenesisParams) testutil.GenesisState { @@ -438,6 +448,7 @@ func newDefaultGenesisState(app *app.App, params defaultGenesisParams) testutil. genesisState = setDefaultGovGenesisState(app, genesisState, params.gov) genesisState = setDefaultSlashingGenesisState(app, genesisState, params.slashing) genesisState = setDefaultErc20GenesisState(app, genesisState) + genesisState = setDefaultCbdcGenesisState(app, genesisState) return genesisState } diff --git a/x/cbdc/keeper/msg_server_update_params_test.go b/x/cbdc/keeper/msg_server_update_params_test.go index b86cf4a5..1b981256 100644 --- a/x/cbdc/keeper/msg_server_update_params_test.go +++ b/x/cbdc/keeper/msg_server_update_params_test.go @@ -29,14 +29,15 @@ func TestMsgServer_UpdateParams(t *testing.T) { expectedErr: types.ErrInvalidOwner, }, { - name: "should pass - rotate owner", - authority: testGovAuthority, - params: types.NewParams(newOwner), + name: "should fail - empty owner", + authority: testGovAuthority, + params: types.NewParams(""), + expectedErr: types.ErrInvalidOwner, }, { - name: "should pass - clear owner", + name: "should pass - rotate owner", authority: testGovAuthority, - params: types.NewParams(""), + params: types.NewParams(newOwner), }, } diff --git a/x/cbdc/module_simulation.go b/x/cbdc/module_simulation.go index 01c01902..0532af2d 100644 --- a/x/cbdc/module_simulation.go +++ b/x/cbdc/module_simulation.go @@ -14,7 +14,6 @@ import ( // avoid unused import issue var ( - _ = sample.AccAddress _ = simulation.MsgEntryKind _ = baseapp.Paramspace _ = rand.Rand{} @@ -23,7 +22,7 @@ var ( // GenerateGenesisState creates a randomized GenState of the module func (AppModule) GenerateGenesisState(simState *module.SimulationState) { cbdcGenesis := types.GenesisState{ - Params: types.DefaultParams(), + Params: types.NewParams(sample.AccAddress()), } simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&cbdcGenesis) } diff --git a/x/cbdc/types/params.go b/x/cbdc/types/params.go index fd6ee165..c87c4ce0 100644 --- a/x/cbdc/types/params.go +++ b/x/cbdc/types/params.go @@ -20,7 +20,9 @@ func NewParams(owner string) Params { return Params{Owner: owner} } -// DefaultParams returns a default set of parameters +// DefaultParams returns a default set of parameters. The owner is intentionally +// empty (and therefore invalid): each chain must set a mint/burn owner in +// genesis, otherwise InitChain fails rather than booting with no minter. func DefaultParams() Params { return NewParams("") } @@ -37,15 +39,16 @@ func (p *Params) Validate() error { return validateOwner(p.Owner) } -// validateOwner accepts an empty owner (mint/burn stays disabled until gov sets -// one) or a well-formed bech32 address. +// validateOwner requires a non-empty, well-formed bech32 address. The owner is +// the mint/burn signer, so an unset owner is rejected: a genesis that forgets to +// set it fails InitChain instead of silently coming up with no minter. func validateOwner(i interface{}) error { owner, ok := i.(string) if !ok { return ErrInvalidOwner.Wrapf("invalid parameter type: %T", i) } if owner == "" { - return nil + return ErrInvalidOwner.Wrap("owner must not be empty") } if _, err := sdk.AccAddressFromBech32(owner); err != nil { return ErrInvalidOwner.Wrapf("invalid owner address (%s): %s", owner, err) diff --git a/x/cbdc/types/params_test.go b/x/cbdc/types/params_test.go index 093da6c8..27100724 100644 --- a/x/cbdc/types/params_test.go +++ b/x/cbdc/types/params_test.go @@ -13,7 +13,7 @@ func TestParams_Validate(t *testing.T) { owner string expectErr bool }{ - {name: "empty owner is allowed", owner: "", expectErr: false}, + {name: "empty owner is rejected", owner: "", expectErr: true}, {name: "valid bech32 owner", owner: sample.AccAddress(), expectErr: false}, {name: "malformed owner", owner: "not-an-address", expectErr: true}, } From 0a851acb488838d577faf213b26400038edfd288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 12:09:40 +0200 Subject: [PATCH 15/17] refactor(cbdc): extract mintingAllowed/burningAllowed pre-flight checks --- x/cbdc/keeper/burn.go | 12 +++++++++++- x/cbdc/keeper/mint.go | 11 ++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/x/cbdc/keeper/burn.go b/x/cbdc/keeper/burn.go index a982d8c5..16a15058 100644 --- a/x/cbdc/keeper/burn.go +++ b/x/cbdc/keeper/burn.go @@ -6,7 +6,10 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -func (k Keeper) BurnCoins(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { +// burningAllowed performs all pre-flight gating for a burn. The ctx and address +// params are kept for symmetry with mintingAllowed and for future gating (e.g. a +// paused flag) that would otherwise require a signature change. +func (k Keeper) burningAllowed(_ sdk.Context, _ sdk.AccAddress, amount sdk.Coin) error { if err := amount.Validate(); err != nil { return err } @@ -16,6 +19,13 @@ func (k Keeper) BurnCoins(ctx sdk.Context, owner string, address sdk.AccAddress, if !amount.IsPositive() { return types.ErrInvalidAmount } + return nil +} + +func (k Keeper) BurnCoins(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { + if err := k.burningAllowed(ctx, address, amount); err != nil { + return err + } coins := sdk.NewCoins(amount) if err := k.bk.SendCoinsFromAccountToModule(ctx, address, types.ModuleName, coins); err != nil { diff --git a/x/cbdc/keeper/mint.go b/x/cbdc/keeper/mint.go index ed146e32..f7a61971 100644 --- a/x/cbdc/keeper/mint.go +++ b/x/cbdc/keeper/mint.go @@ -6,7 +6,9 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -func (k Keeper) MintCoins(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { +// mintingAllowed performs all pre-flight gating for a mint. Keeping it separate +// from MintCoins makes new gating (e.g. a paused flag) easy to add and audit. +func (k Keeper) mintingAllowed(ctx sdk.Context, address sdk.AccAddress, amount sdk.Coin) error { if err := amount.Validate(); err != nil { return err } @@ -22,6 +24,13 @@ func (k Keeper) MintCoins(ctx sdk.Context, owner string, address sdk.AccAddress, if !k.bk.IsSendEnabledCoin(ctx, amount) { return types.ErrSendDisabled.Wrap(amount.Denom) } + return nil +} + +func (k Keeper) MintCoins(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { + if err := k.mintingAllowed(ctx, address, amount); err != nil { + return err + } coins := sdk.NewCoins(amount) if err := k.bk.MintCoins(ctx, types.ModuleName, coins); err != nil { From fb466c7ecfc67c5b02c122df7511eb0e5c2e537e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 12:27:45 +0200 Subject: [PATCH 16/17] feat(cbdc): add gov-controlled issuance_paused switch --- proto/cbdc/params.proto | 6 ++ .../integration/cbdc/integration/setup.go | 2 +- x/cbdc/keeper/burn.go | 11 ++-- x/cbdc/keeper/common_test.go | 2 +- x/cbdc/keeper/mint.go | 3 + x/cbdc/keeper/msg_server_burn_test.go | 9 +++ x/cbdc/keeper/msg_server_mint_test.go | 9 +++ .../keeper/msg_server_update_params_test.go | 17 +++-- x/cbdc/module_simulation.go | 2 +- x/cbdc/types/errors.go | 13 ++-- x/cbdc/types/params.go | 31 +++++++-- x/cbdc/types/params.pb.go | 66 ++++++++++++++++--- x/cbdc/types/params_test.go | 4 +- 13 files changed, 141 insertions(+), 34 deletions(-) diff --git a/proto/cbdc/params.proto b/proto/cbdc/params.proto index d3571f26..ad8d35ae 100644 --- a/proto/cbdc/params.proto +++ b/proto/cbdc/params.proto @@ -10,4 +10,10 @@ message Params { // owner is the address allowed to mint/burn CBDC tokens. It can be rotated // on-chain via a governance MsgUpdateParams proposal. string owner = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + // issuance_paused, when true, stops both minting and burning. It is a + // gov-controlled emergency switch independent of the owner: only the gov + // authority can toggle it (via MsgUpdateParams), so mint/burn can be halted + // even if the owner key is compromised. It does not affect params updates or + // queries. + bool issuance_paused = 2; } diff --git a/testutil/integration/cbdc/integration/setup.go b/testutil/integration/cbdc/integration/setup.go index 6c289502..885aebf4 100644 --- a/testutil/integration/cbdc/integration/setup.go +++ b/testutil/integration/cbdc/integration/setup.go @@ -432,7 +432,7 @@ func setDefaultErc20GenesisState(app *app.App, genesisState testutil.GenesisStat // default params leave it empty (which fails InitChain by design). func setDefaultCbdcGenesisState(app *app.App, genesisState testutil.GenesisState) testutil.GenesisState { cbdcGen := cbdctypes.DefaultGenesis() - cbdcGen.Params = cbdctypes.NewParams(authtypes.NewModuleAddress(govtypes.ModuleName).String()) + cbdcGen.Params = cbdctypes.NewParams(authtypes.NewModuleAddress(govtypes.ModuleName).String(), false) genesisState[cbdctypes.ModuleName] = app.AppCodec().MustMarshalJSON(cbdcGen) return genesisState } diff --git a/x/cbdc/keeper/burn.go b/x/cbdc/keeper/burn.go index 16a15058..d0c13d6c 100644 --- a/x/cbdc/keeper/burn.go +++ b/x/cbdc/keeper/burn.go @@ -6,10 +6,13 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -// burningAllowed performs all pre-flight gating for a burn. The ctx and address -// params are kept for symmetry with mintingAllowed and for future gating (e.g. a -// paused flag) that would otherwise require a signature change. -func (k Keeper) burningAllowed(_ sdk.Context, _ sdk.AccAddress, amount sdk.Coin) error { +// burningAllowed performs all pre-flight gating for a burn. The address param is +// kept for symmetry with mintingAllowed and for future address-based gating that +// would otherwise require a signature change. +func (k Keeper) burningAllowed(ctx sdk.Context, _ sdk.AccAddress, amount sdk.Coin) error { + if k.GetParams(ctx).IssuancePaused { + return types.ErrIssuancePaused + } if err := amount.Validate(); err != nil { return err } diff --git a/x/cbdc/keeper/common_test.go b/x/cbdc/keeper/common_test.go index 11b2e3e5..6265781e 100644 --- a/x/cbdc/keeper/common_test.go +++ b/x/cbdc/keeper/common_test.go @@ -68,7 +68,7 @@ func getMockedCbdcKeeper(_ *testing.T, key *storetypes.KVStoreKey, tsKey *storet testGovAuthority, testCBDCDenom, ) - cbdcKeeper.SetParams(ctx, types.NewParams(testOwner)) + cbdcKeeper.SetParams(ctx, types.NewParams(testOwner, false)) return cbdcKeeper } diff --git a/x/cbdc/keeper/mint.go b/x/cbdc/keeper/mint.go index f7a61971..b1372029 100644 --- a/x/cbdc/keeper/mint.go +++ b/x/cbdc/keeper/mint.go @@ -9,6 +9,9 @@ import ( // mintingAllowed performs all pre-flight gating for a mint. Keeping it separate // from MintCoins makes new gating (e.g. a paused flag) easy to add and audit. func (k Keeper) mintingAllowed(ctx sdk.Context, address sdk.AccAddress, amount sdk.Coin) error { + if k.GetParams(ctx).IssuancePaused { + return types.ErrIssuancePaused + } if err := amount.Validate(); err != nil { return err } diff --git a/x/cbdc/keeper/msg_server_burn_test.go b/x/cbdc/keeper/msg_server_burn_test.go index 2ad53416..5339c83e 100644 --- a/x/cbdc/keeper/msg_server_burn_test.go +++ b/x/cbdc/keeper/msg_server_burn_test.go @@ -155,3 +155,12 @@ func TestKeeper_BurnCoins(t *testing.T) { }) } } + +func TestKeeper_BurnCoins_Paused(t *testing.T) { + keeper, ctx := setupCbdcKeeper(t, func(_ sdk.Context, _ *testutil.MockBankKeeper) {}) + keeper.SetParams(ctx, types.NewParams(testOwner, true)) + + address := sdk.MustAccAddressFromBech32("ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp") + err := keeper.BurnCoins(ctx, testOwner, address, sdk.NewCoin(testCBDCDenom, math.NewInt(100))) + require.ErrorIs(t, err, types.ErrIssuancePaused) +} diff --git a/x/cbdc/keeper/msg_server_mint_test.go b/x/cbdc/keeper/msg_server_mint_test.go index e1137d18..27791c1e 100644 --- a/x/cbdc/keeper/msg_server_mint_test.go +++ b/x/cbdc/keeper/msg_server_mint_test.go @@ -180,3 +180,12 @@ func TestKeeper_MintCoins(t *testing.T) { }) } } + +func TestKeeper_MintCoins_Paused(t *testing.T) { + keeper, ctx := setupCbdcKeeper(t, func(_ sdk.Context, _ *testutil.MockBankKeeper) {}) + keeper.SetParams(ctx, types.NewParams(testOwner, true)) + + address := sdk.MustAccAddressFromBech32("ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp") + err := keeper.MintCoins(ctx, testOwner, address, sdk.NewCoin(testCBDCDenom, math.NewInt(100))) + require.ErrorIs(t, err, types.ErrIssuancePaused) +} diff --git a/x/cbdc/keeper/msg_server_update_params_test.go b/x/cbdc/keeper/msg_server_update_params_test.go index 1b981256..5567a614 100644 --- a/x/cbdc/keeper/msg_server_update_params_test.go +++ b/x/cbdc/keeper/msg_server_update_params_test.go @@ -19,25 +19,30 @@ func TestMsgServer_UpdateParams(t *testing.T) { { name: "should fail - unauthorized authority", authority: testOwner, - params: types.NewParams(newOwner), + params: types.NewParams(newOwner, false), expectedErr: types.ErrUnauthorized, }, { name: "should fail - invalid owner", authority: testGovAuthority, - params: types.NewParams("invalidowner"), + params: types.NewParams("invalidowner", false), expectedErr: types.ErrInvalidOwner, }, { name: "should fail - empty owner", authority: testGovAuthority, - params: types.NewParams(""), + params: types.NewParams("", false), expectedErr: types.ErrInvalidOwner, }, { name: "should pass - rotate owner", authority: testGovAuthority, - params: types.NewParams(newOwner), + params: types.NewParams(newOwner, false), + }, + { + name: "should pass - pause issuance", + authority: testGovAuthority, + params: types.NewParams(newOwner, true), }, } @@ -59,7 +64,9 @@ func TestMsgServer_UpdateParams(t *testing.T) { } require.NoError(t, err) - require.Equal(t, tc.params.Owner, cbdcKeeper.GetParams(ctx).Owner) + got := cbdcKeeper.GetParams(ctx) + require.Equal(t, tc.params.Owner, got.Owner) + require.Equal(t, tc.params.IssuancePaused, got.IssuancePaused) }) } } diff --git a/x/cbdc/module_simulation.go b/x/cbdc/module_simulation.go index 0532af2d..bb65fc9c 100644 --- a/x/cbdc/module_simulation.go +++ b/x/cbdc/module_simulation.go @@ -22,7 +22,7 @@ var ( // GenerateGenesisState creates a randomized GenState of the module func (AppModule) GenerateGenesisState(simState *module.SimulationState) { cbdcGenesis := types.GenesisState{ - Params: types.NewParams(sample.AccAddress()), + Params: types.NewParams(sample.AccAddress(), false), } simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&cbdcGenesis) } diff --git a/x/cbdc/types/errors.go b/x/cbdc/types/errors.go index 1cbcfc28..391c0468 100644 --- a/x/cbdc/types/errors.go +++ b/x/cbdc/types/errors.go @@ -8,10 +8,11 @@ import ( // x/cbdc module sentinel errors var ( - ErrInvalidAmount = sdkerrors.Register(ModuleName, 1, "amount must be positive") - ErrInvalidDenom = sdkerrors.Register(ModuleName, 2, "amount denom must match the configured CBDC denom") - ErrUnauthorized = sdkerrors.Register(ModuleName, 3, "unauthorized signer") - ErrInvalidOwner = sdkerrors.Register(ModuleName, 4, "invalid owner address") - ErrBlockedAddr = sdkerrors.Register(ModuleName, 5, "address is blocked from receiving funds") - ErrSendDisabled = sdkerrors.Register(ModuleName, 6, "transfers are disabled for the CBDC denom") + ErrInvalidAmount = sdkerrors.Register(ModuleName, 1, "amount must be positive") + ErrInvalidDenom = sdkerrors.Register(ModuleName, 2, "amount denom must match the configured CBDC denom") + ErrUnauthorized = sdkerrors.Register(ModuleName, 3, "unauthorized signer") + ErrInvalidOwner = sdkerrors.Register(ModuleName, 4, "invalid owner address") + ErrBlockedAddr = sdkerrors.Register(ModuleName, 5, "address is blocked from receiving funds") + ErrSendDisabled = sdkerrors.Register(ModuleName, 6, "transfers are disabled for the CBDC denom") + ErrIssuancePaused = sdkerrors.Register(ModuleName, 7, "mint/burn is paused") ) diff --git a/x/cbdc/types/params.go b/x/cbdc/types/params.go index c87c4ce0..dceaabcc 100644 --- a/x/cbdc/types/params.go +++ b/x/cbdc/types/params.go @@ -1,14 +1,21 @@ package types import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) var _ paramtypes.ParamSet = (*Params)(nil) -// KeyOwner is the param store key for the mint/burn owner address. -var KeyOwner = []byte("Owner") +// Param store keys. +var ( + // KeyOwner is the param store key for the mint/burn owner address. + KeyOwner = []byte("Owner") + // KeyIssuancePaused is the param store key for the issuance pause switch. + KeyIssuancePaused = []byte("IssuancePaused") +) // ParamKeyTable the param key table for launch module func ParamKeyTable() paramtypes.KeyTable { @@ -16,27 +23,31 @@ func ParamKeyTable() paramtypes.KeyTable { } // NewParams creates a new Params instance -func NewParams(owner string) Params { - return Params{Owner: owner} +func NewParams(owner string, issuancePaused bool) Params { + return Params{Owner: owner, IssuancePaused: issuancePaused} } // DefaultParams returns a default set of parameters. The owner is intentionally // empty (and therefore invalid): each chain must set a mint/burn owner in // genesis, otherwise InitChain fails rather than booting with no minter. func DefaultParams() Params { - return NewParams("") + return NewParams("", false) } // ParamSetPairs get the params.ParamSet func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyOwner, &p.Owner, validateOwner), + paramtypes.NewParamSetPair(KeyIssuancePaused, &p.IssuancePaused, validateIssuancePaused), } } // Validate validates the set of params func (p *Params) Validate() error { - return validateOwner(p.Owner) + if err := validateOwner(p.Owner); err != nil { + return err + } + return validateIssuancePaused(p.IssuancePaused) } // validateOwner requires a non-empty, well-formed bech32 address. The owner is @@ -55,3 +66,11 @@ func validateOwner(i interface{}) error { } return nil } + +// validateIssuancePaused only checks the param is a bool; both values are valid. +func validateIssuancePaused(i interface{}) error { + if _, ok := i.(bool); !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + return nil +} diff --git a/x/cbdc/types/params.pb.go b/x/cbdc/types/params.pb.go index 981e4018..48939a43 100644 --- a/x/cbdc/types/params.pb.go +++ b/x/cbdc/types/params.pb.go @@ -28,6 +28,12 @@ type Params struct { // owner is the address allowed to mint/burn CBDC tokens. It can be rotated // on-chain via a governance MsgUpdateParams proposal. Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + // issuance_paused, when true, stops both minting and burning. It is a + // gov-controlled emergency switch independent of the owner: only the gov + // authority can toggle it (via MsgUpdateParams), so mint/burn can be halted + // even if the owner key is compromised. It does not affect params updates or + // queries. + IssuancePaused bool `protobuf:"varint,2,opt,name=issuance_paused,json=issuancePaused,proto3" json:"issuance_paused,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -70,6 +76,13 @@ func (m *Params) GetOwner() string { return "" } +func (m *Params) GetIssuancePaused() bool { + if m != nil { + return m.IssuancePaused + } + return false +} + func init() { proto.RegisterType((*Params)(nil), "cbdc.Params") } @@ -77,19 +90,21 @@ func init() { func init() { proto.RegisterFile("cbdc/params.proto", fileDescriptor_a383b166b3425dd0) } var fileDescriptor_a383b166b3425dd0 = []byte{ - // 181 bytes of a gzipped FileDescriptorProto + // 212 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4c, 0x4e, 0x4a, 0x49, 0xd6, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0x09, 0x49, 0x49, 0x26, 0xe7, 0x17, 0xe7, 0xe6, 0x17, 0xc7, 0x83, 0xc5, 0xf4, 0x21, 0x1c, 0x88, - 0x02, 0x25, 0x0b, 0x2e, 0xb6, 0x00, 0xb0, 0x06, 0x21, 0x3d, 0x2e, 0xd6, 0xfc, 0xf2, 0xbc, 0xd4, + 0x02, 0xa5, 0x44, 0x2e, 0xb6, 0x00, 0xb0, 0x06, 0x21, 0x3d, 0x2e, 0xd6, 0xfc, 0xf2, 0xbc, 0xd4, 0x22, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x4e, 0x27, 0x89, 0x4b, 0x5b, 0x74, 0x45, 0xa0, 0x4a, 0x1d, - 0x53, 0x52, 0x8a, 0x52, 0x8b, 0x8b, 0x83, 0x4b, 0x8a, 0x32, 0xf3, 0xd2, 0x83, 0x20, 0xca, 0x9c, - 0x5c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, - 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x2b, 0x3d, 0xb3, 0x24, - 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0xbf, 0x20, 0x35, 0xb5, 0xa8, 0xb8, 0xb2, 0xb8, 0x44, - 0x1f, 0xe4, 0x10, 0xdd, 0xbc, 0xfc, 0x94, 0x54, 0xfd, 0x0a, 0x30, 0x5b, 0xbf, 0xa4, 0xb2, 0x20, - 0xb5, 0x38, 0x89, 0x0d, 0xec, 0x0c, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd2, 0xf2, 0x07, - 0xbe, 0xbc, 0x00, 0x00, 0x00, + 0x53, 0x52, 0x8a, 0x52, 0x8b, 0x8b, 0x83, 0x4b, 0x8a, 0x32, 0xf3, 0xd2, 0x83, 0x20, 0xca, 0x84, + 0xd4, 0xb9, 0xf8, 0x33, 0x8b, 0x8b, 0x4b, 0x13, 0xf3, 0x92, 0x53, 0xe3, 0x0b, 0x12, 0x4b, 0x8b, + 0x53, 0x53, 0x24, 0x98, 0x14, 0x18, 0x35, 0x38, 0x82, 0xf8, 0x60, 0xc2, 0x01, 0x60, 0x51, 0x27, + 0x97, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, + 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4a, 0xcf, 0x2c, 0xc9, + 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x2f, 0x48, 0x4d, 0x2d, 0x2a, 0xae, 0x2c, 0x2e, 0xd1, + 0x07, 0xb9, 0x58, 0x37, 0x2f, 0x3f, 0x25, 0x55, 0xbf, 0x02, 0xcc, 0xd6, 0x2f, 0xa9, 0x2c, 0x48, + 0x2d, 0x4e, 0x62, 0x03, 0xbb, 0xd7, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x63, 0x99, 0x78, + 0xe5, 0x00, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -112,6 +127,16 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.IssuancePaused { + i-- + if m.IssuancePaused { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } if len(m.Owner) > 0 { i -= len(m.Owner) copy(dAtA[i:], m.Owner) @@ -143,6 +168,9 @@ func (m *Params) Size() (n int) { if l > 0 { n += 1 + l + sovParams(uint64(l)) } + if m.IssuancePaused { + n += 2 + } return n } @@ -213,6 +241,26 @@ func (m *Params) Unmarshal(dAtA []byte) error { } m.Owner = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IssuancePaused", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IssuancePaused = bool(v != 0) default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/cbdc/types/params_test.go b/x/cbdc/types/params_test.go index 27100724..07bb9b5a 100644 --- a/x/cbdc/types/params_test.go +++ b/x/cbdc/types/params_test.go @@ -11,16 +11,18 @@ func TestParams_Validate(t *testing.T) { tt := []struct { name string owner string + paused bool expectErr bool }{ {name: "empty owner is rejected", owner: "", expectErr: true}, {name: "valid bech32 owner", owner: sample.AccAddress(), expectErr: false}, {name: "malformed owner", owner: "not-an-address", expectErr: true}, + {name: "paused is valid", owner: sample.AccAddress(), paused: true, expectErr: false}, } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - params := NewParams(tc.owner) + params := NewParams(tc.owner, tc.paused) err := params.Validate() if tc.expectErr { require.ErrorIs(t, err, ErrInvalidOwner) From e9eaff70a1e231e65823771ace8ea706f1a82b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Luque?= Date: Fri, 5 Jun 2026 12:47:02 +0200 Subject: [PATCH 17/17] fix(cbdc): re-check owner inside keeper mint/burn --- x/cbdc/keeper/burn.go | 17 +++++++++++------ x/cbdc/keeper/mint.go | 16 +++++++++++----- x/cbdc/keeper/msg_server_burn_test.go | 8 ++++++++ x/cbdc/keeper/msg_server_mint_test.go | 8 ++++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/x/cbdc/keeper/burn.go b/x/cbdc/keeper/burn.go index d0c13d6c..8d1acb97 100644 --- a/x/cbdc/keeper/burn.go +++ b/x/cbdc/keeper/burn.go @@ -6,11 +6,16 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -// burningAllowed performs all pre-flight gating for a burn. The address param is -// kept for symmetry with mintingAllowed and for future address-based gating that -// would otherwise require a signature change. -func (k Keeper) burningAllowed(ctx sdk.Context, _ sdk.AccAddress, amount sdk.Coin) error { - if k.GetParams(ctx).IssuancePaused { +// burningAllowed performs all pre-flight gating for a burn, including the owner +// authorization check so the keeper cannot be burned from by any caller that +// bypasses the msg server. The address param is kept for symmetry with +// mintingAllowed and for future address-based gating. +func (k Keeper) burningAllowed(ctx sdk.Context, owner string, _ sdk.AccAddress, amount sdk.Coin) error { + params := k.GetParams(ctx) + if owner != params.Owner { + return types.ErrUnauthorized + } + if params.IssuancePaused { return types.ErrIssuancePaused } if err := amount.Validate(); err != nil { @@ -26,7 +31,7 @@ func (k Keeper) burningAllowed(ctx sdk.Context, _ sdk.AccAddress, amount sdk.Coi } func (k Keeper) BurnCoins(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { - if err := k.burningAllowed(ctx, address, amount); err != nil { + if err := k.burningAllowed(ctx, owner, address, amount); err != nil { return err } diff --git a/x/cbdc/keeper/mint.go b/x/cbdc/keeper/mint.go index b1372029..f3b95e37 100644 --- a/x/cbdc/keeper/mint.go +++ b/x/cbdc/keeper/mint.go @@ -6,10 +6,16 @@ import ( "github.com/peersyst/cbdc-node/x/cbdc/types" ) -// mintingAllowed performs all pre-flight gating for a mint. Keeping it separate -// from MintCoins makes new gating (e.g. a paused flag) easy to add and audit. -func (k Keeper) mintingAllowed(ctx sdk.Context, address sdk.AccAddress, amount sdk.Coin) error { - if k.GetParams(ctx).IssuancePaused { +// mintingAllowed performs all pre-flight gating for a mint, including the owner +// authorization check so the keeper cannot be minted from by any caller that +// bypasses the msg server. Keeping it separate from MintCoins makes new gating +// easy to add and audit. +func (k Keeper) mintingAllowed(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { + params := k.GetParams(ctx) + if owner != params.Owner { + return types.ErrUnauthorized + } + if params.IssuancePaused { return types.ErrIssuancePaused } if err := amount.Validate(); err != nil { @@ -31,7 +37,7 @@ func (k Keeper) mintingAllowed(ctx sdk.Context, address sdk.AccAddress, amount s } func (k Keeper) MintCoins(ctx sdk.Context, owner string, address sdk.AccAddress, amount sdk.Coin) error { - if err := k.mintingAllowed(ctx, address, amount); err != nil { + if err := k.mintingAllowed(ctx, owner, address, amount); err != nil { return err } diff --git a/x/cbdc/keeper/msg_server_burn_test.go b/x/cbdc/keeper/msg_server_burn_test.go index 5339c83e..55a3aa51 100644 --- a/x/cbdc/keeper/msg_server_burn_test.go +++ b/x/cbdc/keeper/msg_server_burn_test.go @@ -164,3 +164,11 @@ func TestKeeper_BurnCoins_Paused(t *testing.T) { err := keeper.BurnCoins(ctx, testOwner, address, sdk.NewCoin(testCBDCDenom, math.NewInt(100))) require.ErrorIs(t, err, types.ErrIssuancePaused) } + +func TestKeeper_BurnCoins_Unauthorized(t *testing.T) { + keeper, ctx := setupCbdcKeeper(t, func(_ sdk.Context, _ *testutil.MockBankKeeper) {}) + + address := sdk.MustAccAddressFromBech32("ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp") + err := keeper.BurnCoins(ctx, testGovAuthority, address, sdk.NewCoin(testCBDCDenom, math.NewInt(100))) + require.ErrorIs(t, err, types.ErrUnauthorized) +} diff --git a/x/cbdc/keeper/msg_server_mint_test.go b/x/cbdc/keeper/msg_server_mint_test.go index 27791c1e..2727bd9a 100644 --- a/x/cbdc/keeper/msg_server_mint_test.go +++ b/x/cbdc/keeper/msg_server_mint_test.go @@ -189,3 +189,11 @@ func TestKeeper_MintCoins_Paused(t *testing.T) { err := keeper.MintCoins(ctx, testOwner, address, sdk.NewCoin(testCBDCDenom, math.NewInt(100))) require.ErrorIs(t, err, types.ErrIssuancePaused) } + +func TestKeeper_MintCoins_Unauthorized(t *testing.T) { + keeper, ctx := setupCbdcKeeper(t, func(_ sdk.Context, _ *testutil.MockBankKeeper) {}) + + address := sdk.MustAccAddressFromBech32("ethm1a0pd5cyew47pvgf7rd7axxy3humv9ev0nnkprp") + err := keeper.MintCoins(ctx, testGovAuthority, address, sdk.NewCoin(testCBDCDenom, math.NewInt(100))) + require.ErrorIs(t, err, types.ErrUnauthorized) +}