mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-03 11:45:18 +00:00
node: refactor privValidator ext client code & tests (#2895)
* update ConsensusState#OnStop comment * consensus: set logger for WAL in tests * refactor privValidator client code and tests follow-up on https://github.com/tendermint/tendermint/pull/2866
This commit is contained in:
86
node/node.go
86
node/node.go
@@ -3,7 +3,6 @@ package node
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -11,11 +10,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/rs/cors"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
bc "github.com/tendermint/tendermint/blockchain"
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
@@ -148,44 +148,6 @@ type Node struct {
|
||||
prometheusSrv *http.Server
|
||||
}
|
||||
|
||||
func createExternalPrivValidator(listenAddr string, logger log.Logger) (types.PrivValidator, error) {
|
||||
protocol, address := cmn.ProtocolAndAddress(listenAddr)
|
||||
|
||||
var pvsc types.PrivValidator
|
||||
|
||||
switch (protocol) {
|
||||
case "unix":
|
||||
pvsc = privval.NewIPCVal(
|
||||
logger.With("module", "privval"),
|
||||
address,
|
||||
)
|
||||
|
||||
case "tcp":
|
||||
// TODO: persist this key so external signer
|
||||
// can actually authenticate us
|
||||
pvsc = privval.NewTCPVal(
|
||||
logger.With("module", "privval"),
|
||||
listenAddr,
|
||||
ed25519.GenPrivKey(),
|
||||
)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf(
|
||||
"Error creating private validator: expected either tcp or unix "+
|
||||
"protocols, got %s",
|
||||
protocol,
|
||||
)
|
||||
}
|
||||
|
||||
pvServ, _ := pvsc.(cmn.Service)
|
||||
if err := pvServ.Start(); err != nil {
|
||||
return nil, fmt.Errorf("Error starting private validator client: %v", err)
|
||||
}
|
||||
|
||||
return pvsc, nil
|
||||
|
||||
}
|
||||
|
||||
// NewNode returns a new, ready to go, Tendermint Node.
|
||||
func NewNode(config *cfg.Config,
|
||||
privValidator types.PrivValidator,
|
||||
@@ -259,11 +221,12 @@ func NewNode(config *cfg.Config,
|
||||
}
|
||||
|
||||
if config.PrivValidatorListenAddr != "" {
|
||||
// If an address is provided, listen on the socket for a
|
||||
// connection from an external signing process.
|
||||
privValidator, err = createExternalPrivValidator(config.PrivValidatorListenAddr, logger)
|
||||
// If an address is provided, listen on the socket for a connection from an
|
||||
// external signing process.
|
||||
// FIXME: we should start services inside OnStart
|
||||
privValidator, err = createAndStartPrivValidatorSocketClient(config.PrivValidatorListenAddr, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "Error with private validator socket client")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,11 +589,8 @@ func (n *Node) OnStop() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if pvsc, ok := n.privValidator.(cmn.Service); ok {
|
||||
if err := pvsc.Stop(); err != nil {
|
||||
n.Logger.Error("Error stopping priv validator client", "err", err)
|
||||
}
|
||||
pvsc.Stop()
|
||||
}
|
||||
|
||||
if n.prometheusSrv != nil {
|
||||
@@ -884,6 +844,36 @@ func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) {
|
||||
db.SetSync(genesisDocKey, bytes)
|
||||
}
|
||||
|
||||
func createAndStartPrivValidatorSocketClient(
|
||||
listenAddr string,
|
||||
logger log.Logger,
|
||||
) (types.PrivValidator, error) {
|
||||
var pvsc types.PrivValidator
|
||||
|
||||
protocol, address := cmn.ProtocolAndAddress(listenAddr)
|
||||
switch protocol {
|
||||
case "unix":
|
||||
pvsc = privval.NewIPCVal(logger.With("module", "privval"), address)
|
||||
case "tcp":
|
||||
// TODO: persist this key so external signer
|
||||
// can actually authenticate us
|
||||
pvsc = privval.NewTCPVal(logger.With("module", "privval"), listenAddr, ed25519.GenPrivKey())
|
||||
default:
|
||||
return nil, fmt.Errorf(
|
||||
"Wrong listen address: expected either 'tcp' or 'unix' protocols, got %s",
|
||||
protocol,
|
||||
)
|
||||
}
|
||||
|
||||
if pvsc, ok := pvsc.(cmn.Service); ok {
|
||||
if err := pvsc.Start(); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to start")
|
||||
}
|
||||
}
|
||||
|
||||
return pvsc, nil
|
||||
}
|
||||
|
||||
// splitAndTrimEmpty slices s into all subslices separated by sep and returns a
|
||||
// slice of the string s with all leading and trailing Unicode code points
|
||||
// contained in cutset removed. If sep is empty, SplitAndTrim splits after each
|
||||
|
||||
@@ -3,28 +3,28 @@ package node
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
"net"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/abci/example/kvstore"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
sm "github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
)
|
||||
|
||||
func TestNodeStartStop(t *testing.T) {
|
||||
@@ -32,17 +32,16 @@ func TestNodeStartStop(t *testing.T) {
|
||||
|
||||
// create & start node
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
assert.NoError(t, err, "expected no err on DefaultNewNode")
|
||||
err1 := n.Start()
|
||||
if err1 != nil {
|
||||
t.Error(err1)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
err = n.Start()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("Started node %v", n.sw.NodeInfo())
|
||||
|
||||
// wait for the node to produce a block
|
||||
blockCh := make(chan interface{})
|
||||
err = n.EventBus().Subscribe(context.Background(), "node_test", types.EventQueryNewBlock, blockCh)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
select {
|
||||
case <-blockCh:
|
||||
case <-time.After(10 * time.Second):
|
||||
@@ -94,7 +93,7 @@ func TestNodeDelayedStop(t *testing.T) {
|
||||
// create & start node
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
n.GenesisDoc().GenesisTime = now.Add(5 * time.Second)
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
n.Start()
|
||||
startTime := tmtime.Now()
|
||||
@@ -106,7 +105,7 @@ func TestNodeSetAppVersion(t *testing.T) {
|
||||
|
||||
// create & start node
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
assert.NoError(t, err, "expected no err on DefaultNewNode")
|
||||
require.NoError(t, err)
|
||||
|
||||
// default config uses the kvstore app
|
||||
var appVersion version.Protocol = kvstore.ProtocolVersion
|
||||
@@ -122,91 +121,71 @@ func TestNodeSetAppVersion(t *testing.T) {
|
||||
func TestNodeSetPrivValTCP(t *testing.T) {
|
||||
addr := "tcp://" + testFreeAddr(t)
|
||||
|
||||
config := cfg.ResetTestRoot("node_priv_val_tcp_test")
|
||||
config.BaseConfig.PrivValidatorListenAddr = addr
|
||||
|
||||
rs := privval.NewRemoteSigner(
|
||||
log.TestingLogger(),
|
||||
cmn.RandStr(12),
|
||||
config.ChainID(),
|
||||
addr,
|
||||
types.NewMockPV(),
|
||||
ed25519.GenPrivKey(),
|
||||
)
|
||||
privval.RemoteSignerConnDeadline(5 * time.Millisecond)(rs)
|
||||
privval.RemoteSignerConnRetries(1e6)(rs)
|
||||
|
||||
config := cfg.ResetTestRoot("node_priv_val_tcp_test")
|
||||
config.BaseConfig.PrivValidatorListenAddr = addr
|
||||
|
||||
// kick off remote signer routine, and then start TM.
|
||||
go func(rs *privval.RemoteSigner) {
|
||||
rs.Start()
|
||||
defer rs.Stop()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}(rs)
|
||||
go func() {
|
||||
err := rs.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
defer rs.Stop()
|
||||
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
|
||||
assert.NoError(t, err, "expected no err on DefaultNewNode")
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.IsType(t, &privval.TCPVal{}, n.PrivValidator())
|
||||
}
|
||||
|
||||
func TestNodeSetPrivValTCPNoPrefix(t *testing.T) {
|
||||
addr := "tcp://" + testFreeAddr(t)
|
||||
// address without a protocol must result in error
|
||||
func TestPrivValidatorListenAddrNoProtocol(t *testing.T) {
|
||||
addrNoPrefix := testFreeAddr(t)
|
||||
|
||||
rs := privval.NewRemoteSigner(
|
||||
log.TestingLogger(),
|
||||
cmn.RandStr(12),
|
||||
addr,
|
||||
types.NewMockPV(),
|
||||
ed25519.GenPrivKey(),
|
||||
)
|
||||
privval.RemoteSignerConnDeadline(5 * time.Millisecond)(rs)
|
||||
privval.RemoteSignerConnRetries(1e6)(rs)
|
||||
config := cfg.ResetTestRoot("node_priv_val_tcp_test")
|
||||
config.BaseConfig.PrivValidatorListenAddr = addr
|
||||
config.BaseConfig.PrivValidatorListenAddr = addrNoPrefix
|
||||
|
||||
// kick off remote signer routine, and then start TM.
|
||||
go func(rs *privval.RemoteSigner) {
|
||||
rs.Start()
|
||||
defer rs.Stop()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}(rs)
|
||||
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
|
||||
assert.NoError(t, err, "expected no err on DefaultNewNode")
|
||||
assert.IsType(t, &privval.TCPVal{}, n.PrivValidator())
|
||||
_, err := DefaultNewNode(config, log.TestingLogger())
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestNodeSetPrivValIPC(t *testing.T) {
|
||||
tmpfile := "/tmp/kms." + cmn.RandStr(6) + ".sock"
|
||||
defer os.Remove(tmpfile) // clean up
|
||||
addr := "unix://" + tmpfile
|
||||
|
||||
config := cfg.ResetTestRoot("node_priv_val_tcp_test")
|
||||
config.BaseConfig.PrivValidatorListenAddr = "unix://" + tmpfile
|
||||
|
||||
rs := privval.NewIPCRemoteSigner(
|
||||
log.TestingLogger(),
|
||||
cmn.RandStr(12),
|
||||
config.ChainID(),
|
||||
tmpfile,
|
||||
types.NewMockPV(),
|
||||
)
|
||||
|
||||
privval.IPCRemoteSignerConnDeadline(3 * time.Second)(rs)
|
||||
|
||||
// kick off remote signer routine, and then start TM.
|
||||
go func(rs *privval.IPCRemoteSigner) {
|
||||
rs.Start()
|
||||
defer rs.Stop()
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}(rs)
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
require.NoError(t, err)
|
||||
assert.IsType(t, &privval.IPCVal{}, n.PrivValidator())
|
||||
}()
|
||||
|
||||
config := cfg.ResetTestRoot("node_priv_val_tcp_test")
|
||||
config.BaseConfig.PrivValidatorListenAddr = addr
|
||||
n, err := DefaultNewNode(config, log.TestingLogger())
|
||||
err := rs.Start()
|
||||
require.NoError(t, err)
|
||||
defer rs.Stop()
|
||||
|
||||
assert.NoError(t, err, "expected no err on DefaultNewNode")
|
||||
assert.IsType(t, &privval.IPCVal{}, n.PrivValidator())
|
||||
<-done
|
||||
}
|
||||
|
||||
|
||||
// testFreeAddr claims a free port so we don't block on listener being ready.
|
||||
func testFreeAddr(t *testing.T) string {
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
|
||||
Reference in New Issue
Block a user