Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

privval: increase read/write timeout to 5s and calculate ping interval based on it #5638

Merged
merged 7 commits into from Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG_PENDING.md
Expand Up @@ -25,8 +25,9 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
### IMPROVEMENTS

- [crypto/ed25519] \#5632 Adopt zip215 `ed25519` verification. (@marbar3778)
- [privval] \#5603 Add `--key` to `init`, `gen_validator`, `testnet` & `unsafe_reset_priv_validator` for use in generating `secp256k1` keys.
- [privval] \#5603 Add `--key` to `init`, `gen_validator`, `testnet` & `unsafe_reset_priv_validator` for use in generating `secp256k1` keys.

### BUG FIXES

- [types] \#5523 Change json naming of `PartSetHeader` within `BlockID` from `parts` to `part_set_header` (@marbar3778)
- [privval] \#5638 Increase read/write timeout to 5s and calculate ping interval based on it (@JoeKash)
20 changes: 11 additions & 9 deletions privval/signer_dialer_endpoint.go
Expand Up @@ -15,24 +15,26 @@ const (
// SignerServiceEndpointOption sets an optional parameter on the SignerDialerEndpoint.
type SignerServiceEndpointOption func(*SignerDialerEndpoint)

// SignerDialerEndpointTimeoutReadWrite sets the read and write timeout for connections
// from external signing processes.
// SignerDialerEndpointTimeoutReadWrite sets the read and write timeout for
// connections from client processes.
func SignerDialerEndpointTimeoutReadWrite(timeout time.Duration) SignerServiceEndpointOption {
return func(ss *SignerDialerEndpoint) { ss.timeoutReadWrite = timeout }
}

// SignerDialerEndpointConnRetries sets the amount of attempted retries to acceptNewConnection.
// SignerDialerEndpointConnRetries sets the amount of attempted retries to
// acceptNewConnection.
func SignerDialerEndpointConnRetries(retries int) SignerServiceEndpointOption {
return func(ss *SignerDialerEndpoint) { ss.maxConnRetries = retries }
}

// SignerDialerEndpointRetryWaitInterval sets the retry wait interval to a custom value
// SignerDialerEndpointRetryWaitInterval sets the retry wait interval to a
// custom value.
func SignerDialerEndpointRetryWaitInterval(interval time.Duration) SignerServiceEndpointOption {
return func(ss *SignerDialerEndpoint) { ss.retryWait = interval }
}

// SignerDialerEndpoint dials using its dialer and responds to any
// signature requests using its privVal.
// SignerDialerEndpoint dials using its dialer and responds to any signature
// requests using its privVal.
type SignerDialerEndpoint struct {
signerEndpoint

Expand All @@ -57,13 +59,13 @@ func NewSignerDialerEndpoint(
maxConnRetries: defaultMaxDialRetries,
}

sd.BaseService = *service.NewBaseService(logger, "SignerDialerEndpoint", sd)
sd.signerEndpoint.timeoutReadWrite = defaultTimeoutReadWriteSeconds * time.Second

for _, optionFunc := range options {
optionFunc(sd)
}

sd.BaseService = *service.NewBaseService(logger, "SignerDialerEndpoint", sd)
sd.signerEndpoint.timeoutReadWrite = defaultTimeoutReadWriteSeconds * time.Second

return sd
}

Expand Down
2 changes: 1 addition & 1 deletion privval/signer_endpoint.go
Expand Up @@ -12,7 +12,7 @@ import (
)

const (
defaultTimeoutReadWriteSeconds = 3
defaultTimeoutReadWriteSeconds = 5
)

type signerEndpoint struct {
Expand Down
39 changes: 30 additions & 9 deletions privval/signer_listener_endpoint.go
Expand Up @@ -11,11 +11,22 @@ import (
privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval"
)

// SignerValidatorEndpointOption sets an optional parameter on the SocketVal.
type SignerValidatorEndpointOption func(*SignerListenerEndpoint)
// SignerListenerEndpointOption sets an optional parameter on the SignerListenerEndpoint.
type SignerListenerEndpointOption func(*SignerListenerEndpoint)

// SignerListenerEndpointTimeoutReadWrite sets the read and write timeout for
// connections from external signing processes.
//
// Default: 5s
func SignerListenerEndpointTimeoutReadWrite(timeout time.Duration) SignerListenerEndpointOption {
return func(sl *SignerListenerEndpoint) { sl.signerEndpoint.timeoutReadWrite = timeout }
}

// SignerListenerEndpoint listens for an external process to dial in
// and keeps the connection alive by dropping and reconnecting
// SignerListenerEndpoint listens for an external process to dial in and keeps
// the connection alive by dropping and reconnecting.
//
// The process will send pings every ~3s (read/write timeout * 2/3) to keep the
// connection alive.
type SignerListenerEndpoint struct {
signerEndpoint

Expand All @@ -25,6 +36,7 @@ type SignerListenerEndpoint struct {

timeoutAccept time.Duration
pingTimer *time.Ticker
pingInterval time.Duration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? We're only setting up the timer on construction anyway, so it's not really used for anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to add reset call in the follow up PR

  •   // Reset pingTimer to avoid sending unnecessary pings.
    
  •   sl.pingTimer.Reset(sl.pingInterval)
    

Had to remove it because of go 1.15 requirement.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, got it. 👍


instanceMtx tmsync.Mutex // Ensures instance public methods access, i.e. SendRequest
}
Expand All @@ -33,23 +45,31 @@ type SignerListenerEndpoint struct {
func NewSignerListenerEndpoint(
logger log.Logger,
listener net.Listener,
options ...SignerListenerEndpointOption,
) *SignerListenerEndpoint {
sc := &SignerListenerEndpoint{
sl := &SignerListenerEndpoint{
listener: listener,
timeoutAccept: defaultTimeoutAcceptSeconds * time.Second,
}

sc.BaseService = *service.NewBaseService(logger, "SignerListenerEndpoint", sc)
sc.signerEndpoint.timeoutReadWrite = defaultTimeoutReadWriteSeconds * time.Second
return sc
sl.BaseService = *service.NewBaseService(logger, "SignerListenerEndpoint", sl)
sl.signerEndpoint.timeoutReadWrite = defaultTimeoutReadWriteSeconds * time.Second

for _, optionFunc := range options {
optionFunc(sl)
}

return sl
}

// OnStart implements service.Service.
func (sl *SignerListenerEndpoint) OnStart() error {
sl.connectRequestCh = make(chan struct{})
sl.connectionAvailableCh = make(chan net.Conn)

sl.pingTimer = time.NewTicker(defaultPingPeriodMilliseconds * time.Millisecond)
// NOTE: ping timeout must be less than read/write timeout
sl.pingInterval = time.Duration(sl.signerEndpoint.timeoutReadWrite.Milliseconds()*2/3) * time.Millisecond
sl.pingTimer = time.NewTicker(sl.pingInterval)

go sl.serviceLoop()
go sl.pingLoop()
Expand Down Expand Up @@ -117,6 +137,7 @@ func (sl *SignerListenerEndpoint) ensureConnection(maxWait time.Duration) error
}

// block until connected or timeout
sl.Logger.Info("SignerListener: Blocking for connection")
sl.triggerConnect()
err := sl.WaitConnection(sl.connectionAvailableCh, maxWait)
if err != nil {
Expand Down
6 changes: 5 additions & 1 deletion privval/signer_listener_endpoint_test.go
Expand Up @@ -168,7 +168,11 @@ func newSignerListenerEndpoint(logger log.Logger, addr string, timeoutReadWrite
listener = tcpLn
}

return NewSignerListenerEndpoint(logger, listener)
return NewSignerListenerEndpoint(
logger,
listener,
SignerListenerEndpointTimeoutReadWrite(testTimeoutReadWrite),
)
}

func startListenerEndpointAsync(t *testing.T, sle *SignerListenerEndpoint, endpointIsOpenCh chan struct{}) {
Expand Down
3 changes: 1 addition & 2 deletions privval/socket_listeners.go
Expand Up @@ -9,8 +9,7 @@ import (
)

const (
defaultTimeoutAcceptSeconds = 3
defaultPingPeriodMilliseconds = 100
defaultTimeoutAcceptSeconds = 3
)

// timeoutError can be used to check if an error returned from the netp package
Expand Down