Compare commits

...

10 Commits

Author SHA1 Message Date
Ethan Buchman
0d985ede28 Merge pull request #3417 from tendermint/release/v0.31.0
Release/v0.31.0
2019-03-19 19:53:37 -04:00
Ismail Khoffi
1e3469789d Ensure WriteTimeout > TimeoutBroadcastTxCommit (#3443)
* Make sure config.TimeoutBroadcastTxCommit < rpcserver.WriteTimeout()

* remove redundant comment

* libs/rpc/http_server: move Read/WriteTimeout into Config

* increase defaults for read/write timeouts

Based on this article
https://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configuration

* WriteTimeout should be larger than TimeoutBroadcastTxCommit

* set a deadline for subscribing to txs

* extract duration into const

* add two changelog entries

* Update CHANGELOG_PENDING.md

Co-Authored-By: melekes <anton.kalyaev@gmail.com>

* Update CHANGELOG_PENDING.md

Co-Authored-By: melekes <anton.kalyaev@gmail.com>

* 12 -> 10

* changelog

* changelog
2019-03-19 19:45:51 -04:00
Ethan Buchman
5f68fbae37 Merge pull request #3449 from tendermint/ismail/merge_develop_into_release/0.31.0
Merge develop into release/0.31.0
2019-03-19 19:25:26 -04:00
Ismail Khoffi
e276f35f86 remove 3421 from changelog 2019-03-19 14:36:42 +01:00
Ismail Khoffi
8e62a3d62a Add #3421 to changelog and reorder alphabetically 2019-03-19 12:19:02 +01:00
Ismail Khoffi
48aaccab8f Merge in develop and update CHANGELOG.md 2019-03-19 12:09:26 +01:00
Anton Kaliaev
4162ebe8b5 types: refactor PB2TM.ConsensusParams to take BlockTimeIota as an arg (#3442)
See https://github.com/tendermint/tendermint/pull/3403/files#r266208947

In #3403 we unexposed BlockTimeIota from the ABCI, but it's still part
of the ConsensusParams struct, so we have to remember to add it back
after calling PB2TM.ConsensusParams. Instead, PB2TM.ConsensusParams
should take it as an argument

Fixes #3432
2019-03-19 11:38:32 +04:00
Ethan Buchman
551b6322f5 Update v0.31.0 release notes (#3434)
* changelog: fix formatting

* update release notes

* update changelog

* linkify

* update UPGRADING
2019-03-16 19:24:12 -04:00
Anton Kaliaev
7457133307 grpcdb: close Iterator/ReverseIterator after use (#3424)
Fixes #3402
2019-03-14 15:00:58 +04:00
Anton Kaliaev
a59930a327 localnet: fix $LOG variable (#3423)
Fixes #3421

Before: it was creating a file named ${LOG:-tendermint.log} in .build/nodeX
After: it creates a file named tendermint.log
2019-03-13 16:09:05 +04:00
23 changed files with 212 additions and 90 deletions

View File

@@ -2,48 +2,72 @@
## v0.31.0
*March 13th, 2019*
*March 16th, 2019*
Special thanks to external contributors on this release:
@danil-lashin, @guagualvcha, @jleni, @siburu, @silasdavis, @srmo, @Stumble, @svenstaro
@danil-lashin, @guagualvcha, @siburu, @silasdavis, @srmo, @Stumble, @svenstaro
This release brings pubsub 2.0, limits the mempool size to 1GB (max_txs_bytes) and number of `/subscribe` WebSocket
clients (`max_subscription_clients`) and adds `/unsubscribe_all` endpoint to the lite client.
It also contains many smaller improvements and bug-fixes.
Pubsub 2.0 is an improved version of the older pubsub, which is a) non-blocking b) has nicer API.
Note our HttpClient's interface got updated to reflect the pubsub changes and now also has a better API for WebSocket subscriptions.
This release is primarily about the new pubsub implementation, dubbed `pubsub 2.0`, and related changes,
like configurable limits on the number of active RPC subscriptions at a time (`max_subscription_clients`).
Pubsub 2.0 is an improved version of the older pubsub that is non-blocking and has a nicer API.
Note the improved pubsub API also resulted in some improvements to the HTTPClient interface and the API for WebSocket subscriptions.
This release also adds a configurable limit to the mempool size (`max_txs_bytes`, default 1GB)
and a configurable timeout for the `/broadcast_tx_commit` endpoint.
See the [v0.31.0
Milestone](https://github.com/tendermint/tendermint/milestone/19?closed=1) for
more details.
Friendly reminder, we have a [bug bounty
program](https://hackerone.com/tendermint).
### BREAKING CHANGES:
* CLI/RPC/Config
- [rpc/client] Update Subscribe interface to reflect new pubsub/eventBus API [ADR-33](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-033-pubsub.md)
- [config] [\#2826](https://github.com/tendermint/tendermint/issues/2826) Add `rpc.max_subscription_clients` config parameter to control how many unique clientIDs can `/subscribe` at the same time
- [config] [\#2826](https://github.com/tendermint/tendermint/issues/2826) Add `rpc.max_subscriptions_per_client` config parameter to control how many unique queries a given client can `/subscribe` to
- [config] [\#2826](https://github.com/tendermint/tendermint/issues/2826) Add `rpc.max_subscription_clients` config parameter allowing you to change time to wait for a tx to be committed during `/broadcast_tx_commit`
- [config] [\#2920](https://github.com/tendermint/tendermint/issues/2920) Remove `consensus.blocktime_iota` parameter
- [rpc] [\#3227](https://github.com/tendermint/tendermint/issues/3227) New PubSub design does not block on clients when publishing
messages. Slow clients may miss messages and receive an error, terminating
the subscription.
- [rpc] [\#3269](https://github.com/tendermint/tendermint/issues/2826) Limit number of unique clientIDs with open subscriptions. Configurable via `rpc.max_subscription_clients`
- [rpc] [\#3269](https://github.com/tendermint/tendermint/issues/2826) Limit number of unique queries a given client can subscribe to at once. Configurable via `rpc.max_subscriptions_per_client`.
- [rpc] [\#3435](https://github.com/tendermint/tendermint/issues/3435) Default ReadTimeout and WriteTimeout changed to 10s. WriteTimeout can increased by setting `rpc.timeout_broadcast_tx_commit` in the config.
- [rpc/client] [\#3269](https://github.com/tendermint/tendermint/issues/3269) Update `EventsClient` interface to reflect new pubsub/eventBus API [ADR-33](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-033-pubsub.md). This includes `Subscribe`, `Unsubscribe`, and `UnsubscribeAll` methods.
* Apps
- [genesis] [\#2920](https://github.com/tendermint/tendermint/issues/2920) Rename `consensus_params.block_size` to `consensus_params.block` in ABCI ConsensusParams
- [abci] [\#3403](https://github.com/tendermint/tendermint/issues/3403) Remove `time_iota_ms` from BlockParams. This is a
ConsensusParam but need not be exposed to the app for now.
- [abci] [\#2920](https://github.com/tendermint/tendermint/issues/2920) Rename `consensus_params.block_size` to `consensus_params.block` in ABCI ConsensusParams
* Go API
- [libs/common] TrapSignal accepts logger as a first parameter and does not block anymore
* previously it was dumping "captured ..." msg to os.Stdout
* TrapSignal should not be responsible for blocking thread of execution
- [libs/db] [\#3397](https://github.com/tendermint/tendermint/pull/3397) Add possibility to `Close()` `Batch` to prevent memory leak when using ClevelDB. (@Stumble)
- [libs/common] TrapSignal accepts logger as a first parameter and does not block anymore
* previously it was dumping "captured ..." msg to os.Stdout
* TrapSignal should not be responsible for blocking thread of execution
- [libs/db] [\#3397](https://github.com/tendermint/tendermint/pull/3397) Add possibility to `Close()` `Batch` to prevent memory leak when using ClevelDB. (@Stumble)
- [types] [\#3354](https://github.com/tendermint/tendermint/issues/3354) Remove RoundState from EventDataRoundState
- [rpc] [\#3435](https://github.com/tendermint/tendermint/issues/3435) `StartHTTPServer` / `StartHTTPAndTLSServer` now require a Config (use `rpcserver.DefaultConfig`)
* Blockchain Protocol
* P2P Protocol
### FEATURES:
- [mempool] [\#3079](https://github.com/tendermint/tendermint/issues/3079) bound mempool memory usage (`mempool.max_txs_bytes` is set to 1GB by default; see config.toml)
mempool's current `txs_total_bytes` is exposed via `total_bytes` field in
- [config] [\#3269](https://github.com/tendermint/tendermint/issues/2826) New configuration values for controlling RPC subscriptions:
- `rpc.max_subscription_clients` sets the maximum number of unique clients
with open subscriptions
- `rpc.max_subscriptions_per_client`sets the maximum number of unique
subscriptions from a given client
- `rpc.timeout_broadcast_tx_commit` sets the time to wait for a tx to be committed during `/broadcast_tx_commit`
- [types] [\#2920](https://github.com/tendermint/tendermint/issues/2920) Add `time_iota_ms` to block's consensus parameters (not exposed to the application)
- [lite] [\#3269](https://github.com/tendermint/tendermint/issues/3269) Add `/unsubscribe_all` endpoint to unsubscribe from all events
- [mempool] [\#3079](https://github.com/tendermint/tendermint/issues/3079) Bound mempool memory usage via the `mempool.max_txs_bytes` configuration value. Set to 1GB by default. The mempool's current `txs_total_bytes` is exposed via `total_bytes` field in
`/num_unconfirmed_txs` and `/unconfirmed_txs` RPC endpoints.
- [config] [\#2920](https://github.com/tendermint/tendermint/issues/2920) Remove `consensus.blocktime_iota` parameter
- [genesis] [\#2920](https://github.com/tendermint/tendermint/issues/2920) Add `time_iota_ms` to block's consensus parameters (not exposed to the application)
- [lite] add `/unsubscribe_all` endpoint, which allows you to unsubscribe from all events
### IMPROVEMENTS:
- [all] [\#3385](https://github.com/tendermint/tendermint/issues/3385), [\#3386](https://github.com/tendermint/tendermint/issues/3386) Various linting improvements
- [crypto] [\#3371](https://github.com/tendermint/tendermint/issues/3371) Copy in secp256k1 package from go-ethereum instead of importing
go-ethereum (@silasdavis)
- [deps] [\#3382](https://github.com/tendermint/tendermint/issues/3382) Don't pin repos without releases
- [deps] [\#3357](https://github.com/tendermint/tendermint/issues/3357), [\#3389](https://github.com/tendermint/tendermint/issues/3389), [\#3392](https://github.com/tendermint/tendermint/issues/3392) Update gogo/protobuf, golang/protobuf, levigo, golang.org/x/crypto
- [libs/common] [\#3238](https://github.com/tendermint/tendermint/issues/3238) exit with zero (0) code upon receiving SIGTERM/SIGINT
- [libs/db] [\#3378](https://github.com/tendermint/tendermint/issues/3378) CLevelDB#Stats now returns the following properties:
- leveldb.num-files-at-level{n}
@@ -57,11 +81,14 @@ Note our HttpClient's interface got updated to reflect the pubsub changes and no
- [privval] [\#3351](https://github.com/tendermint/tendermint/pull/3351) First part of larger refactoring that clarifies and separates concerns in the privval package.
### BUG FIXES:
- [p2p/conn] [\#3347](https://github.com/tendermint/tendermint/issues/3347) Reject all-zero shared secrets in the Diffie-Hellman step of secret-connection
- [libs/pubsub] [\#951](https://github.com/tendermint/tendermint/issues/951), [\#1880](https://github.com/tendermint/tendermint/issues/1880) use non-blocking send when dispatching messages [ADR-33](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-033-pubsub.md)
- [p2p] [\#3369](https://github.com/tendermint/tendermint/issues/3369) do not panic when filter times out
- [cmd] [\#3408](https://github.com/tendermint/tendermint/issues/3408) Fix `testnet` command's panic when creating non-validator configs (using `--n` flag) (@srmo)
- [blockchain] [\#3358](https://github.com/tendermint/tendermint/pull/3358) Fix timer leak in `BlockPool` (@guagualvcha)
- [cmd] [\#3408](https://github.com/tendermint/tendermint/issues/3408) Fix `testnet` command's panic when creating non-validator configs (using `--n` flag) (@srmo)
- [libs/db/remotedb/grpcdb] [\#3402](https://github.com/tendermint/tendermint/issues/3402) Close Iterator/ReverseIterator after use
- [libs/pubsub] [\#951](https://github.com/tendermint/tendermint/issues/951), [\#1880](https://github.com/tendermint/tendermint/issues/1880) Use non-blocking send when dispatching messages [ADR-33](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-033-pubsub.md)
- [lite] [\#3364](https://github.com/tendermint/tendermint/issues/3364) Fix `/validators` and `/abci_query` proxy endpoints
(@guagualvcha)
- [p2p/conn] [\#3347](https://github.com/tendermint/tendermint/issues/3347) Reject all-zero shared secrets in the Diffie-Hellman step of secret-connection
- [p2p] [\#3369](https://github.com/tendermint/tendermint/issues/3369) Do not panic when filter times out
- [p2p] [\#3359](https://github.com/tendermint/tendermint/pull/3359) Fix reconnecting report duplicate ID error due to race condition between adding peer to peerSet and starting it (@guagualvcha)
## v0.30.2
@@ -78,7 +105,7 @@ fix here.
### BREAKING CHANGES:
* Go API
- [libs/db] [\#3842](https://github.com/cosmos/cosmos-sdk/issues/3842) Add Close() method to Batch interface (@Stumble)
- [libs/db] [\#3842](https://github.com/cosmos/cosmos-sdk/issues/3842) Add Close() method to Batch interface (@Stumble)
### BUG FIXES:
- [libs/db] [\#3842](https://github.com/cosmos/cosmos-sdk/issues/3842) Fix CLevelDB memory leak (@Stumble)

View File

@@ -19,4 +19,3 @@
### IMPROVEMENTS:
### BUG FIXES:

View File

@@ -5,8 +5,15 @@ a newer version of Tendermint Core.
## v0.31.0
Since the pubsub no longer blocks on sending, some WS clients might stop working as expected.
If your WS client is not consuming events fast enough, Tendermint can terminate the subscription.
This release contains a breaking change to the behaviour of the pubsub system.
It also contains some minor breaking changes in the Go API and ABCI.
There are no changes to the block or p2p protocols, so v0.31.0 should work fine
with blockchains created from the v0.30 series.
### RPC
The pubsub no longer blocks on publishing. This may cause some WebSocket (WS) clients to stop working as expected.
If your WS client is not consuming events fast enough, Tendermint can terminate the subscription.
In this case, the WS client will receive an error with description:
```json
@@ -19,8 +26,24 @@ In this case, the WS client will receive an error with description:
"data": "subscription was cancelled (reason: client is not pulling messages fast enough)" // or "subscription was cancelled (reason: Tendermint exited)"
}
}
Additionally, there are now limits on the number of subscribers and
subscriptions that can be active at once. See the new
`rpc.max_subscription_clients` and `rpc.max_subscriptions_per_client` values to
configure this.
```
### Applications
Simple rename of `ConsensusParams.BlockSize` to `ConsensusParams.Block`.
The `ConsensusParams.Block.TimeIotaMS` field was also removed. It's configured
in the ConsensusParsm in genesis.
### Go API
See the [CHANGELOG](CHANGELOG.md). These are relatively straight forward.
## v0.30.0
This release contains a breaking change to both the block and p2p protocols,

View File

@@ -7,7 +7,6 @@ import (
"time"
"github.com/pkg/errors"
rpcserver "github.com/tendermint/tendermint/rpc/lib/server"
)
const (
@@ -336,6 +335,9 @@ type RPCConfig struct {
MaxSubscriptionsPerClient int `mapstructure:"max_subscriptions_per_client"`
// How long to wait for a tx to be committed during /broadcast_tx_commit
// WARNING: Using a value larger than 10s will result in increasing the
// global HTTP write timeout, which applies to all connections and endpoints.
// See https://github.com/tendermint/tendermint/issues/3435
TimeoutBroadcastTxCommit time.Duration `mapstructure:"timeout_broadcast_tx_commit"`
}
@@ -385,9 +387,6 @@ func (cfg *RPCConfig) ValidateBasic() error {
if cfg.TimeoutBroadcastTxCommit < 0 {
return errors.New("timeout_broadcast_tx_commit can't be negative")
}
if cfg.TimeoutBroadcastTxCommit > rpcserver.WriteTimeout {
return fmt.Errorf("timeout_broadcast_tx_commit can't be greater than rpc server's write timeout: %v", rpcserver.WriteTimeout)
}
return nil
}

View File

@@ -176,6 +176,9 @@ max_subscription_clients = {{ .RPC.MaxSubscriptionClients }}
max_subscriptions_per_client = {{ .RPC.MaxSubscriptionsPerClient }}
# How long to wait for a tx to be committed during /broadcast_tx_commit.
# WARNING: Using a value larger than 10s will result in increasing the
# global HTTP write timeout, which applies to all connections and endpoints.
# See https://github.com/tendermint/tendermint/issues/3435
timeout_broadcast_tx_commit = "{{ .RPC.TimeoutBroadcastTxCommit }}"
##### peer to peer configuration options #####

View File

@@ -324,12 +324,7 @@ func (h *Handshaker) ReplayBlocks(
}
if res.ConsensusParams != nil {
// Preserve TimeIotaMs since it's not exposed to the application.
timeIotaMs := state.ConsensusParams.Block.TimeIotaMs
{
state.ConsensusParams = types.PB2TM.ConsensusParams(res.ConsensusParams)
}
state.ConsensusParams.Block.TimeIotaMs = timeIotaMs
state.ConsensusParams = types.PB2TM.ConsensusParams(res.ConsensusParams, state.ConsensusParams.Block.TimeIotaMs)
}
sm.SaveState(h.stateDB, state)
}

View File

@@ -8,7 +8,7 @@ services:
- "26656-26657:26656-26657"
environment:
- ID=0
- LOG=$${LOG:-tendermint.log}
- LOG=${LOG:-tendermint.log}
volumes:
- ./build:/tendermint:Z
networks:
@@ -22,7 +22,7 @@ services:
- "26659-26660:26656-26657"
environment:
- ID=1
- LOG=$${LOG:-tendermint.log}
- LOG=${LOG:-tendermint.log}
volumes:
- ./build:/tendermint:Z
networks:
@@ -34,7 +34,7 @@ services:
image: "tendermint/localnode"
environment:
- ID=2
- LOG=$${LOG:-tendermint.log}
- LOG=${LOG:-tendermint.log}
ports:
- "26661-26662:26656-26657"
volumes:
@@ -48,7 +48,7 @@ services:
image: "tendermint/localnode"
environment:
- ID=3
- LOG=$${LOG:-tendermint.log}
- LOG=${LOG:-tendermint.log}
ports:
- "26663-26664:26656-26657"
volumes:

View File

@@ -122,6 +122,9 @@ max_subscription_clients = 100
max_subscriptions_per_client = 5
# How long to wait for a tx to be committed during /broadcast_tx_commit.
# WARNING: Using a value larger than 10s will result in increasing the
# global HTTP write timeout, which applies to all connections and endpoints.
# See https://github.com/tendermint/tendermint/issues/3435
timeout_broadcast_tx_commit = "10s"
##### peer to peer configuration options #####

View File

@@ -138,6 +138,7 @@ func (s *server) SetSync(ctx context.Context, in *protodb.Entity) (*protodb.Noth
func (s *server) Iterator(query *protodb.Entity, dis protodb.DB_IteratorServer) error {
it := s.db.Iterator(query.Start, query.End)
defer it.Close()
return s.handleIterator(it, dis.Send)
}
@@ -162,6 +163,7 @@ func (s *server) handleIterator(it db.Iterator, sendFunc func(*protodb.Iterator)
func (s *server) ReverseIterator(query *protodb.Entity, dis protodb.DB_ReverseIteratorServer) error {
it := s.db.ReverseIterator(query.Start, query.End)
defer it.Close()
return s.handleIterator(it, dis.Send)
}

View File

@@ -45,11 +45,13 @@ func StartProxy(c rpcclient.Client, listenAddr string, logger log.Logger, maxOpe
core.SetLogger(logger)
mux.HandleFunc(wsEndpoint, wm.WebsocketHandler)
l, err := rpcserver.Listen(listenAddr, rpcserver.Config{MaxOpenConnections: maxOpenConnections})
config := rpcserver.DefaultConfig()
config.MaxOpenConnections = maxOpenConnections
l, err := rpcserver.Listen(listenAddr, config)
if err != nil {
return err
}
return rpcserver.StartHTTPServer(l, mux, logger)
return rpcserver.StartHTTPServer(l, mux, logger, config)
}
// RPCRoutes just routes everything to the given client, as if it were

View File

@@ -689,9 +689,18 @@ func (n *Node) startRPC() ([]net.Listener, error) {
mux.HandleFunc("/websocket", wm.WebsocketHandler)
rpcserver.RegisterRPCFuncs(mux, rpccore.Routes, coreCodec, rpcLogger)
config := rpcserver.DefaultConfig()
config.MaxOpenConnections = n.config.RPC.MaxOpenConnections
// If necessary adjust global WriteTimeout to ensure it's greater than
// TimeoutBroadcastTxCommit.
// See https://github.com/tendermint/tendermint/issues/3435
if config.WriteTimeout <= n.config.RPC.TimeoutBroadcastTxCommit {
config.WriteTimeout = n.config.RPC.TimeoutBroadcastTxCommit + 1*time.Second
}
listener, err := rpcserver.Listen(
listenAddr,
rpcserver.Config{MaxOpenConnections: n.config.RPC.MaxOpenConnections},
config,
)
if err != nil {
return nil, err
@@ -711,6 +720,7 @@ func (n *Node) startRPC() ([]net.Listener, error) {
listener,
rootHandler,
rpcLogger,
config,
)
listeners[i] = listener
}
@@ -718,8 +728,9 @@ func (n *Node) startRPC() ([]net.Listener, error) {
// we expose a simplified api over grpc for convenience to app devs
grpcListenAddr := n.config.RPC.GRPCListenAddress
if grpcListenAddr != "" {
listener, err := rpcserver.Listen(
grpcListenAddr, rpcserver.Config{MaxOpenConnections: n.config.RPC.GRPCMaxOpenConnections})
config := rpcserver.DefaultConfig()
config.MaxOpenConnections = n.config.RPC.MaxOpenConnections
listener, err := rpcserver.Listen(grpcListenAddr, config)
if err != nil {
return nil, err
}

View File

@@ -105,8 +105,7 @@ func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, er
if err != nil {
return nil, errors.Wrap(err, "failed to parse query")
}
subCtx, cancel := context.WithTimeout(context.Background(), subscribeTimeout)
subCtx, cancel := context.WithTimeout(ctx.Context(), SubscribeTimeout)
defer cancel()
sub, err := eventBus.Subscribe(subCtx, addr, q)
if err != nil {

View File

@@ -197,7 +197,7 @@ func BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadc
}
// Subscribe to tx being committed in block.
subCtx, cancel := context.WithTimeout(context.Background(), subscribeTimeout)
subCtx, cancel := context.WithTimeout(ctx.Context(), SubscribeTimeout)
defer cancel()
q := types.EventQueryTxFor(tx)
deliverTxSub, err := eventBus.Subscribe(subCtx, subscriber, q)

View File

@@ -1,6 +1,8 @@
package core
import (
"time"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/consensus"
"github.com/tendermint/tendermint/crypto"
@@ -9,7 +11,6 @@ import (
mempl "github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/proxy"
rpcserver "github.com/tendermint/tendermint/rpc/lib/server"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/state/txindex"
"github.com/tendermint/tendermint/types"
@@ -19,9 +20,11 @@ const (
// see README
defaultPerPage = 30
maxPerPage = 100
)
var subscribeTimeout = rpcserver.WriteTimeout / 2
// SubscribeTimeout is the maximum time we wait to subscribe for an event.
// must be less than the server's write timeout (see rpcserver.DefaultConfig)
SubscribeTimeout = 5 * time.Second
)
//----------------------------------------------
// These interfaces are used by RPC and must be thread safe

View File

@@ -121,11 +121,12 @@ func setup() {
wm := server.NewWebsocketManager(Routes, RoutesCdc, server.ReadWait(5*time.Second), server.PingPeriod(1*time.Second))
wm.SetLogger(tcpLogger)
mux.HandleFunc(websocketEndpoint, wm.WebsocketHandler)
listener1, err := server.Listen(tcpAddr, server.Config{})
config := server.DefaultConfig()
listener1, err := server.Listen(tcpAddr, config)
if err != nil {
panic(err)
}
go server.StartHTTPServer(listener1, mux, tcpLogger)
go server.StartHTTPServer(listener1, mux, tcpLogger, config)
unixLogger := logger.With("socket", "unix")
mux2 := http.NewServeMux()
@@ -133,11 +134,11 @@ func setup() {
wm = server.NewWebsocketManager(Routes, RoutesCdc)
wm.SetLogger(unixLogger)
mux2.HandleFunc(websocketEndpoint, wm.WebsocketHandler)
listener2, err := server.Listen(unixAddr, server.Config{})
listener2, err := server.Listen(unixAddr, config)
if err != nil {
panic(err)
}
go server.StartHTTPServer(listener2, mux2, unixLogger)
go server.StartHTTPServer(listener2, mux2, unixLogger, config)
// wait for servers to start
time.Sleep(time.Second * 2)

View File

@@ -2,6 +2,7 @@ package rpcserver
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"fmt"
@@ -439,6 +440,9 @@ type wsConnection struct {
// callback which is called upon disconnect
onDisconnect func(remoteAddr string)
ctx context.Context
cancel context.CancelFunc
}
// NewWSConnection wraps websocket.Conn.
@@ -532,6 +536,10 @@ func (wsc *wsConnection) OnStop() {
if wsc.onDisconnect != nil {
wsc.onDisconnect(wsc.remoteAddr)
}
if wsc.ctx != nil {
wsc.cancel()
}
}
// GetRemoteAddr returns the remote address of the underlying connection.
@@ -569,6 +577,16 @@ func (wsc *wsConnection) Codec() *amino.Codec {
return wsc.cdc
}
// Context returns the connection's context.
// The context is canceled when the client's connection closes.
func (wsc *wsConnection) Context() context.Context {
if wsc.ctx != nil {
return wsc.ctx
}
wsc.ctx, wsc.cancel = context.WithCancel(context.Background())
return wsc.ctx
}
// Read from the socket and subscribe to or unsubscribe from events
func (wsc *wsConnection) readRoutine() {
defer func() {

View File

@@ -18,9 +18,23 @@ import (
types "github.com/tendermint/tendermint/rpc/lib/types"
)
// Config is an RPC server configuration.
// Config is a RPC server configuration.
type Config struct {
// see netutil.LimitListener
MaxOpenConnections int
// mirrors http.Server#ReadTimeout
ReadTimeout time.Duration
// mirrors http.Server#WriteTimeout
WriteTimeout time.Duration
}
// DefaultConfig returns a default configuration.
func DefaultConfig() *Config {
return &Config{
MaxOpenConnections: 0, // unlimited
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
}
const (
@@ -30,25 +44,17 @@ const (
// same as the net/http default
maxHeaderBytes = 1 << 20
// Timeouts for reading/writing to the http connection.
// Public so handlers can read them -
// /broadcast_tx_commit has it's own timeout, which should
// be less than the WriteTimeout here.
// TODO: use a config instead.
ReadTimeout = 3 * time.Second
WriteTimeout = 20 * time.Second
)
// StartHTTPServer takes a listener and starts an HTTP server with the given handler.
// It wraps handler with RecoverAndLogHandler.
// NOTE: This function blocks - you may want to call it in a go-routine.
func StartHTTPServer(listener net.Listener, handler http.Handler, logger log.Logger) error {
func StartHTTPServer(listener net.Listener, handler http.Handler, logger log.Logger, config *Config) error {
logger.Info(fmt.Sprintf("Starting RPC HTTP server on %s", listener.Addr()))
s := &http.Server{
Handler: RecoverAndLogHandler(maxBytesHandler{h: handler, n: maxBodyBytes}, logger),
ReadTimeout: ReadTimeout,
WriteTimeout: WriteTimeout,
ReadTimeout: config.ReadTimeout,
WriteTimeout: config.WriteTimeout,
MaxHeaderBytes: maxHeaderBytes,
}
err := s.Serve(listener)
@@ -64,13 +70,14 @@ func StartHTTPAndTLSServer(
handler http.Handler,
certFile, keyFile string,
logger log.Logger,
config *Config,
) error {
logger.Info(fmt.Sprintf("Starting RPC HTTPS server on %s (cert: %q, key: %q)",
listener.Addr(), certFile, keyFile))
s := &http.Server{
Handler: RecoverAndLogHandler(maxBytesHandler{h: handler, n: maxBodyBytes}, logger),
ReadTimeout: ReadTimeout,
WriteTimeout: WriteTimeout,
ReadTimeout: config.ReadTimeout,
WriteTimeout: config.WriteTimeout,
MaxHeaderBytes: maxHeaderBytes,
}
err := s.ServeTLS(listener, certFile, keyFile)
@@ -180,7 +187,7 @@ func (h maxBytesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Listen starts a new net.Listener on the given address.
// It returns an error if the address is invalid or the call to Listen() fails.
func Listen(addr string, config Config) (listener net.Listener, err error) {
func Listen(addr string, config *Config) (listener net.Listener, err error) {
parts := strings.SplitN(addr, "://", 2)
if len(parts) != 2 {
return nil, errors.Errorf(

View File

@@ -30,10 +30,12 @@ func TestMaxOpenConnections(t *testing.T) {
time.Sleep(10 * time.Millisecond)
fmt.Fprint(w, "some body")
})
l, err := Listen("tcp://127.0.0.1:0", Config{MaxOpenConnections: max})
config := DefaultConfig()
config.MaxOpenConnections = max
l, err := Listen("tcp://127.0.0.1:0", config)
require.NoError(t, err)
defer l.Close()
go StartHTTPServer(l, mux, log.TestingLogger())
go StartHTTPServer(l, mux, log.TestingLogger(), config)
// Make N GET calls to the server.
attempts := max * 2
@@ -64,15 +66,17 @@ func TestMaxOpenConnections(t *testing.T) {
}
func TestStartHTTPAndTLSServer(t *testing.T) {
config := DefaultConfig()
config.MaxOpenConnections = 1
// set up fixtures
listenerAddr := "tcp://0.0.0.0:0"
listener, err := Listen(listenerAddr, Config{MaxOpenConnections: 1})
listener, err := Listen(listenerAddr, config)
require.NoError(t, err)
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {})
// test failure
err = StartHTTPAndTLSServer(listener, mux, "", "", log.TestingLogger())
err = StartHTTPAndTLSServer(listener, mux, "", "", log.TestingLogger(), config)
require.IsType(t, (*os.PathError)(nil), err)
// TODO: test that starting the server can actually work

View File

@@ -36,9 +36,10 @@ func main() {
cmn.TrapSignal(logger, func() {})
rpcserver.RegisterRPCFuncs(mux, routes, cdc, logger)
listener, err := rpcserver.Listen("0.0.0.0:8008", rpcserver.Config{})
config := rpcserver.DefaultConfig()
listener, err := rpcserver.Listen("0.0.0.0:8008", config)
if err != nil {
cmn.Exit(err.Error())
}
rpcserver.StartHTTPServer(listener, mux, logger)
rpcserver.StartHTTPServer(listener, mux, logger, config)
}

View File

@@ -1,6 +1,7 @@
package rpctypes
import (
"context"
"encoding/json"
"fmt"
"net/http"
@@ -243,6 +244,8 @@ type WSRPCConnection interface {
TryWriteRPCResponse(resp RPCResponse) bool
// Codec returns an Amino codec used.
Codec() *amino.Codec
// Context returns the connection's context.
Context() context.Context
}
// Context is the first parameter for all functions. It carries a json-rpc
@@ -260,8 +263,12 @@ type Context struct {
HTTPReq *http.Request
}
// RemoteAddr returns either HTTPReq#RemoteAddr or result of the
// WSConn#GetRemoteAddr().
// RemoteAddr returns the remote address (usually a string "IP:port").
// If neither HTTPReq nor WSConn is set, an empty string is returned.
// HTTP:
// http.Request#RemoteAddr
// WS:
// result of GetRemoteAddr
func (ctx *Context) RemoteAddr() string {
if ctx.HTTPReq != nil {
return ctx.HTTPReq.RemoteAddr
@@ -271,6 +278,22 @@ func (ctx *Context) RemoteAddr() string {
return ""
}
// Context returns the request's context.
// The returned context is always non-nil; it defaults to the background context.
// HTTP:
// The context is canceled when the client's connection closes, the request
// is canceled (with HTTP/2), or when the ServeHTTP method returns.
// WS:
// The context is canceled when the client's connections closes.
func (ctx *Context) Context() context.Context {
if ctx.HTTPReq != nil {
return ctx.HTTPReq.Context()
} else if ctx.WSConn != nil {
return ctx.WSConn.Context()
}
return context.Background()
}
//----------------------------------------
// SOCKETS

View File

@@ -17,11 +17,12 @@ func startRPC(listenAddr string, m *monitor.Monitor, logger log.Logger) net.List
wm := rpc.NewWebsocketManager(routes, nil)
mux.HandleFunc("/websocket", wm.WebsocketHandler)
rpc.RegisterRPCFuncs(mux, routes, cdc, logger)
listener, err := rpc.Listen(listenAddr, rpc.Config{})
config := rpc.DefaultConfig()
listener, err := rpc.Listen(listenAddr, config)
if err != nil {
panic(err)
}
go rpc.StartHTTPServer(listener, mux, logger)
go rpc.StartHTTPServer(listener, mux, logger, config)
return listener
}

View File

@@ -221,7 +221,9 @@ func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*Validator, error)
return tmVals, nil
}
func (pb2tm) ConsensusParams(csp *abci.ConsensusParams) ConsensusParams {
// BlockParams.TimeIotaMs is not exposed to the application. Therefore a caller
// must provide it.
func (pb2tm) ConsensusParams(csp *abci.ConsensusParams, blockTimeIotaMs int64) ConsensusParams {
params := ConsensusParams{
Block: BlockParams{},
Evidence: EvidenceParams{},
@@ -231,8 +233,9 @@ func (pb2tm) ConsensusParams(csp *abci.ConsensusParams) ConsensusParams {
// we must defensively consider any structs may be nil
if csp.Block != nil {
params.Block = BlockParams{
MaxBytes: csp.Block.MaxBytes,
MaxGas: csp.Block.MaxGas,
MaxBytes: csp.Block.MaxBytes,
MaxGas: csp.Block.MaxGas,
TimeIotaMs: blockTimeIotaMs,
}
}

View File

@@ -64,9 +64,7 @@ func TestABCIValidators(t *testing.T) {
func TestABCIConsensusParams(t *testing.T) {
cp := DefaultConsensusParams()
abciCP := TM2PB.ConsensusParams(cp)
cp2 := PB2TM.ConsensusParams(abciCP)
// TimeIotaMs is not exposed to the application.
cp2.Block.TimeIotaMs = cp.Block.TimeIotaMs
cp2 := PB2TM.ConsensusParams(abciCP, cp.Block.TimeIotaMs)
assert.Equal(t, *cp, cp2)
}