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.

1662 lines
49 KiB

new pubsub package comment out failing consensus tests for now rewrite rpc httpclient to use new pubsub package import pubsub as tmpubsub, query as tmquery make event IDs constants EventKey -> EventTypeKey rename EventsPubsub to PubSub mempool does not use pubsub rename eventsSub to pubsub new subscribe API fix channel size issues and consensus tests bugs refactor rpc client add missing discardFromChan method add mutex rename pubsub to eventBus remove IsRunning from WSRPCConnection interface (not needed) add a comment in broadcastNewRoundStepsAndVotes rename registerEventCallbacks to broadcastNewRoundStepsAndVotes See https://dave.cheney.net/2014/03/19/channel-axioms stop eventBuses after reactor tests remove unnecessary Unsubscribe return subscribe helper function move discardFromChan to where it is used subscribe now returns an err this gives us ability to refuse to subscribe if pubsub is at its max capacity. use context for control overflow cache queries handle err when subscribing in replay_test rename testClientID to testSubscriber extract var set channel buffer capacity to 1 in replay_file fix byzantine_test unsubscribe from single event, not all events refactor httpclient to return events to appropriate channels return failing testReplayCrashBeforeWriteVote test fix TestValidatorSetChanges refactor code a bit fix testReplayCrashBeforeWriteVote add comment fix TestValidatorSetChanges fixes from Bucky's review update comment [ci skip] test TxEventBuffer update changelog fix TestValidatorSetChanges (2nd attempt) only do wg.Done when no errors benchmark event bus create pubsub server inside NewEventBus only expose config params (later if needed) set buffer capacity to 0 so we are not testing cache new tx event format: key = "Tx" plus a tag {"tx.hash": XYZ} This should allow to subscribe to all transactions! or a specific one using a query: "tm.events.type = Tx and tx.hash = '013ABF99434...'" use TimeoutCommit instead of afterPublishEventNewBlockTimeout TimeoutCommit is the time a node waits after committing a block, before it goes into the next height. So it will finish everything from the last block, but then wait a bit. The idea is this gives it time to hear more votes from other validators, to strengthen the commit it includes in the next block. But it also gives it time to hear about new transactions. waitForBlockWithUpdatedVals rewrite WAL crash tests Task: test that we can recover from any WAL crash. Solution: the old tests were relying on event hub being run in the same thread (we were injecting the private validator's last signature). when considering a rewrite, we considered two possible solutions: write a "fuzzy" testing system where WAL is crashing upon receiving a new message, or inject failures and trigger them in tests using something like https://github.com/coreos/gofail. remove sleep no cs.Lock around wal.Save test different cases (empty block, non-empty block, ...) comments add comments test 4 cases: empty block, non-empty block, non-empty block with smaller part size, many blocks fixes as per Bucky's last review reset subscriptions on UnsubscribeAll use a simple counter to track message for which we panicked also, set a smaller part size for all test cases
8 years ago
10 years ago
new pubsub package comment out failing consensus tests for now rewrite rpc httpclient to use new pubsub package import pubsub as tmpubsub, query as tmquery make event IDs constants EventKey -> EventTypeKey rename EventsPubsub to PubSub mempool does not use pubsub rename eventsSub to pubsub new subscribe API fix channel size issues and consensus tests bugs refactor rpc client add missing discardFromChan method add mutex rename pubsub to eventBus remove IsRunning from WSRPCConnection interface (not needed) add a comment in broadcastNewRoundStepsAndVotes rename registerEventCallbacks to broadcastNewRoundStepsAndVotes See https://dave.cheney.net/2014/03/19/channel-axioms stop eventBuses after reactor tests remove unnecessary Unsubscribe return subscribe helper function move discardFromChan to where it is used subscribe now returns an err this gives us ability to refuse to subscribe if pubsub is at its max capacity. use context for control overflow cache queries handle err when subscribing in replay_test rename testClientID to testSubscriber extract var set channel buffer capacity to 1 in replay_file fix byzantine_test unsubscribe from single event, not all events refactor httpclient to return events to appropriate channels return failing testReplayCrashBeforeWriteVote test fix TestValidatorSetChanges refactor code a bit fix testReplayCrashBeforeWriteVote add comment fix TestValidatorSetChanges fixes from Bucky's review update comment [ci skip] test TxEventBuffer update changelog fix TestValidatorSetChanges (2nd attempt) only do wg.Done when no errors benchmark event bus create pubsub server inside NewEventBus only expose config params (later if needed) set buffer capacity to 0 so we are not testing cache new tx event format: key = "Tx" plus a tag {"tx.hash": XYZ} This should allow to subscribe to all transactions! or a specific one using a query: "tm.events.type = Tx and tx.hash = '013ABF99434...'" use TimeoutCommit instead of afterPublishEventNewBlockTimeout TimeoutCommit is the time a node waits after committing a block, before it goes into the next height. So it will finish everything from the last block, but then wait a bit. The idea is this gives it time to hear more votes from other validators, to strengthen the commit it includes in the next block. But it also gives it time to hear about new transactions. waitForBlockWithUpdatedVals rewrite WAL crash tests Task: test that we can recover from any WAL crash. Solution: the old tests were relying on event hub being run in the same thread (we were injecting the private validator's last signature). when considering a rewrite, we considered two possible solutions: write a "fuzzy" testing system where WAL is crashing upon receiving a new message, or inject failures and trigger them in tests using something like https://github.com/coreos/gofail. remove sleep no cs.Lock around wal.Save test different cases (empty block, non-empty block, ...) comments add comments test 4 cases: empty block, non-empty block, non-empty block with smaller part size, many blocks fixes as per Bucky's last review reset subscriptions on UnsubscribeAll use a simple counter to track message for which we panicked also, set a smaller part size for all test cases
8 years ago
10 years ago
8 years ago
10 years ago
10 years ago
new pubsub package comment out failing consensus tests for now rewrite rpc httpclient to use new pubsub package import pubsub as tmpubsub, query as tmquery make event IDs constants EventKey -> EventTypeKey rename EventsPubsub to PubSub mempool does not use pubsub rename eventsSub to pubsub new subscribe API fix channel size issues and consensus tests bugs refactor rpc client add missing discardFromChan method add mutex rename pubsub to eventBus remove IsRunning from WSRPCConnection interface (not needed) add a comment in broadcastNewRoundStepsAndVotes rename registerEventCallbacks to broadcastNewRoundStepsAndVotes See https://dave.cheney.net/2014/03/19/channel-axioms stop eventBuses after reactor tests remove unnecessary Unsubscribe return subscribe helper function move discardFromChan to where it is used subscribe now returns an err this gives us ability to refuse to subscribe if pubsub is at its max capacity. use context for control overflow cache queries handle err when subscribing in replay_test rename testClientID to testSubscriber extract var set channel buffer capacity to 1 in replay_file fix byzantine_test unsubscribe from single event, not all events refactor httpclient to return events to appropriate channels return failing testReplayCrashBeforeWriteVote test fix TestValidatorSetChanges refactor code a bit fix testReplayCrashBeforeWriteVote add comment fix TestValidatorSetChanges fixes from Bucky's review update comment [ci skip] test TxEventBuffer update changelog fix TestValidatorSetChanges (2nd attempt) only do wg.Done when no errors benchmark event bus create pubsub server inside NewEventBus only expose config params (later if needed) set buffer capacity to 0 so we are not testing cache new tx event format: key = "Tx" plus a tag {"tx.hash": XYZ} This should allow to subscribe to all transactions! or a specific one using a query: "tm.events.type = Tx and tx.hash = '013ABF99434...'" use TimeoutCommit instead of afterPublishEventNewBlockTimeout TimeoutCommit is the time a node waits after committing a block, before it goes into the next height. So it will finish everything from the last block, but then wait a bit. The idea is this gives it time to hear more votes from other validators, to strengthen the commit it includes in the next block. But it also gives it time to hear about new transactions. waitForBlockWithUpdatedVals rewrite WAL crash tests Task: test that we can recover from any WAL crash. Solution: the old tests were relying on event hub being run in the same thread (we were injecting the private validator's last signature). when considering a rewrite, we considered two possible solutions: write a "fuzzy" testing system where WAL is crashing upon receiving a new message, or inject failures and trigger them in tests using something like https://github.com/coreos/gofail. remove sleep no cs.Lock around wal.Save test different cases (empty block, non-empty block, ...) comments add comments test 4 cases: empty block, non-empty block, non-empty block with smaller part size, many blocks fixes as per Bucky's last review reset subscriptions on UnsubscribeAll use a simple counter to track message for which we panicked also, set a smaller part size for all test cases
8 years ago
8 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
8 years ago
7 years ago
10 years ago
7 years ago
10 years ago
10 years ago
7 years ago
10 years ago
7 years ago
7 years ago
8 years ago
8 years ago
10 years ago
7 years ago
10 years ago
7 years ago
7 years ago
10 years ago
10 years ago
10 years ago
10 years ago
8 years ago
8 years ago
10 years ago
10 years ago
10 years ago
new pubsub package comment out failing consensus tests for now rewrite rpc httpclient to use new pubsub package import pubsub as tmpubsub, query as tmquery make event IDs constants EventKey -> EventTypeKey rename EventsPubsub to PubSub mempool does not use pubsub rename eventsSub to pubsub new subscribe API fix channel size issues and consensus tests bugs refactor rpc client add missing discardFromChan method add mutex rename pubsub to eventBus remove IsRunning from WSRPCConnection interface (not needed) add a comment in broadcastNewRoundStepsAndVotes rename registerEventCallbacks to broadcastNewRoundStepsAndVotes See https://dave.cheney.net/2014/03/19/channel-axioms stop eventBuses after reactor tests remove unnecessary Unsubscribe return subscribe helper function move discardFromChan to where it is used subscribe now returns an err this gives us ability to refuse to subscribe if pubsub is at its max capacity. use context for control overflow cache queries handle err when subscribing in replay_test rename testClientID to testSubscriber extract var set channel buffer capacity to 1 in replay_file fix byzantine_test unsubscribe from single event, not all events refactor httpclient to return events to appropriate channels return failing testReplayCrashBeforeWriteVote test fix TestValidatorSetChanges refactor code a bit fix testReplayCrashBeforeWriteVote add comment fix TestValidatorSetChanges fixes from Bucky's review update comment [ci skip] test TxEventBuffer update changelog fix TestValidatorSetChanges (2nd attempt) only do wg.Done when no errors benchmark event bus create pubsub server inside NewEventBus only expose config params (later if needed) set buffer capacity to 0 so we are not testing cache new tx event format: key = "Tx" plus a tag {"tx.hash": XYZ} This should allow to subscribe to all transactions! or a specific one using a query: "tm.events.type = Tx and tx.hash = '013ABF99434...'" use TimeoutCommit instead of afterPublishEventNewBlockTimeout TimeoutCommit is the time a node waits after committing a block, before it goes into the next height. So it will finish everything from the last block, but then wait a bit. The idea is this gives it time to hear more votes from other validators, to strengthen the commit it includes in the next block. But it also gives it time to hear about new transactions. waitForBlockWithUpdatedVals rewrite WAL crash tests Task: test that we can recover from any WAL crash. Solution: the old tests were relying on event hub being run in the same thread (we were injecting the private validator's last signature). when considering a rewrite, we considered two possible solutions: write a "fuzzy" testing system where WAL is crashing upon receiving a new message, or inject failures and trigger them in tests using something like https://github.com/coreos/gofail. remove sleep no cs.Lock around wal.Save test different cases (empty block, non-empty block, ...) comments add comments test 4 cases: empty block, non-empty block, non-empty block with smaller part size, many blocks fixes as per Bucky's last review reset subscriptions on UnsubscribeAll use a simple counter to track message for which we panicked also, set a smaller part size for all test cases
8 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
8 years ago
10 years ago
10 years ago
8 years ago
10 years ago
10 years ago
7 years ago
10 years ago
8 years ago
10 years ago
7 years ago
7 years ago
10 years ago
10 years ago
10 years ago
7 years ago
7 years ago
8 years ago
10 years ago
8 years ago
10 years ago
10 years ago
8 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
8 years ago
7 years ago
8 years ago
8 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
fix data race Closes #1442 ``` WARNING: DATA RACE Write at 0x00c4209de7c8 by goroutine 23: github.com/tendermint/tendermint/types.(*Block).fillHeader() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:88 +0x157 github.com/tendermint/tendermint/types.(*Block).Hash() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:104 +0x121 github.com/tendermint/tendermint/types.(*Block).HashesTo() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:135 +0x4f github.com/tendermint/tendermint/consensus.(*ConsensusState).enterPrecommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1037 +0x182d github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1425 +0x1a6c github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1318 +0x77 github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:581 +0x7a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:539 +0x6c3 Previous read at 0x00c4209de7c8 by goroutine 47: github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*HexBytes).MarshalJSON() <autogenerated>:1 +0x52 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.invokeMarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:433 +0x88 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:82 +0x8d2 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).MarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/amino.go:296 +0x182 github.com/tendermint/tendermint/rpc/lib/types.NewRPCSuccessResponse() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/types/types.go:100 +0x12c github.com/tendermint/tendermint/rpc/lib/server.makeJSONRPCHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/handlers.go:152 +0xab7 net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.(*ServeMux).ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2254 +0xa2 github.com/tendermint/tendermint/rpc/lib/server.RecoverAndLogHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:138 +0x4fa net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.serverHandler.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2619 +0xbc net/http.(*conn).serve() /usr/lib/go-1.9/src/net/http/server.go:1801 +0x83b Goroutine 23 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:250 +0x35b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/reactor.go:69 +0x1b4 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).Start() <autogenerated>:1 +0x43 github.com/tendermint/tendermint/p2p.(*Switch).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch.go:177 +0x124 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/node.(*Node).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/node/node.go:416 +0xa1b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/rpc/test.StartTendermint() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/test/helpers.go:100 +0x5b github.com/tendermint/tendermint/rpc/client_test.TestMain() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/client/main_test.go:17 +0x4c main.main() github.com/tendermint/tendermint/rpc/client/_test/_testmain.go:76 +0x1cd Goroutine 47 (running) created at: net/http.(*Server).Serve() /usr/lib/go-1.9/src/net/http/server.go:2720 +0x37c net/http.Serve() /usr/lib/go-1.9/src/net/http/server.go:2323 +0xe2 github.com/tendermint/tendermint/rpc/lib/server.StartHTTPServer.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:35 +0xb3 ```
7 years ago
7 years ago
7 years ago
7 years ago
fix data race Closes #1442 ``` WARNING: DATA RACE Write at 0x00c4209de7c8 by goroutine 23: github.com/tendermint/tendermint/types.(*Block).fillHeader() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:88 +0x157 github.com/tendermint/tendermint/types.(*Block).Hash() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:104 +0x121 github.com/tendermint/tendermint/types.(*Block).HashesTo() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:135 +0x4f github.com/tendermint/tendermint/consensus.(*ConsensusState).enterPrecommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1037 +0x182d github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1425 +0x1a6c github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1318 +0x77 github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:581 +0x7a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:539 +0x6c3 Previous read at 0x00c4209de7c8 by goroutine 47: github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*HexBytes).MarshalJSON() <autogenerated>:1 +0x52 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.invokeMarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:433 +0x88 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:82 +0x8d2 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).MarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/amino.go:296 +0x182 github.com/tendermint/tendermint/rpc/lib/types.NewRPCSuccessResponse() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/types/types.go:100 +0x12c github.com/tendermint/tendermint/rpc/lib/server.makeJSONRPCHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/handlers.go:152 +0xab7 net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.(*ServeMux).ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2254 +0xa2 github.com/tendermint/tendermint/rpc/lib/server.RecoverAndLogHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:138 +0x4fa net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.serverHandler.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2619 +0xbc net/http.(*conn).serve() /usr/lib/go-1.9/src/net/http/server.go:1801 +0x83b Goroutine 23 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:250 +0x35b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/reactor.go:69 +0x1b4 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).Start() <autogenerated>:1 +0x43 github.com/tendermint/tendermint/p2p.(*Switch).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch.go:177 +0x124 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/node.(*Node).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/node/node.go:416 +0xa1b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/rpc/test.StartTendermint() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/test/helpers.go:100 +0x5b github.com/tendermint/tendermint/rpc/client_test.TestMain() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/client/main_test.go:17 +0x4c main.main() github.com/tendermint/tendermint/rpc/client/_test/_testmain.go:76 +0x1cd Goroutine 47 (running) created at: net/http.(*Server).Serve() /usr/lib/go-1.9/src/net/http/server.go:2720 +0x37c net/http.Serve() /usr/lib/go-1.9/src/net/http/server.go:2323 +0xe2 github.com/tendermint/tendermint/rpc/lib/server.StartHTTPServer.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:35 +0xb3 ```
7 years ago
7 years ago
fix data race Closes #1442 ``` WARNING: DATA RACE Write at 0x00c4209de7c8 by goroutine 23: github.com/tendermint/tendermint/types.(*Block).fillHeader() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:88 +0x157 github.com/tendermint/tendermint/types.(*Block).Hash() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:104 +0x121 github.com/tendermint/tendermint/types.(*Block).HashesTo() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:135 +0x4f github.com/tendermint/tendermint/consensus.(*ConsensusState).enterPrecommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1037 +0x182d github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1425 +0x1a6c github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1318 +0x77 github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:581 +0x7a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:539 +0x6c3 Previous read at 0x00c4209de7c8 by goroutine 47: github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*HexBytes).MarshalJSON() <autogenerated>:1 +0x52 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.invokeMarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:433 +0x88 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:82 +0x8d2 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).MarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/amino.go:296 +0x182 github.com/tendermint/tendermint/rpc/lib/types.NewRPCSuccessResponse() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/types/types.go:100 +0x12c github.com/tendermint/tendermint/rpc/lib/server.makeJSONRPCHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/handlers.go:152 +0xab7 net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.(*ServeMux).ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2254 +0xa2 github.com/tendermint/tendermint/rpc/lib/server.RecoverAndLogHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:138 +0x4fa net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.serverHandler.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2619 +0xbc net/http.(*conn).serve() /usr/lib/go-1.9/src/net/http/server.go:1801 +0x83b Goroutine 23 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:250 +0x35b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/reactor.go:69 +0x1b4 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).Start() <autogenerated>:1 +0x43 github.com/tendermint/tendermint/p2p.(*Switch).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch.go:177 +0x124 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/node.(*Node).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/node/node.go:416 +0xa1b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/rpc/test.StartTendermint() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/test/helpers.go:100 +0x5b github.com/tendermint/tendermint/rpc/client_test.TestMain() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/client/main_test.go:17 +0x4c main.main() github.com/tendermint/tendermint/rpc/client/_test/_testmain.go:76 +0x1cd Goroutine 47 (running) created at: net/http.(*Server).Serve() /usr/lib/go-1.9/src/net/http/server.go:2720 +0x37c net/http.Serve() /usr/lib/go-1.9/src/net/http/server.go:2323 +0xe2 github.com/tendermint/tendermint/rpc/lib/server.StartHTTPServer.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:35 +0xb3 ```
7 years ago
10 years ago
10 years ago
fix data race Closes #1442 ``` WARNING: DATA RACE Write at 0x00c4209de7c8 by goroutine 23: github.com/tendermint/tendermint/types.(*Block).fillHeader() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:88 +0x157 github.com/tendermint/tendermint/types.(*Block).Hash() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:104 +0x121 github.com/tendermint/tendermint/types.(*Block).HashesTo() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:135 +0x4f github.com/tendermint/tendermint/consensus.(*ConsensusState).enterPrecommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1037 +0x182d github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1425 +0x1a6c github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1318 +0x77 github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:581 +0x7a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:539 +0x6c3 Previous read at 0x00c4209de7c8 by goroutine 47: github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*HexBytes).MarshalJSON() <autogenerated>:1 +0x52 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.invokeMarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:433 +0x88 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:82 +0x8d2 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).MarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/amino.go:296 +0x182 github.com/tendermint/tendermint/rpc/lib/types.NewRPCSuccessResponse() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/types/types.go:100 +0x12c github.com/tendermint/tendermint/rpc/lib/server.makeJSONRPCHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/handlers.go:152 +0xab7 net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.(*ServeMux).ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2254 +0xa2 github.com/tendermint/tendermint/rpc/lib/server.RecoverAndLogHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:138 +0x4fa net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.serverHandler.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2619 +0xbc net/http.(*conn).serve() /usr/lib/go-1.9/src/net/http/server.go:1801 +0x83b Goroutine 23 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:250 +0x35b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/reactor.go:69 +0x1b4 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).Start() <autogenerated>:1 +0x43 github.com/tendermint/tendermint/p2p.(*Switch).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch.go:177 +0x124 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/node.(*Node).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/node/node.go:416 +0xa1b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/rpc/test.StartTendermint() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/test/helpers.go:100 +0x5b github.com/tendermint/tendermint/rpc/client_test.TestMain() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/client/main_test.go:17 +0x4c main.main() github.com/tendermint/tendermint/rpc/client/_test/_testmain.go:76 +0x1cd Goroutine 47 (running) created at: net/http.(*Server).Serve() /usr/lib/go-1.9/src/net/http/server.go:2720 +0x37c net/http.Serve() /usr/lib/go-1.9/src/net/http/server.go:2323 +0xe2 github.com/tendermint/tendermint/rpc/lib/server.StartHTTPServer.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:35 +0xb3 ```
7 years ago
fix data race Closes #1442 ``` WARNING: DATA RACE Write at 0x00c4209de7c8 by goroutine 23: github.com/tendermint/tendermint/types.(*Block).fillHeader() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:88 +0x157 github.com/tendermint/tendermint/types.(*Block).Hash() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:104 +0x121 github.com/tendermint/tendermint/types.(*Block).HashesTo() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:135 +0x4f github.com/tendermint/tendermint/consensus.(*ConsensusState).enterPrecommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1037 +0x182d github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1425 +0x1a6c github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1318 +0x77 github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:581 +0x7a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:539 +0x6c3 Previous read at 0x00c4209de7c8 by goroutine 47: github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*HexBytes).MarshalJSON() <autogenerated>:1 +0x52 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.invokeMarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:433 +0x88 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:82 +0x8d2 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).MarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/amino.go:296 +0x182 github.com/tendermint/tendermint/rpc/lib/types.NewRPCSuccessResponse() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/types/types.go:100 +0x12c github.com/tendermint/tendermint/rpc/lib/server.makeJSONRPCHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/handlers.go:152 +0xab7 net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.(*ServeMux).ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2254 +0xa2 github.com/tendermint/tendermint/rpc/lib/server.RecoverAndLogHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:138 +0x4fa net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.serverHandler.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2619 +0xbc net/http.(*conn).serve() /usr/lib/go-1.9/src/net/http/server.go:1801 +0x83b Goroutine 23 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:250 +0x35b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/reactor.go:69 +0x1b4 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).Start() <autogenerated>:1 +0x43 github.com/tendermint/tendermint/p2p.(*Switch).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch.go:177 +0x124 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/node.(*Node).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/node/node.go:416 +0xa1b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/rpc/test.StartTendermint() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/test/helpers.go:100 +0x5b github.com/tendermint/tendermint/rpc/client_test.TestMain() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/client/main_test.go:17 +0x4c main.main() github.com/tendermint/tendermint/rpc/client/_test/_testmain.go:76 +0x1cd Goroutine 47 (running) created at: net/http.(*Server).Serve() /usr/lib/go-1.9/src/net/http/server.go:2720 +0x37c net/http.Serve() /usr/lib/go-1.9/src/net/http/server.go:2323 +0xe2 github.com/tendermint/tendermint/rpc/lib/server.StartHTTPServer.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:35 +0xb3 ```
7 years ago
10 years ago
10 years ago
fix data race Closes #1442 ``` WARNING: DATA RACE Write at 0x00c4209de7c8 by goroutine 23: github.com/tendermint/tendermint/types.(*Block).fillHeader() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:88 +0x157 github.com/tendermint/tendermint/types.(*Block).Hash() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:104 +0x121 github.com/tendermint/tendermint/types.(*Block).HashesTo() /home/vagrant/go/src/github.com/tendermint/tendermint/types/block.go:135 +0x4f github.com/tendermint/tendermint/consensus.(*ConsensusState).enterPrecommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1037 +0x182d github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1425 +0x1a6c github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1318 +0x77 github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:581 +0x7a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:539 +0x6c3 Previous read at 0x00c4209de7c8 by goroutine 47: github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*HexBytes).MarshalJSON() <autogenerated>:1 +0x52 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.invokeMarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:433 +0x88 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:82 +0x8d2 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSONStruct() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:348 +0x539 github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec)._encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:119 +0x83f github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).encodeReflectJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/json-encode.go:50 +0x10e github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino.(*Codec).MarshalJSON() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/go-amino/amino.go:296 +0x182 github.com/tendermint/tendermint/rpc/lib/types.NewRPCSuccessResponse() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/types/types.go:100 +0x12c github.com/tendermint/tendermint/rpc/lib/server.makeJSONRPCHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/handlers.go:152 +0xab7 net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.(*ServeMux).ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2254 +0xa2 github.com/tendermint/tendermint/rpc/lib/server.RecoverAndLogHandler.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:138 +0x4fa net/http.HandlerFunc.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:1918 +0x51 net/http.serverHandler.ServeHTTP() /usr/lib/go-1.9/src/net/http/server.go:2619 +0xbc net/http.(*conn).serve() /usr/lib/go-1.9/src/net/http/server.go:1801 +0x83b Goroutine 23 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:250 +0x35b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/reactor.go:69 +0x1b4 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/consensus.(*ConsensusReactor).Start() <autogenerated>:1 +0x43 github.com/tendermint/tendermint/p2p.(*Switch).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch.go:177 +0x124 github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/node.(*Node).OnStart() /home/vagrant/go/src/github.com/tendermint/tendermint/node/node.go:416 +0xa1b github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common.(*BaseService).Start() /home/vagrant/go/src/github.com/tendermint/tendermint/vendor/github.com/tendermint/tmlibs/common/service.go:130 +0x5fc github.com/tendermint/tendermint/rpc/test.StartTendermint() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/test/helpers.go:100 +0x5b github.com/tendermint/tendermint/rpc/client_test.TestMain() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/client/main_test.go:17 +0x4c main.main() github.com/tendermint/tendermint/rpc/client/_test/_testmain.go:76 +0x1cd Goroutine 47 (running) created at: net/http.(*Server).Serve() /usr/lib/go-1.9/src/net/http/server.go:2720 +0x37c net/http.Serve() /usr/lib/go-1.9/src/net/http/server.go:2323 +0xe2 github.com/tendermint/tendermint/rpc/lib/server.StartHTTPServer.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/rpc/lib/server/http_server.go:35 +0xb3 ```
7 years ago
protect Record* peerStateStats functions by mutex Fixes #1414 DATA RACE: ``` Read at 0x00c4214ee940 by goroutine 146: github.com/tendermint/tendermint/consensus.(*peerStateStats).String() <autogenerated>:1 +0x57 fmt.(*pp).handleMethods() /usr/local/go/src/fmt/print.go:596 +0x3f4 fmt.(*pp).printArg() /usr/local/go/src/fmt/print.go:679 +0x11f fmt.(*pp).doPrintf() /usr/local/go/src/fmt/print.go:996 +0x319 fmt.Sprintf() /usr/local/go/src/fmt/print.go:196 +0x73 github.com/tendermint/tendermint/consensus.(*PeerState).StringIndented() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:1426 +0x573 github.com/tendermint/tendermint/consensus.(*PeerState).String() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:1419 +0x66 github.com/go-logfmt/logfmt.safeString() /home/ubuntu/go/src/github.com/go-logfmt/logfmt/encode.go:299 +0x9d github.com/go-logfmt/logfmt.writeValue() /home/ubuntu/go/src/github.com/go-logfmt/logfmt/encode.go:217 +0x5a0 github.com/go-logfmt/logfmt.(*Encoder).EncodeKeyval() /home/ubuntu/go/src/github.com/go-logfmt/logfmt/encode.go:61 +0x1dd github.com/tendermint/tmlibs/log.tmfmtLogger.Log() /home/ubuntu/go/src/github.com/tendermint/tmlibs/log/tmfmt_logger.go:107 +0x1001 github.com/tendermint/tmlibs/log.(*tmfmtLogger).Log() <autogenerated>:1 +0x93 github.com/go-kit/kit/log.(*context).Log() /home/ubuntu/go/src/github.com/go-kit/kit/log/log.go:124 +0x248 github.com/tendermint/tmlibs/log.(*tmLogger).Debug() /home/ubuntu/go/src/github.com/tendermint/tmlibs/log/tm_logger.go:64 +0x1d0 github.com/tendermint/tendermint/consensus.(*PeerState).PickSendVote() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:1059 +0x242 github.com/tendermint/tendermint/consensus.(*ConsensusReactor).gossipVotesForHeight() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:789 +0x6ef github.com/tendermint/tendermint/consensus.(*ConsensusReactor).gossipVotesRoutine() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:723 +0x1039 Previous write at 0x00c4214ee940 by goroutine 21: github.com/tendermint/tendermint/consensus.(*PeerState).RecordVote() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:1242 +0x15a github.com/tendermint/tendermint/consensus.(*ConsensusReactor).Receive() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:309 +0x32e6 github.com/tendermint/tendermint/p2p.createMConnection.func1() /home/ubuntu/go/src/github.com/tendermint/tendermint/p2p/peer.go:365 +0xea github.com/tendermint/tendermint/p2p/conn.(*MConnection).recvRoutine() /home/ubuntu/go/src/github.com/tendermint/tendermint/p2p/conn/connection.go:531 +0x779 ```
7 years ago
protect Record* peerStateStats functions by mutex Fixes #1414 DATA RACE: ``` Read at 0x00c4214ee940 by goroutine 146: github.com/tendermint/tendermint/consensus.(*peerStateStats).String() <autogenerated>:1 +0x57 fmt.(*pp).handleMethods() /usr/local/go/src/fmt/print.go:596 +0x3f4 fmt.(*pp).printArg() /usr/local/go/src/fmt/print.go:679 +0x11f fmt.(*pp).doPrintf() /usr/local/go/src/fmt/print.go:996 +0x319 fmt.Sprintf() /usr/local/go/src/fmt/print.go:196 +0x73 github.com/tendermint/tendermint/consensus.(*PeerState).StringIndented() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:1426 +0x573 github.com/tendermint/tendermint/consensus.(*PeerState).String() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:1419 +0x66 github.com/go-logfmt/logfmt.safeString() /home/ubuntu/go/src/github.com/go-logfmt/logfmt/encode.go:299 +0x9d github.com/go-logfmt/logfmt.writeValue() /home/ubuntu/go/src/github.com/go-logfmt/logfmt/encode.go:217 +0x5a0 github.com/go-logfmt/logfmt.(*Encoder).EncodeKeyval() /home/ubuntu/go/src/github.com/go-logfmt/logfmt/encode.go:61 +0x1dd github.com/tendermint/tmlibs/log.tmfmtLogger.Log() /home/ubuntu/go/src/github.com/tendermint/tmlibs/log/tmfmt_logger.go:107 +0x1001 github.com/tendermint/tmlibs/log.(*tmfmtLogger).Log() <autogenerated>:1 +0x93 github.com/go-kit/kit/log.(*context).Log() /home/ubuntu/go/src/github.com/go-kit/kit/log/log.go:124 +0x248 github.com/tendermint/tmlibs/log.(*tmLogger).Debug() /home/ubuntu/go/src/github.com/tendermint/tmlibs/log/tm_logger.go:64 +0x1d0 github.com/tendermint/tendermint/consensus.(*PeerState).PickSendVote() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:1059 +0x242 github.com/tendermint/tendermint/consensus.(*ConsensusReactor).gossipVotesForHeight() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:789 +0x6ef github.com/tendermint/tendermint/consensus.(*ConsensusReactor).gossipVotesRoutine() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:723 +0x1039 Previous write at 0x00c4214ee940 by goroutine 21: github.com/tendermint/tendermint/consensus.(*PeerState).RecordVote() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:1242 +0x15a github.com/tendermint/tendermint/consensus.(*ConsensusReactor).Receive() github.com/tendermint/tendermint/consensus/_test/_obj_test/reactor.go:309 +0x32e6 github.com/tendermint/tendermint/p2p.createMConnection.func1() /home/ubuntu/go/src/github.com/tendermint/tendermint/p2p/peer.go:365 +0xea github.com/tendermint/tendermint/p2p/conn.(*MConnection).recvRoutine() /home/ubuntu/go/src/github.com/tendermint/tendermint/p2p/conn/connection.go:531 +0x779 ```
7 years ago
10 years ago
10 years ago
10 years ago
10 years ago
7 years ago
7 years ago
10 years ago
7 years ago
10 years ago
10 years ago
10 years ago
10 years ago
8 years ago
  1. package consensus
  2. import (
  3. "fmt"
  4. "reflect"
  5. "sync"
  6. "time"
  7. "github.com/pkg/errors"
  8. amino "github.com/tendermint/go-amino"
  9. cstypes "github.com/tendermint/tendermint/consensus/types"
  10. cmn "github.com/tendermint/tendermint/libs/common"
  11. tmevents "github.com/tendermint/tendermint/libs/events"
  12. "github.com/tendermint/tendermint/libs/log"
  13. "github.com/tendermint/tendermint/p2p"
  14. sm "github.com/tendermint/tendermint/state"
  15. "github.com/tendermint/tendermint/types"
  16. tmtime "github.com/tendermint/tendermint/types/time"
  17. )
  18. const (
  19. StateChannel = byte(0x20)
  20. DataChannel = byte(0x21)
  21. VoteChannel = byte(0x22)
  22. VoteSetBitsChannel = byte(0x23)
  23. maxMsgSize = 1048576 // 1MB; NOTE/TODO: keep in sync with types.PartSet sizes.
  24. blocksToContributeToBecomeGoodPeer = 10000
  25. votesToContributeToBecomeGoodPeer = 10000
  26. )
  27. //-----------------------------------------------------------------------------
  28. // ConsensusReactor defines a reactor for the consensus service.
  29. type ConsensusReactor struct {
  30. p2p.BaseReactor // BaseService + p2p.Switch
  31. conS *ConsensusState
  32. mtx sync.RWMutex
  33. fastSync bool
  34. eventBus *types.EventBus
  35. metrics *Metrics
  36. }
  37. type ReactorOption func(*ConsensusReactor)
  38. // NewConsensusReactor returns a new ConsensusReactor with the given
  39. // consensusState.
  40. func NewConsensusReactor(consensusState *ConsensusState, fastSync bool, options ...ReactorOption) *ConsensusReactor {
  41. conR := &ConsensusReactor{
  42. conS: consensusState,
  43. fastSync: fastSync,
  44. metrics: NopMetrics(),
  45. }
  46. conR.updateFastSyncingMetric()
  47. conR.BaseReactor = *p2p.NewBaseReactor("ConsensusReactor", conR)
  48. for _, option := range options {
  49. option(conR)
  50. }
  51. return conR
  52. }
  53. // OnStart implements BaseService by subscribing to events, which later will be
  54. // broadcasted to other peers and starting state if we're not in fast sync.
  55. func (conR *ConsensusReactor) OnStart() error {
  56. conR.Logger.Info("ConsensusReactor ", "fastSync", conR.FastSync())
  57. // start routine that computes peer statistics for evaluating peer quality
  58. go conR.peerStatsRoutine()
  59. conR.subscribeToBroadcastEvents()
  60. if !conR.FastSync() {
  61. err := conR.conS.Start()
  62. if err != nil {
  63. return err
  64. }
  65. }
  66. return nil
  67. }
  68. // OnStop implements BaseService by unsubscribing from events and stopping
  69. // state.
  70. func (conR *ConsensusReactor) OnStop() {
  71. conR.unsubscribeFromBroadcastEvents()
  72. conR.conS.Stop()
  73. if !conR.FastSync() {
  74. conR.conS.Wait()
  75. }
  76. }
  77. // SwitchToConsensus switches from fast_sync mode to consensus mode.
  78. // It resets the state, turns off fast_sync, and starts the consensus state-machine
  79. func (conR *ConsensusReactor) SwitchToConsensus(state sm.State, blocksSynced int) {
  80. conR.Logger.Info("SwitchToConsensus")
  81. conR.conS.reconstructLastCommit(state)
  82. // NOTE: The line below causes broadcastNewRoundStepRoutine() to
  83. // broadcast a NewRoundStepMessage.
  84. conR.conS.updateToState(state)
  85. conR.mtx.Lock()
  86. conR.fastSync = false
  87. conR.mtx.Unlock()
  88. conR.metrics.FastSyncing.Set(0)
  89. if blocksSynced > 0 {
  90. // dont bother with the WAL if we fast synced
  91. conR.conS.doWALCatchup = false
  92. }
  93. err := conR.conS.Start()
  94. if err != nil {
  95. conR.Logger.Error("Error starting conS", "err", err)
  96. return
  97. }
  98. }
  99. // GetChannels implements Reactor
  100. func (conR *ConsensusReactor) GetChannels() []*p2p.ChannelDescriptor {
  101. // TODO optimize
  102. return []*p2p.ChannelDescriptor{
  103. {
  104. ID: StateChannel,
  105. Priority: 5,
  106. SendQueueCapacity: 100,
  107. RecvMessageCapacity: maxMsgSize,
  108. },
  109. {
  110. ID: DataChannel, // maybe split between gossiping current block and catchup stuff
  111. Priority: 10, // once we gossip the whole block there's nothing left to send until next height or round
  112. SendQueueCapacity: 100,
  113. RecvBufferCapacity: 50 * 4096,
  114. RecvMessageCapacity: maxMsgSize,
  115. },
  116. {
  117. ID: VoteChannel,
  118. Priority: 5,
  119. SendQueueCapacity: 100,
  120. RecvBufferCapacity: 100 * 100,
  121. RecvMessageCapacity: maxMsgSize,
  122. },
  123. {
  124. ID: VoteSetBitsChannel,
  125. Priority: 1,
  126. SendQueueCapacity: 2,
  127. RecvBufferCapacity: 1024,
  128. RecvMessageCapacity: maxMsgSize,
  129. },
  130. }
  131. }
  132. // AddPeer implements Reactor
  133. func (conR *ConsensusReactor) AddPeer(peer p2p.Peer) {
  134. if !conR.IsRunning() {
  135. return
  136. }
  137. // Create peerState for peer
  138. peerState := NewPeerState(peer).SetLogger(conR.Logger)
  139. peer.Set(types.PeerStateKey, peerState)
  140. // Begin routines for this peer.
  141. go conR.gossipDataRoutine(peer, peerState)
  142. go conR.gossipVotesRoutine(peer, peerState)
  143. go conR.queryMaj23Routine(peer, peerState)
  144. // Send our state to peer.
  145. // If we're fast_syncing, broadcast a RoundStepMessage later upon SwitchToConsensus().
  146. if !conR.FastSync() {
  147. conR.sendNewRoundStepMessage(peer)
  148. }
  149. }
  150. // RemovePeer implements Reactor
  151. func (conR *ConsensusReactor) RemovePeer(peer p2p.Peer, reason interface{}) {
  152. if !conR.IsRunning() {
  153. return
  154. }
  155. // TODO
  156. //peer.Get(PeerStateKey).(*PeerState).Disconnect()
  157. }
  158. // Receive implements Reactor
  159. // NOTE: We process these messages even when we're fast_syncing.
  160. // Messages affect either a peer state or the consensus state.
  161. // Peer state updates can happen in parallel, but processing of
  162. // proposals, block parts, and votes are ordered by the receiveRoutine
  163. // NOTE: blocks on consensus state for proposals, block parts, and votes
  164. func (conR *ConsensusReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) {
  165. if !conR.IsRunning() {
  166. conR.Logger.Debug("Receive", "src", src, "chId", chID, "bytes", msgBytes)
  167. return
  168. }
  169. msg, err := decodeMsg(msgBytes)
  170. if err != nil {
  171. conR.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes)
  172. conR.Switch.StopPeerForError(src, err)
  173. return
  174. }
  175. if err = msg.ValidateBasic(); err != nil {
  176. conR.Logger.Error("Peer sent us invalid msg", "peer", src, "msg", msg, "err", err)
  177. conR.Switch.StopPeerForError(src, err)
  178. return
  179. }
  180. conR.Logger.Debug("Receive", "src", src, "chId", chID, "msg", msg)
  181. // Get peer states
  182. ps := src.Get(types.PeerStateKey).(*PeerState)
  183. switch chID {
  184. case StateChannel:
  185. switch msg := msg.(type) {
  186. case *NewRoundStepMessage:
  187. ps.ApplyNewRoundStepMessage(msg)
  188. case *NewValidBlockMessage:
  189. ps.ApplyNewValidBlockMessage(msg)
  190. case *HasVoteMessage:
  191. ps.ApplyHasVoteMessage(msg)
  192. case *VoteSetMaj23Message:
  193. cs := conR.conS
  194. cs.mtx.Lock()
  195. height, votes := cs.Height, cs.Votes
  196. cs.mtx.Unlock()
  197. if height != msg.Height {
  198. return
  199. }
  200. // Peer claims to have a maj23 for some BlockID at H,R,S,
  201. err := votes.SetPeerMaj23(msg.Round, msg.Type, ps.peer.ID(), msg.BlockID)
  202. if err != nil {
  203. conR.Switch.StopPeerForError(src, err)
  204. return
  205. }
  206. // Respond with a VoteSetBitsMessage showing which votes we have.
  207. // (and consequently shows which we don't have)
  208. var ourVotes *cmn.BitArray
  209. switch msg.Type {
  210. case types.PrevoteType:
  211. ourVotes = votes.Prevotes(msg.Round).BitArrayByBlockID(msg.BlockID)
  212. case types.PrecommitType:
  213. ourVotes = votes.Precommits(msg.Round).BitArrayByBlockID(msg.BlockID)
  214. default:
  215. panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?")
  216. }
  217. src.TrySend(VoteSetBitsChannel, cdc.MustMarshalBinaryBare(&VoteSetBitsMessage{
  218. Height: msg.Height,
  219. Round: msg.Round,
  220. Type: msg.Type,
  221. BlockID: msg.BlockID,
  222. Votes: ourVotes,
  223. }))
  224. case *ProposalHeartbeatMessage:
  225. hb := msg.Heartbeat
  226. conR.Logger.Debug("Received proposal heartbeat message",
  227. "height", hb.Height, "round", hb.Round, "sequence", hb.Sequence,
  228. "valIdx", hb.ValidatorIndex, "valAddr", hb.ValidatorAddress)
  229. default:
  230. conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
  231. }
  232. case DataChannel:
  233. if conR.FastSync() {
  234. conR.Logger.Info("Ignoring message received during fastSync", "msg", msg)
  235. return
  236. }
  237. switch msg := msg.(type) {
  238. case *ProposalMessage:
  239. ps.SetHasProposal(msg.Proposal)
  240. conR.conS.peerMsgQueue <- msgInfo{msg, src.ID()}
  241. case *ProposalPOLMessage:
  242. ps.ApplyProposalPOLMessage(msg)
  243. case *BlockPartMessage:
  244. ps.SetHasProposalBlockPart(msg.Height, msg.Round, msg.Part.Index)
  245. conR.metrics.BlockParts.With("peer_id", string(src.ID())).Add(1)
  246. conR.conS.peerMsgQueue <- msgInfo{msg, src.ID()}
  247. default:
  248. conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
  249. }
  250. case VoteChannel:
  251. if conR.FastSync() {
  252. conR.Logger.Info("Ignoring message received during fastSync", "msg", msg)
  253. return
  254. }
  255. switch msg := msg.(type) {
  256. case *VoteMessage:
  257. cs := conR.conS
  258. cs.mtx.Lock()
  259. height, valSize, lastCommitSize := cs.Height, cs.Validators.Size(), cs.LastCommit.Size()
  260. cs.mtx.Unlock()
  261. ps.EnsureVoteBitArrays(height, valSize)
  262. ps.EnsureVoteBitArrays(height-1, lastCommitSize)
  263. ps.SetHasVote(msg.Vote)
  264. cs.peerMsgQueue <- msgInfo{msg, src.ID()}
  265. default:
  266. // don't punish (leave room for soft upgrades)
  267. conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
  268. }
  269. case VoteSetBitsChannel:
  270. if conR.FastSync() {
  271. conR.Logger.Info("Ignoring message received during fastSync", "msg", msg)
  272. return
  273. }
  274. switch msg := msg.(type) {
  275. case *VoteSetBitsMessage:
  276. cs := conR.conS
  277. cs.mtx.Lock()
  278. height, votes := cs.Height, cs.Votes
  279. cs.mtx.Unlock()
  280. if height == msg.Height {
  281. var ourVotes *cmn.BitArray
  282. switch msg.Type {
  283. case types.PrevoteType:
  284. ourVotes = votes.Prevotes(msg.Round).BitArrayByBlockID(msg.BlockID)
  285. case types.PrecommitType:
  286. ourVotes = votes.Precommits(msg.Round).BitArrayByBlockID(msg.BlockID)
  287. default:
  288. panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?")
  289. }
  290. ps.ApplyVoteSetBitsMessage(msg, ourVotes)
  291. } else {
  292. ps.ApplyVoteSetBitsMessage(msg, nil)
  293. }
  294. default:
  295. // don't punish (leave room for soft upgrades)
  296. conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg)))
  297. }
  298. default:
  299. conR.Logger.Error(fmt.Sprintf("Unknown chId %X", chID))
  300. }
  301. if err != nil {
  302. conR.Logger.Error("Error in Receive()", "err", err)
  303. }
  304. }
  305. // SetEventBus sets event bus.
  306. func (conR *ConsensusReactor) SetEventBus(b *types.EventBus) {
  307. conR.eventBus = b
  308. conR.conS.SetEventBus(b)
  309. }
  310. // FastSync returns whether the consensus reactor is in fast-sync mode.
  311. func (conR *ConsensusReactor) FastSync() bool {
  312. conR.mtx.RLock()
  313. defer conR.mtx.RUnlock()
  314. return conR.fastSync
  315. }
  316. //--------------------------------------
  317. // subscribeToBroadcastEvents subscribes for new round steps, votes and
  318. // proposal heartbeats using internal pubsub defined on state to broadcast
  319. // them to peers upon receiving.
  320. func (conR *ConsensusReactor) subscribeToBroadcastEvents() {
  321. const subscriber = "consensus-reactor"
  322. conR.conS.evsw.AddListenerForEvent(subscriber, types.EventNewRoundStep,
  323. func(data tmevents.EventData) {
  324. conR.broadcastNewRoundStepMessage(data.(*cstypes.RoundState))
  325. })
  326. conR.conS.evsw.AddListenerForEvent(subscriber, types.EventValidBlock,
  327. func(data tmevents.EventData) {
  328. conR.broadcastNewValidBlockMessage(data.(*cstypes.RoundState))
  329. })
  330. conR.conS.evsw.AddListenerForEvent(subscriber, types.EventVote,
  331. func(data tmevents.EventData) {
  332. conR.broadcastHasVoteMessage(data.(*types.Vote))
  333. })
  334. conR.conS.evsw.AddListenerForEvent(subscriber, types.EventProposalHeartbeat,
  335. func(data tmevents.EventData) {
  336. conR.broadcastProposalHeartbeatMessage(data.(*types.Heartbeat))
  337. })
  338. }
  339. func (conR *ConsensusReactor) unsubscribeFromBroadcastEvents() {
  340. const subscriber = "consensus-reactor"
  341. conR.conS.evsw.RemoveListener(subscriber)
  342. }
  343. func (conR *ConsensusReactor) broadcastProposalHeartbeatMessage(hb *types.Heartbeat) {
  344. conR.Logger.Debug("Broadcasting proposal heartbeat message",
  345. "height", hb.Height, "round", hb.Round, "sequence", hb.Sequence)
  346. msg := &ProposalHeartbeatMessage{hb}
  347. conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(msg))
  348. }
  349. func (conR *ConsensusReactor) broadcastNewRoundStepMessage(rs *cstypes.RoundState) {
  350. nrsMsg := makeRoundStepMessage(rs)
  351. conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg))
  352. }
  353. func (conR *ConsensusReactor) broadcastNewValidBlockMessage(rs *cstypes.RoundState) {
  354. csMsg := &NewValidBlockMessage{
  355. Height: rs.Height,
  356. Round: rs.Round,
  357. BlockPartsHeader: rs.ProposalBlockParts.Header(),
  358. BlockParts: rs.ProposalBlockParts.BitArray(),
  359. IsCommit: rs.Step == cstypes.RoundStepCommit,
  360. }
  361. conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(csMsg))
  362. }
  363. // Broadcasts HasVoteMessage to peers that care.
  364. func (conR *ConsensusReactor) broadcastHasVoteMessage(vote *types.Vote) {
  365. msg := &HasVoteMessage{
  366. Height: vote.Height,
  367. Round: vote.Round,
  368. Type: vote.Type,
  369. Index: vote.ValidatorIndex,
  370. }
  371. conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(msg))
  372. /*
  373. // TODO: Make this broadcast more selective.
  374. for _, peer := range conR.Switch.Peers().List() {
  375. ps := peer.Get(PeerStateKey).(*PeerState)
  376. prs := ps.GetRoundState()
  377. if prs.Height == vote.Height {
  378. // TODO: Also filter on round?
  379. peer.TrySend(StateChannel, struct{ ConsensusMessage }{msg})
  380. } else {
  381. // Height doesn't match
  382. // TODO: check a field, maybe CatchupCommitRound?
  383. // TODO: But that requires changing the struct field comment.
  384. }
  385. }
  386. */
  387. }
  388. func makeRoundStepMessage(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage) {
  389. nrsMsg = &NewRoundStepMessage{
  390. Height: rs.Height,
  391. Round: rs.Round,
  392. Step: rs.Step,
  393. SecondsSinceStartTime: int(time.Since(rs.StartTime).Seconds()),
  394. LastCommitRound: rs.LastCommit.Round(),
  395. }
  396. return
  397. }
  398. func (conR *ConsensusReactor) sendNewRoundStepMessage(peer p2p.Peer) {
  399. rs := conR.conS.GetRoundState()
  400. nrsMsg := makeRoundStepMessage(rs)
  401. peer.Send(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg))
  402. }
  403. func (conR *ConsensusReactor) gossipDataRoutine(peer p2p.Peer, ps *PeerState) {
  404. logger := conR.Logger.With("peer", peer)
  405. OUTER_LOOP:
  406. for {
  407. // Manage disconnects from self or peer.
  408. if !peer.IsRunning() || !conR.IsRunning() {
  409. logger.Info("Stopping gossipDataRoutine for peer")
  410. return
  411. }
  412. rs := conR.conS.GetRoundState()
  413. prs := ps.GetRoundState()
  414. // Send proposal Block parts?
  415. if rs.ProposalBlockParts.HasHeader(prs.ProposalBlockPartsHeader) {
  416. if index, ok := rs.ProposalBlockParts.BitArray().Sub(prs.ProposalBlockParts.Copy()).PickRandom(); ok {
  417. part := rs.ProposalBlockParts.GetPart(index)
  418. msg := &BlockPartMessage{
  419. Height: rs.Height, // This tells peer that this part applies to us.
  420. Round: rs.Round, // This tells peer that this part applies to us.
  421. Part: part,
  422. }
  423. logger.Debug("Sending block part", "height", prs.Height, "round", prs.Round)
  424. if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) {
  425. ps.SetHasProposalBlockPart(prs.Height, prs.Round, index)
  426. }
  427. continue OUTER_LOOP
  428. }
  429. }
  430. // If the peer is on a previous height, help catch up.
  431. if (0 < prs.Height) && (prs.Height < rs.Height) {
  432. heightLogger := logger.With("height", prs.Height)
  433. // if we never received the commit message from the peer, the block parts wont be initialized
  434. if prs.ProposalBlockParts == nil {
  435. blockMeta := conR.conS.blockStore.LoadBlockMeta(prs.Height)
  436. if blockMeta == nil {
  437. cmn.PanicCrisis(fmt.Sprintf("Failed to load block %d when blockStore is at %d",
  438. prs.Height, conR.conS.blockStore.Height()))
  439. }
  440. ps.InitProposalBlockParts(blockMeta.BlockID.PartsHeader)
  441. // continue the loop since prs is a copy and not effected by this initialization
  442. continue OUTER_LOOP
  443. }
  444. conR.gossipDataForCatchup(heightLogger, rs, prs, ps, peer)
  445. continue OUTER_LOOP
  446. }
  447. // If height and round don't match, sleep.
  448. if (rs.Height != prs.Height) || (rs.Round != prs.Round) {
  449. //logger.Info("Peer Height|Round mismatch, sleeping", "peerHeight", prs.Height, "peerRound", prs.Round, "peer", peer)
  450. time.Sleep(conR.conS.config.PeerGossipSleepDuration)
  451. continue OUTER_LOOP
  452. }
  453. // By here, height and round match.
  454. // Proposal block parts were already matched and sent if any were wanted.
  455. // (These can match on hash so the round doesn't matter)
  456. // Now consider sending other things, like the Proposal itself.
  457. // Send Proposal && ProposalPOL BitArray?
  458. if rs.Proposal != nil && !prs.Proposal {
  459. // Proposal: share the proposal metadata with peer.
  460. {
  461. msg := &ProposalMessage{Proposal: rs.Proposal}
  462. logger.Debug("Sending proposal", "height", prs.Height, "round", prs.Round)
  463. if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) {
  464. // NOTE[ZM]: A peer might have received different proposal msg so this Proposal msg will be rejected!
  465. ps.SetHasProposal(rs.Proposal)
  466. }
  467. }
  468. // ProposalPOL: lets peer know which POL votes we have so far.
  469. // Peer must receive ProposalMessage first.
  470. // rs.Proposal was validated, so rs.Proposal.POLRound <= rs.Round,
  471. // so we definitely have rs.Votes.Prevotes(rs.Proposal.POLRound).
  472. if 0 <= rs.Proposal.POLRound {
  473. msg := &ProposalPOLMessage{
  474. Height: rs.Height,
  475. ProposalPOLRound: rs.Proposal.POLRound,
  476. ProposalPOL: rs.Votes.Prevotes(rs.Proposal.POLRound).BitArray(),
  477. }
  478. logger.Debug("Sending POL", "height", prs.Height, "round", prs.Round)
  479. peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg))
  480. }
  481. continue OUTER_LOOP
  482. }
  483. // Nothing to do. Sleep.
  484. time.Sleep(conR.conS.config.PeerGossipSleepDuration)
  485. continue OUTER_LOOP
  486. }
  487. }
  488. func (conR *ConsensusReactor) gossipDataForCatchup(logger log.Logger, rs *cstypes.RoundState,
  489. prs *cstypes.PeerRoundState, ps *PeerState, peer p2p.Peer) {
  490. if index, ok := prs.ProposalBlockParts.Not().PickRandom(); ok {
  491. // Ensure that the peer's PartSetHeader is correct
  492. blockMeta := conR.conS.blockStore.LoadBlockMeta(prs.Height)
  493. if blockMeta == nil {
  494. logger.Error("Failed to load block meta",
  495. "ourHeight", rs.Height, "blockstoreHeight", conR.conS.blockStore.Height())
  496. time.Sleep(conR.conS.config.PeerGossipSleepDuration)
  497. return
  498. } else if !blockMeta.BlockID.PartsHeader.Equals(prs.ProposalBlockPartsHeader) {
  499. logger.Info("Peer ProposalBlockPartsHeader mismatch, sleeping",
  500. "blockPartsHeader", blockMeta.BlockID.PartsHeader, "peerBlockPartsHeader", prs.ProposalBlockPartsHeader)
  501. time.Sleep(conR.conS.config.PeerGossipSleepDuration)
  502. return
  503. }
  504. // Load the part
  505. part := conR.conS.blockStore.LoadBlockPart(prs.Height, index)
  506. if part == nil {
  507. logger.Error("Could not load part", "index", index,
  508. "blockPartsHeader", blockMeta.BlockID.PartsHeader, "peerBlockPartsHeader", prs.ProposalBlockPartsHeader)
  509. time.Sleep(conR.conS.config.PeerGossipSleepDuration)
  510. return
  511. }
  512. // Send the part
  513. msg := &BlockPartMessage{
  514. Height: prs.Height, // Not our height, so it doesn't matter.
  515. Round: prs.Round, // Not our height, so it doesn't matter.
  516. Part: part,
  517. }
  518. logger.Debug("Sending block part for catchup", "round", prs.Round, "index", index)
  519. if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) {
  520. ps.SetHasProposalBlockPart(prs.Height, prs.Round, index)
  521. } else {
  522. logger.Debug("Sending block part for catchup failed")
  523. }
  524. return
  525. }
  526. //logger.Info("No parts to send in catch-up, sleeping")
  527. time.Sleep(conR.conS.config.PeerGossipSleepDuration)
  528. }
  529. func (conR *ConsensusReactor) gossipVotesRoutine(peer p2p.Peer, ps *PeerState) {
  530. logger := conR.Logger.With("peer", peer)
  531. // Simple hack to throttle logs upon sleep.
  532. var sleeping = 0
  533. OUTER_LOOP:
  534. for {
  535. // Manage disconnects from self or peer.
  536. if !peer.IsRunning() || !conR.IsRunning() {
  537. logger.Info("Stopping gossipVotesRoutine for peer")
  538. return
  539. }
  540. rs := conR.conS.GetRoundState()
  541. prs := ps.GetRoundState()
  542. switch sleeping {
  543. case 1: // First sleep
  544. sleeping = 2
  545. case 2: // No more sleep
  546. sleeping = 0
  547. }
  548. //logger.Debug("gossipVotesRoutine", "rsHeight", rs.Height, "rsRound", rs.Round,
  549. // "prsHeight", prs.Height, "prsRound", prs.Round, "prsStep", prs.Step)
  550. // If height matches, then send LastCommit, Prevotes, Precommits.
  551. if rs.Height == prs.Height {
  552. heightLogger := logger.With("height", prs.Height)
  553. if conR.gossipVotesForHeight(heightLogger, rs, prs, ps) {
  554. continue OUTER_LOOP
  555. }
  556. }
  557. // Special catchup logic.
  558. // If peer is lagging by height 1, send LastCommit.
  559. if prs.Height != 0 && rs.Height == prs.Height+1 {
  560. if ps.PickSendVote(rs.LastCommit) {
  561. logger.Debug("Picked rs.LastCommit to send", "height", prs.Height)
  562. continue OUTER_LOOP
  563. }
  564. }
  565. // Catchup logic
  566. // If peer is lagging by more than 1, send Commit.
  567. if prs.Height != 0 && rs.Height >= prs.Height+2 {
  568. // Load the block commit for prs.Height,
  569. // which contains precommit signatures for prs.Height.
  570. commit := conR.conS.blockStore.LoadBlockCommit(prs.Height)
  571. if ps.PickSendVote(commit) {
  572. logger.Debug("Picked Catchup commit to send", "height", prs.Height)
  573. continue OUTER_LOOP
  574. }
  575. }
  576. if sleeping == 0 {
  577. // We sent nothing. Sleep...
  578. sleeping = 1
  579. logger.Debug("No votes to send, sleeping", "rs.Height", rs.Height, "prs.Height", prs.Height,
  580. "localPV", rs.Votes.Prevotes(rs.Round).BitArray(), "peerPV", prs.Prevotes,
  581. "localPC", rs.Votes.Precommits(rs.Round).BitArray(), "peerPC", prs.Precommits)
  582. } else if sleeping == 2 {
  583. // Continued sleep...
  584. sleeping = 1
  585. }
  586. time.Sleep(conR.conS.config.PeerGossipSleepDuration)
  587. continue OUTER_LOOP
  588. }
  589. }
  590. func (conR *ConsensusReactor) gossipVotesForHeight(logger log.Logger, rs *cstypes.RoundState, prs *cstypes.PeerRoundState, ps *PeerState) bool {
  591. // If there are lastCommits to send...
  592. if prs.Step == cstypes.RoundStepNewHeight {
  593. if ps.PickSendVote(rs.LastCommit) {
  594. logger.Debug("Picked rs.LastCommit to send")
  595. return true
  596. }
  597. }
  598. // If there are POL prevotes to send...
  599. if prs.Step <= cstypes.RoundStepPropose && prs.Round != -1 && prs.Round <= rs.Round && prs.ProposalPOLRound != -1 {
  600. if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil {
  601. if ps.PickSendVote(polPrevotes) {
  602. logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send",
  603. "round", prs.ProposalPOLRound)
  604. return true
  605. }
  606. }
  607. }
  608. // If there are prevotes to send...
  609. if prs.Step <= cstypes.RoundStepPrevoteWait && prs.Round != -1 && prs.Round <= rs.Round {
  610. if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) {
  611. logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round)
  612. return true
  613. }
  614. }
  615. // If there are precommits to send...
  616. if prs.Step <= cstypes.RoundStepPrecommitWait && prs.Round != -1 && prs.Round <= rs.Round {
  617. if ps.PickSendVote(rs.Votes.Precommits(prs.Round)) {
  618. logger.Debug("Picked rs.Precommits(prs.Round) to send", "round", prs.Round)
  619. return true
  620. }
  621. }
  622. // If there are prevotes to send...Needed because of validBlock mechanism
  623. if prs.Round != -1 && prs.Round <= rs.Round {
  624. if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) {
  625. logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round)
  626. return true
  627. }
  628. }
  629. // If there are POLPrevotes to send...
  630. if prs.ProposalPOLRound != -1 {
  631. if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil {
  632. if ps.PickSendVote(polPrevotes) {
  633. logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send",
  634. "round", prs.ProposalPOLRound)
  635. return true
  636. }
  637. }
  638. }
  639. return false
  640. }
  641. // NOTE: `queryMaj23Routine` has a simple crude design since it only comes
  642. // into play for liveness when there's a signature DDoS attack happening.
  643. func (conR *ConsensusReactor) queryMaj23Routine(peer p2p.Peer, ps *PeerState) {
  644. logger := conR.Logger.With("peer", peer)
  645. OUTER_LOOP:
  646. for {
  647. // Manage disconnects from self or peer.
  648. if !peer.IsRunning() || !conR.IsRunning() {
  649. logger.Info("Stopping queryMaj23Routine for peer")
  650. return
  651. }
  652. // Maybe send Height/Round/Prevotes
  653. {
  654. rs := conR.conS.GetRoundState()
  655. prs := ps.GetRoundState()
  656. if rs.Height == prs.Height {
  657. if maj23, ok := rs.Votes.Prevotes(prs.Round).TwoThirdsMajority(); ok {
  658. peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{
  659. Height: prs.Height,
  660. Round: prs.Round,
  661. Type: types.PrevoteType,
  662. BlockID: maj23,
  663. }))
  664. time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  665. }
  666. }
  667. }
  668. // Maybe send Height/Round/Precommits
  669. {
  670. rs := conR.conS.GetRoundState()
  671. prs := ps.GetRoundState()
  672. if rs.Height == prs.Height {
  673. if maj23, ok := rs.Votes.Precommits(prs.Round).TwoThirdsMajority(); ok {
  674. peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{
  675. Height: prs.Height,
  676. Round: prs.Round,
  677. Type: types.PrecommitType,
  678. BlockID: maj23,
  679. }))
  680. time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  681. }
  682. }
  683. }
  684. // Maybe send Height/Round/ProposalPOL
  685. {
  686. rs := conR.conS.GetRoundState()
  687. prs := ps.GetRoundState()
  688. if rs.Height == prs.Height && prs.ProposalPOLRound >= 0 {
  689. if maj23, ok := rs.Votes.Prevotes(prs.ProposalPOLRound).TwoThirdsMajority(); ok {
  690. peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{
  691. Height: prs.Height,
  692. Round: prs.ProposalPOLRound,
  693. Type: types.PrevoteType,
  694. BlockID: maj23,
  695. }))
  696. time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  697. }
  698. }
  699. }
  700. // Little point sending LastCommitRound/LastCommit,
  701. // These are fleeting and non-blocking.
  702. // Maybe send Height/CatchupCommitRound/CatchupCommit.
  703. {
  704. prs := ps.GetRoundState()
  705. if prs.CatchupCommitRound != -1 && 0 < prs.Height && prs.Height <= conR.conS.blockStore.Height() {
  706. commit := conR.conS.LoadCommit(prs.Height)
  707. peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{
  708. Height: prs.Height,
  709. Round: commit.Round(),
  710. Type: types.PrecommitType,
  711. BlockID: commit.BlockID,
  712. }))
  713. time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  714. }
  715. }
  716. time.Sleep(conR.conS.config.PeerQueryMaj23SleepDuration)
  717. continue OUTER_LOOP
  718. }
  719. }
  720. func (conR *ConsensusReactor) peerStatsRoutine() {
  721. for {
  722. if !conR.IsRunning() {
  723. conR.Logger.Info("Stopping peerStatsRoutine")
  724. return
  725. }
  726. select {
  727. case msg := <-conR.conS.statsMsgQueue:
  728. // Get peer
  729. peer := conR.Switch.Peers().Get(msg.PeerID)
  730. if peer == nil {
  731. conR.Logger.Debug("Attempt to update stats for non-existent peer",
  732. "peer", msg.PeerID)
  733. continue
  734. }
  735. // Get peer state
  736. ps := peer.Get(types.PeerStateKey).(*PeerState)
  737. switch msg.Msg.(type) {
  738. case *VoteMessage:
  739. if numVotes := ps.RecordVote(); numVotes%votesToContributeToBecomeGoodPeer == 0 {
  740. conR.Switch.MarkPeerAsGood(peer)
  741. }
  742. case *BlockPartMessage:
  743. if numParts := ps.RecordBlockPart(); numParts%blocksToContributeToBecomeGoodPeer == 0 {
  744. conR.Switch.MarkPeerAsGood(peer)
  745. }
  746. }
  747. case <-conR.conS.Quit():
  748. return
  749. case <-conR.Quit():
  750. return
  751. }
  752. }
  753. }
  754. // String returns a string representation of the ConsensusReactor.
  755. // NOTE: For now, it is just a hard-coded string to avoid accessing unprotected shared variables.
  756. // TODO: improve!
  757. func (conR *ConsensusReactor) String() string {
  758. // better not to access shared variables
  759. return "ConsensusReactor" // conR.StringIndented("")
  760. }
  761. // StringIndented returns an indented string representation of the ConsensusReactor
  762. func (conR *ConsensusReactor) StringIndented(indent string) string {
  763. s := "ConsensusReactor{\n"
  764. s += indent + " " + conR.conS.StringIndented(indent+" ") + "\n"
  765. for _, peer := range conR.Switch.Peers().List() {
  766. ps := peer.Get(types.PeerStateKey).(*PeerState)
  767. s += indent + " " + ps.StringIndented(indent+" ") + "\n"
  768. }
  769. s += indent + "}"
  770. return s
  771. }
  772. func (conR *ConsensusReactor) updateFastSyncingMetric() {
  773. var fastSyncing float64
  774. if conR.fastSync {
  775. fastSyncing = 1
  776. } else {
  777. fastSyncing = 0
  778. }
  779. conR.metrics.FastSyncing.Set(fastSyncing)
  780. }
  781. // ReactorMetrics sets the metrics
  782. func ReactorMetrics(metrics *Metrics) ReactorOption {
  783. return func(conR *ConsensusReactor) { conR.metrics = metrics }
  784. }
  785. //-----------------------------------------------------------------------------
  786. var (
  787. ErrPeerStateHeightRegression = errors.New("Error peer state height regression")
  788. ErrPeerStateInvalidStartTime = errors.New("Error peer state invalid startTime")
  789. )
  790. // PeerState contains the known state of a peer, including its connection and
  791. // threadsafe access to its PeerRoundState.
  792. // NOTE: THIS GETS DUMPED WITH rpc/core/consensus.go.
  793. // Be mindful of what you Expose.
  794. type PeerState struct {
  795. peer p2p.Peer
  796. logger log.Logger
  797. mtx sync.Mutex `json:"-"` // NOTE: Modify below using setters, never directly.
  798. PRS cstypes.PeerRoundState `json:"round_state"` // Exposed.
  799. Stats *peerStateStats `json:"stats"` // Exposed.
  800. }
  801. // peerStateStats holds internal statistics for a peer.
  802. type peerStateStats struct {
  803. Votes int `json:"votes"`
  804. BlockParts int `json:"block_parts"`
  805. }
  806. func (pss peerStateStats) String() string {
  807. return fmt.Sprintf("peerStateStats{votes: %d, blockParts: %d}",
  808. pss.Votes, pss.BlockParts)
  809. }
  810. // NewPeerState returns a new PeerState for the given Peer
  811. func NewPeerState(peer p2p.Peer) *PeerState {
  812. return &PeerState{
  813. peer: peer,
  814. logger: log.NewNopLogger(),
  815. PRS: cstypes.PeerRoundState{
  816. Round: -1,
  817. ProposalPOLRound: -1,
  818. LastCommitRound: -1,
  819. CatchupCommitRound: -1,
  820. },
  821. Stats: &peerStateStats{},
  822. }
  823. }
  824. // SetLogger allows to set a logger on the peer state. Returns the peer state
  825. // itself.
  826. func (ps *PeerState) SetLogger(logger log.Logger) *PeerState {
  827. ps.logger = logger
  828. return ps
  829. }
  830. // GetRoundState returns an shallow copy of the PeerRoundState.
  831. // There's no point in mutating it since it won't change PeerState.
  832. func (ps *PeerState) GetRoundState() *cstypes.PeerRoundState {
  833. ps.mtx.Lock()
  834. defer ps.mtx.Unlock()
  835. prs := ps.PRS // copy
  836. return &prs
  837. }
  838. // ToJSON returns a json of PeerState, marshalled using go-amino.
  839. func (ps *PeerState) ToJSON() ([]byte, error) {
  840. ps.mtx.Lock()
  841. defer ps.mtx.Unlock()
  842. return cdc.MarshalJSON(ps)
  843. }
  844. // GetHeight returns an atomic snapshot of the PeerRoundState's height
  845. // used by the mempool to ensure peers are caught up before broadcasting new txs
  846. func (ps *PeerState) GetHeight() int64 {
  847. ps.mtx.Lock()
  848. defer ps.mtx.Unlock()
  849. return ps.PRS.Height
  850. }
  851. // SetHasProposal sets the given proposal as known for the peer.
  852. func (ps *PeerState) SetHasProposal(proposal *types.Proposal) {
  853. ps.mtx.Lock()
  854. defer ps.mtx.Unlock()
  855. if ps.PRS.Height != proposal.Height || ps.PRS.Round != proposal.Round {
  856. return
  857. }
  858. if ps.PRS.Proposal {
  859. return
  860. }
  861. ps.PRS.Proposal = true
  862. // ps.PRS.ProposalBlockParts is set due to NewValidBlockMessage
  863. if ps.PRS.ProposalBlockParts != nil {
  864. return
  865. }
  866. ps.PRS.ProposalBlockPartsHeader = proposal.BlockID.PartsHeader
  867. ps.PRS.ProposalBlockParts = cmn.NewBitArray(proposal.BlockID.PartsHeader.Total)
  868. ps.PRS.ProposalPOLRound = proposal.POLRound
  869. ps.PRS.ProposalPOL = nil // Nil until ProposalPOLMessage received.
  870. }
  871. // InitProposalBlockParts initializes the peer's proposal block parts header and bit array.
  872. func (ps *PeerState) InitProposalBlockParts(partsHeader types.PartSetHeader) {
  873. ps.mtx.Lock()
  874. defer ps.mtx.Unlock()
  875. if ps.PRS.ProposalBlockParts != nil {
  876. return
  877. }
  878. ps.PRS.ProposalBlockPartsHeader = partsHeader
  879. ps.PRS.ProposalBlockParts = cmn.NewBitArray(partsHeader.Total)
  880. }
  881. // SetHasProposalBlockPart sets the given block part index as known for the peer.
  882. func (ps *PeerState) SetHasProposalBlockPart(height int64, round int, index int) {
  883. ps.mtx.Lock()
  884. defer ps.mtx.Unlock()
  885. if ps.PRS.Height != height || ps.PRS.Round != round {
  886. return
  887. }
  888. ps.PRS.ProposalBlockParts.SetIndex(index, true)
  889. }
  890. // PickSendVote picks a vote and sends it to the peer.
  891. // Returns true if vote was sent.
  892. func (ps *PeerState) PickSendVote(votes types.VoteSetReader) bool {
  893. if vote, ok := ps.PickVoteToSend(votes); ok {
  894. msg := &VoteMessage{vote}
  895. ps.logger.Debug("Sending vote message", "ps", ps, "vote", vote)
  896. return ps.peer.Send(VoteChannel, cdc.MustMarshalBinaryBare(msg))
  897. }
  898. return false
  899. }
  900. // PickVoteToSend picks a vote to send to the peer.
  901. // Returns true if a vote was picked.
  902. // NOTE: `votes` must be the correct Size() for the Height().
  903. func (ps *PeerState) PickVoteToSend(votes types.VoteSetReader) (vote *types.Vote, ok bool) {
  904. ps.mtx.Lock()
  905. defer ps.mtx.Unlock()
  906. if votes.Size() == 0 {
  907. return nil, false
  908. }
  909. height, round, type_, size := votes.Height(), votes.Round(), types.SignedMsgType(votes.Type()), votes.Size()
  910. // Lazily set data using 'votes'.
  911. if votes.IsCommit() {
  912. ps.ensureCatchupCommitRound(height, round, size)
  913. }
  914. ps.ensureVoteBitArrays(height, size)
  915. psVotes := ps.getVoteBitArray(height, round, type_)
  916. if psVotes == nil {
  917. return nil, false // Not something worth sending
  918. }
  919. if index, ok := votes.BitArray().Sub(psVotes).PickRandom(); ok {
  920. ps.setHasVote(height, round, type_, index)
  921. return votes.GetByIndex(index), true
  922. }
  923. return nil, false
  924. }
  925. func (ps *PeerState) getVoteBitArray(height int64, round int, type_ types.SignedMsgType) *cmn.BitArray {
  926. if !types.IsVoteTypeValid(type_) {
  927. return nil
  928. }
  929. if ps.PRS.Height == height {
  930. if ps.PRS.Round == round {
  931. switch type_ {
  932. case types.PrevoteType:
  933. return ps.PRS.Prevotes
  934. case types.PrecommitType:
  935. return ps.PRS.Precommits
  936. }
  937. }
  938. if ps.PRS.CatchupCommitRound == round {
  939. switch type_ {
  940. case types.PrevoteType:
  941. return nil
  942. case types.PrecommitType:
  943. return ps.PRS.CatchupCommit
  944. }
  945. }
  946. if ps.PRS.ProposalPOLRound == round {
  947. switch type_ {
  948. case types.PrevoteType:
  949. return ps.PRS.ProposalPOL
  950. case types.PrecommitType:
  951. return nil
  952. }
  953. }
  954. return nil
  955. }
  956. if ps.PRS.Height == height+1 {
  957. if ps.PRS.LastCommitRound == round {
  958. switch type_ {
  959. case types.PrevoteType:
  960. return nil
  961. case types.PrecommitType:
  962. return ps.PRS.LastCommit
  963. }
  964. }
  965. return nil
  966. }
  967. return nil
  968. }
  969. // 'round': A round for which we have a +2/3 commit.
  970. func (ps *PeerState) ensureCatchupCommitRound(height int64, round int, numValidators int) {
  971. if ps.PRS.Height != height {
  972. return
  973. }
  974. /*
  975. NOTE: This is wrong, 'round' could change.
  976. e.g. if orig round is not the same as block LastCommit round.
  977. if ps.CatchupCommitRound != -1 && ps.CatchupCommitRound != round {
  978. cmn.PanicSanity(fmt.Sprintf("Conflicting CatchupCommitRound. Height: %v, Orig: %v, New: %v", height, ps.CatchupCommitRound, round))
  979. }
  980. */
  981. if ps.PRS.CatchupCommitRound == round {
  982. return // Nothing to do!
  983. }
  984. ps.PRS.CatchupCommitRound = round
  985. if round == ps.PRS.Round {
  986. ps.PRS.CatchupCommit = ps.PRS.Precommits
  987. } else {
  988. ps.PRS.CatchupCommit = cmn.NewBitArray(numValidators)
  989. }
  990. }
  991. // EnsureVoteBitArrays ensures the bit-arrays have been allocated for tracking
  992. // what votes this peer has received.
  993. // NOTE: It's important to make sure that numValidators actually matches
  994. // what the node sees as the number of validators for height.
  995. func (ps *PeerState) EnsureVoteBitArrays(height int64, numValidators int) {
  996. ps.mtx.Lock()
  997. defer ps.mtx.Unlock()
  998. ps.ensureVoteBitArrays(height, numValidators)
  999. }
  1000. func (ps *PeerState) ensureVoteBitArrays(height int64, numValidators int) {
  1001. if ps.PRS.Height == height {
  1002. if ps.PRS.Prevotes == nil {
  1003. ps.PRS.Prevotes = cmn.NewBitArray(numValidators)
  1004. }
  1005. if ps.PRS.Precommits == nil {
  1006. ps.PRS.Precommits = cmn.NewBitArray(numValidators)
  1007. }
  1008. if ps.PRS.CatchupCommit == nil {
  1009. ps.PRS.CatchupCommit = cmn.NewBitArray(numValidators)
  1010. }
  1011. if ps.PRS.ProposalPOL == nil {
  1012. ps.PRS.ProposalPOL = cmn.NewBitArray(numValidators)
  1013. }
  1014. } else if ps.PRS.Height == height+1 {
  1015. if ps.PRS.LastCommit == nil {
  1016. ps.PRS.LastCommit = cmn.NewBitArray(numValidators)
  1017. }
  1018. }
  1019. }
  1020. // RecordVote increments internal votes related statistics for this peer.
  1021. // It returns the total number of added votes.
  1022. func (ps *PeerState) RecordVote() int {
  1023. ps.mtx.Lock()
  1024. defer ps.mtx.Unlock()
  1025. ps.Stats.Votes++
  1026. return ps.Stats.Votes
  1027. }
  1028. // VotesSent returns the number of blocks for which peer has been sending us
  1029. // votes.
  1030. func (ps *PeerState) VotesSent() int {
  1031. ps.mtx.Lock()
  1032. defer ps.mtx.Unlock()
  1033. return ps.Stats.Votes
  1034. }
  1035. // RecordBlockPart increments internal block part related statistics for this peer.
  1036. // It returns the total number of added block parts.
  1037. func (ps *PeerState) RecordBlockPart() int {
  1038. ps.mtx.Lock()
  1039. defer ps.mtx.Unlock()
  1040. ps.Stats.BlockParts++
  1041. return ps.Stats.BlockParts
  1042. }
  1043. // BlockPartsSent returns the number of useful block parts the peer has sent us.
  1044. func (ps *PeerState) BlockPartsSent() int {
  1045. ps.mtx.Lock()
  1046. defer ps.mtx.Unlock()
  1047. return ps.Stats.BlockParts
  1048. }
  1049. // SetHasVote sets the given vote as known by the peer
  1050. func (ps *PeerState) SetHasVote(vote *types.Vote) {
  1051. ps.mtx.Lock()
  1052. defer ps.mtx.Unlock()
  1053. ps.setHasVote(vote.Height, vote.Round, vote.Type, vote.ValidatorIndex)
  1054. }
  1055. func (ps *PeerState) setHasVote(height int64, round int, type_ types.SignedMsgType, index int) {
  1056. logger := ps.logger.With("peerH/R", fmt.Sprintf("%d/%d", ps.PRS.Height, ps.PRS.Round), "H/R", fmt.Sprintf("%d/%d", height, round))
  1057. logger.Debug("setHasVote", "type", type_, "index", index)
  1058. // NOTE: some may be nil BitArrays -> no side effects.
  1059. psVotes := ps.getVoteBitArray(height, round, type_)
  1060. if psVotes != nil {
  1061. psVotes.SetIndex(index, true)
  1062. }
  1063. }
  1064. // ApplyNewRoundStepMessage updates the peer state for the new round.
  1065. func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) {
  1066. ps.mtx.Lock()
  1067. defer ps.mtx.Unlock()
  1068. // Ignore duplicates or decreases
  1069. if CompareHRS(msg.Height, msg.Round, msg.Step, ps.PRS.Height, ps.PRS.Round, ps.PRS.Step) <= 0 {
  1070. return
  1071. }
  1072. // Just remember these values.
  1073. psHeight := ps.PRS.Height
  1074. psRound := ps.PRS.Round
  1075. psCatchupCommitRound := ps.PRS.CatchupCommitRound
  1076. psCatchupCommit := ps.PRS.CatchupCommit
  1077. startTime := tmtime.Now().Add(-1 * time.Duration(msg.SecondsSinceStartTime) * time.Second)
  1078. ps.PRS.Height = msg.Height
  1079. ps.PRS.Round = msg.Round
  1080. ps.PRS.Step = msg.Step
  1081. ps.PRS.StartTime = startTime
  1082. if psHeight != msg.Height || psRound != msg.Round {
  1083. ps.PRS.Proposal = false
  1084. ps.PRS.ProposalBlockPartsHeader = types.PartSetHeader{}
  1085. ps.PRS.ProposalBlockParts = nil
  1086. ps.PRS.ProposalPOLRound = -1
  1087. ps.PRS.ProposalPOL = nil
  1088. // We'll update the BitArray capacity later.
  1089. ps.PRS.Prevotes = nil
  1090. ps.PRS.Precommits = nil
  1091. }
  1092. if psHeight == msg.Height && psRound != msg.Round && msg.Round == psCatchupCommitRound {
  1093. // Peer caught up to CatchupCommitRound.
  1094. // Preserve psCatchupCommit!
  1095. // NOTE: We prefer to use prs.Precommits if
  1096. // pr.Round matches pr.CatchupCommitRound.
  1097. ps.PRS.Precommits = psCatchupCommit
  1098. }
  1099. if psHeight != msg.Height {
  1100. // Shift Precommits to LastCommit.
  1101. if psHeight+1 == msg.Height && psRound == msg.LastCommitRound {
  1102. ps.PRS.LastCommitRound = msg.LastCommitRound
  1103. ps.PRS.LastCommit = ps.PRS.Precommits
  1104. } else {
  1105. ps.PRS.LastCommitRound = msg.LastCommitRound
  1106. ps.PRS.LastCommit = nil
  1107. }
  1108. // We'll update the BitArray capacity later.
  1109. ps.PRS.CatchupCommitRound = -1
  1110. ps.PRS.CatchupCommit = nil
  1111. }
  1112. }
  1113. // ApplyNewValidBlockMessage updates the peer state for the new valid block.
  1114. func (ps *PeerState) ApplyNewValidBlockMessage(msg *NewValidBlockMessage) {
  1115. ps.mtx.Lock()
  1116. defer ps.mtx.Unlock()
  1117. if ps.PRS.Height != msg.Height {
  1118. return
  1119. }
  1120. if ps.PRS.Round != msg.Round && !msg.IsCommit {
  1121. return
  1122. }
  1123. ps.PRS.ProposalBlockPartsHeader = msg.BlockPartsHeader
  1124. ps.PRS.ProposalBlockParts = msg.BlockParts
  1125. }
  1126. // ApplyProposalPOLMessage updates the peer state for the new proposal POL.
  1127. func (ps *PeerState) ApplyProposalPOLMessage(msg *ProposalPOLMessage) {
  1128. ps.mtx.Lock()
  1129. defer ps.mtx.Unlock()
  1130. if ps.PRS.Height != msg.Height {
  1131. return
  1132. }
  1133. if ps.PRS.ProposalPOLRound != msg.ProposalPOLRound {
  1134. return
  1135. }
  1136. // TODO: Merge onto existing ps.PRS.ProposalPOL?
  1137. // We might have sent some prevotes in the meantime.
  1138. ps.PRS.ProposalPOL = msg.ProposalPOL
  1139. }
  1140. // ApplyHasVoteMessage updates the peer state for the new vote.
  1141. func (ps *PeerState) ApplyHasVoteMessage(msg *HasVoteMessage) {
  1142. ps.mtx.Lock()
  1143. defer ps.mtx.Unlock()
  1144. if ps.PRS.Height != msg.Height {
  1145. return
  1146. }
  1147. ps.setHasVote(msg.Height, msg.Round, msg.Type, msg.Index)
  1148. }
  1149. // ApplyVoteSetBitsMessage updates the peer state for the bit-array of votes
  1150. // it claims to have for the corresponding BlockID.
  1151. // `ourVotes` is a BitArray of votes we have for msg.BlockID
  1152. // NOTE: if ourVotes is nil (e.g. msg.Height < rs.Height),
  1153. // we conservatively overwrite ps's votes w/ msg.Votes.
  1154. func (ps *PeerState) ApplyVoteSetBitsMessage(msg *VoteSetBitsMessage, ourVotes *cmn.BitArray) {
  1155. ps.mtx.Lock()
  1156. defer ps.mtx.Unlock()
  1157. votes := ps.getVoteBitArray(msg.Height, msg.Round, msg.Type)
  1158. if votes != nil {
  1159. if ourVotes == nil {
  1160. votes.Update(msg.Votes)
  1161. } else {
  1162. otherVotes := votes.Sub(ourVotes)
  1163. hasVotes := otherVotes.Or(msg.Votes)
  1164. votes.Update(hasVotes)
  1165. }
  1166. }
  1167. }
  1168. // String returns a string representation of the PeerState
  1169. func (ps *PeerState) String() string {
  1170. return ps.StringIndented("")
  1171. }
  1172. // StringIndented returns a string representation of the PeerState
  1173. func (ps *PeerState) StringIndented(indent string) string {
  1174. ps.mtx.Lock()
  1175. defer ps.mtx.Unlock()
  1176. return fmt.Sprintf(`PeerState{
  1177. %s Key %v
  1178. %s RoundState %v
  1179. %s Stats %v
  1180. %s}`,
  1181. indent, ps.peer.ID(),
  1182. indent, ps.PRS.StringIndented(indent+" "),
  1183. indent, ps.Stats,
  1184. indent)
  1185. }
  1186. //-----------------------------------------------------------------------------
  1187. // Messages
  1188. // ConsensusMessage is a message that can be sent and received on the ConsensusReactor
  1189. type ConsensusMessage interface {
  1190. ValidateBasic() error
  1191. }
  1192. func RegisterConsensusMessages(cdc *amino.Codec) {
  1193. cdc.RegisterInterface((*ConsensusMessage)(nil), nil)
  1194. cdc.RegisterConcrete(&NewRoundStepMessage{}, "tendermint/NewRoundStepMessage", nil)
  1195. cdc.RegisterConcrete(&NewValidBlockMessage{}, "tendermint/NewValidBlockMessage", nil)
  1196. cdc.RegisterConcrete(&ProposalMessage{}, "tendermint/Proposal", nil)
  1197. cdc.RegisterConcrete(&ProposalPOLMessage{}, "tendermint/ProposalPOL", nil)
  1198. cdc.RegisterConcrete(&BlockPartMessage{}, "tendermint/BlockPart", nil)
  1199. cdc.RegisterConcrete(&VoteMessage{}, "tendermint/Vote", nil)
  1200. cdc.RegisterConcrete(&HasVoteMessage{}, "tendermint/HasVote", nil)
  1201. cdc.RegisterConcrete(&VoteSetMaj23Message{}, "tendermint/VoteSetMaj23", nil)
  1202. cdc.RegisterConcrete(&VoteSetBitsMessage{}, "tendermint/VoteSetBits", nil)
  1203. cdc.RegisterConcrete(&ProposalHeartbeatMessage{}, "tendermint/ProposalHeartbeat", nil)
  1204. }
  1205. func decodeMsg(bz []byte) (msg ConsensusMessage, err error) {
  1206. if len(bz) > maxMsgSize {
  1207. return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", len(bz), maxMsgSize)
  1208. }
  1209. err = cdc.UnmarshalBinaryBare(bz, &msg)
  1210. return
  1211. }
  1212. //-------------------------------------
  1213. // NewRoundStepMessage is sent for every step taken in the ConsensusState.
  1214. // For every height/round/step transition
  1215. type NewRoundStepMessage struct {
  1216. Height int64
  1217. Round int
  1218. Step cstypes.RoundStepType
  1219. SecondsSinceStartTime int
  1220. LastCommitRound int
  1221. }
  1222. // ValidateBasic performs basic validation.
  1223. func (m *NewRoundStepMessage) ValidateBasic() error {
  1224. if m.Height < 0 {
  1225. return errors.New("Negative Height")
  1226. }
  1227. if m.Round < 0 {
  1228. return errors.New("Negative Round")
  1229. }
  1230. if !m.Step.IsValid() {
  1231. return errors.New("Invalid Step")
  1232. }
  1233. // NOTE: SecondsSinceStartTime may be negative
  1234. if (m.Height == 1 && m.LastCommitRound != -1) ||
  1235. (m.Height > 1 && m.LastCommitRound < -1) { // TODO: #2737 LastCommitRound should always be >= 0 for heights > 1
  1236. return errors.New("Invalid LastCommitRound (for 1st block: -1, for others: >= 0)")
  1237. }
  1238. return nil
  1239. }
  1240. // String returns a string representation.
  1241. func (m *NewRoundStepMessage) String() string {
  1242. return fmt.Sprintf("[NewRoundStep H:%v R:%v S:%v LCR:%v]",
  1243. m.Height, m.Round, m.Step, m.LastCommitRound)
  1244. }
  1245. //-------------------------------------
  1246. // NewValidBlockMessage is sent when a validator observes a valid block B in some round r,
  1247. //i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r.
  1248. // In case the block is also committed, then IsCommit flag is set to true.
  1249. type NewValidBlockMessage struct {
  1250. Height int64
  1251. Round int
  1252. BlockPartsHeader types.PartSetHeader
  1253. BlockParts *cmn.BitArray
  1254. IsCommit bool
  1255. }
  1256. // ValidateBasic performs basic validation.
  1257. func (m *NewValidBlockMessage) ValidateBasic() error {
  1258. if m.Height < 0 {
  1259. return errors.New("Negative Height")
  1260. }
  1261. if m.Round < 0 {
  1262. return errors.New("Negative Round")
  1263. }
  1264. if err := m.BlockPartsHeader.ValidateBasic(); err != nil {
  1265. return fmt.Errorf("Wrong BlockPartsHeader: %v", err)
  1266. }
  1267. if m.BlockParts.Size() != m.BlockPartsHeader.Total {
  1268. return fmt.Errorf("BlockParts bit array size %d not equal to BlockPartsHeader.Total %d",
  1269. m.BlockParts.Size(),
  1270. m.BlockPartsHeader.Total)
  1271. }
  1272. return nil
  1273. }
  1274. // String returns a string representation.
  1275. func (m *NewValidBlockMessage) String() string {
  1276. return fmt.Sprintf("[ValidBlockMessage H:%v R:%v BP:%v BA:%v IsCommit:%v]",
  1277. m.Height, m.Round, m.BlockPartsHeader, m.BlockParts, m.IsCommit)
  1278. }
  1279. //-------------------------------------
  1280. // ProposalMessage is sent when a new block is proposed.
  1281. type ProposalMessage struct {
  1282. Proposal *types.Proposal
  1283. }
  1284. // ValidateBasic performs basic validation.
  1285. func (m *ProposalMessage) ValidateBasic() error {
  1286. return m.Proposal.ValidateBasic()
  1287. }
  1288. // String returns a string representation.
  1289. func (m *ProposalMessage) String() string {
  1290. return fmt.Sprintf("[Proposal %v]", m.Proposal)
  1291. }
  1292. //-------------------------------------
  1293. // ProposalPOLMessage is sent when a previous proposal is re-proposed.
  1294. type ProposalPOLMessage struct {
  1295. Height int64
  1296. ProposalPOLRound int
  1297. ProposalPOL *cmn.BitArray
  1298. }
  1299. // ValidateBasic performs basic validation.
  1300. func (m *ProposalPOLMessage) ValidateBasic() error {
  1301. if m.Height < 0 {
  1302. return errors.New("Negative Height")
  1303. }
  1304. if m.ProposalPOLRound < 0 {
  1305. return errors.New("Negative ProposalPOLRound")
  1306. }
  1307. if m.ProposalPOL.Size() == 0 {
  1308. return errors.New("Empty ProposalPOL bit array")
  1309. }
  1310. return nil
  1311. }
  1312. // String returns a string representation.
  1313. func (m *ProposalPOLMessage) String() string {
  1314. return fmt.Sprintf("[ProposalPOL H:%v POLR:%v POL:%v]", m.Height, m.ProposalPOLRound, m.ProposalPOL)
  1315. }
  1316. //-------------------------------------
  1317. // BlockPartMessage is sent when gossipping a piece of the proposed block.
  1318. type BlockPartMessage struct {
  1319. Height int64
  1320. Round int
  1321. Part *types.Part
  1322. }
  1323. // ValidateBasic performs basic validation.
  1324. func (m *BlockPartMessage) ValidateBasic() error {
  1325. if m.Height < 0 {
  1326. return errors.New("Negative Height")
  1327. }
  1328. if m.Round < 0 {
  1329. return errors.New("Negative Round")
  1330. }
  1331. if err := m.Part.ValidateBasic(); err != nil {
  1332. return fmt.Errorf("Wrong Part: %v", err)
  1333. }
  1334. return nil
  1335. }
  1336. // String returns a string representation.
  1337. func (m *BlockPartMessage) String() string {
  1338. return fmt.Sprintf("[BlockPart H:%v R:%v P:%v]", m.Height, m.Round, m.Part)
  1339. }
  1340. //-------------------------------------
  1341. // VoteMessage is sent when voting for a proposal (or lack thereof).
  1342. type VoteMessage struct {
  1343. Vote *types.Vote
  1344. }
  1345. // ValidateBasic performs basic validation.
  1346. func (m *VoteMessage) ValidateBasic() error {
  1347. return m.Vote.ValidateBasic()
  1348. }
  1349. // String returns a string representation.
  1350. func (m *VoteMessage) String() string {
  1351. return fmt.Sprintf("[Vote %v]", m.Vote)
  1352. }
  1353. //-------------------------------------
  1354. // HasVoteMessage is sent to indicate that a particular vote has been received.
  1355. type HasVoteMessage struct {
  1356. Height int64
  1357. Round int
  1358. Type types.SignedMsgType
  1359. Index int
  1360. }
  1361. // ValidateBasic performs basic validation.
  1362. func (m *HasVoteMessage) ValidateBasic() error {
  1363. if m.Height < 0 {
  1364. return errors.New("Negative Height")
  1365. }
  1366. if m.Round < 0 {
  1367. return errors.New("Negative Round")
  1368. }
  1369. if !types.IsVoteTypeValid(m.Type) {
  1370. return errors.New("Invalid Type")
  1371. }
  1372. if m.Index < 0 {
  1373. return errors.New("Negative Index")
  1374. }
  1375. return nil
  1376. }
  1377. // String returns a string representation.
  1378. func (m *HasVoteMessage) String() string {
  1379. return fmt.Sprintf("[HasVote VI:%v V:{%v/%02d/%v}]", m.Index, m.Height, m.Round, m.Type)
  1380. }
  1381. //-------------------------------------
  1382. // VoteSetMaj23Message is sent to indicate that a given BlockID has seen +2/3 votes.
  1383. type VoteSetMaj23Message struct {
  1384. Height int64
  1385. Round int
  1386. Type types.SignedMsgType
  1387. BlockID types.BlockID
  1388. }
  1389. // ValidateBasic performs basic validation.
  1390. func (m *VoteSetMaj23Message) ValidateBasic() error {
  1391. if m.Height < 0 {
  1392. return errors.New("Negative Height")
  1393. }
  1394. if m.Round < 0 {
  1395. return errors.New("Negative Round")
  1396. }
  1397. if !types.IsVoteTypeValid(m.Type) {
  1398. return errors.New("Invalid Type")
  1399. }
  1400. if err := m.BlockID.ValidateBasic(); err != nil {
  1401. return fmt.Errorf("Wrong BlockID: %v", err)
  1402. }
  1403. return nil
  1404. }
  1405. // String returns a string representation.
  1406. func (m *VoteSetMaj23Message) String() string {
  1407. return fmt.Sprintf("[VSM23 %v/%02d/%v %v]", m.Height, m.Round, m.Type, m.BlockID)
  1408. }
  1409. //-------------------------------------
  1410. // VoteSetBitsMessage is sent to communicate the bit-array of votes seen for the BlockID.
  1411. type VoteSetBitsMessage struct {
  1412. Height int64
  1413. Round int
  1414. Type types.SignedMsgType
  1415. BlockID types.BlockID
  1416. Votes *cmn.BitArray
  1417. }
  1418. // ValidateBasic performs basic validation.
  1419. func (m *VoteSetBitsMessage) ValidateBasic() error {
  1420. if m.Height < 0 {
  1421. return errors.New("Negative Height")
  1422. }
  1423. if m.Round < 0 {
  1424. return errors.New("Negative Round")
  1425. }
  1426. if !types.IsVoteTypeValid(m.Type) {
  1427. return errors.New("Invalid Type")
  1428. }
  1429. if err := m.BlockID.ValidateBasic(); err != nil {
  1430. return fmt.Errorf("Wrong BlockID: %v", err)
  1431. }
  1432. // NOTE: Votes.Size() can be zero if the node does not have any
  1433. return nil
  1434. }
  1435. // String returns a string representation.
  1436. func (m *VoteSetBitsMessage) String() string {
  1437. return fmt.Sprintf("[VSB %v/%02d/%v %v %v]", m.Height, m.Round, m.Type, m.BlockID, m.Votes)
  1438. }
  1439. //-------------------------------------
  1440. // ProposalHeartbeatMessage is sent to signal that a node is alive and waiting for transactions for a proposal.
  1441. type ProposalHeartbeatMessage struct {
  1442. Heartbeat *types.Heartbeat
  1443. }
  1444. // ValidateBasic performs basic validation.
  1445. func (m *ProposalHeartbeatMessage) ValidateBasic() error {
  1446. return m.Heartbeat.ValidateBasic()
  1447. }
  1448. // String returns a string representation.
  1449. func (m *ProposalHeartbeatMessage) String() string {
  1450. return fmt.Sprintf("[HEARTBEAT %v]", m.Heartbeat)
  1451. }