You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1297 lines
39 KiB

privval: refactor Remote signers (#3370) This PR is related to #3107 and a continuation of #3351 It is important to emphasise that in the privval original design, client/server and listening/dialing roles are inverted and do not follow a conventional interaction. Given two hosts A and B: Host A is listener/client Host B is dialer/server (contains the secret key) When A requires a signature, it needs to wait for B to dial in before it can issue a request. A only accepts a single connection and any failure leads to dropping the connection and waiting for B to reconnect. The original rationale behind this design was based on security. Host B only allows outbound connections to a list of whitelisted hosts. It is not possible to reach B unless B dials in. There are no listening/open ports in B. This PR results in the following changes: Refactors ping/heartbeat to avoid previously existing race conditions. Separates transport (dialer/listener) from signing (client/server) concerns to simplify workflow. Unifies and abstracts away the differences between unix and tcp sockets. A single signer endpoint implementation unifies connection handling code (read/write/close/connection obj) The signer request handler (server side) is customizable to increase testability. Updates and extends unit tests A high level overview of the classes is as follows: Transport (endpoints): The following classes take care of establishing a connection SignerDialerEndpoint SignerListeningEndpoint SignerEndpoint groups common functionality (read/write/timeouts/etc.) Signing (client/server): The following classes take care of exchanging request/responses SignerClient SignerServer This PR also closes #3601 Commits: * refactoring - work in progress * reworking unit tests * Encapsulating and fixing unit tests * Improve tests * Clean up * Fix/improve unit tests * clean up tests * Improving service endpoint * fixing unit test * fix linter issues * avoid invalid cache values (improve later?) * complete implementation * wip * improved connection loop * Improve reconnections + fixing unit tests * addressing comments * small formatting changes * clean up * Update node/node.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client_test.go Co-Authored-By: jleni <juan.leni@zondax.ch> * check during initialization * dropping connecting when writing fails * removing break * use t.log instead * unifying and using cmn.GetFreePort() * review fixes * reordering and unifying drop connection * closing instead of signalling * refactored service loop * removed superfluous brackets * GetPubKey can return errors * Revert "GetPubKey can return errors" This reverts commit 68c06f19b4650389d7e5ab1659b318889028202c. * adding entry to changelog * Update CHANGELOG_PENDING.md Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_listener_endpoint_test.go Co-Authored-By: jleni <juan.leni@zondax.ch> * updating node.go * review fixes * fixes linter * fixing unit test * small fixes in comments * addressing review comments * addressing review comments 2 * reverting suggestion * Update privval/signer_client_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update privval/signer_client_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update privval/signer_listener_endpoint_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * do not expose brokenSignerDialerEndpoint * clean up logging * unifying methods shorten test time signer also drops * reenabling pings * improving testability + unit test * fixing go fmt + unit test * remove unused code * Addressing review comments * simplifying connection workflow * fix linter/go import issue * using base service quit * updating comment * Simplifying design + adjusting names * fixing linter issues * refactoring test harness + fixes * Addressing review comments * cleaning up * adding additional error check
5 years ago
limit number of /subscribe clients and queries per client (#3269) * limit number of /subscribe clients and queries per client Add the following config variables (under [rpc] section): * max_subscription_clients * max_subscriptions_per_client * timeout_broadcast_tx_commit Fixes #2826 new HTTPClient interface for subscriptions finalize HTTPClient events interface remove EventSubscriber fix data race ``` WARNING: DATA RACE Read at 0x00c000a36060 by goroutine 129: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe.func1() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:168 +0x1f0 Previous write at 0x00c000a36060 by goroutine 132: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:191 +0x4e0 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 129 (running) created at: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:164 +0x4b7 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 132 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x659 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:119 +0x186 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 ================== ``` lite client works (tested manually) godoc comments httpclient: do not close the out channel use TimeoutBroadcastTxCommit no timeout for unsubscribe but 1s Local (5s HTTP) timeout for resubscribe format code change Subscribe#out cap to 1 and replace config vars with RPCConfig TimeoutBroadcastTxCommit can't be greater than rpcserver.WriteTimeout rpc: Context as first parameter to all functions reformat code fixes after my own review fixes after Ethan's review add test stubs fix config.toml * fixes after manual testing - rpc: do not recommend to use BroadcastTxCommit because it's slow and wastes Tendermint resources (pubsub) - rpc: better error in Subscribe and BroadcastTxCommit - HTTPClient: do not resubscribe if err = ErrAlreadySubscribed * fixes after Ismail's review * Update rpc/grpc/grpc_test.go Co-Authored-By: melekes <anton.kalyaev@gmail.com>
6 years ago
blockchain: Reorg reactor (#3561) * go routines in blockchain reactor * Added reference to the go routine diagram * Initial commit * cleanup * Undo testing_logger change, committed by mistake * Fix the test loggers * pulled some fsm code into pool.go * added pool tests * changes to the design added block requests under peer moved the request trigger in the reactor poolRoutine, triggered now by a ticker in general moved everything required for making block requests smarter in the poolRoutine added a simple map of heights to keep track of what will need to be requested next added a few more tests * send errors to FSM in a different channel than blocks send errors (RemovePeer) from switch on a different channel than the one receiving blocks renamed channels added more pool tests * more pool tests * lint errors * more tests * more tests * switch fast sync to new implementation * fixed data race in tests * cleanup * finished fsm tests * address golangci comments :) * address golangci comments :) * Added timeout on next block needed to advance * updating docs and cleanup * fix issue in test from previous cleanup * cleanup * Added termination scenarios, tests and more cleanup * small fixes to adr, comments and cleanup * Fix bug in sendRequest() If we tried to send a request to a peer not present in the switch, a missing continue statement caused the request to be blackholed in a peer that was removed and never retried. While this bug was manifesting, the reactor kept asking for other blocks that would be stored and never consumed. Added the number of unconsumed blocks in the math for requesting blocks ahead of current processing height so eventually there will be no more blocks requested until the already received ones are consumed. * remove bpPeer's didTimeout field * Use distinct err codes for peer timeout and FSM timeouts * Don't allow peers to update with lower height * review comments from Ethan and Zarko * some cleanup, renaming, comments * Move block execution in separate goroutine * Remove pool's numPending * review comments * fix lint, remove old blockchain reactor and duplicates in fsm tests * small reorg around peer after review comments * add the reactor spec * verify block only once * review comments * change to int for max number of pending requests * cleanup and godoc * Add configuration flag fast sync version * golangci fixes * fix config template * move both reactor versions under blockchain * cleanup, golint, renaming stuff * updated documentation, fixed more golint warnings * integrate with behavior package * sync with master * gofmt * add changelog_pending entry * move to improvments * suggestion to changelog entry
5 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
privval: refactor Remote signers (#3370) This PR is related to #3107 and a continuation of #3351 It is important to emphasise that in the privval original design, client/server and listening/dialing roles are inverted and do not follow a conventional interaction. Given two hosts A and B: Host A is listener/client Host B is dialer/server (contains the secret key) When A requires a signature, it needs to wait for B to dial in before it can issue a request. A only accepts a single connection and any failure leads to dropping the connection and waiting for B to reconnect. The original rationale behind this design was based on security. Host B only allows outbound connections to a list of whitelisted hosts. It is not possible to reach B unless B dials in. There are no listening/open ports in B. This PR results in the following changes: Refactors ping/heartbeat to avoid previously existing race conditions. Separates transport (dialer/listener) from signing (client/server) concerns to simplify workflow. Unifies and abstracts away the differences between unix and tcp sockets. A single signer endpoint implementation unifies connection handling code (read/write/close/connection obj) The signer request handler (server side) is customizable to increase testability. Updates and extends unit tests A high level overview of the classes is as follows: Transport (endpoints): The following classes take care of establishing a connection SignerDialerEndpoint SignerListeningEndpoint SignerEndpoint groups common functionality (read/write/timeouts/etc.) Signing (client/server): The following classes take care of exchanging request/responses SignerClient SignerServer This PR also closes #3601 Commits: * refactoring - work in progress * reworking unit tests * Encapsulating and fixing unit tests * Improve tests * Clean up * Fix/improve unit tests * clean up tests * Improving service endpoint * fixing unit test * fix linter issues * avoid invalid cache values (improve later?) * complete implementation * wip * improved connection loop * Improve reconnections + fixing unit tests * addressing comments * small formatting changes * clean up * Update node/node.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client_test.go Co-Authored-By: jleni <juan.leni@zondax.ch> * check during initialization * dropping connecting when writing fails * removing break * use t.log instead * unifying and using cmn.GetFreePort() * review fixes * reordering and unifying drop connection * closing instead of signalling * refactored service loop * removed superfluous brackets * GetPubKey can return errors * Revert "GetPubKey can return errors" This reverts commit 68c06f19b4650389d7e5ab1659b318889028202c. * adding entry to changelog * Update CHANGELOG_PENDING.md Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_listener_endpoint_test.go Co-Authored-By: jleni <juan.leni@zondax.ch> * updating node.go * review fixes * fixes linter * fixing unit test * small fixes in comments * addressing review comments * addressing review comments 2 * reverting suggestion * Update privval/signer_client_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update privval/signer_client_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update privval/signer_listener_endpoint_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * do not expose brokenSignerDialerEndpoint * clean up logging * unifying methods shorten test time signer also drops * reenabling pings * improving testability + unit test * fixing go fmt + unit test * remove unused code * Addressing review comments * simplifying connection workflow * fix linter/go import issue * using base service quit * updating comment * Simplifying design + adjusting names * fixing linter issues * refactoring test harness + fixes * Addressing review comments * cleaning up * adding additional error check
5 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
blockchain: Reorg reactor (#3561) * go routines in blockchain reactor * Added reference to the go routine diagram * Initial commit * cleanup * Undo testing_logger change, committed by mistake * Fix the test loggers * pulled some fsm code into pool.go * added pool tests * changes to the design added block requests under peer moved the request trigger in the reactor poolRoutine, triggered now by a ticker in general moved everything required for making block requests smarter in the poolRoutine added a simple map of heights to keep track of what will need to be requested next added a few more tests * send errors to FSM in a different channel than blocks send errors (RemovePeer) from switch on a different channel than the one receiving blocks renamed channels added more pool tests * more pool tests * lint errors * more tests * more tests * switch fast sync to new implementation * fixed data race in tests * cleanup * finished fsm tests * address golangci comments :) * address golangci comments :) * Added timeout on next block needed to advance * updating docs and cleanup * fix issue in test from previous cleanup * cleanup * Added termination scenarios, tests and more cleanup * small fixes to adr, comments and cleanup * Fix bug in sendRequest() If we tried to send a request to a peer not present in the switch, a missing continue statement caused the request to be blackholed in a peer that was removed and never retried. While this bug was manifesting, the reactor kept asking for other blocks that would be stored and never consumed. Added the number of unconsumed blocks in the math for requesting blocks ahead of current processing height so eventually there will be no more blocks requested until the already received ones are consumed. * remove bpPeer's didTimeout field * Use distinct err codes for peer timeout and FSM timeouts * Don't allow peers to update with lower height * review comments from Ethan and Zarko * some cleanup, renaming, comments * Move block execution in separate goroutine * Remove pool's numPending * review comments * fix lint, remove old blockchain reactor and duplicates in fsm tests * small reorg around peer after review comments * add the reactor spec * verify block only once * review comments * change to int for max number of pending requests * cleanup and godoc * Add configuration flag fast sync version * golangci fixes * fix config template * move both reactor versions under blockchain * cleanup, golint, renaming stuff * updated documentation, fixed more golint warnings * integrate with behavior package * sync with master * gofmt * add changelog_pending entry * move to improvments * suggestion to changelog entry
5 years ago
blockchain: Reorg reactor (#3561) * go routines in blockchain reactor * Added reference to the go routine diagram * Initial commit * cleanup * Undo testing_logger change, committed by mistake * Fix the test loggers * pulled some fsm code into pool.go * added pool tests * changes to the design added block requests under peer moved the request trigger in the reactor poolRoutine, triggered now by a ticker in general moved everything required for making block requests smarter in the poolRoutine added a simple map of heights to keep track of what will need to be requested next added a few more tests * send errors to FSM in a different channel than blocks send errors (RemovePeer) from switch on a different channel than the one receiving blocks renamed channels added more pool tests * more pool tests * lint errors * more tests * more tests * switch fast sync to new implementation * fixed data race in tests * cleanup * finished fsm tests * address golangci comments :) * address golangci comments :) * Added timeout on next block needed to advance * updating docs and cleanup * fix issue in test from previous cleanup * cleanup * Added termination scenarios, tests and more cleanup * small fixes to adr, comments and cleanup * Fix bug in sendRequest() If we tried to send a request to a peer not present in the switch, a missing continue statement caused the request to be blackholed in a peer that was removed and never retried. While this bug was manifesting, the reactor kept asking for other blocks that would be stored and never consumed. Added the number of unconsumed blocks in the math for requesting blocks ahead of current processing height so eventually there will be no more blocks requested until the already received ones are consumed. * remove bpPeer's didTimeout field * Use distinct err codes for peer timeout and FSM timeouts * Don't allow peers to update with lower height * review comments from Ethan and Zarko * some cleanup, renaming, comments * Move block execution in separate goroutine * Remove pool's numPending * review comments * fix lint, remove old blockchain reactor and duplicates in fsm tests * small reorg around peer after review comments * add the reactor spec * verify block only once * review comments * change to int for max number of pending requests * cleanup and godoc * Add configuration flag fast sync version * golangci fixes * fix config template * move both reactor versions under blockchain * cleanup, golint, renaming stuff * updated documentation, fixed more golint warnings * integrate with behavior package * sync with master * gofmt * add changelog_pending entry * move to improvments * suggestion to changelog entry
5 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
limit number of /subscribe clients and queries per client (#3269) * limit number of /subscribe clients and queries per client Add the following config variables (under [rpc] section): * max_subscription_clients * max_subscriptions_per_client * timeout_broadcast_tx_commit Fixes #2826 new HTTPClient interface for subscriptions finalize HTTPClient events interface remove EventSubscriber fix data race ``` WARNING: DATA RACE Read at 0x00c000a36060 by goroutine 129: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe.func1() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:168 +0x1f0 Previous write at 0x00c000a36060 by goroutine 132: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:191 +0x4e0 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 129 (running) created at: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:164 +0x4b7 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 132 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x659 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:119 +0x186 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 ================== ``` lite client works (tested manually) godoc comments httpclient: do not close the out channel use TimeoutBroadcastTxCommit no timeout for unsubscribe but 1s Local (5s HTTP) timeout for resubscribe format code change Subscribe#out cap to 1 and replace config vars with RPCConfig TimeoutBroadcastTxCommit can't be greater than rpcserver.WriteTimeout rpc: Context as first parameter to all functions reformat code fixes after my own review fixes after Ethan's review add test stubs fix config.toml * fixes after manual testing - rpc: do not recommend to use BroadcastTxCommit because it's slow and wastes Tendermint resources (pubsub) - rpc: better error in Subscribe and BroadcastTxCommit - HTTPClient: do not resubscribe if err = ErrAlreadySubscribed * fixes after Ismail's review * Update rpc/grpc/grpc_test.go Co-Authored-By: melekes <anton.kalyaev@gmail.com>
6 years ago
limit number of /subscribe clients and queries per client (#3269) * limit number of /subscribe clients and queries per client Add the following config variables (under [rpc] section): * max_subscription_clients * max_subscriptions_per_client * timeout_broadcast_tx_commit Fixes #2826 new HTTPClient interface for subscriptions finalize HTTPClient events interface remove EventSubscriber fix data race ``` WARNING: DATA RACE Read at 0x00c000a36060 by goroutine 129: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe.func1() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:168 +0x1f0 Previous write at 0x00c000a36060 by goroutine 132: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:191 +0x4e0 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 129 (running) created at: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:164 +0x4b7 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 132 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x659 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:119 +0x186 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 ================== ``` lite client works (tested manually) godoc comments httpclient: do not close the out channel use TimeoutBroadcastTxCommit no timeout for unsubscribe but 1s Local (5s HTTP) timeout for resubscribe format code change Subscribe#out cap to 1 and replace config vars with RPCConfig TimeoutBroadcastTxCommit can't be greater than rpcserver.WriteTimeout rpc: Context as first parameter to all functions reformat code fixes after my own review fixes after Ethan's review add test stubs fix config.toml * fixes after manual testing - rpc: do not recommend to use BroadcastTxCommit because it's slow and wastes Tendermint resources (pubsub) - rpc: better error in Subscribe and BroadcastTxCommit - HTTPClient: do not resubscribe if err = ErrAlreadySubscribed * fixes after Ismail's review * Update rpc/grpc/grpc_test.go Co-Authored-By: melekes <anton.kalyaev@gmail.com>
6 years ago
limit number of /subscribe clients and queries per client (#3269) * limit number of /subscribe clients and queries per client Add the following config variables (under [rpc] section): * max_subscription_clients * max_subscriptions_per_client * timeout_broadcast_tx_commit Fixes #2826 new HTTPClient interface for subscriptions finalize HTTPClient events interface remove EventSubscriber fix data race ``` WARNING: DATA RACE Read at 0x00c000a36060 by goroutine 129: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe.func1() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:168 +0x1f0 Previous write at 0x00c000a36060 by goroutine 132: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:191 +0x4e0 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 129 (running) created at: github.com/tendermint/tendermint/rpc/client.(*Local).Subscribe() /go/src/github.com/tendermint/tendermint/rpc/client/localclient.go:164 +0x4b7 github.com/tendermint/tendermint/rpc/client.WaitForOneEvent() /go/src/github.com/tendermint/tendermint/rpc/client/helpers.go:64 +0x178 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync.func1() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:139 +0x298 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Goroutine 132 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x659 github.com/tendermint/tendermint/rpc/client_test.TestTxEventsSentWithBroadcastTxSync() /go/src/github.com/tendermint/tendermint/rpc/client/event_test.go:119 +0x186 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 ================== ``` lite client works (tested manually) godoc comments httpclient: do not close the out channel use TimeoutBroadcastTxCommit no timeout for unsubscribe but 1s Local (5s HTTP) timeout for resubscribe format code change Subscribe#out cap to 1 and replace config vars with RPCConfig TimeoutBroadcastTxCommit can't be greater than rpcserver.WriteTimeout rpc: Context as first parameter to all functions reformat code fixes after my own review fixes after Ethan's review add test stubs fix config.toml * fixes after manual testing - rpc: do not recommend to use BroadcastTxCommit because it's slow and wastes Tendermint resources (pubsub) - rpc: better error in Subscribe and BroadcastTxCommit - HTTPClient: do not resubscribe if err = ErrAlreadySubscribed * fixes after Ismail's review * Update rpc/grpc/grpc_test.go Co-Authored-By: melekes <anton.kalyaev@gmail.com>
6 years ago
mempool: move interface into mempool package (#3524) ## Description Refs #2659 Breaking changes in the mempool package: [mempool] #2659 Mempool now an interface old Mempool renamed to CListMempool NewMempool renamed to NewCListMempool Option renamed to CListOption MempoolReactor renamed to Reactor NewMempoolReactor renamed to NewReactor unexpose TxID method TxInfo.PeerID renamed to SenderID unexpose MempoolReactor.Mempool Breaking changes in the state package: [state] #2659 Mempool interface moved to mempool package MockMempool moved to top-level mock package and renamed to Mempool Non Breaking changes in the node package: [node] #2659 Add Mempool method, which allows you to access mempool ## Commits * move Mempool interface into mempool package Refs #2659 Breaking changes in the mempool package: - Mempool now an interface - old Mempool renamed to CListMempool Breaking changes to state package: - MockMempool moved to mempool/mock package and renamed to Mempool - Mempool interface moved to mempool package * assert CListMempool impl Mempool * gofmt code * rename MempoolReactor to Reactor - combine everything into one interface - rename TxInfo.PeerID to TxInfo.SenderID - unexpose MempoolReactor.Mempool * move mempool mock into top-level mock package * add a fixme TxsFront should not be a part of the Mempool interface because it leaks implementation details. Instead, we need to come up with general interface for querying the mempool so the MempoolReactor can fetch and broadcast txs to peers. * change node#Mempool to return interface * save commit = new reactor arch * Revert "save commit = new reactor arch" This reverts commit 1bfceacd9d65a720574683a7f22771e69af9af4d. * require CListMempool in mempool.Reactor * add two changelog entries * fixes after my own review * quote interfaces, structs and functions * fixes after Ismail's review * make node's mempool an interface * make InitWAL/CloseWAL methods a part of Mempool interface * fix merge conflicts * make node's mempool an interface
6 years ago
mempool: move interface into mempool package (#3524) ## Description Refs #2659 Breaking changes in the mempool package: [mempool] #2659 Mempool now an interface old Mempool renamed to CListMempool NewMempool renamed to NewCListMempool Option renamed to CListOption MempoolReactor renamed to Reactor NewMempoolReactor renamed to NewReactor unexpose TxID method TxInfo.PeerID renamed to SenderID unexpose MempoolReactor.Mempool Breaking changes in the state package: [state] #2659 Mempool interface moved to mempool package MockMempool moved to top-level mock package and renamed to Mempool Non Breaking changes in the node package: [node] #2659 Add Mempool method, which allows you to access mempool ## Commits * move Mempool interface into mempool package Refs #2659 Breaking changes in the mempool package: - Mempool now an interface - old Mempool renamed to CListMempool Breaking changes to state package: - MockMempool moved to mempool/mock package and renamed to Mempool - Mempool interface moved to mempool package * assert CListMempool impl Mempool * gofmt code * rename MempoolReactor to Reactor - combine everything into one interface - rename TxInfo.PeerID to TxInfo.SenderID - unexpose MempoolReactor.Mempool * move mempool mock into top-level mock package * add a fixme TxsFront should not be a part of the Mempool interface because it leaks implementation details. Instead, we need to come up with general interface for querying the mempool so the MempoolReactor can fetch and broadcast txs to peers. * change node#Mempool to return interface * save commit = new reactor arch * Revert "save commit = new reactor arch" This reverts commit 1bfceacd9d65a720574683a7f22771e69af9af4d. * require CListMempool in mempool.Reactor * add two changelog entries * fixes after my own review * quote interfaces, structs and functions * fixes after Ismail's review * make node's mempool an interface * make InitWAL/CloseWAL methods a part of Mempool interface * fix merge conflicts * make node's mempool an interface
6 years ago
mempool: move interface into mempool package (#3524) ## Description Refs #2659 Breaking changes in the mempool package: [mempool] #2659 Mempool now an interface old Mempool renamed to CListMempool NewMempool renamed to NewCListMempool Option renamed to CListOption MempoolReactor renamed to Reactor NewMempoolReactor renamed to NewReactor unexpose TxID method TxInfo.PeerID renamed to SenderID unexpose MempoolReactor.Mempool Breaking changes in the state package: [state] #2659 Mempool interface moved to mempool package MockMempool moved to top-level mock package and renamed to Mempool Non Breaking changes in the node package: [node] #2659 Add Mempool method, which allows you to access mempool ## Commits * move Mempool interface into mempool package Refs #2659 Breaking changes in the mempool package: - Mempool now an interface - old Mempool renamed to CListMempool Breaking changes to state package: - MockMempool moved to mempool/mock package and renamed to Mempool - Mempool interface moved to mempool package * assert CListMempool impl Mempool * gofmt code * rename MempoolReactor to Reactor - combine everything into one interface - rename TxInfo.PeerID to TxInfo.SenderID - unexpose MempoolReactor.Mempool * move mempool mock into top-level mock package * add a fixme TxsFront should not be a part of the Mempool interface because it leaks implementation details. Instead, we need to come up with general interface for querying the mempool so the MempoolReactor can fetch and broadcast txs to peers. * change node#Mempool to return interface * save commit = new reactor arch * Revert "save commit = new reactor arch" This reverts commit 1bfceacd9d65a720574683a7f22771e69af9af4d. * require CListMempool in mempool.Reactor * add two changelog entries * fixes after my own review * quote interfaces, structs and functions * fixes after Ismail's review * make node's mempool an interface * make InitWAL/CloseWAL methods a part of Mempool interface * fix merge conflicts * make node's mempool an interface
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
node: refactor node.NewNode (#3456) The node.NewNode method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the node.TestCreateProposalBlock test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. See also this gist https://gist.github.com/thanethomson/56e1640d057a26186e38ad678a1d114c for some background work done when starting to refactor here. ## Commits: * [WIP] Refactor node.NewNode to simplify The `node.NewNode` method is pretty complex at the moment, an in order to address issues like #3156, we need to simplify the interface for partial node instantiation. In some places, we don't need to build up a full node (like in the `node.TestCreateProposalBlock` test), but the complexity of such partial instantiation needs to be reduced. This PR aims to eventually make this easier/simpler. * Refactor state loading and genesis doc provider into state package * Refactor for clarity of return parameters * Fix incorrect capitalization of error messages * Simplify extracted functions' names * Document optionally-prefixed functions * Refactor optionallyFastSync for clarity of separation of concerns * Restructure function for early return * Restructure function for early return * Remove dependence on deprecated panic functions * refactor code a bit more plus, expose PEXReactor on node * align logger names * add a changelog entry * align logger names 2 * add a note about PEXReactor returning nil
6 years ago
privval: refactor Remote signers (#3370) This PR is related to #3107 and a continuation of #3351 It is important to emphasise that in the privval original design, client/server and listening/dialing roles are inverted and do not follow a conventional interaction. Given two hosts A and B: Host A is listener/client Host B is dialer/server (contains the secret key) When A requires a signature, it needs to wait for B to dial in before it can issue a request. A only accepts a single connection and any failure leads to dropping the connection and waiting for B to reconnect. The original rationale behind this design was based on security. Host B only allows outbound connections to a list of whitelisted hosts. It is not possible to reach B unless B dials in. There are no listening/open ports in B. This PR results in the following changes: Refactors ping/heartbeat to avoid previously existing race conditions. Separates transport (dialer/listener) from signing (client/server) concerns to simplify workflow. Unifies and abstracts away the differences between unix and tcp sockets. A single signer endpoint implementation unifies connection handling code (read/write/close/connection obj) The signer request handler (server side) is customizable to increase testability. Updates and extends unit tests A high level overview of the classes is as follows: Transport (endpoints): The following classes take care of establishing a connection SignerDialerEndpoint SignerListeningEndpoint SignerEndpoint groups common functionality (read/write/timeouts/etc.) Signing (client/server): The following classes take care of exchanging request/responses SignerClient SignerServer This PR also closes #3601 Commits: * refactoring - work in progress * reworking unit tests * Encapsulating and fixing unit tests * Improve tests * Clean up * Fix/improve unit tests * clean up tests * Improving service endpoint * fixing unit test * fix linter issues * avoid invalid cache values (improve later?) * complete implementation * wip * improved connection loop * Improve reconnections + fixing unit tests * addressing comments * small formatting changes * clean up * Update node/node.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client_test.go Co-Authored-By: jleni <juan.leni@zondax.ch> * check during initialization * dropping connecting when writing fails * removing break * use t.log instead * unifying and using cmn.GetFreePort() * review fixes * reordering and unifying drop connection * closing instead of signalling * refactored service loop * removed superfluous brackets * GetPubKey can return errors * Revert "GetPubKey can return errors" This reverts commit 68c06f19b4650389d7e5ab1659b318889028202c. * adding entry to changelog * Update CHANGELOG_PENDING.md Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_listener_endpoint_test.go Co-Authored-By: jleni <juan.leni@zondax.ch> * updating node.go * review fixes * fixes linter * fixing unit test * small fixes in comments * addressing review comments * addressing review comments 2 * reverting suggestion * Update privval/signer_client_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update privval/signer_client_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update privval/signer_listener_endpoint_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * do not expose brokenSignerDialerEndpoint * clean up logging * unifying methods shorten test time signer also drops * reenabling pings * improving testability + unit test * fixing go fmt + unit test * remove unused code * Addressing review comments * simplifying connection workflow * fix linter/go import issue * using base service quit * updating comment * Simplifying design + adjusting names * fixing linter issues * refactoring test harness + fixes * Addressing review comments * cleaning up * adding additional error check
5 years ago
Close and retry a RemoteSigner on err (#2923) * Close and recreate a RemoteSigner on err * Update changelog * Address Anton's comments / suggestions: - update changelog - restart TCPVal - shut down on `ErrUnexpectedResponse` * re-init remote signer client with fresh connection if Ping fails - add/update TODOs in secret connection - rename tcp.go -> tcp_client.go, same with ipc to clarify their purpose * account for `conn returned by waitConnection can be `nil` - also add TODO about RemoteSigner conn field * Tests for retrying: IPC / TCP - shorter info log on success - set conn and use it in tests to close conn * Tests for retrying: IPC / TCP - shorter info log on success - set conn and use it in tests to close conn - add rwmutex for conn field in IPC * comments and doc.go * fix ipc tests. fixes #2677 * use constants for tests * cleanup some error statements * fixes #2784, race in tests * remove print statement * minor fixes from review * update comment on sts spec * cosmetics * p2p/conn: add failing tests * p2p/conn: make SecretConnection thread safe * changelog * IPCVal signer refactor - use a .reset() method - don't use embedded RemoteSignerClient - guard RemoteSignerClient with mutex - drop the .conn - expose Close() on RemoteSignerClient * apply IPCVal refactor to TCPVal * remove mtx from RemoteSignerClient * consolidate IPCVal and TCPVal, fixes #3104 - done in tcp_client.go - now called SocketVal - takes a listener in the constructor - make tcpListener and unixListener contain all the differences * delete ipc files * introduce unix and tcp dialer for RemoteSigner * rename files - drop tcp_ prefix - rename priv_validator.go to file.go * bring back listener options * fix node * fix priv_val_server * fix node test * minor cleanup and comments
6 years ago
privval: refactor Remote signers (#3370) This PR is related to #3107 and a continuation of #3351 It is important to emphasise that in the privval original design, client/server and listening/dialing roles are inverted and do not follow a conventional interaction. Given two hosts A and B: Host A is listener/client Host B is dialer/server (contains the secret key) When A requires a signature, it needs to wait for B to dial in before it can issue a request. A only accepts a single connection and any failure leads to dropping the connection and waiting for B to reconnect. The original rationale behind this design was based on security. Host B only allows outbound connections to a list of whitelisted hosts. It is not possible to reach B unless B dials in. There are no listening/open ports in B. This PR results in the following changes: Refactors ping/heartbeat to avoid previously existing race conditions. Separates transport (dialer/listener) from signing (client/server) concerns to simplify workflow. Unifies and abstracts away the differences between unix and tcp sockets. A single signer endpoint implementation unifies connection handling code (read/write/close/connection obj) The signer request handler (server side) is customizable to increase testability. Updates and extends unit tests A high level overview of the classes is as follows: Transport (endpoints): The following classes take care of establishing a connection SignerDialerEndpoint SignerListeningEndpoint SignerEndpoint groups common functionality (read/write/timeouts/etc.) Signing (client/server): The following classes take care of exchanging request/responses SignerClient SignerServer This PR also closes #3601 Commits: * refactoring - work in progress * reworking unit tests * Encapsulating and fixing unit tests * Improve tests * Clean up * Fix/improve unit tests * clean up tests * Improving service endpoint * fixing unit test * fix linter issues * avoid invalid cache values (improve later?) * complete implementation * wip * improved connection loop * Improve reconnections + fixing unit tests * addressing comments * small formatting changes * clean up * Update node/node.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client_test.go Co-Authored-By: jleni <juan.leni@zondax.ch> * check during initialization * dropping connecting when writing fails * removing break * use t.log instead * unifying and using cmn.GetFreePort() * review fixes * reordering and unifying drop connection * closing instead of signalling * refactored service loop * removed superfluous brackets * GetPubKey can return errors * Revert "GetPubKey can return errors" This reverts commit 68c06f19b4650389d7e5ab1659b318889028202c. * adding entry to changelog * Update CHANGELOG_PENDING.md Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_client.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_dialer_endpoint.go Co-Authored-By: jleni <juan.leni@zondax.ch> * Update privval/signer_listener_endpoint_test.go Co-Authored-By: jleni <juan.leni@zondax.ch> * updating node.go * review fixes * fixes linter * fixing unit test * small fixes in comments * addressing review comments * addressing review comments 2 * reverting suggestion * Update privval/signer_client_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update privval/signer_client_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * Update privval/signer_listener_endpoint_test.go Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com> * do not expose brokenSignerDialerEndpoint * clean up logging * unifying methods shorten test time signer also drops * reenabling pings * improving testability + unit test * fixing go fmt + unit test * remove unused code * Addressing review comments * simplifying connection workflow * fix linter/go import issue * using base service quit * updating comment * Simplifying design + adjusting names * fixing linter issues * refactoring test harness + fixes * Addressing review comments * cleaning up * adding additional error check
5 years ago
  1. package node
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. _ "net/http/pprof" // nolint: gosec // securely exposed on separate, optional port
  9. "strconv"
  10. "time"
  11. _ "github.com/lib/pq" // provide the psql db driver
  12. "github.com/prometheus/client_golang/prometheus"
  13. "github.com/prometheus/client_golang/prometheus/promhttp"
  14. "github.com/rs/cors"
  15. abci "github.com/tendermint/tendermint/abci/types"
  16. cfg "github.com/tendermint/tendermint/config"
  17. "github.com/tendermint/tendermint/crypto"
  18. cs "github.com/tendermint/tendermint/internal/consensus"
  19. "github.com/tendermint/tendermint/internal/evidence"
  20. "github.com/tendermint/tendermint/internal/mempool"
  21. "github.com/tendermint/tendermint/internal/p2p"
  22. "github.com/tendermint/tendermint/internal/p2p/pex"
  23. "github.com/tendermint/tendermint/internal/statesync"
  24. "github.com/tendermint/tendermint/libs/log"
  25. tmnet "github.com/tendermint/tendermint/libs/net"
  26. tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
  27. "github.com/tendermint/tendermint/libs/service"
  28. "github.com/tendermint/tendermint/libs/strings"
  29. tmtime "github.com/tendermint/tendermint/libs/time"
  30. "github.com/tendermint/tendermint/light"
  31. "github.com/tendermint/tendermint/privval"
  32. tmgrpc "github.com/tendermint/tendermint/privval/grpc"
  33. "github.com/tendermint/tendermint/proxy"
  34. rpccore "github.com/tendermint/tendermint/rpc/core"
  35. grpccore "github.com/tendermint/tendermint/rpc/grpc"
  36. rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
  37. sm "github.com/tendermint/tendermint/state"
  38. "github.com/tendermint/tendermint/state/indexer"
  39. "github.com/tendermint/tendermint/store"
  40. "github.com/tendermint/tendermint/types"
  41. )
  42. // nodeImpl is the highest level interface to a full Tendermint node.
  43. // It includes all configuration information and running services.
  44. type nodeImpl struct {
  45. service.BaseService
  46. // config
  47. config *cfg.Config
  48. genesisDoc *types.GenesisDoc // initial validator set
  49. privValidator types.PrivValidator // local node's validator key
  50. // network
  51. transport *p2p.MConnTransport
  52. sw *p2p.Switch // p2p connections
  53. peerManager *p2p.PeerManager
  54. router *p2p.Router
  55. addrBook pex.AddrBook // known peers
  56. nodeInfo types.NodeInfo
  57. nodeKey types.NodeKey // our node privkey
  58. isListening bool
  59. // services
  60. eventBus *types.EventBus // pub/sub for services
  61. stateStore sm.Store
  62. blockStore *store.BlockStore // store the blockchain to disk
  63. bcReactor service.Service // for fast-syncing
  64. mempoolReactor service.Service // for gossipping transactions
  65. mempool mempool.Mempool
  66. stateSync bool // whether the node should state sync on startup
  67. stateSyncReactor *statesync.Reactor // for hosting and restoring state sync snapshots
  68. consensusState *cs.State // latest consensus state
  69. consensusReactor *cs.Reactor // for participating in the consensus
  70. pexReactor *pex.Reactor // for exchanging peer addresses
  71. pexReactorV2 *pex.ReactorV2 // for exchanging peer addresses
  72. evidenceReactor *evidence.Reactor
  73. evidencePool *evidence.Pool // tracking evidence
  74. proxyApp proxy.AppConns // connection to the application
  75. rpcListeners []net.Listener // rpc servers
  76. eventSinks []indexer.EventSink
  77. indexerService *indexer.Service
  78. prometheusSrv *http.Server
  79. }
  80. // newDefaultNode returns a Tendermint node with default settings for the
  81. // PrivValidator, ClientCreator, GenesisDoc, and DBProvider.
  82. // It implements NodeProvider.
  83. func newDefaultNode(config *cfg.Config, logger log.Logger) (service.Service, error) {
  84. nodeKey, err := types.LoadOrGenNodeKey(config.NodeKeyFile())
  85. if err != nil {
  86. return nil, fmt.Errorf("failed to load or gen node key %s: %w", config.NodeKeyFile(), err)
  87. }
  88. if config.Mode == cfg.ModeSeed {
  89. return makeSeedNode(config,
  90. cfg.DefaultDBProvider,
  91. nodeKey,
  92. defaultGenesisDocProviderFunc(config),
  93. logger,
  94. )
  95. }
  96. var pval *privval.FilePV
  97. if config.Mode == cfg.ModeValidator {
  98. pval, err = privval.LoadOrGenFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
  99. if err != nil {
  100. return nil, err
  101. }
  102. } else {
  103. pval = nil
  104. }
  105. appClient, _ := proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir())
  106. return makeNode(config,
  107. pval,
  108. nodeKey,
  109. appClient,
  110. defaultGenesisDocProviderFunc(config),
  111. cfg.DefaultDBProvider,
  112. logger,
  113. )
  114. }
  115. // makeNode returns a new, ready to go, Tendermint Node.
  116. func makeNode(config *cfg.Config,
  117. privValidator types.PrivValidator,
  118. nodeKey types.NodeKey,
  119. clientCreator proxy.ClientCreator,
  120. genesisDocProvider genesisDocProvider,
  121. dbProvider cfg.DBProvider,
  122. logger log.Logger) (service.Service, error) {
  123. blockStore, stateDB, err := initDBs(config, dbProvider)
  124. if err != nil {
  125. return nil, err
  126. }
  127. stateStore := sm.NewStore(stateDB)
  128. genDoc, err := genesisDocProvider()
  129. if err != nil {
  130. return nil, err
  131. }
  132. err = genDoc.ValidateAndComplete()
  133. if err != nil {
  134. return nil, fmt.Errorf("error in genesis doc: %w", err)
  135. }
  136. state, err := loadStateFromDBOrGenesisDocProvider(stateStore, genDoc)
  137. if err != nil {
  138. return nil, err
  139. }
  140. // Create the proxyApp and establish connections to the ABCI app (consensus, mempool, query).
  141. proxyApp, err := createAndStartProxyAppConns(clientCreator, logger)
  142. if err != nil {
  143. return nil, err
  144. }
  145. // EventBus and IndexerService must be started before the handshake because
  146. // we might need to index the txs of the replayed block as this might not have happened
  147. // when the node stopped last time (i.e. the node stopped after it saved the block
  148. // but before it indexed the txs, or, endblocker panicked)
  149. eventBus, err := createAndStartEventBus(logger)
  150. if err != nil {
  151. return nil, err
  152. }
  153. indexerService, eventSinks, err := createAndStartIndexerService(config, dbProvider, eventBus, logger, genDoc.ChainID)
  154. if err != nil {
  155. return nil, err
  156. }
  157. // If an address is provided, listen on the socket for a connection from an
  158. // external signing process.
  159. if config.PrivValidator.ListenAddr != "" {
  160. protocol, _ := tmnet.ProtocolAndAddress(config.PrivValidator.ListenAddr)
  161. // FIXME: we should start services inside OnStart
  162. switch protocol {
  163. case "grpc":
  164. privValidator, err = createAndStartPrivValidatorGRPCClient(config, genDoc.ChainID, logger)
  165. if err != nil {
  166. return nil, fmt.Errorf("error with private validator grpc client: %w", err)
  167. }
  168. default:
  169. privValidator, err = createAndStartPrivValidatorSocketClient(config.PrivValidator.ListenAddr, genDoc.ChainID, logger)
  170. if err != nil {
  171. return nil, fmt.Errorf("error with private validator socket client: %w", err)
  172. }
  173. }
  174. }
  175. var pubKey crypto.PubKey
  176. if config.Mode == cfg.ModeValidator {
  177. pubKey, err = privValidator.GetPubKey(context.TODO())
  178. if err != nil {
  179. return nil, fmt.Errorf("can't get pubkey: %w", err)
  180. }
  181. if pubKey == nil {
  182. return nil, errors.New("could not retrieve public key from private validator")
  183. }
  184. }
  185. // Determine whether we should attempt state sync.
  186. stateSync := config.StateSync.Enable && !onlyValidatorIsUs(state, pubKey)
  187. if stateSync && state.LastBlockHeight > 0 {
  188. logger.Info("Found local state with non-zero height, skipping state sync")
  189. stateSync = false
  190. }
  191. // Create the handshaker, which calls RequestInfo, sets the AppVersion on the state,
  192. // and replays any blocks as necessary to sync tendermint with the app.
  193. consensusLogger := logger.With("module", "consensus")
  194. if !stateSync {
  195. if err := doHandshake(stateStore, state, blockStore, genDoc, eventBus, proxyApp, consensusLogger); err != nil {
  196. return nil, err
  197. }
  198. // Reload the state. It will have the Version.Consensus.App set by the
  199. // Handshake, and may have other modifications as well (ie. depending on
  200. // what happened during block replay).
  201. state, err = stateStore.Load()
  202. if err != nil {
  203. return nil, fmt.Errorf("cannot load state: %w", err)
  204. }
  205. }
  206. // Determine whether we should do fast sync. This must happen after the handshake, since the
  207. // app may modify the validator set, specifying ourself as the only validator.
  208. fastSync := config.FastSyncMode && !onlyValidatorIsUs(state, pubKey)
  209. logNodeStartupInfo(state, pubKey, logger, consensusLogger, config.Mode)
  210. // TODO: Fetch and provide real options and do proper p2p bootstrapping.
  211. // TODO: Use a persistent peer database.
  212. nodeInfo, err := makeNodeInfo(config, nodeKey, eventSinks, genDoc, state)
  213. if err != nil {
  214. return nil, err
  215. }
  216. p2pLogger := logger.With("module", "p2p")
  217. transport := createTransport(p2pLogger, config)
  218. peerManager, err := createPeerManager(config, dbProvider, p2pLogger, nodeKey.ID)
  219. if err != nil {
  220. return nil, fmt.Errorf("failed to create peer manager: %w", err)
  221. }
  222. csMetrics, p2pMetrics, memplMetrics, smMetrics := defaultMetricsProvider(config.Instrumentation)(genDoc.ChainID)
  223. router, err := createRouter(p2pLogger, p2pMetrics, nodeInfo, nodeKey.PrivKey,
  224. peerManager, transport, getRouterConfig(config, proxyApp))
  225. if err != nil {
  226. return nil, fmt.Errorf("failed to create router: %w", err)
  227. }
  228. mpReactorShim, mpReactor, mp, err := createMempoolReactor(
  229. config, proxyApp, state, memplMetrics, peerManager, router, logger,
  230. )
  231. if err != nil {
  232. return nil, err
  233. }
  234. evReactorShim, evReactor, evPool, err := createEvidenceReactor(
  235. config, dbProvider, stateDB, blockStore, peerManager, router, logger,
  236. )
  237. if err != nil {
  238. return nil, err
  239. }
  240. // make block executor for consensus and blockchain reactors to execute blocks
  241. blockExec := sm.NewBlockExecutor(
  242. stateStore,
  243. logger.With("module", "state"),
  244. proxyApp.Consensus(),
  245. mp,
  246. evPool,
  247. blockStore,
  248. sm.BlockExecutorWithMetrics(smMetrics),
  249. )
  250. csReactorShim, csReactor, csState := createConsensusReactor(
  251. config, state, blockExec, blockStore, mp, evPool,
  252. privValidator, csMetrics, stateSync || fastSync, eventBus,
  253. peerManager, router, consensusLogger,
  254. )
  255. // Create the blockchain reactor. Note, we do not start fast sync if we're
  256. // doing a state sync first.
  257. bcReactorShim, bcReactor, err := createBlockchainReactor(
  258. logger, config, state, blockExec, blockStore, csReactor,
  259. peerManager, router, fastSync && !stateSync, csMetrics,
  260. )
  261. if err != nil {
  262. return nil, fmt.Errorf("could not create blockchain reactor: %w", err)
  263. }
  264. // TODO: Remove this once the switch is removed.
  265. var bcReactorForSwitch p2p.Reactor
  266. if bcReactorShim != nil {
  267. bcReactorForSwitch = bcReactorShim
  268. } else {
  269. bcReactorForSwitch = bcReactor.(p2p.Reactor)
  270. }
  271. // Make ConsensusReactor. Don't enable fully if doing a state sync and/or fast sync first.
  272. // FIXME We need to update metrics here, since other reactors don't have access to them.
  273. if stateSync {
  274. csMetrics.StateSyncing.Set(1)
  275. } else if fastSync {
  276. csMetrics.FastSyncing.Set(1)
  277. }
  278. // Set up state sync reactor, and schedule a sync if requested.
  279. // FIXME The way we do phased startups (e.g. replay -> fast sync -> consensus) is very messy,
  280. // we should clean this whole thing up. See:
  281. // https://github.com/tendermint/tendermint/issues/4644
  282. var (
  283. stateSyncReactor *statesync.Reactor
  284. stateSyncReactorShim *p2p.ReactorShim
  285. channels map[p2p.ChannelID]*p2p.Channel
  286. peerUpdates *p2p.PeerUpdates
  287. )
  288. stateSyncReactorShim = p2p.NewReactorShim(logger.With("module", "statesync"), "StateSyncShim", statesync.ChannelShims)
  289. if config.P2P.DisableLegacy {
  290. channels = makeChannelsFromShims(router, statesync.ChannelShims)
  291. peerUpdates = peerManager.Subscribe()
  292. } else {
  293. channels = getChannelsFromShim(stateSyncReactorShim)
  294. peerUpdates = stateSyncReactorShim.PeerUpdates
  295. }
  296. stateSyncReactor = statesync.NewReactor(
  297. *config.StateSync,
  298. stateSyncReactorShim.Logger,
  299. proxyApp.Snapshot(),
  300. proxyApp.Query(),
  301. channels[statesync.SnapshotChannel],
  302. channels[statesync.ChunkChannel],
  303. channels[statesync.LightBlockChannel],
  304. peerUpdates,
  305. stateStore,
  306. blockStore,
  307. config.StateSync.TempDir,
  308. )
  309. // add the channel descriptors to both the transports
  310. // FIXME: This should be removed when the legacy p2p stack is removed and
  311. // transports can either be agnostic to channel descriptors or can be
  312. // declared in the constructor.
  313. transport.AddChannelDescriptors(mpReactorShim.GetChannels())
  314. transport.AddChannelDescriptors(bcReactorForSwitch.GetChannels())
  315. transport.AddChannelDescriptors(csReactorShim.GetChannels())
  316. transport.AddChannelDescriptors(evReactorShim.GetChannels())
  317. transport.AddChannelDescriptors(stateSyncReactorShim.GetChannels())
  318. // Optionally, start the pex reactor
  319. //
  320. // TODO:
  321. //
  322. // We need to set Seeds and PersistentPeers on the switch,
  323. // since it needs to be able to use these (and their DNS names)
  324. // even if the PEX is off. We can include the DNS name in the NetAddress,
  325. // but it would still be nice to have a clear list of the current "PersistentPeers"
  326. // somewhere that we can return with net_info.
  327. //
  328. // If PEX is on, it should handle dialing the seeds. Otherwise the switch does it.
  329. // Note we currently use the addrBook regardless at least for AddOurAddress
  330. var (
  331. pexReactor *pex.Reactor
  332. pexReactorV2 *pex.ReactorV2
  333. sw *p2p.Switch
  334. addrBook pex.AddrBook
  335. )
  336. pexCh := pex.ChannelDescriptor()
  337. transport.AddChannelDescriptors([]*p2p.ChannelDescriptor{&pexCh})
  338. if config.P2P.DisableLegacy {
  339. addrBook = nil
  340. pexReactorV2, err = createPEXReactorV2(config, logger, peerManager, router)
  341. if err != nil {
  342. return nil, err
  343. }
  344. } else {
  345. // setup Transport and Switch
  346. sw = createSwitch(
  347. config, transport, p2pMetrics, mpReactorShim, bcReactorForSwitch,
  348. stateSyncReactorShim, csReactorShim, evReactorShim, proxyApp, nodeInfo, nodeKey, p2pLogger,
  349. )
  350. err = sw.AddPersistentPeers(strings.SplitAndTrimEmpty(config.P2P.PersistentPeers, ",", " "))
  351. if err != nil {
  352. return nil, fmt.Errorf("could not add peers from persistent-peers field: %w", err)
  353. }
  354. err = sw.AddUnconditionalPeerIDs(strings.SplitAndTrimEmpty(config.P2P.UnconditionalPeerIDs, ",", " "))
  355. if err != nil {
  356. return nil, fmt.Errorf("could not add peer ids from unconditional_peer_ids field: %w", err)
  357. }
  358. addrBook, err = createAddrBookAndSetOnSwitch(config, sw, p2pLogger, nodeKey)
  359. if err != nil {
  360. return nil, fmt.Errorf("could not create addrbook: %w", err)
  361. }
  362. pexReactor = createPEXReactorAndAddToSwitch(addrBook, config, sw, logger)
  363. }
  364. if config.RPC.PprofListenAddress != "" {
  365. go func() {
  366. logger.Info("Starting pprof server", "laddr", config.RPC.PprofListenAddress)
  367. logger.Error("pprof server error", "err", http.ListenAndServe(config.RPC.PprofListenAddress, nil))
  368. }()
  369. }
  370. node := &nodeImpl{
  371. config: config,
  372. genesisDoc: genDoc,
  373. privValidator: privValidator,
  374. transport: transport,
  375. sw: sw,
  376. peerManager: peerManager,
  377. router: router,
  378. addrBook: addrBook,
  379. nodeInfo: nodeInfo,
  380. nodeKey: nodeKey,
  381. stateStore: stateStore,
  382. blockStore: blockStore,
  383. bcReactor: bcReactor,
  384. mempoolReactor: mpReactor,
  385. mempool: mp,
  386. consensusState: csState,
  387. consensusReactor: csReactor,
  388. stateSyncReactor: stateSyncReactor,
  389. stateSync: stateSync,
  390. pexReactor: pexReactor,
  391. pexReactorV2: pexReactorV2,
  392. evidenceReactor: evReactor,
  393. evidencePool: evPool,
  394. proxyApp: proxyApp,
  395. indexerService: indexerService,
  396. eventBus: eventBus,
  397. eventSinks: eventSinks,
  398. }
  399. node.BaseService = *service.NewBaseService(logger, "Node", node)
  400. return node, nil
  401. }
  402. // makeSeedNode returns a new seed node, containing only p2p, pex reactor
  403. func makeSeedNode(config *cfg.Config,
  404. dbProvider cfg.DBProvider,
  405. nodeKey types.NodeKey,
  406. genesisDocProvider genesisDocProvider,
  407. logger log.Logger,
  408. ) (service.Service, error) {
  409. genDoc, err := genesisDocProvider()
  410. if err != nil {
  411. return nil, err
  412. }
  413. state, err := sm.MakeGenesisState(genDoc)
  414. if err != nil {
  415. return nil, err
  416. }
  417. nodeInfo, err := makeSeedNodeInfo(config, nodeKey, genDoc, state)
  418. if err != nil {
  419. return nil, err
  420. }
  421. // Setup Transport and Switch.
  422. p2pMetrics := p2p.PrometheusMetrics(config.Instrumentation.Namespace, "chain_id", genDoc.ChainID)
  423. p2pLogger := logger.With("module", "p2p")
  424. transport := createTransport(p2pLogger, config)
  425. sw := createSwitch(
  426. config, transport, p2pMetrics, nil, nil,
  427. nil, nil, nil, nil, nodeInfo, nodeKey, p2pLogger,
  428. )
  429. err = sw.AddPersistentPeers(strings.SplitAndTrimEmpty(config.P2P.PersistentPeers, ",", " "))
  430. if err != nil {
  431. return nil, fmt.Errorf("could not add peers from persistent_peers field: %w", err)
  432. }
  433. err = sw.AddUnconditionalPeerIDs(strings.SplitAndTrimEmpty(config.P2P.UnconditionalPeerIDs, ",", " "))
  434. if err != nil {
  435. return nil, fmt.Errorf("could not add peer ids from unconditional_peer_ids field: %w", err)
  436. }
  437. addrBook, err := createAddrBookAndSetOnSwitch(config, sw, p2pLogger, nodeKey)
  438. if err != nil {
  439. return nil, fmt.Errorf("could not create addrbook: %w", err)
  440. }
  441. peerManager, err := createPeerManager(config, dbProvider, p2pLogger, nodeKey.ID)
  442. if err != nil {
  443. return nil, fmt.Errorf("failed to create peer manager: %w", err)
  444. }
  445. router, err := createRouter(p2pLogger, p2pMetrics, nodeInfo, nodeKey.PrivKey,
  446. peerManager, transport, getRouterConfig(config, nil))
  447. if err != nil {
  448. return nil, fmt.Errorf("failed to create router: %w", err)
  449. }
  450. var (
  451. pexReactor *pex.Reactor
  452. pexReactorV2 *pex.ReactorV2
  453. )
  454. // add the pex reactor
  455. // FIXME: we add channel descriptors to both the router and the transport but only the router
  456. // should be aware of channel info. We should remove this from transport once the legacy
  457. // p2p stack is removed.
  458. pexCh := pex.ChannelDescriptor()
  459. transport.AddChannelDescriptors([]*p2p.ChannelDescriptor{&pexCh})
  460. if config.P2P.DisableLegacy {
  461. pexReactorV2, err = createPEXReactorV2(config, logger, peerManager, router)
  462. if err != nil {
  463. return nil, err
  464. }
  465. } else {
  466. pexReactor = createPEXReactorAndAddToSwitch(addrBook, config, sw, logger)
  467. }
  468. if config.RPC.PprofListenAddress != "" {
  469. go func() {
  470. logger.Info("Starting pprof server", "laddr", config.RPC.PprofListenAddress)
  471. logger.Error("pprof server error", "err", http.ListenAndServe(config.RPC.PprofListenAddress, nil))
  472. }()
  473. }
  474. node := &nodeImpl{
  475. config: config,
  476. genesisDoc: genDoc,
  477. transport: transport,
  478. sw: sw,
  479. addrBook: addrBook,
  480. nodeInfo: nodeInfo,
  481. nodeKey: nodeKey,
  482. peerManager: peerManager,
  483. router: router,
  484. pexReactor: pexReactor,
  485. pexReactorV2: pexReactorV2,
  486. }
  487. node.BaseService = *service.NewBaseService(logger, "SeedNode", node)
  488. return node, nil
  489. }
  490. // OnStart starts the Node. It implements service.Service.
  491. func (n *nodeImpl) OnStart() error {
  492. now := tmtime.Now()
  493. genTime := n.genesisDoc.GenesisTime
  494. if genTime.After(now) {
  495. n.Logger.Info("Genesis time is in the future. Sleeping until then...", "genTime", genTime)
  496. time.Sleep(genTime.Sub(now))
  497. }
  498. // Start the RPC server before the P2P server
  499. // so we can eg. receive txs for the first block
  500. if n.config.RPC.ListenAddress != "" && n.config.Mode != cfg.ModeSeed {
  501. listeners, err := n.startRPC()
  502. if err != nil {
  503. return err
  504. }
  505. n.rpcListeners = listeners
  506. }
  507. if n.config.Instrumentation.Prometheus &&
  508. n.config.Instrumentation.PrometheusListenAddr != "" {
  509. n.prometheusSrv = n.startPrometheusServer(n.config.Instrumentation.PrometheusListenAddr)
  510. }
  511. // Start the transport.
  512. addr, err := types.NewNetAddressString(n.nodeKey.ID.AddressString(n.config.P2P.ListenAddress))
  513. if err != nil {
  514. return err
  515. }
  516. if err := n.transport.Listen(p2p.NewEndpoint(addr)); err != nil {
  517. return err
  518. }
  519. n.isListening = true
  520. n.Logger.Info("p2p service", "legacy_enabled", !n.config.P2P.DisableLegacy)
  521. if n.config.P2P.DisableLegacy {
  522. err = n.router.Start()
  523. } else {
  524. // Add private IDs to addrbook to block those peers being added
  525. n.addrBook.AddPrivateIDs(strings.SplitAndTrimEmpty(n.config.P2P.PrivatePeerIDs, ",", " "))
  526. err = n.sw.Start()
  527. }
  528. if err != nil {
  529. return err
  530. }
  531. if n.config.Mode != cfg.ModeSeed {
  532. if n.config.FastSync.Version == cfg.BlockchainV0 {
  533. // Start the real blockchain reactor separately since the switch uses the shim.
  534. if err := n.bcReactor.Start(); err != nil {
  535. return err
  536. }
  537. }
  538. // Start the real consensus reactor separately since the switch uses the shim.
  539. if err := n.consensusReactor.Start(); err != nil {
  540. return err
  541. }
  542. // Start the real state sync reactor separately since the switch uses the shim.
  543. if err := n.stateSyncReactor.Start(); err != nil {
  544. return err
  545. }
  546. // Start the real mempool reactor separately since the switch uses the shim.
  547. if err := n.mempoolReactor.Start(); err != nil {
  548. return err
  549. }
  550. // Start the real evidence reactor separately since the switch uses the shim.
  551. if err := n.evidenceReactor.Start(); err != nil {
  552. return err
  553. }
  554. }
  555. if n.config.P2P.DisableLegacy && n.pexReactorV2 != nil {
  556. if err := n.pexReactorV2.Start(); err != nil {
  557. return err
  558. }
  559. } else {
  560. // Always connect to persistent peers
  561. err = n.sw.DialPeersAsync(strings.SplitAndTrimEmpty(n.config.P2P.PersistentPeers, ",", " "))
  562. if err != nil {
  563. return fmt.Errorf("could not dial peers from persistent-peers field: %w", err)
  564. }
  565. }
  566. // Run state sync
  567. if n.stateSync {
  568. bcR, ok := n.bcReactor.(cs.FastSyncReactor)
  569. if !ok {
  570. return fmt.Errorf("this blockchain reactor does not support switching from state sync")
  571. }
  572. // we need to get the genesis state to get parameters such as
  573. state, err := sm.MakeGenesisState(n.genesisDoc)
  574. if err != nil {
  575. return fmt.Errorf("unable to derive state: %w", err)
  576. }
  577. ssc := n.config.StateSync
  578. sp, err := constructStateProvider(ssc, state, n.Logger.With("module", "light"))
  579. if err != nil {
  580. return fmt.Errorf("failed to set up light client state provider: %w", err)
  581. }
  582. if err := startStateSync(n.stateSyncReactor, bcR, n.consensusReactor, sp,
  583. ssc, n.config.FastSyncMode, state.InitialHeight, n.eventBus); err != nil {
  584. return fmt.Errorf("failed to start state sync: %w", err)
  585. }
  586. }
  587. return nil
  588. }
  589. // OnStop stops the Node. It implements service.Service.
  590. func (n *nodeImpl) OnStop() {
  591. n.Logger.Info("Stopping Node")
  592. // first stop the non-reactor services
  593. if err := n.eventBus.Stop(); err != nil {
  594. n.Logger.Error("Error closing eventBus", "err", err)
  595. }
  596. if err := n.indexerService.Stop(); err != nil {
  597. n.Logger.Error("Error closing indexerService", "err", err)
  598. }
  599. if n.config.Mode != cfg.ModeSeed {
  600. // now stop the reactors
  601. if n.config.FastSync.Version == cfg.BlockchainV0 {
  602. // Stop the real blockchain reactor separately since the switch uses the shim.
  603. if err := n.bcReactor.Stop(); err != nil {
  604. n.Logger.Error("failed to stop the blockchain reactor", "err", err)
  605. }
  606. }
  607. // Stop the real consensus reactor separately since the switch uses the shim.
  608. if err := n.consensusReactor.Stop(); err != nil {
  609. n.Logger.Error("failed to stop the consensus reactor", "err", err)
  610. }
  611. // Stop the real state sync reactor separately since the switch uses the shim.
  612. if err := n.stateSyncReactor.Stop(); err != nil {
  613. n.Logger.Error("failed to stop the state sync reactor", "err", err)
  614. }
  615. // Stop the real mempool reactor separately since the switch uses the shim.
  616. if err := n.mempoolReactor.Stop(); err != nil {
  617. n.Logger.Error("failed to stop the mempool reactor", "err", err)
  618. }
  619. // Stop the real evidence reactor separately since the switch uses the shim.
  620. if err := n.evidenceReactor.Stop(); err != nil {
  621. n.Logger.Error("failed to stop the evidence reactor", "err", err)
  622. }
  623. }
  624. if n.config.P2P.DisableLegacy && n.pexReactorV2 != nil {
  625. if err := n.pexReactorV2.Stop(); err != nil {
  626. n.Logger.Error("failed to stop the PEX v2 reactor", "err", err)
  627. }
  628. }
  629. if n.config.P2P.DisableLegacy {
  630. if err := n.router.Stop(); err != nil {
  631. n.Logger.Error("failed to stop router", "err", err)
  632. }
  633. } else {
  634. if err := n.sw.Stop(); err != nil {
  635. n.Logger.Error("failed to stop switch", "err", err)
  636. }
  637. }
  638. if err := n.transport.Close(); err != nil {
  639. n.Logger.Error("Error closing transport", "err", err)
  640. }
  641. n.isListening = false
  642. // finally stop the listeners / external services
  643. for _, l := range n.rpcListeners {
  644. n.Logger.Info("Closing rpc listener", "listener", l)
  645. if err := l.Close(); err != nil {
  646. n.Logger.Error("Error closing listener", "listener", l, "err", err)
  647. }
  648. }
  649. if pvsc, ok := n.privValidator.(service.Service); ok {
  650. if err := pvsc.Stop(); err != nil {
  651. n.Logger.Error("Error closing private validator", "err", err)
  652. }
  653. }
  654. if n.prometheusSrv != nil {
  655. if err := n.prometheusSrv.Shutdown(context.Background()); err != nil {
  656. // Error from closing listeners, or context timeout:
  657. n.Logger.Error("Prometheus HTTP server Shutdown", "err", err)
  658. }
  659. }
  660. }
  661. // ConfigureRPC makes sure RPC has all the objects it needs to operate.
  662. func (n *nodeImpl) ConfigureRPC() (*rpccore.Environment, error) {
  663. rpcCoreEnv := rpccore.Environment{
  664. ProxyAppQuery: n.proxyApp.Query(),
  665. ProxyAppMempool: n.proxyApp.Mempool(),
  666. StateStore: n.stateStore,
  667. BlockStore: n.blockStore,
  668. EvidencePool: n.evidencePool,
  669. ConsensusState: n.consensusState,
  670. P2PPeers: n.sw,
  671. P2PTransport: n,
  672. GenDoc: n.genesisDoc,
  673. EventSinks: n.eventSinks,
  674. ConsensusReactor: n.consensusReactor,
  675. EventBus: n.eventBus,
  676. Mempool: n.mempool,
  677. Logger: n.Logger.With("module", "rpc"),
  678. Config: *n.config.RPC,
  679. FastSyncReactor: n.bcReactor.(cs.FastSyncReactor),
  680. }
  681. if n.config.Mode == cfg.ModeValidator {
  682. pubKey, err := n.privValidator.GetPubKey(context.TODO())
  683. if pubKey == nil || err != nil {
  684. return nil, fmt.Errorf("can't get pubkey: %w", err)
  685. }
  686. rpcCoreEnv.PubKey = pubKey
  687. }
  688. if err := rpcCoreEnv.InitGenesisChunks(); err != nil {
  689. return nil, err
  690. }
  691. return &rpcCoreEnv, nil
  692. }
  693. func (n *nodeImpl) startRPC() ([]net.Listener, error) {
  694. env, err := n.ConfigureRPC()
  695. if err != nil {
  696. return nil, err
  697. }
  698. listenAddrs := strings.SplitAndTrimEmpty(n.config.RPC.ListenAddress, ",", " ")
  699. routes := env.GetRoutes()
  700. if n.config.RPC.Unsafe {
  701. env.AddUnsafe(routes)
  702. }
  703. config := rpcserver.DefaultConfig()
  704. config.MaxBodyBytes = n.config.RPC.MaxBodyBytes
  705. config.MaxHeaderBytes = n.config.RPC.MaxHeaderBytes
  706. config.MaxOpenConnections = n.config.RPC.MaxOpenConnections
  707. // If necessary adjust global WriteTimeout to ensure it's greater than
  708. // TimeoutBroadcastTxCommit.
  709. // See https://github.com/tendermint/tendermint/issues/3435
  710. if config.WriteTimeout <= n.config.RPC.TimeoutBroadcastTxCommit {
  711. config.WriteTimeout = n.config.RPC.TimeoutBroadcastTxCommit + 1*time.Second
  712. }
  713. // we may expose the rpc over both a unix and tcp socket
  714. listeners := make([]net.Listener, len(listenAddrs))
  715. for i, listenAddr := range listenAddrs {
  716. mux := http.NewServeMux()
  717. rpcLogger := n.Logger.With("module", "rpc-server")
  718. wmLogger := rpcLogger.With("protocol", "websocket")
  719. wm := rpcserver.NewWebsocketManager(routes,
  720. rpcserver.OnDisconnect(func(remoteAddr string) {
  721. err := n.eventBus.UnsubscribeAll(context.Background(), remoteAddr)
  722. if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
  723. wmLogger.Error("Failed to unsubscribe addr from events", "addr", remoteAddr, "err", err)
  724. }
  725. }),
  726. rpcserver.ReadLimit(config.MaxBodyBytes),
  727. )
  728. wm.SetLogger(wmLogger)
  729. mux.HandleFunc("/websocket", wm.WebsocketHandler)
  730. rpcserver.RegisterRPCFuncs(mux, routes, rpcLogger)
  731. listener, err := rpcserver.Listen(
  732. listenAddr,
  733. config,
  734. )
  735. if err != nil {
  736. return nil, err
  737. }
  738. var rootHandler http.Handler = mux
  739. if n.config.RPC.IsCorsEnabled() {
  740. corsMiddleware := cors.New(cors.Options{
  741. AllowedOrigins: n.config.RPC.CORSAllowedOrigins,
  742. AllowedMethods: n.config.RPC.CORSAllowedMethods,
  743. AllowedHeaders: n.config.RPC.CORSAllowedHeaders,
  744. })
  745. rootHandler = corsMiddleware.Handler(mux)
  746. }
  747. if n.config.RPC.IsTLSEnabled() {
  748. go func() {
  749. if err := rpcserver.ServeTLS(
  750. listener,
  751. rootHandler,
  752. n.config.RPC.CertFile(),
  753. n.config.RPC.KeyFile(),
  754. rpcLogger,
  755. config,
  756. ); err != nil {
  757. n.Logger.Error("Error serving server with TLS", "err", err)
  758. }
  759. }()
  760. } else {
  761. go func() {
  762. if err := rpcserver.Serve(
  763. listener,
  764. rootHandler,
  765. rpcLogger,
  766. config,
  767. ); err != nil {
  768. n.Logger.Error("Error serving server", "err", err)
  769. }
  770. }()
  771. }
  772. listeners[i] = listener
  773. }
  774. // we expose a simplified api over grpc for convenience to app devs
  775. grpcListenAddr := n.config.RPC.GRPCListenAddress
  776. if grpcListenAddr != "" {
  777. config := rpcserver.DefaultConfig()
  778. config.MaxBodyBytes = n.config.RPC.MaxBodyBytes
  779. config.MaxHeaderBytes = n.config.RPC.MaxHeaderBytes
  780. // NOTE: GRPCMaxOpenConnections is used, not MaxOpenConnections
  781. config.MaxOpenConnections = n.config.RPC.GRPCMaxOpenConnections
  782. // If necessary adjust global WriteTimeout to ensure it's greater than
  783. // TimeoutBroadcastTxCommit.
  784. // See https://github.com/tendermint/tendermint/issues/3435
  785. if config.WriteTimeout <= n.config.RPC.TimeoutBroadcastTxCommit {
  786. config.WriteTimeout = n.config.RPC.TimeoutBroadcastTxCommit + 1*time.Second
  787. }
  788. listener, err := rpcserver.Listen(grpcListenAddr, config)
  789. if err != nil {
  790. return nil, err
  791. }
  792. go func() {
  793. if err := grpccore.StartGRPCServer(env, listener); err != nil {
  794. n.Logger.Error("Error starting gRPC server", "err", err)
  795. }
  796. }()
  797. listeners = append(listeners, listener)
  798. }
  799. return listeners, nil
  800. }
  801. // startPrometheusServer starts a Prometheus HTTP server, listening for metrics
  802. // collectors on addr.
  803. func (n *nodeImpl) startPrometheusServer(addr string) *http.Server {
  804. srv := &http.Server{
  805. Addr: addr,
  806. Handler: promhttp.InstrumentMetricHandler(
  807. prometheus.DefaultRegisterer, promhttp.HandlerFor(
  808. prometheus.DefaultGatherer,
  809. promhttp.HandlerOpts{MaxRequestsInFlight: n.config.Instrumentation.MaxOpenConnections},
  810. ),
  811. ),
  812. }
  813. go func() {
  814. if err := srv.ListenAndServe(); err != http.ErrServerClosed {
  815. // Error starting or closing listener:
  816. n.Logger.Error("Prometheus HTTP server ListenAndServe", "err", err)
  817. }
  818. }()
  819. return srv
  820. }
  821. // Switch returns the Node's Switch.
  822. func (n *nodeImpl) Switch() *p2p.Switch {
  823. return n.sw
  824. }
  825. // BlockStore returns the Node's BlockStore.
  826. func (n *nodeImpl) BlockStore() *store.BlockStore {
  827. return n.blockStore
  828. }
  829. // ConsensusState returns the Node's ConsensusState.
  830. func (n *nodeImpl) ConsensusState() *cs.State {
  831. return n.consensusState
  832. }
  833. // ConsensusReactor returns the Node's ConsensusReactor.
  834. func (n *nodeImpl) ConsensusReactor() *cs.Reactor {
  835. return n.consensusReactor
  836. }
  837. // MempoolReactor returns the Node's mempool reactor.
  838. func (n *nodeImpl) MempoolReactor() service.Service {
  839. return n.mempoolReactor
  840. }
  841. // Mempool returns the Node's mempool.
  842. func (n *nodeImpl) Mempool() mempool.Mempool {
  843. return n.mempool
  844. }
  845. // PEXReactor returns the Node's PEXReactor. It returns nil if PEX is disabled.
  846. func (n *nodeImpl) PEXReactor() *pex.Reactor {
  847. return n.pexReactor
  848. }
  849. // EvidencePool returns the Node's EvidencePool.
  850. func (n *nodeImpl) EvidencePool() *evidence.Pool {
  851. return n.evidencePool
  852. }
  853. // EventBus returns the Node's EventBus.
  854. func (n *nodeImpl) EventBus() *types.EventBus {
  855. return n.eventBus
  856. }
  857. // PrivValidator returns the Node's PrivValidator.
  858. // XXX: for convenience only!
  859. func (n *nodeImpl) PrivValidator() types.PrivValidator {
  860. return n.privValidator
  861. }
  862. // GenesisDoc returns the Node's GenesisDoc.
  863. func (n *nodeImpl) GenesisDoc() *types.GenesisDoc {
  864. return n.genesisDoc
  865. }
  866. // ProxyApp returns the Node's AppConns, representing its connections to the ABCI application.
  867. func (n *nodeImpl) ProxyApp() proxy.AppConns {
  868. return n.proxyApp
  869. }
  870. // Config returns the Node's config.
  871. func (n *nodeImpl) Config() *cfg.Config {
  872. return n.config
  873. }
  874. // EventSinks returns the Node's event indexing sinks.
  875. func (n *nodeImpl) EventSinks() []indexer.EventSink {
  876. return n.eventSinks
  877. }
  878. //------------------------------------------------------------------------------
  879. func (n *nodeImpl) Listeners() []string {
  880. return []string{
  881. fmt.Sprintf("Listener(@%v)", n.config.P2P.ExternalAddress),
  882. }
  883. }
  884. func (n *nodeImpl) IsListening() bool {
  885. return n.isListening
  886. }
  887. // NodeInfo returns the Node's Info from the Switch.
  888. func (n *nodeImpl) NodeInfo() types.NodeInfo {
  889. return n.nodeInfo
  890. }
  891. // startStateSync starts an asynchronous state sync process, then switches to fast sync mode.
  892. func startStateSync(
  893. ssR statesync.SyncReactor,
  894. bcR cs.FastSyncReactor,
  895. conR cs.ConsSyncReactor,
  896. sp statesync.StateProvider,
  897. config *cfg.StateSyncConfig,
  898. fastSync bool,
  899. stateInitHeight int64,
  900. eb *types.EventBus,
  901. ) error {
  902. stateSyncLogger := eb.Logger.With("module", "statesync")
  903. stateSyncLogger.Info("starting state sync...")
  904. // at the beginning of the statesync start, we use the initialHeight as the event height
  905. // because of the statesync doesn't have the concreate state height before fetched the snapshot.
  906. d := types.EventDataStateSyncStatus{Complete: false, Height: stateInitHeight}
  907. if err := eb.PublishEventStateSyncStatus(d); err != nil {
  908. stateSyncLogger.Error("failed to emit the statesync start event", "err", err)
  909. }
  910. go func() {
  911. state, err := ssR.Sync(context.TODO(), sp, config.DiscoveryTime)
  912. if err != nil {
  913. stateSyncLogger.Error("state sync failed", "err", err)
  914. return
  915. }
  916. if err := ssR.Backfill(state); err != nil {
  917. stateSyncLogger.Error("backfill failed; node has insufficient history to verify all evidence;"+
  918. " proceeding optimistically...", "err", err)
  919. }
  920. conR.SetStateSyncingMetrics(0)
  921. d := types.EventDataStateSyncStatus{Complete: true, Height: state.LastBlockHeight}
  922. if err := eb.PublishEventStateSyncStatus(d); err != nil {
  923. stateSyncLogger.Error("failed to emit the statesync start event", "err", err)
  924. }
  925. if fastSync {
  926. // FIXME Very ugly to have these metrics bleed through here.
  927. conR.SetFastSyncingMetrics(1)
  928. if err := bcR.SwitchToFastSync(state); err != nil {
  929. stateSyncLogger.Error("failed to switch to fast sync", "err", err)
  930. return
  931. }
  932. d := types.EventDataFastSyncStatus{Complete: false, Height: state.LastBlockHeight}
  933. if err := eb.PublishEventFastSyncStatus(d); err != nil {
  934. stateSyncLogger.Error("failed to emit the fastsync starting event", "err", err)
  935. }
  936. } else {
  937. conR.SwitchToConsensus(state, true)
  938. }
  939. }()
  940. return nil
  941. }
  942. // genesisDocProvider returns a GenesisDoc.
  943. // It allows the GenesisDoc to be pulled from sources other than the
  944. // filesystem, for instance from a distributed key-value store cluster.
  945. type genesisDocProvider func() (*types.GenesisDoc, error)
  946. // defaultGenesisDocProviderFunc returns a GenesisDocProvider that loads
  947. // the GenesisDoc from the config.GenesisFile() on the filesystem.
  948. func defaultGenesisDocProviderFunc(config *cfg.Config) genesisDocProvider {
  949. return func() (*types.GenesisDoc, error) {
  950. return types.GenesisDocFromFile(config.GenesisFile())
  951. }
  952. }
  953. // metricsProvider returns a consensus, p2p and mempool Metrics.
  954. type metricsProvider func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempool.Metrics, *sm.Metrics)
  955. // defaultMetricsProvider returns Metrics build using Prometheus client library
  956. // if Prometheus is enabled. Otherwise, it returns no-op Metrics.
  957. func defaultMetricsProvider(config *cfg.InstrumentationConfig) metricsProvider {
  958. return func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempool.Metrics, *sm.Metrics) {
  959. if config.Prometheus {
  960. return cs.PrometheusMetrics(config.Namespace, "chain_id", chainID),
  961. p2p.PrometheusMetrics(config.Namespace, "chain_id", chainID),
  962. mempool.PrometheusMetrics(config.Namespace, "chain_id", chainID),
  963. sm.PrometheusMetrics(config.Namespace, "chain_id", chainID)
  964. }
  965. return cs.NopMetrics(), p2p.NopMetrics(), mempool.NopMetrics(), sm.NopMetrics()
  966. }
  967. }
  968. //------------------------------------------------------------------------------
  969. // loadStateFromDBOrGenesisDocProvider attempts to load the state from the
  970. // database, or creates one using the given genesisDocProvider. On success this also
  971. // returns the genesis doc loaded through the given provider.
  972. func loadStateFromDBOrGenesisDocProvider(
  973. stateStore sm.Store,
  974. genDoc *types.GenesisDoc,
  975. ) (sm.State, error) {
  976. // 1. Attempt to load state form the database
  977. state, err := stateStore.Load()
  978. if err != nil {
  979. return sm.State{}, err
  980. }
  981. if state.IsEmpty() {
  982. // 2. If it's not there, derive it from the genesis doc
  983. state, err = sm.MakeGenesisState(genDoc)
  984. if err != nil {
  985. return sm.State{}, err
  986. }
  987. }
  988. return state, nil
  989. }
  990. func createAndStartPrivValidatorSocketClient(
  991. listenAddr,
  992. chainID string,
  993. logger log.Logger,
  994. ) (types.PrivValidator, error) {
  995. pve, err := privval.NewSignerListener(listenAddr, logger)
  996. if err != nil {
  997. return nil, fmt.Errorf("failed to start private validator: %w", err)
  998. }
  999. pvsc, err := privval.NewSignerClient(pve, chainID)
  1000. if err != nil {
  1001. return nil, fmt.Errorf("failed to start private validator: %w", err)
  1002. }
  1003. // try to get a pubkey from private validate first time
  1004. _, err = pvsc.GetPubKey(context.TODO())
  1005. if err != nil {
  1006. return nil, fmt.Errorf("can't get pubkey: %w", err)
  1007. }
  1008. const (
  1009. retries = 50 // 50 * 100ms = 5s total
  1010. timeout = 100 * time.Millisecond
  1011. )
  1012. pvscWithRetries := privval.NewRetrySignerClient(pvsc, retries, timeout)
  1013. return pvscWithRetries, nil
  1014. }
  1015. func createAndStartPrivValidatorGRPCClient(
  1016. config *cfg.Config,
  1017. chainID string,
  1018. logger log.Logger,
  1019. ) (types.PrivValidator, error) {
  1020. pvsc, err := tmgrpc.DialRemoteSigner(
  1021. config.PrivValidator,
  1022. chainID,
  1023. logger,
  1024. config.Instrumentation.Prometheus,
  1025. )
  1026. if err != nil {
  1027. return nil, fmt.Errorf("failed to start private validator: %w", err)
  1028. }
  1029. // try to get a pubkey from private validate first time
  1030. _, err = pvsc.GetPubKey(context.TODO())
  1031. if err != nil {
  1032. return nil, fmt.Errorf("can't get pubkey: %w", err)
  1033. }
  1034. return pvsc, nil
  1035. }
  1036. func getRouterConfig(conf *cfg.Config, proxyApp proxy.AppConns) p2p.RouterOptions {
  1037. opts := p2p.RouterOptions{
  1038. QueueType: conf.P2P.QueueType,
  1039. }
  1040. if conf.P2P.MaxNumInboundPeers > 0 {
  1041. opts.MaxIncomingConnectionAttempts = conf.P2P.MaxIncomingConnectionAttempts
  1042. }
  1043. if conf.FilterPeers && proxyApp != nil {
  1044. opts.FilterPeerByID = func(ctx context.Context, id types.NodeID) error {
  1045. res, err := proxyApp.Query().QuerySync(context.Background(), abci.RequestQuery{
  1046. Path: fmt.Sprintf("/p2p/filter/id/%s", id),
  1047. })
  1048. if err != nil {
  1049. return err
  1050. }
  1051. if res.IsErr() {
  1052. return fmt.Errorf("error querying abci app: %v", res)
  1053. }
  1054. return nil
  1055. }
  1056. opts.FilterPeerByIP = func(ctx context.Context, ip net.IP, port uint16) error {
  1057. res, err := proxyApp.Query().QuerySync(ctx, abci.RequestQuery{
  1058. Path: fmt.Sprintf("/p2p/filter/addr/%s", net.JoinHostPort(ip.String(), strconv.Itoa(int(port)))),
  1059. })
  1060. if err != nil {
  1061. return err
  1062. }
  1063. if res.IsErr() {
  1064. return fmt.Errorf("error querying abci app: %v", res)
  1065. }
  1066. return nil
  1067. }
  1068. }
  1069. return opts
  1070. }
  1071. // FIXME: Temporary helper function, shims should be removed.
  1072. func makeChannelsFromShims(
  1073. router *p2p.Router,
  1074. chShims map[p2p.ChannelID]*p2p.ChannelDescriptorShim,
  1075. ) map[p2p.ChannelID]*p2p.Channel {
  1076. channels := map[p2p.ChannelID]*p2p.Channel{}
  1077. for chID, chShim := range chShims {
  1078. ch, err := router.OpenChannel(*chShim.Descriptor, chShim.MsgType, chShim.Descriptor.RecvBufferCapacity)
  1079. if err != nil {
  1080. panic(fmt.Sprintf("failed to open channel %v: %v", chID, err))
  1081. }
  1082. channels[chID] = ch
  1083. }
  1084. return channels
  1085. }
  1086. func getChannelsFromShim(reactorShim *p2p.ReactorShim) map[p2p.ChannelID]*p2p.Channel {
  1087. channels := map[p2p.ChannelID]*p2p.Channel{}
  1088. for chID := range reactorShim.Channels {
  1089. channels[chID] = reactorShim.GetChannel(chID)
  1090. }
  1091. return channels
  1092. }
  1093. func constructStateProvider(
  1094. ssc *cfg.StateSyncConfig,
  1095. state sm.State,
  1096. logger log.Logger,
  1097. ) (statesync.StateProvider, error) {
  1098. ctx, cancel := context.WithTimeout(context.TODO(), 10*time.Second)
  1099. defer cancel()
  1100. to := light.TrustOptions{
  1101. Period: ssc.TrustPeriod,
  1102. Height: ssc.TrustHeight,
  1103. Hash: ssc.TrustHashBytes(),
  1104. }
  1105. return statesync.NewLightClientStateProvider(
  1106. ctx,
  1107. state.ChainID, state.Version, state.InitialHeight,
  1108. ssc.RPCServers, to, logger,
  1109. )
  1110. }