diff --git a/node/node.go b/node/node.go index f66dc836a..969d4b612 100644 --- a/node/node.go +++ b/node/node.go @@ -44,7 +44,14 @@ type Node struct { proxyApp proxy.AppConns } -func NewNode(config cfg.Config, privValidator *types.PrivValidator) *Node { +func NewNodeDefault(config cfg.Config) *Node { + // Get PrivValidator + privValidatorFile := config.GetString("priv_validator_file") + privValidator := types.LoadOrGenPrivValidator(privValidatorFile) + return NewNode(config, privValidator, proxy.NewTMSPClientDefault) +} + +func NewNode(config cfg.Config, privValidator *types.PrivValidator, newTMSPClient proxy.NewTMSPClient) *Node { EnsureDir(config.GetString("db_dir"), 0700) // incase we use memdb, cswal still gets written here @@ -60,7 +67,7 @@ func NewNode(config cfg.Config, privValidator *types.PrivValidator) *Node { // Create the proxyApp, which houses three connections: // query, consensus, and mempool - proxyApp := proxy.NewAppConns(config, state, blockStore) + proxyApp := proxy.NewAppConns(config, newTMSPClient, state, blockStore) // add the chainid and number of validators to the global config config.Set("chain_id", state.ChainID) @@ -299,9 +306,12 @@ func getState(config cfg.Config, stateDB dbm.DB) *sm.State { //------------------------------------------------------------------------------ -// Users wishing to use an external signer for their validators +// Users wishing to: +// * use an external signer for their validators +// * supply an in-proc tmsp app // should fork tendermint/tendermint and implement RunNode to -// load their custom priv validator and call NewNode +// call NewNode with their custom priv validator and/or custom +// proxy.NewTMSPClient function. func RunNode(config cfg.Config) { // Wait until the genesis doc becomes available genDocFile := config.GetString("genesis_file") @@ -324,12 +334,8 @@ func RunNode(config cfg.Config) { } } - // Get PrivValidator - privValidatorFile := config.GetString("priv_validator_file") - privValidator := types.LoadOrGenPrivValidator(privValidatorFile) - // Create & start node - n := NewNode(config, privValidator) + n := NewNodeDefault(config) protocol, address := ProtocolAndAddress(config.GetString("node_laddr")) l := p2p.NewDefaultListener(protocol, address, config.GetBool("skip_upnp")) @@ -384,7 +390,7 @@ func newConsensusState(config cfg.Config) *consensus.ConsensusState { // Create two proxyAppConn connections, // one for the consensus and one for the mempool. - proxyApp := proxy.NewAppConns(config, state, blockStore) + proxyApp := proxy.NewAppConns(config, proxy.NewTMSPClientDefault, state, blockStore) // add the chainid to the global config config.Set("chain_id", state.ChainID) diff --git a/node/node_test.go b/node/node_test.go index e3dd1d5ad..880a2dab7 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -6,18 +6,13 @@ import ( "github.com/tendermint/go-p2p" "github.com/tendermint/tendermint/config/tendermint_test" - "github.com/tendermint/tendermint/types" ) func TestNodeStartStop(t *testing.T) { config := tendermint_test.ResetConfig("node_node_test") - // Get PrivValidator - privValidatorFile := config.GetString("priv_validator_file") - privValidator := types.LoadOrGenPrivValidator(privValidatorFile) - // Create & start node - n := NewNode(config, privValidator) + n := NewNodeDefault(config) protocol, address := ProtocolAndAddress(config.GetString("node_laddr")) l := p2p.NewDefaultListener(protocol, address, config.GetBool("skip_upnp")) n.AddListener(l) diff --git a/proxy/app_conn_test.go b/proxy/app_conn_test.go index 00a80cb11..7e425d55e 100644 --- a/proxy/app_conn_test.go +++ b/proxy/app_conn_test.go @@ -53,7 +53,7 @@ func TestEcho(t *testing.T) { } defer s.Stop() // Start client - cli, err := NewTMSPClient(sockPath, SOCKET) + cli, err := NewTMSPClientDefault(sockPath, SOCKET) if err != nil { Exit(err.Error()) } @@ -76,7 +76,7 @@ func BenchmarkEcho(b *testing.B) { } defer s.Stop() // Start client - cli, err := NewTMSPClient(sockPath, SOCKET) + cli, err := NewTMSPClientDefault(sockPath, SOCKET) if err != nil { Exit(err.Error()) } @@ -104,7 +104,7 @@ func TestInfo(t *testing.T) { } defer s.Stop() // Start client - cli, err := NewTMSPClient(sockPath, SOCKET) + cli, err := NewTMSPClientDefault(sockPath, SOCKET) if err != nil { Exit(err.Error()) } diff --git a/proxy/client.go b/proxy/client.go new file mode 100644 index 000000000..17e742390 --- /dev/null +++ b/proxy/client.go @@ -0,0 +1,43 @@ +package proxy + +import ( + "fmt" + "sync" + + tmspcli "github.com/tendermint/tmsp/client" + "github.com/tendermint/tmsp/example/dummy" + nilapp "github.com/tendermint/tmsp/example/nil" +) + +// Function type to get a connected tmsp client +// Allows consumers to provide their own in-proc apps, +// or to implement alternate address schemes and transports +type NewTMSPClient func(addr, transport string) (tmspcli.Client, error) + +// Get a connected tmsp client. +// Offers some default in-proc apps, else socket/grpc. +func NewTMSPClientDefault(addr, transport string) (tmspcli.Client, error) { + var client tmspcli.Client + + // use local app (for testing) + // TODO: local proxy app conn + switch addr { + case "nilapp": + app := nilapp.NewNilApplication() + mtx := new(sync.Mutex) // TODO + client = tmspcli.NewLocalClient(mtx, app) + case "dummy": + app := dummy.NewDummyApplication() + mtx := new(sync.Mutex) // TODO + client = tmspcli.NewLocalClient(mtx, app) + default: + // Run forever in a loop + mustConnect := false + remoteApp, err := tmspcli.NewClient(addr, transport, mustConnect) + if err != nil { + return nil, fmt.Errorf("Failed to connect to proxy for mempool: %v", err) + } + client = remoteApp + } + return client, nil +} diff --git a/proxy/multi_app_conn.go b/proxy/multi_app_conn.go index b51bf2be2..5c16678f9 100644 --- a/proxy/multi_app_conn.go +++ b/proxy/multi_app_conn.go @@ -1,56 +1,22 @@ package proxy import ( - "fmt" - "sync" - . "github.com/tendermint/go-common" cfg "github.com/tendermint/go-config" - tmspcli "github.com/tendermint/tmsp/client" - "github.com/tendermint/tmsp/example/dummy" - nilapp "github.com/tendermint/tmsp/example/nil" ) -// Get a connected tmsp client -func NewTMSPClient(addr, transport string) (tmspcli.Client, error) { - var client tmspcli.Client - - // use local app (for testing) - // TODO: local proxy app conn - switch addr { - case "nilapp": - app := nilapp.NewNilApplication() - mtx := new(sync.Mutex) // TODO - client = tmspcli.NewLocalClient(mtx, app) - case "dummy": - app := dummy.NewDummyApplication() - mtx := new(sync.Mutex) // TODO - client = tmspcli.NewLocalClient(mtx, app) - default: - // Run forever in a loop - mustConnect := false - remoteApp, err := tmspcli.NewClient(addr, transport, mustConnect) - if err != nil { - return nil, fmt.Errorf("Failed to connect to proxy for mempool: %v", err) - } - client = remoteApp - } - return client, nil -} - -//--------- - +// Tendermint's interface to the application consists of multiple connections type AppConns interface { Mempool() AppConnMempool Consensus() AppConnConsensus Query() AppConnQuery } -func NewAppConns(config cfg.Config, state State, blockStore BlockStore) AppConns { - return NewMultiAppConn(config, state, blockStore) +func NewAppConns(config cfg.Config, newTMSPClient NewTMSPClient, state State, blockStore BlockStore) AppConns { + return NewMultiAppConn(config, newTMSPClient, state, blockStore) } -// a multiAppConn is made of a few appConns (mempool, consensus) +// a multiAppConn is made of a few appConns (mempool, consensus, query) // and manages their underlying tmsp clients, ensuring they reboot together type multiAppConn struct { QuitService @@ -63,14 +29,17 @@ type multiAppConn struct { mempoolConn *appConnMempool consensusConn *appConnConsensus queryConn *appConnQuery + + newTMSPClient NewTMSPClient } // Make all necessary tmsp connections to the application -func NewMultiAppConn(config cfg.Config, state State, blockStore BlockStore) *multiAppConn { +func NewMultiAppConn(config cfg.Config, newTMSPClient NewTMSPClient, state State, blockStore BlockStore) *multiAppConn { multiAppConn := &multiAppConn{ - config: config, - state: state, - blockStore: blockStore, + config: config, + state: state, + blockStore: blockStore, + newTMSPClient: newTMSPClient, } multiAppConn.QuitService = *NewQuitService(log, "multiAppConn", multiAppConn) multiAppConn.Start() @@ -98,21 +67,21 @@ func (app *multiAppConn) OnStart() error { transport := app.config.GetString("tmsp") // query connection - querycli, err := NewTMSPClient(addr, transport) + querycli, err := app.newTMSPClient(addr, transport) if err != nil { return err } app.queryConn = NewAppConnQuery(querycli) // mempool connection - memcli, err := NewTMSPClient(addr, transport) + memcli, err := app.newTMSPClient(addr, transport) if err != nil { return err } app.mempoolConn = NewAppConnMempool(memcli) // consensus connection - concli, err := NewTMSPClient(addr, transport) + concli, err := app.newTMSPClient(addr, transport) if err != nil { return err } diff --git a/rpc/test/helpers.go b/rpc/test/helpers.go index d9a5aa915..17acaf9be 100644 --- a/rpc/test/helpers.go +++ b/rpc/test/helpers.go @@ -13,7 +13,6 @@ import ( "github.com/tendermint/tendermint/config/tendermint_test" nm "github.com/tendermint/tendermint/node" ctypes "github.com/tendermint/tendermint/rpc/core/types" - "github.com/tendermint/tendermint/types" ) // global variables for use across all tests @@ -52,9 +51,7 @@ func init() { // create a new node and sleep forever func newNode(ready chan struct{}) { // Create & start node - privValidatorFile := config.GetString("priv_validator_file") - privValidator := types.LoadOrGenPrivValidator(privValidatorFile) - node = nm.NewNode(config, privValidator) + node = nm.NewNodeDefault(config) protocol, address := nm.ProtocolAndAddress(config.GetString("node_laddr")) l := p2p.NewDefaultListener(protocol, address, true) node.AddListener(l)