From 28f7e4a4ade1b62040474ef95af7002dc459f5c3 Mon Sep 17 00:00:00 2001 From: Arham Chordia <43543921+arhamchordia@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:50:50 +0530 Subject: [PATCH] Fix app, cmd and compilation of binary and docker reproducible issues. (#744) --- Dockerfile | 8 +- ante/ante.go | 43 ++- ante/gov_expedited_ante.go | 79 ++++++ ante/gov_expedited_ante_test.go | 215 +++++++++++++++ ante/gov_vote_ante.go | 144 ++++++++++ ante/gov_vote_ante_test.go | 272 +++++++++++++++++++ app/app.go | 178 +++++++----- app/encoding.go | 2 +- app/helpers/test_helpers.go | 211 ++++++++++++++ app/keepers/keepers.go | 45 +-- app/modules.go | 65 ++++- app/params/params.go | 58 +++- app/upgrades/v3/constants.go | 13 +- cmd/quasard/cmd/bech32.go | 50 ++++ cmd/quasard/cmd/config.go | 30 +- cmd/quasard/cmd/root.go | 126 ++++++--- cmd/quasard/main.go | 7 +- go.mod | 19 +- go.sum | 12 + scripts/makefiles/build.mk | 10 +- types/errors/errors.go | 40 +++ x/tokenfactory/bindings/custom_query_test.go | 2 +- x/tokenfactory/keeper/keeper.go | 3 +- 23 files changed, 1439 insertions(+), 193 deletions(-) create mode 100644 ante/gov_expedited_ante.go create mode 100644 ante/gov_expedited_ante_test.go create mode 100644 ante/gov_vote_ante.go create mode 100644 ante/gov_vote_ante_test.go create mode 100644 app/helpers/test_helpers.go create mode 100644 cmd/quasard/cmd/bech32.go create mode 100644 types/errors/errors.go diff --git a/Dockerfile b/Dockerfile index 761302ab5..5aea82ce8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,12 +28,12 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ go mod download # Cosmwasm - Download correct libwasmvm version -RUN ARCH=$(uname -m) && WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm/v2 | sed 's/.* //') && \ - wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/libwasmvm_muslc.$ARCH.a \ - -O /lib/libwasmvm_muslc.a && \ +RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm/v2 | cut -d ' ' -f 2) && \ + wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/libwasmvm_muslc.$(uname -m).a \ + -O /lib/libwasmvm_muslc.$(uname -m).a && \ # verify checksum wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/checksums.txt -O /tmp/checksums.txt && \ - sha256sum /lib/libwasmvm_muslc.a | grep $(cat /tmp/checksums.txt | grep libwasmvm_muslc.$ARCH | cut -d ' ' -f 1) + sha256sum /lib/libwasmvm_muslc.$(uname -m).a | grep $(cat /tmp/checksums.txt | grep libwasmvm_muslc.$(uname -m) | cut -d ' ' -f 1) # Copy the remaining files COPY . . diff --git a/ante/ante.go b/ante/ante.go index 0bf26687f..5d9576e56 100644 --- a/ante/ante.go +++ b/ante/ante.go @@ -1,35 +1,53 @@ package ante import ( + ibcante "github.com/cosmos/ibc-go/v8/modules/core/ante" + ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" + + corestoretypes "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth/ante" - ibcante "github.com/cosmos/ibc-go/v8/modules/core/ante" - ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + + quasarerrors "github.com/quasar-finance/quasar/types/errors" ) +// UseFeeMarketDecorator to make the integration testing easier: we can switch off its ante and post decorators with this flag +var UseFeeMarketDecorator = true + // HandlerOptions extend the SDK's AnteHandler options by requiring the IBC // channel keeper. type HandlerOptions struct { ante.HandlerOptions - Codec codec.BinaryCodec - IBCkeeper *ibckeeper.Keeper + Codec codec.BinaryCodec + IBCkeeper *ibckeeper.Keeper + StakingKeeper *stakingkeeper.Keeper + TXCounterStoreService corestoretypes.KVStoreService + WasmConfig *wasmtypes.WasmConfig } func NewAnteHandler(opts HandlerOptions) (sdk.AnteHandler, error) { if opts.AccountKeeper == nil { - return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler") + return nil, errorsmod.Wrap(quasarerrors.ErrLogic, "account keeper is required for AnteHandler") } if opts.BankKeeper == nil { - return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler") + return nil, errorsmod.Wrap(quasarerrors.ErrLogic, "bank keeper is required for AnteHandler") } if opts.SignModeHandler == nil { - return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for AnteHandler") + return nil, errorsmod.Wrap(quasarerrors.ErrLogic, "sign mode handler is required for AnteHandler") } if opts.IBCkeeper == nil { - return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "IBC keeper is required for AnteHandler") + return nil, errorsmod.Wrap(quasarerrors.ErrLogic, "IBC keeper is required for AnteHandler") + } + + if opts.StakingKeeper == nil { + return nil, errorsmod.Wrap(quasarerrors.ErrNotFound, "staking param store is required for AnteHandler") } sigGasConsumer := opts.SigGasConsumer @@ -38,13 +56,16 @@ func NewAnteHandler(opts HandlerOptions) (sdk.AnteHandler, error) { } anteDecorators := []sdk.AnteDecorator{ - ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first + ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first + wasmkeeper.NewLimitSimulationGasDecorator(opts.WasmConfig.SimulationGasLimit), // after setup context to enforce limits early + wasmkeeper.NewCountTXDecorator(opts.TXCounterStoreService), ante.NewExtensionOptionsDecorator(opts.ExtensionOptionChecker), ante.NewValidateBasicDecorator(), ante.NewTxTimeoutHeightDecorator(), ante.NewValidateMemoDecorator(opts.AccountKeeper), ante.NewConsumeGasForTxSizeDecorator(opts.AccountKeeper), - ante.NewDeductFeeDecorator(opts.AccountKeeper, opts.BankKeeper, opts.FeegrantKeeper, opts.TxFeeChecker), + NewGovVoteDecorator(opts.Codec, opts.StakingKeeper), + NewGovExpeditedProposalsDecorator(opts.Codec), ante.NewSetPubKeyDecorator(opts.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators ante.NewValidateSigCountDecorator(opts.AccountKeeper), ante.NewSigGasConsumeDecorator(opts.AccountKeeper, sigGasConsumer), diff --git a/ante/gov_expedited_ante.go b/ante/gov_expedited_ante.go new file mode 100644 index 000000000..5bcfd49ec --- /dev/null +++ b/ante/gov_expedited_ante.go @@ -0,0 +1,79 @@ +package ante + +import ( + errorsmod "cosmossdk.io/errors" + quasarerrors "github.com/quasar-finance/quasar/types/errors" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" +) + +var expeditedPropDecoratorEnabled = true + +// SetExpeditedProposalsEnabled toggles the expedited proposals decorator on/off. +// Should only be used in testing - this is to allow simtests to pass. +func SetExpeditedProposalsEnabled(val bool) { + expeditedPropDecoratorEnabled = val +} + +var expeditedPropsWhitelist = map[string]struct{}{ + "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade": {}, + "/cosmos.upgrade.v1beta1.MsgCancelUpgrade": {}, +} + +// Check if the proposal is whitelisted for expedited voting. +type GovExpeditedProposalsDecorator struct { + cdc codec.BinaryCodec +} + +func NewGovExpeditedProposalsDecorator(cdc codec.BinaryCodec) GovExpeditedProposalsDecorator { + return GovExpeditedProposalsDecorator{ + cdc: cdc, + } +} + +// AnteHandle checks if the proposal is whitelisted for expedited voting. +// Only proposals submitted using "quasard tx gov submit-proposal" can be expedited. +// Legacy proposals submitted using "quasard tx gov submit-legacy-proposal" cannot be marked as expedited. +func (g GovExpeditedProposalsDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + if expeditedPropDecoratorEnabled { + for _, msg := range tx.GetMsgs() { + prop, ok := msg.(*govv1.MsgSubmitProposal) + if !ok { + continue + } + if prop.Expedited { + if err := g.validateExpeditedGovProp(prop); err != nil { + return ctx, err + } + } + } + } + return next(ctx, tx, simulate) +} + +func (g GovExpeditedProposalsDecorator) isWhitelisted(msgType string) bool { + _, ok := expeditedPropsWhitelist[msgType] + return ok +} + +func (g GovExpeditedProposalsDecorator) validateExpeditedGovProp(prop *govv1.MsgSubmitProposal) error { + msgs := prop.GetMessages() + if len(msgs) == 0 { + return quasarerrors.ErrInvalidExpeditedProposal + } + for _, message := range msgs { + // in case of legacy content submitted using govv1.MsgSubmitProposal + if sdkMsg, isLegacy := message.GetCachedValue().(*govv1.MsgExecLegacyContent); isLegacy { + if !g.isWhitelisted(sdkMsg.Content.TypeUrl) { + return errorsmod.Wrapf(quasarerrors.ErrInvalidExpeditedProposal, "invalid Msg type: %s", sdkMsg.Content.TypeUrl) + } + continue + } + if !g.isWhitelisted(message.TypeUrl) { + return errorsmod.Wrapf(quasarerrors.ErrInvalidExpeditedProposal, "invalid Msg type: %s", message.TypeUrl) + } + } + return nil +} diff --git a/ante/gov_expedited_ante_test.go b/ante/gov_expedited_ante_test.go new file mode 100644 index 000000000..df642f5e1 --- /dev/null +++ b/ante/gov_expedited_ante_test.go @@ -0,0 +1,215 @@ +package ante_test + +import ( + "testing" + + "cosmossdk.io/math" + upgradetypes "cosmossdk.io/x/upgrade/types" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + "github.com/quasar-finance/quasar/ante" + "github.com/quasar-finance/quasar/app/helpers" + "github.com/stretchr/testify/require" +) + +func TestGovExpeditedProposalsDecorator(t *testing.T) { + quasarApp := helpers.Setup(t) + + testCases := []struct { + name string + ctx sdk.Context + msgs []sdk.Msg + expectErr bool + }{ + // these cases should pass + { + name: "expedited - govv1.MsgSubmitProposal - MsgSoftwareUpgrade", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{&upgradetypes.MsgSoftwareUpgrade{ + Authority: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + Plan: upgradetypes.Plan{ + Name: "upgrade plan-plan", + Info: "some text here", + Height: 123456789, + }, + }}, true), + }, + expectErr: false, + }, + { + name: "expedited - govv1.MsgSubmitProposal - MsgCancelUpgrade", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{&upgradetypes.MsgCancelUpgrade{ + Authority: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + }}, true), + }, + expectErr: false, + }, + { + name: "normal - govv1.MsgSubmitProposal - TextProposal", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newLegacyTextProp(false), // normal + }, + expectErr: false, + }, + { + name: "normal - govv1.MsgSubmitProposal - MsgCommunityPoolSpend", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{&distrtypes.MsgCommunityPoolSpend{ + Authority: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + Recipient: sdk.AccAddress{}.String(), + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }}, false), // normal + }, + expectErr: false, + }, + { + name: "normal - govv1.MsgSubmitProposal - MsgTransfer", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{&banktypes.MsgSend{ + FromAddress: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + ToAddress: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }}, false), // normal + }, + expectErr: false, + }, + { + name: "normal - govv1.MsgSubmitProposal - MsgUpdateParams", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{&banktypes.MsgUpdateParams{ + Authority: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + }}, false), + }, + expectErr: false, + }, + // legacy proposals - antehandler should not affect them + // submitted using "quasard tx gov submit-legacy-proposal" + { + name: "normal - govv1beta.MsgSubmitProposal - LegacySoftwareUpgrade", + ctx: sdk.Context{}, + msgs: []sdk.Msg{newGovV1BETA1LegacyUpgradeProp()}, + expectErr: false, + }, + { + name: "normal - govv1beta.MsgSubmitProposal - LegacyCancelSoftwareUpgrade", + ctx: sdk.Context{}, + msgs: []sdk.Msg{newGovV1BETA1LegacyCancelUpgradeProp()}, + expectErr: false, + }, + // these cases should fail + // these are normal proposals, not whitelisted for expedited voting + { + name: "fail - expedited - govv1.MsgSubmitProposal - Empty", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{}, true), + }, + expectErr: true, + }, + { + name: "fail - expedited - govv1.MsgSubmitProposal - TextProposal", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newLegacyTextProp(true), // expedite + }, + expectErr: true, + }, + { + name: "fail - expedited - govv1.MsgSubmitProposal - MsgCommunityPoolSpend", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{&distrtypes.MsgCommunityPoolSpend{ + Authority: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + Recipient: sdk.AccAddress{}.String(), + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }}, true), + }, + expectErr: true, + }, + { + name: "fail - expedited - govv1.MsgSubmitProposal - MsgTransfer", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{&banktypes.MsgSend{ + FromAddress: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + ToAddress: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100))), + }}, true), + }, + expectErr: true, + }, + { + name: "fail - expedited - govv1.MsgSubmitProposal - MsgUpdateParams", + ctx: sdk.Context{}, + msgs: []sdk.Msg{ + newGovProp([]sdk.Msg{&banktypes.MsgUpdateParams{ + Authority: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + }}, true), + }, + expectErr: true, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + txCfg := quasarApp.GetTxConfig() + decorator := ante.NewGovExpeditedProposalsDecorator(quasarApp.AppCodec()) + + txBuilder := txCfg.NewTxBuilder() + require.NoError(t, txBuilder.SetMsgs(tc.msgs...)) + + _, err := decorator.AnteHandle(tc.ctx, txBuilder.GetTx(), false, + func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { return ctx, nil }) + if tc.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func newLegacyTextProp(expedite bool) *govv1.MsgSubmitProposal { + testProposal := govv1beta1.NewTextProposal("Proposal", "Test as normal proposal") + msgContent, err := govv1.NewLegacyContent(testProposal, "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn") + if err != nil { + return nil + } + return newGovProp([]sdk.Msg{msgContent}, expedite) +} + +func newGovV1BETA1LegacyUpgradeProp() *govv1beta1.MsgSubmitProposal { + legacyContent := upgradetypes.NewSoftwareUpgradeProposal("test legacy upgrade", "test legacy upgrade", upgradetypes.Plan{ + Name: "upgrade plan-plan", + Info: "some text here", + Height: 123456789, + }) + + msg, _ := govv1beta1.NewMsgSubmitProposal(legacyContent, sdk.NewCoins(), sdk.AccAddress{}) + return msg +} + +func newGovV1BETA1LegacyCancelUpgradeProp() *govv1beta1.MsgSubmitProposal { + legacyContent := upgradetypes.NewCancelSoftwareUpgradeProposal("test legacy upgrade", "test legacy upgrade") + + msg, _ := govv1beta1.NewMsgSubmitProposal(legacyContent, sdk.NewCoins(), sdk.AccAddress{}) + return msg +} + +func newGovProp(msgs []sdk.Msg, expedite bool) *govv1.MsgSubmitProposal { + msg, _ := govv1.NewMsgSubmitProposal(msgs, sdk.NewCoins(), sdk.AccAddress{}.String(), "", "expedite", "expedite", expedite) + // fmt.Println("### msg ###", msg, "err", err) + return msg +} diff --git a/ante/gov_vote_ante.go b/ante/gov_vote_ante.go new file mode 100644 index 000000000..80b739b69 --- /dev/null +++ b/ante/gov_vote_ante.go @@ -0,0 +1,144 @@ +package ante + +import ( + errorsmod "cosmossdk.io/errors" + "cosmossdk.io/math" + quasarerrors "github.com/quasar-finance/quasar/types/errors" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz" + govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +var ( + minStakedTokens = math.LegacyNewDec(1000000) // 1_000_000 uatom (or 1 atom) + maxDelegationsChecked = 100 // number of delegation to check for the minStakedTokens +) + +// SetMinStakedTokens sets the minimum amount of staked tokens required to vote +// Should only be used in testing +func SetMinStakedTokens(tokens math.LegacyDec) { + minStakedTokens = tokens +} + +type GovVoteDecorator struct { + stakingKeeper *stakingkeeper.Keeper + cdc codec.BinaryCodec +} + +func NewGovVoteDecorator(cdc codec.BinaryCodec, stakingKeeper *stakingkeeper.Keeper) GovVoteDecorator { + return GovVoteDecorator{ + stakingKeeper: stakingKeeper, + cdc: cdc, + } +} + +func (g GovVoteDecorator) AnteHandle( + ctx sdk.Context, tx sdk.Tx, + simulate bool, next sdk.AnteHandler, +) (newCtx sdk.Context, err error) { + // do not run check during simulations + if simulate { + return next(ctx, tx, simulate) + } + + msgs := tx.GetMsgs() + if err = g.ValidateVoteMsgs(ctx, msgs); err != nil { + return ctx, err + } + + return next(ctx, tx, simulate) +} + +// ValidateVoteMsgs checks if a voter has enough stake to vote +func (g GovVoteDecorator) ValidateVoteMsgs(ctx sdk.Context, msgs []sdk.Msg) error { + validMsg := func(m sdk.Msg) error { + var accAddr sdk.AccAddress + var err error + + switch msg := m.(type) { + case *govv1beta1.MsgVote: + accAddr, err = sdk.AccAddressFromBech32(msg.Voter) + if err != nil { + return err + } + case *govv1.MsgVote: + accAddr, err = sdk.AccAddressFromBech32(msg.Voter) + if err != nil { + return err + } + default: + // not a vote message - nothing to validate + return nil + } + + if minStakedTokens.IsZero() { + return nil + } + + enoughStake := false + delegationCount := 0 + stakedTokens := math.LegacyNewDec(0) + err = g.stakingKeeper.IterateDelegatorDelegations(ctx, accAddr, func(delegation stakingtypes.Delegation) bool { + validatorAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) + if err != nil { + panic(err) // shouldn't happen + } + validator, err := g.stakingKeeper.GetValidator(ctx, validatorAddr) + if err == nil { + shares := delegation.Shares + tokens := validator.TokensFromSharesTruncated(shares) + stakedTokens = stakedTokens.Add(tokens) + if stakedTokens.GTE(minStakedTokens) { + enoughStake = true + return true // break the iteration + } + } + delegationCount++ + // break the iteration if maxDelegationsChecked were already checked + return delegationCount >= maxDelegationsChecked + }) + if err != nil { + return err + } + + if !enoughStake { + return errorsmod.Wrapf(quasarerrors.ErrInsufficientStake, "insufficient stake for voting - min required %v", minStakedTokens) + } + + return nil + } + + validAuthz := func(execMsg *authz.MsgExec) error { + for _, v := range execMsg.Msgs { + var innerMsg sdk.Msg + if err := g.cdc.UnpackAny(v, &innerMsg); err != nil { + return errorsmod.Wrap(quasarerrors.ErrUnauthorized, "cannot unmarshal authz exec msgs") + } + if err := validMsg(innerMsg); err != nil { + return err + } + } + + return nil + } + + for _, m := range msgs { + if msg, ok := m.(*authz.MsgExec); ok { + if err := validAuthz(msg); err != nil { + return err + } + continue + } + + // validate normal msgs + if err := validMsg(m); err != nil { + return err + } + } + return nil +} diff --git a/ante/gov_vote_ante_test.go b/ante/gov_vote_ante_test.go new file mode 100644 index 000000000..cb6066f94 --- /dev/null +++ b/ante/gov_vote_ante_test.go @@ -0,0 +1,272 @@ +package ante_test + +import ( + "github.com/quasar-finance/quasar/ante" + "github.com/quasar-finance/quasar/app/helpers" + "testing" + + "github.com/stretchr/testify/require" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// Test that the GovVoteDecorator rejects v1beta1 vote messages from accounts with less than 1 atom staked +// Submitting v1beta1.VoteMsg should not be possible through the CLI, but it's still possible to craft a transaction +func TestVoteSpamDecoratorGovV1Beta1(t *testing.T) { + quasarApp := helpers.Setup(t) + ctx := quasarApp.NewUncachedContext(true, tmproto.Header{}) + decorator := ante.NewGovVoteDecorator(quasarApp.AppCodec(), quasarApp.StakingKeeper) + stakingKeeper := quasarApp.StakingKeeper + + // Get validator + validators, err := stakingKeeper.GetAllValidators(ctx) + require.NoError(t, err) + valAddr1, err := stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) + require.NoError(t, err) + valAddr1 = sdk.ValAddress(valAddr1) + + // Create one more validator + pk := ed25519.GenPrivKeyFromSecret([]byte{uint8(13)}).PubKey() + validator2, err := stakingtypes.NewValidator( + sdk.ValAddress(pk.Address()).String(), + pk, + stakingtypes.Description{}, + ) + require.NoError(t, err) + valAddr2, err := stakingKeeper.ValidatorAddressCodec().StringToBytes(validator2.GetOperator()) + valAddr2 = sdk.ValAddress(valAddr2) + require.NoError(t, err) + // Make sure the validator is bonded so it's not removed on Undelegate + validator2.Status = stakingtypes.Bonded + err = stakingKeeper.SetValidator(ctx, validator2) + require.NoError(t, err) + err = stakingKeeper.SetValidatorByConsAddr(ctx, validator2) + require.NoError(t, err) + err = stakingKeeper.SetNewValidatorByPowerIndex(ctx, validator2) + require.NoError(t, err) + err = stakingKeeper.Hooks().AfterValidatorCreated(ctx, valAddr2) + require.NoError(t, err) + + // Get delegator (this account was created during setup) + addr, err := quasarApp.AccountKeeper.Accounts.Indexes.Number.MatchExact(ctx, 0) + require.NoError(t, err) + delegator, err := sdk.AccAddressFromBech32(addr.String()) + require.NoError(t, err) + + tests := []struct { + name string + bondAmt math.Int + validators []sdk.ValAddress + expectPass bool + }{ + { + name: "delegate 0 atom", + bondAmt: math.ZeroInt(), + validators: []sdk.ValAddress{valAddr1}, + expectPass: false, + }, + { + name: "delegate 0.1 atom", + bondAmt: math.NewInt(100000), + validators: []sdk.ValAddress{valAddr1}, + expectPass: false, + }, + { + name: "delegate 1 atom", + bondAmt: math.NewInt(1000000), + validators: []sdk.ValAddress{valAddr1}, + expectPass: true, + }, + { + name: "delegate 1 atom to two validators", + bondAmt: math.NewInt(1000000), + validators: []sdk.ValAddress{valAddr1, valAddr2}, + expectPass: true, + }, + { + name: "delegate 0.9 atom to two validators", + bondAmt: math.NewInt(900000), + validators: []sdk.ValAddress{valAddr1, valAddr2}, + expectPass: false, + }, + { + name: "delegate 10 atom", + bondAmt: math.NewInt(10000000), + validators: []sdk.ValAddress{valAddr1}, + expectPass: true, + }, + } + + for _, tc := range tests { + // Unbond all tokens for this delegator + delegations, err := stakingKeeper.GetAllDelegatorDelegations(ctx, delegator) + require.NoError(t, err) + for _, del := range delegations { + valAddr, err := sdk.ValAddressFromBech32(del.GetValidatorAddr()) + require.NoError(t, err) + _, _, err = stakingKeeper.Undelegate(ctx, delegator, valAddr, del.GetShares()) + require.NoError(t, err) + } + + // Delegate tokens + if !tc.bondAmt.IsZero() { + amt := tc.bondAmt.Quo(math.NewInt(int64(len(tc.validators)))) + for _, valAddr := range tc.validators { + val, err := stakingKeeper.GetValidator(ctx, valAddr) + require.NoError(t, err) + _, err = stakingKeeper.Delegate(ctx, delegator, amt, stakingtypes.Unbonded, val, true) + require.NoError(t, err) + } + } + + // Create vote message + msg := govv1beta1.NewMsgVote( + delegator, + 0, + govv1beta1.OptionYes, + ) + + // Validate vote message + err = decorator.ValidateVoteMsgs(ctx, []sdk.Msg{msg}) + if tc.expectPass { + require.NoError(t, err, "expected %v to pass", tc.name) + } else { + require.Error(t, err, "expected %v to fail", tc.name) + } + } +} + +// Test that the GovVoteDecorator rejects v1 vote messages from accounts with less than 1 atom staked +// Usually, only v1.VoteMsg can be submitted using the CLI. +func TestVoteSpamDecoratorGovV1(t *testing.T) { + quasarApp := helpers.Setup(t) + ctx := quasarApp.NewUncachedContext(true, tmproto.Header{}) + decorator := ante.NewGovVoteDecorator(quasarApp.AppCodec(), quasarApp.StakingKeeper) + stakingKeeper := quasarApp.StakingKeeper + + // Get validator + validators, err := stakingKeeper.GetAllValidators(ctx) + require.NoError(t, err) + valAddr1, err := stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) + require.NoError(t, err) + valAddr1 = sdk.ValAddress(valAddr1) + + // Create one more validator + pk := ed25519.GenPrivKeyFromSecret([]byte{uint8(13)}).PubKey() + validator2, err := stakingtypes.NewValidator( + sdk.ValAddress(pk.Address()).String(), + pk, + stakingtypes.Description{}, + ) + require.NoError(t, err) + valAddr2, err := stakingKeeper.ValidatorAddressCodec().StringToBytes(validator2.GetOperator()) + require.NoError(t, err) + valAddr2 = sdk.ValAddress(valAddr2) + // Make sure the validator is bonded so it's not removed on Undelegate + validator2.Status = stakingtypes.Bonded + err = stakingKeeper.SetValidator(ctx, validator2) + require.NoError(t, err) + err = stakingKeeper.SetValidatorByConsAddr(ctx, validator2) + require.NoError(t, err) + err = stakingKeeper.SetNewValidatorByPowerIndex(ctx, validator2) + require.NoError(t, err) + err = stakingKeeper.Hooks().AfterValidatorCreated(ctx, valAddr2) + require.NoError(t, err) + + // Get delegator (this account was created during setup) + addr, err := quasarApp.AccountKeeper.Accounts.Indexes.Number.MatchExact(ctx, 0) + require.NoError(t, err) + delegator, err := sdk.AccAddressFromBech32(addr.String()) + require.NoError(t, err) + + tests := []struct { + name string + bondAmt math.Int + validators []sdk.ValAddress + expectPass bool + }{ + { + name: "delegate 0 atom", + bondAmt: math.ZeroInt(), + validators: []sdk.ValAddress{valAddr1}, + expectPass: false, + }, + { + name: "delegate 0.1 atom", + bondAmt: math.NewInt(100000), + validators: []sdk.ValAddress{valAddr1}, + expectPass: false, + }, + { + name: "delegate 1 atom", + bondAmt: math.NewInt(1000000), + validators: []sdk.ValAddress{valAddr1}, + expectPass: true, + }, + { + name: "delegate 1 atom to two validators", + bondAmt: math.NewInt(1000000), + validators: []sdk.ValAddress{valAddr1, valAddr2}, + expectPass: true, + }, + { + name: "delegate 0.9 atom to two validators", + bondAmt: math.NewInt(900000), + validators: []sdk.ValAddress{valAddr1, valAddr2}, + expectPass: false, + }, + { + name: "delegate 10 atom", + bondAmt: math.NewInt(10000000), + validators: []sdk.ValAddress{valAddr1}, + expectPass: true, + }, + } + + for _, tc := range tests { + // Unbond all tokens for this delegator + delegations, err := stakingKeeper.GetAllDelegatorDelegations(ctx, delegator) + require.NoError(t, err) + for _, del := range delegations { + valAddr, err := sdk.ValAddressFromBech32(del.GetValidatorAddr()) + require.NoError(t, err) + _, _, err = stakingKeeper.Undelegate(ctx, delegator, valAddr, del.GetShares()) + require.NoError(t, err) + } + + // Delegate tokens + if !tc.bondAmt.IsZero() { + amt := tc.bondAmt.Quo(math.NewInt(int64(len(tc.validators)))) + for _, valAddr := range tc.validators { + val, err := stakingKeeper.GetValidator(ctx, valAddr) + require.NoError(t, err) + _, err = stakingKeeper.Delegate(ctx, delegator, amt, stakingtypes.Unbonded, val, true) + require.NoError(t, err) + } + } + + // Create vote message + msg := govv1.NewMsgVote( + delegator, + 0, + govv1.VoteOption_VOTE_OPTION_YES, + "new-v1-vote-message-test", + ) + + // Validate vote message + err = decorator.ValidateVoteMsgs(ctx, []sdk.Msg{msg}) + if tc.expectPass { + require.NoError(t, err, "expected %v to pass", tc.name) + } else { + require.Error(t, err, "expected %v to fail", tc.name) + } + } +} diff --git a/app/app.go b/app/app.go index bda57a41f..db5d338b6 100644 --- a/app/app.go +++ b/app/app.go @@ -2,6 +2,10 @@ package app import ( "fmt" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + "github.com/cosmos/cosmos-sdk/types/msgservice" + "io" "net/http" "os" @@ -11,15 +15,13 @@ import ( autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" "cosmossdk.io/log" - // capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" + "cosmossdk.io/x/tx/signing" upgradetypes "cosmossdk.io/x/upgrade/types" "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - // dbm "github.com/cometbft/cometbft-db" abci "github.com/cometbft/cometbft/abci/types" tmjson "github.com/cometbft/cometbft/libs/json" - // "github.com/cometbft/cometbft/libs/log" tmos "github.com/cometbft/cometbft/libs/os" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" dbm "github.com/cosmos/cosmos-db" @@ -28,25 +30,33 @@ import ( "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/codec/types" runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services" "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/cosmos/cosmos-sdk/std" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + sigtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth/ante" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/crisis" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/cosmos/gogoproto/proto" capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" + ibctesting "github.com/cosmos/ibc-go/v8/testing" ibctestingtypes "github.com/cosmos/ibc-go/v8/testing/types" + "github.com/spf13/cast" + quasarante "github.com/quasar-finance/quasar/ante" "github.com/quasar-finance/quasar/app/keepers" "github.com/quasar-finance/quasar/app/openapiconsole" @@ -55,13 +65,6 @@ import ( v2 "github.com/quasar-finance/quasar/app/upgrades/v2" v3 "github.com/quasar-finance/quasar/app/upgrades/v3" "github.com/quasar-finance/quasar/docs" - "github.com/spf13/cast" -) - -const ( - AccountAddressPrefix = "quasar" - Name = "quasar" - DirName = "quasarnode" ) var ( @@ -74,6 +77,7 @@ var ( // ModuleBasics defines the module BasicManager is in charge of setting up basic, // non-dependant module elements, such as codec registration // and genesis verification. + // todo remove this before v50, keeping it here till we find a better way to handle it for test-setup ModuleBasics = module.NewBasicManager(AppModuleBasics...) // module account permissions @@ -91,7 +95,10 @@ func overrideWasmVariables() { } var ( + // todo + //_ runtime.AppI = (*QuasarApp)(nil) _ servertypes.Application = (*QuasarApp)(nil) + _ ibctesting.TestingApp = (*QuasarApp)(nil) ) func init() { @@ -100,7 +107,7 @@ func init() { panic(err) } - DefaultNodeHome = filepath.Join(userHomeDir, "."+DirName) + DefaultNodeHome = filepath.Join(userHomeDir, "."+appParams.DirName) } // QuasarApp extends an ABCI application, but with most of its parameters exported. @@ -110,13 +117,15 @@ type QuasarApp struct { *baseapp.BaseApp *keepers.AppKeepers - cdc *codec.LegacyAmino + legacyAmino *codec.LegacyAmino appCodec codec.Codec + txConfig client.TxConfig interfaceRegistry types.InterfaceRegistry invCheckPeriod uint // mm is the module manager - mm *module.Manager + mm *module.Manager + ModuleBasics module.BasicManager // sm is the simulation manager sm *module.SimulationManager @@ -133,31 +142,52 @@ func New( skipUpgradeHeights map[int64]bool, homePath string, invCheckPeriod uint, - encodingConfig appParams.EncodingConfig, appOpts servertypes.AppOptions, wasmOpts []wasmkeeper.Option, baseAppOptions ...func(*baseapp.BaseApp), ) *QuasarApp { overrideWasmVariables() - appCodec := encodingConfig.Marshaler - cdc := encodingConfig.Amino - interfaceRegistry := encodingConfig.InterfaceRegistry + + // encoding config starts here + legacyAmino := codec.NewLegacyAmino() + interfaceRegistry, err := types.NewInterfaceRegistryWithOptions(types.InterfaceRegistryOptions{ + ProtoFiles: proto.HybridResolver, + SigningOptions: signing.Options{ + AddressCodec: address.Bech32Codec{ + Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(), + }, + ValidatorAddressCodec: address.Bech32Codec{ + Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(), + }, + }, + }) + if err != nil { + panic(err) + } + appCodec := codec.NewProtoCodec(interfaceRegistry) + txConfig := authtx.NewTxConfig(appCodec, authtx.DefaultSignModes) + + std.RegisterLegacyAminoCodec(legacyAmino) + std.RegisterInterfaces(interfaceRegistry) + // encoding config ends here bApp := baseapp.NewBaseApp( - Name, + appParams.Name, logger, db, - encodingConfig.TxConfig.TxDecoder(), + txConfig.TxDecoder(), baseAppOptions..., ) bApp.SetCommitMultiStoreTracer(traceStore) bApp.SetVersion(version.Version) bApp.SetInterfaceRegistry(interfaceRegistry) + bApp.SetTxEncoder(txConfig.TxEncoder()) app := &QuasarApp{ AppKeepers: &keepers.AppKeepers{}, BaseApp: bApp, - cdc: cdc, + legacyAmino: legacyAmino, + txConfig: txConfig, appCodec: appCodec, interfaceRegistry: interfaceRegistry, invCheckPeriod: invCheckPeriod, @@ -181,13 +211,20 @@ func New( // init special keepers app.InitSpecialKeepers( appCodec, - bApp, cdc, invCheckPeriod, skipUpgradeHeights, homePath) + bApp, + legacyAmino, + invCheckPeriod, + skipUpgradeHeights, + homePath, + logger, + appOpts, + ) // init normal keepers app.InitNormalKeepers( appCodec, - encodingConfig, bApp, + legacyAmino, maccPerms, dataDir, wasmDir, @@ -202,8 +239,26 @@ func New( // NOTE: Any module instantiated in the module manager that is later modified // must be passed by reference here. skipGenesisInvariants := cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants)) - app.mm = module.NewManager(appModules(app, encodingConfig, skipGenesisInvariants)...) + app.mm = module.NewManager(appModules(app, appCodec, txConfig, skipGenesisInvariants)...) + app.ModuleBasics = newBasicManagerFromManager(app) + enabledSignModes := append([]sigtypes.SignMode(nil), authtx.DefaultSignModes...) + enabledSignModes = append(enabledSignModes, sigtypes.SignMode_SIGN_MODE_TEXTUAL) + + txConfigOpts := authtx.ConfigOptions{ + EnabledSignModes: enabledSignModes, + TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(app.BankKeeper), + } + txConfig, err = authtx.NewTxConfigWithOptions( + appCodec, + txConfigOpts, + ) + if err != nil { + panic(err) + } + app.txConfig = txConfig + + // NOTE: upgrade module is required to be prioritized app.mm.SetOrderPreBlockers( upgradetypes.ModuleName, ) @@ -226,11 +281,11 @@ func New( app.mm.SetOrderInitGenesis(orderInitBlockers()...) app.mm.RegisterInvariants(app.CrisisKeeper) - app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()) - app.mm.RegisterServices(app.configurator) - - // REFLECTION - SDK47 + err = app.mm.RegisterServices(app.configurator) + if err != nil { + panic(err) + } autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.mm.Modules)) @@ -240,33 +295,16 @@ func New( } reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc) - /* TODO - SDK50 keeping in pending for now. - // app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) + // add test gRPC service for testing gRPC queries in isolation + testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{}) + // create the simulation manager and define the order of the modules for deterministic simulations - app.sm = module.NewSimulationManager( - auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), - capability.NewAppModule(appCodec, *app.CapabilityKeeper), - feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), - gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), - mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), - staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), - distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), - slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), - params.NewAppModule(app.ParamsKeeper), - evidence.NewAppModule(app.EvidenceKeeper), - wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), - ibc.NewAppModule(app.IBCKeeper), - app.RawIcs20TransferAppModule, - epochsModule, - //qvestingModule, TODO fix or remove - // TODO fix qoracle testing for sim - // qoracleModule, - // TODO fix intergam genesis + testing first (right now, test code does not even compile...) - // intergammModule, - ) + // + // NOTE: this is not required apps that don't use the simulator for fuzz testing + // transactions + app.sm = module.NewSimulationManager(simulationModules(app, appCodec, skipGenesisInvariants)...) + app.sm.RegisterStoreDecoders() - */ // initialize stores app.MountKVStores(app.GetKVStoreKey()) @@ -278,12 +316,15 @@ func New( HandlerOptions: ante.HandlerOptions{ AccountKeeper: app.AccountKeeper, BankKeeper: app.BankKeeper, - SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), FeegrantKeeper: app.FeeGrantKeeper, + SignModeHandler: txConfig.SignModeHandler(), SigGasConsumer: ante.DefaultSigVerificationGasConsumer, }, - Codec: appCodec, - IBCkeeper: app.IBCKeeper, + Codec: appCodec, + IBCkeeper: app.IBCKeeper, + StakingKeeper: app.StakingKeeper, + WasmConfig: &wasmConfig, + TXCounterStoreService: runtime.NewKVStoreService(app.AppKeepers.GetKey(wasmtypes.StoreKey)), }, ) if err != nil { @@ -291,8 +332,9 @@ func New( } app.SetAnteHandler(anteHandler) - app.SetPreBlocker(app.PreBlocker) + app.SetInitChainer(app.InitChainer) + app.SetPreBlocker(app.PreBlocker) app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) @@ -316,6 +358,19 @@ func New( } } + // At startup, after all modules have been registered, check that all prot + // annotations are correct. + protoFiles, err := proto.MergedRegistry() + if err != nil { + panic(err) + } + err = msgservice.ValidateProtoAnnotations(protoFiles) + if err != nil { + // Once we switch to using protoreflect-based antehandlers, we might + // want to panic here instead of logging a warning. + fmt.Fprintln(os.Stderr, err.Error()) + } + if loadLatest { if err := app.LoadLatestVersion(); err != nil { tmos.Exit(err.Error()) @@ -423,8 +478,7 @@ func (app *QuasarApp) ModuleAccountAddrs() map[string]bool { // addresses. func (app *QuasarApp) BlockedModuleAccountAddrs() map[string]bool { modAccAddrs := app.ModuleAccountAddrs() - // TODO: Investigate why gov module in removed from blocked list - // https://github.com/cosmos/gaia/blob/main/app/app.go#L280 + delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String()) return modAccAddrs @@ -435,12 +489,12 @@ func (app *QuasarApp) RegisterNodeService(clientCtx client.Context, cfg config.C nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg) } -// LegacyAmino returns SimApp's amino codec. +// LegacyAmino returns SimApp's legacyAmino codec. // // NOTE: This is solely to be used for testing purposes as it may be desirable // for modules to register their own custom testing types. func (app *QuasarApp) LegacyAmino() *codec.LegacyAmino { - return app.cdc + return app.legacyAmino } // AppCodec returns an app codec. @@ -474,7 +528,7 @@ func (app *QuasarApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.API cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register legacy and grpc-gateway routes for all modules. - ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) + app.ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register node gRPC service for grpc-gateway. nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) @@ -521,7 +575,7 @@ func (app *QuasarApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper { } func (app *QuasarApp) GetTxConfig() client.TxConfig { - return MakeEncodingConfig().TxConfig + return app.txConfig } func (app *QuasarApp) GetStakingKeeper() ibctestingtypes.StakingKeeper { diff --git a/app/encoding.go b/app/encoding.go index 63ce72410..a96573418 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -8,7 +8,7 @@ import ( "github.com/quasar-finance/quasar/app/params" ) -// makeEncodingConfig creates an EncodingConfig for an amino based test configuration. +// makeEncodingConfig creates an EncodingConfig for an legacyAmino based test configuration. func makeEncodingConfig() params.EncodingConfig { amino := codec.NewLegacyAmino() interfaceRegistry := types.NewInterfaceRegistry() diff --git a/app/helpers/test_helpers.go b/app/helpers/test_helpers.go new file mode 100644 index 000000000..88e1e25d0 --- /dev/null +++ b/app/helpers/test_helpers.go @@ -0,0 +1,211 @@ +package helpers + +import ( + "encoding/json" + "os" + "testing" + "time" + + "cosmossdk.io/log" + "cosmossdk.io/math" + abci "github.com/cometbft/cometbft/abci/types" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtypes "github.com/cometbft/cometbft/types" + dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/cosmos-sdk/client/flags" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/server" + "github.com/cosmos/cosmos-sdk/testutil/mock" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/quasar-finance/quasar/app" + "github.com/spf13/cast" + "github.com/spf13/viper" + "github.com/stretchr/testify/require" +) + +// SimAppChainID hardcoded chainID for simulation +const ( + SimAppChainID = "quasar-app" +) + +// DefaultConsensusParams defines the default Tendermint consensus params used +// in quasarApp testing. +var DefaultConsensusParams = &tmproto.ConsensusParams{ + Block: &tmproto.BlockParams{ + MaxBytes: 200000, + MaxGas: 2000000, + }, + Evidence: &tmproto.EvidenceParams{ + MaxAgeNumBlocks: 302400, + MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration + MaxBytes: 10000, + }, + Validator: &tmproto.ValidatorParams{ + PubKeyTypes: []string{ + tmtypes.ABCIPubKeyTypeEd25519, + }, + }, +} + +type PV struct { + PrivKey cryptotypes.PrivKey +} + +type EmptyAppOptions struct{} + +func (EmptyAppOptions) Get(_ string) interface{} { return nil } + +func Setup(t *testing.T) *app.QuasarApp { + t.Helper() + + privVal := mock.NewPV() + pubKey, err := privVal.GetPubKey() + require.NoError(t, err) + // create validator set with single validator + validator := tmtypes.NewValidator(pubKey, 1) + valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) + + // generate genesis account + senderPrivKey := mock.NewPV() + senderPubKey := senderPrivKey.PrivKey.PubKey() + + acc := authtypes.NewBaseAccount(senderPubKey.Address().Bytes(), senderPubKey, 0, 0) + balance := banktypes.Balance{ + Address: acc.GetAddress().String(), + Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(100000000000000))), + } + genesisAccounts := []authtypes.GenesisAccount{acc} + app := SetupWithGenesisValSet(t, valSet, genesisAccounts, balance) + + return app +} + +// SetupWithGenesisValSet initializes a new quasarApp with a validator set and genesis accounts +// that also act as delegators. For simplicity, each validator is bonded with a delegation +// of one consensus engine unit in the default token of the quasarApp from first genesis +// account. A Nop logger is set in quasarApp. +func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *app.QuasarApp { + t.Helper() + + quasarApp, genesisState := setup() + genesisState = genesisStateWithValSet(t, quasarApp, genesisState, valSet, genAccs, balances...) + + stateBytes, err := json.MarshalIndent(genesisState, "", " ") + require.NoError(t, err) + + // init chain will set the validator set and initialize the genesis accounts + _, err = quasarApp.InitChain( + &abci.RequestInitChain{ + Validators: []abci.ValidatorUpdate{}, + ConsensusParams: DefaultConsensusParams, + AppStateBytes: stateBytes, + }, + ) + require.NoError(t, err) + + require.NoError(t, err) + _, err = quasarApp.FinalizeBlock(&abci.RequestFinalizeBlock{ + Height: quasarApp.LastBlockHeight() + 1, + Hash: quasarApp.LastCommitID().Hash, + NextValidatorsHash: valSet.Hash(), + }) + require.NoError(t, err) + + return quasarApp +} + +func setup() (*app.QuasarApp, app.GenesisState) { + dir, err := os.MkdirTemp("", "quasar-test-app") + if err != nil { + panic(err) + } + + appOptions := make(simtestutil.AppOptionsMap, 0) + appOptions[server.FlagInvCheckPeriod] = 5 + appOptions[server.FlagMinGasPrices] = "0uqsr" + + initAppOptions := viper.New() + initAppOptions.Set(flags.FlagHome, dir) + quasarApp := app.New( + log.NewNopLogger(), + dbm.NewMemDB(), + nil, + true, + map[int64]bool{}, + dir, + cast.ToUint(initAppOptions.Get(server.FlagInvCheckPeriod)), + initAppOptions, + app.EmptyWasmOpts, + ) + return quasarApp, quasarApp.ModuleBasics.DefaultGenesis(quasarApp.AppCodec()) +} + +func genesisStateWithValSet(t *testing.T, + app *app.QuasarApp, genesisState app.GenesisState, + valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, + balances ...banktypes.Balance, +) app.GenesisState { + t.Helper() + // set genesis accounts + authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) + genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis) + + validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) + delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) + + bondAmt := sdk.DefaultPowerReduction + + for _, val := range valSet.Validators { + pk, err := cryptocodec.FromCmtPubKeyInterface(val.PubKey) + require.NoError(t, err) + pkAny, err := codectypes.NewAnyWithValue(pk) + require.NoError(t, err) + validator := stakingtypes.Validator{ + OperatorAddress: sdk.ValAddress(val.Address).String(), + ConsensusPubkey: pkAny, + Jailed: false, + Status: stakingtypes.Bonded, + Tokens: bondAmt, + DelegatorShares: math.LegacyOneDec(), + Description: stakingtypes.Description{}, + UnbondingHeight: int64(0), + UnbondingTime: time.Unix(0, 0).UTC(), + Commission: stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()), + } + validators = append(validators, validator) + delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress().String(), sdk.ValAddress(val.Address).String(), math.LegacyOneDec())) + + } + // set validators and delegations + stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations) + genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis) + + totalSupply := sdk.NewCoins() + for _, b := range balances { + // add genesis acc tokens to total supply + totalSupply = totalSupply.Add(b.Coins...) + } + + for range delegations { + // add delegated tokens to total supply + totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)) + } + + // add bonded amount to bonded pool module account + balances = append(balances, banktypes.Balance{ + Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), + Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)}, + }) + + // update total supply + bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}, []banktypes.SendEnabled{}) + genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) + + return genesisState +} diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 3b3684041..0012a093f 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -1,8 +1,7 @@ package keepers import ( - "strings" - + "cosmossdk.io/log" storetypes "cosmossdk.io/store/types" evidencekeeper "cosmossdk.io/x/evidence/keeper" evidencetypes "cosmossdk.io/x/evidence/types" @@ -17,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/runtime" + servertypes "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -68,6 +68,8 @@ import ( tfkeeper "github.com/quasar-finance/quasar/x/tokenfactory/keeper" tfmodulekeeper "github.com/quasar-finance/quasar/x/tokenfactory/keeper" tftypes "github.com/quasar-finance/quasar/x/tokenfactory/types" + "os" + "strings" ) const ( @@ -131,20 +133,27 @@ func (appKeepers *AppKeepers) InitSpecialKeepers( invCheckPeriod uint, skipUpgradeHeights map[int64]bool, homePath string, + logger log.Logger, + appOpts servertypes.AppOptions, ) { appKeepers.GenerateKeys() - appKeepers.ParamsKeeper = appKeepers.initParamsKeeper(appCodec, cdc, appKeepers.keys[paramstypes.StoreKey], appKeepers.tkeys[paramstypes.TStoreKey]) /* - consensusParamsKeeper := consensusparamkeeper.NewKeeper( - appCodec, - appKeepers.keys[consensusparamtypes.StoreKey], - authtypes.NewModuleAddress(govtypes.ModuleName).String(), - ) + configure state listening capabilities using AppOptions + we are doing nothing with the returned streamingServices and waitGroup in this case */ + // load state streaming if enabled + + if err := bApp.RegisterStreamingServices(appOpts, appKeepers.keys); err != nil { + logger.Error("failed to load state streaming", "err", err) + os.Exit(1) + } + + appKeepers.ParamsKeeper = appKeepers.initParamsKeeper(appCodec, cdc, appKeepers.keys[paramstypes.StoreKey], appKeepers.tkeys[paramstypes.TStoreKey]) + consensusParamsKeeper := consensusparamkeeper.NewKeeper(appCodec, runtime.NewKVStoreService(appKeepers.keys[consensusparamtypes.StoreKey]), - authtypes.NewModuleAddress(govtypes.ModuleName).String(), // TODO - govtypes.ModuleName to be checked. + authtypes.NewModuleAddress(govtypes.ModuleName).String(), runtime.EventService{}) appKeepers.ConsensusParamsKeeper = &consensusParamsKeeper @@ -185,8 +194,8 @@ func (appKeepers *AppKeepers) InitSpecialKeepers( // InitNormalKeepers initializes all 'normal' keepers (account, app, bank, auth, staking, distribution, slashing, transfer, IBC router, governance, mint keepers). func (appKeepers *AppKeepers) InitNormalKeepers( appCodec codec.Codec, - encodingConfig appparams.EncodingConfig, bApp *baseapp.BaseApp, + legacyAmino *codec.LegacyAmino, maccPerms map[string][]string, dataDir string, wasmDir string, @@ -195,8 +204,6 @@ func (appKeepers *AppKeepers) InitNormalKeepers( blockedAddress map[string]bool, ibcWasmConfig ibcwasmtypes.WasmConfig, ) { - legacyAmino := encodingConfig.Amino - accountKeeper := authkeeper.NewAccountKeeper( appCodec, runtime.NewKVStoreService(appKeepers.keys[authtypes.StoreKey]), @@ -225,8 +232,8 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.AccountKeeper, appKeepers.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(), - address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), - address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + address.NewBech32Codec(appparams.Bech32PrefixValAddr), + address.NewBech32Codec(appparams.Bech32PrefixConsAddr), ) appKeepers.StakingKeeper = stakingKeeper @@ -284,7 +291,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.StakingKeeper, appKeepers.UpgradeKeeper, appKeepers.ScopedIBCKeeper, - authtypes.NewModuleAddress(govtypes.ModuleName).String(), // TODO - To be verified. + authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) ibcWasmClientKeeper := ibcwasmkeeper.NewKeeperWithConfig( @@ -308,7 +315,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.AccountKeeper, appKeepers.BankKeeper, appKeepers.ScopedTransferKeeper, - authtypes.NewModuleAddress(govtypes.ModuleName).String(), // TODO - To be verified. + authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) appKeepers.TransferKeeper = transferKeeper @@ -323,8 +330,9 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.IBCKeeper.PortKeeper, appKeepers.ScopedICAControllerKeeper, bApp.MsgServiceRouter(), - authtypes.NewModuleAddress(govtypes.ModuleName).String(), // TODO - To be verified. + authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) + icaHostKeeper := icahostkeeper.NewKeeper( appCodec, appKeepers.keys[icahosttypes.StoreKey], @@ -335,8 +343,9 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.AccountKeeper, appKeepers.ScopedICAHostKeeper, bApp.MsgServiceRouter(), - authtypes.NewModuleAddress(govtypes.ModuleName).String(), // TODO - To be verified. + authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) + icaHostKeeper.WithQueryRouter(bApp.GRPCQueryRouter()) appKeepers.ICAHostKeeper = &icaHostKeeper evidenceKeeper := evidencekeeper.NewKeeper( diff --git a/app/modules.go b/app/modules.go index 06351690d..e82cca9fb 100644 --- a/app/modules.go +++ b/app/modules.go @@ -9,9 +9,12 @@ import ( upgradetypes "cosmossdk.io/x/upgrade/types" "github.com/CosmWasm/wasmd/x/wasm" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" + authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" @@ -85,7 +88,6 @@ var AppModuleBasics = []module.AppModuleBasic{ []govclient.ProposalHandler{ paramsclient.ProposalHandler, // upgradeclient.LegacyProposalHandler, - // upgradeclient.LegacyProposalHandler, // ibcclientclient.UpdateClientProposalHandler, // ibcclientclient.UpgradeProposalHandler, }, @@ -109,17 +111,65 @@ var AppModuleBasics = []module.AppModuleBasic{ ibctm.AppModuleBasic{}, } +// ModuleBasics defines the module BasicManager that is in charge of setting up basic, +// non-dependant module elements, such as codec registration +// and genesis verification. +func newBasicManagerFromManager(app *QuasarApp) module.BasicManager { + basicManager := module.NewBasicManagerFromManager( + app.mm, + map[string]module.AppModuleBasic{ + genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), + govtypes.ModuleName: gov.NewAppModuleBasic( + []govclient.ProposalHandler{ + paramsclient.ProposalHandler, + }, + ), + }) + basicManager.RegisterLegacyAminoCodec(app.legacyAmino) + basicManager.RegisterInterfaces(app.interfaceRegistry) + return basicManager +} + +// simulationModules returns modules for simulation manager +// define the order of the modules for deterministic simulations +func simulationModules( + app *QuasarApp, + appCodec codec.Codec, + _ bool, +) []module.AppModuleSimulation { + return []module.AppModuleSimulation{ + auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), + capability.NewAppModule(appCodec, *app.CapabilityKeeper, false), + feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), + gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), + mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, app.GetSubspace(minttypes.ModuleName)), + staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)), + distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)), + slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName), app.interfaceRegistry), + params.NewAppModule(app.ParamsKeeper), + evidence.NewAppModule(app.EvidenceKeeper), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + ibc.NewAppModule(app.IBCKeeper), + wasm.NewAppModule(appCodec, app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.MsgServiceRouter(), app.GetSubspace(wasmtypes.ModuleName)), + app.RawIcs20TransferAppModule, + ica.NewAppModule(&app.ICAControllerKeeper, app.ICAHostKeeper), + + // quasar modules + // empty because no module implements simulation + } +} + func appModules( app *QuasarApp, - encodingConfig appparams.EncodingConfig, + appCodec codec.Codec, + txConfig client.TxEncodingConfig, skipGenesisInvariants bool, ) []module.AppModule { - appCodec := encodingConfig.Marshaler - return []module.AppModule{ genutil.NewAppModule( app.AccountKeeper, app.StakingKeeper, app.BaseApp, - encodingConfig.TxConfig, + txConfig, ), auth.NewAppModule(appCodec, app.AccountKeeper, nil, app.GetSubspace(authtypes.ModuleName)), vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), @@ -132,7 +182,7 @@ func appModules( app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName), app.interfaceRegistry), distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)), staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)), - upgrade.NewAppModule(app.UpgradeKeeper, addresscodec.NewBech32Codec(appparams.AccountAddressPrefix)), + upgrade.NewAppModule(app.UpgradeKeeper, addresscodec.NewBech32Codec(appparams.Bech32PrefixAccAddr)), ibcwasm.NewAppModule(*app.IBCWasmClientKeeper), evidence.NewAppModule(app.EvidenceKeeper), feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), @@ -146,15 +196,12 @@ func appModules( // quasar modules epochsmodule.NewAppModule(*app.EpochsKeeper), - // qoraclemodule.NewAppModule(appCodec, app.QOracleKeeper, app.QOsmosisKeeper), tfmodule.NewAppModule(app.TfKeeper, app.AccountKeeper, app.BankKeeper), - // qvestingmodule.NewAppModule(appCodec, app.QVestingKeeper, app.AccountKeeper, app.BankKeeper), // TODO - TB BE REMOVED } } func orderBeginBlockers() []string { return []string{ - upgradetypes.ModuleName, capabilitytypes.ModuleName, epochsmoduletypes.ModuleName, minttypes.ModuleName, diff --git a/app/params/params.go b/app/params/params.go index 853be880e..7a884a0b4 100644 --- a/app/params/params.go +++ b/app/params/params.go @@ -1,5 +1,12 @@ package params +import ( + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + const ( HumanCoinUnit = "qsr" BaseCoinUnit = "uqsr" @@ -7,6 +14,53 @@ const ( DefaultBondDenom = BaseCoinUnit - AccountAddressPrefix = "quasar" - Name = "quasarnode" + Name = "quasar" + DirName = "quasarnode" + + // Bech32PrefixAccAddr defines the Bech32 prefix of an account's address. + Bech32PrefixAccAddr = "quasar" ) + +var ( + // Bech32PrefixAccPub defines the Bech32 prefix of an account's public key. + Bech32PrefixAccPub = Bech32PrefixAccAddr + "pub" + // Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address. + Bech32PrefixValAddr = Bech32PrefixAccAddr + "valoper" + // Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key. + Bech32PrefixValPub = Bech32PrefixAccAddr + "valoperpub" + // Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address. + Bech32PrefixConsAddr = Bech32PrefixAccAddr + "valcons" + // Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key. + Bech32PrefixConsPub = Bech32PrefixAccAddr + "valconspub" +) + +func init() { + SetAddressPrefixes() +} + +// SetAddressPrefixes builds the Config with Bech32 addressPrefix and publKeyPrefix for accounts, validators, and consensus nodes and verifies that addreeses have correct format. +func SetAddressPrefixes() { + config := sdk.GetConfig() + config.SetBech32PrefixForAccount(Bech32PrefixAccAddr, Bech32PrefixAccPub) + config.SetBech32PrefixForValidator(Bech32PrefixValAddr, Bech32PrefixValPub) + config.SetBech32PrefixForConsensusNode(Bech32PrefixConsAddr, Bech32PrefixConsPub) + + // This is copied from the cosmos sdk v0.43.0-beta1 + // source: https://github.com/cosmos/cosmos-sdk/blob/v0.43.0-beta1/types/address.go#L141 + config.SetAddressVerifier(func(bytes []byte) error { + if len(bytes) == 0 { + return errorsmod.Wrap(sdkerrors.ErrUnknownAddress, "addresses cannot be empty") + } + + if len(bytes) > address.MaxAddrLen { + return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "address max length is %d, got %d, %x", address.MaxAddrLen, len(bytes), bytes) + } + + // TODO: Do we want to allow addresses of lengths other than 20 and 32 bytes? + if len(bytes) != 20 && len(bytes) != 32 { + return errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "address length must be 20 or 32 bytes, got %d, %x", len(bytes), bytes) + } + + return nil + }) +} diff --git a/app/upgrades/v3/constants.go b/app/upgrades/v3/constants.go index d3f65981f..0dd30ec66 100644 --- a/app/upgrades/v3/constants.go +++ b/app/upgrades/v3/constants.go @@ -2,10 +2,7 @@ package v3 import ( store "cosmossdk.io/store/types" - consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" - crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" - icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v8/types" - ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" + circuittypes "cosmossdk.io/x/circuit/types" "github.com/quasar-finance/quasar/app/upgrades" ) @@ -16,12 +13,8 @@ var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, CreateUpgradeHandler: CreateUpgradeHandler, StoreUpgrades: store.StoreUpgrades{ - Added: []string{ // v47 modules - crisistypes.StoreKey, - consensustypes.StoreKey, - ibcwasmtypes.StoreKey, - icqtypes.StoreKey, - // TODO: add circuit module + Added: []string{ + circuittypes.ModuleName, }, Deleted: []string{}, }, diff --git a/cmd/quasard/cmd/bech32.go b/cmd/quasard/cmd/bech32.go new file mode 100644 index 000000000..c9674179b --- /dev/null +++ b/cmd/quasard/cmd/bech32.go @@ -0,0 +1,50 @@ +package cmd + +// DONTCOVER + +import ( + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/types/bech32" +) + +var flagBech32Prefix = "prefix" + +// get cmd to convert any bech32 address to an osmo prefix. +func ConvertBech32Cmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "bech32-convert [bech32 string]", + Short: "Convert any bech32 string to the quasar prefix", + Long: `Convert any bech32 string to the quasar prefix +Especially useful for converting cosmos addresses to quasar addresses + +Example: + quasard bech32-convert cosmos1ey69r37gfxvxg62sh4r0ktpuc46pzjrmz29g45 + `, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + bech32prefix, err := cmd.Flags().GetString(flagBech32Prefix) + if err != nil { + return err + } + + _, bz, err := bech32.DecodeAndConvert(args[0]) + if err != nil { + return err + } + + bech32Addr, err := bech32.ConvertAndEncode(bech32prefix, bz) + if err != nil { + panic(err) + } + + cmd.Println(bech32Addr) + + return nil + }, + } + + cmd.Flags().StringP(flagBech32Prefix, "p", "quasar", "Bech32 Prefix to encode to") + + return cmd +} diff --git a/cmd/quasard/cmd/config.go b/cmd/quasard/cmd/config.go index bb130df7e..c1272eace 100644 --- a/cmd/quasard/cmd/config.go +++ b/cmd/quasard/cmd/config.go @@ -2,36 +2,20 @@ package cmd import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/quasar-finance/quasar/app" + appparams "github.com/quasar-finance/quasar/app/params" ) func InitTestConfig() { // Set prefixes - accountPubKeyPrefix := app.AccountAddressPrefix + "pub" - validatorAddressPrefix := app.AccountAddressPrefix + "valoper" - validatorPubKeyPrefix := app.AccountAddressPrefix + "valoperpub" - consNodeAddressPrefix := app.AccountAddressPrefix + "valcons" - consNodePubKeyPrefix := app.AccountAddressPrefix + "valconspub" + accountPubKeyPrefix := appparams.Bech32PrefixAccAddr + "pub" + validatorAddressPrefix := appparams.Bech32PrefixAccAddr + "valoper" + validatorPubKeyPrefix := appparams.Bech32PrefixAccAddr + "valoperpub" + consNodeAddressPrefix := appparams.Bech32PrefixAccAddr + "valcons" + consNodePubKeyPrefix := appparams.Bech32PrefixAccAddr + "valconspub" // Set and seal config config := sdk.GetConfig() - config.SetBech32PrefixForAccount(app.AccountAddressPrefix, accountPubKeyPrefix) + config.SetBech32PrefixForAccount(appparams.Bech32PrefixAccAddr, accountPubKeyPrefix) config.SetBech32PrefixForValidator(validatorAddressPrefix, validatorPubKeyPrefix) config.SetBech32PrefixForConsensusNode(consNodeAddressPrefix, consNodePubKeyPrefix) } - -func initSDKConfig() { - // Set prefixes - accountPubKeyPrefix := app.AccountAddressPrefix + "pub" - validatorAddressPrefix := app.AccountAddressPrefix + "valoper" - validatorPubKeyPrefix := app.AccountAddressPrefix + "valoperpub" - consNodeAddressPrefix := app.AccountAddressPrefix + "valcons" - consNodePubKeyPrefix := app.AccountAddressPrefix + "valconspub" - - // Set and seal config - config := sdk.GetConfig() - config.SetBech32PrefixForAccount(app.AccountAddressPrefix, accountPubKeyPrefix) - config.SetBech32PrefixForValidator(validatorAddressPrefix, validatorPubKeyPrefix) - config.SetBech32PrefixForConsensusNode(consNodeAddressPrefix, consNodePubKeyPrefix) - config.Seal() -} diff --git a/cmd/quasard/cmd/root.go b/cmd/quasard/cmd/root.go index 905399a50..6a05453f4 100644 --- a/cmd/quasard/cmd/root.go +++ b/cmd/quasard/cmd/root.go @@ -11,6 +11,8 @@ import ( "cosmossdk.io/store/snapshots" snapshottypes "cosmossdk.io/store/snapshots/types" storetypes "cosmossdk.io/store/types" + confixcmd "cosmossdk.io/tools/confix/cmd" + rosettaCmd "cosmossdk.io/tools/rosetta/cmd" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" tmcfg "github.com/cometbft/cometbft/config" tmcli "github.com/cometbft/cometbft/libs/cli" @@ -22,10 +24,15 @@ import ( "github.com/cosmos/cosmos-sdk/client/debug" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/client/pruning" "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/client/snapshot" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/server" serverconfig "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/cosmos/cosmos-sdk/types/module" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -34,27 +41,49 @@ import ( genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/prometheus/client_golang/prometheus" - "github.com/quasar-finance/quasar/app" - appparams "github.com/quasar-finance/quasar/app/params" "github.com/spf13/cast" "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/quasar-finance/quasar/app" + appparams "github.com/quasar-finance/quasar/app/params" ) // NewRootCmd creates a new root command for a Cosmos SDK application -func NewRootCmd() (*cobra.Command, appparams.EncodingConfig) { - encodingConfig := app.MakeEncodingConfig() +func NewRootCmd() *cobra.Command { + // we "pre"-instantiate the application for getting the injected/configured encoding configuration + initAppOptions := viper.New() + tempDir := tempDir() + initAppOptions.Set(flags.FlagHome, tempDir) + tempApplication := app.New( + log.NewNopLogger(), + dbm.NewMemDB(), + nil, + true, + map[int64]bool{}, + tempDir, + cast.ToUint(initAppOptions.Get(server.FlagInvCheckPeriod)), + initAppOptions, + app.EmptyWasmOpts, + ) + defer func() { + if err := tempApplication.Close(); err != nil { + panic(err) + } + }() + initClientCtx := client.Context{}. - WithCodec(encodingConfig.Marshaler). - WithInterfaceRegistry(encodingConfig.InterfaceRegistry). - WithTxConfig(encodingConfig.TxConfig). - WithLegacyAmino(encodingConfig.Amino). + WithCodec(tempApplication.AppCodec()). + WithInterfaceRegistry(tempApplication.InterfaceRegistry()). + WithTxConfig(tempApplication.GetTxConfig()). + WithLegacyAmino(tempApplication.LegacyAmino()). WithInput(os.Stdin). WithAccountRetriever(types.AccountRetriever{}). WithHomeDir(app.DefaultNodeHome). WithViper("") rootCmd := &cobra.Command{ - Use: app.Name + "d", + Use: appparams.Name + "d", Short: "Start Quasar QuasarApp", PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { // set the default command outputs @@ -81,9 +110,9 @@ func NewRootCmd() (*cobra.Command, appparams.EncodingConfig) { }, } - initRootCmd(rootCmd, encodingConfig) + initRootCmd(rootCmd, tempApplication.ModuleBasics, tempApplication.AppCodec(), tempApplication.InterfaceRegistry(), tempApplication.GetTxConfig()) - return rootCmd, encodingConfig + return rootCmd } // initTendermintConfig helps to override default Tendermint Config values. @@ -97,56 +126,65 @@ func initTendermintConfig() *tmcfg.Config { func initRootCmd( rootCmd *cobra.Command, - encodingConfig appparams.EncodingConfig, + basicManager module.BasicManager, + cdc codec.Codec, + interfaceRegistry codectypes.InterfaceRegistry, + txConfig client.TxConfig, ) { - // Set config - initSDKConfig() - gentxModule := app.ModuleBasics[genutiltypes.ModuleName].(genutil.AppModuleBasic) + + ac := appCreator{} + + debugCmd := debug.Cmd() + debugCmd.AddCommand(ConvertBech32Cmd()) + + gentxModule := basicManager[genutiltypes.ModuleName].(genutil.AppModuleBasic) rootCmd.AddCommand( - genutilcli.InitCmd(app.ModuleBasics, app.DefaultNodeHome), + genutilcli.InitCmd(basicManager, app.DefaultNodeHome), + tmcli.NewCompletionCmd(rootCmd, true), + // todo add testnet commands + confixcmd.ConfigCommand(), + pruning.Cmd(ac.newApp, app.DefaultNodeHome), + snapshot.Cmd(ac.newApp), genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome, gentxModule.GenTxValidator, - encodingConfig.TxConfig.SigningContext().ValidatorAddressCodec()), - // genutilcli.MigrateGenesisCmd(), TODO - SDK 50. Genesis Map To be provided. + txConfig.SigningContext().ValidatorAddressCodec()), genutilcli.GenTxCmd( - app.ModuleBasics, - encodingConfig.TxConfig, + basicManager, + txConfig, banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome, - encodingConfig.TxConfig.SigningContext().ValidatorAddressCodec(), + txConfig.SigningContext().ValidatorAddressCodec(), ), - genutilcli.ValidateGenesisCmd(app.ModuleBasics), + genutilcli.ValidateGenesisCmd(basicManager), AddGenesisAccountCmd(app.DefaultNodeHome), - tmcli.NewCompletionCmd(rootCmd, true), - debug.Cmd(), + debugCmd, // config.Cmd(), TODO - SDK 50. Config support to be added. https://github.com/neutron-org/neutron/blob/feat/sdk-50/cmd/neutrond/config.go ) - a := appCreator{ - encodingConfig, - } - // add server commands server.AddCommands( rootCmd, app.DefaultNodeHome, - a.newApp, - a.appExport, + ac.newApp, + ac.appExport, addModuleInitFlags, ) // add keybase, auxiliary RPC, query, and tx child commands rootCmd.AddCommand( server.StatusCommand(), - queryCommand(), - txCommand(), + queryCommand(basicManager), + txCommand(basicManager), keys.Commands(), ) + + // add rosetta + rootCmd.AddCommand(rosettaCmd.RosettaCommand(interfaceRegistry, cdc)) } // queryCommand returns the sub-command to send queries to the app -func queryCommand() *cobra.Command { +func queryCommand(basicManager module.BasicManager) *cobra.Command { cmd := &cobra.Command{ Use: "query", Aliases: []string{"q"}, @@ -165,14 +203,14 @@ func queryCommand() *cobra.Command { authcmd.QueryTxsByEventsCmd(), ) - app.ModuleBasics.AddQueryCommands(cmd) + basicManager.AddQueryCommands(cmd) cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") return cmd } // txCommand returns the sub-command to send transactions to the app -func txCommand() *cobra.Command { +func txCommand(basicManager module.BasicManager) *cobra.Command { cmd := &cobra.Command{ Use: "tx", Short: "Transactions subcommands", @@ -192,7 +230,10 @@ func txCommand() *cobra.Command { authcmd.GetDecodeCommand(), ) - app.ModuleBasics.AddTxCommands(cmd) + // NOTE: this must be registered for now so that submit-legacy-proposal + // message (e.g. consumer-addition proposal) can be routed to the its handler and processed correctly. + basicManager.AddTxCommands(cmd) + cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") return cmd @@ -268,7 +309,6 @@ func (a appCreator) newApp( skipUpgradeHeights, cast.ToString(appOpts.Get(flags.FlagHome)), cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)), - a.encodingConfig, appOpts, wasmOpts, baseapp.SetChainID(chainID), @@ -286,6 +326,7 @@ func (a appCreator) newApp( ) } +// todo fix app export // appExport creates a new simapp (optionally at a given height) func (a appCreator) appExport( logger log.Logger, @@ -314,7 +355,6 @@ func (a appCreator) appExport( map[int64]bool{}, homePath, uint(1), - a.encodingConfig, appOpts, app.EmptyWasmOpts, ) @@ -383,3 +423,13 @@ lru_size = 0` return customAppTemplate, customAppConfig } + +var tempDir = func() string { + dir, err := os.MkdirTemp("", ".quasarnode") + if err != nil { + dir = app.DefaultNodeHome + } + defer os.RemoveAll(dir) + + return dir +} diff --git a/cmd/quasard/main.go b/cmd/quasard/main.go index 3b4a9ea5c..213f221fc 100644 --- a/cmd/quasard/main.go +++ b/cmd/quasard/main.go @@ -4,15 +4,18 @@ import ( "os" svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" + "github.com/quasar-finance/quasar/app" + appparams "github.com/quasar-finance/quasar/app/params" "github.com/quasar-finance/quasar/cmd/quasard/cmd" ) // "Looks good to me. Ready for launch. LFG" -@valeyo func main() { - rootCmd, _ := cmd.NewRootCmd() + appparams.SetAddressPrefixes() + rootCmd := cmd.NewRootCmd() - if err := svrcmd.Execute(rootCmd, "OSMOSISD", app.DefaultNodeHome); err != nil { + if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil { os.Exit(1) } } diff --git a/go.mod b/go.mod index 484a8812b..29842da9c 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,18 @@ go 1.22.4 require ( cosmossdk.io/api v0.7.5 + cosmossdk.io/client/v2 v2.0.0-beta.3 // indirect cosmossdk.io/core v0.11.0 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.3.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.0 + cosmossdk.io/tools/confix v0.1.1 + cosmossdk.io/tools/rosetta v0.2.1-0.20230613133644-0a778132a60f + cosmossdk.io/x/circuit v0.1.0 cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 + cosmossdk.io/x/tx v0.13.3 cosmossdk.io/x/upgrade v0.1.4 github.com/CosmWasm/wasmd v0.51.0 github.com/CosmWasm/wasmvm/v2 v2.0.1 @@ -44,9 +49,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/storage v1.38.0 // indirect - cosmossdk.io/client/v2 v2.0.0-beta.3 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect - cosmossdk.io/x/tx v0.13.3 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/4meepo/tagalign v1.3.4 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -202,7 +205,6 @@ require ( github.com/ldez/tagliatelle v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/linxGnu/grocksdb v1.8.14 // indirect github.com/lufeee/execinquery v1.2.1 // indirect github.com/macabu/inamedparam v0.1.3 // indirect @@ -265,7 +267,7 @@ require ( github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.19.0 // indirect + github.com/spf13/viper v1.19.0 github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect github.com/stretchr/objx v0.5.2 // indirect @@ -333,9 +335,16 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) +require ( + github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect + github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect + github.com/creachadair/atomicfile v0.3.1 // indirect + github.com/creachadair/tomledit v0.0.24 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect +) + require ( cosmossdk.io/collections v0.4.0 // indirect - // github.com/CosmWasm/wasmvm/v2 v2.0.1 // indirect github.com/DataDog/datadog-go v3.2.0+incompatible // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/cosmos/cosmos-db v1.0.2 diff --git a/go.sum b/go.sum index 96c121888..ce541a424 100644 --- a/go.sum +++ b/go.sum @@ -206,6 +206,10 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/store v1.1.0 h1:LnKwgYMc9BInn9PhpTFEQVbL9UK475G2H911CGGnWHk= cosmossdk.io/store v1.1.0/go.mod h1:oZfW/4Fc/zYqu3JmQcQdUJ3fqu5vnYTn3LZFFy8P8ng= +cosmossdk.io/tools/confix v0.1.1 h1:aexyRv9+y15veH3Qw16lxQwo+ki7r2I+g0yNTEFEQM8= +cosmossdk.io/tools/confix v0.1.1/go.mod h1:nQVvP1tHsGXS83PonPVWJtSbddIqyjEw99L4M3rPJyQ= +cosmossdk.io/tools/rosetta v0.2.1-0.20230613133644-0a778132a60f h1:p/pez1Q7Xwh9AiHWMA0uHxsB+XpReABHr6xCyMWdDAg= +cosmossdk.io/tools/rosetta v0.2.1-0.20230613133644-0a778132a60f/go.mod h1:kzkqn95F9UonJTmjS+aydreXxsWiaGKe/b4HxHZvwHM= cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= cosmossdk.io/x/circuit v0.1.0/go.mod h1:YDzblVE8+E+urPYQq5kq5foRY/IzhXovSYXb4nwd39w= cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= @@ -402,6 +406,8 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= +github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= github.com/cometbft/cometbft v0.38.9 h1:cJBJBG0mPKz+sqelCi/hlfZjadZQGdDNnu6YQ1ZsUHQ= github.com/cometbft/cometbft v0.38.9/go.mod h1:xOoGZrtUT+A5izWfHSJgl0gYZUE7lu7Z2XIS1vWG/QQ= github.com/cometbft/cometbft-db v0.11.0 h1:M3Lscmpogx5NTbb1EGyGDaFRdsoLWrUWimFEyf7jej8= @@ -445,9 +451,15 @@ github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= +github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creachadair/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q= +github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= +github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ= +github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= diff --git a/scripts/makefiles/build.mk b/scripts/makefiles/build.mk index 1607aef0a..b0fabc6e8 100644 --- a/scripts/makefiles/build.mk +++ b/scripts/makefiles/build.mk @@ -45,7 +45,7 @@ DEBUG_BUILD_FLAGS:= $(subst $(REMOVE_STRING),,$(BUILD_FLAGS)) DEBUG_LDFLAGS = $(subst $(REMOVE_STRING),,$(ldflags)) build-dev-install: go.sum - GOWORK=off go install $(DEBUG_BUILD_FLAGS) $(GC_FLAGS) $(GO_MODULE)/cmd/quasarnoded + GOWORK=off go install $(DEBUG_BUILD_FLAGS) $(GC_FLAGS) $(GO_MODULE)/cmd/quasard build-dev-build: mkdir -p $(BUILDDIR)/ @@ -67,12 +67,12 @@ build-reproducible-amd64: go.sum --build-arg GIT_VERSION=$(VERSION) \ --build-arg GIT_COMMIT=$(COMMIT) \ --platform linux/amd64 \ - -t quasar:local-amd64 \ + -t quasar-amd64 \ --load \ -f Dockerfile . $(DOCKER) rm -f quasarbinary || true - $(DOCKER) create -ti --name quasarbinary quasar:local-amd64 - $(DOCKER) cp quasarbinary:/bin/quasarnoded $(BUILDDIR)/quasarnoded-linux-amd64 + $(DOCKER) create -ti --name quasarbinary quasar-amd64 + $(DOCKER) cp quasarbinary:/bin/quasard $(BUILDDIR)/quasard-linux-amd64 $(DOCKER) rm -f quasarbinary build-reproducible-arm64: go.sum @@ -90,7 +90,7 @@ build-reproducible-arm64: go.sum -f Dockerfile . $(DOCKER) rm -f quasarbinary || true $(DOCKER) create -ti --name quasarbinary quasar-arm64 - $(DOCKER) cp quasarbinary:/bin/quasarnoded $(BUILDDIR)/quasarnoded-linux-arm64 + $(DOCKER) cp quasarbinary:/bin/quasard $(BUILDDIR)/quasard-linux-arm64 $(DOCKER) rm -f quasarbinary go.sum: go.mod diff --git a/types/errors/errors.go b/types/errors/errors.go new file mode 100644 index 000000000..0b1962dee --- /dev/null +++ b/types/errors/errors.go @@ -0,0 +1,40 @@ +package errors + +import ( + errorsmod "cosmossdk.io/errors" +) + +const codespace = "gaia" + +var ( + // ErrTxDecode is returned if we cannot parse a transaction + ErrTxDecode = errorsmod.Register(codespace, 1, "tx parse error") + // ErrUnauthorized is used whenever a request without sufficient + // authorization is handled. + ErrUnauthorized = errorsmod.Register(codespace, 2, "unauthorized") + + // ErrInsufficientFunds is used when the account cannot pay requested amount. + ErrInsufficientFunds = errorsmod.Register(codespace, 3, "insufficient funds") + + // ErrInsufficientFunds is used when the account cannot pay requested amount. + ErrInsufficientFee = errorsmod.Register(codespace, 4, "insufficient fee") + + // ErrInvalidCoins is used when sdk.Coins are invalid. + ErrInvalidCoins = errorsmod.Register(codespace, 5, "invalid coins") + + // ErrInvalidType defines an error an invalid type. + ErrInvalidType = errorsmod.Register(codespace, 6, "invalid type") + + // ErrLogic defines an internal logic error, e.g. an invariant or assertion + // that is violated. It is a programmer error, not a user-facing error. + ErrLogic = errorsmod.Register(codespace, 7, "internal logic error") + + // ErrNotFound defines an error when requested entity doesn't exist in the state. + ErrNotFound = errorsmod.Register(codespace, 8, "not found") + + // ErrInsufficientStake is used when the account has insufficient staked tokens. + ErrInsufficientStake = errorsmod.Register(codespace, 9, "insufficient stake") + + // ErrInvalidExpeditedProposal is used when an expedite proposal is submitted for an unsupported proposal type. + ErrInvalidExpeditedProposal = errorsmod.Register(codespace, 10, "unsupported expedited proposal type") +) diff --git a/x/tokenfactory/bindings/custom_query_test.go b/x/tokenfactory/bindings/custom_query_test.go index 1aad03124..c8cc0d2fa 100644 --- a/x/tokenfactory/bindings/custom_query_test.go +++ b/x/tokenfactory/bindings/custom_query_test.go @@ -6,7 +6,7 @@ import ( "fmt" "testing" - wasmvmtypes "github.com/CosmWasm/wasmvm/types" + wasmvmtypes "github.com/CosmWasm/wasmvm/v2/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/quasar-finance/quasar/app" bindings "github.com/quasar-finance/quasar/x/tokenfactory/bindings/types" diff --git a/x/tokenfactory/keeper/keeper.go b/x/tokenfactory/keeper/keeper.go index 80aaae533..1b540e537 100644 --- a/x/tokenfactory/keeper/keeper.go +++ b/x/tokenfactory/keeper/keeper.go @@ -89,6 +89,5 @@ func (k *Keeper) SetContractKeeper(contractKeeper types.ContractKeeper) { // it purely mints and burns them on behalf of the admin of respective denoms, // and sends to the relevant address. func (k Keeper) CreateModuleAccount(ctx sdk.Context) { - moduleAcc := authtypes.NewEmptyModuleAccount(types.ModuleName, authtypes.Minter, authtypes.Burner) - k.accountKeeper.SetModuleAccount(ctx, moduleAcc) + k.accountKeeper.GetModuleAccount(ctx, types.ModuleName) }