From e5b1e4d1ced00a127f82a9d1b8055b69993b5aa4 Mon Sep 17 00:00:00 2001 From: changtong1996 <36472950+changtong1996@users.noreply.github.com> Date: Sat, 2 May 2020 16:08:54 +0800 Subject: [PATCH] v1.0 --- Makefile | 33 +++ app/app.go | 346 ++++++++++++++++++++++ app/export.go | 169 +++++++++++ cmd/djzhcli/main.go | 173 +++++++++++ cmd/djzhd/genaccounts.go | 153 ++++++++++ cmd/djzhd/main.go | 109 +++++++ go.mod | 20 ++ x/djzh/README.md | 7 + x/djzh/abci.go | 17 ++ x/djzh/alias.go | 46 +++ x/djzh/client/cli/query.go | 82 +++++ x/djzh/client/cli/tx.go | 83 ++++++ x/djzh/client/rest/query.go | 58 ++++ x/djzh/client/rest/rest.go | 24 ++ x/djzh/client/rest/tx.go | 279 +++++++++++++++++ x/djzh/genesis.go | 21 ++ x/djzh/handler.go | 236 +++++++++++++++ x/djzh/internal/keeper/keeper.go | 178 +++++++++++ x/djzh/internal/keeper/params.go | 22 ++ x/djzh/internal/keeper/querier.go | 66 +++++ x/djzh/internal/types/codec.go | 25 ++ x/djzh/internal/types/errors.go | 11 + x/djzh/internal/types/events.go | 31 ++ x/djzh/internal/types/expected_keepers.go | 24 ++ x/djzh/internal/types/genesis.go | 26 ++ x/djzh/internal/types/key.go | 15 + x/djzh/internal/types/msg.go | 322 ++++++++++++++++++++ x/djzh/internal/types/params.go | 57 ++++ x/djzh/internal/types/querier.go | 19 ++ x/djzh/internal/types/types.go | 117 ++++++++ x/djzh/module.go | 146 +++++++++ x/djzh/spec/README.md | 17 ++ 32 files changed, 2932 insertions(+) create mode 100644 Makefile create mode 100644 app/app.go create mode 100644 app/export.go create mode 100644 cmd/djzhcli/main.go create mode 100644 cmd/djzhd/genaccounts.go create mode 100644 cmd/djzhd/main.go create mode 100644 go.mod create mode 100644 x/djzh/README.md create mode 100644 x/djzh/abci.go create mode 100644 x/djzh/alias.go create mode 100644 x/djzh/client/cli/query.go create mode 100644 x/djzh/client/cli/tx.go create mode 100644 x/djzh/client/rest/query.go create mode 100644 x/djzh/client/rest/rest.go create mode 100644 x/djzh/client/rest/tx.go create mode 100644 x/djzh/genesis.go create mode 100644 x/djzh/handler.go create mode 100644 x/djzh/internal/keeper/keeper.go create mode 100644 x/djzh/internal/keeper/params.go create mode 100644 x/djzh/internal/keeper/querier.go create mode 100644 x/djzh/internal/types/codec.go create mode 100644 x/djzh/internal/types/errors.go create mode 100644 x/djzh/internal/types/events.go create mode 100644 x/djzh/internal/types/expected_keepers.go create mode 100644 x/djzh/internal/types/genesis.go create mode 100644 x/djzh/internal/types/key.go create mode 100644 x/djzh/internal/types/msg.go create mode 100644 x/djzh/internal/types/params.go create mode 100644 x/djzh/internal/types/querier.go create mode 100644 x/djzh/internal/types/types.go create mode 100644 x/djzh/module.go create mode 100644 x/djzh/spec/README.md diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..81f0332 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +PACKAGES=$(shell go list ./... | grep -v '/simulation') + +VERSION := $(shell echo $(shell git describe --tags) | sed 's/^v//') +COMMIT := $(shell git log -1 --format='%H') + +# TODO: Update the ldflags with the app, client & server names +ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=NewApp \ + -X github.com/cosmos/cosmos-sdk/version.ServerName=djzhd \ + -X github.com/cosmos/cosmos-sdk/version.ClientName=djzhcli \ + -X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \ + -X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) + +BUILD_FLAGS := -ldflags '$(ldflags)' + +all: install + +install: go.sum + go install $(BUILD_FLAGS) ./cmd/djzhd + go install $(BUILD_FLAGS) ./cmd/djzhcli + +go.sum: go.mod + @echo "--> Ensure dependencies have not been modified" + GO111MODULE=on go mod verify + +# Uncomment when you have some tests +# test: +# @go test -mod=readonly $(PACKAGES) + +# look into .golangci.yml for enabling / disabling linters +lint: + @echo "--> Running linter" + @golangci-lint run + @go mod verify \ No newline at end of file diff --git a/app/app.go b/app/app.go new file mode 100644 index 0000000..14ed91f --- /dev/null +++ b/app/app.go @@ -0,0 +1,346 @@ +package app + +import ( + "encoding/json" + "io" + "os" + + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + tmos "github.com/tendermint/tendermint/libs/os" + dbm "github.com/tendermint/tm-db" + + bam "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/vesting" + "github.com/cosmos/cosmos-sdk/x/bank" + distr "github.com/cosmos/cosmos-sdk/x/distribution" + "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/slashing" + "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/cosmos/cosmos-sdk/x/supply" + + "github.com/changtong1996/djzh/x/djzh" +) + +const appName = "app" + +var ( + // TODO: rename your cli + + // DefaultCLIHome default home directories for the application CLI + DefaultCLIHome = os.ExpandEnv("$HOME/.djzhcli") + + // TODO: rename your daemon + + // DefaultNodeHome sets the folder where the applcation data and configuration will be stored + DefaultNodeHome = os.ExpandEnv("$HOME/.djzhd") + + // ModuleBasics The module BasicManager is in charge of setting up basic, + // non-dependant module elements, such as codec registration + // and genesis verification. + ModuleBasics = module.NewBasicManager( + genutil.AppModuleBasic{}, + auth.AppModuleBasic{}, + bank.AppModuleBasic{}, + staking.AppModuleBasic{}, + distr.AppModuleBasic{}, + params.AppModuleBasic{}, + slashing.AppModuleBasic{}, + supply.AppModuleBasic{}, + // TODO: Add your module(s) AppModuleBasic + djzh.AppModuleBasic{}, + ) + + // module account permissions + maccPerms = map[string][]string{ + auth.FeeCollectorName: nil, + distr.ModuleName: nil, + staking.BondedPoolName: {supply.Burner, supply.Staking}, + staking.NotBondedPoolName: {supply.Burner, supply.Staking}, + } +) + +// MakeCodec creates the application codec. The codec is sealed before it is +// returned. +func MakeCodec() *codec.Codec { + var cdc = codec.New() + + ModuleBasics.RegisterCodec(cdc) + vesting.RegisterCodec(cdc) + sdk.RegisterCodec(cdc) + codec.RegisterCrypto(cdc) + + return cdc.Seal() +} + +// NewApp extended ABCI application +type NewApp struct { + *bam.BaseApp + cdc *codec.Codec + + invCheckPeriod uint + + // keys to access the substores + keys map[string]*sdk.KVStoreKey + tKeys map[string]*sdk.TransientStoreKey + + // subspaces + subspaces map[string]params.Subspace + + // keepers + accountKeeper auth.AccountKeeper + bankKeeper bank.Keeper + stakingKeeper staking.Keeper + slashingKeeper slashing.Keeper + distrKeeper distr.Keeper + supplyKeeper supply.Keeper + paramsKeeper params.Keeper + // TODO: Add your module(s) + djzhKeeper djzh.Keeper + + // Module Manager + mm *module.Manager + + // simulation manager + sm *module.SimulationManager +} + +// verify app interface at compile time +var _ simapp.App = (*NewApp)(nil) + +// NewdjzhApp is a constructor function for djzhApp +func NewInitApp( + logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, + invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp), +) *NewApp { + // First define the top level codec that will be shared by the different modules + cdc := MakeCodec() + + // BaseApp handles interactions with Tendermint through the ABCI protocol + bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc), baseAppOptions...) + bApp.SetCommitMultiStoreTracer(traceStore) + bApp.SetAppVersion(version.Version) + + // TODO: Add the keys that module requires + keys := sdk.NewKVStoreKeys(bam.MainStoreKey, auth.StoreKey, staking.StoreKey, + supply.StoreKey, distr.StoreKey, slashing.StoreKey, params.StoreKey, djzh.StoreKey) + + tKeys := sdk.NewTransientStoreKeys(staking.TStoreKey, params.TStoreKey) + + // Here you initialize your application with the store keys it requires + var app = &NewApp{ + BaseApp: bApp, + cdc: cdc, + invCheckPeriod: invCheckPeriod, + keys: keys, + tKeys: tKeys, + subspaces: make(map[string]params.Subspace), + } + + // The ParamsKeeper handles parameter storage for the application + app.paramsKeeper = params.NewKeeper(app.cdc, keys[params.StoreKey], tKeys[params.TStoreKey]) + // Set specific supspaces + app.subspaces[auth.ModuleName] = app.paramsKeeper.Subspace(auth.DefaultParamspace) + app.subspaces[bank.ModuleName] = app.paramsKeeper.Subspace(bank.DefaultParamspace) + app.subspaces[staking.ModuleName] = app.paramsKeeper.Subspace(staking.DefaultParamspace) + app.subspaces[distr.ModuleName] = app.paramsKeeper.Subspace(distr.DefaultParamspace) + app.subspaces[slashing.ModuleName] = app.paramsKeeper.Subspace(slashing.DefaultParamspace) + + // The AccountKeeper handles address -> account lookups + app.accountKeeper = auth.NewAccountKeeper( + app.cdc, + keys[auth.StoreKey], + app.subspaces[auth.ModuleName], + auth.ProtoBaseAccount, + ) + + // The BankKeeper allows you perform sdk.Coins interactions + app.bankKeeper = bank.NewBaseKeeper( + app.accountKeeper, + app.subspaces[bank.ModuleName], + app.ModuleAccountAddrs(), + ) + + // The SupplyKeeper collects transaction fees and renders them to the fee distribution module + app.supplyKeeper = supply.NewKeeper( + app.cdc, + keys[supply.StoreKey], + app.accountKeeper, + app.bankKeeper, + maccPerms, + ) + + // The staking keeper + stakingKeeper := staking.NewKeeper( + app.cdc, + keys[staking.StoreKey], + app.supplyKeeper, + app.subspaces[staking.ModuleName], + ) + + app.distrKeeper = distr.NewKeeper( + app.cdc, + keys[distr.StoreKey], + app.subspaces[distr.ModuleName], + &stakingKeeper, + app.supplyKeeper, + auth.FeeCollectorName, + app.ModuleAccountAddrs(), + ) + + app.slashingKeeper = slashing.NewKeeper( + app.cdc, + keys[slashing.StoreKey], + &stakingKeeper, + app.subspaces[slashing.ModuleName], + ) + + // register the staking hooks + // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks + app.stakingKeeper = *stakingKeeper.SetHooks( + staking.NewMultiStakingHooks( + app.distrKeeper.Hooks(), + app.slashingKeeper.Hooks()), + ) + + // TODO: Add your module(s) keepers + app.djzhKeeper = djzh.NewKeeper( + app.bankKeeper, + keys[djzh.StoreKey], + app.cdc, + ) + + // NOTE: Any module instantiated in the module manager that is later modified + // must be passed by reference here. + app.mm = module.NewManager( + genutil.NewAppModule(app.accountKeeper, app.stakingKeeper, app.BaseApp.DeliverTx), + auth.NewAppModule(app.accountKeeper), + bank.NewAppModule(app.bankKeeper, app.accountKeeper), + supply.NewAppModule(app.supplyKeeper, app.accountKeeper), + distr.NewAppModule(app.distrKeeper, app.accountKeeper, app.supplyKeeper, app.stakingKeeper), + slashing.NewAppModule(app.slashingKeeper, app.accountKeeper, app.stakingKeeper), + // TODO: Add your module(s) + staking.NewAppModule(app.stakingKeeper, app.accountKeeper, app.supplyKeeper), + djzh.NewAppModule(app.djzhKeeper, app.bankKeeper), + + ) + // During begin block slashing happens after distr.BeginBlocker so that + // there is nothing left over in the validator fee pool, so as to keep the + // CanWithdrawInvariant invariant. + + app.mm.SetOrderBeginBlockers(distr.ModuleName, slashing.ModuleName) + app.mm.SetOrderEndBlockers(staking.ModuleName) + + // Sets the order of Genesis - Order matters, genutil is to always come last + // NOTE: The genutils module must occur after staking so that pools are + // properly initialized with tokens from genesis accounts. + app.mm.SetOrderInitGenesis( + distr.ModuleName, + staking.ModuleName, + auth.ModuleName, + bank.ModuleName, + slashing.ModuleName, + // TODO: Add your module(s) + supply.ModuleName, + genutil.ModuleName, + djzh.ModuleName, + ) + + // register all module routes and module queriers + app.mm.RegisterRoutes(app.Router(), app.QueryRouter()) + + // The initChainer handles translating the genesis.json file into initial state for the network + app.SetInitChainer(app.InitChainer) + app.SetBeginBlocker(app.BeginBlocker) + app.SetEndBlocker(app.EndBlocker) + + // The AnteHandler handles signature verification and transaction pre-processing + app.SetAnteHandler( + auth.NewAnteHandler( + app.accountKeeper, + app.supplyKeeper, + auth.DefaultSigVerificationGasConsumer, + ), + ) + + // initialize stores + app.MountKVStores(keys) + app.MountTransientStores(tKeys) + + if loadLatest { + err := app.LoadLatestVersion(app.keys[bam.MainStoreKey]) + if err != nil { + tmos.Exit(err.Error()) + } + } + + return app +} + +// GenesisState represents chain state at the start of the chain. Any initial state (account balances) are stored here. +type GenesisState map[string]json.RawMessage + +// NewDefaultGenesisState generates the default state for the application. +func NewDefaultGenesisState() GenesisState { + return ModuleBasics.DefaultGenesis() +} + +// InitChainer application update at chain initialization +func (app *NewApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { + var genesisState simapp.GenesisState + + app.cdc.MustUnmarshalJSON(req.AppStateBytes, &genesisState) + + return app.mm.InitGenesis(ctx, genesisState) +} + +// BeginBlocker application updates every begin block +func (app *NewApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { + return app.mm.BeginBlock(ctx, req) +} + +// EndBlocker application updates every end block +func (app *NewApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { + return app.mm.EndBlock(ctx, req) +} + +// LoadHeight loads a particular height +func (app *NewApp) LoadHeight(height int64) error { + return app.LoadVersion(height, app.keys[bam.MainStoreKey]) +} + +// ModuleAccountAddrs returns all the app's module account addresses. +func (app *NewApp) ModuleAccountAddrs() map[string]bool { + modAccAddrs := make(map[string]bool) + for acc := range maccPerms { + modAccAddrs[supply.NewModuleAddress(acc).String()] = true + } + + return modAccAddrs +} + +// Codec returns the application's sealed codec. +func (app *NewApp) Codec() *codec.Codec { + return app.cdc +} + +// SimulationManager implements the SimulationApp interface +func (app *NewApp) SimulationManager() *module.SimulationManager { + return app.sm +} + +// GetMaccPerms returns a mapping of the application's module account permissions. +func GetMaccPerms() map[string][]string { + modAccPerms := make(map[string][]string) + for k, v := range maccPerms { + modAccPerms[k] = v + } + return modAccPerms +} diff --git a/app/export.go b/app/export.go new file mode 100644 index 0000000..ebd4f19 --- /dev/null +++ b/app/export.go @@ -0,0 +1,169 @@ +package app + +import ( + "encoding/json" + "log" + + abci "github.com/tendermint/tendermint/abci/types" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/slashing" + "github.com/cosmos/cosmos-sdk/x/staking" +) + +// ExportAppStateAndValidators exports the state of the application for a genesis +// file. +func (app *NewApp) ExportAppStateAndValidators( + forZeroHeight bool, jailWhiteList []string, +) (appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) { + + // as if they could withdraw from the start of the next block + ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()}) + + if forZeroHeight { + app.prepForZeroHeightGenesis(ctx, jailWhiteList) + } + + genState := app.mm.ExportGenesis(ctx) + appState, err = codec.MarshalJSONIndent(app.cdc, genState) + if err != nil { + return nil, nil, err + } + + validators = staking.WriteValidators(ctx, app.stakingKeeper) + return appState, validators, nil +} + +// prepare for fresh start at zero height +// NOTE zero height genesis is a temporary feature which will be deprecated +// in favour of export at a block height +func (app *NewApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string) { + applyWhiteList := false + + //Check if there is a whitelist + if len(jailWhiteList) > 0 { + applyWhiteList = true + } + + whiteListMap := make(map[string]bool) + + for _, addr := range jailWhiteList { + _, err := sdk.ValAddressFromBech32(addr) + if err != nil { + log.Fatal(err) + } + whiteListMap[addr] = true + } + + /* Handle fee distribution state. */ + + // withdraw all validator commission + app.stakingKeeper.IterateValidators(ctx, func(_ int64, val staking.ValidatorI) (stop bool) { + _, err := app.distrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator()) + if err != nil { + log.Fatal(err) + } + return false + }) + + // withdraw all delegator rewards + dels := app.stakingKeeper.GetAllDelegations(ctx) + for _, delegation := range dels { + _, err := app.distrKeeper.WithdrawDelegationRewards(ctx, delegation.DelegatorAddress, delegation.ValidatorAddress) + if err != nil { + log.Fatal(err) + } + } + + // clear validator slash events + app.distrKeeper.DeleteAllValidatorSlashEvents(ctx) + + // clear validator historical rewards + app.distrKeeper.DeleteAllValidatorHistoricalRewards(ctx) + + // set context height to zero + height := ctx.BlockHeight() + ctx = ctx.WithBlockHeight(0) + + // reinitialize all validators + app.stakingKeeper.IterateValidators(ctx, func(_ int64, val staking.ValidatorI) (stop bool) { + + // donate any unwithdrawn outstanding reward fraction tokens to the community pool + scraps := app.distrKeeper.GetValidatorOutstandingRewards(ctx, val.GetOperator()) + feePool := app.distrKeeper.GetFeePool(ctx) + feePool.CommunityPool = feePool.CommunityPool.Add(scraps...) + app.distrKeeper.SetFeePool(ctx, feePool) + + app.distrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()) + return false + }) + + // reinitialize all delegations + for _, del := range dels { + app.distrKeeper.Hooks().BeforeDelegationCreated(ctx, del.DelegatorAddress, del.ValidatorAddress) + app.distrKeeper.Hooks().AfterDelegationModified(ctx, del.DelegatorAddress, del.ValidatorAddress) + } + + // reset context height + ctx = ctx.WithBlockHeight(height) + + /* Handle staking state. */ + + // iterate through redelegations, reset creation height + app.stakingKeeper.IterateRedelegations(ctx, func(_ int64, red staking.Redelegation) (stop bool) { + for i := range red.Entries { + red.Entries[i].CreationHeight = 0 + } + app.stakingKeeper.SetRedelegation(ctx, red) + return false + }) + + // iterate through unbonding delegations, reset creation height + app.stakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd staking.UnbondingDelegation) (stop bool) { + for i := range ubd.Entries { + ubd.Entries[i].CreationHeight = 0 + } + app.stakingKeeper.SetUnbondingDelegation(ctx, ubd) + return false + }) + + // Iterate through validators by power descending, reset bond heights, and + // update bond intra-tx counters. + store := ctx.KVStore(app.keys[staking.StoreKey]) + iter := sdk.KVStoreReversePrefixIterator(store, staking.ValidatorsKey) + counter := int16(0) + + for ; iter.Valid(); iter.Next() { + addr := sdk.ValAddress(iter.Key()[1:]) + validator, found := app.stakingKeeper.GetValidator(ctx, addr) + if !found { + panic("expected validator, not found") + } + + validator.UnbondingHeight = 0 + if applyWhiteList && !whiteListMap[addr.String()] { + validator.Jailed = true + } + + app.stakingKeeper.SetValidator(ctx, validator) + counter++ + } + + iter.Close() + + _ = app.stakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) + + /* Handle slashing state. */ + + // reset start height on signing infos + app.slashingKeeper.IterateValidatorSigningInfos( + ctx, + func(addr sdk.ConsAddress, info slashing.ValidatorSigningInfo) (stop bool) { + info.StartHeight = 0 + app.slashingKeeper.SetValidatorSigningInfo(ctx, addr, info) + return false + }, + ) +} diff --git a/cmd/djzhcli/main.go b/cmd/djzhcli/main.go new file mode 100644 index 0000000..17d361e --- /dev/null +++ b/cmd/djzhcli/main.go @@ -0,0 +1,173 @@ +package main + +import ( + "fmt" + "os" + "path" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/client/lcd" + "github.com/cosmos/cosmos-sdk/client/rpc" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/auth" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" + authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" + "github.com/cosmos/cosmos-sdk/x/bank" + bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/libs/cli" + + "github.com/changtong1996/djzh/app" + +) + +func main() { + // Configure cobra to sort commands + cobra.EnableCommandSorting = false + + // Instantiate the codec for the command line application + cdc := app.MakeCodec() + + // Read in the configuration file for the sdk + config := sdk.GetConfig() + config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub) + config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub) + config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub) + config.Seal() + + // TODO: setup keybase, viper object, etc. to be passed into + // the below functions and eliminate global vars, like we do + // with the cdc + + rootCmd := &cobra.Command{ + Use: "djzhcli", + Short: "djzh client", + } + + // Add --chain-id to persistent flags and mark it required + rootCmd.PersistentFlags().String(flags.FlagChainID, "", "Chain ID of tendermint node") + rootCmd.PersistentPreRunE = func(_ *cobra.Command, _ []string) error { + return initConfig(rootCmd) + } + + // Construct Root Command + rootCmd.AddCommand( + rpc.StatusCommand(), + client.ConfigCmd(app.DefaultCLIHome), + queryCmd(cdc), + txCmd(cdc), + flags.LineBreak, + lcd.ServeCommand(cdc, registerRoutes), + flags.LineBreak, + keys.Commands(), + flags.LineBreak, + version.Cmd, + flags.NewCompletionCmd(rootCmd, true), + ) + + // Add flags and prefix all env exposed with AA + executor := cli.PrepareMainCmd(rootCmd, "AA", app.DefaultCLIHome) + + err := executor.Execute() + if err != nil { + fmt.Printf("Failed executing CLI command: %s, exiting...\n", err) + os.Exit(1) + } +} + +func queryCmd(cdc *amino.Codec) *cobra.Command { + queryCmd := &cobra.Command{ + Use: "query", + Aliases: []string{"q"}, + Short: "Querying subcommands", + } + + queryCmd.AddCommand( + authcmd.GetAccountCmd(cdc), + flags.LineBreak, + rpc.ValidatorCommand(cdc), + rpc.BlockCommand(), + authcmd.QueryTxsByEventsCmd(cdc), + authcmd.QueryTxCmd(cdc), + flags.LineBreak, + ) + + // add modules' query commands + app.ModuleBasics.AddQueryCommands(queryCmd, cdc) + + return queryCmd +} + +func txCmd(cdc *amino.Codec) *cobra.Command { + txCmd := &cobra.Command{ + Use: "tx", + Short: "Transactions subcommands", + } + + txCmd.AddCommand( + bankcmd.SendTxCmd(cdc), + flags.LineBreak, + authcmd.GetSignCommand(cdc), + authcmd.GetMultiSignCommand(cdc), + flags.LineBreak, + authcmd.GetBroadcastCommand(cdc), + authcmd.GetEncodeCommand(cdc), + authcmd.GetDecodeCommand(cdc), + flags.LineBreak, + ) + + // add modules' tx commands + app.ModuleBasics.AddTxCommands(txCmd, cdc) + + // remove auth and bank commands as they're mounted under the root tx command + var cmdsToRemove []*cobra.Command + + for _, cmd := range txCmd.Commands() { + if cmd.Use == auth.ModuleName || cmd.Use == bank.ModuleName { + cmdsToRemove = append(cmdsToRemove, cmd) + } + } + + txCmd.RemoveCommand(cmdsToRemove...) + + return txCmd +} + +// registerRoutes registers the routes from the different modules for the LCD. +// NOTE: details on the routes added for each module are in the module documentation +// NOTE: If making updates here you also need to update the test helper in client/lcd/test_helper.go +func registerRoutes(rs *lcd.RestServer) { + client.RegisterRoutes(rs.CliCtx, rs.Mux) + authrest.RegisterTxRoutes(rs.CliCtx, rs.Mux) + app.ModuleBasics.RegisterRESTRoutes(rs.CliCtx, rs.Mux) +} + +func initConfig(cmd *cobra.Command) error { + home, err := cmd.PersistentFlags().GetString(cli.HomeFlag) + if err != nil { + return err + } + + cfgFile := path.Join(home, "config", "config.toml") + if _, err := os.Stat(cfgFile); err == nil { + viper.SetConfigFile(cfgFile) + + if err := viper.ReadInConfig(); err != nil { + return err + } + } + if err := viper.BindPFlag(flags.FlagChainID, cmd.PersistentFlags().Lookup(flags.FlagChainID)); err != nil { + return err + } + if err := viper.BindPFlag(cli.EncodingFlag, cmd.PersistentFlags().Lookup(cli.EncodingFlag)); err != nil { + return err + } + return viper.BindPFlag(cli.OutputFlag, cmd.PersistentFlags().Lookup(cli.OutputFlag)) +} diff --git a/cmd/djzhd/genaccounts.go b/cmd/djzhd/genaccounts.go new file mode 100644 index 0000000..a7ef321 --- /dev/null +++ b/cmd/djzhd/genaccounts.go @@ -0,0 +1,153 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/tendermint/tendermint/libs/cli" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/keys" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" + authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting" + "github.com/cosmos/cosmos-sdk/x/genutil" +) + +const ( + flagClientHome = "home-client" + flagVestingStart = "vesting-start-time" + flagVestingEnd = "vesting-end-time" + flagVestingAmt = "vesting-amount" +) + +// AddGenesisAccountCmd returns add-genesis-account cobra Command. +func AddGenesisAccountCmd( + ctx *server.Context, cdc *codec.Codec, defaultNodeHome, defaultClientHome string, +) *cobra.Command { + + cmd := &cobra.Command{ + Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]", + Short: "Add a genesis account to genesis.json", + Long: `Add a genesis account to genesis.json. The provided account must specify +the account address or key name and a list of initial coins. If a key name is given, +the address will be looked up in the local Keybase. The list of initial tokens must +contain valid denominations. Accounts may optionally be supplied with vesting parameters. +`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + config := ctx.Config + config.SetRoot(viper.GetString(cli.HomeFlag)) + + addr, err := sdk.AccAddressFromBech32(args[0]) + inBuf := bufio.NewReader(cmd.InOrStdin()) + if err != nil { + // attempt to lookup address from Keybase if no address was provided + kb, err := keys.NewKeyring( + sdk.KeyringServiceName(), + viper.GetString(flags.FlagKeyringBackend), + viper.GetString(flagClientHome), + inBuf, + ) + if err != nil { + return err + } + + info, err := kb.Get(args[0]) + if err != nil { + return fmt.Errorf("failed to get address from Keybase: %w", err) + } + + addr = info.GetAddress() + } + + coins, err := sdk.ParseCoins(args[1]) + if err != nil { + return fmt.Errorf("failed to parse coins: %w", err) + } + + vestingStart := viper.GetInt64(flagVestingStart) + vestingEnd := viper.GetInt64(flagVestingEnd) + vestingAmt, err := sdk.ParseCoins(viper.GetString(flagVestingAmt)) + if err != nil { + return fmt.Errorf("failed to parse vesting amount: %w", err) + } + + // create concrete account type based on input parameters + var genAccount authexported.GenesisAccount + + baseAccount := auth.NewBaseAccount(addr, coins.Sort(), nil, 0, 0) + if !vestingAmt.IsZero() { + baseVestingAccount, err := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd) + if err != nil { + return fmt.Errorf("failed to create base vesting account: %w", err) + } + + switch { + case vestingStart != 0 && vestingEnd != 0: + genAccount = authvesting.NewContinuousVestingAccountRaw(baseVestingAccount, vestingStart) + + case vestingEnd != 0: + genAccount = authvesting.NewDelayedVestingAccountRaw(baseVestingAccount) + + default: + return errors.New("invalid vesting parameters; must supply start and end time or end time") + } + } else { + genAccount = baseAccount + } + + if err := genAccount.Validate(); err != nil { + return fmt.Errorf("failed to validate new genesis account: %w", err) + } + + genFile := config.GenesisFile() + appState, genDoc, err := genutil.GenesisStateFromGenFile(cdc, genFile) + if err != nil { + return fmt.Errorf("failed to unmarshal genesis state: %w", err) + } + + authGenState := auth.GetGenesisStateFromAppState(cdc, appState) + + if authGenState.Accounts.Contains(addr) { + return fmt.Errorf("cannot add account at existing address %s", addr) + } + + // Add the new account to the set of genesis accounts and sanitize the + // accounts afterwards. + authGenState.Accounts = append(authGenState.Accounts, genAccount) + authGenState.Accounts = auth.SanitizeGenesisAccounts(authGenState.Accounts) + + authGenStateBz, err := cdc.MarshalJSON(authGenState) + if err != nil { + return fmt.Errorf("failed to marshal auth genesis state: %w", err) + } + + appState[auth.ModuleName] = authGenStateBz + + appStateJSON, err := cdc.MarshalJSON(appState) + if err != nil { + return fmt.Errorf("failed to marshal application genesis state: %w", err) + } + + genDoc.AppState = appStateJSON + return genutil.ExportGenesisFile(genDoc, genFile) + }, + } + + cmd.Flags().String(cli.HomeFlag, defaultNodeHome, "node's home directory") + //cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") + cmd.Flags().String(flagClientHome, defaultClientHome, "client's home directory") + cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts") + cmd.Flags().Uint64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts") + cmd.Flags().Uint64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts") + + return cmd +} diff --git a/cmd/djzhd/main.go b/cmd/djzhd/main.go new file mode 100644 index 0000000..f4386ef --- /dev/null +++ b/cmd/djzhd/main.go @@ -0,0 +1,109 @@ +package main + +import ( + "encoding/json" + "io" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/cli" + "github.com/tendermint/tendermint/libs/log" + tmtypes "github.com/tendermint/tendermint/types" + dbm "github.com/tendermint/tm-db" + + "github.com/changtong1996/djzh/app" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client/debug" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/server" + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" + "github.com/cosmos/cosmos-sdk/x/staking" +) + +const flagInvCheckPeriod = "inv-check-period" + +var invCheckPeriod uint + +func main() { + cdc := app.MakeCodec() + + config := sdk.GetConfig() + config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub) + config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub) + config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub) + config.Seal() + + ctx := server.NewDefaultContext() + cobra.EnableCommandSorting = false + rootCmd := &cobra.Command{ + Use: "djzhd", + Short: "djzh Daemon (server)", + PersistentPreRunE: server.PersistentPreRunEFn(ctx), + } + + rootCmd.AddCommand(genutilcli.InitCmd(ctx, cdc, app.ModuleBasics, app.DefaultNodeHome)) + rootCmd.AddCommand(genutilcli.CollectGenTxsCmd(ctx, cdc, auth.GenesisAccountIterator{}, app.DefaultNodeHome)) + rootCmd.AddCommand(genutilcli.MigrateGenesisCmd(ctx, cdc)) + rootCmd.AddCommand( + genutilcli.GenTxCmd( + ctx, cdc, app.ModuleBasics, staking.AppModuleBasic{}, + auth.GenesisAccountIterator{}, app.DefaultNodeHome, app.DefaultCLIHome, + ), + ) + rootCmd.AddCommand(genutilcli.ValidateGenesisCmd(ctx, cdc, app.ModuleBasics)) + rootCmd.AddCommand(AddGenesisAccountCmd(ctx, cdc, app.DefaultNodeHome, app.DefaultCLIHome)) + rootCmd.AddCommand(flags.NewCompletionCmd(rootCmd, true)) + rootCmd.AddCommand(debug.Cmd(cdc)) + + server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators) + + // prepare and add flags + executor := cli.PrepareBaseCmd(rootCmd, "AU", app.DefaultNodeHome) + rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod, + 0, "Assert registered invariants every N blocks") + err := executor.Execute() + if err != nil { + panic(err) + } +} + +func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application { + var cache sdk.MultiStorePersistentCache + + if viper.GetBool(server.FlagInterBlockCache) { + cache = store.NewCommitKVStoreCacheManager() + } + + return app.NewInitApp( + logger, db, traceStore, true, invCheckPeriod, + baseapp.SetPruning(store.NewPruningOptionsFromString(viper.GetString("pruning"))), + baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)), + baseapp.SetHaltHeight(viper.GetUint64(server.FlagHaltHeight)), + baseapp.SetHaltTime(viper.GetUint64(server.FlagHaltTime)), + baseapp.SetInterBlockCache(cache), + ) +} + +func exportAppStateAndTMValidators( + logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailWhiteList []string, +) (json.RawMessage, []tmtypes.GenesisValidator, error) { + + if height != -1 { + aApp := app.NewInitApp(logger, db, traceStore, true, uint(1)) + err := aApp.LoadHeight(height) + if err != nil { + return nil, nil, err + } + return aApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList) + } + + aApp := app.NewInitApp(logger, db, traceStore, true, uint(1)) + + return aApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..48ee1f4 --- /dev/null +++ b/go.mod @@ -0,0 +1,20 @@ +module github.com/changtong1996/djzh +go 1.13 + +require ( + github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a // indirect + github.com/cosmos/cosmos-sdk v0.38.0 + github.com/golang/mock v1.3.1 // indirect + github.com/onsi/ginkgo v1.8.0 // indirect + github.com/onsi/gomega v1.5.0 // indirect + github.com/prometheus/client_golang v1.1.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962 // indirect + github.com/spf13/afero v1.2.2 // indirect + github.com/spf13/cobra v0.0.5 + github.com/spf13/viper v1.6.2 + github.com/tendermint/go-amino v0.15.1 + github.com/tendermint/tendermint v0.33.0 + github.com/tendermint/tm-db v0.4.0 + golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect + golang.org/x/text v0.3.2 // indirect +) \ No newline at end of file diff --git a/x/djzh/README.md b/x/djzh/README.md new file mode 100644 index 0000000..23a3fa9 --- /dev/null +++ b/x/djzh/README.md @@ -0,0 +1,7 @@ +# TODO + +The scaffolding tool creates a module with countless todos. These todos are placed in places in which you much delete them and fill them with what the module you are building needs. + +## APP + +Once you have created your module and you are ready to integrate it into your app then you can follow the readme that is generated in the scaffolding of the app. diff --git a/x/djzh/abci.go b/x/djzh/abci.go new file mode 100644 index 0000000..d3435d5 --- /dev/null +++ b/x/djzh/abci.go @@ -0,0 +1,17 @@ +package djzh + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +// BeginBlocker check for infraction evidence or downtime of validators +// on every begin block +func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k Keeper) { +// TODO: fill out if your application requires beginblock, if not you can delete this function +} + +// EndBlocker called every block, process inflation, update validator set. +func EndBlocker(ctx sdk.Context, k Keeper) { +// TODO: fill out if your application requires endblock, if not you can delete this function +} diff --git a/x/djzh/alias.go b/x/djzh/alias.go new file mode 100644 index 0000000..1b39340 --- /dev/null +++ b/x/djzh/alias.go @@ -0,0 +1,46 @@ +package djzh + +import ( + "github.com/changtong1996/djzh/x/djzh/internal/keeper" + "github.com/changtong1996/djzh/x/djzh/internal/types" +) + +const ( + // TODO: define constants that you would like exposed from the internal package + + ModuleName = types.ModuleName + RouterKey = types.RouterKey + StoreKey = types.StoreKey + DefaultParamspace = types.DefaultParamspace + //QueryParams = types.QueryParams + QuerierRoute = types.QuerierRoute +) + +var ( + // functions aliases + NewKeeper = keeper.NewKeeper + NewQuerier = keeper.NewQuerier + RegisterCodec = types.RegisterCodec + NewGenesisState = types.NewGenesisState + DefaultGenesisState = types.DefaultGenesisState + ValidateGenesis = types.ValidateGenesis + // TODO: Fill out function aliases + + // variable aliases + ModuleCdc = types.ModuleCdc + // TODO: Fill out variable aliases +) + +type ( + Keeper = keeper.Keeper + GenesisState = types.GenesisState + Params = types.Params +/* QueryArticleNames = types.QueryArticleNames*/ + // TODO: Fill out module types +/* QueryVoteNum = types.QueryVoteNum*/ + MsgCreateArticle = types.MsgCreateArticle + MsgCreateComment = types.MsgCreateComment + MsgCreateReturnVisit= types.MsgCreateReturnVisit + MsgCreateAVote = types.MsgCreateAVote + MsgCreateCVote = types.MsgCreateCVote +) diff --git a/x/djzh/client/cli/query.go b/x/djzh/client/cli/query.go new file mode 100644 index 0000000..74918df --- /dev/null +++ b/x/djzh/client/cli/query.go @@ -0,0 +1,82 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" +/* sdk "github.com/cosmos/cosmos-sdk/types"*/ + + "github.com/changtong1996/djzh/x/djzh/internal/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { + // Group djzh queries under a subcommand + djzhQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + djzhQueryCmd.AddCommand( + flags.GetCommands( + // TODO: Add query Cmds + GetCmdArticle(queryRoute, cdc), + GetCmdVoteNum(queryRoute, cdc), + )..., + ) + + return djzhQueryCmd +} + +// TODO: Add Query Commands +func GetCmdArticle(queryRoute string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "article [article_id]", + Short: "Query a article by article_id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error{ + cliCtx := context.NewCLIContext().WithCodec(cdc) + article_id := args[0] + + res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/getarticle/%s", queryRoute, article_id), nil) + if err != nil { + fmt.Printf("could not get article - %s \n", article_id) + return nil + } + + var out types.Article + cdc.MustUnmarshalJSON(res, &out) + return cliCtx.PrintOutput(out) + }, + } +} + + +func GetCmdVoteNum(queryRoute string, cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "vote number of article [name]", + Short: "get the vote number of a article", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error{ + cliCtx := context.NewCLIContext().WithCodec(cdc) + name := args[0] + + res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/whois/%s", queryRoute, name), nil) + if err != nil { + fmt.Printf("could not get - %s \n", name) + return nil + } + var out types.Article + cdc.MustUnmarshalJSON(res, &out) + return cliCtx.PrintOutput(out) + }, + } +} \ No newline at end of file diff --git a/x/djzh/client/cli/tx.go b/x/djzh/client/cli/tx.go new file mode 100644 index 0000000..18f6983 --- /dev/null +++ b/x/djzh/client/cli/tx.go @@ -0,0 +1,83 @@ +package cli + +import ( + "fmt" +/* "bufio" + "strconv"*/ + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" +/* "github.com/cosmos/cosmos-sdk/client/context"*/ + "github.com/cosmos/cosmos-sdk/codec" +/* sdk "github.com/cosmos/cosmos-sdk/types"*/ +/* "github.com/cosmos/cosmos-sdk/x/auth"*/ +/* "github.com/cosmos/cosmos-sdk/x/auth/client/utils"*/ + "github.com/changtong1996/djzh/x/djzh/internal/types" +) + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd(cdc *codec.Codec) *cobra.Command { + djzhTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + djzhTxCmd.AddCommand(flags.PostCommands( + // TODO: Add tx based commands + // GetCmd(cdc) + )...) + + return djzhTxCmd +} + + +/*func GetCmdNewVote(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "add-vote [article_id][voteup]", + Short: "add a vote", + Args: cobra.ExactArgs(2), // Does your request require arguments + RunE: func(cmd *cobra.Command, args []string) error { + + cliCtx := context.NewCLIContext().WithCodec(cdc) + inBuf := bufio.NewReader(cmd.InOrStdin()) + txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) + + voteUP, err := strconv.Atoi(args[1]) + msg := types.NewMsgCreateAVote(cliCtx.GetFromAddress(), args[0], voteUP) + err = msg.ValidateBasic() + if err != nil { + return err + } + + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) + }, + } +}*/ + +// Example: +// +// GetCmd is the CLI command for doing +// func GetCmd(cdc *codec.Codec) *cobra.Command { +// return &cobra.Command{ +// Use: "/* Describe your action cmd */", +// Short: "/* Provide a short description on the cmd */", +// Args: cobra.ExactArgs(2), // Does your request require arguments +// RunE: func(cmd *cobra.Command, args []string) error { +// cliCtx := context.NewCLIContext().WithCodec(cdc) +// inBuf := bufio.NewReader(cmd.InOrStdin()) +// txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) + +// msg := types.NewMsg(/* Action params */) +// err = msg.ValidateBasic() +// if err != nil { +// return err +// } + +// return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) +// }, +// } +// } diff --git a/x/djzh/client/rest/query.go b/x/djzh/client/rest/query.go new file mode 100644 index 0000000..000e8ae --- /dev/null +++ b/x/djzh/client/rest/query.go @@ -0,0 +1,58 @@ +package rest + +import ( + "fmt" + "net/http" + + "github.com/gorilla/mux" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/types/rest" +/* "github.com/changtong1996/djzh/x/djzh/internal/types"*/ +) + + +func GetArticleHandler(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) //这个地方有点问题?得到的结果是什么 + + paramType := vars[article_id] + + res, _, err := cliCtx.QueryWithData(fmt.Sprintf("custom/djzh/getarticle/%s", paramType), nil) + if err != nil { + rest.WriteErrorResponse(w, http.StatusNotFound, err.Error()) + return + } + + rest.PostProcessResponse(w, cliCtx, res) + } +} + + +/*func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router) { + // TODO: Define your GET REST endpoints + r.HandleFunc( + "/djzh/parameters", + queryParamsHandlerFn(cliCtx), + ).Methods("GET") +} + +func queryParamsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) + if !ok { + return + } + + route := fmt.Sprintf("custom/%s/parameters", types.QuerierRoute) + + res, height, err := cliCtx.QueryWithData(route, nil) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) + } +}*/ diff --git a/x/djzh/client/rest/rest.go b/x/djzh/client/rest/rest.go new file mode 100644 index 0000000..5d88dfe --- /dev/null +++ b/x/djzh/client/rest/rest.go @@ -0,0 +1,24 @@ +package rest + +import ( + "fmt" + "github.com/gorilla/mux" + + "github.com/cosmos/cosmos-sdk/client/context" +) + +const( + article_id = "article_id" +) + +// RegisterRoutes registers djzh-related REST handlers to a router +func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) { +/* registerQueryRoutes(cliCtx, r) + registerTxRoutes(cliCtx, r)*/ + r.HandleFunc(fmt.Sprintf("/djzh/articles/getarticle"), GetArticleHandler(cliCtx)).Methods("POST") + r.HandleFunc(fmt.Sprintf("/djzh/articles/createarticle"), CreateArticleHandler(cliCtx)).Methods("POST") + r.HandleFunc(fmt.Sprintf("/djzh/articles/createcomment"), CreateCommentHandler(cliCtx)).Methods("POST") + r.HandleFunc(fmt.Sprintf("/djzh/articles/createreturnvisit"), CreateReturnVisitHandler(cliCtx)).Methods("POST") + r.HandleFunc(fmt.Sprintf("/djzh/articles/createavote"), CreateAVoteHandler(cliCtx)).Methods("POST") + r.HandleFunc(fmt.Sprintf("/djzh/articles/createcvote"), CreateCVoteHandler(cliCtx)).Methods("POST") +} diff --git a/x/djzh/client/rest/tx.go b/x/djzh/client/rest/tx.go new file mode 100644 index 0000000..c187745 --- /dev/null +++ b/x/djzh/client/rest/tx.go @@ -0,0 +1,279 @@ +package rest + +import ( + /*"bytes"*/ + "net/http" +/* + "github.com/gorilla/mux"*/ + + "github.com/cosmos/cosmos-sdk/client/context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/x/auth/client/utils" + "github.com/changtong1996/djzh/x/djzh/internal/types" +) + + + +type CreateArticleReq struct { + BaseReq rest.BaseReq `json:"base_req"` + Creator string `json:"creator"` // address of the article creator + A_text string `json:"a_text"` + A_title string `json:"a_title"` + Tag string `json:"tag"` + Article_id string `json:"article_id"` + Tid string `json:"tid"` + Uid string `json:"uid"` + A_timestamp string `json:"a_timestamp"` + Reward sdk.Coins `json:"reward"` // reward of the article +} + +func CreateArticleHandler(cliCtx context.CLIContext) http.HandlerFunc{ + return func(w http.ResponseWriter, r *http.Request) { + var req CreateArticleReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") + return + } + + baseReq := req.BaseReq.Sanitize() + if !baseReq.ValidateBasic(w) { + return + } + + addr, err := sdk.AccAddressFromBech32(req.Creator) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + // create the message + msg := types.NewMsgCreateArticle(addr, req.A_text, req.A_title, req.Tag, req.Article_id, req.Tid, req.Uid, req.A_timestamp, req.Reward) + err = msg.ValidateBasic() + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + utils.WriteGenerateStdTxResponse(w, cliCtx, baseReq, []sdk.Msg{msg}) + } +} + + + +type CreateCommentReq struct { + BaseReq rest.BaseReq `json:"base_req"` + Creator string `json:"creator"` // address of the article creator + Comment_id string `json:"comment_id"` // id of the comment + Article_id string `json:"article_id"` // id of the article + Tid string `json:"tid"` // id of the transaction + Uid string `json:"uid"` // id of the user + C_timestamp string `json:"c_timestamp"` // timestamp of the comment + C_text string `json:"c_text"` // context of the comment + Reward sdk.Coins `json:"reward"` +} + +func CreateCommentHandler(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req CreateCommentReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") + return + } + + baseReq := req.BaseReq.Sanitize() + if !baseReq.ValidateBasic(w) { + return + } + + addr, err := sdk.AccAddressFromBech32(req.Creator) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + // create the message + msg := types.NewMsgCreateComment(addr, req.Comment_id, req.Article_id, req.Tid, req.Uid, req.C_timestamp, req.C_text, req.Reward) + err = msg.ValidateBasic() + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + utils.WriteGenerateStdTxResponse(w, cliCtx, baseReq, []sdk.Msg{msg}) + } +} + + + +type CreateReturnVisitReq struct { + BaseReq rest.BaseReq `json:"base_req"` + Creator string `json:"creator"` // address of the article creator + Return_visit_id string `json:"return_visit_id"` + Article_id string `json:"article_id"` + Tid string `json:"tid"` + Uid string `json:"uid"` + Rv_timestamp string `json:"rv_timestamp"` + Rv_text string `json:"rv_text"` + Flag string `json:"flag"` + Reward sdk.Coins `json:"reward"` // reward of the article + +} + + +func CreateReturnVisitHandler(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req CreateReturnVisitReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") + return + } + + baseReq := req.BaseReq.Sanitize() + if !baseReq.ValidateBasic(w) { + return + } + + addr, err := sdk.AccAddressFromBech32(req.Creator) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + // create the message + msg := types.NewMsgCreateReturnVisit(addr, req.Return_visit_id, req.Article_id, req.Tid, req.Uid, req.Rv_timestamp, req.Rv_text, req.Flag, req.Reward) + err = msg.ValidateBasic() + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + utils.WriteGenerateStdTxResponse(w, cliCtx, baseReq, []sdk.Msg{msg}) + } +} + + +type CreateAVoteReq struct { + BaseReq rest.BaseReq `json:"base_req"` + Creator string `json:"creator"` // address of the article creator + Article_id string `json:"article_id"` // id of the article + VoteUP int `json:"voteUP"` + VoteDOWN int `json:"voteDOWN"` + Num int `json:"num"` +} + + +func CreateAVoteHandler(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req CreateAVoteReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") + return + } + + baseReq := req.BaseReq.Sanitize() + if !baseReq.ValidateBasic(w) { + return + } + + addr, err := sdk.AccAddressFromBech32(req.Creator) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + // create the message + msg := types.NewMsgCreateAVote(addr, req.Article_id, req.VoteUP, req.VoteDOWN, req.Num) + err = msg.ValidateBasic() + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + utils.WriteGenerateStdTxResponse(w, cliCtx, baseReq, []sdk.Msg{msg}) + } +} + + + +type CreateCVoteReq struct { + BaseReq rest.BaseReq `json:"base_req"` + Creator string `json:"creator"` // address of the comment creator + Comment_id string `json:"comment_id"` // id of the comment + VoteUP int `json:"voteUP"` + VoteDOWN int `json:"voteDOWN"` + Num int `json:"num"` +} + + +func CreateCVoteHandler(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req CreateCVoteReq + + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &req) { + rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") + return + } + + baseReq := req.BaseReq.Sanitize() + if !baseReq.ValidateBasic(w) { + return + } + + addr, err := sdk.AccAddressFromBech32(req.Creator) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + // create the message + msg := types.NewMsgCreateCVote(addr, req.Comment_id, req.VoteUP, req.VoteDOWN, req.Num) + err = msg.ValidateBasic() + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + utils.WriteGenerateStdTxResponse(w, cliCtx, baseReq, []sdk.Msg{msg}) + } +} + + + + + +/*func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { + // r.HandleFunc( + // TODO: Define the Rest route , + // Call the function which should be executed for this route), + // ).Methods("POST") +}*/ + +/* +// Action TX body +type Req struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + // TODO: Define more types if needed +} + +func RequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req Req + vars := mux.Vars(r) + + baseReq := req.BaseReq.Sanitize() + if !baseReq.ValidateBasic(w) { + return + } + + // TODO: Define the module tx logic for this action + + utils.WriteGenerateStdTxResponse(w, cliCtx, BaseReq, []sdk.Msg{msg}) + } +} +*/ \ No newline at end of file diff --git a/x/djzh/genesis.go b/x/djzh/genesis.go new file mode 100644 index 0000000..2ff1045 --- /dev/null +++ b/x/djzh/genesis.go @@ -0,0 +1,21 @@ +package djzh + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +/* abci "github.com/tendermint/tendermint/abci/types"*/ +) + +// InitGenesis initialize default parameters +// and the keeper's address to pubkey map +func InitGenesis(ctx sdk.Context, k Keeper, /* TODO: Define what keepers the module needs *//*,*/ data GenesisState) { + // TODO: Define logic for when you would like to initalize a new genesis +/* return []abci.ValidatorUpdate{}*/ +} + +// ExportGenesis writes the current store values +// to a genesis file, which can be imported again +// with InitGenesis +func ExportGenesis(ctx sdk.Context, k Keeper) (data GenesisState) { + // TODO: Define logic for exporting state + return NewGenesisState() +} diff --git a/x/djzh/handler.go b/x/djzh/handler.go new file mode 100644 index 0000000..d1c2113 --- /dev/null +++ b/x/djzh/handler.go @@ -0,0 +1,236 @@ +package djzh + +import ( + "fmt" + + "github.com/tendermint/tendermint/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/changtong1996/djzh/x/djzh/internal/types" +) + +// NewHandler creates an sdk.Handler for all the djzh type messages +func NewHandler(k Keeper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { + ctx = ctx.WithEventManager(sdk.NewEventManager()) + switch msg := msg.(type) { + // TODO: Define your msg cases + // + //Example: + // case Msg: + // return handleMsg(ctx, k, msg) + case MsgCreateArticle: + return handleMsgCreateArticle(ctx, k, msg) + + case MsgCreateComment: + return handleMsgCreateComment(ctx, k, msg) + + case MsgCreateReturnVisit: + return handleMsgCreateReturnVisit(ctx, k, msg) + + case MsgCreateAVote: + return handleMsgCreateAVote(ctx, k, msg) + + case MsgCreateCVote: + return handleMsgCreateCVote(ctx, k, msg) + + default: + errMsg := fmt.Sprintf("unrecognized %s message type: %T", ModuleName, msg) + return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) + } + } +} + +// handleMsgCreateArticle creates a new article and moves the reward into escrow +func handleMsgCreateArticle(ctx sdk.Context, k Keeper, msg MsgCreateArticle) (*sdk.Result, error) { + var article = types.Article{ + Creator: msg.Creator, + A_text: msg.A_text, + A_title: msg.A_title, + Tag: msg.Tag, + Article_id: msg.Article_id, + Tid: msg.Tid, + Uid: msg.Uid, + A_timestamp: msg.A_timestamp, + Reward: msg.Reward, + } + _, err := k.GetArticle(ctx, article.Article_id) + if err == nil { + return nil, sdkerrors.Wrap(err, "Article with that hash already exists") + } + moduleAcct := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName))) + sdkError := k.CoinKeeper.SendCoins(ctx, article.Creator, moduleAcct, article.Reward) + if sdkError != nil { + return nil, sdkError + } + k.SetArticle(ctx, article) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, types.EventTypeCreateArticle), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Creator.String()), + sdk.NewAttribute(types.AttributeText, msg.A_text), + sdk.NewAttribute(types.AttributeA_title, msg.A_title), + sdk.NewAttribute(types.AttributeTag, msg.Tag), + sdk.NewAttribute(types.AttributeArticle_id, msg.Article_id), + sdk.NewAttribute(types.AttributeTid, msg.Tid), + sdk.NewAttribute(types.AttributeUid, msg.Uid), + sdk.NewAttribute(types.AttributeA_timestamp, msg.A_timestamp), + sdk.NewAttribute(types.AttributeReward, msg.Reward.String()), + ), + ) + return &sdk.Result{Events: ctx.EventManager().Events()}, nil +} + + + +func handleMsgCreateComment(ctx sdk.Context, k Keeper, msg MsgCreateComment) (*sdk.Result, error) { + var comment = types.Comment{ + Creator: msg.Creator, + Comment_id: msg.Comment_id, + Article_id: msg.Article_id, + Tid: msg.Tid, + Uid: msg.Uid, + C_timestamp: msg.C_timestamp, + C_text: msg.C_text, + Reward: msg.Reward, + } + _, err := k.GetComment(ctx, comment.Comment_id) + if err == nil { + return nil, sdkerrors.Wrap(err, "Comment with that id already exists") + } + moduleAcct := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName))) + sdkError := k.CoinKeeper.SendCoins(ctx, comment.Creator, moduleAcct, comment.Reward) + if sdkError != nil { + return nil, sdkError + } + k.SetComment(ctx, comment) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, types.EventTypeCreateComment), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Creator.String()), + sdk.NewAttribute(types.AttributeReward, msg.Reward.String()), + ), + ) + return &sdk.Result{Events: ctx.EventManager().Events()}, nil +} + + + +func handleMsgCreateReturnVisit(ctx sdk.Context, k Keeper, msg MsgCreateReturnVisit) (*sdk.Result, error) { + var rv = types.ReturnVisit{ + Creator: msg.Creator, + Return_visit_id: msg.Return_visit_id, + Article_id: msg.Article_id, + Tid: msg.Tid, + Uid: msg.Uid, + Rv_timestamp: msg.Rv_timestamp, + Rv_text: msg.Rv_text, + Flag: msg.Flag, + Reward: msg.Reward, + } + _, err := k.GetReturnVisit(ctx, rv.Return_visit_id) + if err == nil { + return nil, sdkerrors.Wrap(err, "Rv with that id already exists") + } + moduleAcct := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName))) + sdkError := k.CoinKeeper.SendCoins(ctx, rv.Creator, moduleAcct, rv.Reward) + if sdkError != nil { + return nil, sdkError + } + k.SetReturnVisit(ctx, rv) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, types.EventTypeCreateReturnVisit), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Creator.String()), + sdk.NewAttribute(types.AttributeReward, msg.Reward.String()), + ), + ) + return &sdk.Result{Events: ctx.EventManager().Events()}, nil +} + + + + + + + +func handleMsgCreateAVote(ctx sdk.Context, k Keeper, msg MsgCreateAVote) (*sdk.Result, error) { + var aVote = types.ArticleVote{ + Creator: msg.Creator, + Article_id: msg.Article_id, + VoteUP: msg.VoteUP, + VoteDOWN: msg.VoteDOWN, + Num: msg.Num, + } + _, err := k.GetAVote(ctx, aVote.Article_id) + if err == nil { + return nil, sdkerrors.Wrap(err, "Rv with that id already exists") + } + + + k.SetAVote(ctx, aVote) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, types.EventTypeCreateAVote), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Creator.String()), + ), + ) + return &sdk.Result{Events: ctx.EventManager().Events()}, nil +} + + + + + +func handleMsgCreateCVote(ctx sdk.Context, k Keeper, msg MsgCreateCVote) (*sdk.Result, error) { + var cVote = types.CommentVote{ + Creator: msg.Creator, + Comment_id: msg.Comment_id, + VoteUP: msg.VoteUP, + VoteDOWN: msg.VoteDOWN, + Num: msg.Num, + } + _, err := k.GetCVote(ctx, cVote.Comment_id) + if err == nil { + return nil, sdkerrors.Wrap(err, "Rv with that id already exists") + } + + + k.SetCVote(ctx, cVote) + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeyAction, types.EventTypeCreateCVote), + sdk.NewAttribute(sdk.AttributeKeySender, msg.Creator.String()), + ), + ) + return &sdk.Result{Events: ctx.EventManager().Events()}, nil +} +/*// handde does x +func handleMsg(ctx sdk.Context, k Keeper, msg Msg) (*sdk.Result, error) { + err := k.(ctx, msg.ValidatorAddr) + if err != nil { + return nil, err + } + + // TODO: Define your msg events + ctx.EventManager().EmitEvent( + sdk.NewEvent( + sdk.EventTypeMessage, + sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory), + sdk.NewAttribute(sdk.AttributeKeySender, msg.ValidatorAddr.String()), + ), + ) + + return &sdk.Result{Events: ctx.EventManager().Events()}, nil +} +*/ \ No newline at end of file diff --git a/x/djzh/internal/keeper/keeper.go b/x/djzh/internal/keeper/keeper.go new file mode 100644 index 0000000..4bb697a --- /dev/null +++ b/x/djzh/internal/keeper/keeper.go @@ -0,0 +1,178 @@ +package keeper + +import ( + "fmt" + +/* "github.com/tendermint/tendermint/crypto"*/ + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/changtong1996/djzh/x/djzh/internal/types" +) + +// Keeper of the djzh store +type Keeper struct { + CoinKeeper bank.Keeper + storeKey sdk.StoreKey + cdc *codec.Codec +} + +// NewKeeper creates a djzh keeper +func NewKeeper(coinKeeper bank.Keeper, key sdk.StoreKey, cdc *codec.Codec) Keeper { + keeper := Keeper{ + CoinKeeper: coinKeeper, + storeKey: key, + cdc: cdc, + } + return keeper +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + + + +func (k Keeper) GetArticle(ctx sdk.Context, article_id string) (types.Article, error) { + store := ctx.KVStore(k.storeKey) + var article types.Article + byteKey := []byte(article_id) + err := k.cdc.UnmarshalBinaryLengthPrefixed(store.Get(byteKey), &article) + if err != nil { + return article, err + } + return article, nil +} + +func (k Keeper) SetArticle(ctx sdk.Context, article types.Article ) { + article_id := article.Article_id + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshalBinaryLengthPrefixed(article) + key := []byte(article_id) + store.Set(key, bz) +} + +func (k Keeper) DeleteArticle(ctx sdk.Context, article_id string) { + store := ctx.KVStore(k.storeKey) + store.Delete([]byte(article_id)) +} + + + + +func (k Keeper) GetComment(ctx sdk.Context, comment_id string) (types.Comment, error) { + store := ctx.KVStore(k.storeKey) + var comment types.Comment + byteKey := []byte(comment_id) + err := k.cdc.UnmarshalBinaryLengthPrefixed(store.Get(byteKey), &comment) + if err != nil { + return comment, err + } + return comment, nil +} + +func (k Keeper) SetComment(ctx sdk.Context, comment types.Comment ) { + comment_id := comment.Comment_id + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshalBinaryLengthPrefixed(comment) + key := []byte(comment_id) + store.Set(key, bz) +} + +func (k Keeper) DeleteComment(ctx sdk.Context, comment_id string) { + store := ctx.KVStore(k.storeKey) + store.Delete([]byte(comment_id)) +} + + + + + +// Get returns the pubkey from the adddress-pubkey relation +func (k Keeper) GetReturnVisit(ctx sdk.Context, return_visit_id string) (types.ReturnVisit, error) { + store := ctx.KVStore(k.storeKey) + var rv types.ReturnVisit + byteKey := []byte(return_visit_id) + err := k.cdc.UnmarshalBinaryLengthPrefixed(store.Get(byteKey), &rv) + if err != nil { + return rv, err + } + return rv, nil +} + +func (k Keeper) SetReturnVisit(ctx sdk.Context, rv types.ReturnVisit ) { + return_visit_id := rv.Return_visit_id + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshalBinaryLengthPrefixed(rv) + key := []byte(return_visit_id) + store.Set(key, bz) +} + +func (k Keeper) DeleteReturnVisit(ctx sdk.Context, return_visit_id string) { + store := ctx.KVStore(k.storeKey) + store.Delete([]byte(return_visit_id)) +} + + + + + + + +// Get returns the pubkey from the adddress-pubkey relation +func (k Keeper) GetAVote(ctx sdk.Context, article_id string) (types.ArticleVote, error) { + store := ctx.KVStore(k.storeKey) + var aVote types.ArticleVote + byteKey := []byte(article_id) + err := k.cdc.UnmarshalBinaryLengthPrefixed(store.Get(byteKey), &aVote) + if err != nil { + return aVote, err + } + return aVote, nil +} + +func (k Keeper) SetAVote(ctx sdk.Context, aVote types.ArticleVote ) { + article_id := aVote.Article_id + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshalBinaryLengthPrefixed(aVote) + key := []byte(article_id) + store.Set(key, bz) +} + +func (k Keeper) DeleteAVote(ctx sdk.Context, article_id string) { + store := ctx.KVStore(k.storeKey) + store.Delete([]byte(article_id)) +} + + + + + + +// Get returns the pubkey from the adddress-pubkey relation +func (k Keeper) GetCVote(ctx sdk.Context, comment_id string) (types.CommentVote, error) { + store := ctx.KVStore(k.storeKey) + var cVote types.CommentVote + byteKey := []byte(comment_id) + err := k.cdc.UnmarshalBinaryLengthPrefixed(store.Get(byteKey), &cVote) + if err != nil { + return cVote, err + } + return cVote, nil +} + +func (k Keeper) SetCVote(ctx sdk.Context, cVote types.CommentVote ) { + comment_id := cVote.Comment_id + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshalBinaryLengthPrefixed(cVote) + key := []byte(comment_id) + store.Set(key, bz) +} + +func (k Keeper) DeleteCVote(ctx sdk.Context, comment_id string) { + store := ctx.KVStore(k.storeKey) + store.Delete([]byte(comment_id)) +} \ No newline at end of file diff --git a/x/djzh/internal/keeper/params.go b/x/djzh/internal/keeper/params.go new file mode 100644 index 0000000..6848426 --- /dev/null +++ b/x/djzh/internal/keeper/params.go @@ -0,0 +1,22 @@ +package keeper +/* +// TODO: Define if your module needs Parameters, if not this can be deleted + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/changtong/djzh/x/djzh/internal/types" +) + +// GetParams returns the total set of djzh parameters. +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + k.paramspace.GetParamSet(ctx, ¶ms) + return params +} + +// SetParams sets the djzh parameters to the param space. +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramspace.SetParamSet(ctx, ¶ms) +} +*/ \ No newline at end of file diff --git a/x/djzh/internal/keeper/querier.go b/x/djzh/internal/keeper/querier.go new file mode 100644 index 0000000..badffc6 --- /dev/null +++ b/x/djzh/internal/keeper/querier.go @@ -0,0 +1,66 @@ +package keeper + +import ( +/* "fmt"*/ + + abci "github.com/tendermint/tendermint/abci/types" + +/* "github.com/cosmos/cosmos-sdk/client"*/ + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"/* + "github.com/changtong1996/djzh/x/djzh/internal/types"*/ +) + +const( + QueryVoteNum = "voteNum" + QueryGetArticle = "getarticle"//used in /cli/query.go QueryWithData +) + +// NewQuerier creates a new querier for djzh clients.不太懂这个path的作用是什么 +func NewQuerier(k Keeper) sdk.Querier { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) { + switch path[0] { + case QueryVoteNum: + return queryVoteNum(ctx, k, path[1:]) + case QueryGetArticle: + return queryGetArticle(ctx, k, path[1:]) + // TODO: Put the modules query routes + default: + return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown djzh query endpoint") + } + } +} + +func queryVoteNum(ctx sdk.Context, k Keeper, path []string) ([]byte, error) { + voteNum, err := k.GetAVote(ctx, path[0]) + + if err != nil { + return nil, err + } + + res, err := codec.MarshalJSONIndent(k.cdc, voteNum) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) + } + + return res, nil +} + +func queryGetArticle(ctx sdk.Context, k Keeper, path []string) ([]byte, error) { + article, err := k.GetArticle(ctx, path[0]) + + if err != nil { + return nil, err + } + + res, err := codec.MarshalJSONIndent(k.cdc, article) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) + } + + return res, nil +} + +// TODO: Add the modules query functions +// They will be similar to the above one: queryParams() diff --git a/x/djzh/internal/types/codec.go b/x/djzh/internal/types/codec.go new file mode 100644 index 0000000..4168c06 --- /dev/null +++ b/x/djzh/internal/types/codec.go @@ -0,0 +1,25 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" +) + +// RegisterCodec registers concrete types on codec +func RegisterCodec(cdc *codec.Codec) { + // TODO: Register the modules msgs + cdc.RegisterConcrete(MsgCreateArticle{}, "djzh/MsgCreateArticle", nil) + cdc.RegisterConcrete(MsgCreateComment{}, "djzh/MsgCreateComment", nil) + cdc.RegisterConcrete(MsgCreateReturnVisit{}, "djzh/MsgCreateReturnVisit", nil) + cdc.RegisterConcrete(MsgCreateAVote{}, "djzh/MsgCreateAVote", nil) + cdc.RegisterConcrete(MsgCreateCVote{}, "djzh/MsgCreateCVote", nil) +} + +// ModuleCdc defines the module codec +var ModuleCdc *codec.Codec + +func init() { + ModuleCdc = codec.New() + RegisterCodec(ModuleCdc) + codec.RegisterCrypto(ModuleCdc) + ModuleCdc.Seal() +} diff --git a/x/djzh/internal/types/errors.go b/x/djzh/internal/types/errors.go new file mode 100644 index 0000000..282f50f --- /dev/null +++ b/x/djzh/internal/types/errors.go @@ -0,0 +1,11 @@ +package types + +/*import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +)*/ + +// TODO: Fill out some custom errors for the module +// You can see how they are constructed below: +// var ( +// ErrInvalid = sdkerrors.Register(ModuleName, 1, "custom error message") +// ) diff --git a/x/djzh/internal/types/events.go b/x/djzh/internal/types/events.go new file mode 100644 index 0000000..4d3a139 --- /dev/null +++ b/x/djzh/internal/types/events.go @@ -0,0 +1,31 @@ +package types + +// djzh module event types +const ( + // TODO: Create your event types + // EventType = "action" + + // TODO: Create keys fo your events, the values will be derivided from the msg + // AttributeKeyAddress = "address" + + // TODO: Some events may not have values for that reason you want to emit that something happened. + // AttributeValueDoubleSign = "double_sign" + EventTypeCreateArticle = "CreateArticle" + EventTypeCreateComment = "CreateComment" + EventTypeCreateReturnVisit = "CreateReturnVisit" + EventTypeCreateAVote = "CreateAVote" + EventTypeCreateCVote = "CreateCVote" + + + + AttributeText = "a_text" + AttributeA_title = "a_title" + AttributeTag = "tag" + AttributeArticle_id = "article_id" + AttributeTid = "tid" + AttributeUid = "uid" + AttributeA_timestamp = "a_timestamp" + AttributeReward = "reward" + + AttributeValueCategory = ModuleName +) diff --git a/x/djzh/internal/types/expected_keepers.go b/x/djzh/internal/types/expected_keepers.go new file mode 100644 index 0000000..67a4bb5 --- /dev/null +++ b/x/djzh/internal/types/expected_keepers.go @@ -0,0 +1,24 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/params" +) + +// ParamSubspace defines the expected Subspace interfacace +type ParamSubspace interface { + WithKeyTable(table params.KeyTable) params.Subspace + Get(ctx sdk.Context, key []byte, ptr interface{}) + GetParamSet(ctx sdk.Context, ps params.ParamSet) + SetParamSet(ctx sdk.Context, ps params.ParamSet) +} + +/* +When a module wishes to interact with an otehr module it is good practice to define what it will use +as an interface so the module can not use things that are not permitted. +TODO: Create interfaces of what you expect the other keepers to have to be able to use this module. +type BankKeeper interface { + SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error +} +*/ diff --git a/x/djzh/internal/types/genesis.go b/x/djzh/internal/types/genesis.go new file mode 100644 index 0000000..54a06c5 --- /dev/null +++ b/x/djzh/internal/types/genesis.go @@ -0,0 +1,26 @@ +package types + +// GenesisState - all djzh state that must be provided at genesis +type GenesisState struct { + // TODO: Fill out what is needed by the module for genesis +} + +// NewGenesisState creates a new GenesisState object +func NewGenesisState( /* TODO: Fill out with what is needed for genesis state */) GenesisState { + return GenesisState{ + // TODO: Fill out according to your genesis state + } +} + +// DefaultGenesisState - default GenesisState used by Cosmos Hub +func DefaultGenesisState() GenesisState { + return GenesisState{ + // TODO: Fill out according to your genesis state, these values will be initialized but empty + } +} + +// ValidateGenesis validates the djzh genesis parameters +func ValidateGenesis(data GenesisState) error { + // TODO: Create a sanity check to make sure the state conforms to the modules needs + return nil +} diff --git a/x/djzh/internal/types/key.go b/x/djzh/internal/types/key.go new file mode 100644 index 0000000..69a71e7 --- /dev/null +++ b/x/djzh/internal/types/key.go @@ -0,0 +1,15 @@ +package types + +const ( + // ModuleName is the name of the module + ModuleName = "djzh" + + // StoreKey to be used when creating the KVStore + StoreKey = ModuleName + + // RouterKey to be used for routing msgs + RouterKey = ModuleName + + // QuerierRoute to be used for querierer msgs + QuerierRoute = ModuleName +) diff --git a/x/djzh/internal/types/msg.go b/x/djzh/internal/types/msg.go new file mode 100644 index 0000000..25c5967 --- /dev/null +++ b/x/djzh/internal/types/msg.go @@ -0,0 +1,322 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +type MsgCreateArticle struct { + Creator sdk.AccAddress `json:"creator"` // address of the article creator + A_text string `json:"a_text"` // + A_title string `json:"a_title"` + Tag string `json:"tag"` + Article_id string `json:"article_id"` + Tid string `json:"tid"` + Uid string `json:"uid"` + A_timestamp string `json:"a_timestamp"` + Reward sdk.Coins `json:"reward"` // reward of the article +} + +func NewMsgCreateArticle(creator sdk.AccAddress, a_text string, a_title string, tag string, article_id string, + tid string, uid string, a_timestamp string, reward sdk.Coins) MsgCreateArticle { + return MsgCreateArticle{ + Creator: creator, + A_text: a_text, + A_title: a_title, + Tag: tag, + Article_id: article_id, + Tid: tid, + Uid: uid, + A_timestamp: a_timestamp, + Reward: reward, + } +} + +const CreateArticleConst = "CreateArticle" + + +//nolint +func (msg MsgCreateArticle) Route() string { return RouterKey } +func (msg MsgCreateArticle) Type() string { return CreateArticleConst } + +func (msg MsgCreateArticle) GetSigners() []sdk.AccAddress{ + return []sdk.AccAddress{sdk.AccAddress(msg.Creator)} +} + +func (msg MsgCreateArticle) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +// ValidateBasic validity check for the AnteHandler +func (msg MsgCreateArticle) ValidateBasic() error { + if msg.Creator.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "creator can't be empty") + } + if msg.Article_id == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "articleid can't be empty") + } + return nil +} + + + + + + +type MsgCreateComment struct { + Creator sdk.AccAddress `json:"creator"` // address of the article creator + Comment_id string `json:"comment_id"` // id of the comment + Article_id string `json:"article_id"` // id of the article + Tid string `json:"tid"` // id of the transaction + Uid string `json:"uid"` // id of the user + C_timestamp string `json:"c_timestamp"` // timestamp of the comment + C_text string `json:"c_text"` // context of the comment + Reward sdk.Coins `json:"reward"` +} + +func NewMsgCreateComment(creator sdk.AccAddress, comment_id string, article_id string, tid string, uid string, + c_timestamp string, c_text string, reward sdk.Coins) MsgCreateComment { + return MsgCreateComment{ + Creator: creator, + Comment_id: comment_id, + Article_id: article_id, + Tid: tid, + Uid: uid, + C_timestamp: c_timestamp, + C_text: c_text, + Reward: reward, + } +} + +const CreateCommentConst = "CreateComment" + + +//nolint +func (msg MsgCreateComment) Route() string { return RouterKey } +func (msg MsgCreateComment) Type() string { return CreateCommentConst } +func (msg MsgCreateComment) GetSigners() []sdk.AccAddress{ + return []sdk.AccAddress{sdk.AccAddress(msg.Creator)} +} + +func (msg MsgCreateComment) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +// ValidateBasic validity check for the AnteHandler +func (msg MsgCreateComment) ValidateBasic() error { + if msg.Creator.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "creator can't be empty") + } + if msg.Comment_id == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "solutionScavengerHash can't be empty") + } + return nil +} + + + + + + + + + +type MsgCreateReturnVisit struct { + Creator sdk.AccAddress `json:"creator"` // address of the article creator + Return_visit_id string `json:"return_visit_id"` + Article_id string `json:"article_id"` + Tid string `json:"tid"` + Uid string `json:"uid"` + Rv_timestamp string `json:"rv_timestamp"` + Rv_text string `json:"rv_text"` + Flag string `json:"flag"` + Reward sdk.Coins `json:"reward"` // reward of the article + +} + +func NewMsgCreateReturnVisit(creator sdk.AccAddress, return_visit_id string, article_id string, tid string, uid string, + rv_timestamp string, rv_text string, flag string, reward sdk.Coins) MsgCreateReturnVisit { + return MsgCreateReturnVisit{ + Creator: creator, + Return_visit_id: return_visit_id, + Article_id: article_id, + Tid: tid, + Uid: uid, + Rv_timestamp: rv_timestamp, + Rv_text: rv_text, + Flag: flag, + Reward: reward, + } +} + +const CreateReturnVisitConst = "CreateReturnVisit" + + +//nolint +func (msg MsgCreateReturnVisit) Route() string { return RouterKey } +func (msg MsgCreateReturnVisit) Type() string { return CreateReturnVisitConst } +func (msg MsgCreateReturnVisit) GetSigners() []sdk.AccAddress{ + return []sdk.AccAddress{sdk.AccAddress(msg.Creator)} +} + +func (msg MsgCreateReturnVisit) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +// ValidateBasic validity check for the AnteHandler +func (msg MsgCreateReturnVisit) ValidateBasic() error { + if msg.Creator.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "creator can't be empty") + } + if msg.Return_visit_id == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "rv can't be empty") + } + return nil +} + + + + + + + + +type MsgCreateAVote struct { + Creator sdk.AccAddress `json:"creator"` // address of the article creator + Article_id string `json:"article_id"` // id of the article + VoteUP int `json:"voteUP"` + VoteDOWN int `json:"voteDOWN"` + Num int `json:"num"` +} + +func NewMsgCreateAVote(creator sdk.AccAddress, article_id string, voteUP int, voteDOWN int, num int) MsgCreateAVote { + return MsgCreateAVote{ + Creator: creator, + Article_id: article_id, + VoteUP: voteUP, + VoteDOWN: voteDOWN, + Num: num, + } +} + +const CreateAVoteConst = "CreateAVote" + + +//nolint +func (msg MsgCreateAVote) Route() string { return RouterKey } +func (msg MsgCreateAVote) Type() string { return CreateAVoteConst } +func (msg MsgCreateAVote) GetSigners() []sdk.AccAddress{ + return []sdk.AccAddress{sdk.AccAddress(msg.Creator)} +} + +func (msg MsgCreateAVote) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +// ValidateBasic validity check for the AnteHandler +func (msg MsgCreateAVote) ValidateBasic() error { + if msg.Creator.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "creator can't be empty") + } + if msg.Article_id == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "solutionScavengerHash can't be empty") + } + return nil +} + + + + + + + +type MsgCreateCVote struct { + Creator sdk.AccAddress `json:"creator"` // address of the article creator + Comment_id string `json:"comment_id"` // id of the article + VoteUP int `json:"voteUP"` + VoteDOWN int `json:"voteDOWN"` + Num int `json:"num"` + +} + +func NewMsgCreateCVote(creator sdk.AccAddress, comment_id string, voteUP int, voteDOWN int, num int) MsgCreateCVote { + return MsgCreateCVote{ + Creator: creator, + Comment_id: comment_id, + VoteUP: voteUP, + VoteDOWN: voteDOWN, + Num: num, + } +} + +const CreateCVoteConst = "CreateCVote" + + +//nolint +func (msg MsgCreateCVote) Route() string { return RouterKey } +func (msg MsgCreateCVote) Type() string { return CreateCVoteConst } +func (msg MsgCreateCVote) GetSigners() []sdk.AccAddress{ + return []sdk.AccAddress{sdk.AccAddress(msg.Creator)} +} + +func (msg MsgCreateCVote) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +// ValidateBasic validity check for the AnteHandler +func (msg MsgCreateCVote) ValidateBasic() error { + if msg.Creator.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "creator can't be empty") + } + if msg.Comment_id == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "comment_id can't be empty") + } + return nil +} + + +// TODO: Describe your actions, these will implment the interface of `sdk.Msg` +/* +verify interface at compile time +var _ sdk.Msg = &Msg{} + +Msg - struct for unjailing jailed validator +type Msg struct { + ValidatorAddr sdk.ValAddress `json:"address" yaml:"address"` // address of the validator operator +} + +NewMsg creates a new Msg instance +func NewMsg(validatorAddr sdk.ValAddress) Msg { + return Msg{ + ValidatorAddr: validatorAddr, + } +} + +const Const = "" + +// nolint +func (msg Msg) Route() string { return RouterKey } +func (msg Msg) Type() string { return Const } +func (msg Msg) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{sdk.AccAddress(msg.ValidatorAddr)} +} + +GetSignBytes gets the bytes for the message signer to sign on +func (msg Msg) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +ValidateBasic validity check for the AnteHandler +func (msg Msg) ValidateBasic() error { + if msg.ValidatorAddr.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing validator address" + } + return nil +} +*/ diff --git a/x/djzh/internal/types/params.go b/x/djzh/internal/types/params.go new file mode 100644 index 0000000..9faa524 --- /dev/null +++ b/x/djzh/internal/types/params.go @@ -0,0 +1,57 @@ +package types + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/x/params" +) + +// Default parameter namespace +const ( + DefaultParamspace = ModuleName + // TODO: Define your default parameters +) + +// Parameter store keys +var ( + // TODO: Define your keys for the parameter store + // KeyParamName = []byte("ParamName") +) + +// ParamKeyTable for djzh module +func ParamKeyTable() params.KeyTable { + return params.NewKeyTable().RegisterParamSet(&Params{}) +} + +// Params - used for initializing default parameter for djzh at genesis +type Params struct { + // TODO: Add your Paramaters to the Paramter struct + // KeyParamName string `json:"key_param_name"` +} + +// NewParams creates a new Params object +func NewParams(/* TODO: Pass in the paramters*/) Params { + return Params{ + // TODO: Create your Params Type + } +} + +// String implements the stringer interface for Params +func (p Params) String() string { + return fmt.Sprintf(` + // TODO: Return all the params as a string + `, ) +} + +// ParamSetPairs - Implements params.ParamSet +func (p *Params) ParamSetPairs() params.ParamSetPairs { + return params.ParamSetPairs{ + // TODO: Pair your key with the param + // params.NewParamSetPair(KeyParamName, &p.ParamName), + } +} + +// DefaultParams defines the parameters for this module +func DefaultParams() Params { + return NewParams( /* TODO: Pass in your default Params */ ) +} diff --git a/x/djzh/internal/types/querier.go b/x/djzh/internal/types/querier.go new file mode 100644 index 0000000..3135540 --- /dev/null +++ b/x/djzh/internal/types/querier.go @@ -0,0 +1,19 @@ +package types +/*import "strings"*/ + +// Query endpoints supported by the djzh querier +const ( + // TODO: Describe query parameters, update with your query + // Query = "" +) + + +// QueryResList Queries Result Payload for a query +/*type QueryVoteNum []string + +// implement fmt.Stringer +func (n QueryVoteNum) String() string { + return strings.Join(n[:], "\n") +} + +*/ diff --git a/x/djzh/internal/types/types.go b/x/djzh/internal/types/types.go new file mode 100644 index 0000000..811c7ec --- /dev/null +++ b/x/djzh/internal/types/types.go @@ -0,0 +1,117 @@ +package types + +import ( + "fmt" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + + +type Article struct { + Creator sdk.AccAddress `json:"creator"` + Article_id string `json:"article_id"` // id of the article + Uid string `json:"uid"` // id of the user + Tid string `json:"tid"` // id of the transaction + A_timestamp string `json:"a_timestamp"` // timestamp of the article + A_title string `json:"a_title"` // title of the article + A_text string `json:"a_text"` // text of the article + Tag string `json:"tag"` + Flag int `json:"flag"` + Reward sdk.Coins `json:"reward"` +} + +func (a Article) String() string { + return strings.TrimSpace(fmt.Sprintf(`Creator: %s + Article_id: %s + Uid: %s + Tid: %s + A_timestamp: %s + A_title: %s + A_text: %s + Tag: %s + Flag: %d + Reward:%s`, + a.Creator, + a.Article_id, + a.Uid, + a.Tid, + a.A_timestamp, + a.A_title, + a.A_text, + a.Tag, + a.Flag, + a.Reward, + )) +} + +type ArticleVote struct { + Creator sdk.AccAddress `json:"creator"` + Article_id string `json:"article_id"` // id of the article + VoteUP int `json:"voteUP"` + VoteDOWN int `json:"voteDOWN"` + Num int `json:"num"` +} + + +type Comment struct { + Creator sdk.AccAddress `json:"creator"` + Comment_id string `json:"comment_id"` // id of the comment + Article_id string `json:"article_id"` // id of the article + Tid string `json:"tid"` // id of the transaction + Uid string `json:"uid"` // id of the user + C_timestamp string `json:"c_timestamp"` // timestamp of the comment + C_text string `json:"c_text"` // context of the comment + Flag int `json:"flag"` + Reward sdk.Coins `json:"reward"` +} + + +type CommentVote struct { + Creator sdk.AccAddress `json:"creator"` + Comment_id string `json:"comment_id"` // id of the comment + VoteUP int `json:"voteUP"` + VoteDOWN int `json:"voteDOWN"` + Num int `json:"num"` +} + + +type Domain struct { + Domainn string `json:"domain"` // + Ip string `json:"ip"` + Owner string `json:"owner"` + Suffix string `json:"suffix"` +} + + +type Equity struct { + Uid string `json:"uid"` + Balance string `json:"balance"` // 股权资产数 + Detail string `json:"detail"` +} + + +type EquityTransaction struct { + Et_id string `json:"et_id"` + Source_id string `json:"source_id"` + Destination_id string `json:"destination_id"` + Tid string `json:"tid"` + Balance string `json:"balance"` + Et_timestamp int `json:"et_timestamp"` + Detail string `json:"detail"` +} + +type ReturnVisit struct{ + Creator sdk.AccAddress `json:"creator"` + Return_visit_id string `json:"return_visit_id"` + Article_id string `json:"article_id"` + Tid string `json:"tid"` + Uid string `json:"uid"` + Rv_timestamp string `json:"rv_timestamp"` + Rv_text string `json:"rv_text"` + Flag string `json:"flag"` + Reward sdk.Coins `json:"reward"` +} + + + diff --git a/x/djzh/module.go b/x/djzh/module.go new file mode 100644 index 0000000..cc7ca1e --- /dev/null +++ b/x/djzh/module.go @@ -0,0 +1,146 @@ +package djzh + +import ( + "encoding/json" + + "github.com/gorilla/mux" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/bank" +/* "github.com/changtong1996/djzh/x/djzh/internal/types"*/ + "github.com/changtong1996/djzh/x/djzh/client/cli" + "github.com/changtong1996/djzh/x/djzh/client/rest" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// AppModuleBasic defines the basic application module used by the djzh module. +type AppModuleBasic struct{} + +var _ module.AppModuleBasic = AppModuleBasic{} + +// Name returns the djzh module's name. +func (AppModuleBasic) Name() string { + return ModuleName +} + +// RegisterCodec registers the djzh module's types for the given codec. +func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { + RegisterCodec(cdc) +} + +// DefaultGenesis returns default genesis state as raw bytes for the djzh +// module. +func (AppModuleBasic) DefaultGenesis() json.RawMessage { + return ModuleCdc.MustMarshalJSON(DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the djzh module. +func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { + var data GenesisState + err := ModuleCdc.UnmarshalJSON(bz, &data) + if err != nil { + return err + } + return ValidateGenesis(data) +} + +// RegisterRESTRoutes registers the REST routes for the djzh module. +func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) { + rest.RegisterRoutes(ctx, rtr) +} + +// GetTxCmd returns the root tx command for the djzh module. +func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command { + return cli.GetTxCmd(cdc) +} + +// GetQueryCmd returns no root query command for the djzh module. +func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command { + return cli.GetQueryCmd(StoreKey, cdc) +} + +//____________________________________________________________________________ + +// AppModule implements an application module for the djzh module. +type AppModule struct { + AppModuleBasic + + keeper Keeper + // TODO: Add keepers that your application depends on + coinKeeper bank.Keeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(k Keeper, bankKeeper bank.Keeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + keeper: k, + // TODO: Add keepers that your application depends on + coinKeeper: bankKeeper, + } +} + +// Name returns the djzh module's name. +func (AppModule) Name() string { + return ModuleName +} + +// RegisterInvariants registers the djzh module invariants. +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// Route returns the message routing key for the djzh module. +func (AppModule) Route() string { + return RouterKey +} + +// NewHandler returns an sdk.Handler for the djzh module. +func (am AppModule) NewHandler() sdk.Handler { + return NewHandler(am.keeper) +} + +// QuerierRoute returns the djzh module's querier route name. +func (AppModule) QuerierRoute() string { + return QuerierRoute +} + +// NewQuerierHandler returns the djzh module sdk.Querier. +func (am AppModule) NewQuerierHandler() sdk.Querier { + return NewQuerier(am.keeper) +} + +// InitGenesis performs genesis initialization for the djzh 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) + InitGenesis(ctx, am.keeper, genesisState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the djzh +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return ModuleCdc.MustMarshalJSON(gs) +} + +// BeginBlock returns the begin blocker for the djzh module. +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { + BeginBlocker(ctx, req, am.keeper) +} + +// EndBlock returns the end blocker for the djzh module. It returns no validator +// updates. +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} diff --git a/x/djzh/spec/README.md b/x/djzh/spec/README.md new file mode 100644 index 0000000..002a879 --- /dev/null +++ b/x/djzh/spec/README.md @@ -0,0 +1,17 @@ +# djzh module specification + +## Abstract + + + +## Contents + +// TODO: Create the below files if they are needed. +1. **[Concepts](01_concepts.md)** +2. **[State](02_state.md)** +3. **[Messages](03_messages.md)** +4. **[Begin-Block](04_begin_block.md)** +5. **[End-Block](06_end_bloc.md)** +6. **[05_hooks](06_hooks.md)** +7. **[Events](07_events.md)** +8. **[Parameters](08_params.md)**