Merge PR #4847: Sim refactor 1 move store decoders to modules

* move store decoders to modules

* fix

* module pattern

* compile

* update Decoders params

* fix

* address @colin-axner comments

* Update cmd_test.go

* simulation manager

* mino fixes

* cleanup

* Apply suggestions from code review

Co-Authored-By: frog power 4000 <rigel.rozanski@gmail.com>

* address @rigelrozanski comments

* changelog

* Apply suggestions from code review

Co-Authored-By: colin axner <colinaxner@berkeley.edu>

* restructure modules simulation pkgs

* address @alexanderbez comments

* fix
This commit is contained in:
Federico Kunze 2019-08-14 00:16:03 +02:00 committed by frog power 4000
parent 81f86fefe5
commit c441ce2fab
43 changed files with 1377 additions and 877 deletions

View File

@ -60,6 +60,9 @@ longer panics if the store to load contains substores that we didn't explicitly
* (simulation) [\#4824](https://github.com/cosmos/cosmos-sdk/issues/4824) PrintAllInvariants flag will print all failed invariants
* (simulation) [\#4490](https://github.com/cosmos/cosmos-sdk/issues/4490) add `InitialBlockHeight` flag to resume a simulation from a given block
* Support exporting the simulation stats to a given JSON file
* (simulation) [\#4847](https://github.com/cosmos/cosmos-sdk/issues/4847) `SimApp` and simulation refactors
* Implement `SimulationManager` for executing modules' simulation functionalities in a modularized way
* Add `DecodeStore` to the `SimulationManager` for decoding each module's types
* (simulation) [\#4893](https://github.com/cosmos/cosmos-sdk/issues/4893) Change SimApp keepers to be public and add getter functions for keys and codec
* (store) [\#4792](https://github.com/cosmos/cosmos-sdk/issues/4792) panic on non-registered store
* (types) [\#4821](https://github.com/cosmos/cosmos-sdk/issues/4821) types/errors package added with support for stacktraces. It is meant as a more feature-rich replacement for sdk.Errors in the mid-term.

View File

@ -1,4 +1,3 @@
// nolint: misspell
package client_test
import (
@ -38,10 +37,10 @@ func TestValidateCmd(t *testing.T) {
args []string
wantErr bool
}{
{"misspelled command", []string{"comission"}, true},
{"misspelled command", []string{"comission"}, true}, // nolint: misspell
{"no command provided", []string{}, false},
{"help flag", []string{"comission", "--help"}, false},
{"shorthand help flag", []string{"comission", "-h"}, false},
{"help flag", []string{"comission", "--help"}, false}, // nolint: misspell
{"shorthand help flag", []string{"comission", "-h"}, false}, // nolint: misspell
}
for _, tt := range tests {

View File

@ -103,6 +103,9 @@ type SimApp struct {
// the module manager
mm *module.Manager
// simulation manager
sm *module.SimulationManager
}
// NewSimApp returns a reference to an initialized SimApp.
@ -202,6 +205,9 @@ func NewSimApp(
app.mm.RegisterInvariants(&app.CrisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter())
app.sm = module.NewSimulationManager(app.mm.Modules)
app.sm.RegisterStoreDecoders()
// initialize stores
app.MountKVStores(keys)
app.MountTransientStores(tkeys)

View File

@ -20,20 +20,20 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authsim "github.com/cosmos/cosmos-sdk/x/auth/simulation"
"github.com/cosmos/cosmos-sdk/x/bank"
authsimops "github.com/cosmos/cosmos-sdk/x/auth/simulation/operations"
banksimops "github.com/cosmos/cosmos-sdk/x/bank/simulation/operations"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
distrsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation"
distrsimops "github.com/cosmos/cosmos-sdk/x/distribution/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/gov"
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
govsimops "github.com/cosmos/cosmos-sdk/x/gov/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/params"
paramsim "github.com/cosmos/cosmos-sdk/x/params/simulation"
paramsimops "github.com/cosmos/cosmos-sdk/x/params/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/simulation"
"github.com/cosmos/cosmos-sdk/x/slashing"
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
slashingsimops "github.com/cosmos/cosmos-sdk/x/slashing/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingsim "github.com/cosmos/cosmos-sdk/x/staking/simulation"
stakingsimops "github.com/cosmos/cosmos-sdk/x/staking/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/supply"
)
@ -184,7 +184,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
authsim.SimulateDeductFee(app.AccountKeeper, app.SupplyKeeper),
authsimops.SimulateDeductFee(app.AccountKeeper, app.SupplyKeeper),
},
{
func(_ *rand.Rand) int {
@ -195,7 +195,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
bank.SimulateMsgSend(app.AccountKeeper, app.BankKeeper),
banksimops.SimulateMsgSend(app.AccountKeeper, app.BankKeeper),
},
{
func(_ *rand.Rand) int {
@ -206,7 +206,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
bank.SimulateSingleInputMsgMultiSend(app.AccountKeeper, app.BankKeeper),
banksimops.SimulateSingleInputMsgMultiSend(app.AccountKeeper, app.BankKeeper),
},
{
func(_ *rand.Rand) int {
@ -217,7 +217,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
distrsim.SimulateMsgSetWithdrawAddress(app.AccountKeeper, app.DistrKeeper),
distrsimops.SimulateMsgSetWithdrawAddress(app.DistrKeeper),
},
{
func(_ *rand.Rand) int {
@ -228,7 +228,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
distrsim.SimulateMsgWithdrawDelegatorReward(app.AccountKeeper, app.DistrKeeper),
distrsimops.SimulateMsgWithdrawDelegatorReward(app.DistrKeeper),
},
{
func(_ *rand.Rand) int {
@ -239,7 +239,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
distrsim.SimulateMsgWithdrawValidatorCommission(app.AccountKeeper, app.DistrKeeper),
distrsimops.SimulateMsgWithdrawValidatorCommission(app.DistrKeeper),
},
{
func(_ *rand.Rand) int {
@ -250,7 +250,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, govsim.SimulateTextProposalContent),
govsimops.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, govsimops.SimulateTextProposalContent),
},
{
func(_ *rand.Rand) int {
@ -261,7 +261,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, distrsim.SimulateCommunityPoolSpendProposalContent(app.DistrKeeper)),
govsimops.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, distrsimops.SimulateCommunityPoolSpendProposalContent(app.DistrKeeper)),
},
{
func(_ *rand.Rand) int {
@ -272,7 +272,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
govsim.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, paramsim.SimulateParamChangeProposalContent),
govsimops.SimulateSubmittingVotingAndSlashingForProposal(app.GovKeeper, paramsimops.SimulateParamChangeProposalContent),
},
{
func(_ *rand.Rand) int {
@ -283,7 +283,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
govsim.SimulateMsgDeposit(app.GovKeeper),
govsimops.SimulateMsgDeposit(app.GovKeeper),
},
{
func(_ *rand.Rand) int {
@ -294,7 +294,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
stakingsim.SimulateMsgCreateValidator(app.AccountKeeper, app.StakingKeeper),
stakingsimops.SimulateMsgCreateValidator(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
@ -305,7 +305,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
stakingsim.SimulateMsgEditValidator(app.StakingKeeper),
stakingsimops.SimulateMsgEditValidator(app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
@ -316,7 +316,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
stakingsim.SimulateMsgDelegate(app.AccountKeeper, app.StakingKeeper),
stakingsimops.SimulateMsgDelegate(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
@ -327,7 +327,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
stakingsim.SimulateMsgUndelegate(app.AccountKeeper, app.StakingKeeper),
stakingsimops.SimulateMsgUndelegate(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
@ -338,7 +338,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
stakingsim.SimulateMsgBeginRedelegate(app.AccountKeeper, app.StakingKeeper),
stakingsimops.SimulateMsgBeginRedelegate(app.AccountKeeper, app.StakingKeeper),
},
{
func(_ *rand.Rand) int {
@ -349,7 +349,7 @@ func testAndRunTxs(app *SimApp) []simulation.WeightedOperation {
})
return v
}(nil),
slashingsim.SimulateMsgUnjail(app.SlashingKeeper),
slashingsimops.SimulateMsgUnjail(app.SlashingKeeper),
},
}
}
@ -597,11 +597,15 @@ func TestAppImportExport(t *testing.T) {
storeKeyA := storeKeysPrefix.A
storeKeyB := storeKeysPrefix.B
prefixes := storeKeysPrefix.Prefixes
storeA := ctxA.KVStore(storeKeyA)
storeB := ctxB.KVStore(storeKeyB)
failedKVs := sdk.DiffKVStores(storeA, storeB, prefixes)
fmt.Printf("Compared %d key/value pairs between %s and %s\n", len(failedKVs)/2, storeKeyA, storeKeyB)
require.Len(t, failedKVs, 0, GetSimulationLog(storeKeyA.Name(), app.cdc, newApp.cdc, failedKVs))
failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, prefixes)
require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare")
fmt.Printf("Compared %d key/value pairs between %s and %s\n", len(failedKVAs), storeKeyA, storeKeyB)
require.Len(t, failedKVAs, 0, GetSimulationLog(storeKeyA.Name(), app.sm.StoreDecoders, app.cdc, failedKVAs, failedKVBs))
}
}

View File

@ -2,8 +2,6 @@
package simapp
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"io"
@ -11,7 +9,6 @@ import (
"math/rand"
"time"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/secp256k1"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/libs/log"
@ -500,242 +497,21 @@ func GenStakingGenesisState(
// GetSimulationLog unmarshals the KVPair's Value to the corresponding type based on the
// each's module store key and the prefix bytes of the KVPair's key.
func GetSimulationLog(storeName string, cdcA, cdcB *codec.Codec, kvs []cmn.KVPair) (log string) {
var kvA, kvB cmn.KVPair
for i := 0; i < len(kvs); i += 2 {
kvA = kvs[i]
kvB = kvs[i+1]
func GetSimulationLog(storeName string, sdr sdk.StoreDecoderRegistry, cdc *codec.Codec, kvAs, kvBs []cmn.KVPair) (log string) {
for i := 0; i < len(kvAs); i++ {
if len(kvA.Value) == 0 && len(kvB.Value) == 0 {
if len(kvAs[i].Value) == 0 && len(kvBs[i].Value) == 0 {
// skip if the value doesn't have any bytes
continue
}
switch storeName {
case auth.StoreKey:
log += DecodeAccountStore(cdcA, cdcB, kvA, kvB)
case mint.StoreKey:
log += DecodeMintStore(cdcA, cdcB, kvA, kvB)
case staking.StoreKey:
log += DecodeStakingStore(cdcA, cdcB, kvA, kvB)
case slashing.StoreKey:
log += DecodeSlashingStore(cdcA, cdcB, kvA, kvB)
case gov.StoreKey:
log += DecodeGovStore(cdcA, cdcB, kvA, kvB)
case distribution.StoreKey:
log += DecodeDistributionStore(cdcA, cdcB, kvA, kvB)
case supply.StoreKey:
log += DecodeSupplyStore(cdcA, cdcB, kvA, kvB)
default:
log += fmt.Sprintf("store A %X => %X\nstore B %X => %X\n", kvA.Key, kvA.Value, kvB.Key, kvB.Value)
decoder, ok := sdr[storeName]
if ok {
log += decoder(cdc, kvAs[i], kvBs[i])
} else {
log += fmt.Sprintf("store A %X => %X\nstore B %X => %X\n", kvAs[i].Key, kvAs[i].Value, kvBs[i].Key, kvBs[i].Value)
}
}
return
}
// DecodeAccountStore unmarshals the KVPair's Value to the corresponding auth type
func DecodeAccountStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], auth.AddressStoreKeyPrefix):
var accA, accB auth.Account
cdcA.MustUnmarshalBinaryBare(kvA.Value, &accA)
cdcB.MustUnmarshalBinaryBare(kvB.Value, &accB)
return fmt.Sprintf("%v\n%v", accA, accB)
case bytes.Equal(kvA.Key, auth.GlobalAccountNumberKey):
var globalAccNumberA, globalAccNumberB uint64
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &globalAccNumberA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &globalAccNumberB)
return fmt.Sprintf("GlobalAccNumberA: %d\nGlobalAccNumberB: %d", globalAccNumberA, globalAccNumberB)
default:
panic(fmt.Sprintf("invalid account key %X", kvA.Key))
}
}
// DecodeMintStore unmarshals the KVPair's Value to the corresponding mint type
func DecodeMintStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key, mint.MinterKey):
var minterA, minterB mint.Minter
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &minterA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &minterB)
return fmt.Sprintf("%v\n%v", minterA, minterB)
default:
panic(fmt.Sprintf("invalid mint key %X", kvA.Key))
}
}
// DecodeDistributionStore unmarshals the KVPair's Value to the corresponding distribution type
func DecodeDistributionStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], distribution.FeePoolKey):
var feePoolA, feePoolB distribution.FeePool
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &feePoolA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &feePoolB)
return fmt.Sprintf("%v\n%v", feePoolA, feePoolB)
case bytes.Equal(kvA.Key[:1], distribution.ProposerKey):
return fmt.Sprintf("%v\n%v", sdk.ConsAddress(kvA.Value), sdk.ConsAddress(kvB.Value))
case bytes.Equal(kvA.Key[:1], distribution.ValidatorOutstandingRewardsPrefix):
var rewardsA, rewardsB distribution.ValidatorOutstandingRewards
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &rewardsA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &rewardsB)
return fmt.Sprintf("%v\n%v", rewardsA, rewardsB)
case bytes.Equal(kvA.Key[:1], distribution.DelegatorWithdrawAddrPrefix):
return fmt.Sprintf("%v\n%v", sdk.AccAddress(kvA.Value), sdk.AccAddress(kvB.Value))
case bytes.Equal(kvA.Key[:1], distribution.DelegatorStartingInfoPrefix):
var infoA, infoB distribution.DelegatorStartingInfo
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &infoA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &infoB)
return fmt.Sprintf("%v\n%v", infoA, infoB)
case bytes.Equal(kvA.Key[:1], distribution.ValidatorHistoricalRewardsPrefix):
var rewardsA, rewardsB distribution.ValidatorHistoricalRewards
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &rewardsA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &rewardsB)
return fmt.Sprintf("%v\n%v", rewardsA, rewardsB)
case bytes.Equal(kvA.Key[:1], distribution.ValidatorCurrentRewardsPrefix):
var rewardsA, rewardsB distribution.ValidatorCurrentRewards
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &rewardsA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &rewardsB)
return fmt.Sprintf("%v\n%v", rewardsA, rewardsB)
case bytes.Equal(kvA.Key[:1], distribution.ValidatorAccumulatedCommissionPrefix):
var commissionA, commissionB distribution.ValidatorAccumulatedCommission
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &commissionA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &commissionB)
return fmt.Sprintf("%v\n%v", commissionA, commissionB)
case bytes.Equal(kvA.Key[:1], distribution.ValidatorSlashEventPrefix):
var eventA, eventB distribution.ValidatorSlashEvent
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &eventA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &eventB)
return fmt.Sprintf("%v\n%v", eventA, eventB)
default:
panic(fmt.Sprintf("invalid distribution key prefix %X", kvA.Key[:1]))
}
}
// DecodeStakingStore unmarshals the KVPair's Value to the corresponding staking type
func DecodeStakingStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], staking.LastTotalPowerKey):
var powerA, powerB sdk.Int
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &powerA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &powerB)
return fmt.Sprintf("%v\n%v", powerA, powerB)
case bytes.Equal(kvA.Key[:1], staking.ValidatorsKey):
var validatorA, validatorB staking.Validator
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &validatorA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &validatorB)
return fmt.Sprintf("%v\n%v", validatorA, validatorB)
case bytes.Equal(kvA.Key[:1], staking.LastValidatorPowerKey),
bytes.Equal(kvA.Key[:1], staking.ValidatorsByConsAddrKey),
bytes.Equal(kvA.Key[:1], staking.ValidatorsByPowerIndexKey):
return fmt.Sprintf("%v\n%v", sdk.ValAddress(kvA.Value), sdk.ValAddress(kvB.Value))
case bytes.Equal(kvA.Key[:1], staking.DelegationKey):
var delegationA, delegationB staking.Delegation
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &delegationA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &delegationB)
return fmt.Sprintf("%v\n%v", delegationA, delegationB)
case bytes.Equal(kvA.Key[:1], staking.UnbondingDelegationKey),
bytes.Equal(kvA.Key[:1], staking.UnbondingDelegationByValIndexKey):
var ubdA, ubdB staking.UnbondingDelegation
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &ubdA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &ubdB)
return fmt.Sprintf("%v\n%v", ubdA, ubdB)
case bytes.Equal(kvA.Key[:1], staking.RedelegationKey),
bytes.Equal(kvA.Key[:1], staking.RedelegationByValSrcIndexKey):
var redA, redB staking.Redelegation
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &redA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &redB)
return fmt.Sprintf("%v\n%v", redA, redB)
default:
panic(fmt.Sprintf("invalid staking key prefix %X", kvA.Key[:1]))
}
}
// DecodeSlashingStore unmarshals the KVPair's Value to the corresponding slashing type
func DecodeSlashingStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], slashing.ValidatorSigningInfoKey):
var infoA, infoB slashing.ValidatorSigningInfo
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &infoA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &infoB)
return fmt.Sprintf("%v\n%v", infoA, infoB)
case bytes.Equal(kvA.Key[:1], slashing.ValidatorMissedBlockBitArrayKey):
var missedA, missedB bool
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &missedA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &missedB)
return fmt.Sprintf("missedA: %v\nmissedB: %v", missedA, missedB)
case bytes.Equal(kvA.Key[:1], slashing.AddrPubkeyRelationKey):
var pubKeyA, pubKeyB crypto.PubKey
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &pubKeyA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &pubKeyB)
bechPKA := sdk.MustBech32ifyAccPub(pubKeyA)
bechPKB := sdk.MustBech32ifyAccPub(pubKeyB)
return fmt.Sprintf("PubKeyA: %s\nPubKeyB: %s", bechPKA, bechPKB)
default:
panic(fmt.Sprintf("invalid slashing key prefix %X", kvA.Key[:1]))
}
}
// DecodeGovStore unmarshals the KVPair's Value to the corresponding gov type
func DecodeGovStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], gov.ProposalsKeyPrefix):
var proposalA, proposalB gov.Proposal
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &proposalA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &proposalB)
return fmt.Sprintf("%v\n%v", proposalA, proposalB)
case bytes.Equal(kvA.Key[:1], gov.ActiveProposalQueuePrefix),
bytes.Equal(kvA.Key[:1], gov.InactiveProposalQueuePrefix),
bytes.Equal(kvA.Key[:1], gov.ProposalIDKey):
proposalIDA := binary.LittleEndian.Uint64(kvA.Value)
proposalIDB := binary.LittleEndian.Uint64(kvB.Value)
return fmt.Sprintf("proposalIDA: %d\nProposalIDB: %d", proposalIDA, proposalIDB)
case bytes.Equal(kvA.Key[:1], gov.DepositsKeyPrefix):
var depositA, depositB gov.Deposit
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &depositA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &depositB)
return fmt.Sprintf("%v\n%v", depositA, depositB)
case bytes.Equal(kvA.Key[:1], gov.VotesKeyPrefix):
var voteA, voteB gov.Vote
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &voteA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &voteB)
return fmt.Sprintf("%v\n%v", voteA, voteB)
default:
panic(fmt.Sprintf("invalid governance key prefix %X", kvA.Key[:1]))
}
}
// DecodeSupplyStore unmarshals the KVPair's Value to the corresponding supply type
func DecodeSupplyStore(cdcA, cdcB *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], supply.SupplyKey):
var supplyA, supplyB supply.Supply
cdcA.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &supplyA)
cdcB.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &supplyB)
return fmt.Sprintf("%v\n%v", supplyB, supplyB)
default:
panic(fmt.Sprintf("invalid supply key %X", kvA.Key))
}
}

View File

@ -1,10 +1,7 @@
package simapp
import (
"encoding/binary"
"fmt"
"time"
"testing"
"github.com/stretchr/testify/require"
@ -15,13 +12,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/distribution"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/supply"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -38,322 +28,40 @@ func makeTestCodec() (cdc *codec.Codec) {
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
auth.RegisterCodec(cdc)
distr.RegisterCodec(cdc)
gov.RegisterCodec(cdc)
staking.RegisterCodec(cdc)
supply.RegisterCodec(cdc)
return
}
func TestGetSimulationLog(t *testing.T) {
cdc := makeTestCodec()
decoders := make(sdk.StoreDecoderRegistry)
decoders[auth.StoreKey] = func(cdc *codec.Codec, kvAs, kvBs cmn.KVPair) string { return "10" }
tests := []struct {
store string
kvPairs []cmn.KVPair
store string
kvPairs []cmn.KVPair
expectedLog string
}{
{auth.StoreKey, []cmn.KVPair{
{Key: auth.AddressStoreKey(delAddr1), Value: cdc.MustMarshalBinaryBare(auth.BaseAccount{})},
{Key: auth.AddressStoreKey(delAddr1), Value: cdc.MustMarshalBinaryBare(auth.BaseAccount{})},
}},
{mint.StoreKey, []cmn.KVPair{
{Key: mint.MinterKey, Value: cdc.MustMarshalBinaryLengthPrefixed(mint.Minter{})},
{Key: mint.MinterKey, Value: cdc.MustMarshalBinaryLengthPrefixed(mint.Minter{})},
}},
{staking.StoreKey, []cmn.KVPair{
{Key: staking.LastValidatorPowerKey, Value: valAddr1.Bytes()},
{Key: staking.LastValidatorPowerKey, Value: valAddr1.Bytes()},
}},
{gov.StoreKey, []cmn.KVPair{
{Key: gov.VoteKey(1, delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(gov.Vote{})},
{Key: gov.VoteKey(1, delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(gov.Vote{})},
}},
{distribution.StoreKey, []cmn.KVPair{
{Key: distr.ProposerKey, Value: consAddr1.Bytes()},
{Key: distr.ProposerKey, Value: consAddr1.Bytes()},
}},
{slashing.StoreKey, []cmn.KVPair{
{Key: slashing.GetValidatorMissedBlockBitArrayKey(consAddr1, 6), Value: cdc.MustMarshalBinaryLengthPrefixed(true)},
{Key: slashing.GetValidatorMissedBlockBitArrayKey(consAddr1, 6), Value: cdc.MustMarshalBinaryLengthPrefixed(true)},
}},
{supply.StoreKey, []cmn.KVPair{
{Key: supply.SupplyKey, Value: cdc.MustMarshalBinaryLengthPrefixed(supply.NewSupply(sdk.Coins{}))},
{Key: supply.SupplyKey, Value: cdc.MustMarshalBinaryLengthPrefixed(supply.NewSupply(sdk.Coins{}))},
}},
{"Empty", []cmn.KVPair{{}, {}}},
{"OtherStore", []cmn.KVPair{
{Key: []byte("key"), Value: []byte("value")},
{Key: []byte("key"), Value: []byte("other_value")},
}},
{
"Empty",
[]cmn.KVPair{{}},
"",
},
{
auth.StoreKey,
[]cmn.KVPair{{Key: auth.GlobalAccountNumberKey, Value: cdc.MustMarshalBinaryLengthPrefixed(uint64(10))}},
"10",
},
{
"OtherStore",
[]cmn.KVPair{{Key: []byte("key"), Value: []byte("value")}},
fmt.Sprintf("store A %X => %X\nstore B %X => %X\n", []byte("key"), []byte("value"), []byte("key"), []byte("value")),
},
}
for _, tt := range tests {
t.Run(tt.store, func(t *testing.T) {
require.NotPanics(t, func() { GetSimulationLog(tt.store, cdc, cdc, tt.kvPairs) }, tt.store)
})
}
}
func TestDecodeAccountStore(t *testing.T) {
cdc := makeTestCodec()
acc := auth.NewBaseAccountWithAddress(delAddr1)
globalAccNumber := uint64(10)
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: auth.AddressStoreKey(delAddr1), Value: cdc.MustMarshalBinaryBare(acc)},
cmn.KVPair{Key: auth.GlobalAccountNumberKey, Value: cdc.MustMarshalBinaryLengthPrefixed(globalAccNumber)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"Minter", fmt.Sprintf("%v\n%v", acc, acc)},
{"GlobalAccNumber", fmt.Sprintf("GlobalAccNumberA: %d\nGlobalAccNumberB: %d", globalAccNumber, globalAccNumber)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeAccountStore(cdc, cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeAccountStore(cdc, cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}
func TestDecodeMintStore(t *testing.T) {
cdc := makeTestCodec()
minter := mint.NewMinter(sdk.OneDec(), sdk.NewDec(15))
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: mint.MinterKey, Value: cdc.MustMarshalBinaryLengthPrefixed(minter)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"Minter", fmt.Sprintf("%v\n%v", minter, minter)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeMintStore(cdc, cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeMintStore(cdc, cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}
func TestDecodeDistributionStore(t *testing.T) {
cdc := makeTestCodec()
decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.OneDec())}
feePool := distr.InitialFeePool()
feePool.CommunityPool = decCoins
info := distr.NewDelegatorStartingInfo(2, sdk.OneDec(), 200)
outstanding := distr.ValidatorOutstandingRewards{decCoins[0]}
commission := distr.ValidatorAccumulatedCommission{decCoins[0]}
historicalRewards := distr.NewValidatorHistoricalRewards(decCoins, 100)
currentRewards := distr.NewValidatorCurrentRewards(decCoins, 5)
slashEvent := distr.NewValidatorSlashEvent(10, sdk.OneDec())
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: distr.FeePoolKey, Value: cdc.MustMarshalBinaryLengthPrefixed(feePool)},
cmn.KVPair{Key: distr.ProposerKey, Value: consAddr1.Bytes()},
cmn.KVPair{Key: distr.GetValidatorOutstandingRewardsKey(valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(outstanding)},
cmn.KVPair{Key: distr.GetDelegatorWithdrawAddrKey(delAddr1), Value: delAddr1.Bytes()},
cmn.KVPair{Key: distr.GetDelegatorStartingInfoKey(valAddr1, delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(info)},
cmn.KVPair{Key: distr.GetValidatorHistoricalRewardsKey(valAddr1, 100), Value: cdc.MustMarshalBinaryLengthPrefixed(historicalRewards)},
cmn.KVPair{Key: distr.GetValidatorCurrentRewardsKey(valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(currentRewards)},
cmn.KVPair{Key: distr.GetValidatorAccumulatedCommissionKey(valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(commission)},
cmn.KVPair{Key: distr.GetValidatorSlashEventKeyPrefix(valAddr1, 13), Value: cdc.MustMarshalBinaryLengthPrefixed(slashEvent)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"FeePool", fmt.Sprintf("%v\n%v", feePool, feePool)},
{"Proposer", fmt.Sprintf("%v\n%v", consAddr1, consAddr1)},
{"ValidatorOutstandingRewards", fmt.Sprintf("%v\n%v", outstanding, outstanding)},
{"DelegatorWithdrawAddr", fmt.Sprintf("%v\n%v", delAddr1, delAddr1)},
{"DelegatorStartingInfo", fmt.Sprintf("%v\n%v", info, info)},
{"ValidatorHistoricalRewards", fmt.Sprintf("%v\n%v", historicalRewards, historicalRewards)},
{"ValidatorCurrentRewards", fmt.Sprintf("%v\n%v", currentRewards, currentRewards)},
{"ValidatorAccumulatedCommission", fmt.Sprintf("%v\n%v", commission, commission)},
{"ValidatorSlashEvent", fmt.Sprintf("%v\n%v", slashEvent, slashEvent)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeDistributionStore(cdc, cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeDistributionStore(cdc, cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}
func TestDecodeStakingStore(t *testing.T) {
cdc := makeTestCodec()
bondTime := time.Now().UTC()
val := staking.NewValidator(valAddr1, delPk1, staking.NewDescription("test", "test", "test", "test", "test"))
del := staking.NewDelegation(delAddr1, valAddr1, sdk.OneDec())
ubd := staking.NewUnbondingDelegation(delAddr1, valAddr1, 15, bondTime, sdk.OneInt())
red := staking.NewRedelegation(delAddr1, valAddr1, valAddr1, 12, bondTime, sdk.OneInt(), sdk.OneDec())
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: staking.LastTotalPowerKey, Value: cdc.MustMarshalBinaryLengthPrefixed(sdk.OneInt())},
cmn.KVPair{Key: staking.GetValidatorKey(valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(val)},
cmn.KVPair{Key: staking.LastValidatorPowerKey, Value: valAddr1.Bytes()},
cmn.KVPair{Key: staking.GetDelegationKey(delAddr1, valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(del)},
cmn.KVPair{Key: staking.GetUBDKey(delAddr1, valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(ubd)},
cmn.KVPair{Key: staking.GetREDKey(delAddr1, valAddr1, valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(red)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"LastTotalPower", fmt.Sprintf("%v\n%v", sdk.OneInt(), sdk.OneInt())},
{"Validator", fmt.Sprintf("%v\n%v", val, val)},
{"LastValidatorPower/ValidatorsByConsAddr/ValidatorsByPowerIndex", fmt.Sprintf("%v\n%v", valAddr1, valAddr1)},
{"Delegation", fmt.Sprintf("%v\n%v", del, del)},
{"UnbondingDelegation", fmt.Sprintf("%v\n%v", ubd, ubd)},
{"Redelegation", fmt.Sprintf("%v\n%v", red, red)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeStakingStore(cdc, cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeStakingStore(cdc, cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}
func TestDecodeSlashingStore(t *testing.T) {
cdc := makeTestCodec()
info := slashing.NewValidatorSigningInfo(consAddr1, 0, 1, time.Now().UTC(), false, 0)
bechPK := sdk.MustBech32ifyAccPub(delPk1)
missed := true
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: slashing.GetValidatorSigningInfoKey(consAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(info)},
cmn.KVPair{Key: slashing.GetValidatorMissedBlockBitArrayKey(consAddr1, 6), Value: cdc.MustMarshalBinaryLengthPrefixed(missed)},
cmn.KVPair{Key: slashing.GetAddrPubkeyRelationKey(delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(delPk1)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"ValidatorSigningInfo", fmt.Sprintf("%v\n%v", info, info)},
{"ValidatorMissedBlockBitArray", fmt.Sprintf("missedA: %v\nmissedB: %v", missed, missed)},
{"AddrPubkeyRelation", fmt.Sprintf("PubKeyA: %s\nPubKeyB: %s", bechPK, bechPK)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeSlashingStore(cdc, cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeSlashingStore(cdc, cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}
func TestDecodeGovStore(t *testing.T) {
cdc := makeTestCodec()
endTime := time.Now().UTC()
content := gov.ContentFromProposalType("test", "test", gov.ProposalTypeText)
proposal := gov.NewProposal(content, 1, endTime, endTime.Add(24*time.Hour))
proposalIDBz := make([]byte, 8)
binary.LittleEndian.PutUint64(proposalIDBz, 1)
deposit := gov.NewDeposit(1, delAddr1, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())))
vote := gov.NewVote(1, delAddr1, gov.OptionYes)
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: gov.ProposalKey(1), Value: cdc.MustMarshalBinaryLengthPrefixed(proposal)},
cmn.KVPair{Key: gov.InactiveProposalQueueKey(1, endTime), Value: proposalIDBz},
cmn.KVPair{Key: gov.DepositKey(1, delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(deposit)},
cmn.KVPair{Key: gov.VoteKey(1, delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(vote)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"proposals", fmt.Sprintf("%v\n%v", proposal, proposal)},
{"proposal IDs", "proposalIDA: 1\nProposalIDB: 1"},
{"deposits", fmt.Sprintf("%v\n%v", deposit, deposit)},
{"votes", fmt.Sprintf("%v\n%v", vote, vote)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeGovStore(cdc, cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeGovStore(cdc, cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}
func TestDecodeSupplyStore(t *testing.T) {
cdc := makeTestCodec()
totalSupply := supply.NewSupply(sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000)))
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: supply.SupplyKey, Value: cdc.MustMarshalBinaryLengthPrefixed(totalSupply)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"Supply", fmt.Sprintf("%v\n%v", totalSupply, totalSupply)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeSupplyStore(cdc, cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeSupplyStore(cdc, cdc, kvPairs[i], kvPairs[i]), tt.name)
}
require.Equal(t, tt.expectedLog, GetSimulationLog(tt.store, decoders, cdc, tt.kvPairs, tt.kvPairs), tt.store)
})
}
}

View File

@ -18,7 +18,7 @@ func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator {
// DiffKVStores compares two KVstores and returns all the key/value pairs
// that differ from one another. It also skips value comparison for a set of provided prefixes
func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvs []cmn.KVPair) {
func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvAs, kvBs []cmn.KVPair) {
iterA := a.Iterator(nil, nil)
iterB := b.Iterator(nil, nil)
@ -36,7 +36,8 @@ func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvs []cmn.KVPa
iterB.Next()
}
if !bytes.Equal(kvA.Key, kvB.Key) {
kvs = append(kvs, []cmn.KVPair{kvA, kvB}...)
kvAs = append(kvAs, kvA)
kvBs = append(kvBs, kvB)
}
compareValue := true
for _, prefix := range prefixesToSkip {
@ -46,7 +47,8 @@ func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvs []cmn.KVPa
}
}
if compareValue && !bytes.Equal(kvA.Value, kvB.Value) {
kvs = append(kvs, []cmn.KVPair{kvA, kvB}...)
kvAs = append(kvAs, kvA)
kvBs = append(kvBs, kvB)
}
}
return

View File

@ -3,6 +3,7 @@ Package module contains application module patterns and associated "manager" fun
The module pattern has been broken down by:
- independent module functionality (AppModuleBasic)
- inter-dependent module genesis functionality (AppModuleGenesis)
- inter-dependent module simulation functionality (AppModuleSimulation)
- inter-dependent module full functionality (AppModule)
inter-dependent module functionality is module functionality which somehow
@ -41,6 +42,7 @@ import (
)
//__________________________________________________________________________________________
// AppModuleBasic is the standard form for basic non-dependant elements of an application module.
type AppModuleBasic interface {
Name() string
@ -56,9 +58,10 @@ type AppModuleBasic interface {
GetQueryCmd(*codec.Codec) *cobra.Command
}
// collections of AppModuleBasic
// BasicManager is a collection of AppModuleBasic
type BasicManager map[string]AppModuleBasic
// NewBasicManager creates a new BasicManager object
func NewBasicManager(modules ...AppModuleBasic) BasicManager {
moduleMap := make(map[string]AppModuleBasic)
for _, module := range modules {
@ -67,14 +70,14 @@ func NewBasicManager(modules ...AppModuleBasic) BasicManager {
return moduleMap
}
// RegisterCodecs registers all module codecs
// RegisterCodec registers all module codecs
func (bm BasicManager) RegisterCodec(cdc *codec.Codec) {
for _, b := range bm {
b.RegisterCodec(cdc)
}
}
// Provided default genesis information for all modules
// DefaultGenesis provides default genesis information for all modules
func (bm BasicManager) DefaultGenesis() map[string]json.RawMessage {
genesis := make(map[string]json.RawMessage)
for _, b := range bm {
@ -83,7 +86,7 @@ func (bm BasicManager) DefaultGenesis() map[string]json.RawMessage {
return genesis
}
// Provided default genesis information for all modules
// ValidateGenesis performs genesis state validation for all modules
func (bm BasicManager) ValidateGenesis(genesis map[string]json.RawMessage) error {
for _, b := range bm {
if err := b.ValidateGenesis(genesis[b.Name()]); err != nil {
@ -93,14 +96,14 @@ func (bm BasicManager) ValidateGenesis(genesis map[string]json.RawMessage) error
return nil
}
// RegisterRestRoutes registers all module rest routes
// RegisterRESTRoutes registers all module rest routes
func (bm BasicManager) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
for _, b := range bm {
b.RegisterRESTRoutes(ctx, rtr)
}
}
// add all tx commands to the rootTxCmd
// AddTxCommands adds all tx commands to the rootTxCmd
func (bm BasicManager) AddTxCommands(rootTxCmd *cobra.Command, cdc *codec.Codec) {
for _, b := range bm {
if cmd := b.GetTxCmd(cdc); cmd != nil {
@ -109,7 +112,7 @@ func (bm BasicManager) AddTxCommands(rootTxCmd *cobra.Command, cdc *codec.Codec)
}
}
// add all query commands to the rootQueryCmd
// AddQueryCommands adds all query commands to the rootQueryCmd
func (bm BasicManager) AddQueryCommands(rootQueryCmd *cobra.Command, cdc *codec.Codec) {
for _, b := range bm {
if cmd := b.GetQueryCmd(cdc); cmd != nil {
@ -119,6 +122,7 @@ func (bm BasicManager) AddQueryCommands(rootQueryCmd *cobra.Command, cdc *codec.
}
//_________________________________________________________
// AppModuleGenesis is the standard form for an application module genesis functions
type AppModuleGenesis interface {
AppModuleBasic
@ -126,9 +130,17 @@ type AppModuleGenesis interface {
ExportGenesis(sdk.Context) json.RawMessage
}
// AppModuleSimulation defines the standard functions that every module should expose
// for the SDK blockchain simulator
type AppModuleSimulation interface {
// register a func to decode the each module's defined types from their corresponding store key
RegisterStoreDecoder(sdk.StoreDecoderRegistry)
}
// AppModule is the standard form for an application module
type AppModule interface {
AppModuleGenesis
AppModuleSimulation
// registers
RegisterInvariants(sdk.InvariantRegistry)
@ -139,12 +151,14 @@ type AppModule interface {
QuerierRoute() string
NewQuerierHandler() sdk.Querier
// ABCI
BeginBlock(sdk.Context, abci.RequestBeginBlock)
EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate
}
//___________________________
// app module
// GenesisOnlyAppModule is an AppModule that only has import/export functionality
type GenesisOnlyAppModule struct {
AppModuleGenesis
}
@ -156,31 +170,35 @@ func NewGenesisOnlyAppModule(amg AppModuleGenesis) AppModule {
}
}
// register invariants
// RegisterInvariants is a placeholder function register no invariants
func (GenesisOnlyAppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
// module message route ngame
// RegisterStoreDecoder empty store decoder registry
func (GenesisOnlyAppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
// Route empty module message route
func (GenesisOnlyAppModule) Route() string { return "" }
// module handler
// NewHandler returns an empty module handler
func (GenesisOnlyAppModule) NewHandler() sdk.Handler { return nil }
// module querier route ngame
// QuerierRoute returns an empty module querier route
func (GenesisOnlyAppModule) QuerierRoute() string { return "" }
// module querier
// NewQuerierHandler returns an empty module querier
func (gam GenesisOnlyAppModule) NewQuerierHandler() sdk.Querier { return nil }
// module begin-block
// BeginBlock returns an empty module begin-block
func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {}
// module end-block
// EndBlock returns an empty module end-block
func (GenesisOnlyAppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}
//____________________________________________________________________________
// module manager provides the high level utility for managing and executing
// Manager defines a module manager that provides the high level utility for managing and executing
// operations for a group of modules
type Manager struct {
Modules map[string]AppModule
@ -190,7 +208,7 @@ type Manager struct {
OrderEndBlockers []string
}
// NewModuleManager creates a new Manager object
// NewManager creates a new Manager object
func NewManager(modules ...AppModule) *Manager {
moduleMap := make(map[string]AppModule)
@ -209,34 +227,34 @@ func NewManager(modules ...AppModule) *Manager {
}
}
// set the order of init genesis calls
// SetOrderInitGenesis sets the order of init genesis calls
func (m *Manager) SetOrderInitGenesis(moduleNames ...string) {
m.OrderInitGenesis = moduleNames
}
// set the order of export genesis calls
// SetOrderExportGenesis sets the order of export genesis calls
func (m *Manager) SetOrderExportGenesis(moduleNames ...string) {
m.OrderExportGenesis = moduleNames
}
// set the order of set begin-blocker calls
// SetOrderBeginBlockers sets the order of set begin-blocker calls
func (m *Manager) SetOrderBeginBlockers(moduleNames ...string) {
m.OrderBeginBlockers = moduleNames
}
// set the order of set end-blocker calls
// SetOrderEndBlockers sets the order of set end-blocker calls
func (m *Manager) SetOrderEndBlockers(moduleNames ...string) {
m.OrderEndBlockers = moduleNames
}
// register all module routes and module querier routes
// RegisterInvariants registers all module routes and module querier routes
func (m *Manager) RegisterInvariants(ir sdk.InvariantRegistry) {
for _, module := range m.Modules {
module.RegisterInvariants(ir)
}
}
// register all module routes and module querier routes
// RegisterRoutes registers all module routes and module querier routes
func (m *Manager) RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter) {
for _, module := range m.Modules {
if module.Route() != "" {
@ -248,7 +266,7 @@ func (m *Manager) RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter)
}
}
// perform init genesis functionality for modules
// InitGenesis performs init genesis functionality for modules
func (m *Manager) InitGenesis(ctx sdk.Context, genesisData map[string]json.RawMessage) abci.ResponseInitChain {
var validatorUpdates []abci.ValidatorUpdate
for _, moduleName := range m.OrderInitGenesis {
@ -271,7 +289,7 @@ func (m *Manager) InitGenesis(ctx sdk.Context, genesisData map[string]json.RawMe
}
}
// perform export genesis functionality for modules
// ExportGenesis performs export genesis functionality for modules
func (m *Manager) ExportGenesis(ctx sdk.Context) map[string]json.RawMessage {
genesisData := make(map[string]json.RawMessage)
for _, moduleName := range m.OrderExportGenesis {
@ -320,6 +338,4 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo
ValidatorUpdates: validatorUpdates,
Events: ctx.EventManager().ABCIEvents(),
}
}
// DONTCOVER
}

View File

@ -0,0 +1,27 @@
package module
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// SimulationManager defines a simulation manager that provides the high level utility
// for managing and executing simulation functionalities for a group of modules
type SimulationManager struct {
Modules map[string]AppModule
StoreDecoders sdk.StoreDecoderRegistry
}
// NewSimulationManager creates a new SimulationManager object
func NewSimulationManager(moduleMap map[string]AppModule) *SimulationManager {
return &SimulationManager{
Modules: moduleMap,
StoreDecoders: make(sdk.StoreDecoderRegistry),
}
}
// RegisterStoreDecoders registers each of the modules' store decoders into a map
func (sm *SimulationManager) RegisterStoreDecoders() {
for _, module := range sm.Modules {
module.RegisterStoreDecoder(sm.StoreDecoders)
}
}

View File

@ -3,6 +3,7 @@ package types
import (
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store/types"
)
@ -24,6 +25,10 @@ type (
Iterator = types.Iterator
)
// StoreDecoderRegistry defines each of the modules store decoders. Used for ImportExport
// simulation.
type StoreDecoderRegistry map[string]func(cdc *codec.Codec, kvA, kvB cmn.KVPair) string
// Iterator over all the keys with a certain prefix in ascending order
func KVStorePrefixIterator(kvs KVStore, prefix []byte) Iterator {
return types.KVStorePrefixIterator(kvs, prefix)
@ -36,7 +41,7 @@ func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator {
// DiffKVStores compares two KVstores and returns all the key/value pairs
// that differ from one another. It also skips value comparison for a set of provided prefixes
func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) []cmn.KVPair {
func DiffKVStores(a KVStore, b KVStore, prefixesToSkip [][]byte) (kvAs, kvBs []cmn.KVPair) {
return types.DiffKVStores(a, b, prefixesToSkip)
}

View File

@ -13,33 +13,36 @@ import (
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/cosmos/cosmos-sdk/x/auth/client/rest"
"github.com/cosmos/cosmos-sdk/x/auth/simulation"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the auth module.
type AppModuleBasic struct{}
// module name
// Name returns the auth module's name.
func (AppModuleBasic) Name() string {
return types.ModuleName
}
// register module codec
// RegisterCodec registers the auth module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
types.RegisterCodec(cdc)
}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the auth
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return types.ModuleCdc.MustMarshalJSON(types.DefaultGenesisState())
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the auth module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data types.GenesisState
err := types.ModuleCdc.UnmarshalJSON(bz, &data)
@ -49,61 +52,76 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return types.ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers the REST routes for the auth module.
func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
rest.RegisterRoutes(ctx, rtr, types.StoreKey)
}
// get the root tx command of this module
// GetTxCmd returns the root tx command for the auth module.
func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetTxCmd(cdc)
}
// get the root query command of this module
// GetQueryCmd returns the root query command for the auth module.
func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetQueryCmd(cdc)
}
//___________________________
// app module object
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the auth module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder registers a decoder for auth module's types
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
//____________________________________________________________________________
// AppModule implements an application module for the auth module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
accountKeeper AccountKeeper
}
// NewAppModule creates a new AppModule object
func NewAppModule(accountKeeper AccountKeeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
accountKeeper: accountKeeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
accountKeeper: accountKeeper,
}
}
// module name
// Name returns the auth module's name.
func (AppModule) Name() string {
return types.ModuleName
}
// register invariants
// RegisterInvariants performs a no-op.
func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
// module message route name
// Route returns the message routing key for the auth module.
func (AppModule) Route() string { return "" }
// module handler
// NewHandler returns an sdk.Handler for the auth module.
func (AppModule) NewHandler() sdk.Handler { return nil }
// module querier route name
// QuerierRoute returns the auth module's querier route name.
func (AppModule) QuerierRoute() string {
return types.QuerierRoute
}
// module querier
// NewQuerierHandler returns the auth module sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier {
return NewQuerier(am.accountKeeper)
}
// module init-genesis
// InitGenesis performs genesis initialization for the auth module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
types.ModuleCdc.MustUnmarshalJSON(data, &genesisState)
@ -111,16 +129,18 @@ func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.Va
return []abci.ValidatorUpdate{}
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the auth
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.accountKeeper)
return types.ModuleCdc.MustMarshalJSON(gs)
}
// module begin-block
// BeginBlock returns the begin blocker for the auth module.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
// EndBlock returns the end blocker for the auth module. It returns no validator
// updates.
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -0,0 +1,30 @@
package simulation
import (
"bytes"
"fmt"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
// DecodeStore unmarshals the KVPair's Value to the corresponding auth type
func DecodeStore(cdc *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], types.AddressStoreKeyPrefix):
var accA, accB exported.Account
cdc.MustUnmarshalBinaryBare(kvA.Value, &accA)
cdc.MustUnmarshalBinaryBare(kvB.Value, &accB)
return fmt.Sprintf("%v\n%v", accA, accB)
case bytes.Equal(kvA.Key, types.GlobalAccountNumberKey):
var globalAccNumberA, globalAccNumberB uint64
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &globalAccNumberA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &globalAccNumberB)
return fmt.Sprintf("GlobalAccNumberA: %d\nGlobalAccNumberB: %d", globalAccNumberA, globalAccNumberB)
default:
panic(fmt.Sprintf("invalid account key %X", kvA.Key))
}
}

View File

@ -0,0 +1,61 @@
package simulation
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
var (
delPk1 = ed25519.GenPrivKey().PubKey()
delAddr1 = sdk.AccAddress(delPk1.Address())
valAddr1 = sdk.ValAddress(delPk1.Address())
consAddr1 = sdk.ConsAddress(delPk1.Address().Bytes())
)
func makeTestCodec() (cdc *codec.Codec) {
cdc = codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
types.RegisterCodec(cdc)
return
}
func TestDecodeStore(t *testing.T) {
cdc := makeTestCodec()
acc := types.NewBaseAccountWithAddress(delAddr1)
globalAccNumber := uint64(10)
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: types.AddressStoreKey(delAddr1), Value: cdc.MustMarshalBinaryBare(acc)},
cmn.KVPair{Key: types.GlobalAccountNumberKey, Value: cdc.MustMarshalBinaryLengthPrefixed(globalAccNumber)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"Account", fmt.Sprintf("%v\n%v", acc, acc)},
{"GlobalAccNumber", fmt.Sprintf("GlobalAccNumberA: %d\nGlobalAccNumberB: %d", globalAccNumber, globalAccNumber)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeStore(cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeStore(cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}

View File

@ -1,4 +1,4 @@
package simulation
package operations
import (
"errors"

View File

@ -19,25 +19,27 @@ import (
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the bank module.
type AppModuleBasic struct{}
// module name
// Name returns the bank module's name.
func (AppModuleBasic) Name() string { return ModuleName }
// register module codec
// RegisterCodec registers the bank module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { RegisterCodec(cdc) }
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the bank
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(DefaultGenesisState())
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the bank module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -47,23 +49,34 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers the REST routes for the bank module.
func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
rest.RegisterRoutes(ctx, rtr)
}
// get the root tx command of this module
// GetTxCmd returns the root tx command for the bank module.
func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetTxCmd(cdc)
}
// get the root query command of this module
// GetQueryCmd returns no root query command for the bank module.
func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }
//___________________________
// app module
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the bank module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
func (AppModuleSimulation) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
//____________________________________________________________________________
// AppModule implements an application module for the bank module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
keeper Keeper
accountKeeper types.AccountKeeper
}
@ -71,35 +84,37 @@ type AppModule struct {
// NewAppModule creates a new AppModule object
func NewAppModule(keeper Keeper, accountKeeper types.AccountKeeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
accountKeeper: accountKeeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
accountKeeper: accountKeeper,
}
}
// module name
// Name returns the bank module's name.
func (AppModule) Name() string { return ModuleName }
// register invariants
// RegisterInvariants registers the bank module invariants.
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
keeper.RegisterInvariants(ir, am.accountKeeper)
}
// module message route name
// Route returns the message routing key for the bank module.
func (AppModule) Route() string { return RouterKey }
// module handler
// NewHandler returns an sdk.Handler for the bank module.
func (am AppModule) NewHandler() sdk.Handler { return NewHandler(am.keeper) }
// module querier route name
// QuerierRoute returns the bank module's querier route name.
func (AppModule) QuerierRoute() string { return RouterKey }
// module querier
// NewQuerierHandler returns the bank module sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier {
return keeper.NewQuerier(am.keeper)
}
// module init-genesis
// InitGenesis performs genesis initialization for the bank module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
@ -107,16 +122,18 @@ func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.Va
return []abci.ValidatorUpdate{}
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the bank
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return ModuleCdc.MustMarshalJSON(gs)
}
// module begin-block
// BeginBlock performs a no-op.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
// EndBlock returns the end blocker for the bank module. It returns no validator
// updates.
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -1,4 +1,4 @@
package bank
package operations
import (
"fmt"
@ -8,16 +8,16 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank/internal/keeper"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
"github.com/cosmos/cosmos-sdk/x/mock"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// SendTx tests and runs a single msg send where both
// SimulateMsgSend tests and runs a single msg send where both
// accounts already exist.
func SimulateMsgSend(mapper types.AccountKeeper, bk keeper.Keeper) simulation.Operation {
handler := NewHandler(bk)
func SimulateMsgSend(mapper types.AccountKeeper, bk bank.Keeper) simulation.Operation {
handler := bank.NewHandler(bk)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) (
opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
@ -108,10 +108,10 @@ func sendAndVerifyMsgSend(app *baseapp.BaseApp, mapper types.AccountKeeper, msg
return nil
}
// SingleInputSendMsg tests and runs a single msg multisend, with one input and one output, where both
// SimulateSingleInputMsgMultiSend tests and runs a single msg multisend, with one input and one output, where both
// accounts already exist.
func SimulateSingleInputMsgMultiSend(mapper types.AccountKeeper, bk keeper.Keeper) simulation.Operation {
handler := NewHandler(bk)
func SimulateSingleInputMsgMultiSend(mapper types.AccountKeeper, bk bank.Keeper) simulation.Operation {
handler := bank.NewHandler(bk)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) (
opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {

View File

@ -18,8 +18,9 @@ import (
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// AppModuleBasic defines the basic application module used by the crisis module.
@ -61,9 +62,20 @@ func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
// GetQueryCmd returns no root query command for the crisis module.
func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the crisis module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
func (AppModuleSimulation) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
//____________________________________________________________________________
// AppModule implements an application module for the crisis module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
// NOTE: We store a reference to the keeper here so that after a module
// manager is created, the invariants can be properly registered and
@ -74,8 +86,9 @@ type AppModule struct {
// NewAppModule creates a new AppModule object
func NewAppModule(keeper *keeper.Keeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
}
}
@ -121,7 +134,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
return types.ModuleCdc.MustMarshalJSON(gs)
}
// BeginBlock returns the begin blocker for the crisis module.
// BeginBlock performs a no-op.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// EndBlock returns the end blocker for the crisis module. It returns no validator

View File

@ -14,33 +14,36 @@ import (
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/distribution/client/cli"
"github.com/cosmos/cosmos-sdk/x/distribution/client/rest"
"github.com/cosmos/cosmos-sdk/x/distribution/simulation"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the distribution module.
type AppModuleBasic struct{}
// module name
// Name returns the distribution module's name.
func (AppModuleBasic) Name() string {
return ModuleName
}
// register module codec
// RegisterCodec registers the distribution module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
RegisterCodec(cdc)
}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the distribution
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(DefaultGenesisState())
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the distribution module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -50,24 +53,38 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers the REST routes for the distribution module.
func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
rest.RegisterRoutes(ctx, rtr, StoreKey)
}
// get the root tx command of this module
// GetTxCmd returns the root tx command for the distribution module.
func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetTxCmd(StoreKey, cdc)
}
// get the root query command of this module
// GetQueryCmd returns the root query command for the distribution module.
func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetQueryCmd(StoreKey, cdc)
}
// app module
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the distribution module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder registers a decoder for distribution module's types
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
//____________________________________________________________________________
// AppModule implements an application module for the distribution module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
keeper Keeper
supplyKeeper types.SupplyKeeper
}
@ -75,43 +92,45 @@ type AppModule struct {
// NewAppModule creates a new AppModule object
func NewAppModule(keeper Keeper, supplyKeeper types.SupplyKeeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
supplyKeeper: supplyKeeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
supplyKeeper: supplyKeeper,
}
}
// module name
// Name returns the distribution module's name.
func (AppModule) Name() string {
return ModuleName
}
// register invariants
// RegisterInvariants registers the distribution module invariants.
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
RegisterInvariants(ir, am.keeper)
}
// module message route name
// Route returns the message routing key for the distribution module.
func (AppModule) Route() string {
return RouterKey
}
// module handler
// NewHandler returns an sdk.Handler for the distribution module.
func (am AppModule) NewHandler() sdk.Handler {
return NewHandler(am.keeper)
}
// module querier route name
// QuerierRoute returns the distribution module's querier route name.
func (AppModule) QuerierRoute() string {
return QuerierRoute
}
// module querier
// NewQuerierHandler returns the distribution module sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier {
return NewQuerier(am.keeper)
}
// module init-genesis
// InitGenesis performs genesis initialization for the distribution module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
@ -119,18 +138,20 @@ func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.Va
return []abci.ValidatorUpdate{}
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the distribution
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return ModuleCdc.MustMarshalJSON(gs)
}
// module begin-block
// BeginBlock returns the begin blocker for the distribution module.
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, req, am.keeper)
}
// module end-block
// EndBlock returns the end blocker for the distribution module. It returns no validator
// updates.
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -0,0 +1,70 @@
package simulation
import (
"bytes"
"fmt"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
// DecodeStore unmarshals the KVPair's Value to the corresponding distribution type
func DecodeStore(cdc *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], keeper.FeePoolKey):
var feePoolA, feePoolB types.FeePool
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &feePoolA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &feePoolB)
return fmt.Sprintf("%v\n%v", feePoolA, feePoolB)
case bytes.Equal(kvA.Key[:1], keeper.ProposerKey):
return fmt.Sprintf("%v\n%v", sdk.ConsAddress(kvA.Value), sdk.ConsAddress(kvB.Value))
case bytes.Equal(kvA.Key[:1], keeper.ValidatorOutstandingRewardsPrefix):
var rewardsA, rewardsB types.ValidatorOutstandingRewards
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &rewardsA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &rewardsB)
return fmt.Sprintf("%v\n%v", rewardsA, rewardsB)
case bytes.Equal(kvA.Key[:1], keeper.DelegatorWithdrawAddrPrefix):
return fmt.Sprintf("%v\n%v", sdk.AccAddress(kvA.Value), sdk.AccAddress(kvB.Value))
case bytes.Equal(kvA.Key[:1], keeper.DelegatorStartingInfoPrefix):
var infoA, infoB types.DelegatorStartingInfo
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &infoA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &infoB)
return fmt.Sprintf("%v\n%v", infoA, infoB)
case bytes.Equal(kvA.Key[:1], keeper.ValidatorHistoricalRewardsPrefix):
var rewardsA, rewardsB types.ValidatorHistoricalRewards
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &rewardsA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &rewardsB)
return fmt.Sprintf("%v\n%v", rewardsA, rewardsB)
case bytes.Equal(kvA.Key[:1], keeper.ValidatorCurrentRewardsPrefix):
var rewardsA, rewardsB types.ValidatorCurrentRewards
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &rewardsA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &rewardsB)
return fmt.Sprintf("%v\n%v", rewardsA, rewardsB)
case bytes.Equal(kvA.Key[:1], keeper.ValidatorAccumulatedCommissionPrefix):
var commissionA, commissionB types.ValidatorAccumulatedCommission
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &commissionA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &commissionB)
return fmt.Sprintf("%v\n%v", commissionA, commissionB)
case bytes.Equal(kvA.Key[:1], keeper.ValidatorSlashEventPrefix):
var eventA, eventB types.ValidatorSlashEvent
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &eventA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &eventB)
return fmt.Sprintf("%v\n%v", eventA, eventB)
default:
panic(fmt.Sprintf("invalid distribution key prefix %X", kvA.Key[:1]))
}
}

View File

@ -0,0 +1,84 @@
package simulation
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
var (
delPk1 = ed25519.GenPrivKey().PubKey()
delAddr1 = sdk.AccAddress(delPk1.Address())
valAddr1 = sdk.ValAddress(delPk1.Address())
consAddr1 = sdk.ConsAddress(delPk1.Address().Bytes())
)
func makeTestCodec() (cdc *codec.Codec) {
cdc = codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
types.RegisterCodec(cdc)
return
}
func TestDecodeDistributionStore(t *testing.T) {
cdc := makeTestCodec()
decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.OneDec())}
feePool := types.InitialFeePool()
feePool.CommunityPool = decCoins
info := types.NewDelegatorStartingInfo(2, sdk.OneDec(), 200)
outstanding := types.ValidatorOutstandingRewards{decCoins[0]}
commission := types.ValidatorAccumulatedCommission{decCoins[0]}
historicalRewards := types.NewValidatorHistoricalRewards(decCoins, 100)
currentRewards := types.NewValidatorCurrentRewards(decCoins, 5)
slashEvent := types.NewValidatorSlashEvent(10, sdk.OneDec())
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: keeper.FeePoolKey, Value: cdc.MustMarshalBinaryLengthPrefixed(feePool)},
cmn.KVPair{Key: keeper.ProposerKey, Value: consAddr1.Bytes()},
cmn.KVPair{Key: keeper.GetValidatorOutstandingRewardsKey(valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(outstanding)},
cmn.KVPair{Key: keeper.GetDelegatorWithdrawAddrKey(delAddr1), Value: delAddr1.Bytes()},
cmn.KVPair{Key: keeper.GetDelegatorStartingInfoKey(valAddr1, delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(info)},
cmn.KVPair{Key: keeper.GetValidatorHistoricalRewardsKey(valAddr1, 100), Value: cdc.MustMarshalBinaryLengthPrefixed(historicalRewards)},
cmn.KVPair{Key: keeper.GetValidatorCurrentRewardsKey(valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(currentRewards)},
cmn.KVPair{Key: keeper.GetValidatorAccumulatedCommissionKey(valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(commission)},
cmn.KVPair{Key: keeper.GetValidatorSlashEventKeyPrefix(valAddr1, 13), Value: cdc.MustMarshalBinaryLengthPrefixed(slashEvent)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"FeePool", fmt.Sprintf("%v\n%v", feePool, feePool)},
{"Proposer", fmt.Sprintf("%v\n%v", consAddr1, consAddr1)},
{"ValidatorOutstandingRewards", fmt.Sprintf("%v\n%v", outstanding, outstanding)},
{"DelegatorWithdrawAddr", fmt.Sprintf("%v\n%v", delAddr1, delAddr1)},
{"DelegatorStartingInfo", fmt.Sprintf("%v\n%v", info, info)},
{"ValidatorHistoricalRewards", fmt.Sprintf("%v\n%v", historicalRewards, historicalRewards)},
{"ValidatorCurrentRewards", fmt.Sprintf("%v\n%v", currentRewards, currentRewards)},
{"ValidatorAccumulatedCommission", fmt.Sprintf("%v\n%v", commission, commission)},
{"ValidatorSlashEvent", fmt.Sprintf("%v\n%v", slashEvent, slashEvent)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeStore(cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeStore(cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}

View File

@ -1,4 +1,4 @@
package simulation
package operations
import (
"fmt"
@ -6,15 +6,14 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/gov"
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
govsimops "github.com/cosmos/cosmos-sdk/x/gov/simulation/operations"
"github.com/cosmos/cosmos-sdk/x/simulation"
)
// SimulateMsgSetWithdrawAddress generates a MsgSetWithdrawAddress with random values.
func SimulateMsgSetWithdrawAddress(m auth.AccountKeeper, k distribution.Keeper) simulation.Operation {
func SimulateMsgSetWithdrawAddress(k distribution.Keeper) simulation.Operation {
handler := distribution.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account) (opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
@ -39,7 +38,7 @@ func SimulateMsgSetWithdrawAddress(m auth.AccountKeeper, k distribution.Keeper)
}
// SimulateMsgWithdrawDelegatorReward generates a MsgWithdrawDelegatorReward with random values.
func SimulateMsgWithdrawDelegatorReward(m auth.AccountKeeper, k distribution.Keeper) simulation.Operation {
func SimulateMsgWithdrawDelegatorReward(k distribution.Keeper) simulation.Operation {
handler := distribution.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account) (opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
@ -64,7 +63,7 @@ func SimulateMsgWithdrawDelegatorReward(m auth.AccountKeeper, k distribution.Kee
}
// SimulateMsgWithdrawValidatorCommission generates a MsgWithdrawValidatorCommission with random values.
func SimulateMsgWithdrawValidatorCommission(m auth.AccountKeeper, k distribution.Keeper) simulation.Operation {
func SimulateMsgWithdrawValidatorCommission(k distribution.Keeper) simulation.Operation {
handler := distribution.NewHandler(k)
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simulation.Account) (opMsg simulation.OperationMsg, fOps []simulation.FutureOperation, err error) {
@ -88,7 +87,7 @@ func SimulateMsgWithdrawValidatorCommission(m auth.AccountKeeper, k distribution
}
// SimulateCommunityPoolSpendProposalContent generates random community-pool-spend proposal content
func SimulateCommunityPoolSpendProposalContent(k distribution.Keeper) govsim.ContentSimulator {
func SimulateCommunityPoolSpendProposalContent(k distribution.Keeper) govsimops.ContentSimulator {
return func(r *rand.Rand, _ *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account) gov.Content {
recipientAcc := simulation.RandomAcc(r, accs)
coins := sdk.Coins{}

View File

@ -17,27 +17,29 @@ import (
)
var (
_ module.AppModuleGenesis = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleGenesis = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the genesis accounts module.
type AppModuleBasic struct{}
// module name
// Name returns the genesis accounts module's name.
func (AppModuleBasic) Name() string {
return ModuleName
}
// register module codec
// RegisterCodec performs a no-op.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the genesis accounts
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(GenesisState{})
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the genesis accounts module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -47,17 +49,18 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers no REST routes for the genesis accounts module.
func (AppModuleBasic) RegisterRESTRoutes(_ context.CLIContext, _ *mux.Router) {}
// get the root tx command of this module
// GetTxCmd returns no root tx command for the genesis accounts module.
func (AppModuleBasic) GetTxCmd(_ *codec.Codec) *cobra.Command { return nil }
// get the root query command of this module
// GetQueryCmd returns no root query command for the genesis accounts module.
func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }
// extra function from sdk.AppModuleBasic
// iterate the genesis accounts and perform an operation at each of them
// IterateGenesisAccounts iterates over the genesis accounts and perform an operation at each of them
// - to used by other modules
func (AppModuleBasic) IterateGenesisAccounts(cdc *codec.Codec, appGenesis map[string]json.RawMessage,
iterateFn func(exported.Account) (stop bool)) {
@ -71,10 +74,21 @@ func (AppModuleBasic) IterateGenesisAccounts(cdc *codec.Codec, appGenesis map[st
}
}
//___________________________
// app module
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the genesis accounts module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
func (AppModuleSimulation) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
//____________________________________________________________________________
// AppModule implements an application module for the genesis accounts module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
accountKeeper types.AccountKeeper
}
@ -82,12 +96,14 @@ type AppModule struct {
func NewAppModule(accountKeeper types.AccountKeeper) module.AppModule {
return module.NewGenesisOnlyAppModule(AppModule{
AppModuleBasic: AppModuleBasic{},
accountKeeper: accountKeeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
accountKeeper: accountKeeper,
})
}
// module init-genesis
// InitGenesis performs genesis initialization for the genesis accounts module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
@ -95,7 +111,8 @@ func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.Va
return []abci.ValidatorUpdate{}
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the genesis accounts
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.accountKeeper)
return ModuleCdc.MustMarshalJSON(gs)

View File

@ -16,27 +16,29 @@ import (
)
var (
_ module.AppModuleGenesis = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleGenesis = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the genutil module.
type AppModuleBasic struct{}
// module name
// Name returns the genutil module's name.
func (AppModuleBasic) Name() string {
return ModuleName
}
// register module codec
// RegisterCodec registers the genutil module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the genutil
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(GenesisState{})
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the genutil module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -46,19 +48,30 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers the REST routes for the genutil module.
func (AppModuleBasic) RegisterRESTRoutes(_ context.CLIContext, _ *mux.Router) {}
// get the root tx command of this module
// GetTxCmd returns no root tx command for the genutil module.
func (AppModuleBasic) GetTxCmd(_ *codec.Codec) *cobra.Command { return nil }
// get the root query command of this module
// GetQueryCmd returns no root query command for the genutil module.
func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }
//___________________________
// app module
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the auth module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder registers a decoder for genutil module's types
func (AppModuleSimulation) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {}
//____________________________________________________________________________
// AppModule implements an application module for the genutil module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
accountKeeper types.AccountKeeper
stakingKeeper types.StakingKeeper
deliverTx deliverTxfn
@ -69,21 +82,24 @@ func NewAppModule(accountKeeper types.AccountKeeper,
stakingKeeper types.StakingKeeper, deliverTx deliverTxfn) module.AppModule {
return module.NewGenesisOnlyAppModule(AppModule{
AppModuleBasic: AppModuleBasic{},
accountKeeper: accountKeeper,
stakingKeeper: stakingKeeper,
deliverTx: deliverTx,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
accountKeeper: accountKeeper,
stakingKeeper: stakingKeeper,
deliverTx: deliverTx,
})
}
// module init-genesis
// InitGenesis performs genesis initialization for the genutil module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
return InitGenesis(ctx, ModuleCdc, am.stakingKeeper, am.deliverTx, genesisState)
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the genutil
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
return nil
}

View File

@ -17,15 +17,17 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov/client"
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
"github.com/cosmos/cosmos-sdk/x/gov/client/rest"
"github.com/cosmos/cosmos-sdk/x/gov/simulation"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// AppModuleBasic - app module basics object
// AppModuleBasic defines the basic application module used by the gov module.
type AppModuleBasic struct {
proposalHandlers []client.ProposalHandler // proposal handlers which live in governance cli and rest
}
@ -37,24 +39,23 @@ func NewAppModuleBasic(proposalHandlers ...client.ProposalHandler) AppModuleBasi
}
}
var _ module.AppModuleBasic = AppModuleBasic{}
// Name - module name
// Name returns the gov module's name.
func (AppModuleBasic) Name() string {
return types.ModuleName
}
// RegisterCodec -register module codec
// RegisterCodec registers the gov module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
RegisterCodec(cdc)
}
// DefaultGenesis - default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the gov
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(DefaultGenesisState())
}
// ValidateGenesis - module validate genesis
// ValidateGenesis performs genesis state validation for the gov module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -64,7 +65,7 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// RegisterRESTRoutes - register rest routes
// RegisterRESTRoutes registers the REST routes for the gov module.
func (a AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
var proposalRESTHandlers []rest.ProposalRESTHandler
for _, proposalHandler := range a.proposalHandlers {
@ -74,7 +75,7 @@ func (a AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Rout
rest.RegisterRoutes(ctx, rtr, proposalRESTHandlers)
}
// GetTxCmd gets the root tx command of this module
// GetTxCmd returns the root tx command for the gov module.
func (a AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
var proposalCLIHandlers []*cobra.Command
@ -85,16 +86,28 @@ func (a AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetTxCmd(StoreKey, cdc, proposalCLIHandlers)
}
// GetQueryCmd gets the root query command of this module
// GetQueryCmd returns the root query command for the gov module.
func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetQueryCmd(StoreKey, cdc)
}
//___________________________
//____________________________________________________________________________
// AppModule - app module object
// AppModuleSimulation defines the module simulation functions used by the gov module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder performs a no-op.
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
//____________________________________________________________________________
// AppModule implements an application module for the gov module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
keeper Keeper
supplyKeeper types.SupplyKeeper
}
@ -102,13 +115,14 @@ type AppModule struct {
// NewAppModule creates a new AppModule object
func NewAppModule(keeper Keeper, supplyKeeper types.SupplyKeeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
supplyKeeper: supplyKeeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
supplyKeeper: supplyKeeper,
}
}
// Name - module name
// Name returns the gov module's name.
func (AppModule) Name() string {
return ModuleName
}
@ -118,27 +132,28 @@ func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
RegisterInvariants(ir, am.keeper)
}
// Route - module message route name
// Route returns the message routing key for the gov module.
func (AppModule) Route() string {
return RouterKey
}
// NewHandler - module handler
// NewHandler returns an sdk.Handler for the gov module.
func (am AppModule) NewHandler() sdk.Handler {
return NewHandler(am.keeper)
}
// QuerierRoute - module querier route name
// QuerierRoute returns the gov module's querier route name.
func (AppModule) QuerierRoute() string {
return QuerierRoute
}
// NewQuerierHandler - module querier
// NewQuerierHandler returns no sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier {
return NewQuerier(am.keeper)
}
// InitGenesis - module init-genesis
// InitGenesis performs genesis initialization for the gov module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
@ -146,16 +161,18 @@ func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.Va
return []abci.ValidatorUpdate{}
}
// ExportGenesis - module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the gov
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return ModuleCdc.MustMarshalJSON(gs)
}
// BeginBlock - module begin-block
// BeginBlock performs a no-op.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// EndBlock - module end-block
// EndBlock returns the end blocker for the gov module. It returns no validator
// updates.
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
EndBlocker(ctx, am.keeper)
return []abci.ValidatorUpdate{}

View File

@ -0,0 +1,45 @@
package simulation
import (
"bytes"
"encoding/binary"
"fmt"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
// DecodeStore unmarshals the KVPair's Value to the corresponding gov type
func DecodeStore(cdc *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], types.ProposalsKeyPrefix):
var proposalA, proposalB types.Proposal
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &proposalA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &proposalB)
return fmt.Sprintf("%v\n%v", proposalA, proposalB)
case bytes.Equal(kvA.Key[:1], types.ActiveProposalQueuePrefix),
bytes.Equal(kvA.Key[:1], types.InactiveProposalQueuePrefix),
bytes.Equal(kvA.Key[:1], types.ProposalIDKey):
proposalIDA := binary.LittleEndian.Uint64(kvA.Value)
proposalIDB := binary.LittleEndian.Uint64(kvB.Value)
return fmt.Sprintf("proposalIDA: %d\nProposalIDB: %d", proposalIDA, proposalIDB)
case bytes.Equal(kvA.Key[:1], types.DepositsKeyPrefix):
var depositA, depositB types.Deposit
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &depositA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &depositB)
return fmt.Sprintf("%v\n%v", depositA, depositB)
case bytes.Equal(kvA.Key[:1], types.VotesKeyPrefix):
var voteA, voteB types.Vote
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &voteA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &voteB)
return fmt.Sprintf("%v\n%v", voteA, voteB)
default:
panic(fmt.Sprintf("invalid governance key prefix %X", kvA.Key[:1]))
}
}

View File

@ -0,0 +1,75 @@
package simulation
import (
"encoding/binary"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
var (
delPk1 = ed25519.GenPrivKey().PubKey()
delAddr1 = sdk.AccAddress(delPk1.Address())
valAddr1 = sdk.ValAddress(delPk1.Address())
consAddr1 = sdk.ConsAddress(delPk1.Address().Bytes())
)
func makeTestCodec() (cdc *codec.Codec) {
cdc = codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
types.RegisterCodec(cdc)
return
}
func TestDecodeStore(t *testing.T) {
cdc := makeTestCodec()
endTime := time.Now().UTC()
content := types.ContentFromProposalType("test", "test", types.ProposalTypeText)
proposal := types.NewProposal(content, 1, endTime, endTime.Add(24*time.Hour))
proposalIDBz := make([]byte, 8)
binary.LittleEndian.PutUint64(proposalIDBz, 1)
deposit := types.NewDeposit(1, delAddr1, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())))
vote := types.NewVote(1, delAddr1, types.OptionYes)
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: types.ProposalKey(1), Value: cdc.MustMarshalBinaryLengthPrefixed(proposal)},
cmn.KVPair{Key: types.InactiveProposalQueueKey(1, endTime), Value: proposalIDBz},
cmn.KVPair{Key: types.DepositKey(1, delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(deposit)},
cmn.KVPair{Key: types.VoteKey(1, delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(vote)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"proposals", fmt.Sprintf("%v\n%v", proposal, proposal)},
{"proposal IDs", "proposalIDA: 1\nProposalIDB: 1"},
{"deposits", fmt.Sprintf("%v\n%v", deposit, deposit)},
{"votes", fmt.Sprintf("%v\n%v", vote, vote)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeStore(cdc, cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeStore(cdc, cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}

View File

@ -1,4 +1,4 @@
package simulation
package operations
import (
"fmt"

View File

@ -14,32 +14,35 @@ import (
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/mint/client/cli"
"github.com/cosmos/cosmos-sdk/x/mint/client/rest"
"github.com/cosmos/cosmos-sdk/x/mint/simulation"
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the mint module.
type AppModuleBasic struct{}
var _ module.AppModuleBasic = AppModuleBasic{}
// module name
// Name returns the mint module's name.
func (AppModuleBasic) Name() string {
return ModuleName
}
// register module codec
// RegisterCodec registers the mint module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the mint
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(DefaultGenesisState())
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the mint module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -49,59 +52,74 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers the REST routes for the mint module.
func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
rest.RegisterRoutes(ctx, rtr)
}
// get the root tx command of this module
// GetTxCmd returns no root tx command for the mint module.
func (AppModuleBasic) GetTxCmd(_ *codec.Codec) *cobra.Command { return nil }
// get the root query command of this module
// GetQueryCmd returns the root query command for the mint module.
func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetQueryCmd(cdc)
}
//___________________________
// app module
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the mint module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder registers a decoder for mint module's types.
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
//____________________________________________________________________________
// AppModule implements an application module for the mint module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
keeper Keeper
}
// NewAppModule creates a new AppModule object
func NewAppModule(keeper Keeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
}
}
// module name
// Name returns the mint module's name.
func (AppModule) Name() string {
return ModuleName
}
// register invariants
// RegisterInvariants registers the mint module invariants.
func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
// module message route name
// Route returns the message routing key for the mint module.
func (AppModule) Route() string { return "" }
// module handler
// NewHandler returns an sdk.Handler for the mint module.
func (am AppModule) NewHandler() sdk.Handler { return nil }
// module querier route name
// QuerierRoute returns the mint module's querier route name.
func (AppModule) QuerierRoute() string {
return QuerierRoute
}
// module querier
// NewQuerierHandler returns the mint module sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier {
return NewQuerier(am.keeper)
}
// module init-genesis
// InitGenesis performs genesis initialization for the mint module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
@ -109,18 +127,20 @@ func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.Va
return []abci.ValidatorUpdate{}
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the mint
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return ModuleCdc.MustMarshalJSON(gs)
}
// module begin-block
// BeginBlock returns the begin blocker for the mint module.
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
BeginBlocker(ctx, am.keeper)
}
// module end-block
// EndBlock returns the end blocker for the mint module. It returns no validator
// updates.
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -0,0 +1,24 @@
package simulation
import (
"bytes"
"fmt"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/mint/internal/types"
)
// DecodeStore unmarshals the KVPair's Value to the corresponding mint type
func DecodeStore(cdc *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key, types.MinterKey):
var minterA, minterB types.Minter
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &minterA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &minterB)
return fmt.Sprintf("%v\n%v", minterA, minterB)
default:
panic(fmt.Sprintf("invalid mint key %X", kvA.Key))
}
}

View File

@ -0,0 +1,48 @@
package simulation
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/mint/internal/types"
)
func makeTestCodec() (cdc *codec.Codec) {
cdc = codec.New()
sdk.RegisterCodec(cdc)
return
}
func TestDecodeStore(t *testing.T) {
cdc := makeTestCodec()
minter := types.NewMinter(sdk.OneDec(), sdk.NewDec(15))
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: types.MinterKey, Value: cdc.MustMarshalBinaryLengthPrefixed(minter)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"Minter", fmt.Sprintf("%v\n%v", minter, minter)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeStore(cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeStore(cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}

View File

@ -16,32 +16,31 @@ var (
_ module.AppModuleBasic = AppModuleBasic{}
)
const moduleName = "params"
// app module basics object
// AppModuleBasic defines the basic application module used by the params module.
type AppModuleBasic struct{}
// module name
// Name returns the params module's name.
func (AppModuleBasic) Name() string {
return moduleName
return ModuleName
}
// register module codec
// RegisterCodec registers the params module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
types.RegisterCodec(cdc)
}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the params
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage { return nil }
// module validate genesis
// ValidateGenesis performs genesis state validation for the params module.
func (AppModuleBasic) ValidateGenesis(_ json.RawMessage) error { return nil }
// register rest routes
// RegisterRESTRoutes registers the REST routes for the params module.
func (AppModuleBasic) RegisterRESTRoutes(_ context.CLIContext, _ *mux.Router) {}
// get the root tx command of this module
// GetTxCmd returns no root tx command for the params module.
func (AppModuleBasic) GetTxCmd(_ *codec.Codec) *cobra.Command { return nil }
// get the root query command of this module
// GetQueryCmd returns no root query command for the params module.
func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }

View File

@ -1,4 +1,4 @@
package simulation
package operations
import (
"encoding/json"

View File

@ -15,34 +15,37 @@ import (
"github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
"github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
"github.com/cosmos/cosmos-sdk/x/slashing/internal/types"
"github.com/cosmos/cosmos-sdk/x/slashing/simulation"
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the slashing module.
type AppModuleBasic struct{}
var _ module.AppModuleBasic = AppModuleBasic{}
// module name
// Name returns the slashing module's name.
func (AppModuleBasic) Name() string {
return types.ModuleName
}
// register module codec
// RegisterCodec registers the slashing module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
RegisterCodec(cdc)
}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the slashing
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(DefaultGenesisState())
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the slashing module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -52,25 +55,38 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers the REST routes for the slashing module.
func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
rest.RegisterRoutes(ctx, rtr)
}
// get the root tx command of this module
// GetTxCmd returns the root tx command for the slashing module.
func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetTxCmd(cdc)
}
// get the root query command of this module
// GetQueryCmd returns no root query command for the slashing module.
func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetQueryCmd(StoreKey, cdc)
}
//___________________________
// app module
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the slashing module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder registers a decoder for slashing module's types
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
//____________________________________________________________________________
// AppModule implements an application module for the slashing module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
keeper Keeper
stakingKeeper types.StakingKeeper
}
@ -78,41 +94,43 @@ type AppModule struct {
// NewAppModule creates a new AppModule object
func NewAppModule(keeper Keeper, stakingKeeper types.StakingKeeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
stakingKeeper: stakingKeeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
stakingKeeper: stakingKeeper,
}
}
// module name
// Name returns the slashing module's name.
func (AppModule) Name() string {
return ModuleName
}
// register invariants
// RegisterInvariants registers the slashing module invariants.
func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
// module message route name
// Route returns the message routing key for the slashing module.
func (AppModule) Route() string {
return RouterKey
}
// module handler
// NewHandler returns an sdk.Handler for the slashing module.
func (am AppModule) NewHandler() sdk.Handler {
return NewHandler(am.keeper)
}
// module querier route name
// QuerierRoute returns the slashing module's querier route name.
func (AppModule) QuerierRoute() string {
return QuerierRoute
}
// module querier
// NewQuerierHandler returns the slashing module sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier {
return NewQuerier(am.keeper)
}
// module init-genesis
// InitGenesis performs genesis initialization for the slashing module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
@ -120,18 +138,20 @@ func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.Va
return []abci.ValidatorUpdate{}
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the slashing
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return ModuleCdc.MustMarshalJSON(gs)
}
// module begin-block
// BeginBlock returns the begin blocker for the slashing module.
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, req, am.keeper)
}
// module end-block
// EndBlock returns the end blocker for the slashing module. It returns no validator
// updates.
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -0,0 +1,41 @@
package simulation
import (
"bytes"
"fmt"
"github.com/tendermint/tendermint/crypto"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/slashing/internal/types"
)
// DecodeStore unmarshals the KVPair's Value to the corresponding slashing type
func DecodeStore(cdc *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], types.ValidatorSigningInfoKey):
var infoA, infoB types.ValidatorSigningInfo
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &infoA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &infoB)
return fmt.Sprintf("%v\n%v", infoA, infoB)
case bytes.Equal(kvA.Key[:1], types.ValidatorMissedBlockBitArrayKey):
var missedA, missedB bool
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &missedA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &missedB)
return fmt.Sprintf("missedA: %v\nmissedB: %v", missedA, missedB)
case bytes.Equal(kvA.Key[:1], types.AddrPubkeyRelationKey):
var pubKeyA, pubKeyB crypto.PubKey
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &pubKeyA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &pubKeyB)
bechPKA := sdk.MustBech32ifyAccPub(pubKeyA)
bechPKB := sdk.MustBech32ifyAccPub(pubKeyB)
return fmt.Sprintf("PubKeyA: %s\nPubKeyB: %s", bechPKA, bechPKB)
default:
panic(fmt.Sprintf("invalid slashing key prefix %X", kvA.Key[:1]))
}
}

View File

@ -0,0 +1,66 @@
package simulation
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/slashing/internal/types"
)
var (
delPk1 = ed25519.GenPrivKey().PubKey()
delAddr1 = sdk.AccAddress(delPk1.Address())
valAddr1 = sdk.ValAddress(delPk1.Address())
consAddr1 = sdk.ConsAddress(delPk1.Address().Bytes())
)
func makeTestCodec() (cdc *codec.Codec) {
cdc = codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
types.RegisterCodec(cdc)
return
}
func TestDecodeStore(t *testing.T) {
cdc := makeTestCodec()
info := types.NewValidatorSigningInfo(consAddr1, 0, 1, time.Now().UTC(), false, 0)
bechPK := sdk.MustBech32ifyAccPub(delPk1)
missed := true
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: types.GetValidatorSigningInfoKey(consAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(info)},
cmn.KVPair{Key: types.GetValidatorMissedBlockBitArrayKey(consAddr1, 6), Value: cdc.MustMarshalBinaryLengthPrefixed(missed)},
cmn.KVPair{Key: types.GetAddrPubkeyRelationKey(delAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(delPk1)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"ValidatorSigningInfo", fmt.Sprintf("%v\n%v", info, info)},
{"ValidatorMissedBlockBitArray", fmt.Sprintf("missedA: %v\nmissedB: %v", missed, missed)},
{"AddrPubkeyRelation", fmt.Sprintf("PubKeyA: %s\nPubKeyB: %s", bechPK, bechPK)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeStore(cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeStore(cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}

View File

@ -1,4 +1,4 @@
package simulation
package operations
import (
"fmt"

View File

@ -18,35 +18,38 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/staking/client/cli"
"github.com/cosmos/cosmos-sdk/x/staking/client/rest"
"github.com/cosmos/cosmos-sdk/x/staking/simulation"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the staking module.
type AppModuleBasic struct{}
var _ module.AppModuleBasic = AppModuleBasic{}
// module name
// Name returns the staking module's name.
func (AppModuleBasic) Name() string {
return ModuleName
}
// register module codec
// RegisterCodec registers the staking module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
RegisterCodec(cdc)
}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the staking
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(DefaultGenesisState())
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the staking module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -56,17 +59,17 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers the REST routes for the staking module.
func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
rest.RegisterRoutes(ctx, rtr)
}
// get the root tx command of this module
// GetTxCmd returns the root tx command for the staking module.
func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetTxCmd(StoreKey, cdc)
}
// get the root query command of this module
// GetQueryCmd returns no root query command for the staking module.
func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetQueryCmd(StoreKey, cdc)
}
@ -92,9 +95,23 @@ func (AppModuleBasic) BuildCreateValidatorMsg(cliCtx context.CLIContext,
return cli.BuildCreateValidatorMsg(cliCtx, txBldr)
}
// app module
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the staking module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder registers a decoder for staking module's types
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
//____________________________________________________________________________
// AppModule implements an application module for the staking module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
keeper Keeper
distrKeeper types.DistributionKeeper
accKeeper types.AccountKeeper
@ -106,61 +123,65 @@ func NewAppModule(keeper Keeper, distrKeeper types.DistributionKeeper, accKeeper
supplyKeeper types.SupplyKeeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
distrKeeper: distrKeeper,
accKeeper: accKeeper,
supplyKeeper: supplyKeeper,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
distrKeeper: distrKeeper,
accKeeper: accKeeper,
supplyKeeper: supplyKeeper,
}
}
// module name
// Name returns the staking module's name.
func (AppModule) Name() string {
return ModuleName
}
// register invariants
// RegisterInvariants registers the staking module invariants.
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
RegisterInvariants(ir, am.keeper)
}
// module message route name
// Route returns the message routing key for the staking module.
func (AppModule) Route() string {
return RouterKey
}
// module handler
// NewHandler returns an sdk.Handler for the staking module.
func (am AppModule) NewHandler() sdk.Handler {
return NewHandler(am.keeper)
}
// module querier route name
// QuerierRoute returns the staking module's querier route name.
func (AppModule) QuerierRoute() string {
return QuerierRoute
}
// module querier
// NewQuerierHandler returns the staking module sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier {
return NewQuerier(am.keeper)
}
// module init-genesis
// InitGenesis performs genesis initialization for the staking module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
return InitGenesis(ctx, am.keeper, am.accKeeper, am.supplyKeeper, genesisState)
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the staking
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return ModuleCdc.MustMarshalJSON(gs)
}
// module begin-block
// BeginBlock returns the begin blocker for the staking module.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
// EndBlock returns the end blocker for the staking module. It returns no validator
// updates.
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return EndBlocker(ctx, am.keeper)
}

View File

@ -0,0 +1,57 @@
package simulation
import (
"bytes"
"fmt"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
// DecodeStore unmarshals the KVPair's Value to the corresponding staking type
func DecodeStore(cdc *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], types.LastTotalPowerKey):
var powerA, powerB sdk.Int
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &powerA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &powerB)
return fmt.Sprintf("%v\n%v", powerA, powerB)
case bytes.Equal(kvA.Key[:1], types.ValidatorsKey):
var validatorA, validatorB types.Validator
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &validatorA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &validatorB)
return fmt.Sprintf("%v\n%v", validatorA, validatorB)
case bytes.Equal(kvA.Key[:1], types.LastValidatorPowerKey),
bytes.Equal(kvA.Key[:1], types.ValidatorsByConsAddrKey),
bytes.Equal(kvA.Key[:1], types.ValidatorsByPowerIndexKey):
return fmt.Sprintf("%v\n%v", sdk.ValAddress(kvA.Value), sdk.ValAddress(kvB.Value))
case bytes.Equal(kvA.Key[:1], types.DelegationKey):
var delegationA, delegationB types.Delegation
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &delegationA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &delegationB)
return fmt.Sprintf("%v\n%v", delegationA, delegationB)
case bytes.Equal(kvA.Key[:1], types.UnbondingDelegationKey),
bytes.Equal(kvA.Key[:1], types.UnbondingDelegationByValIndexKey):
var ubdA, ubdB types.UnbondingDelegation
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &ubdA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &ubdB)
return fmt.Sprintf("%v\n%v", ubdA, ubdB)
case bytes.Equal(kvA.Key[:1], types.RedelegationKey),
bytes.Equal(kvA.Key[:1], types.RedelegationByValSrcIndexKey):
var redA, redB types.Redelegation
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &redA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &redB)
return fmt.Sprintf("%v\n%v", redA, redB)
default:
panic(fmt.Sprintf("invalid staking key prefix %X", kvA.Key[:1]))
}
}

View File

@ -0,0 +1,75 @@
package simulation
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
var (
delPk1 = ed25519.GenPrivKey().PubKey()
delAddr1 = sdk.AccAddress(delPk1.Address())
valAddr1 = sdk.ValAddress(delPk1.Address())
consAddr1 = sdk.ConsAddress(delPk1.Address().Bytes())
)
func makeTestCodec() (cdc *codec.Codec) {
cdc = codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
types.RegisterCodec(cdc)
return
}
func TestDecodeStore(t *testing.T) {
cdc := makeTestCodec()
bondTime := time.Now().UTC()
val := types.NewValidator(valAddr1, delPk1, types.NewDescription("test", "test", "test", "test", "test"))
del := types.NewDelegation(delAddr1, valAddr1, sdk.OneDec())
ubd := types.NewUnbondingDelegation(delAddr1, valAddr1, 15, bondTime, sdk.OneInt())
red := types.NewRedelegation(delAddr1, valAddr1, valAddr1, 12, bondTime, sdk.OneInt(), sdk.OneDec())
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: types.LastTotalPowerKey, Value: cdc.MustMarshalBinaryLengthPrefixed(sdk.OneInt())},
cmn.KVPair{Key: types.GetValidatorKey(valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(val)},
cmn.KVPair{Key: types.LastValidatorPowerKey, Value: valAddr1.Bytes()},
cmn.KVPair{Key: types.GetDelegationKey(delAddr1, valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(del)},
cmn.KVPair{Key: types.GetUBDKey(delAddr1, valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(ubd)},
cmn.KVPair{Key: types.GetREDKey(delAddr1, valAddr1, valAddr1), Value: cdc.MustMarshalBinaryLengthPrefixed(red)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"LastTotalPower", fmt.Sprintf("%v\n%v", sdk.OneInt(), sdk.OneInt())},
{"Validator", fmt.Sprintf("%v\n%v", val, val)},
{"LastValidatorPower/ValidatorsByConsAddr/ValidatorsByPowerIndex", fmt.Sprintf("%v\n%v", valAddr1, valAddr1)},
{"Delegation", fmt.Sprintf("%v\n%v", del, del)},
{"UnbondingDelegation", fmt.Sprintf("%v\n%v", ubd, ubd)},
{"Redelegation", fmt.Sprintf("%v\n%v", red, red)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeStore(cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeStore(cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}

View File

@ -1,4 +1,4 @@
package simulation
package operations
import (
"fmt"

View File

@ -15,32 +15,35 @@ import (
"github.com/cosmos/cosmos-sdk/x/supply/client/cli"
"github.com/cosmos/cosmos-sdk/x/supply/client/rest"
"github.com/cosmos/cosmos-sdk/x/supply/internal/types"
"github.com/cosmos/cosmos-sdk/x/supply/simulation"
)
var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
_ module.AppModuleSimulation = AppModuleSimulation{}
)
// app module basics object
// AppModuleBasic defines the basic application module used by the supply module.
type AppModuleBasic struct{}
// module name
// Name returns the supply module's name.
func (AppModuleBasic) Name() string {
return ModuleName
}
// register module codec
// RegisterCodec registers the supply module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
RegisterCodec(cdc)
}
// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the supply
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return ModuleCdc.MustMarshalJSON(DefaultGenesisState())
}
// module validate genesis
// ValidateGenesis performs genesis state validation for the supply module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data GenesisState
err := ModuleCdc.UnmarshalJSON(bz, &data)
@ -50,22 +53,36 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return ValidateGenesis(data)
}
// register rest routes
// RegisterRESTRoutes registers the REST routes for the supply module.
func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
rest.RegisterRoutes(ctx, rtr)
}
// get the root tx command of this module
// GetTxCmd returns the root tx command for the supply module.
func (AppModuleBasic) GetTxCmd(_ *codec.Codec) *cobra.Command { return nil }
// get the root query command of this module
// GetQueryCmd returns no root query command for the supply module.
func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetQueryCmd(cdc)
}
// app module
//____________________________________________________________________________
// AppModuleSimulation defines the module simulation functions used by the supply module.
type AppModuleSimulation struct{}
// RegisterStoreDecoder registers a decoder for supply module's types
func (AppModuleSimulation) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
sdr[StoreKey] = simulation.DecodeStore
}
//____________________________________________________________________________
// AppModule implements an application module for the supply module.
type AppModule struct {
AppModuleBasic
AppModuleSimulation
keeper Keeper
ak types.AccountKeeper
}
@ -73,41 +90,43 @@ type AppModule struct {
// NewAppModule creates a new AppModule object
func NewAppModule(keeper Keeper, ak types.AccountKeeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
ak: ak,
AppModuleBasic: AppModuleBasic{},
AppModuleSimulation: AppModuleSimulation{},
keeper: keeper,
ak: ak,
}
}
// module name
// Name returns the supply module's name.
func (AppModule) Name() string {
return ModuleName
}
// register invariants
// RegisterInvariants registers the supply module invariants.
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
RegisterInvariants(ir, am.keeper)
}
// module message route name
// Route returns the message routing key for the supply module.
func (AppModule) Route() string {
return RouterKey
}
// module handler
// NewHandler returns an sdk.Handler for the supply module.
func (am AppModule) NewHandler() sdk.Handler { return nil }
// module querier route name
// QuerierRoute returns the supply module's querier route name.
func (AppModule) QuerierRoute() string {
return QuerierRoute
}
// module querier
// NewQuerierHandler returns the supply module sdk.Querier.
func (am AppModule) NewQuerierHandler() sdk.Querier {
return NewQuerier(am.keeper)
}
// module init-genesis
// InitGenesis performs genesis initialization for the supply module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
ModuleCdc.MustUnmarshalJSON(data, &genesisState)
@ -115,16 +134,18 @@ func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.Va
return []abci.ValidatorUpdate{}
}
// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the supply
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
return ModuleCdc.MustMarshalJSON(gs)
}
// module begin-block
// BeginBlock returns the begin blocker for the supply module.
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
// module end-block
// EndBlock returns the end blocker for the supply module. It returns no validator
// updates.
func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

View File

@ -0,0 +1,25 @@
package simulation
import (
"bytes"
"fmt"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/supply/internal/keeper"
"github.com/cosmos/cosmos-sdk/x/supply/internal/types"
)
// DecodeStore unmarshals the KVPair's Value to the corresponding supply type
func DecodeStore(cdc *codec.Codec, kvA, kvB cmn.KVPair) string {
switch {
case bytes.Equal(kvA.Key[:1], keeper.SupplyKey):
var supplyA, supplyB types.Supply
cdc.MustUnmarshalBinaryLengthPrefixed(kvA.Value, &supplyA)
cdc.MustUnmarshalBinaryLengthPrefixed(kvB.Value, &supplyB)
return fmt.Sprintf("%v\n%v", supplyB, supplyB)
default:
panic(fmt.Sprintf("invalid supply key %X", kvA.Key))
}
}

View File

@ -0,0 +1,52 @@
package simulation
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/supply/internal/keeper"
"github.com/cosmos/cosmos-sdk/x/supply/internal/types"
)
func makeTestCodec() (cdc *codec.Codec) {
cdc = codec.New()
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
types.RegisterCodec(cdc)
return
}
func TestDecodeStore(t *testing.T) {
cdc := makeTestCodec()
totalSupply := types.NewSupply(sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000)))
kvPairs := cmn.KVPairs{
cmn.KVPair{Key: keeper.SupplyKey, Value: cdc.MustMarshalBinaryLengthPrefixed(totalSupply)},
cmn.KVPair{Key: []byte{0x99}, Value: []byte{0x99}},
}
tests := []struct {
name string
expectedLog string
}{
{"Supply", fmt.Sprintf("%v\n%v", totalSupply, totalSupply)},
{"other", ""},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch i {
case len(tests) - 1:
require.Panics(t, func() { DecodeStore(cdc, kvPairs[i], kvPairs[i]) }, tt.name)
default:
require.Equal(t, tt.expectedLog, DecodeStore(cdc, kvPairs[i], kvPairs[i]), tt.name)
}
})
}
}