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.

1099 lines
35 KiB

9 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
9 years ago
9 years ago
fix TestFullRound1 race (Refs #846) ``` ================== WARNING: DATA RACE Write at 0x00c42d7605f0 by goroutine 844: github.com/tendermint/tendermint/consensus.(*ConsensusState).updateToState() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:465 +0x59e I[11-14|22:37:28.781] Added to prevote vote="Vote{0:646753DCE124 1/02/1(Prevote) E9B19636DCDB {/CAD5FA805E8C.../}}" prevotes="VoteSet{H:1 R:2 T:1 +2/3:<nil> BA{2:X_} map[]}" github.com/tendermint/tendermint/consensus.(*ConsensusState).finalizeCommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1229 +0x16a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).tryFinalizeCommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1135 +0x721 github.com/tendermint/tendermint/consensus.(*ConsensusState).enterCommit.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1087 +0x153 github.com/tendermint/tendermint/consensus.(*ConsensusState).enterCommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1114 +0xa34 github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1423 +0xdd6 github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1317 +0x77 github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:565 +0x7a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:523 +0x6d2 Previous read at 0x00c42d7605f0 by goroutine 654: github.com/tendermint/tendermint/consensus.validatePrevote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/common_test.go:149 +0x57 github.com/tendermint/tendermint/consensus.TestFullRound1() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state_test.go:256 +0x3c5 testing.tRunner() /usr/local/go/src/testing/testing.go:746 +0x16c Goroutine 844 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).startRoutines() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:258 +0x8c github.com/tendermint/tendermint/consensus.startTestRound() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/common_test.go:118 +0x63 github.com/tendermint/tendermint/consensus.TestFullRound1() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state_test.go:247 +0x1fb testing.tRunner() /usr/local/go/src/testing/testing.go:746 +0x16c Goroutine 654 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:789 +0x568 testing.runTests.func1() /usr/local/go/src/testing/testing.go:1004 +0xa7 testing.tRunner() /usr/local/go/src/testing/testing.go:746 +0x16c testing.runTests() /usr/local/go/src/testing/testing.go:1002 +0x521 testing.(*M).Run() /usr/local/go/src/testing/testing.go:921 +0x206 main.main() github.com/tendermint/tendermint/consensus/_test/_testmain.go:106 +0x1d3 ================== ```
7 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
9 years ago
8 years ago
9 years ago
9 years ago
9 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
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
9 years ago
9 years ago
9 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
9 years ago
9 years ago
8 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
fix TestFullRound1 race (Refs #846) ``` ================== WARNING: DATA RACE Write at 0x00c42d7605f0 by goroutine 844: github.com/tendermint/tendermint/consensus.(*ConsensusState).updateToState() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:465 +0x59e I[11-14|22:37:28.781] Added to prevote vote="Vote{0:646753DCE124 1/02/1(Prevote) E9B19636DCDB {/CAD5FA805E8C.../}}" prevotes="VoteSet{H:1 R:2 T:1 +2/3:<nil> BA{2:X_} map[]}" github.com/tendermint/tendermint/consensus.(*ConsensusState).finalizeCommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1229 +0x16a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).tryFinalizeCommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1135 +0x721 github.com/tendermint/tendermint/consensus.(*ConsensusState).enterCommit.func1() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1087 +0x153 github.com/tendermint/tendermint/consensus.(*ConsensusState).enterCommit() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1114 +0xa34 github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1423 +0xdd6 github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:1317 +0x77 github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:565 +0x7a9 github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:523 +0x6d2 Previous read at 0x00c42d7605f0 by goroutine 654: github.com/tendermint/tendermint/consensus.validatePrevote() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/common_test.go:149 +0x57 github.com/tendermint/tendermint/consensus.TestFullRound1() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state_test.go:256 +0x3c5 testing.tRunner() /usr/local/go/src/testing/testing.go:746 +0x16c Goroutine 844 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).startRoutines() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state.go:258 +0x8c github.com/tendermint/tendermint/consensus.startTestRound() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/common_test.go:118 +0x63 github.com/tendermint/tendermint/consensus.TestFullRound1() /home/vagrant/go/src/github.com/tendermint/tendermint/consensus/state_test.go:247 +0x1fb testing.tRunner() /usr/local/go/src/testing/testing.go:746 +0x16c Goroutine 654 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:789 +0x568 testing.runTests.func1() /usr/local/go/src/testing/testing.go:1004 +0xa7 testing.tRunner() /usr/local/go/src/testing/testing.go:746 +0x16c testing.runTests() /usr/local/go/src/testing/testing.go:1002 +0x521 testing.(*M).Run() /usr/local/go/src/testing/testing.go:921 +0x206 main.main() github.com/tendermint/tendermint/consensus/_test/_testmain.go:106 +0x1d3 ================== ```
7 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
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 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
  1. package consensus
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "testing"
  7. "time"
  8. cstypes "github.com/tendermint/tendermint/consensus/types"
  9. "github.com/tendermint/tendermint/types"
  10. cmn "github.com/tendermint/tmlibs/common"
  11. "github.com/tendermint/tmlibs/log"
  12. tmpubsub "github.com/tendermint/tmlibs/pubsub"
  13. )
  14. func init() {
  15. config = ResetConfig("consensus_state_test")
  16. }
  17. func ensureProposeTimeout(timeoutPropose int) time.Duration {
  18. return time.Duration(timeoutPropose*2) * time.Millisecond
  19. }
  20. /*
  21. ProposeSuite
  22. x * TestProposerSelection0 - round robin ordering, round 0
  23. x * TestProposerSelection2 - round robin ordering, round 2++
  24. x * TestEnterProposeNoValidator - timeout into prevote round
  25. x * TestEnterPropose - finish propose without timing out (we have the proposal)
  26. x * TestBadProposal - 2 vals, bad proposal (bad block state hash), should prevote and precommit nil
  27. FullRoundSuite
  28. x * TestFullRound1 - 1 val, full successful round
  29. x * TestFullRoundNil - 1 val, full round of nil
  30. x * TestFullRound2 - 2 vals, both required for full round
  31. LockSuite
  32. x * TestLockNoPOL - 2 vals, 4 rounds. one val locked, precommits nil every round except first.
  33. x * TestLockPOLRelock - 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka
  34. x * TestLockPOLUnlock - 4 vals, one precommits, other 3 polka nil at next round, so we unlock and precomit nil
  35. x * TestLockPOLSafety1 - 4 vals. We shouldn't change lock based on polka at earlier round
  36. x * TestLockPOLSafety2 - 4 vals. After unlocking, we shouldn't relock based on polka at earlier round
  37. * TestNetworkLock - once +1/3 precommits, network should be locked
  38. * TestNetworkLockPOL - once +1/3 precommits, the block with more recent polka is committed
  39. SlashingSuite
  40. x * TestSlashingPrevotes - a validator prevoting twice in a round gets slashed
  41. x * TestSlashingPrecommits - a validator precomitting twice in a round gets slashed
  42. CatchupSuite
  43. * TestCatchup - if we might be behind and we've seen any 2/3 prevotes, round skip to new round, precommit, or prevote
  44. HaltSuite
  45. x * TestHalt1 - if we see +2/3 precommits after timing out into new round, we should still commit
  46. */
  47. //----------------------------------------------------------------------------------------------------
  48. // ProposeSuite
  49. func TestStateProposerSelection0(t *testing.T) {
  50. cs1, vss := randConsensusState(4)
  51. height, round := cs1.Height, cs1.Round
  52. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  53. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  54. startTestRound(cs1, height, round)
  55. // wait for new round so proposer is set
  56. <-newRoundCh
  57. // lets commit a block and ensure proposer for the next height is correct
  58. prop := cs1.GetRoundState().Validators.GetProposer()
  59. if !bytes.Equal(prop.Address, cs1.privValidator.GetAddress()) {
  60. t.Fatalf("expected proposer to be validator %d. Got %X", 0, prop.Address)
  61. }
  62. // wait for complete proposal
  63. <-proposalCh
  64. rs := cs1.GetRoundState()
  65. signAddVotes(cs1, types.VoteTypePrecommit, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vss[1:]...)
  66. // wait for new round so next validator is set
  67. <-newRoundCh
  68. prop = cs1.GetRoundState().Validators.GetProposer()
  69. if !bytes.Equal(prop.Address, vss[1].GetAddress()) {
  70. panic(cmn.Fmt("expected proposer to be validator %d. Got %X", 1, prop.Address))
  71. }
  72. }
  73. // Now let's do it all again, but starting from round 2 instead of 0
  74. func TestStateProposerSelection2(t *testing.T) {
  75. cs1, vss := randConsensusState(4) // test needs more work for more than 3 validators
  76. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  77. // this time we jump in at round 2
  78. incrementRound(vss[1:]...)
  79. incrementRound(vss[1:]...)
  80. startTestRound(cs1, cs1.Height, 2)
  81. <-newRoundCh // wait for the new round
  82. // everyone just votes nil. we get a new proposer each round
  83. for i := 0; i < len(vss); i++ {
  84. prop := cs1.GetRoundState().Validators.GetProposer()
  85. if !bytes.Equal(prop.Address, vss[(i+2)%len(vss)].GetAddress()) {
  86. panic(cmn.Fmt("expected proposer to be validator %d. Got %X", (i+2)%len(vss), prop.Address))
  87. }
  88. rs := cs1.GetRoundState()
  89. signAddVotes(cs1, types.VoteTypePrecommit, nil, rs.ProposalBlockParts.Header(), vss[1:]...)
  90. <-newRoundCh // wait for the new round event each round
  91. incrementRound(vss[1:]...)
  92. }
  93. }
  94. // a non-validator should timeout into the prevote round
  95. func TestStateEnterProposeNoPrivValidator(t *testing.T) {
  96. cs, _ := randConsensusState(1)
  97. cs.SetPrivValidator(nil)
  98. height, round := cs.Height, cs.Round
  99. // Listen for propose timeout event
  100. timeoutCh := subscribe(cs.eventBus, types.EventQueryTimeoutPropose)
  101. startTestRound(cs, height, round)
  102. // if we're not a validator, EnterPropose should timeout
  103. ticker := time.NewTicker(ensureProposeTimeout(cs.config.TimeoutPropose))
  104. select {
  105. case <-timeoutCh:
  106. case <-ticker.C:
  107. panic("Expected EnterPropose to timeout")
  108. }
  109. if cs.GetRoundState().Proposal != nil {
  110. t.Error("Expected to make no proposal, since no privValidator")
  111. }
  112. }
  113. // a validator should not timeout of the prevote round (TODO: unless the block is really big!)
  114. func TestStateEnterProposeYesPrivValidator(t *testing.T) {
  115. cs, _ := randConsensusState(1)
  116. height, round := cs.Height, cs.Round
  117. // Listen for propose timeout event
  118. timeoutCh := subscribe(cs.eventBus, types.EventQueryTimeoutPropose)
  119. proposalCh := subscribe(cs.eventBus, types.EventQueryCompleteProposal)
  120. cs.enterNewRound(height, round)
  121. cs.startRoutines(3)
  122. <-proposalCh
  123. // Check that Proposal, ProposalBlock, ProposalBlockParts are set.
  124. rs := cs.GetRoundState()
  125. if rs.Proposal == nil {
  126. t.Error("rs.Proposal should be set")
  127. }
  128. if rs.ProposalBlock == nil {
  129. t.Error("rs.ProposalBlock should be set")
  130. }
  131. if rs.ProposalBlockParts.Total() == 0 {
  132. t.Error("rs.ProposalBlockParts should be set")
  133. }
  134. // if we're a validator, enterPropose should not timeout
  135. ticker := time.NewTicker(ensureProposeTimeout(cs.config.TimeoutPropose))
  136. select {
  137. case <-timeoutCh:
  138. panic("Expected EnterPropose not to timeout")
  139. case <-ticker.C:
  140. }
  141. }
  142. func TestStateBadProposal(t *testing.T) {
  143. cs1, vss := randConsensusState(2)
  144. height, round := cs1.Height, cs1.Round
  145. vs2 := vss[1]
  146. partSize := cs1.state.ConsensusParams.BlockPartSizeBytes
  147. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  148. voteCh := subscribe(cs1.eventBus, types.EventQueryVote)
  149. propBlock, _ := cs1.createProposalBlock() //changeProposer(t, cs1, vs2)
  150. // make the second validator the proposer by incrementing round
  151. round = round + 1
  152. incrementRound(vss[1:]...)
  153. // make the block bad by tampering with statehash
  154. stateHash := propBlock.AppHash
  155. if len(stateHash) == 0 {
  156. stateHash = make([]byte, 32)
  157. }
  158. stateHash[0] = byte((stateHash[0] + 1) % 255)
  159. propBlock.AppHash = stateHash
  160. propBlockParts := propBlock.MakePartSet(partSize)
  161. proposal := types.NewProposal(vs2.Height, round, propBlockParts.Header(), -1, types.BlockID{})
  162. if err := vs2.SignProposal(config.ChainID(), proposal); err != nil {
  163. t.Fatal("failed to sign bad proposal", err)
  164. }
  165. // set the proposal block
  166. if err := cs1.SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil {
  167. t.Fatal(err)
  168. }
  169. // start the machine
  170. startTestRound(cs1, height, round)
  171. // wait for proposal
  172. <-proposalCh
  173. // wait for prevote
  174. <-voteCh
  175. validatePrevote(t, cs1, round, vss[0], nil)
  176. // add bad prevote from vs2 and wait for it
  177. signAddVotes(cs1, types.VoteTypePrevote, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
  178. <-voteCh
  179. // wait for precommit
  180. <-voteCh
  181. validatePrecommit(t, cs1, round, 0, vss[0], nil, nil)
  182. signAddVotes(cs1, types.VoteTypePrecommit, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
  183. }
  184. //----------------------------------------------------------------------------------------------------
  185. // FullRoundSuite
  186. // propose, prevote, and precommit a block
  187. func TestStateFullRound1(t *testing.T) {
  188. cs, vss := randConsensusState(1)
  189. height, round := cs.Height, cs.Round
  190. // NOTE: buffer capacity of 0 ensures we can validate prevote and last commit
  191. // before consensus can move to the next height (and cause a race condition)
  192. cs.eventBus.Stop()
  193. eventBus := types.NewEventBusWithBufferCapacity(0)
  194. eventBus.SetLogger(log.TestingLogger().With("module", "events"))
  195. cs.SetEventBus(eventBus)
  196. eventBus.Start()
  197. voteCh := subscribe(cs.eventBus, types.EventQueryVote)
  198. propCh := subscribe(cs.eventBus, types.EventQueryCompleteProposal)
  199. newRoundCh := subscribe(cs.eventBus, types.EventQueryNewRound)
  200. startTestRound(cs, height, round)
  201. <-newRoundCh
  202. // grab proposal
  203. re := <-propCh
  204. propBlockHash := re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState).ProposalBlock.Hash()
  205. <-voteCh // wait for prevote
  206. validatePrevote(t, cs, round, vss[0], propBlockHash)
  207. <-voteCh // wait for precommit
  208. // we're going to roll right into new height
  209. <-newRoundCh
  210. validateLastPrecommit(t, cs, vss[0], propBlockHash)
  211. }
  212. // nil is proposed, so prevote and precommit nil
  213. func TestStateFullRoundNil(t *testing.T) {
  214. cs, vss := randConsensusState(1)
  215. height, round := cs.Height, cs.Round
  216. voteCh := subscribe(cs.eventBus, types.EventQueryVote)
  217. cs.enterPrevote(height, round)
  218. cs.startRoutines(4)
  219. <-voteCh // prevote
  220. <-voteCh // precommit
  221. // should prevote and precommit nil
  222. validatePrevoteAndPrecommit(t, cs, round, 0, vss[0], nil, nil)
  223. }
  224. // run through propose, prevote, precommit commit with two validators
  225. // where the first validator has to wait for votes from the second
  226. func TestStateFullRound2(t *testing.T) {
  227. cs1, vss := randConsensusState(2)
  228. vs2 := vss[1]
  229. height, round := cs1.Height, cs1.Round
  230. voteCh := subscribe(cs1.eventBus, types.EventQueryVote)
  231. newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlock)
  232. // start round and wait for propose and prevote
  233. startTestRound(cs1, height, round)
  234. <-voteCh // prevote
  235. // we should be stuck in limbo waiting for more prevotes
  236. rs := cs1.GetRoundState()
  237. propBlockHash, propPartsHeader := rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header()
  238. // prevote arrives from vs2:
  239. signAddVotes(cs1, types.VoteTypePrevote, propBlockHash, propPartsHeader, vs2)
  240. <-voteCh
  241. <-voteCh //precommit
  242. // the proposed block should now be locked and our precommit added
  243. validatePrecommit(t, cs1, 0, 0, vss[0], propBlockHash, propBlockHash)
  244. // we should be stuck in limbo waiting for more precommits
  245. // precommit arrives from vs2:
  246. signAddVotes(cs1, types.VoteTypePrecommit, propBlockHash, propPartsHeader, vs2)
  247. <-voteCh
  248. // wait to finish commit, propose in next height
  249. <-newBlockCh
  250. }
  251. //------------------------------------------------------------------------------------------
  252. // LockSuite
  253. // two validators, 4 rounds.
  254. // two vals take turns proposing. val1 locks on first one, precommits nil on everything else
  255. func TestStateLockNoPOL(t *testing.T) {
  256. cs1, vss := randConsensusState(2)
  257. vs2 := vss[1]
  258. height := cs1.Height
  259. partSize := cs1.state.ConsensusParams.BlockPartSizeBytes
  260. timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
  261. timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
  262. voteCh := subscribe(cs1.eventBus, types.EventQueryVote)
  263. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  264. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  265. /*
  266. Round1 (cs1, B) // B B // B B2
  267. */
  268. // start round and wait for prevote
  269. cs1.enterNewRound(height, 0)
  270. cs1.startRoutines(0)
  271. re := <-proposalCh
  272. rs := re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  273. theBlockHash := rs.ProposalBlock.Hash()
  274. <-voteCh // prevote
  275. // we should now be stuck in limbo forever, waiting for more prevotes
  276. // prevote arrives from vs2:
  277. signAddVotes(cs1, types.VoteTypePrevote, cs1.ProposalBlock.Hash(), cs1.ProposalBlockParts.Header(), vs2)
  278. <-voteCh // prevote
  279. <-voteCh // precommit
  280. // the proposed block should now be locked and our precommit added
  281. validatePrecommit(t, cs1, 0, 0, vss[0], theBlockHash, theBlockHash)
  282. // we should now be stuck in limbo forever, waiting for more precommits
  283. // lets add one for a different block
  284. // NOTE: in practice we should never get to a point where there are precommits for different blocks at the same round
  285. hash := make([]byte, len(theBlockHash))
  286. copy(hash, theBlockHash)
  287. hash[0] = byte((hash[0] + 1) % 255)
  288. signAddVotes(cs1, types.VoteTypePrecommit, hash, rs.ProposalBlock.MakePartSet(partSize).Header(), vs2)
  289. <-voteCh // precommit
  290. // (note we're entering precommit for a second time this round)
  291. // but with invalid args. then we enterPrecommitWait, and the timeout to new round
  292. <-timeoutWaitCh
  293. ///
  294. <-newRoundCh
  295. t.Log("#### ONTO ROUND 1")
  296. /*
  297. Round2 (cs1, B) // B B2
  298. */
  299. incrementRound(vs2)
  300. // now we're on a new round and not the proposer, so wait for timeout
  301. re = <-timeoutProposeCh
  302. rs = re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  303. if rs.ProposalBlock != nil {
  304. panic("Expected proposal block to be nil")
  305. }
  306. // wait to finish prevote
  307. <-voteCh
  308. // we should have prevoted our locked block
  309. validatePrevote(t, cs1, 1, vss[0], rs.LockedBlock.Hash())
  310. // add a conflicting prevote from the other validator
  311. signAddVotes(cs1, types.VoteTypePrevote, hash, rs.ProposalBlock.MakePartSet(partSize).Header(), vs2)
  312. <-voteCh
  313. // now we're going to enter prevote again, but with invalid args
  314. // and then prevote wait, which should timeout. then wait for precommit
  315. <-timeoutWaitCh
  316. <-voteCh // precommit
  317. // the proposed block should still be locked and our precommit added
  318. // we should precommit nil and be locked on the proposal
  319. validatePrecommit(t, cs1, 1, 0, vss[0], nil, theBlockHash)
  320. // add conflicting precommit from vs2
  321. // NOTE: in practice we should never get to a point where there are precommits for different blocks at the same round
  322. signAddVotes(cs1, types.VoteTypePrecommit, hash, rs.ProposalBlock.MakePartSet(partSize).Header(), vs2)
  323. <-voteCh
  324. // (note we're entering precommit for a second time this round, but with invalid args
  325. // then we enterPrecommitWait and timeout into NewRound
  326. <-timeoutWaitCh
  327. <-newRoundCh
  328. t.Log("#### ONTO ROUND 2")
  329. /*
  330. Round3 (vs2, _) // B, B2
  331. */
  332. incrementRound(vs2)
  333. re = <-proposalCh
  334. rs = re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  335. // now we're on a new round and are the proposer
  336. if !bytes.Equal(rs.ProposalBlock.Hash(), rs.LockedBlock.Hash()) {
  337. panic(cmn.Fmt("Expected proposal block to be locked block. Got %v, Expected %v", rs.ProposalBlock, rs.LockedBlock))
  338. }
  339. <-voteCh // prevote
  340. validatePrevote(t, cs1, 2, vss[0], rs.LockedBlock.Hash())
  341. signAddVotes(cs1, types.VoteTypePrevote, hash, rs.ProposalBlock.MakePartSet(partSize).Header(), vs2)
  342. <-voteCh
  343. <-timeoutWaitCh // prevote wait
  344. <-voteCh // precommit
  345. validatePrecommit(t, cs1, 2, 0, vss[0], nil, theBlockHash) // precommit nil but be locked on proposal
  346. signAddVotes(cs1, types.VoteTypePrecommit, hash, rs.ProposalBlock.MakePartSet(partSize).Header(), vs2) // NOTE: conflicting precommits at same height
  347. <-voteCh
  348. <-timeoutWaitCh
  349. // before we time out into new round, set next proposal block
  350. prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1)
  351. if prop == nil || propBlock == nil {
  352. t.Fatal("Failed to create proposal block with vs2")
  353. }
  354. incrementRound(vs2)
  355. <-newRoundCh
  356. t.Log("#### ONTO ROUND 3")
  357. /*
  358. Round4 (vs2, C) // B C // B C
  359. */
  360. // now we're on a new round and not the proposer
  361. // so set the proposal block
  362. if err := cs1.SetProposalAndBlock(prop, propBlock, propBlock.MakePartSet(partSize), ""); err != nil {
  363. t.Fatal(err)
  364. }
  365. <-proposalCh
  366. <-voteCh // prevote
  367. // prevote for locked block (not proposal)
  368. validatePrevote(t, cs1, 0, vss[0], cs1.LockedBlock.Hash())
  369. signAddVotes(cs1, types.VoteTypePrevote, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2)
  370. <-voteCh
  371. <-timeoutWaitCh
  372. <-voteCh
  373. validatePrecommit(t, cs1, 2, 0, vss[0], nil, theBlockHash) // precommit nil but locked on proposal
  374. signAddVotes(cs1, types.VoteTypePrecommit, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2) // NOTE: conflicting precommits at same height
  375. <-voteCh
  376. }
  377. // 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka
  378. func TestStateLockPOLRelock(t *testing.T) {
  379. cs1, vss := randConsensusState(4)
  380. vs2, vs3, vs4 := vss[1], vss[2], vss[3]
  381. partSize := cs1.state.ConsensusParams.BlockPartSizeBytes
  382. timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
  383. timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
  384. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  385. voteCh := subscribe(cs1.eventBus, types.EventQueryVote)
  386. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  387. newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader)
  388. // everything done from perspective of cs1
  389. /*
  390. Round1 (cs1, B) // B B B B// B nil B nil
  391. eg. vs2 and vs4 didn't see the 2/3 prevotes
  392. */
  393. // start round and wait for propose and prevote
  394. startTestRound(cs1, cs1.Height, 0)
  395. <-newRoundCh
  396. re := <-proposalCh
  397. rs := re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  398. theBlockHash := rs.ProposalBlock.Hash()
  399. <-voteCh // prevote
  400. signAddVotes(cs1, types.VoteTypePrevote, cs1.ProposalBlock.Hash(), cs1.ProposalBlockParts.Header(), vs2, vs3, vs4)
  401. // prevotes
  402. discardFromChan(voteCh, 3)
  403. <-voteCh // our precommit
  404. // the proposed block should now be locked and our precommit added
  405. validatePrecommit(t, cs1, 0, 0, vss[0], theBlockHash, theBlockHash)
  406. // add precommits from the rest
  407. signAddVotes(cs1, types.VoteTypePrecommit, nil, types.PartSetHeader{}, vs2, vs4)
  408. signAddVotes(cs1, types.VoteTypePrecommit, cs1.ProposalBlock.Hash(), cs1.ProposalBlockParts.Header(), vs3)
  409. // precommites
  410. discardFromChan(voteCh, 3)
  411. // before we timeout to the new round set the new proposal
  412. prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1)
  413. propBlockParts := propBlock.MakePartSet(partSize)
  414. propBlockHash := propBlock.Hash()
  415. incrementRound(vs2, vs3, vs4)
  416. // timeout to new round
  417. <-timeoutWaitCh
  418. //XXX: this isnt guaranteed to get there before the timeoutPropose ...
  419. if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil {
  420. t.Fatal(err)
  421. }
  422. <-newRoundCh
  423. t.Log("### ONTO ROUND 1")
  424. /*
  425. Round2 (vs2, C) // B C C C // C C C _)
  426. cs1 changes lock!
  427. */
  428. // now we're on a new round and not the proposer
  429. // but we should receive the proposal
  430. select {
  431. case <-proposalCh:
  432. case <-timeoutProposeCh:
  433. <-proposalCh
  434. }
  435. // go to prevote, prevote for locked block (not proposal), move on
  436. <-voteCh
  437. validatePrevote(t, cs1, 0, vss[0], theBlockHash)
  438. // now lets add prevotes from everyone else for the new block
  439. signAddVotes(cs1, types.VoteTypePrevote, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
  440. // prevotes
  441. discardFromChan(voteCh, 3)
  442. // now either we go to PrevoteWait or Precommit
  443. select {
  444. case <-timeoutWaitCh: // we're in PrevoteWait, go to Precommit
  445. // XXX: there's no guarantee we see the polka, this might be a precommit for nil,
  446. // in which case the test fails!
  447. <-voteCh
  448. case <-voteCh: // we went straight to Precommit
  449. }
  450. // we should have unlocked and locked on the new block
  451. validatePrecommit(t, cs1, 1, 1, vss[0], propBlockHash, propBlockHash)
  452. signAddVotes(cs1, types.VoteTypePrecommit, propBlockHash, propBlockParts.Header(), vs2, vs3)
  453. discardFromChan(voteCh, 2)
  454. be := <-newBlockCh
  455. b := be.(types.TMEventData).Unwrap().(types.EventDataNewBlockHeader)
  456. re = <-newRoundCh
  457. rs = re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  458. if rs.Height != 2 {
  459. panic("Expected height to increment")
  460. }
  461. if !bytes.Equal(b.Header.Hash(), propBlockHash) {
  462. panic("Expected new block to be proposal block")
  463. }
  464. }
  465. // 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka
  466. func TestStateLockPOLUnlock(t *testing.T) {
  467. cs1, vss := randConsensusState(4)
  468. vs2, vs3, vs4 := vss[1], vss[2], vss[3]
  469. partSize := cs1.state.ConsensusParams.BlockPartSizeBytes
  470. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  471. timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
  472. timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
  473. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  474. unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock)
  475. voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress())
  476. // everything done from perspective of cs1
  477. /*
  478. Round1 (cs1, B) // B B B B // B nil B nil
  479. eg. didn't see the 2/3 prevotes
  480. */
  481. // start round and wait for propose and prevote
  482. startTestRound(cs1, cs1.Height, 0)
  483. <-newRoundCh
  484. re := <-proposalCh
  485. rs := re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  486. theBlockHash := rs.ProposalBlock.Hash()
  487. <-voteCh // prevote
  488. signAddVotes(cs1, types.VoteTypePrevote, cs1.ProposalBlock.Hash(), cs1.ProposalBlockParts.Header(), vs2, vs3, vs4)
  489. <-voteCh //precommit
  490. // the proposed block should now be locked and our precommit added
  491. validatePrecommit(t, cs1, 0, 0, vss[0], theBlockHash, theBlockHash)
  492. rs = cs1.GetRoundState()
  493. // add precommits from the rest
  494. signAddVotes(cs1, types.VoteTypePrecommit, nil, types.PartSetHeader{}, vs2, vs4)
  495. signAddVotes(cs1, types.VoteTypePrecommit, cs1.ProposalBlock.Hash(), cs1.ProposalBlockParts.Header(), vs3)
  496. // before we time out into new round, set next proposal block
  497. prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1)
  498. propBlockParts := propBlock.MakePartSet(partSize)
  499. incrementRound(vs2, vs3, vs4)
  500. // timeout to new round
  501. re = <-timeoutWaitCh
  502. rs = re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  503. lockedBlockHash := rs.LockedBlock.Hash()
  504. //XXX: this isnt guaranteed to get there before the timeoutPropose ...
  505. if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil {
  506. t.Fatal(err)
  507. }
  508. <-newRoundCh
  509. t.Log("#### ONTO ROUND 1")
  510. /*
  511. Round2 (vs2, C) // B nil nil nil // nil nil nil _
  512. cs1 unlocks!
  513. */
  514. // now we're on a new round and not the proposer,
  515. // but we should receive the proposal
  516. select {
  517. case <-proposalCh:
  518. case <-timeoutProposeCh:
  519. <-proposalCh
  520. }
  521. // go to prevote, prevote for locked block (not proposal)
  522. <-voteCh
  523. validatePrevote(t, cs1, 0, vss[0], lockedBlockHash)
  524. // now lets add prevotes from everyone else for nil (a polka!)
  525. signAddVotes(cs1, types.VoteTypePrevote, nil, types.PartSetHeader{}, vs2, vs3, vs4)
  526. // the polka makes us unlock and precommit nil
  527. <-unlockCh
  528. <-voteCh // precommit
  529. // we should have unlocked and committed nil
  530. // NOTE: since we don't relock on nil, the lock round is 0
  531. validatePrecommit(t, cs1, 1, 0, vss[0], nil, nil)
  532. signAddVotes(cs1, types.VoteTypePrecommit, nil, types.PartSetHeader{}, vs2, vs3)
  533. <-newRoundCh
  534. }
  535. // 4 vals
  536. // a polka at round 1 but we miss it
  537. // then a polka at round 2 that we lock on
  538. // then we see the polka from round 1 but shouldn't unlock
  539. func TestStateLockPOLSafety1(t *testing.T) {
  540. cs1, vss := randConsensusState(4)
  541. vs2, vs3, vs4 := vss[1], vss[2], vss[3]
  542. partSize := cs1.state.ConsensusParams.BlockPartSizeBytes
  543. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  544. timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
  545. timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
  546. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  547. voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress())
  548. // start round and wait for propose and prevote
  549. startTestRound(cs1, cs1.Height, 0)
  550. <-newRoundCh
  551. re := <-proposalCh
  552. rs := re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  553. propBlock := rs.ProposalBlock
  554. <-voteCh // prevote
  555. validatePrevote(t, cs1, 0, vss[0], propBlock.Hash())
  556. // the others sign a polka but we don't see it
  557. prevotes := signVotes(types.VoteTypePrevote, propBlock.Hash(), propBlock.MakePartSet(partSize).Header(), vs2, vs3, vs4)
  558. // before we time out into new round, set next proposer
  559. // and next proposal block
  560. /*
  561. _, v1 := cs1.Validators.GetByAddress(vss[0].Address)
  562. v1.VotingPower = 1
  563. if updated := cs1.Validators.Update(v1); !updated {
  564. panic("failed to update validator")
  565. }*/
  566. t.Logf("old prop hash %v", fmt.Sprintf("%X", propBlock.Hash()))
  567. // we do see them precommit nil
  568. signAddVotes(cs1, types.VoteTypePrecommit, nil, types.PartSetHeader{}, vs2, vs3, vs4)
  569. prop, propBlock := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1)
  570. propBlockHash := propBlock.Hash()
  571. propBlockParts := propBlock.MakePartSet(partSize)
  572. incrementRound(vs2, vs3, vs4)
  573. //XXX: this isnt guaranteed to get there before the timeoutPropose ...
  574. if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil {
  575. t.Fatal(err)
  576. }
  577. <-newRoundCh
  578. t.Log("### ONTO ROUND 1")
  579. /*Round2
  580. // we timeout and prevote our lock
  581. // a polka happened but we didn't see it!
  582. */
  583. // now we're on a new round and not the proposer,
  584. // but we should receive the proposal
  585. select {
  586. case re = <-proposalCh:
  587. case <-timeoutProposeCh:
  588. re = <-proposalCh
  589. }
  590. rs = re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  591. if rs.LockedBlock != nil {
  592. panic("we should not be locked!")
  593. }
  594. t.Logf("new prop hash %v", fmt.Sprintf("%X", propBlockHash))
  595. // go to prevote, prevote for proposal block
  596. <-voteCh
  597. validatePrevote(t, cs1, 1, vss[0], propBlockHash)
  598. // now we see the others prevote for it, so we should lock on it
  599. signAddVotes(cs1, types.VoteTypePrevote, propBlockHash, propBlockParts.Header(), vs2, vs3, vs4)
  600. <-voteCh // precommit
  601. // we should have precommitted
  602. validatePrecommit(t, cs1, 1, 1, vss[0], propBlockHash, propBlockHash)
  603. signAddVotes(cs1, types.VoteTypePrecommit, nil, types.PartSetHeader{}, vs2, vs3)
  604. <-timeoutWaitCh
  605. incrementRound(vs2, vs3, vs4)
  606. <-newRoundCh
  607. t.Log("### ONTO ROUND 2")
  608. /*Round3
  609. we see the polka from round 1 but we shouldn't unlock!
  610. */
  611. // timeout of propose
  612. <-timeoutProposeCh
  613. // finish prevote
  614. <-voteCh
  615. // we should prevote what we're locked on
  616. validatePrevote(t, cs1, 2, vss[0], propBlockHash)
  617. newStepCh := subscribe(cs1.eventBus, types.EventQueryNewRoundStep)
  618. // add prevotes from the earlier round
  619. addVotes(cs1, prevotes...)
  620. t.Log("Done adding prevotes!")
  621. ensureNoNewStep(newStepCh)
  622. }
  623. // 4 vals.
  624. // polka P0 at R0, P1 at R1, and P2 at R2,
  625. // we lock on P0 at R0, don't see P1, and unlock using P2 at R2
  626. // then we should make sure we don't lock using P1
  627. // What we want:
  628. // dont see P0, lock on P1 at R1, dont unlock using P0 at R2
  629. func TestStateLockPOLSafety2(t *testing.T) {
  630. cs1, vss := randConsensusState(4)
  631. vs2, vs3, vs4 := vss[1], vss[2], vss[3]
  632. partSize := cs1.state.ConsensusParams.BlockPartSizeBytes
  633. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  634. timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose)
  635. timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
  636. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  637. unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock)
  638. voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress())
  639. // the block for R0: gets polkad but we miss it
  640. // (even though we signed it, shhh)
  641. _, propBlock0 := decideProposal(cs1, vss[0], cs1.Height, cs1.Round)
  642. propBlockHash0 := propBlock0.Hash()
  643. propBlockParts0 := propBlock0.MakePartSet(partSize)
  644. // the others sign a polka but we don't see it
  645. prevotes := signVotes(types.VoteTypePrevote, propBlockHash0, propBlockParts0.Header(), vs2, vs3, vs4)
  646. // the block for round 1
  647. prop1, propBlock1 := decideProposal(cs1, vs2, vs2.Height, vs2.Round+1)
  648. propBlockHash1 := propBlock1.Hash()
  649. propBlockParts1 := propBlock1.MakePartSet(partSize)
  650. propBlockID1 := types.BlockID{propBlockHash1, propBlockParts1.Header()}
  651. incrementRound(vs2, vs3, vs4)
  652. cs1.updateRoundStep(0, cstypes.RoundStepPrecommitWait)
  653. t.Log("### ONTO Round 1")
  654. // jump in at round 1
  655. height := cs1.Height
  656. startTestRound(cs1, height, 1)
  657. <-newRoundCh
  658. if err := cs1.SetProposalAndBlock(prop1, propBlock1, propBlockParts1, "some peer"); err != nil {
  659. t.Fatal(err)
  660. }
  661. <-proposalCh
  662. <-voteCh // prevote
  663. signAddVotes(cs1, types.VoteTypePrevote, propBlockHash1, propBlockParts1.Header(), vs2, vs3, vs4)
  664. <-voteCh // precommit
  665. // the proposed block should now be locked and our precommit added
  666. validatePrecommit(t, cs1, 1, 1, vss[0], propBlockHash1, propBlockHash1)
  667. // add precommits from the rest
  668. signAddVotes(cs1, types.VoteTypePrecommit, nil, types.PartSetHeader{}, vs2, vs4)
  669. signAddVotes(cs1, types.VoteTypePrecommit, propBlockHash1, propBlockParts1.Header(), vs3)
  670. incrementRound(vs2, vs3, vs4)
  671. // timeout of precommit wait to new round
  672. <-timeoutWaitCh
  673. // in round 2 we see the polkad block from round 0
  674. newProp := types.NewProposal(height, 2, propBlockParts0.Header(), 0, propBlockID1)
  675. if err := vs3.SignProposal(config.ChainID(), newProp); err != nil {
  676. t.Fatal(err)
  677. }
  678. if err := cs1.SetProposalAndBlock(newProp, propBlock0, propBlockParts0, "some peer"); err != nil {
  679. t.Fatal(err)
  680. }
  681. // Add the pol votes
  682. addVotes(cs1, prevotes...)
  683. <-newRoundCh
  684. t.Log("### ONTO Round 2")
  685. /*Round2
  686. // now we see the polka from round 1, but we shouldnt unlock
  687. */
  688. select {
  689. case <-timeoutProposeCh:
  690. <-proposalCh
  691. case <-proposalCh:
  692. }
  693. select {
  694. case <-unlockCh:
  695. panic("validator unlocked using an old polka")
  696. case <-voteCh:
  697. // prevote our locked block
  698. }
  699. validatePrevote(t, cs1, 2, vss[0], propBlockHash1)
  700. }
  701. //------------------------------------------------------------------------------------------
  702. // SlashingSuite
  703. // TODO: Slashing
  704. /*
  705. func TestStateSlashingPrevotes(t *testing.T) {
  706. cs1, vss := randConsensusState(2)
  707. vs2 := vss[1]
  708. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  709. timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
  710. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  711. voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress())
  712. // start round and wait for propose and prevote
  713. startTestRound(cs1, cs1.Height, 0)
  714. <-newRoundCh
  715. re := <-proposalCh
  716. <-voteCh // prevote
  717. rs := re.(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  718. // we should now be stuck in limbo forever, waiting for more prevotes
  719. // add one for a different block should cause us to go into prevote wait
  720. hash := rs.ProposalBlock.Hash()
  721. hash[0] = byte(hash[0]+1) % 255
  722. signAddVotes(cs1, types.VoteTypePrevote, hash, rs.ProposalBlockParts.Header(), vs2)
  723. <-timeoutWaitCh
  724. // NOTE: we have to send the vote for different block first so we don't just go into precommit round right
  725. // away and ignore more prevotes (and thus fail to slash!)
  726. // add the conflicting vote
  727. signAddVotes(cs1, types.VoteTypePrevote, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vs2)
  728. // XXX: Check for existence of Dupeout info
  729. }
  730. func TestStateSlashingPrecommits(t *testing.T) {
  731. cs1, vss := randConsensusState(2)
  732. vs2 := vss[1]
  733. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  734. timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
  735. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  736. voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress())
  737. // start round and wait for propose and prevote
  738. startTestRound(cs1, cs1.Height, 0)
  739. <-newRoundCh
  740. re := <-proposalCh
  741. <-voteCh // prevote
  742. // add prevote from vs2
  743. signAddVotes(cs1, types.VoteTypePrevote, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vs2)
  744. <-voteCh // precommit
  745. // we should now be stuck in limbo forever, waiting for more prevotes
  746. // add one for a different block should cause us to go into prevote wait
  747. hash := rs.ProposalBlock.Hash()
  748. hash[0] = byte(hash[0]+1) % 255
  749. signAddVotes(cs1, types.VoteTypePrecommit, hash, rs.ProposalBlockParts.Header(), vs2)
  750. // NOTE: we have to send the vote for different block first so we don't just go into precommit round right
  751. // away and ignore more prevotes (and thus fail to slash!)
  752. // add precommit from vs2
  753. signAddVotes(cs1, types.VoteTypePrecommit, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vs2)
  754. // XXX: Check for existence of Dupeout info
  755. }
  756. */
  757. //------------------------------------------------------------------------------------------
  758. // CatchupSuite
  759. //------------------------------------------------------------------------------------------
  760. // HaltSuite
  761. // 4 vals.
  762. // we receive a final precommit after going into next round, but others might have gone to commit already!
  763. func TestStateHalt1(t *testing.T) {
  764. cs1, vss := randConsensusState(4)
  765. vs2, vs3, vs4 := vss[1], vss[2], vss[3]
  766. partSize := cs1.state.ConsensusParams.BlockPartSizeBytes
  767. proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal)
  768. timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait)
  769. newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound)
  770. newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlock)
  771. voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress())
  772. // start round and wait for propose and prevote
  773. startTestRound(cs1, cs1.Height, 0)
  774. <-newRoundCh
  775. re := <-proposalCh
  776. rs := re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  777. propBlock := rs.ProposalBlock
  778. propBlockParts := propBlock.MakePartSet(partSize)
  779. <-voteCh // prevote
  780. signAddVotes(cs1, types.VoteTypePrevote, propBlock.Hash(), propBlockParts.Header(), vs3, vs4)
  781. <-voteCh // precommit
  782. // the proposed block should now be locked and our precommit added
  783. validatePrecommit(t, cs1, 0, 0, vss[0], propBlock.Hash(), propBlock.Hash())
  784. // add precommits from the rest
  785. signAddVotes(cs1, types.VoteTypePrecommit, nil, types.PartSetHeader{}, vs2) // didnt receive proposal
  786. signAddVotes(cs1, types.VoteTypePrecommit, propBlock.Hash(), propBlockParts.Header(), vs3)
  787. // we receive this later, but vs3 might receive it earlier and with ours will go to commit!
  788. precommit4 := signVote(vs4, types.VoteTypePrecommit, propBlock.Hash(), propBlockParts.Header())
  789. incrementRound(vs2, vs3, vs4)
  790. // timeout to new round
  791. <-timeoutWaitCh
  792. re = <-newRoundCh
  793. rs = re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  794. t.Log("### ONTO ROUND 1")
  795. /*Round2
  796. // we timeout and prevote our lock
  797. // a polka happened but we didn't see it!
  798. */
  799. // go to prevote, prevote for locked block
  800. <-voteCh // prevote
  801. validatePrevote(t, cs1, 0, vss[0], rs.LockedBlock.Hash())
  802. // now we receive the precommit from the previous round
  803. addVotes(cs1, precommit4)
  804. // receiving that precommit should take us straight to commit
  805. <-newBlockCh
  806. re = <-newRoundCh
  807. rs = re.(types.TMEventData).Unwrap().(types.EventDataRoundState).RoundState.(*cstypes.RoundState)
  808. if rs.Height != 2 {
  809. panic("expected height to increment")
  810. }
  811. }
  812. // subscribe subscribes test client to the given query and returns a channel with cap = 1.
  813. func subscribe(eventBus *types.EventBus, q tmpubsub.Query) <-chan interface{} {
  814. out := make(chan interface{}, 1)
  815. err := eventBus.Subscribe(context.Background(), testSubscriber, q, out)
  816. if err != nil {
  817. panic(fmt.Sprintf("failed to subscribe %s to %v", testSubscriber, q))
  818. }
  819. return out
  820. }
  821. // discardFromChan reads n values from the channel.
  822. func discardFromChan(ch <-chan interface{}, n int) {
  823. for i := 0; i < n; i++ {
  824. <-ch
  825. }
  826. }