diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..d587999e1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[Makefile] +indent_style = tab + +[*.sh] +indent_style = tab diff --git a/.gitignore b/.gitignore index 920af7622..62f28681c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -*.swp -*.swo -*.pyc vendor +.glide diff --git a/CHANGELOG.md b/CHANGELOG.md index b7115552a..09d7bf5ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.5.0 (May 18, 2017) + +BREAKING CHANGES: + +- `NewSocketClient` and `NewGRPCClient` no longer start the client automatically, and don't return errors. The caller is responsible for running `client.Start()` and checking the error. +- `NewSocketServer` and `NewGRPCServer` no longer start the server automatically, and don't return errors. The caller is responsible for running `server.Start()` and checking the error. + + +FEATURES: + +- [types] new method `func (res Result) IsSameCode(compare Result) bool` checks whether two results have the same code +- [types] new methods `func (r *ResponseCheckTx) Result() Result` and `func (r *ResponseDeliverTx) Result() Result` to convert from protobuf types (for control over json serialization) +- [types] new method `func (r *ResponseQuery) Result() *ResultQuery` and struct `ResultQuery` to convert from protobuf types (for control over json serializtion) + +IMPROVEMENTS: + +- Update imports for new `tmlibs` repository +- Use the new logger +- [abci-cli] Add flags to the query command for `path`, `height`, and `prove` +- [types] use `data.Bytes` and `json` tags in the `Result` struct + +BUG FIXES: + ## 0.4.1 (April 18, 2017) IMPROVEMENTS: diff --git a/Makefile b/Makefile index 31236551f..19ae42600 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ build: # test.sh requires that we run the installed cmds, must not be out of date test: install - find . -name test.sock -exec rm {} \; + find . -path ./vendor -prune -o -name *.sock -exec rm {} \; @ go test -p 1 `${NOVENDOR}` @ bash tests/test.sh @@ -30,7 +30,7 @@ lint: @ go get -u github.com/golang/lint/golint @ for file in $$(find "." -name '*.go' | grep -v '/vendor/' | grep -v '\.pb\.go'); do \ golint -set_exit_status $${file}; \ - done; + done; test_integrations: get_vendor_deps install test diff --git a/client/client.go b/client/client.go index 38fff4863..c911dd876 100644 --- a/client/client.go +++ b/client/client.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) type Client interface { @@ -43,15 +43,16 @@ type Client interface { //---------------------------------------- +// NewClient returns a new ABCI client of the specified transport type. +// It returns an error if the transport is not "socket" or "grpc" func NewClient(addr, transport string, mustConnect bool) (client Client, err error) { switch transport { case "socket": - client, err = NewSocketClient(addr, mustConnect) + client = NewSocketClient(addr, mustConnect) case "grpc": - client, err = NewGRPCClient(addr, mustConnect) + client = NewGRPCClient(addr, mustConnect) default: err = fmt.Errorf("Unknown abci transport %s", transport) - } return } diff --git a/client/grpc_client.go b/client/grpc_client.go index 7cca5079a..9743cdf62 100644 --- a/client/grpc_client.go +++ b/client/grpc_client.go @@ -10,7 +10,7 @@ import ( grpc "google.golang.org/grpc" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) // A stripped copy of the remoteClient that makes @@ -27,14 +27,13 @@ type grpcClient struct { resCb func(*types.Request, *types.Response) // listens to all callbacks } -func NewGRPCClient(addr string, mustConnect bool) (*grpcClient, error) { +func NewGRPCClient(addr string, mustConnect bool) *grpcClient { cli := &grpcClient{ addr: addr, mustConnect: mustConnect, } cli.BaseService = *cmn.NewBaseService(nil, "grpcClient", cli) - _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. - return cli, err + return cli } func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { @@ -51,7 +50,7 @@ RETRY_LOOP: if cli.mustConnect { return err } - log.Warn(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) + cli.Logger.Error(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -93,7 +92,7 @@ func (cli *grpcClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(fmt.Sprintf("Stopping abci.grpcClient for error: %v", err.Error())) + cli.Logger.Error(fmt.Sprintf("Stopping abci.grpcClient for error: %v", err.Error())) cli.Stop() } diff --git a/client/local_client.go b/client/local_client.go index 1150db4a1..37f76abb3 100644 --- a/client/local_client.go +++ b/client/local_client.go @@ -4,7 +4,7 @@ import ( "sync" types "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) type localClient struct { @@ -22,7 +22,7 @@ func NewLocalClient(mtx *sync.Mutex, app types.Application) *localClient { mtx: mtx, Application: app, } - cli.BaseService = *cmn.NewBaseService(log, "localClient", cli) + cli.BaseService = *cmn.NewBaseService(nil, "localClient", cli) return cli } diff --git a/client/log.go b/client/log.go deleted file mode 100644 index 944b05ba0..000000000 --- a/client/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package abcicli - -import ( - "github.com/tendermint/go-logger" -) - -var log = logger.New("module", "abcicli") diff --git a/client/socket_client.go b/client/socket_client.go index 5aeeac7ac..f95eac5cc 100644 --- a/client/socket_client.go +++ b/client/socket_client.go @@ -11,7 +11,7 @@ import ( "time" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) const ( @@ -42,7 +42,7 @@ type socketClient struct { } -func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { +func NewSocketClient(addr string, mustConnect bool) *socketClient { cli := &socketClient{ reqQueue: make(chan *ReqRes, reqQueueSize), flushTimer: cmn.NewThrottleTimer("socketClient", flushThrottleMS), @@ -53,9 +53,7 @@ func NewSocketClient(addr string, mustConnect bool) (*socketClient, error) { resCb: nil, } cli.BaseService = *cmn.NewBaseService(nil, "socketClient", cli) - - _, err := cli.Start() // Just start it, it's confusing for callers to remember to start. - return cli, err + return cli } func (cli *socketClient) OnStart() error { @@ -70,7 +68,7 @@ RETRY_LOOP: if cli.mustConnect { return err } - log.Warn(fmt.Sprintf("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) + cli.Logger.Error(fmt.Sprintf("abci.socketClient failed to connect to %v. Retrying...", cli.addr)) time.Sleep(time.Second * 3) continue RETRY_LOOP } @@ -107,7 +105,7 @@ func (cli *socketClient) StopForError(err error) { } cli.mtx.Unlock() - log.Warn(fmt.Sprintf("Stopping abci.socketClient for error: %v", err.Error())) + cli.Logger.Error(fmt.Sprintf("Stopping abci.socketClient for error: %v", err.Error())) cli.Stop() } @@ -147,7 +145,7 @@ func (cli *socketClient) sendRequestsRoutine(conn net.Conn) { cli.StopForError(fmt.Errorf("Error writing msg: %v", err)) return } - // log.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) + // cli.Logger.Debug("Sent request", "requestType", reflect.TypeOf(reqres.Request), "request", reqres.Request) if _, ok := reqres.Request.Value.(*types.Request_Flush); ok { err = w.Flush() if err != nil { @@ -175,7 +173,7 @@ func (cli *socketClient) recvResponseRoutine(conn net.Conn) { cli.StopForError(errors.New(r.Exception.Error)) return default: - // log.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) + // cli.Logger.Debug("Received response", "responseType", reflect.TypeOf(res), "response", res) err := cli.didRecvResponse(res) if err != nil { cli.StopForError(err) diff --git a/cmd/abci-cli/abci-cli.go b/cmd/abci-cli/abci-cli.go index accae9d1e..0f1dd82d0 100644 --- a/cmd/abci-cli/abci-cli.go +++ b/cmd/abci-cli/abci-cli.go @@ -6,13 +6,13 @@ import ( "errors" "fmt" "io" - "log" "os" "strings" - "github.com/tendermint/abci/client" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" "github.com/tendermint/abci/version" + "github.com/tendermint/tmlibs/log" "github.com/urfave/cli" ) @@ -36,6 +36,8 @@ type queryResponse struct { // client is a global variable so it can be reused by the console var client abcicli.Client +var logger log.Logger + func main() { //workaround for the cli library (https://github.com/urfave/cli/issues/565) @@ -124,22 +126,47 @@ func main() { Action: func(c *cli.Context) error { return cmdQuery(c) }, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "path", + Value: "/store", + Usage: "Path to prefix the query with", + }, + cli.IntFlag{ + Name: "height", + Value: 0, + Usage: "Height to query the blockchain at", + }, + cli.BoolFlag{ + Name: "prove", + Usage: "Whether or not to return a merkle proof of the query result", + }, + }, }, } app.Before = before err := app.Run(os.Args) if err != nil { - log.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) } } func before(c *cli.Context) error { + if logger == nil { + logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), log.AllowError()) + } if client == nil { var err error client, err = abcicli.NewClient(c.GlobalString("address"), c.GlobalString("abci"), false) if err != nil { - log.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) + } + client.SetLogger(logger.With("module", "abci-client")) + if _, err := client.Start(); err != nil { + return err } } return nil @@ -296,21 +323,27 @@ func cmdCommit(c *cli.Context) error { } // Query application state -// TODO: Make request and response support all fields. func cmdQuery(c *cli.Context) error { args := c.Args() + if len(args) != 1 { - return errors.New("Command query takes 1 argument") + return errors.New("Command query takes 1 argument, the query bytes") } - queryBytes, err := stringOrHexToBytes(c.Args()[0]) + + queryBytes, err := stringOrHexToBytes(args[0]) if err != nil { return err } + + path := c.String("path") + height := c.Int("height") + prove := c.Bool("prove") + resQuery, err := client.QuerySync(types.RequestQuery{ Data: queryBytes, - Path: "/store", // TOOD expose - Height: 0, // TODO expose - //Prove: true, // TODO expose + Path: path, + Height: uint64(height), + Prove: prove, }) if err != nil { return err diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 6858fc43e..aa55778cc 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -2,11 +2,12 @@ package main import ( "flag" - "log" + "os" "github.com/tendermint/abci/example/counter" "github.com/tendermint/abci/server" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func main() { @@ -17,10 +18,18 @@ func main() { flag.Parse() app := counter.NewCounterApplication(*serialPtr) + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - log.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) + } + srv.SetLogger(logger.With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + logger.Error(err.Error()) + os.Exit(1) } // Wait forever diff --git a/cmd/dummy/main.go b/cmd/dummy/main.go index b48a15c7a..85bbca18d 100644 --- a/cmd/dummy/main.go +++ b/cmd/dummy/main.go @@ -2,12 +2,13 @@ package main import ( "flag" - "log" + "os" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func main() { @@ -17,18 +18,27 @@ func main() { persistencePtr := flag.String("persist", "", "directory to use for a database") flag.Parse() + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + // Create the application - in memory or persisted to disk var app types.Application if *persistencePtr == "" { app = dummy.NewDummyApplication() } else { app = dummy.NewPersistentDummyApplication(*persistencePtr) + app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy")) } // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, app) if err != nil { - log.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) + } + srv.SetLogger(logger.With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + logger.Error(err.Error()) + os.Exit(1) } // Wait forever diff --git a/example/block_aware/block_aware_app.go b/example/block_aware/block_aware_app.go index 454c3560b..8bacecd13 100644 --- a/example/block_aware/block_aware_app.go +++ b/example/block_aware/block_aware_app.go @@ -2,11 +2,12 @@ package main import ( "flag" - "log" + "os" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func main() { @@ -15,10 +16,18 @@ func main() { abciPtr := flag.String("abci", "socket", "socket | grpc") flag.Parse() + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + // Start the listener srv, err := server.NewServer(*addrPtr, *abciPtr, NewChainAwareApplication()) if err != nil { - log.Fatal(err.Error()) + logger.Error(err.Error()) + os.Exit(1) + } + srv.SetLogger(logger.With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + logger.Error(err.Error()) + os.Exit(1) } // Wait forever diff --git a/example/block_aware/block_aware_test.go b/example/block_aware/block_aware_test.go index 2ce6aacf3..05a5c05c3 100644 --- a/example/block_aware/block_aware_test.go +++ b/example/block_aware/block_aware_test.go @@ -1,19 +1,17 @@ package main import ( - "fmt" - "log" "strconv" "strings" "testing" - "github.com/tendermint/abci/client" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" + "github.com/tendermint/tmlibs/log" ) func TestChainAware(t *testing.T) { - app := NewChainAwareApplication() // Start the listener @@ -21,14 +19,18 @@ func TestChainAware(t *testing.T) { if err != nil { t.Fatal(err) } + srv.SetLogger(log.TestingLogger().With("module", "abci-server")) + if _, err := srv.Start(); err != nil { + t.Fatal(err.Error()) + } defer srv.Stop() // Connect to the socket - client, err := abcicli.NewSocketClient("unix://test.sock", false) - if err != nil { - log.Fatal(fmt.Sprintf("Error starting socket client: %v", err.Error())) + client := abcicli.NewSocketClient("unix://test.sock", false) + client.SetLogger(log.TestingLogger().With("module", "abci-client")) + if _, err := client.Start(); err != nil { + t.Fatalf("Error starting socket client: %v", err.Error()) } - client.Start() defer client.Stop() n := uint64(5) diff --git a/example/counter/counter.go b/example/counter/counter.go index c40541ed9..c4e4e267a 100644 --- a/example/counter/counter.go +++ b/example/counter/counter.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) type CounterApplication struct { diff --git a/example/dummy/dummy.go b/example/dummy/dummy.go index f88b1b20e..4485deac8 100644 --- a/example/dummy/dummy.go +++ b/example/dummy/dummy.go @@ -4,8 +4,9 @@ import ( "strings" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" - "github.com/tendermint/go-merkle" + "github.com/tendermint/merkleeyes/iavl" + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/merkle" ) type DummyApplication struct { @@ -15,7 +16,7 @@ type DummyApplication struct { } func NewDummyApplication() *DummyApplication { - state := merkle.NewIAVLTree(0, nil) + state := iavl.NewIAVLTree(0, nil) return &DummyApplication{state: state} } diff --git a/example/dummy/dummy_test.go b/example/dummy/dummy_test.go index 879cf3c4a..e180af3e3 100644 --- a/example/dummy/dummy_test.go +++ b/example/dummy/dummy_test.go @@ -10,9 +10,10 @@ import ( abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" - "github.com/tendermint/go-crypto" - "github.com/tendermint/go-merkle" + crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/merkleeyes/iavl" + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) { @@ -38,7 +39,7 @@ func testDummy(t *testing.T, app types.Application, tx []byte, key, value string }) require.Equal(t, types.CodeType_OK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := merkle.ReadProof(resQuery.Proof) + proof, err := iavl.ReadProof(resQuery.Proof) require.Nil(t, err) require.True(t, proof.Verify([]byte(key), resQuery.Value, proof.RootHash)) // NOTE: we have no way to verify the RootHash } @@ -211,38 +212,44 @@ func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) { func makeSocketClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { // Start the listener socket := cmn.Fmt("unix://%s.sock", name) - server, err := server.NewSocketServer(socket, app) - if err != nil { + logger := log.TestingLogger() + + server := server.NewSocketServer(socket, app) + server.SetLogger(logger.With("module", "abci-server")) + if _, err := server.Start(); err != nil { return nil, nil, err } // Connect to the socket - client, err := abcicli.NewSocketClient(socket, false) - if err != nil { + client := abcicli.NewSocketClient(socket, false) + client.SetLogger(logger.With("module", "abci-client")) + if _, err := client.Start(); err != nil { server.Stop() return nil, nil, err } - client.Start() - return client, server, err + return client, server, nil } func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) { // Start the listener socket := cmn.Fmt("unix://%s.sock", name) + logger := log.TestingLogger() gapp := types.NewGRPCApplication(app) - server, err := server.NewGRPCServer(socket, gapp) - if err != nil { + server := server.NewGRPCServer(socket, gapp) + server.SetLogger(logger.With("module", "abci-server")) + if _, err := server.Start(); err != nil { return nil, nil, err } - client, err := abcicli.NewGRPCClient(socket, true) - if err != nil { + client := abcicli.NewGRPCClient(socket, true) + client.SetLogger(logger.With("module", "abci-client")) + if _, err := client.Start(); err != nil { server.Stop() return nil, nil, err } - return client, server, err + return client, server, nil } func TestClientServer(t *testing.T) { @@ -302,7 +309,7 @@ func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) require.Nil(t, err) require.Equal(t, types.CodeType_OK, resQuery.Code) require.Equal(t, value, string(resQuery.Value)) - proof, err := merkle.ReadProof(resQuery.Proof) + proof, err := iavl.ReadProof(resQuery.Proof) require.Nil(t, err) require.True(t, proof.Verify([]byte(key), resQuery.Value, proof.RootHash)) // NOTE: we have no way to verify the RootHash } diff --git a/example/dummy/log.go b/example/dummy/log.go deleted file mode 100644 index 8571fa01e..000000000 --- a/example/dummy/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package dummy - -import ( - "github.com/tendermint/go-logger" -) - -var log = logger.New("module", "dummy") diff --git a/example/dummy/persistent_dummy.go b/example/dummy/persistent_dummy.go index 48eff420d..fb59a2724 100644 --- a/example/dummy/persistent_dummy.go +++ b/example/dummy/persistent_dummy.go @@ -6,11 +6,13 @@ import ( "strconv" "strings" + "github.com/pkg/errors" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" - dbm "github.com/tendermint/go-db" - "github.com/tendermint/go-merkle" - "github.com/tendermint/go-wire" + wire "github.com/tendermint/go-wire" + "github.com/tendermint/merkleeyes/iavl" + cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/tmlibs/log" ) const ( @@ -29,23 +31,30 @@ type PersistentDummyApplication struct { // validator set changes []*types.Validator + + logger log.Logger } func NewPersistentDummyApplication(dbDir string) *PersistentDummyApplication { db := dbm.NewDB("dummy", "leveldb", dbDir) lastBlock := LoadLastBlock(db) - stateTree := merkle.NewIAVLTree(0, db) + stateTree := iavl.NewIAVLTree(0, db) stateTree.Load(lastBlock.AppHash) - log.Notice("Loaded state", "block", lastBlock.Height, "root", stateTree.Hash()) + // log.Notice("Loaded state", "block", lastBlock.Height, "root", stateTree.Hash()) return &PersistentDummyApplication{ - app: &DummyApplication{state: stateTree}, - db: db, + app: &DummyApplication{state: stateTree}, + db: db, + logger: log.NewNopLogger(), } } +func (app *PersistentDummyApplication) SetLogger(l log.Logger) { + app.logger = l +} + func (app *PersistentDummyApplication) Info() (resInfo types.ResponseInfo) { resInfo = app.app.Info() lastBlock := LoadLastBlock(app.db) @@ -79,13 +88,16 @@ func (app *PersistentDummyApplication) CheckTx(tx []byte) types.Result { func (app *PersistentDummyApplication) Commit() types.Result { // Save appHash := app.app.state.Save() - log.Info("Saved state", "root", appHash) + app.logger.Info("Saved state", "root", appHash) lastBlock := LastBlockInfo{ Height: app.blockHeader.Height, AppHash: appHash, // this hash will be in the next block header } + + app.logger.Info("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) SaveLastBlock(app.db, lastBlock) + return types.NewResultOK(appHash, "") } @@ -98,7 +110,7 @@ func (app *PersistentDummyApplication) InitChain(validators []*types.Validator) for _, v := range validators { r := app.updateValidator(v) if r.IsErr() { - log.Error("Error updating validators", "r", r) + app.logger.Error("Error updating validators", "r", r) } } } @@ -134,8 +146,7 @@ func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) { r, n, err := bytes.NewReader(buf), new(int), new(error) wire.ReadBinaryPtr(&lastBlock, r, 0, n, err) if *err != nil { - // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED - log.Crit(cmn.Fmt("Data has been corrupted or its spec has changed: %v\n", *err)) + cmn.PanicCrisis(errors.Wrap(*err, "cannot load last block (data has been corrupted or its spec has changed)")) } // TODO: ensure that buf is completely read. } @@ -144,12 +155,11 @@ func LoadLastBlock(db dbm.DB) (lastBlock LastBlockInfo) { } func SaveLastBlock(db dbm.DB, lastBlock LastBlockInfo) { - log.Notice("Saving block", "height", lastBlock.Height, "root", lastBlock.AppHash) buf, n, err := new(bytes.Buffer), new(int), new(error) wire.WriteBinary(lastBlock, buf, n, err) if *err != nil { // TODO - cmn.PanicCrisis(*err) + cmn.PanicCrisis(errors.Wrap(*err, "cannot save last block")) } db.Set(lastBlockKey, buf.Bytes()) } diff --git a/example/example_test.go b/example/example_test.go index 034331d62..e9505f223 100644 --- a/example/example_test.go +++ b/example/example_test.go @@ -2,7 +2,6 @@ package example import ( "fmt" - "log" "net" "reflect" "testing" @@ -12,11 +11,12 @@ import ( "golang.org/x/net/context" - "github.com/tendermint/abci/client" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/example/dummy" "github.com/tendermint/abci/server" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/tmlibs/log" ) func TestDummy(t *testing.T) { @@ -35,22 +35,22 @@ func TestGRPC(t *testing.T) { } func testStream(t *testing.T, app types.Application) { - numDeliverTxs := 200000 // Start the listener - server, err := server.NewSocketServer("unix://test.sock", app) - if err != nil { - log.Fatal(cmn.Fmt("Error starting socket server: %v", err.Error())) + server := server.NewSocketServer("unix://test.sock", app) + server.SetLogger(log.TestingLogger().With("module", "abci-server")) + if _, err := server.Start(); err != nil { + t.Fatalf("Error starting socket server: %v", err.Error()) } defer server.Stop() // Connect to the socket - client, err := abcicli.NewSocketClient("unix://test.sock", false) - if err != nil { - log.Fatal(cmn.Fmt("Error starting socket client: %v", err.Error())) + client := abcicli.NewSocketClient("unix://test.sock", false) + client.SetLogger(log.TestingLogger().With("module", "abci-client")) + if _, err := client.Start(); err != nil { + t.Fatalf("Error starting socket client: %v", err.Error()) } - client.Start() defer client.Stop() done := make(chan struct{}) @@ -108,20 +108,20 @@ func dialerFunc(addr string, timeout time.Duration) (net.Conn, error) { } func testGRPCSync(t *testing.T, app *types.GRPCApplication) { - numDeliverTxs := 2000 // Start the listener - server, err := server.NewGRPCServer("unix://test.sock", app) - if err != nil { - log.Fatal(cmn.Fmt("Error starting GRPC server: %v", err.Error())) + server := server.NewGRPCServer("unix://test.sock", app) + server.SetLogger(log.TestingLogger().With("module", "abci-server")) + if _, err := server.Start(); err != nil { + t.Fatalf("Error starting GRPC server: %v", err.Error()) } defer server.Stop() // Connect to the socket conn, err := grpc.Dial("unix://test.sock", grpc.WithInsecure(), grpc.WithDialer(dialerFunc)) if err != nil { - log.Fatal(cmn.Fmt("Error dialing GRPC server: %v", err.Error())) + t.Fatalf("Error dialing GRPC server: %v", err.Error()) } defer conn.Close() diff --git a/glide.lock b/glide.lock index eea3410c4..55c5cdb38 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: a0dd8fe3cb061f9e4f3b3b6f0e6e7fb91982d7c3deb422e53e144a3bdcde216a -updated: 2017-04-18T23:28:11.182163777-04:00 +hash: f9c2ddad16bf8652076a93bd9f398bb498eefb2f5bd2c89a77d966ebd12feec8 +updated: 2017-05-15T10:11:42.094564957-04:00 imports: - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 @@ -7,29 +7,33 @@ imports: - btcec - name: github.com/btcsuite/fastsha256 version: 637e656429416087660c84436a2a035d69d54e2e +- name: github.com/clipperhouse/typewriter + version: c1a48da378ebb7db1db9f35981b5cc24bf2e5b85 +- name: github.com/go-kit/kit + version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 + subpackages: + - log + - log/level + - log/term +- name: github.com/go-logfmt/logfmt + version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/golang/protobuf - version: 69b215d01a5606c843240eab4937eab3acee6530 + version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 subpackages: - proto + - ptypes/any - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 -- name: github.com/mattn/go-colorable - version: 9fdad7c47650b7d2e1da50644c1f4ba7f172f252 -- name: github.com/mattn/go-isatty - version: 56b76bdf51f7708750eac80fa38b952bb9f32639 +- name: github.com/kr/logfmt + version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 - subpackages: - - assert - - require + version: ff09b135c25aae272398c51a07235b90a75aa4f0 - name: github.com/syndtr/goleveldb - version: 3c5717caf1475fd25964109a0fc640bd150fce43 + version: 8c81ea47d4c41a385645e133e15510fc6a2a74b4 subpackages: - leveldb - leveldb/cache @@ -48,30 +52,28 @@ imports: subpackages: - edwards25519 - extra25519 -- name: github.com/tendermint/go-common - version: f9e3db037330c8a8d61d3966de8473eaf01154fa - name: github.com/tendermint/go-crypto - version: 750b25c47a5782f5f2b773ed9e706cb82b3ccef4 -- name: github.com/tendermint/go-data - version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 -- name: github.com/tendermint/go-db - version: 9643f60bc2578693844aacf380a7c32e4c029fee -- name: github.com/tendermint/go-logger - version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 -- name: github.com/tendermint/go-merkle - version: 714d4d04557fd068a7c2a1748241ce8428015a96 -- name: github.com/tendermint/go-process - version: b27edfd189b1a01a0b099f7e9f8263589cf04909 + version: a42b10e0feb465eb56fbc6bb5b71d57ef646ec57 - name: github.com/tendermint/go-wire - version: c1c9a57ab8038448ddea1714c0698f8051e5748c -- name: github.com/tendermint/log15 - version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 + version: 301a758c9d28e9f3900ff5d545403cf4e5f6e73f + subpackages: + - data +- name: github.com/tendermint/merkleeyes + version: c722818b460381bc5b82e38c73ff6e22a9df624d + subpackages: + - iavl +- name: github.com/tendermint/tmlibs + version: 812d9f9b84d1dfe4cb46ce021b3a2d97b48d1292 subpackages: - - term + - common + - db + - log + - merkle + - process - name: github.com/urfave/cli - version: 8ef3805c9de2519805c3f060524b695bba2cd715 + version: d70f47eeca3afd795160003bc6e28b001d60c67c - name: golang.org/x/crypto - version: 1f22c0103821b9390939b6776727195525381532 + version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: - nacl/secretbox - openpgp/armor @@ -80,7 +82,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/net - version: d379faa25cbdc04d653984913a2ceb43b0bc46d7 + version: feeb485667d1fdabe727840fe00adc22431bc86e subpackages: - context - http2 @@ -89,21 +91,36 @@ imports: - internal/timeseries - lex/httplex - trace -- name: golang.org/x/sys - version: 50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e +- name: golang.org/x/text + version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4 subpackages: - - unix + - secure/bidirule + - transform + - unicode/bidi + - unicode/norm +- name: golang.org/x/tools + version: 144c6642b5d832d6c44a53dad6ee61665dd432ce + subpackages: + - go/ast/astutil + - imports +- name: google.golang.org/genproto + version: 411e09b969b1170a9f0c467558eb4c4c110d9c77 + subpackages: + - googleapis/rpc/status - name: google.golang.org/grpc - version: 7b399ed358736bc5522021cdc7d79a8ee9ac6f98 + version: 844f573616520565fdc6fb4db242321b5456fd6d subpackages: - codes - credentials + - grpclb/grpc_lb_v1 - grpclog - internal + - keepalive - metadata - naming - peer - stats + - status - tap - transport testImports: @@ -115,3 +132,8 @@ testImports: version: d8ed2627bdf02c080bf22230dbb337003b7aba2d subpackages: - difflib +- name: github.com/stretchr/testify + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + subpackages: + - assert + - require diff --git a/glide.yaml b/glide.yaml index 4d0358028..11379aad4 100644 --- a/glide.yaml +++ b/glide.yaml @@ -3,27 +3,29 @@ import: - package: github.com/golang/protobuf subpackages: - proto -- package: github.com/tendermint/go-common - version: develop +- package: github.com/pkg/errors - package: github.com/tendermint/go-crypto version: develop -- package: github.com/tendermint/go-data - version: develop -- package: github.com/tendermint/go-logger - version: develop -- package: github.com/tendermint/go-db +- package: github.com/tendermint/go-wire version: develop -- package: github.com/tendermint/go-merkle +- package: github.com/tendermint/merkleeyes version: develop -- package: github.com/tendermint/go-process -- package: github.com/tendermint/go-wire + subpackages: + - iavl +- package: github.com/tendermint/tmlibs version: develop + subpackages: + - common + - db + - log + - merkle + - process - package: github.com/urfave/cli - package: golang.org/x/net subpackages: - context - package: google.golang.org/grpc +testImport: - package: github.com/stretchr/testify - version: ^1.1.4 subpackages: - require diff --git a/server/grpc_server.go b/server/grpc_server.go index 944d4e42c..90346d690 100644 --- a/server/grpc_server.go +++ b/server/grpc_server.go @@ -7,11 +7,9 @@ import ( "google.golang.org/grpc" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) -// var maxNumberConnections = 2 - type GRPCServer struct { cmn.BaseService @@ -23,7 +21,8 @@ type GRPCServer struct { app types.ABCIApplicationServer } -func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Service, error) { +// NewGRPCServer returns a new gRPC ABCI server +func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) cmn.Service { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] s := &GRPCServer{ @@ -33,10 +32,10 @@ func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) (cmn.Servi app: app, } s.BaseService = *cmn.NewBaseService(nil, "ABCIServer", s) - _, err := s.Start() // Just start it - return s, err + return s } +// OnStart starts the gRPC service func (s *GRPCServer) OnStart() error { s.BaseService.OnStart() ln, err := net.Listen(s.proto, s.addr) @@ -50,6 +49,7 @@ func (s *GRPCServer) OnStart() error { return nil } +// OnStop stops the gRPC server func (s *GRPCServer) OnStop() { s.BaseService.OnStop() s.server.Stop() diff --git a/server/log.go b/server/log.go deleted file mode 100644 index 4b313d25f..000000000 --- a/server/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package server - -import ( - "github.com/tendermint/go-logger" -) - -var log = logger.New("module", "abci-server") diff --git a/server/server.go b/server/server.go index eb71b1325..0bbd65e37 100644 --- a/server/server.go +++ b/server/server.go @@ -1,10 +1,19 @@ +/* +Package server is used to start a new ABCI server. + +It contains two server implementation: + * gRPC server + * socket server + +*/ + package server import ( "fmt" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func NewServer(protoAddr, transport string, app types.Application) (cmn.Service, error) { @@ -12,9 +21,9 @@ func NewServer(protoAddr, transport string, app types.Application) (cmn.Service, var err error switch transport { case "socket": - s, err = NewSocketServer(protoAddr, app) + s = NewSocketServer(protoAddr, app) case "grpc": - s, err = NewGRPCServer(protoAddr, types.NewGRPCApplication(app)) + s = NewGRPCServer(protoAddr, types.NewGRPCApplication(app)) default: err = fmt.Errorf("Unknown server type %s", transport) } diff --git a/server/socket_server.go b/server/socket_server.go index bc1980e2d..2b01dbd70 100644 --- a/server/socket_server.go +++ b/server/socket_server.go @@ -9,7 +9,7 @@ import ( "sync" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) // var maxNumberConnections = 2 @@ -29,7 +29,7 @@ type SocketServer struct { app types.Application } -func NewSocketServer(protoAddr string, app types.Application) (cmn.Service, error) { +func NewSocketServer(protoAddr string, app types.Application) cmn.Service { parts := strings.SplitN(protoAddr, "://", 2) proto, addr := parts[0], parts[1] s := &SocketServer{ @@ -40,8 +40,7 @@ func NewSocketServer(protoAddr string, app types.Application) (cmn.Service, erro conns: make(map[int]net.Conn), } s.BaseService = *cmn.NewBaseService(nil, "ABCIServer", s) - _, err := s.Start() // Just start it - return s, err + return s } func (s *SocketServer) OnStart() error { @@ -94,15 +93,15 @@ func (s *SocketServer) acceptConnectionsRoutine() { // semaphore <- struct{}{} // Accept a connection - log.Notice("Waiting for new connection...") + s.Logger.Info("Waiting for new connection...") conn, err := s.listener.Accept() if err != nil { if !s.IsRunning() { return // Ignore error from listener closing. } - log.Crit("Failed to accept connection: " + err.Error()) + s.Logger.Error("Failed to accept connection: " + err.Error()) } else { - log.Notice("Accepted a new connection") + s.Logger.Info("Accepted a new connection") } connID := s.addConn(conn) @@ -119,18 +118,18 @@ func (s *SocketServer) acceptConnectionsRoutine() { // Wait until signal to close connection errClose := <-closeConn if err == io.EOF { - log.Warn("Connection was closed by client") + s.Logger.Error("Connection was closed by client") } else if errClose != nil { - log.Warn("Connection error", "error", errClose) + s.Logger.Error("Connection error", "error", errClose) } else { // never happens - log.Warn("Connection was closed.") + s.Logger.Error("Connection was closed.") } // Close the connection err := s.rmConn(connID, conn) if err != nil { - log.Warn("Error in closing connection", "error", err) + s.Logger.Error("Error in closing connection", "error", err) } // <-semaphore diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go index f01fba4c9..cc68ceadc 100644 --- a/tests/benchmarks/parallel/parallel.go +++ b/tests/benchmarks/parallel/parallel.go @@ -6,7 +6,7 @@ import ( "log" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func main() { diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go index 498aac341..ef5bab86b 100644 --- a/tests/benchmarks/simple/simple.go +++ b/tests/benchmarks/simple/simple.go @@ -8,7 +8,7 @@ import ( "reflect" "github.com/tendermint/abci/types" - cmn "github.com/tendermint/go-common" + cmn "github.com/tendermint/tmlibs/common" ) func main() { diff --git a/tests/test.sh b/tests/test.sh old mode 100644 new mode 100755 diff --git a/tests/test_app/app.go b/tests/test_app/app.go index 87b74ead0..281c9dcb1 100644 --- a/tests/test_app/app.go +++ b/tests/test_app/app.go @@ -6,9 +6,10 @@ import ( "os" "time" - "github.com/tendermint/abci/client" + abcicli "github.com/tendermint/abci/client" "github.com/tendermint/abci/types" - "github.com/tendermint/go-process" + "github.com/tendermint/tmlibs/log" + "github.com/tendermint/tmlibs/process" ) func startApp(abciApp string) *process.Process { @@ -35,8 +36,14 @@ func startClient(abciType string) abcicli.Client { // Start client client, err := abcicli.NewClient("tcp://127.0.0.1:46658", abciType, true) if err != nil { + panic(err.Error()) + } + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + client.SetLogger(logger.With("module", "abcicli")) + if _, err := client.Start(); err != nil { panic("connecting to abci_app: " + err.Error()) } + return client } diff --git a/tests/test_app/test.sh b/tests/test_app/test.sh index a0f2c3ce6..0620b4767 100755 --- a/tests/test_app/test.sh +++ b/tests/test_app/test.sh @@ -3,14 +3,19 @@ set -e # These tests spawn the counter app and server by execing the ABCI_APP command and run some simple client tests against it -ROOT=$GOPATH/src/github.com/tendermint/abci/tests/test_app -cd $ROOT +# Get the directory of where this script is. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +# Change into that dir because we expect that. +cd "$DIR" # test golang counter -ABCI_APP="counter" go run *.go +ABCI_APP="counter" go run ./*.go # test golang counter via grpc -ABCI_APP="counter -abci=grpc" ABCI="grpc" go run *.go +ABCI_APP="counter -abci=grpc" ABCI="grpc" go run ./*.go # test nodejs counter # TODO: fix node app diff --git a/tests/test_cli/test.sh b/tests/test_cli/test.sh index a770730be..4266dd16f 100644 --- a/tests/test_cli/test.sh +++ b/tests/test_cli/test.sh @@ -1,6 +1,12 @@ #! /bin/bash -cd $GOPATH/src/github.com/tendermint/abci +# Get the root directory. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )/../.." && pwd )" + +# Change into that dir because we expect that. +cd "$DIR" || exit function testExample() { N=$1 @@ -10,17 +16,17 @@ function testExample() { echo "Example $N" $APP &> /dev/null & sleep 2 - abci-cli --verbose batch < $INPUT > "${INPUT}.out.new" - killall "$APP" + abci-cli --verbose batch < "$INPUT" > "${INPUT}.out.new" + killall "$APP" - pre=`shasum < "${INPUT}.out"` - post=`shasum < "${INPUT}.out.new"` + pre=$(shasum < "${INPUT}.out") + post=$(shasum < "${INPUT}.out.new") if [[ "$pre" != "$post" ]]; then echo "You broke the tutorial" - echo "Got:" + echo "Got:" cat "${INPUT}.out.new" - echo "Expected:" + echo "Expected:" cat "${INPUT}.out" exit 1 fi diff --git a/types/result.go b/types/result.go index af89058e9..7bf52c90a 100644 --- a/types/result.go +++ b/types/result.go @@ -2,13 +2,15 @@ package types import ( "fmt" + + "github.com/tendermint/go-wire/data" ) // CONTRACT: a zero Result is OK. type Result struct { - Code CodeType - Data []byte - Log string // Can be non-deterministic + Code CodeType `json:"code"` + Data data.Bytes `json:"data"` + Log string `json:"log"` // Can be non-deterministic } func NewResult(code CodeType, data []byte, log string) Result { @@ -27,6 +29,10 @@ func (res Result) IsErr() bool { return res.Code != CodeType_OK } +func (res Result) IsSameCode(compare Result) bool { + return res.Code == compare.Code +} + func (res Result) Error() string { return fmt.Sprintf("ABCI{code:%v, data:%X, log:%v}", res.Code, res.Data, res.Log) } @@ -84,3 +90,47 @@ func NewError(code CodeType, log string) Result { Log: log, } } + +//---------------------------------------- +// Convenience methods for turning the +// pb type into one using data.Bytes + +// Convert ResponseCheckTx to standard Result +func (r *ResponseCheckTx) Result() Result { + return Result{ + Code: r.Code, + Data: r.Data, + Log: r.Log, + } +} + +// Convert ResponseDeliverTx to standard Result +func (r *ResponseDeliverTx) Result() Result { + return Result{ + Code: r.Code, + Data: r.Data, + Log: r.Log, + } +} + +type ResultQuery struct { + Code CodeType `json:"code"` + Index int64 `json:"index"` + Key data.Bytes `json:"key"` + Value data.Bytes `json:"value"` + Proof data.Bytes `json:"proof"` + Height uint64 `json:"height"` + Log string `json:"log"` +} + +func (r *ResponseQuery) Result() *ResultQuery { + return &ResultQuery{ + Code: r.Code, + Index: r.Index, + Key: r.Key, + Value: r.Value, + Proof: r.Proof, + Height: r.Height, + Log: r.Log, + } +} diff --git a/types/types.proto b/types/types.proto index 0c741d3d0..7abc354d9 100644 --- a/types/types.proto +++ b/types/types.proto @@ -3,30 +3,6 @@ package types; // This file is copied from http://github.com/tendermint/abci -//---------------------------------------- -// Message types - -// Not being used -// Could be added to request/response -// so we don't have to type switch -// (would be twice as fast, but we're talking about 15ns) -enum MessageType { - NullMessage = 0x00; - - Echo = 0x01; - Flush = 0x02; - Info = 0x03; - SetOption = 0x04; - Exception = 0x05; - DeliverTx = 0x11; - CheckTx = 0x12; - Commit = 0x13; - Query = 0x14; - InitChain = 0x15; - BeginBlock = 0x16; - EndBlock = 0x17; -} - //---------------------------------------- // Code types @@ -116,7 +92,7 @@ message RequestQuery{ bytes data = 1; string path = 2; uint64 height = 3; - bool prove = 4; + bool prove = 4; } message RequestCommit{ diff --git a/types/validators.go b/types/validators.go index 185355d15..95258aa23 100644 --- a/types/validators.go +++ b/types/validators.go @@ -2,8 +2,10 @@ package types import ( "bytes" + "encoding/json" - "github.com/tendermint/go-wire" + "github.com/tendermint/go-wire/data" + cmn "github.com/tendermint/tmlibs/common" ) // validators implements sort @@ -28,8 +30,8 @@ func (v Validators) Swap(i, j int) { //------------------------------------- type validatorPretty struct { - PubKey []byte `json:"pub_key"` - Power uint64 `json:"power"` + PubKey data.Bytes `json:"pub_key"` + Power uint64 `json:"power"` } func ValidatorsString(vs Validators) string { @@ -37,5 +39,9 @@ func ValidatorsString(vs Validators) string { for i, v := range vs { s[i] = validatorPretty{v.PubKey, v.Power} } - return string(wire.JSONBytes(s)) + b, err := json.Marshal(s) + if err != nil { + cmn.PanicSanity(err.Error()) + } + return string(b) } diff --git a/version/version.go b/version/version.go index 7b02c593e..6687721f1 100644 --- a/version/version.go +++ b/version/version.go @@ -3,7 +3,7 @@ package version // NOTE: we should probably be versioning the ABCI and the abci-cli separately const Maj = "0" -const Min = "4" -const Fix = "1" +const Min = "5" +const Fix = "0" -const Version = "0.4.1" +const Version = "0.5.0"