Browse Source

privval: Query validator key (#5876)

## Description

- Query validator key when a remote signer is used. This is supported gRPC remote signing and filePV only. 


Closes: #3009
pull/5891/head
Marko 4 years ago
committed by GitHub
parent
commit
f05788e632
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 37 deletions
  1. +2
    -1
      CHANGELOG_PENDING.md
  2. +31
    -8
      cmd/tendermint/commands/show_validator.go
  3. +3
    -28
      node/node.go
  4. +38
    -0
      privval/grpc/util.go

+ 2
- 1
CHANGELOG_PENDING.md View File

@ -49,7 +49,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
- [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] \#5725 add gRPC support to private validator.
- [privval] \#5725 Add gRPC support to private validator.
- [privval] \#5876 `tendermint show-validator` will query the remote signer if gRPC is being used (@marbar3778)
- [abci/client] \#5673 `Async` requests return an error if queue is full (@melekes)
- [mempool] \#5673 Cancel `CheckTx` requests if RPC client disconnects or times out (@melekes)
- [abci] \#5706 Added `AbciVersion` to `RequestInfo` allowing applications to check ABCI version when connecting to Tendermint. (@marbar3778)


+ 31
- 8
cmd/tendermint/commands/show_validator.go View File

@ -5,9 +5,12 @@ import (
"github.com/spf13/cobra"
"github.com/tendermint/tendermint/crypto"
tmjson "github.com/tendermint/tendermint/libs/json"
tmnet "github.com/tendermint/tendermint/libs/net"
tmos "github.com/tendermint/tendermint/libs/os"
"github.com/tendermint/tendermint/privval"
tmgrpc "github.com/tendermint/tendermint/privval/grpc"
)
// ShowValidatorCmd adds capabilities for showing the validator info.
@ -20,16 +23,36 @@ var ShowValidatorCmd = &cobra.Command{
}
func showValidator(cmd *cobra.Command, args []string) error {
keyFilePath := config.PrivValidatorKeyFile()
if !tmos.FileExists(keyFilePath) {
return fmt.Errorf("private validator file %s does not exist", keyFilePath)
}
var (
pubKey crypto.PubKey
err error
)
pv := privval.LoadFilePV(keyFilePath, config.PrivValidatorStateFile())
//TODO: remove once gRPC is the only supported protocol
protocol, _ := tmnet.ProtocolAndAddress(config.PrivValidatorListenAddr)
switch protocol {
case "grpc":
pvsc, err := tmgrpc.DialRemoteSigner(config, config.ChainID(), logger)
if err != nil {
return fmt.Errorf("can't connect to remote validator %w", err)
}
pubKey, err = pvsc.GetPubKey()
if err != nil {
return fmt.Errorf("can't get pubkey: %w", err)
}
default:
pubKey, err := pv.GetPubKey()
if err != nil {
return fmt.Errorf("can't get pubkey: %w", err)
keyFilePath := config.PrivValidatorKeyFile()
if !tmos.FileExists(keyFilePath) {
return fmt.Errorf("private validator file %s does not exist", keyFilePath)
}
pv := privval.LoadFilePV(keyFilePath, config.PrivValidatorStateFile())
pubKey, err = pv.GetPubKey()
if err != nil {
return fmt.Errorf("can't get pubkey: %w", err)
}
}
bz, err := tmjson.Marshal(pubKey)


+ 3
- 28
node/node.go View File

@ -10,11 +10,9 @@ import (
_ "net/http/pprof" // nolint: gosec // securely exposed on separate, optional port
"time"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/rs/cors"
"google.golang.org/grpc"
dbm "github.com/tendermint/tm-db"
@ -678,11 +676,11 @@ func NewNode(config *cfg.Config,
// If an address is provided, listen on the socket for a connection from an
// external signing process.
if config.PrivValidatorListenAddr != "" {
protocol, address := tmnet.ProtocolAndAddress(config.PrivValidatorListenAddr)
protocol, _ := tmnet.ProtocolAndAddress(config.PrivValidatorListenAddr)
// FIXME: we should start services inside OnStart
switch protocol {
case "grpc":
privValidator, err = createAndStartPrivValidatorGRPCClient(config, address, genDoc.ChainID, logger)
privValidator, err = createAndStartPrivValidatorGRPCClient(config, genDoc.ChainID, logger)
if err != nil {
return nil, fmt.Errorf("error with private validator grpc client: %w", err)
}
@ -1435,33 +1433,10 @@ func createAndStartPrivValidatorSocketClient(
func createAndStartPrivValidatorGRPCClient(
config *cfg.Config,
address,
chainID string,
logger log.Logger,
) (types.PrivValidator, error) {
var transportSecurity grpc.DialOption
if config.BaseConfig.ArePrivValidatorClientSecurityOptionsPresent() {
transportSecurity = tmgrpc.GenerateTLS(config.PrivValidatorClientCertificateFile(),
config.PrivValidatorClientKeyFile(), config.PrivValidatorRootCAFile(), logger)
} else {
transportSecurity = grpc.WithInsecure()
logger.Info("Using an insecure gRPC connection!")
}
dialOptions := tmgrpc.DefaultDialOptions()
if config.Instrumentation.Prometheus {
grpcMetrics := grpc_prometheus.DefaultClientMetrics
dialOptions = append(dialOptions, grpc.WithUnaryInterceptor(grpcMetrics.UnaryClientInterceptor()))
}
dialOptions = append(dialOptions, transportSecurity)
ctx := context.Background()
conn, err := grpc.DialContext(ctx, address, dialOptions...)
if err != nil {
logger.Error("unable to connect to server", "target", address, "err", err)
}
pvsc, err := tmgrpc.NewSignerClient(conn, chainID, logger)
pvsc, err := tmgrpc.DialRemoteSigner(config, chainID, logger)
if err != nil {
return nil, fmt.Errorf("failed to start private validator: %w", err)
}


+ 38
- 0
privval/grpc/util.go View File

@ -1,6 +1,7 @@
package grpc
import (
"context"
"crypto/tls"
"crypto/x509"
"io/ioutil"
@ -8,7 +9,11 @@ import (
"time"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/log"
tmnet "github.com/tendermint/tendermint/libs/net"
grpc "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/keepalive"
@ -80,3 +85,36 @@ func GenerateTLS(certPath, keyPath, ca string, log log.Logger) grpc.DialOption {
return grpc.WithTransportCredentials(transportCreds)
}
// DialRemoteSigner is a generalized function to dial the gRPC server.
func DialRemoteSigner(
config *cfg.Config,
chainID string,
logger log.Logger,
) (*SignerClient, error) {
var transportSecurity grpc.DialOption
if config.BaseConfig.ArePrivValidatorClientSecurityOptionsPresent() {
transportSecurity = GenerateTLS(config.PrivValidatorClientCertificateFile(),
config.PrivValidatorClientKeyFile(), config.PrivValidatorRootCAFile(), logger)
} else {
transportSecurity = grpc.WithInsecure()
logger.Info("Using an insecure gRPC connection!")
}
dialOptions := DefaultDialOptions()
if config.Instrumentation.Prometheus {
grpcMetrics := grpc_prometheus.DefaultClientMetrics
dialOptions = append(dialOptions, grpc.WithUnaryInterceptor(grpcMetrics.UnaryClientInterceptor()))
}
dialOptions = append(dialOptions, transportSecurity)
ctx := context.Background()
_, address := tmnet.ProtocolAndAddress(config.PrivValidatorListenAddr)
conn, err := grpc.DialContext(ctx, address, dialOptions...)
if err != nil {
logger.Error("unable to connect to server", "target", address, "err", err)
}
return NewSignerClient(conn, chainID, logger)
}

Loading…
Cancel
Save