From 179caa5768b1e35c25015f5b529c3729a104578a Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Sat, 7 Apr 2018 01:12:00 -0400 Subject: [PATCH] refactor gaia with stake --- Makefile | 4 +- cmd/gaia/app/account.go | 32 ++ cmd/gaia/app/app.go | 158 ++++++++++ cmd/gaia/app/app_test.go | 432 ++++++++++++++++++++++++++ cmd/gaia/cmd/gaiacli/main.go | 79 +++++ cmd/{ => gaia/cmd}/gaiad/main.go | 25 +- examples/basecoin/app/app.go | 7 +- examples/basecoin/app/app_test.go | 8 +- examples/basecoin/cmd/basecli/main.go | 21 +- x/stake/handler.go | 37 --- 10 files changed, 744 insertions(+), 59 deletions(-) create mode 100644 cmd/gaia/app/account.go create mode 100644 cmd/gaia/app/app.go create mode 100644 cmd/gaia/app/app_test.go create mode 100644 cmd/gaia/cmd/gaiacli/main.go rename cmd/{ => gaia/cmd}/gaiad/main.go (60%) diff --git a/Makefile b/Makefile index b5177621aa..4d21c61c52 100644 --- a/Makefile +++ b/Makefile @@ -36,8 +36,8 @@ else endif install: - go install $(BUILD_FLAGS) ./cmd/gaiad - go install $(BUILD_FLAGS) ./cmd/gaiacli + go install $(BUILD_FLAGS) ./cmd/gaia/cmd/gaiad + go install $(BUILD_FLAGS) ./cmd/gaia/cmd/gaiacli install_examples: go install $(BUILD_FLAGS) ./examples/basecoin/cmd/basecoind diff --git a/cmd/gaia/app/account.go b/cmd/gaia/app/account.go new file mode 100644 index 0000000000..3d5673b87b --- /dev/null +++ b/cmd/gaia/app/account.go @@ -0,0 +1,32 @@ +package app + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" +) + +// State to Unmarshal +type GenesisState struct { + Accounts []GenesisAccount `json:"accounts"` +} + +// GenesisAccount doesn't need pubkey or sequence +type GenesisAccount struct { + Address sdk.Address `json:"address"` + Coins sdk.Coins `json:"coins"` +} + +func NewGenesisAccount(acc auth.BaseAccount) GenesisAccount { + return GenesisAccount{ + Address: acc.Address, + Coins: acc.Coins, + } +} + +// convert GenesisAccount to GaiaAccount +func (ga *GenesisAccount) ToAccount() (acc auth.BaseAccount) { + return auth.BaseAccount{ + Address: ga.Address, + Coins: ga.Coins.Sort(), + } +} diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go new file mode 100644 index 0000000000..64b1619f86 --- /dev/null +++ b/cmd/gaia/app/app.go @@ -0,0 +1,158 @@ +package app + +import ( + "encoding/json" + + abci "github.com/tendermint/abci/types" + oldwire "github.com/tendermint/go-wire" + cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" + + bam "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/ibc" + "github.com/cosmos/cosmos-sdk/x/stake" +) + +const ( + appName = "GaiaApp" +) + +// Extended ABCI application +type GaiaApp struct { + *bam.BaseApp + cdc *wire.Codec + + // keys to access the substores + capKeyMainStore *sdk.KVStoreKey + capKeyAccountStore *sdk.KVStoreKey + capKeyIBCStore *sdk.KVStoreKey + capKeyStakeStore *sdk.KVStoreKey + + // Manage getting and setting accounts + accountMapper sdk.AccountMapper +} + +func NewGaiaApp(logger log.Logger, dbs map[string]dbm.DB) *GaiaApp { + // create your application object + var app = &GaiaApp{ + BaseApp: bam.NewBaseApp(appName, logger, dbs["main"]), + cdc: MakeCodec(), + capKeyMainStore: sdk.NewKVStoreKey("main"), + capKeyAccountStore: sdk.NewKVStoreKey("acc"), + capKeyIBCStore: sdk.NewKVStoreKey("ibc"), + capKeyStakeStore: sdk.NewKVStoreKey("stake"), + } + + // define the accountMapper + app.accountMapper = auth.NewAccountMapperSealed( + app.capKeyMainStore, // target store + &auth.BaseAccount{}, // prototype + ) + + // add handlers + coinKeeper := bank.NewCoinKeeper(app.accountMapper) + ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) + stakeKeeper := stake.NewKeeper(app.cdc, app.capKeyStakeStore, coinKeeper) + app.Router(). + AddRoute("bank", bank.NewHandler(coinKeeper)). + AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). + AddRoute("stake", stake.NewHandler(stakeKeeper)) + + // initialize BaseApp + app.SetTxDecoder(app.txDecoder) + app.SetInitChainer(app.initChainer) + app.SetEndBlocker(stake.NewEndBlocker(stakeKeeper)) + app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"]) + app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"]) + app.MountStoreWithDB(app.capKeyIBCStore, sdk.StoreTypeIAVL, dbs["ibc"]) + app.MountStoreWithDB(app.capKeyStakeStore, sdk.StoreTypeIAVL, dbs["stake"]) + + // NOTE: Broken until #532 lands + //app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore, app.capKeyStakingStore) + app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper)) + err := app.LoadLatestVersion(app.capKeyMainStore) + if err != nil { + cmn.Exit(err.Error()) + } + + return app +} + +// custom tx codec +// TODO: use new go-wire +func MakeCodec() *wire.Codec { + const ( + msgTypeSend = 0x1 + msgTypeIssue = 0x2 + msgTypeIBCTransferMsg = 0x3 + msgTypeIBCReceiveMsg = 0x4 + msgDeclareCandidacy = 0x5 + msgEditCandidacy = 0x6 + msgDelegate = 0x7 + msgUnbond = 0x8 + ) + var _ = oldwire.RegisterInterface( + struct{ sdk.Msg }{}, + oldwire.ConcreteType{bank.SendMsg{}, msgTypeSend}, + oldwire.ConcreteType{bank.IssueMsg{}, msgTypeIssue}, + oldwire.ConcreteType{ibc.IBCTransferMsg{}, msgTypeIBCTransferMsg}, + oldwire.ConcreteType{ibc.IBCReceiveMsg{}, msgTypeIBCReceiveMsg}, + oldwire.ConcreteType{stake.MsgDeclareCandidacy{}, msgDeclareCandidacy}, + oldwire.ConcreteType{stake.MsgEditCandidacy{}, msgEditCandidacy}, + oldwire.ConcreteType{stake.MsgDelegate{}, msgDelegate}, + oldwire.ConcreteType{stake.MsgUnbond{}, msgUnbond}, + ) + + const accTypeApp = 0x1 + var _ = oldwire.RegisterInterface( + struct{ sdk.Account }{}, + oldwire.ConcreteType{&auth.BaseAccount{}, accTypeApp}, + ) + cdc := wire.NewCodec() + + // cdc.RegisterInterface((*sdk.Msg)(nil), nil) + // bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] + // crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] + // ibc.RegisterWire(cdc) // Register ibc.[IBCTransferMsg, IBCReceiveMsg] + return cdc +} + +// custom logic for transaction decoding +func (app *GaiaApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { + var tx = sdk.StdTx{} + + if len(txBytes) == 0 { + return nil, sdk.ErrTxDecode("txBytes are empty") + } + + // StdTx.Msg is an interface. The concrete types + // are registered by MakeTxCodec in bank.RegisterWire. + err := app.cdc.UnmarshalBinary(txBytes, &tx) + if err != nil { + return nil, sdk.ErrTxDecode("").TraceCause(err, "") + } + return tx, nil +} + +// custom logic for gaia initialization +func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { + stateJSON := req.AppStateBytes + + genesisState := new(GenesisState) + err := json.Unmarshal(stateJSON, genesisState) + if err != nil { + panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 + // return sdk.ErrGenesisParse("").TraceCause(err, "") + } + + for _, gacc := range genesisState.Accounts { + acc := gacc.ToAccount() + app.accountMapper.SetAccount(ctx, &acc) + } + return abci.ResponseInitChain{} +} diff --git a/cmd/gaia/app/app_test.go b/cmd/gaia/app/app_test.go new file mode 100644 index 0000000000..a440e7e38e --- /dev/null +++ b/cmd/gaia/app/app_test.go @@ -0,0 +1,432 @@ +package app + +import ( + "encoding/json" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/ibc" + + abci "github.com/tendermint/abci/types" + crypto "github.com/tendermint/go-crypto" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" +) + +// Construct some global addrs and txs for tests. +var ( + chainID = "" // TODO + + accName = "foobart" + + priv1 = crypto.GenPrivKeyEd25519() + addr1 = priv1.PubKey().Address() + priv2 = crypto.GenPrivKeyEd25519() + addr2 = priv2.PubKey().Address() + addr3 = crypto.GenPrivKeyEd25519().PubKey().Address() + priv4 = crypto.GenPrivKeyEd25519() + addr4 = priv4.PubKey().Address() + coins = sdk.Coins{{"foocoin", 10}} + halfCoins = sdk.Coins{{"foocoin", 5}} + manyCoins = sdk.Coins{{"foocoin", 1}, {"barcoin", 1}} + fee = sdk.StdFee{ + sdk.Coins{{"foocoin", 0}}, + 0, + } + + sendMsg1 = bank.SendMsg{ + Inputs: []bank.Input{bank.NewInput(addr1, coins)}, + Outputs: []bank.Output{bank.NewOutput(addr2, coins)}, + } + + sendMsg2 = bank.SendMsg{ + Inputs: []bank.Input{bank.NewInput(addr1, coins)}, + Outputs: []bank.Output{ + bank.NewOutput(addr2, halfCoins), + bank.NewOutput(addr3, halfCoins), + }, + } + + sendMsg3 = bank.SendMsg{ + Inputs: []bank.Input{ + bank.NewInput(addr1, coins), + bank.NewInput(addr4, coins), + }, + Outputs: []bank.Output{ + bank.NewOutput(addr2, coins), + bank.NewOutput(addr3, coins), + }, + } + + sendMsg4 = bank.SendMsg{ + Inputs: []bank.Input{ + bank.NewInput(addr2, coins), + }, + Outputs: []bank.Output{ + bank.NewOutput(addr1, coins), + }, + } + + sendMsg5 = bank.SendMsg{ + Inputs: []bank.Input{ + bank.NewInput(addr1, manyCoins), + }, + Outputs: []bank.Output{ + bank.NewOutput(addr2, manyCoins), + }, + } +) + +func loggerAndDBs() (log.Logger, map[string]dbm.DB) { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") + dbs := map[string]dbm.DB{ + "main": dbm.NewMemDB(), + "acc": dbm.NewMemDB(), + "ibc": dbm.NewMemDB(), + "staking": dbm.NewMemDB(), + } + return logger, dbs +} + +func newGaiaApp() *GaiaApp { + logger, dbs := loggerAndDBs() + return NewGaiaApp(logger, dbs) +} + +func setGenesisAccounts(gapp *GaiaApp, accs ...auth.BaseAccount) error { + genaccs := make([]GenesisAccount, len(accs)) + for i, acc := range accs { + genaccs[i] = NewGenesisAccount(acc) + } + + genesisState := GenesisState{ + Accounts: genaccs, + } + + stateBytes, err := json.MarshalIndent(genesisState, "", "\t") + if err != nil { + return err + } + + // Initialize the chain + vals := []abci.Validator{} + gapp.InitChain(abci.RequestInitChain{vals, stateBytes}) + gapp.Commit() + + return nil +} + +//_______________________________________________________________________ + +func TestMsgs(t *testing.T) { + gapp := newGaiaApp() + + msgs := []struct { + msg sdk.Msg + }{ + {sendMsg1}, + } + + for i, m := range msgs { + // Run a CheckDeliver + SignCheckDeliver(t, gapp, m.msg, []int64{int64(i)}, false, priv1) + } +} + +func TestSortGenesis(t *testing.T) { + logger, dbs := loggerAndDBs() + gapp := NewGaiaApp(logger, dbs) + + // Note the order: the coins are unsorted! + coinDenom1, coinDenom2 := "foocoin", "barcoin" + + str := `{ + "accounts": [{ + "address": "%s", + "coins": [ + { + "denom": "%s", + "amount": 10 + }, + { + "denom": "%s", + "amount": 20 + } + ] + }] + }` + genState := fmt.Sprintf(str, addr1.String(), coinDenom1, coinDenom2) + + // Initialize the chain + vals := []abci.Validator{} + gapp.InitChain(abci.RequestInitChain{vals, []byte(genState)}) + gapp.Commit() + + // Unsorted coins means invalid + err := sendMsg5.ValidateBasic() + require.Equal(t, sdk.CodeInvalidCoins, err.ABCICode(), err.ABCILog()) + + // Sort coins, should be valid + sendMsg5.Inputs[0].Coins.Sort() + sendMsg5.Outputs[0].Coins.Sort() + err = sendMsg5.ValidateBasic() + require.Nil(t, err) + + // Ensure we can send + SignCheckDeliver(t, gapp, sendMsg5, []int64{0}, true, priv1) +} + +func TestGenesis(t *testing.T) { + logger, dbs := loggerAndDBs() + gapp := NewGaiaApp(logger, dbs) + + // Construct some genesis bytes to reflect GaiaAccount + pk := crypto.GenPrivKeyEd25519().PubKey() + addr := pk.Address() + coins, err := sdk.ParseCoins("77foocoin,99barcoin") + require.Nil(t, err) + baseAcc := auth.BaseAccount{ + Address: addr, + Coins: coins, + } + + err = setGenesisAccounts(gapp, baseAcc) + assert.Nil(t, err) + + // A checkTx context + ctx := gapp.BaseApp.NewContext(true, abci.Header{}) + res1 := gapp.accountMapper.GetAccount(ctx, baseAcc.Address) + assert.Equal(t, baseAcc, res1) + + // reload app and ensure the account is still there + gapp = NewGaiaApp(logger, dbs) + ctx = gapp.BaseApp.NewContext(true, abci.Header{}) + res1 = gapp.accountMapper.GetAccount(ctx, baseAcc.Address) + assert.Equal(t, baseAcc, res1) +} + +func TestSendMsgWithAccounts(t *testing.T) { + gapp := newGaiaApp() + + // Construct some genesis bytes to reflect GaiaAccount + // Give 77 foocoin to the first key + coins, err := sdk.ParseCoins("77foocoin") + require.Nil(t, err) + baseAcc := auth.BaseAccount{ + Address: addr1, + Coins: coins, + } + + // Construct genesis state + err = setGenesisAccounts(gapp, baseAcc) + assert.Nil(t, err) + // A checkTx context (true) + ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) + res1 := gapp.accountMapper.GetAccount(ctxCheck, addr1) + assert.Equal(t, baseAcc, res1.(*auth.BaseAccount)) + + // Run a CheckDeliver + SignCheckDeliver(t, gapp, sendMsg1, []int64{0}, true, priv1) + + // Check balances + CheckBalance(t, gapp, addr1, "67foocoin") + CheckBalance(t, gapp, addr2, "10foocoin") + + // Delivering again should cause replay error + SignCheckDeliver(t, gapp, sendMsg1, []int64{0}, false, priv1) + + // bumping the txnonce number without resigning should be an auth error + tx := genTx(sendMsg1, []int64{0}, priv1) + tx.Signatures[0].Sequence = 1 + res := gapp.Deliver(tx) + + assert.Equal(t, sdk.CodeUnauthorized, res.Code, res.Log) + + // resigning the tx with the bumped sequence should work + SignCheckDeliver(t, gapp, sendMsg1, []int64{1}, true, priv1) +} + +func TestSendMsgMultipleOut(t *testing.T) { + gapp := newGaiaApp() + + genCoins, err := sdk.ParseCoins("42foocoin") + require.Nil(t, err) + + acc1 := auth.BaseAccount{ + Address: addr1, + Coins: genCoins, + } + + acc2 := auth.BaseAccount{ + Address: addr2, + Coins: genCoins, + } + + err = setGenesisAccounts(gapp, acc1, acc2) + assert.Nil(t, err) + + // Simulate a Block + SignCheckDeliver(t, gapp, sendMsg2, []int64{0}, true, priv1) + + // Check balances + CheckBalance(t, gapp, addr1, "32foocoin") + CheckBalance(t, gapp, addr2, "47foocoin") + CheckBalance(t, gapp, addr3, "5foocoin") +} + +func TestSengMsgMultipleInOut(t *testing.T) { + gapp := newGaiaApp() + + genCoins, err := sdk.ParseCoins("42foocoin") + require.Nil(t, err) + + acc1 := auth.BaseAccount{ + Address: addr1, + Coins: genCoins, + } + + acc2 := auth.BaseAccount{ + Address: addr2, + Coins: genCoins, + } + + acc4 := auth.BaseAccount{ + Address: addr4, + Coins: genCoins, + } + + err = setGenesisAccounts(gapp, acc1, acc2, acc4) + assert.Nil(t, err) + + // CheckDeliver + SignCheckDeliver(t, gapp, sendMsg3, []int64{0, 0}, true, priv1, priv4) + + // Check balances + CheckBalance(t, gapp, addr1, "32foocoin") + CheckBalance(t, gapp, addr4, "32foocoin") + CheckBalance(t, gapp, addr2, "52foocoin") + CheckBalance(t, gapp, addr3, "10foocoin") +} + +func TestSendMsgDependent(t *testing.T) { + gapp := newGaiaApp() + + genCoins, err := sdk.ParseCoins("42foocoin") + require.Nil(t, err) + + acc1 := auth.BaseAccount{ + Address: addr1, + Coins: genCoins, + } + + err = setGenesisAccounts(gapp, acc1) + assert.Nil(t, err) + + // CheckDeliver + SignCheckDeliver(t, gapp, sendMsg1, []int64{0}, true, priv1) + + // Check balances + CheckBalance(t, gapp, addr1, "32foocoin") + CheckBalance(t, gapp, addr2, "10foocoin") + + // Simulate a Block + SignCheckDeliver(t, gapp, sendMsg4, []int64{0}, true, priv2) + + // Check balances + CheckBalance(t, gapp, addr1, "42foocoin") +} + +func TestIBCMsgs(t *testing.T) { + gapp := newGaiaApp() + + sourceChain := "source-chain" + destChain := "dest-chain" + + baseAcc := auth.BaseAccount{ + Address: addr1, + Coins: coins, + } + + err := setGenesisAccounts(gapp, baseAcc) + assert.Nil(t, err) + // A checkTx context (true) + ctxCheck := gapp.BaseApp.NewContext(true, abci.Header{}) + res1 := gapp.accountMapper.GetAccount(ctxCheck, addr1) + assert.Equal(t, baseAcc, res1) + + packet := ibc.IBCPacket{ + SrcAddr: addr1, + DestAddr: addr1, + Coins: coins, + SrcChain: sourceChain, + DestChain: destChain, + } + + transferMsg := ibc.IBCTransferMsg{ + IBCPacket: packet, + } + + receiveMsg := ibc.IBCReceiveMsg{ + IBCPacket: packet, + Relayer: addr1, + Sequence: 0, + } + + SignCheckDeliver(t, gapp, transferMsg, []int64{0}, true, priv1) + CheckBalance(t, gapp, addr1, "") + SignCheckDeliver(t, gapp, transferMsg, []int64{1}, false, priv1) + SignCheckDeliver(t, gapp, receiveMsg, []int64{2}, true, priv1) + CheckBalance(t, gapp, addr1, "10foocoin") + SignCheckDeliver(t, gapp, receiveMsg, []int64{3}, false, priv1) +} + +func genTx(msg sdk.Msg, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.StdTx { + sigs := make([]sdk.StdSignature, len(priv)) + for i, p := range priv { + sigs[i] = sdk.StdSignature{ + PubKey: p.PubKey(), + Signature: p.Sign(sdk.StdSignBytes(chainID, seq, fee, msg)), + Sequence: seq[i], + } + } + + return sdk.NewStdTx(msg, fee, sigs) + +} + +func SignCheckDeliver(t *testing.T, gapp *GaiaApp, msg sdk.Msg, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) { + + // Sign the tx + tx := genTx(msg, seq, priv...) + // Run a Check + res := gapp.Check(tx) + if expPass { + require.Equal(t, sdk.CodeOK, res.Code, res.Log) + } else { + require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + } + + // Simulate a Block + gapp.BeginBlock(abci.RequestBeginBlock{}) + res = gapp.Deliver(tx) + if expPass { + require.Equal(t, sdk.CodeOK, res.Code, res.Log) + } else { + require.NotEqual(t, sdk.CodeOK, res.Code, res.Log) + } + gapp.EndBlock(abci.RequestEndBlock{}) + //gapp.Commit() +} + +func CheckBalance(t *testing.T, gapp *GaiaApp, addr sdk.Address, balExpected string) { + ctxDeliver := gapp.BaseApp.NewContext(false, abci.Header{}) + res2 := gapp.accountMapper.GetAccount(ctxDeliver, addr) + assert.Equal(t, balExpected, fmt.Sprintf("%v", res2.GetCoins())) +} diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go new file mode 100644 index 0000000000..c5c3190c30 --- /dev/null +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -0,0 +1,79 @@ +package main + +import ( + "os" + + "github.com/spf13/cobra" + + "github.com/tendermint/tmlibs/cli" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/client/lcd" + "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/client/tx" + + "github.com/cosmos/cosmos-sdk/version" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" + bankcmd "github.com/cosmos/cosmos-sdk/x/bank/commands" + ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/commands" + stakecmd "github.com/cosmos/cosmos-sdk/x/stake/commands" + + "github.com/cosmos/cosmos-sdk/cmd/gaia/app" +) + +// rootCmd is the entry point for this binary +var ( + rootCmd = &cobra.Command{ + Use: "gaiacli", + Short: "Gaia light-client", + } +) + +func main() { + cobra.EnableCommandSorting = false + cdc := app.MakeCodec() + + // TODO: setup keybase, viper object, etc. to be passed into + // the below functions and eliminate global vars, like we do + // with the cdc + + // add standard rpc, and tx commands + rpc.AddCommands(rootCmd) + rootCmd.AddCommand(client.LineBreak) + tx.AddCommands(rootCmd, cdc) + rootCmd.AddCommand(client.LineBreak) + + // add query/post commands (custom to binary) + rootCmd.AddCommand( + client.GetCommands( + authcmd.GetAccountCmd("main", cdc, authcmd.GetAccountDecoder(cdc)), + stakecmd.GetCmdQueryCandidates("stake", cdc), + stakecmd.GetCmdQueryCandidate("stake", cdc), + stakecmd.GetCmdQueryDelegatorBond("stake", cdc), + stakecmd.GetCmdQueryDelegatorBonds("stake", cdc), + )...) + rootCmd.AddCommand( + client.PostCommands( + bankcmd.SendTxCmd(cdc), + ibccmd.IBCTransferCmd(cdc), + ibccmd.IBCRelayCmd(cdc), + stakecmd.GetCmdDeclareCandidacy(cdc), + stakecmd.GetCmdEditCandidacy(cdc), + stakecmd.GetCmdDelegate(cdc), + stakecmd.GetCmdUnbond(cdc), + )...) + + // add proxy, version and key info + rootCmd.AddCommand( + client.LineBreak, + lcd.ServeCommand(cdc), + keys.Commands(), + client.LineBreak, + version.VersionCmd, + ) + + // prepare and add flags + executor := cli.PrepareMainCmd(rootCmd, "GA", os.ExpandEnv("$HOME/.gaiacli")) + executor.Execute() +} diff --git a/cmd/gaiad/main.go b/cmd/gaia/cmd/gaiad/main.go similarity index 60% rename from cmd/gaiad/main.go rename to cmd/gaia/cmd/gaiad/main.go index 9ebf196db8..f966c446ab 100644 --- a/cmd/gaiad/main.go +++ b/cmd/gaia/cmd/gaiad/main.go @@ -11,7 +11,7 @@ import ( dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" - "github.com/cosmos/cosmos-sdk/examples/basecoin/app" + "github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/server" ) @@ -25,7 +25,6 @@ var ( } ) -// TODO: distinguish from basecoin func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { dataDir := filepath.Join(rootDir, "data") db, err := dbm.NewGoLevelDB("gaia", dataDir) @@ -33,6 +32,25 @@ func generateApp(rootDir string, logger log.Logger) (abci.Application, error) { return nil, err } bapp := app.NewBasecoinApp(logger, db) + //dbAcc, err := dbm.NewGoLevelDB("gaia-acc", dataDir) + //if err != nil { + //return nil, err + //} + //dbIBC, err := dbm.NewGoLevelDB("gaia-ibc", dataDir) + //if err != nil { + //return nil, err + //} + //dbStaking, err := dbm.NewGoLevelDB("gaia-staking", dataDir) + //if err != nil { + //return nil, err + //} + //dbs := map[string]dbm.DB{ + //"main": dbMain, + //"acc": dbAcc, + //"ibc": dbIBC, + //"staking": dbStaking, + //} + //bapp := app.NewGaiaApp(logger, dbs) return bapp, nil } @@ -40,6 +58,7 @@ func main() { server.AddCommands(rootCmd, server.DefaultGenAppState, generateApp, context) // prepare and add flags - executor := cli.PrepareBaseCmd(rootCmd, "GA", os.ExpandEnv("$HOME/.gaiad")) + rootDir := os.ExpandEnv("$HOME/.gaiad") + executor := cli.PrepareBaseCmd(rootCmd, "GA", rootDir) executor.Execute() } diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 9ef48bfb5a..bb3ef05ac5 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -15,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/simplestake" - "github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" ) @@ -33,7 +32,7 @@ type BasecoinApp struct { capKeyMainStore *sdk.KVStoreKey capKeyAccountStore *sdk.KVStoreKey capKeyIBCStore *sdk.KVStoreKey - capKeyStakeStore *sdk.KVStoreKey + capKeyStakingStore *sdk.KVStoreKey // Manage getting and setting accounts accountMapper sdk.AccountMapper @@ -54,7 +53,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyAccountStore: sdk.NewKVStoreKey("acc"), capKeyIBCStore: sdk.NewKVStoreKey("ibc"), - capKeyStakeStore: sdk.NewKVStoreKey("stake"), + capKeyStakingStore: sdk.NewKVStoreKey("stake"), } // Define the accountMapper. @@ -71,7 +70,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). - AddRoute("stake", stake.NewHandler(stakeKeeper)) + AddRoute("simplestake", simplestake.NewHandler(stakeKeeper)) // Define the feeHandler. app.feeHandler = auth.BurnFeeHandler diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 1f635f53fe..36461a8e35 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -143,7 +143,7 @@ func TestSortGenesis(t *testing.T) { // Note the order: the coins are unsorted! coinDenom1, coinDenom2 := "foocoin", "barcoin" - str := `{ + genState := fmt.Sprintf(`{ "accounts": [{ "address": "%s", "coins": [ @@ -157,8 +157,7 @@ func TestSortGenesis(t *testing.T) { } ] }] - }` - genState := fmt.Sprintf(str, addr1.String(), coinDenom1, coinDenom2) + }`, addr1.String(), coinDenom1, coinDenom2) // Initialize the chain vals := []abci.Validator{} @@ -345,9 +344,10 @@ func TestQuizMsg(t *testing.T) { // Construct genesis state // Construct some genesis bytes to reflect basecoin/types/AppAccount + coins := sdk.Coins{} baseAcc := auth.BaseAccount{ Address: addr1, - Coins: nil, + Coins: coins, } acc1 := &types.AppAccount{baseAcc, "foobart"} diff --git a/examples/basecoin/cmd/basecli/main.go b/examples/basecoin/cmd/basecli/main.go index bab24f91bf..6271adcecd 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/examples/basecoin/cmd/basecli/main.go @@ -17,7 +17,7 @@ import ( authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/commands" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/commands" - stakecmd "github.com/cosmos/cosmos-sdk/x/stake/commands" + simplestakingcmd "github.com/cosmos/cosmos-sdk/x/simplestake/commands" "github.com/cosmos/cosmos-sdk/examples/basecoin/app" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" @@ -52,20 +52,23 @@ func main() { rootCmd.AddCommand( client.GetCommands( authcmd.GetAccountCmd("main", cdc, types.GetAccountDecoder(cdc)), - stakecmd.GetCmdQueryCandidates("stake", cdc), - stakecmd.GetCmdQueryCandidate("stake", cdc), - stakecmd.GetCmdQueryDelegatorBond("stake", cdc), - stakecmd.GetCmdQueryDelegatorBonds("stake", cdc), )...) rootCmd.AddCommand( client.PostCommands( bankcmd.SendTxCmd(cdc), + )...) + rootCmd.AddCommand( + client.PostCommands( ibccmd.IBCTransferCmd(cdc), + )...) + rootCmd.AddCommand( + client.PostCommands( ibccmd.IBCRelayCmd(cdc), - stakecmd.GetCmdDeclareCandidacy(cdc), - stakecmd.GetCmdEditCandidacy(cdc), - stakecmd.GetCmdDelegate(cdc), - stakecmd.GetCmdUnbond(cdc), + simplestakingcmd.BondTxCmd(cdc), + )...) + rootCmd.AddCommand( + client.PostCommands( + simplestakingcmd.UnbondTxCmd(cdc), )...) // add proxy, version and key info diff --git a/x/stake/handler.go b/x/stake/handler.go index e1f624f103..af1ad291d5 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -252,40 +252,3 @@ func handleMsgUnbond(ctx sdk.Context, msg MsgUnbond, k Keeper) sdk.Result { k.setPool(ctx, p) return sdk.Result{} } - -// TODO use or remove -//// Perform all the actions required to bond tokens to a delegator bond from their account -//func BondCoins(ctx sdk.Context, k Keeper, bond DelegatorBond, -//candidate Candidate, amount sdk.Coin) (DelegatorBond, Candidate, Pool, sdk.Error) { - -//pool := k.GetPool(ctx) -//_, err := k.coinKeeper.SubtractCoins(ctx, bond.DelegatorAddr, sdk.Coins{amount}) -//if err != nil { -//return bond, candidate, pool, err -//} -//pool, candidate, newShares := pool.candidateAddTokens(candidate, amount.Amount) -//bond.Shares = bond.Shares.Add(newShares) -//return bond, candidate, pool, nil -//} -//// Perform all the actions required to bond tokens to a delegator bond from their account -//func UnbondCoins(ctx sdk.Context, k Keeper, bond DelegatorBond, -//candidate Candidate, shares sdk.Rat) (DelegatorBond, Candidate, Pool, sdk.Error) { - -//pool := k.GetPool(ctx) - -//// subtract bond tokens from delegator bond -//if bond.Shares.LT(shares) { -//errMsg := fmt.Sprintf("cannot unbond %v shares, only have %v shares available", shares, bond.Shares) -//return bond, candidate, pool, sdk.ErrInsufficientFunds(errMsg) -//} -//bond.Shares = bond.Shares.Sub(shares) - -//pool, candidate, returnAmount := p.candidateRemoveShares(candidate, shares) -//returnCoins := sdk.Coins{{k.GetParams(ctx).BondDenom, returnAmount}} - -//_, err := k.coinKeeper.AddCoins(ctx, candidate.Address, returnCoins) -//if err != nil { -//return err -//} -//return bond, candidate, pool, nil -//}