Merge pull request #156 from tendermint/feature/replace-binaries-0.7-rigel

golint + general cleanup
This commit is contained in:
Ethan Frey 2017-07-06 12:08:34 +02:00 committed by GitHub
commit 205e38ee1a
30 changed files with 215 additions and 224 deletions

View File

@ -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)

View File

@ -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) {

View File

@ -8,6 +8,7 @@ import (
cmn "github.com/tendermint/tmlibs/common"
)
// LoadGenesis - Load the genesis file into memory
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)

View File

@ -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"
)

View File

@ -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 - unmarshal raw bytes to a basecoin tx
func (BaseTxPresenter) ParseData(raw []byte) (interface{}, error) {
var tx basecoin.Tx
err := wire.ReadBinaryBytes(raw, &tx)
return tx, err

View File

@ -18,7 +18,7 @@ import (
coincmd "github.com/tendermint/basecoin/cmd/basecoin/commands"
)
// BaseCli represents the base command when called without any subcommands
// BaseCli - main basecoin client command
var BaseCli = &cobra.Command{
Use: "basecli",
Short: "Light client for tendermint",
@ -34,16 +34,19 @@ func main() {
commands.AddBasicFlags(BaseCli)
// Prepare queries
pr := proofs.RootCmd
// These are default parsers, but optional in your app (you can remove key)
pr.AddCommand(proofs.TxCmd)
pr.AddCommand(proofs.KeyCmd)
pr.AddCommand(bcmd.AccountQueryCmd)
proofs.RootCmd.AddCommand(
// These are default parsers, but optional in your app (you can remove key)
proofs.TxCmd,
proofs.KeyCmd,
bcmd.AccountQueryCmd,
)
// you will always want this for the base send command
proofs.TxPresenters.Register("base", bcmd.BaseTxPresenter{})
tr := txs.RootCmd
tr.AddCommand(bcmd.SendTxCmd)
txs.RootCmd.AddCommand(
// This is the default transaction, optional in your app
bcmd.SendTxCmd,
)
// Set up the various commands to use
BaseCli.AddCommand(
@ -52,8 +55,8 @@ func main() {
keycmd.RootCmd,
seeds.RootCmd,
rpccmd.RootCmd,
pr,
tr,
proofs.RootCmd,
txs.RootCmd,
proxy.RootCmd,
coincmd.VersionCmd,
bcmd.AutoCompleteCmd,

View File

@ -7,29 +7,25 @@ import (
"path"
"github.com/spf13/cobra"
"github.com/spf13/viper"
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
)
//commands
var (
InitCmd = &cobra.Command{
Use: "init [address]",
Short: "Initialize a basecoin blockchain",
RunE: initCmd,
}
)
// InitCmd - node initialization command
var InitCmd = &cobra.Command{
Use: "init [address]",
Short: "Initialize a basecoin blockchain",
RunE: initCmd,
}
//flags
//nolint - flags
var (
chainIDFlag string
FlagChainID = "chain-id" //TODO group with other flags or remove? is this already a flag here?
)
func init() {
flags := []Flag2Register{
{&chainIDFlag, "chain-id", "test_chain_id", "Chain ID"},
}
RegisterFlags(InitCmd, flags)
InitCmd.Flags().String(FlagChainID, "test_chain_id", "Chain ID")
}
// returns 1 iff it set a file, otherwise 0 (so we can add them)
@ -62,7 +58,7 @@ func initCmd(cmd *cobra.Command, args []string) error {
privValFile := cfg.PrivValidatorFile()
keyFile := path.Join(cfg.RootDir, "key.json")
mod1, err := setupFile(genesisFile, GetGenesisJSON(chainIDFlag, userAddr), 0644)
mod1, err := setupFile(genesisFile, GetGenesisJSON(viper.GetString(FlagChainID), userAddr), 0644)
if err != nil {
return err
}
@ -85,6 +81,7 @@ func initCmd(cmd *cobra.Command, args []string) error {
return nil
}
// PrivValJSON - validator private key file contents in json
var PrivValJSON = `{
"address": "7A956FADD20D3A5B2375042B2959F8AB172A058F",
"last_height": 0,
@ -134,7 +131,7 @@ func GetGenesisJSON(chainID, addr string) string {
}`, chainID, addr)
}
// TODO: remove this once not needed for relay
// KeyJSON - TODO: remove this once not needed for relay
var KeyJSON = `{
"address": "1B1BE55F969F54064628A63B9559E7C21C925165",
"priv_key": {

View File

@ -19,12 +19,15 @@ import (
//---------------------------------------------
// simple implementation of a key
// Address - public address for a key
type Address [20]byte
// MarshalJSON - marshal the json bytes of the address
func (a Address) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%x"`, a[:])), nil
}
// UnmarshalJSON - unmarshal the json bytes of the address
func (a *Address) UnmarshalJSON(addrHex []byte) error {
addr, err := hex.DecodeString(strings.Trim(string(addrHex), `"`))
if err != nil {
@ -34,17 +37,19 @@ func (a *Address) UnmarshalJSON(addrHex []byte) error {
return nil
}
// Key - full private key
type Key struct {
Address Address `json:"address"`
PubKey crypto.PubKey `json:"pub_key"`
PrivKey crypto.PrivKey `json:"priv_key"`
}
// Implements Signer
// Sign - Implements Signer
func (k *Key) Sign(msg []byte) crypto.Signature {
return k.PrivKey.Sign(msg)
}
// LoadKey - load key from json file
func LoadKey(keyFile string) (*Key, error) {
filePath := keyFile
@ -61,7 +66,7 @@ func LoadKey(keyFile string) (*Key, error) {
key := new(Key)
err = json.Unmarshal(keyJSONBytes, key)
if err != nil {
return nil, fmt.Errorf("Error reading key from %v: %v\n", filePath, err) //never stack trace
return nil, fmt.Errorf("Error reading key from %v: %v", filePath, err) //never stack trace
}
return key, nil

View File

@ -14,12 +14,12 @@ type plugin struct {
var plugins = []plugin{}
// RegisterStartPlugin is used to enable a plugin
// RegisterStartPlugin - used to enable a plugin
func RegisterStartPlugin(name string, newPlugin func() types.Plugin) {
plugins = append(plugins, plugin{name: name, newPlugin: newPlugin})
}
//Returns a version command based on version input
// QuickVersionCmd - returns a version command based on version input
func QuickVersionCmd(version string) *cobra.Command {
return &cobra.Command{
Use: "version",

View File

@ -6,6 +6,7 @@ import (
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
)
// UnsafeResetAllCmd - extension of the tendermint command, resets initialization
var UnsafeResetAllCmd = &cobra.Command{
Use: "unsafe_reset_all",
Short: "Reset all blockchain data",

View File

@ -11,6 +11,7 @@ import (
"github.com/tendermint/tmlibs/log"
)
//nolint
const (
defaultLogLevel = "error"
FlagLogLevel = "log_level"
@ -20,6 +21,7 @@ var (
logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "main")
)
// RootCmd - main node command
var RootCmd = &cobra.Command{
Use: "basecoin",
Short: "A cryptocurrency framework in Golang based on Tendermint-Core",

View File

@ -24,13 +24,14 @@ import (
"github.com/tendermint/basecoin/app"
)
// StartCmd - command to start running the basecoin node!
var StartCmd = &cobra.Command{
Use: "start",
Short: "Start basecoin",
RunE: startCmd,
}
// TODO: move to config file
// nolint TODO: move to config file
const EyesCacheSize = 10000
//nolint
@ -41,7 +42,7 @@ const (
)
var (
// use a global to store the handler, so we can set it in main.
// Handler - use a global to store the handler, so we can set it in main.
// TODO: figure out a cleaner way to register plugins
Handler basecoin.Handler
)
@ -95,11 +96,10 @@ func startCmd(cmd *cobra.Command, args []string) error {
logger.Info("Starting Basecoin without Tendermint", "chain_id", chainID)
// run just the abci app/server
return startBasecoinABCI(basecoinApp)
} else {
logger.Info("Starting Basecoin with Tendermint", "chain_id", chainID)
// start the app with tendermint in-process
return startTendermint(rootDir, basecoinApp)
}
logger.Info("Starting Basecoin with Tendermint", "chain_id", chainID)
// start the app with tendermint in-process
return startTendermint(rootDir, basecoinApp)
}
func startBasecoinABCI(basecoinApp *app.Basecoin) error {

View File

@ -5,8 +5,6 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
abci "github.com/tendermint/abci/types"
wire "github.com/tendermint/go-wire"
@ -17,68 +15,6 @@ import (
tmtypes "github.com/tendermint/tendermint/types"
)
//Quickly registering flags can be quickly achieved through using the utility functions
//RegisterFlags, and RegisterPersistentFlags. Ex:
// flags := []Flag2Register{
// {&myStringFlag, "mystringflag", "foobar", "description of what this flag does"},
// {&myBoolFlag, "myboolflag", false, "description of what this flag does"},
// {&myInt64Flag, "myintflag", 333, "description of what this flag does"},
// }
// RegisterFlags(MyCobraCmd, flags)
type Flag2Register struct {
Pointer interface{}
Use string
Value interface{}
Desc string
}
//register flag utils
func RegisterFlags(c *cobra.Command, flags []Flag2Register) {
registerFlags(c, flags, false)
}
func RegisterPersistentFlags(c *cobra.Command, flags []Flag2Register) {
registerFlags(c, flags, true)
}
func registerFlags(c *cobra.Command, flags []Flag2Register, persistent bool) {
var flagset *pflag.FlagSet
if persistent {
flagset = c.PersistentFlags()
} else {
flagset = c.Flags()
}
for _, f := range flags {
ok := false
switch f.Value.(type) {
case string:
if _, ok = f.Pointer.(*string); ok {
flagset.StringVar(f.Pointer.(*string), f.Use, f.Value.(string), f.Desc)
}
case int:
if _, ok = f.Pointer.(*int); ok {
flagset.IntVar(f.Pointer.(*int), f.Use, f.Value.(int), f.Desc)
}
case uint64:
if _, ok = f.Pointer.(*uint64); ok {
flagset.Uint64Var(f.Pointer.(*uint64), f.Use, f.Value.(uint64), f.Desc)
}
case bool:
if _, ok = f.Pointer.(*bool); ok {
flagset.BoolVar(f.Pointer.(*bool), f.Use, f.Value.(bool), f.Desc)
}
}
if !ok {
panic("improper use of RegisterFlags")
}
}
}
// Returns true for non-empty hex-string prefixed with "0x"
func isHex(s string) bool {
if len(s) > 2 && s[:2] == "0x" {
@ -91,6 +27,7 @@ func isHex(s string) bool {
return false
}
// StripHex remove the first two hex bytes
func StripHex(s string) string {
if isHex(s) {
return s[2:]
@ -98,6 +35,7 @@ func StripHex(s string) string {
return s
}
// Query - send an abci query
func Query(tmAddr string, key []byte) (*abci.ResultQuery, error) {
httpClient := client.NewHTTP(tmAddr, "/websocket")
return queryWithClient(httpClient, key)

View File

@ -8,6 +8,7 @@ import (
"github.com/tendermint/basecoin/version"
)
// VersionCmd - command to show the application version
var VersionCmd = &cobra.Command{
Use: "version",
Short: "Show version info",

View File

@ -16,13 +16,11 @@ func main() {
rt.AddCommand(
commands.InitCmd,
commands.StartCmd,
// commands.RelayCmd,
//commands.RelayCmd,
commands.UnsafeResetAllCmd,
commands.VersionCmd,
)
cmd := cli.PrepareMainCmd(rt, "BC", os.ExpandEnv("$HOME/.basecoin"))
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
cmd.Execute()
}

View File

@ -18,7 +18,7 @@ func main() {
}
// TODO: register the counter here
commands.Handler = counter.NewCounterHandler()
commands.Handler = counter.NewHandler()
RootCmd.AddCommand(
commands.InitCmd,

View File

@ -21,9 +21,10 @@ var CounterTxCmd = &cobra.Command{
Long: `Add a vote to the counter.
You must pass --valid for it to count and the countfee will be added to the counter.`,
RunE: doCounterTx,
RunE: counterTx,
}
// nolint - flags names
const (
FlagCountFee = "countfee"
FlagValid = "valid"
@ -37,9 +38,9 @@ func init() {
fs.Int(FlagSequence, -1, "Sequence number for this transaction")
}
// TODO: doCounterTx is very similar to the sendtx one,
// TODO: counterTx is very similar to the sendtx one,
// maybe we can pull out some common patterns?
func doCounterTx(cmd *cobra.Command, args []string) error {
func counterTx(cmd *cobra.Command, args []string) error {
// load data from json or flags
var tx basecoin.Tx
found, err := txcmd.LoadJSON(&tx)
@ -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
}

View File

@ -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

View File

@ -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 (Handler) Name() string {
return NameCounter
}
func (_ CounterHandler) AssertDispatcher() {}
// AssertDispatcher - placeholder to satisfy XXX
func (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

View File

@ -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,
)
@ -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)

View File

@ -1,11 +1,7 @@
//nolint
package errors
/**
* Copyright (C) 2017 Ethan Frey
**/
import (
rawerr "errors"
"fmt"
"github.com/pkg/errors"
@ -14,17 +10,17 @@ import (
)
var (
errDecoding = rawerr.New("Error decoding input")
errUnauthorized = rawerr.New("Unauthorized")
errInvalidSignature = rawerr.New("Invalid Signature")
errTooLarge = rawerr.New("Input size too large")
errMissingSignature = rawerr.New("Signature missing")
errTooManySignatures = rawerr.New("Too many signatures")
errNoChain = rawerr.New("No chain id provided")
errWrongChain = rawerr.New("Wrong chain for tx")
errUnknownTxType = rawerr.New("Tx type unknown")
errInvalidFormat = rawerr.New("Invalid format")
errUnknownModule = rawerr.New("Unknown module")
errDecoding = fmt.Errorf("Error decoding input")
errUnauthorized = fmt.Errorf("Unauthorized")
errInvalidSignature = fmt.Errorf("Invalid Signature")
errTooLarge = fmt.Errorf("Input size too large")
errMissingSignature = fmt.Errorf("Signature missing")
errTooManySignatures = fmt.Errorf("Too many signatures")
errNoChain = fmt.Errorf("No chain id provided")
errWrongChain = fmt.Errorf("Wrong chain for tx")
errUnknownTxType = fmt.Errorf("Tx type unknown")
errInvalidFormat = fmt.Errorf("Invalid format")
errUnknownModule = fmt.Errorf("Unknown module")
)
func ErrUnknownTxType(tx basecoin.Tx) TMError {

View File

@ -1,9 +1,5 @@
package errors
/**
* Copyright (C) 2017 Ethan Frey
**/
import (
"fmt"
@ -23,6 +19,7 @@ type causer interface {
Cause() error
}
// TMError is the tendermint abci return type with stack trace
type TMError interface {
stackTracer
ErrorCode() abci.CodeType

View File

@ -1,3 +1,4 @@
//nolint
package coin
import (

View File

@ -13,6 +13,7 @@ import (
/**** code to parse accounts from genesis docs ***/
// GenesisAccount - genesis account parameters
type GenesisAccount struct {
Address data.Bytes `json:"address"`
// this from types.Account (don't know how to embed this properly)
@ -21,6 +22,7 @@ type GenesisAccount struct {
Balance types.Coins `json:"coins"`
}
// ToAccount - GenesisAccount struct to a basecoin Account
func (g GenesisAccount) ToAccount() Account {
return Account{
Sequence: g.Sequence,
@ -28,6 +30,7 @@ func (g GenesisAccount) ToAccount() Account {
}
}
// GetAddr - Get the address of the genesis account
func (g GenesisAccount) GetAddr() ([]byte, error) {
noAddr, noPk := len(g.Address) == 0, g.PubKey.Empty()

View File

@ -12,24 +12,25 @@ import (
"github.com/tendermint/basecoin/types"
)
const (
NameCoin = "coin"
)
//NameCoin - name space of the coin module
const NameCoin = "coin"
// Handler writes
// Handler includes an accountant
type Handler struct {
Accountant
}
var _ basecoin.Handler = Handler{}
// NewHandler - new accountant handler for the coin module
func NewHandler() Handler {
return Handler{
Accountant: NewAccountant(""),
}
}
func (_ Handler) Name() string {
// Name - return name space
func (Handler) Name() string {
return NameCoin
}
@ -80,6 +81,7 @@ func (h Handler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoi
return basecoin.Result{}, nil
}
// SetOption - sets the genesis account balance
func (h Handler) SetOption(l log.Logger, store types.KVStore, module, key, value string) (log string, err error) {
if module != NameCoin {
return "", errors.ErrUnknownModule(module)
@ -103,10 +105,9 @@ func (h Handler) SetOption(l log.Logger, store types.KVStore, module, key, value
}
return "Success", nil
} else {
msg := fmt.Sprintf("Unknown key: %s", key)
return "", errors.ErrInternal(msg)
}
msg := fmt.Sprintf("Unknown key: %s", key)
return "", errors.ErrInternal(msg)
}
func checkTx(ctx basecoin.Context, tx basecoin.Tx) (send SendTx, err error) {

View File

@ -10,10 +10,13 @@ import (
"github.com/tendermint/basecoin/types"
)
// Accountant - custom object to manage coins for the coin module
// TODO prefix should be post-fix if maintaining the same key space
type Accountant struct {
Prefix []byte
}
// NewAccountant - create the new accountant with prefix information
func NewAccountant(prefix string) Accountant {
if prefix == "" {
prefix = NameCoin
@ -23,8 +26,10 @@ func NewAccountant(prefix string) Accountant {
}
}
// GetAccount - Get account from store and address
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
@ -67,7 +72,7 @@ func (a Accountant) updateCoins(store types.KVStore, addr basecoin.Actor, coins
if seq != acct.Sequence+1 {
return acct, ErrInvalidSequence()
}
acct.Sequence += 1
acct.Sequence++
}
// check amount
@ -80,6 +85,8 @@ func (a Accountant) updateCoins(store types.KVStore, addr basecoin.Actor, coins
return acct, nil
}
// MakeKey - generate key bytes from address using accountant prefix
// TODO Prefix -> PostFix for consistent namespace
func (a Accountant) MakeKey(addr basecoin.Actor) []byte {
key := addr.Bytes()
if len(a.Prefix) > 0 {
@ -88,6 +95,7 @@ func (a Accountant) MakeKey(addr basecoin.Actor) []byte {
return key
}
// Account - coin account structure
type Account struct {
Coins types.Coins `json:"coins"`
Sequence int `json:"sequence"`

View File

@ -4,7 +4,6 @@ import (
"fmt"
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/types"
)
@ -20,12 +19,14 @@ const (
//-----------------------------------------------------------------------------
// TxInput - expected coin movement outputs, used with SendTx
type TxInput struct {
Address basecoin.Actor `json:"address"`
Coins types.Coins `json:"coins"`
Sequence int `json:"sequence"` // Nonce: Must be 1 greater than the last committed TxInput
}
// ValidateBasic - validate transaction input
func (txIn TxInput) ValidateBasic() error {
if txIn.Address.App == "" {
return ErrInvalidAddress()
@ -50,6 +51,7 @@ func (txIn TxInput) String() string {
return fmt.Sprintf("TxInput{%v,%v,%v}", txIn.Address, txIn.Coins, txIn.Sequence)
}
// NewTxInput - create a transaction input, used with SendTx
func NewTxInput(addr basecoin.Actor, coins types.Coins, sequence int) TxInput {
input := TxInput{
Address: addr,
@ -61,11 +63,13 @@ func NewTxInput(addr basecoin.Actor, coins types.Coins, sequence int) TxInput {
//-----------------------------------------------------------------------------
// TxOutput - expected coin movement output, used with SendTx
type TxOutput struct {
Address basecoin.Actor `json:"address"`
Coins types.Coins `json:"coins"`
}
// ValidateBasic - validate transaction output
func (txOut TxOutput) ValidateBasic() error {
if txOut.Address.App == "" {
return ErrInvalidAddress()
@ -87,6 +91,7 @@ func (txOut TxOutput) String() string {
return fmt.Sprintf("TxOutput{%X,%v}", txOut.Address, txOut.Coins)
}
// NewTxOutput - create a transaction output, used with SendTx
func NewTxOutput(addr basecoin.Actor, coins types.Coins) TxOutput {
output := TxOutput{
Address: addr,
@ -97,6 +102,8 @@ func NewTxOutput(addr basecoin.Actor, coins types.Coins) TxOutput {
//-----------------------------------------------------------------------------
// SendTx - high level transaction of the coin module
// Satisfies: TxInner
type SendTx struct {
Inputs []TxInput `json:"inputs"`
Outputs []TxOutput `json:"outputs"`
@ -104,10 +111,12 @@ type SendTx struct {
var _ basecoin.Tx = NewSendTx(nil, nil)
// NewSendTx - new SendTx
func NewSendTx(in []TxInput, out []TxOutput) basecoin.Tx {
return SendTx{Inputs: in, Outputs: out}.Wrap()
}
// ValidateBasic - validate the send transaction
func (tx SendTx) ValidateBasic() error {
// this just makes sure all the inputs and outputs are properly formatted,
// not that they actually have the money inside
@ -142,6 +151,7 @@ func (tx SendTx) String() string {
return fmt.Sprintf("SendTx{%v->%v}", tx.Inputs, tx.Outputs)
}
// Wrap - used to satisfy TxInner
func (tx SendTx) Wrap() basecoin.Tx {
return basecoin.Tx{tx}
}

View File

@ -1,3 +1,4 @@
//nolint
package fee
import (

View File

@ -7,10 +7,10 @@ import (
"github.com/tendermint/basecoin/types"
)
const (
NameFee = "fee"
)
// NameFee - namespace for the fee module
const NameFee = "fee"
// AccountChecker - interface used by SimpleFeeHandler
type AccountChecker interface {
// Get amount checks the current amount
GetAmount(store types.KVStore, addr basecoin.Actor) (types.Coins, error)
@ -20,13 +20,15 @@ type AccountChecker interface {
ChangeAmount(store types.KVStore, addr basecoin.Actor, coins types.Coins) (types.Coins, error)
}
// SimpleFeeHandler - checker object for fee checking
type SimpleFeeHandler struct {
AccountChecker
MinFee types.Coins
stack.PassOption
}
func (_ SimpleFeeHandler) Name() string {
// Name - return the namespace for the fee module
func (SimpleFeeHandler) Name() string {
return NameFee
}
@ -34,6 +36,7 @@ var _ stack.Middleware = SimpleFeeHandler{}
// Yes, I know refactor a bit... really too late already
// CheckTx - check the transaction
func (h SimpleFeeHandler) CheckTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, next basecoin.Checker) (res basecoin.Result, err error) {
feeTx, ok := tx.Unwrap().(*Fee)
if !ok {
@ -57,6 +60,7 @@ func (h SimpleFeeHandler) CheckTx(ctx basecoin.Context, store types.KVStore, tx
return basecoin.Result{Log: "Valid tx"}, nil
}
// DeliverTx - send the fee handler transaction
func (h SimpleFeeHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx basecoin.Tx, next basecoin.Deliver) (res basecoin.Result, err error) {
feeTx, ok := tx.Unwrap().(*Fee)
if !ok {

View File

@ -1,3 +1,4 @@
//nolint
package version
const Maj = "0"