diff --git a/Makefile b/Makefile index d2ae8dcddd..4a554e0f89 100644 --- a/Makefile +++ b/Makefile @@ -6,20 +6,20 @@ TUTORIALS=$(shell find docs/guide -name "*md" -type f) all: get_vendor_deps install test build: - go build ./cmd/... + @go build ./cmd/... install: - go install ./cmd/... - go install ./docs/guide/counter/cmd/... + @go install ./cmd/... + @go install ./docs/guide/counter/cmd/... dist: - @bash scripts/dist.sh - @bash scripts/publish.sh + @bash publish/dist.sh + @bash publish/publish.sh test: test_unit test_cli test_tutorial test_unit: - go test `glide novendor` + @go test `glide novendor` #go run tests/tendermint/*.go test_cli: tests/cli/shunit2 @@ -30,26 +30,26 @@ test_cli: tests/cli/shunit2 # @./tests/cli/ibc.sh test_tutorial: docs/guide/shunit2 - shelldown ${TUTORIALS} - for script in docs/guide/*.sh ; do \ + @shelldown ${TUTORIALS} + @for script in docs/guide/*.sh ; do \ bash $$script ; \ done tests/cli/shunit2: - wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ + @wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ -q -O tests/cli/shunit2 docs/guide/shunit2: - wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ + @wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ -q -O docs/guide/shunit2 get_vendor_deps: tools - glide install + @glide install build-docker: - docker run -it --rm -v "$(PWD):/go/src/github.com/tendermint/basecoin" -w \ + @docker run -it --rm -v "$(PWD):/go/src/github.com/tendermint/basecoin" -w \ "/go/src/github.com/tendermint/basecoin" -e "CGO_ENABLED=0" golang:alpine go build ./cmd/basecoin - docker build -t "tendermint/basecoin" . + @docker build -t "tendermint/basecoin" . tools: @go get $(GOTOOLS) diff --git a/app/app.go b/app/app.go index 16d8f6b654..4fb96772f6 100644 --- a/app/app.go +++ b/app/app.go @@ -17,11 +17,13 @@ import ( "github.com/tendermint/basecoin/version" ) +//nolint const ( ModuleNameBase = "base" ChainKey = "chain_id" ) +// Basecoin - The ABCI application type Basecoin struct { eyesCli *eyes.Client state *sm.State @@ -30,19 +32,20 @@ type Basecoin struct { logger log.Logger } -func NewBasecoin(h basecoin.Handler, eyesCli *eyes.Client, l log.Logger) *Basecoin { - state := sm.NewState(eyesCli, l.With("module", "state")) +// NewBasecoin - create a new instance of the basecoin application +func NewBasecoin(handler basecoin.Handler, eyesCli *eyes.Client, logger log.Logger) *Basecoin { + state := sm.NewState(eyesCli, logger.With("module", "state")) return &Basecoin{ - handler: h, + handler: handler, eyesCli: eyesCli, state: state, cacheState: nil, - logger: l, + logger: logger, } } -// placeholder to just handle sendtx +// DefaultHandler - placeholder to just handle sendtx func DefaultHandler() basecoin.Handler { // use the default stack h := coin.NewHandler() @@ -50,47 +53,45 @@ func DefaultHandler() basecoin.Handler { return stack.NewDefault().Use(d) } -// XXX For testing, not thread safe! +// GetState - XXX For testing, not thread safe! func (app *Basecoin) GetState() *sm.State { return app.state.CacheWrap() } -// ABCI::Info +// Info - ABCI func (app *Basecoin) Info() abci.ResponseInfo { resp, err := app.eyesCli.InfoSync() if err != nil { cmn.PanicCrisis(err) } return abci.ResponseInfo{ - Data: cmn.Fmt("Basecoin v%v", version.Version), + Data: fmt.Sprintf("Basecoin v%v", version.Version), LastBlockHeight: resp.LastBlockHeight, LastBlockAppHash: resp.LastBlockAppHash, } } -// ABCI::SetOption +// SetOption - ABCI func (app *Basecoin) SetOption(key string, value string) string { - module, prefix := splitKey(key) + + module, key := splitKey(key) + if module == ModuleNameBase { - return app.setBaseOption(prefix, value) + if key == ChainKey { + app.state.SetChainID(value) + return "Success" + } + return fmt.Sprintf("Error: unknown base option: %s", key) } - log, err := app.handler.SetOption(app.logger, app.state, module, prefix, value) + log, err := app.handler.SetOption(app.logger, app.state, module, key, value) if err == nil { return log } return "Error: " + err.Error() } -func (app *Basecoin) setBaseOption(key, value string) string { - if key == ChainKey { - app.state.SetChainID(value) - return "Success" - } - return fmt.Sprintf("Error: unknown base option: %s", key) -} - -// ABCI::DeliverTx +// DeliverTx - ABCI func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { tx, err := basecoin.LoadTx(txBytes) if err != nil { @@ -114,7 +115,7 @@ func (app *Basecoin) DeliverTx(txBytes []byte) abci.Result { return res.ToABCI() } -// ABCI::CheckTx +// CheckTx - ABCI func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { tx, err := basecoin.LoadTx(txBytes) if err != nil { @@ -136,7 +137,7 @@ func (app *Basecoin) CheckTx(txBytes []byte) abci.Result { return res.ToABCI() } -// ABCI::Query +// Query - ABCI func (app *Basecoin) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQuery) { if len(reqQuery.Data) == 0 { resQuery.Log = "Query cannot be zero length" @@ -153,7 +154,7 @@ func (app *Basecoin) Query(reqQuery abci.RequestQuery) (resQuery abci.ResponseQu return } -// ABCI::Commit +// Commit - ABCI func (app *Basecoin) Commit() (res abci.Result) { // Commit state @@ -168,21 +169,21 @@ func (app *Basecoin) Commit() (res abci.Result) { return res } -// ABCI::InitChain +// InitChain - ABCI func (app *Basecoin) InitChain(validators []*abci.Validator) { // for _, plugin := range app.plugins.GetList() { // plugin.InitChain(app.state, validators) // } } -// ABCI::BeginBlock +// BeginBlock - ABCI func (app *Basecoin) BeginBlock(hash []byte, header *abci.Header) { // for _, plugin := range app.plugins.GetList() { // plugin.BeginBlock(app.state, hash, header) // } } -// ABCI::EndBlock +// EndBlock - ABCI func (app *Basecoin) EndBlock(height uint64) (res abci.ResponseEndBlock) { // for _, plugin := range app.plugins.GetList() { // pluginRes := plugin.EndBlock(app.state, height) @@ -191,6 +192,8 @@ func (app *Basecoin) EndBlock(height uint64) (res abci.ResponseEndBlock) { return } +//TODO move split key to tmlibs? + // Splits the string at the first '/'. // if there are none, assign default module ("base"). func splitKey(key string) (string, string) { diff --git a/app/genesis.go b/app/genesis.go index 9d6050bcdb..1549ca7071 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -8,6 +8,7 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +// LoadGenesis - Load the genesis json file func (app *Basecoin) LoadGenesis(path string) error { genDoc, err := loadGenesis(path) if err != nil { @@ -35,12 +36,13 @@ type keyValue struct { Value string `json:"value"` } -// includes tendermint (in the json, we ignore here) +// FullGenesisDoc - includes tendermint (in the json, we ignore here) type FullGenesisDoc struct { ChainID string `json:"chain_id"` AppOptions *GenesisDoc `json:"app_options"` } +// GenesisDoc - All genesis values type GenesisDoc struct { Accounts []json.RawMessage `json:"accounts"` PluginOptions []json.RawMessage `json:"plugin_options"` @@ -73,20 +75,20 @@ func loadGenesis(filePath string) (*FullGenesisDoc, error) { return genDoc, nil } -func parseGenesisList(kvz_ []json.RawMessage) (kvz []keyValue, err error) { - if len(kvz_)%2 != 0 { +func parseGenesisList(kvzIn []json.RawMessage) (kvz []keyValue, err error) { + if len(kvzIn)%2 != 0 { return nil, errors.New("genesis cannot have an odd number of items. Format = [key1, value1, key2, value2, ...]") } - for i := 0; i < len(kvz_); i += 2 { + for i := 0; i < len(kvzIn); i += 2 { kv := keyValue{} - rawK := []byte(kvz_[i]) + rawK := []byte(kvzIn[i]) err := json.Unmarshal(rawK, &(kv.Key)) if err != nil { return nil, errors.Errorf("Non-string key: %s", string(rawK)) } // convert value to string if possible (otherwise raw json) - rawV := kvz_[i+1] + rawV := kvzIn[i+1] err = json.Unmarshal(rawV, &(kv.Value)) if err != nil { kv.Value = string(rawV) diff --git a/cmd/basecli/commands/auto.go b/cmd/basecli/commands/auto.go index 4eb7810a2b..040eb6ac38 100644 --- a/cmd/basecli/commands/auto.go +++ b/cmd/basecli/commands/auto.go @@ -7,12 +7,14 @@ import ( "github.com/spf13/viper" ) +// AutoCompleteCmd - command to generate bash autocompletions var AutoCompleteCmd = &cobra.Command{ Use: "complete", Short: "generate bash autocompletions", RunE: doAutoComplete, } +// nolint - flags const ( FlagOutput = "file" ) diff --git a/cmd/basecli/commands/query.go b/cmd/basecli/commands/query.go index 7f3b8db56b..e497c798dd 100644 --- a/cmd/basecli/commands/query.go +++ b/cmd/basecli/commands/query.go @@ -15,6 +15,7 @@ import ( "github.com/tendermint/basecoin/stack" ) +// AccountQueryCmd - command to query an account var AccountQueryCmd = &cobra.Command{ Use: "account [address]", Short: "Get details of an account, with proof", @@ -44,7 +45,8 @@ type BaseTxPresenter struct { proofs.RawPresenter // this handles MakeKey as hex bytes } -func (_ BaseTxPresenter) ParseData(raw []byte) (interface{}, error) { +// ParseData - parse BaseTxPresenter Data +func (b BaseTxPresenter) ParseData(raw []byte) (interface{}, error) { var tx basecoin.Tx err := wire.ReadBinaryBytes(raw, &tx) return tx, err diff --git a/docs/guide/counter/cmd/counter/main.go b/docs/guide/counter/cmd/counter/main.go index 85dafc555e..b7ba4c48ff 100644 --- a/docs/guide/counter/cmd/counter/main.go +++ b/docs/guide/counter/cmd/counter/main.go @@ -18,7 +18,7 @@ func main() { } // TODO: register the counter here - commands.Handler = counter.NewCounterHandler() + commands.Handler = counter.NewHandler() RootCmd.AddCommand( commands.InitCmd, diff --git a/docs/guide/counter/cmd/countercli/commands/counter.go b/docs/guide/counter/cmd/countercli/commands/counter.go index eab32acf1b..0bb39e6abb 100644 --- a/docs/guide/counter/cmd/countercli/commands/counter.go +++ b/docs/guide/counter/cmd/countercli/commands/counter.go @@ -24,6 +24,7 @@ You must pass --valid for it to count and the countfee will be added to the coun RunE: doCounterTx, } +// nolint - flags names const ( FlagCountFee = "countfee" FlagValid = "valid" @@ -74,6 +75,6 @@ func readCounterTxFlags() (tx basecoin.Tx, err error) { return tx, err } - tx = counter.NewCounterTx(viper.GetBool(FlagValid), feeCoins, viper.GetInt(FlagSequence)) + tx = counter.NewTx(viper.GetBool(FlagValid), feeCoins, viper.GetInt(FlagSequence)) return tx, nil } diff --git a/docs/guide/counter/cmd/countercli/commands/query.go b/docs/guide/counter/cmd/countercli/commands/query.go index 0d5febfe9e..be0c502652 100644 --- a/docs/guide/counter/cmd/countercli/commands/query.go +++ b/docs/guide/counter/cmd/countercli/commands/query.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/basecoin/docs/guide/counter/plugins/counter" ) -//CounterQueryCmd CLI command to query the counter state +//CounterQueryCmd - CLI command to query the counter state var CounterQueryCmd = &cobra.Command{ Use: "counter", Short: "Query counter state, with proof", @@ -18,7 +18,7 @@ var CounterQueryCmd = &cobra.Command{ func counterQueryCmd(cmd *cobra.Command, args []string) error { key := counter.StateKey() - var cp counter.CounterState + var cp counter.State proof, err := proofcmd.GetAndParseAppProof(key, &cp) if err != nil { return err diff --git a/docs/guide/counter/plugins/counter/counter.go b/docs/guide/counter/plugins/counter/counter.go index 96d409c754..0aafca19b0 100644 --- a/docs/guide/counter/plugins/counter/counter.go +++ b/docs/guide/counter/plugins/counter/counter.go @@ -13,7 +13,7 @@ import ( "github.com/tendermint/basecoin/types" ) -// CounterTx +// Tx //-------------------------------------------------------------------------------- // register the tx type with it's validation logic @@ -21,34 +21,37 @@ import ( // so it gets routed properly const ( NameCounter = "cntr" - ByteTx = 0x21 + ByteTx = 0x21 //TODO What does this byte represent should use typebytes probably TypeTx = NameCounter + "/count" ) func init() { - basecoin.TxMapper.RegisterImplementation(CounterTx{}, TypeTx, ByteTx) + basecoin.TxMapper.RegisterImplementation(Tx{}, TypeTx, ByteTx) } -type CounterTx struct { +// Tx - struct for all counter transactions +type Tx struct { Valid bool `json:"valid"` Fee types.Coins `json:"fee"` Sequence int `json:"sequence"` } -func NewCounterTx(valid bool, fee types.Coins, sequence int) basecoin.Tx { - return CounterTx{ +// NewTx - return a new counter transaction struct wrapped as a basecoin transaction +func NewTx(valid bool, fee types.Coins, sequence int) basecoin.Tx { + return Tx{ Valid: valid, Fee: fee, Sequence: sequence, }.Wrap() } -func (c CounterTx) Wrap() basecoin.Tx { - return basecoin.Tx{c} +// Wrap - Wrap a Tx as a Basecoin Tx, used to satisfy the XXX interface +func (c Tx) Wrap() basecoin.Tx { + return basecoin.Tx{TxInner: c} } // ValidateBasic just makes sure the Fee is a valid, non-negative value -func (c CounterTx) ValidateBasic() error { +func (c Tx) ValidateBasic() error { if !c.Fee.IsValid() { return coin.ErrInvalidCoins() } @@ -65,26 +68,29 @@ var ( errInvalidCounter = rawerr.New("Counter Tx marked invalid") ) -// This is a custom error class +// ErrInvalidCounter - custom error class func ErrInvalidCounter() error { return errors.WithCode(errInvalidCounter, abci.CodeType_BaseInvalidInput) } + +// IsInvalidCounterErr - custom error class check func IsInvalidCounterErr(err error) bool { return errors.IsSameError(errInvalidCounter, err) } -// This is just a helper function to return a generic "internal error" +// ErrDecoding - This is just a helper function to return a generic "internal error" func ErrDecoding() error { return errors.ErrInternal("Error decoding state") } -// CounterHandler +// Counter Handler //-------------------------------------------------------------------------------- -func NewCounterHandler() basecoin.Handler { +// NewHandler returns a new counter transaction processing handler +func NewHandler() basecoin.Handler { // use the default stack coin := coin.NewHandler() - counter := CounterHandler{} + counter := Handler{} dispatcher := stack.NewDispatcher( stack.WrapHandler(coin), counter, @@ -92,26 +98,29 @@ func NewCounterHandler() basecoin.Handler { return stack.NewDefault().Use(dispatcher) } -type CounterHandler struct { +// Handler the counter transaction processing handler +type Handler struct { stack.NopOption } -var _ stack.Dispatchable = CounterHandler{} +var _ stack.Dispatchable = Handler{} -func (_ CounterHandler) Name() string { +// Name - return counter namespace +func (h Handler) Name() string { return NameCounter } -func (_ CounterHandler) AssertDispatcher() {} +// AssertDispatcher - placeholder to satisfy XXX +func (h Handler) AssertDispatcher() {} // CheckTx checks if the tx is properly structured -func (h CounterHandler) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, _ basecoin.Checker) (res basecoin.Result, err error) { +func (h Handler) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, _ basecoin.Checker) (res basecoin.Result, err error) { _, err = checkTx(ctx, tx) return } // DeliverTx executes the tx if valid -func (h CounterHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, dispatch basecoin.Deliver) (res basecoin.Result, err error) { +func (h Handler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, dispatch basecoin.Deliver) (res basecoin.Result, err error) { ctr, err := checkTx(ctx, tx) if err != nil { return res, err @@ -130,7 +139,7 @@ func (h CounterHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx return res, errors.ErrMissingSignature() } in := []coin.TxInput{{Address: senders[0], Coins: ctr.Fee, Sequence: ctr.Sequence}} - out := []coin.TxOutput{{Address: CounterAcct(), Coins: ctr.Fee}} + out := []coin.TxOutput{{Address: StoreActor(), Coins: ctr.Fee}} send := coin.NewSendTx(in, out) // if the deduction fails (too high), abort the command _, err = dispatch.DeliverTx(ctx, store, send) @@ -144,15 +153,15 @@ func (h CounterHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx if err != nil { return res, err } - state.Counter += 1 + state.Counter++ state.TotalFees = state.TotalFees.Plus(ctr.Fee) - err = StoreState(store, state) + err = SaveState(store, state) return res, err } -func checkTx(ctx basecoin.Context, tx basecoin.Tx) (ctr CounterTx, err error) { - ctr, ok := tx.Unwrap().(CounterTx) +func checkTx(ctx basecoin.Context, tx basecoin.Tx) (ctr Tx, err error) { + ctr, ok := tx.Unwrap().(Tx) if !ok { return ctr, errors.ErrInvalidFormat(tx) } @@ -166,20 +175,24 @@ func checkTx(ctx basecoin.Context, tx basecoin.Tx) (ctr CounterTx, err error) { // CounterStore //-------------------------------------------------------------------------------- -func CounterAcct() basecoin.Actor { - return basecoin.Actor{App: NameCounter, Address: []byte{0x04, 0x20}} +// StoreActor - return the basecoin actor for the account +func StoreActor() basecoin.Actor { + return basecoin.Actor{App: NameCounter, Address: []byte{0x04, 0x20}} //XXX what do these bytes represent? - should use typebyte variables } -type CounterState struct { +// State - state of the counter applicaton +type State struct { Counter int `json:"counter"` TotalFees types.Coins `json:"total_fees"` } +// StateKey - store key for the counter state func StateKey() []byte { return []byte(NameCounter + "/state") } -func LoadState(store types.KVStore) (state CounterState, err error) { +// LoadState - retrieve the counter state from the store +func LoadState(store types.KVStore) (state State, err error) { bytes := store.Get(StateKey()) if len(bytes) > 0 { err = wire.ReadBinaryBytes(bytes, &state) @@ -190,7 +203,8 @@ func LoadState(store types.KVStore) (state CounterState, err error) { return state, nil } -func StoreState(store types.KVStore, state CounterState) error { +// SaveState - save the counter state to the provided store +func SaveState(store types.KVStore, state State) error { bytes := wire.BinaryBytes(state) store.Set(StateKey(), bytes) return nil diff --git a/docs/guide/counter/plugins/counter/counter_test.go b/docs/guide/counter/plugins/counter/counter_test.go index 8b41fcaec4..c29f9f4bdd 100644 --- a/docs/guide/counter/plugins/counter/counter_test.go +++ b/docs/guide/counter/plugins/counter/counter_test.go @@ -27,7 +27,7 @@ func TestCounterPlugin(t *testing.T) { l := log.NewTMLogger(os.Stdout).With("module", "app") // l = log.NewTracingLogger(l) bcApp := app.NewBasecoin( - NewCounterHandler(), + NewHandler(), eyesCli, l, ) @@ -39,7 +39,7 @@ func TestCounterPlugin(t *testing.T) { // Seed Basecoin with account test1Acc := test1PrivAcc.Account - test1Acc.Balance = types.Coins{{"", 1000}, {"gold", 1000}} + test1Acc.Balance = types.Coins{{"", 1000}, {"gold", 1000}} //nolint accOpt, err := json.Marshal(test1Acc) require.Nil(t, err) log := bcApp.SetOption("coin/account", string(accOpt)) @@ -47,7 +47,7 @@ func TestCounterPlugin(t *testing.T) { // Deliver a CounterTx DeliverCounterTx := func(valid bool, counterFee types.Coins, inputSequence int) abci.Result { - tx := NewCounterTx(valid, counterFee, inputSequence) + tx := NewTx(valid, counterFee, inputSequence) tx = txs.NewChain(chainID, tx) stx := txs.NewSig(tx) txs.Sign(stx, test1PrivAcc.PrivKey) @@ -64,10 +64,10 @@ func TestCounterPlugin(t *testing.T) { assert.True(res.IsErr(), res.String()) // Test the fee (increments sequence) - res = DeliverCounterTx(true, types.Coins{{"gold", 100}}, 1) + res = DeliverCounterTx(true, types.Coins{{"gold", 100}}, 1) //nolint assert.True(res.IsOK(), res.String()) // Test unsupported fee - res = DeliverCounterTx(true, types.Coins{{"silver", 100}}, 2) + res = DeliverCounterTx(true, types.Coins{{"silver", 100}}, 2) //nolint assert.True(res.IsErr(), res.String()) } diff --git a/modules/coin/store.go b/modules/coin/store.go index 9f9f671104..9490f302b3 100644 --- a/modules/coin/store.go +++ b/modules/coin/store.go @@ -25,6 +25,7 @@ func NewAccountant(prefix string) Accountant { func (a Accountant) GetAccount(store types.KVStore, addr basecoin.Actor) (Account, error) { acct, err := loadAccount(store, a.MakeKey(addr)) + // for empty accounts, don't return an error, but rather an empty account if IsNoAccountErr(err) { err = nil