From 1d1b2b920f334dea5269a1ca470e22fd142d328f Mon Sep 17 00:00:00 2001 From: Silas Davis <silas@erisindustries.com> Date: Thu, 6 Oct 2016 20:22:48 +0100 Subject: [PATCH] Fix transactor's broken attempt to call a Tendermint native RPC --- consensus/tendermint/config.go | 3 ++- consensus/tendermint/tendermint.go | 10 +++++++++ manager/eris-mint/eris-mint.go | 32 --------------------------- manager/eris-mint/pipe.go | 35 ++++++++++++++++++++---------- manager/eris-mint/transactor.go | 20 +++++++++-------- rpc/tendermint/test/config.go | 6 ++--- rpc/tendermint/test/shared.go | 3 +-- server_config.toml | 17 ++++++--------- 8 files changed, 57 insertions(+), 69 deletions(-) diff --git a/consensus/tendermint/config.go b/consensus/tendermint/config.go index 20fad4cd..1bbb74bd 100644 --- a/consensus/tendermint/config.go +++ b/consensus/tendermint/config.go @@ -73,7 +73,7 @@ func (tmintConfig *TendermintConfig) AssertTendermintDefaults(chainId, workDir, tmintConfig.SetDefault("db_backend", "leveldb") tmintConfig.SetDefault("db_dir", dataDir) tmintConfig.SetDefault("log_level", "info") - tmintConfig.SetDefault("rpc_laddr", "0.0.0.0:46657") + tmintConfig.SetDefault("rpc_laddr", "") tmintConfig.SetDefault("prof_laddr", "") tmintConfig.SetDefault("revision_file", path.Join(workDir, "revision")) tmintConfig.SetDefault("cswal", path.Join(dataDir, "cswal")) @@ -103,6 +103,7 @@ func (tmintConfig *TendermintConfig) AssertTendermintConsistency( tmintConfig.Set("genesis_file", consensusConfig.GenesisFile) // private validator file tmintConfig.Set("priv_validator_file", privateValidatorFilePath) + } // implement interface github.com/tendermint/go-config/config.Config diff --git a/consensus/tendermint/tendermint.go b/consensus/tendermint/tendermint.go index 507e6351..e9815347 100644 --- a/consensus/tendermint/tendermint.go +++ b/consensus/tendermint/tendermint.go @@ -111,6 +111,16 @@ func NewTendermint(moduleConfig *config.ModuleConfig, path.Join(moduleConfig.RootDir, moduleConfig.Config.GetString("private_validator_file"))) + // TODO: [Silas] we want to something better than this like not not have it in + // the config at all, but for now I think it's much safer to make sure we are + // not running the tendermint RPC as it could lead to unexpected behaviour, + // not least if we accidentally try to run it on the same address as our own + if tmintConfig.GetString("rpc_laddr") != "" { + log.Warnf("Force disabling Tendermint's native RPC, which had been set to " + + "run on '%s' in the Tendermint config.", tmintConfig.GetString("rpc_laddr")) + tmintConfig.Set("rpc_laddr", "") + } + newNode := node.NewNode(tmintConfig, privateValidator, func(_, _ string, hash []byte) proxy.AppConn { return NewLocalClient(new(sync.Mutex), application) diff --git a/manager/eris-mint/eris-mint.go b/manager/eris-mint/eris-mint.go index 55d7374d..2c08757c 100644 --- a/manager/eris-mint/eris-mint.go +++ b/manager/eris-mint/eris-mint.go @@ -18,14 +18,11 @@ package erismint import ( "bytes" - "encoding/hex" "fmt" "sync" tendermint_events "github.com/tendermint/go-events" - rpcclient "github.com/tendermint/go-rpc/client" wire "github.com/tendermint/go-wire" - ctypes "github.com/tendermint/tendermint/rpc/core/types" tmsp "github.com/tendermint/tmsp/types" log "github.com/eris-ltd/eris-logger" @@ -50,10 +47,6 @@ type ErisMint struct { evc *tendermint_events.EventCache evsw *tendermint_events.EventSwitch - // client to the tendermint core rpc - client *rpcclient.ClientURI - host string // tendermint core endpoint - nTxs int // count txs in a block } @@ -78,31 +71,6 @@ func (app *ErisMint) GetCheckCache() *sm.BlockCache { return app.checkCache } -func (app *ErisMint) SetHostAddress(host string) { - app.host = host - app.client = rpcclient.NewClientURI(host) //fmt.Sprintf("http://%s", host)) -} - -// Broadcast a tx to the tendermint core -// NOTE: this assumes we know the address of core -func (app *ErisMint) BroadcastTx(tx txs.Tx) error { - buf := new(bytes.Buffer) - var n int - var err error - wire.WriteBinary(struct{ txs.Tx }{tx}, buf, &n, &err) - if err != nil { - return err - } - - params := map[string]interface{}{ - "tx": hex.EncodeToString(buf.Bytes()), - } - - var result ctypes.TMResult - _, err = app.client.Call("broadcast_tx_sync", params, &result) - return err -} - func NewErisMint(s *sm.State, evsw *tendermint_events.EventSwitch) *ErisMint { return &ErisMint{ state: s, diff --git a/manager/eris-mint/pipe.go b/manager/eris-mint/pipe.go index 490a613b..dc9b6487 100644 --- a/manager/eris-mint/pipe.go +++ b/manager/eris-mint/pipe.go @@ -87,26 +87,20 @@ func NewErisMintPipe(moduleConfig *config.ModuleConfig, // start the application erisMint := NewErisMint(startedState, eventSwitch) - // NOTE: [ben] Set Host opens an RPC pipe to Tendermint; this is a remnant - // of the old Eris-DB / Tendermint and should be considered as an in-process - // call when possible - tendermintHost := moduleConfig.Config.GetString("tendermint_host") - erisMint.SetHostAddress(tendermintHost) - // initialise the components of the pipe events := edb_event.NewEvents(eventSwitch) accounts := newAccounts(erisMint) namereg := newNameReg(erisMint) - transactor := newTransactor(moduleConfig.ChainId, eventSwitch, erisMint, - events) - return &erisMintPipe{ + pipe := &erisMintPipe{ erisMintState: startedState, erisMint: erisMint, accounts: accounts, events: events, namereg: namereg, - transactor: transactor, + // We need to set transactor later since we are introducing a mutual dependency + // NOTE: this will be cleaned up when the RPC is unified + transactor: nil, // genesis cache genesisDoc: genesisDoc, genesisState: nil, @@ -114,7 +108,26 @@ func NewErisMintPipe(moduleConfig *config.ModuleConfig, // authority - this is a sort of dependency injection pattern consensusEngine: nil, blockchain: nil, - }, nil + } + + // NOTE: [Silas] + // This is something of a loopback, but seems like a nicer option than + // transactor calling the Tendermint native RPC (as it was before), + // or indeed calling this RPC over the wire given that we have direct access. + // + // We could just hand transactor a copy of Pipe, but doing it this way seems + // like a reasonably minimal and flexible way of providing transactor with the + // broadcast function it needs, without making it explicitly + // aware of/depend on Pipe. + transactor := newTransactor(moduleConfig.ChainId, eventSwitch, erisMint, + events, + func(tx txs.Tx) error { + _, err := pipe.BroadcastTxSync(tx) + return err + }) + + pipe.transactor = transactor + return pipe, nil } //------------------------------------------------------------------------------ diff --git a/manager/eris-mint/transactor.go b/manager/eris-mint/transactor.go index 3480d16a..953c519f 100644 --- a/manager/eris-mint/transactor.go +++ b/manager/eris-mint/transactor.go @@ -38,23 +38,25 @@ import ( ) type transactor struct { - chainID string - eventSwitch tEvents.Fireable - erisMint *ErisMint - eventEmitter event.EventEmitter - txMtx *sync.Mutex + chainID string + eventSwitch tEvents.Fireable + erisMint *ErisMint + eventEmitter event.EventEmitter + txMtx *sync.Mutex + txBroadcaster func(tx txs.Tx) error } func newTransactor(chainID string, eventSwitch tEvents.Fireable, - erisMint *ErisMint, eventEmitter event.EventEmitter) *transactor { - txs := &transactor{ + erisMint *ErisMint, eventEmitter event.EventEmitter, + txBroadcaster func(tx txs.Tx) error) *transactor { + return &transactor{ chainID, eventSwitch, erisMint, eventEmitter, &sync.Mutex{}, + txBroadcaster, } - return txs } // Run a contract's code on an isolated and unpersisted state @@ -132,8 +134,8 @@ func (this *transactor) CallCode(fromAddress, code, data []byte) ( // Broadcast a transaction. func (this *transactor) BroadcastTx(tx txs.Tx) (*txs.Receipt, error) { + err := this.txBroadcaster(tx) - err := this.erisMint.BroadcastTx(tx) if err != nil { return nil, fmt.Errorf("Error broadcasting transaction: %v", err) } diff --git a/rpc/tendermint/test/config.go b/rpc/tendermint/test/config.go index e4b60a9d..ff33cb30 100644 --- a/rpc/tendermint/test/config.go +++ b/rpc/tendermint/test/config.go @@ -173,7 +173,7 @@ private_validator_file = "priv_validator.json" # rpc local address # NOTE: value is ignored when run in-process as RPC is # handled by [servers.tendermint] - rpc_laddr = "0.0.0.0:36657" + rpc_laddr = "" # proxy application address - used for tmsp connections, # and this port should not be exposed for in-process Tendermint proxy_app = "tcp://127.0.0.1:46658" @@ -217,6 +217,4 @@ private_validator_file = "priv_validator.json" [erismint] # Database backend to use for ErisMint state database. db_backend = "leveldb" -# tendermint host address needs to correspond to tendermints configuration -# of the rpc local address -tendermint_host = "0.0.0.0:36657"` +` diff --git a/rpc/tendermint/test/shared.go b/rpc/tendermint/test/shared.go index 16dbf7ab..d211bd5d 100644 --- a/rpc/tendermint/test/shared.go +++ b/rpc/tendermint/test/shared.go @@ -64,9 +64,8 @@ func initGlobalVariables(ffs *fixtures.FileFixtures) error { } chainID = testConfig.GetString("chain.assert_chain_id") - rpcAddr := testConfig.GetString("erismint.tendermint_host") + rpcAddr := config.Tendermint.RpcLocalAddress websocketAddr = rpcAddr - config.Tendermint.RpcLocalAddress = rpcAddr websocketEndpoint = "/websocket" consensusConfig, err := core.LoadModuleConfig(testConfig, rootWorkDir, diff --git a/server_config.toml b/server_config.toml index d680ede7..80e88a93 100644 --- a/server_config.toml +++ b/server_config.toml @@ -101,10 +101,10 @@ genesis_file = "genesis.json" read_buffer_size = 4096 write_buffer_size = 4096 - [servers.tendermint] - # Multiple listeners can be separated with a comma - rpc_local_address = "0.0.0.0:46657" - endpoint = "/websocket" + [servers.tendermint] + # Multiple listeners can be separated with a comma + rpc_local_address = "0.0.0.0:46657" + endpoint = "/websocket" [servers.logging] console_log_level = "info" @@ -172,9 +172,9 @@ private_validator_file = "priv_validator.json" # node local address node_laddr = "0.0.0.0:46656" # rpc local address - # NOTE: value is ignored when run in-process as RPC is - # handled by [servers.tendermint] - rpc_laddr = "0.0.0.0:46657" + # NOTE: value is ignored when run in-process as RPC is + # handled by [servers.tendermint] + rpc_laddr = "" # proxy application address - used for tmsp connections, # and this port should not be exposed for in-process Tendermint proxy_app = "tcp://127.0.0.1:46658" @@ -239,6 +239,3 @@ private_validator_file = "priv_validator.json" # Database backend to use for ErisMint state database. # Supported `leveldb` and `memdb`. db_backend = "leveldb" -# tendermint host address needs to correspond to tendermints configuration -# of the rpc local address -tendermint_host = "0.0.0.0:46657" -- GitLab