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.

471 lines
15 KiB

state: add more tests for block validation (#3674) * Expose priv validators for use in testing * Generalize block header validation test past height 1 * Remove ineffectual assignment * Remove redundant SaveState call * Reorder comment for clarity * Use the block executor ApplyBlock function instead of implementing a stripped-down version of it * Remove commented-out code * Remove unnecessary test The required tests already appear to be implemented (implicitly) through the TestValidateBlockHeader test. * Allow for catching of specific error types during TestValidateBlockCommit * Make return error testable * Clean up and add TestValidateBlockCommit code * Fix formatting * Extract function to create a new mock test app * Update comment for clarity * Fix comment * Add skeleton code for evidence-related test * Allow for addressing priv val by address * Generalize test beyond a single validator * Generalize TestValidateBlockEvidence past first height * Reorder code to clearly separate tests and utility code * Use a common constant for stop height for testing in state/validation_test.go * Refactor errors to resemble existing conventions * Fix formatting * Extract common helper functions Having the tests littered with helper functions makes them less easily readable imho, so I've pulled them out into a separate file. This also makes it easier to see what helper functions are available during testing, so we minimize the chance of duplication when writing new tests. * Remove unused parameter * Remove unused parameters * Add field keys * Remove unused height constant * Fix typo * Fix incorrect return error * Add field keys * Use separate package for tests This refactors all of the state package's tests into a state_test package, so as to keep any usage of the state package's internal methods explicit. Any internal methods/constants used by tests are now explicitly exported in state/export_test.go * Refactor: extract helper function to make, validate, execute and commit a block * Rename state function to makeState * Remove redundant constant for number of validators * Refactor mock evidence registration into TestMain * Remove extraneous nVals variable * Replace function-level TODOs with file-level TODO and explanation * Remove extraneous comment * Fix linting issues brought up by GolangCI (pulled in from latest merge from develop)
5 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
internal/proxy: add initial set of abci metrics (#7115) This PR adds an initial set of metrics for use ABCI. The initial metrics enable the calculation of timing histograms and call counts for each of the ABCI methods. The metrics are also labeled as either 'sync' or 'async' to determine if the method call was performed using ABCI's `*Async` methods. An example of these metrics is included here for reference: ``` tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0001"} 0 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0004"} 5 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.002"} 12 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.009"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.02"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.1"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.65"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="2"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="6"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="25"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="+Inf"} 13 tendermint_abci_connection_method_timing_sum{chain_id="ci",method="commit",type="sync"} 0.007802058000000001 tendermint_abci_connection_method_timing_count{chain_id="ci",method="commit",type="sync"} 13 ``` These metrics can easily be graphed using prometheus's `histogram_quantile(...)` method to pick out a particular quantile to graph or examine. I chose buckets that were somewhat of an estimate of expected range of times for ABCI operations. They start at .0001 seconds and range to 25 seconds. The hope is that this range captures enough possible times to be useful for us and operators.
3 years ago
state: add more tests for block validation (#3674) * Expose priv validators for use in testing * Generalize block header validation test past height 1 * Remove ineffectual assignment * Remove redundant SaveState call * Reorder comment for clarity * Use the block executor ApplyBlock function instead of implementing a stripped-down version of it * Remove commented-out code * Remove unnecessary test The required tests already appear to be implemented (implicitly) through the TestValidateBlockHeader test. * Allow for catching of specific error types during TestValidateBlockCommit * Make return error testable * Clean up and add TestValidateBlockCommit code * Fix formatting * Extract function to create a new mock test app * Update comment for clarity * Fix comment * Add skeleton code for evidence-related test * Allow for addressing priv val by address * Generalize test beyond a single validator * Generalize TestValidateBlockEvidence past first height * Reorder code to clearly separate tests and utility code * Use a common constant for stop height for testing in state/validation_test.go * Refactor errors to resemble existing conventions * Fix formatting * Extract common helper functions Having the tests littered with helper functions makes them less easily readable imho, so I've pulled them out into a separate file. This also makes it easier to see what helper functions are available during testing, so we minimize the chance of duplication when writing new tests. * Remove unused parameter * Remove unused parameters * Add field keys * Remove unused height constant * Fix typo * Fix incorrect return error * Add field keys * Use separate package for tests This refactors all of the state package's tests into a state_test package, so as to keep any usage of the state package's internal methods explicit. Any internal methods/constants used by tests are now explicitly exported in state/export_test.go * Refactor: extract helper function to make, validate, execute and commit a block * Rename state function to makeState * Remove redundant constant for number of validators * Refactor mock evidence registration into TestMain * Remove extraneous nVals variable * Replace function-level TODOs with file-level TODO and explanation * Remove extraneous comment * Fix linting issues brought up by GolangCI (pulled in from latest merge from develop)
5 years ago
internal/proxy: add initial set of abci metrics (#7115) This PR adds an initial set of metrics for use ABCI. The initial metrics enable the calculation of timing histograms and call counts for each of the ABCI methods. The metrics are also labeled as either 'sync' or 'async' to determine if the method call was performed using ABCI's `*Async` methods. An example of these metrics is included here for reference: ``` tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0001"} 0 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0004"} 5 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.002"} 12 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.009"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.02"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.1"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.65"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="2"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="6"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="25"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="+Inf"} 13 tendermint_abci_connection_method_timing_sum{chain_id="ci",method="commit",type="sync"} 0.007802058000000001 tendermint_abci_connection_method_timing_count{chain_id="ci",method="commit",type="sync"} 13 ``` These metrics can easily be graphed using prometheus's `histogram_quantile(...)` method to pick out a particular quantile to graph or examine. I chose buckets that were somewhat of an estimate of expected range of times for ABCI operations. They start at .0001 seconds and range to 25 seconds. The hope is that this range captures enough possible times to be useful for us and operators.
3 years ago
state: add more tests for block validation (#3674) * Expose priv validators for use in testing * Generalize block header validation test past height 1 * Remove ineffectual assignment * Remove redundant SaveState call * Reorder comment for clarity * Use the block executor ApplyBlock function instead of implementing a stripped-down version of it * Remove commented-out code * Remove unnecessary test The required tests already appear to be implemented (implicitly) through the TestValidateBlockHeader test. * Allow for catching of specific error types during TestValidateBlockCommit * Make return error testable * Clean up and add TestValidateBlockCommit code * Fix formatting * Extract function to create a new mock test app * Update comment for clarity * Fix comment * Add skeleton code for evidence-related test * Allow for addressing priv val by address * Generalize test beyond a single validator * Generalize TestValidateBlockEvidence past first height * Reorder code to clearly separate tests and utility code * Use a common constant for stop height for testing in state/validation_test.go * Refactor errors to resemble existing conventions * Fix formatting * Extract common helper functions Having the tests littered with helper functions makes them less easily readable imho, so I've pulled them out into a separate file. This also makes it easier to see what helper functions are available during testing, so we minimize the chance of duplication when writing new tests. * Remove unused parameter * Remove unused parameters * Add field keys * Remove unused height constant * Fix typo * Fix incorrect return error * Add field keys * Use separate package for tests This refactors all of the state package's tests into a state_test package, so as to keep any usage of the state package's internal methods explicit. Any internal methods/constants used by tests are now explicitly exported in state/export_test.go * Refactor: extract helper function to make, validate, execute and commit a block * Rename state function to makeState * Remove redundant constant for number of validators * Refactor mock evidence registration into TestMain * Remove extraneous nVals variable * Replace function-level TODOs with file-level TODO and explanation * Remove extraneous comment * Fix linting issues brought up by GolangCI (pulled in from latest merge from develop)
5 years ago
internal/proxy: add initial set of abci metrics (#7115) This PR adds an initial set of metrics for use ABCI. The initial metrics enable the calculation of timing histograms and call counts for each of the ABCI methods. The metrics are also labeled as either 'sync' or 'async' to determine if the method call was performed using ABCI's `*Async` methods. An example of these metrics is included here for reference: ``` tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0001"} 0 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0004"} 5 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.002"} 12 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.009"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.02"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.1"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.65"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="2"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="6"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="25"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="+Inf"} 13 tendermint_abci_connection_method_timing_sum{chain_id="ci",method="commit",type="sync"} 0.007802058000000001 tendermint_abci_connection_method_timing_count{chain_id="ci",method="commit",type="sync"} 13 ``` These metrics can easily be graphed using prometheus's `histogram_quantile(...)` method to pick out a particular quantile to graph or examine. I chose buckets that were somewhat of an estimate of expected range of times for ABCI operations. They start at .0001 seconds and range to 25 seconds. The hope is that this range captures enough possible times to be useful for us and operators.
3 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
state: add more tests for block validation (#3674) * Expose priv validators for use in testing * Generalize block header validation test past height 1 * Remove ineffectual assignment * Remove redundant SaveState call * Reorder comment for clarity * Use the block executor ApplyBlock function instead of implementing a stripped-down version of it * Remove commented-out code * Remove unnecessary test The required tests already appear to be implemented (implicitly) through the TestValidateBlockHeader test. * Allow for catching of specific error types during TestValidateBlockCommit * Make return error testable * Clean up and add TestValidateBlockCommit code * Fix formatting * Extract function to create a new mock test app * Update comment for clarity * Fix comment * Add skeleton code for evidence-related test * Allow for addressing priv val by address * Generalize test beyond a single validator * Generalize TestValidateBlockEvidence past first height * Reorder code to clearly separate tests and utility code * Use a common constant for stop height for testing in state/validation_test.go * Refactor errors to resemble existing conventions * Fix formatting * Extract common helper functions Having the tests littered with helper functions makes them less easily readable imho, so I've pulled them out into a separate file. This also makes it easier to see what helper functions are available during testing, so we minimize the chance of duplication when writing new tests. * Remove unused parameter * Remove unused parameters * Add field keys * Remove unused height constant * Fix typo * Fix incorrect return error * Add field keys * Use separate package for tests This refactors all of the state package's tests into a state_test package, so as to keep any usage of the state package's internal methods explicit. Any internal methods/constants used by tests are now explicitly exported in state/export_test.go * Refactor: extract helper function to make, validate, execute and commit a block * Rename state function to makeState * Remove redundant constant for number of validators * Refactor mock evidence registration into TestMain * Remove extraneous nVals variable * Replace function-level TODOs with file-level TODO and explanation * Remove extraneous comment * Fix linting issues brought up by GolangCI (pulled in from latest merge from develop)
5 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
internal/proxy: add initial set of abci metrics (#7115) This PR adds an initial set of metrics for use ABCI. The initial metrics enable the calculation of timing histograms and call counts for each of the ABCI methods. The metrics are also labeled as either 'sync' or 'async' to determine if the method call was performed using ABCI's `*Async` methods. An example of these metrics is included here for reference: ``` tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0001"} 0 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0004"} 5 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.002"} 12 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.009"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.02"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.1"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.65"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="2"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="6"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="25"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="+Inf"} 13 tendermint_abci_connection_method_timing_sum{chain_id="ci",method="commit",type="sync"} 0.007802058000000001 tendermint_abci_connection_method_timing_count{chain_id="ci",method="commit",type="sync"} 13 ``` These metrics can easily be graphed using prometheus's `histogram_quantile(...)` method to pick out a particular quantile to graph or examine. I chose buckets that were somewhat of an estimate of expected range of times for ABCI operations. They start at .0001 seconds and range to 25 seconds. The hope is that this range captures enough possible times to be useful for us and operators.
3 years ago
state: add more tests for block validation (#3674) * Expose priv validators for use in testing * Generalize block header validation test past height 1 * Remove ineffectual assignment * Remove redundant SaveState call * Reorder comment for clarity * Use the block executor ApplyBlock function instead of implementing a stripped-down version of it * Remove commented-out code * Remove unnecessary test The required tests already appear to be implemented (implicitly) through the TestValidateBlockHeader test. * Allow for catching of specific error types during TestValidateBlockCommit * Make return error testable * Clean up and add TestValidateBlockCommit code * Fix formatting * Extract function to create a new mock test app * Update comment for clarity * Fix comment * Add skeleton code for evidence-related test * Allow for addressing priv val by address * Generalize test beyond a single validator * Generalize TestValidateBlockEvidence past first height * Reorder code to clearly separate tests and utility code * Use a common constant for stop height for testing in state/validation_test.go * Refactor errors to resemble existing conventions * Fix formatting * Extract common helper functions Having the tests littered with helper functions makes them less easily readable imho, so I've pulled them out into a separate file. This also makes it easier to see what helper functions are available during testing, so we minimize the chance of duplication when writing new tests. * Remove unused parameter * Remove unused parameters * Add field keys * Remove unused height constant * Fix typo * Fix incorrect return error * Add field keys * Use separate package for tests This refactors all of the state package's tests into a state_test package, so as to keep any usage of the state package's internal methods explicit. Any internal methods/constants used by tests are now explicitly exported in state/export_test.go * Refactor: extract helper function to make, validate, execute and commit a block * Rename state function to makeState * Remove redundant constant for number of validators * Refactor mock evidence registration into TestMain * Remove extraneous nVals variable * Replace function-level TODOs with file-level TODO and explanation * Remove extraneous comment * Fix linting issues brought up by GolangCI (pulled in from latest merge from develop)
5 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
6 years ago
pubsub 2.0 (#3227) * green pubsub tests :OK: * get rid of clientToQueryMap * Subscribe and SubscribeUnbuffered * start adapting other pkgs to new pubsub * nope * rename MsgAndTags to Message * remove TagMap it does not bring any additional benefits * bring back EventSubscriber * fix test * fix data race in TestStartNextHeightCorrectly ``` Write at 0x00c0001c7418 by goroutine 796: github.com/tendermint/tendermint/consensus.TestStartNextHeightCorrectly() /go/src/github.com/tendermint/tendermint/consensus/state_test.go:1296 +0xad testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 Previous read at 0x00c0001c7418 by goroutine 858: github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote() /go/src/github.com/tendermint/tendermint/consensus/state.go:1631 +0x1366 github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote() /go/src/github.com/tendermint/tendermint/consensus/state.go:1476 +0x8f github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg() /go/src/github.com/tendermint/tendermint/consensus/state.go:667 +0xa1e github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine() /go/src/github.com/tendermint/tendermint/consensus/state.go:628 +0x794 Goroutine 796 (running) created at: testing.(*T).Run() /usr/local/go/src/testing/testing.go:878 +0x659 testing.runTests.func1() /usr/local/go/src/testing/testing.go:1119 +0xa8 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 testing.runTests() /usr/local/go/src/testing/testing.go:1117 +0x4ee testing.(*M).Run() /usr/local/go/src/testing/testing.go:1034 +0x2ee main.main() _testmain.go:214 +0x332 Goroutine 858 (running) created at: github.com/tendermint/tendermint/consensus.(*ConsensusState).startRoutines() /go/src/github.com/tendermint/tendermint/consensus/state.go:334 +0x221 github.com/tendermint/tendermint/consensus.startTestRound() /go/src/github.com/tendermint/tendermint/consensus/common_test.go:122 +0x63 github.com/tendermint/tendermint/consensus.TestStateFullRound1() /go/src/github.com/tendermint/tendermint/consensus/state_test.go:255 +0x397 testing.tRunner() /usr/local/go/src/testing/testing.go:827 +0x162 ``` * fixes after my own review * fix formatting * wait 100ms before kicking a subscriber out + a test for indexer_service * fixes after my second review * no timeout * add changelog entries * fix merge conflicts * fix typos after Thane's review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * reformat code * rewrite indexer service in the attempt to fix failing test https://github.com/tendermint/tendermint/pull/3227/#issuecomment-462316527 * Revert "rewrite indexer service in the attempt to fix failing test" This reverts commit 0d9107a098230de7138abb1c201877c246e89ed1. * another attempt to fix indexer * fixes after Ethan's review * use unbuffered channel when indexing transactions Refs https://github.com/tendermint/tendermint/pull/3227#discussion_r258786716 * add a comment for EventBus#SubscribeUnbuffered * format code
5 years ago
internal/proxy: add initial set of abci metrics (#7115) This PR adds an initial set of metrics for use ABCI. The initial metrics enable the calculation of timing histograms and call counts for each of the ABCI methods. The metrics are also labeled as either 'sync' or 'async' to determine if the method call was performed using ABCI's `*Async` methods. An example of these metrics is included here for reference: ``` tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0001"} 0 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.0004"} 5 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.002"} 12 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.009"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.02"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.1"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="0.65"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="2"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="6"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="25"} 13 tendermint_abci_connection_method_timing_bucket{chain_id="ci",method="commit",type="sync",le="+Inf"} 13 tendermint_abci_connection_method_timing_sum{chain_id="ci",method="commit",type="sync"} 0.007802058000000001 tendermint_abci_connection_method_timing_count{chain_id="ci",method="commit",type="sync"} 13 ``` These metrics can easily be graphed using prometheus's `histogram_quantile(...)` method to pick out a particular quantile to graph or examine. I chose buckets that were somewhat of an estimate of expected range of times for ABCI operations. They start at .0001 seconds and range to 25 seconds. The hope is that this range captures enough possible times to be useful for us and operators.
3 years ago
state: add more tests for block validation (#3674) * Expose priv validators for use in testing * Generalize block header validation test past height 1 * Remove ineffectual assignment * Remove redundant SaveState call * Reorder comment for clarity * Use the block executor ApplyBlock function instead of implementing a stripped-down version of it * Remove commented-out code * Remove unnecessary test The required tests already appear to be implemented (implicitly) through the TestValidateBlockHeader test. * Allow for catching of specific error types during TestValidateBlockCommit * Make return error testable * Clean up and add TestValidateBlockCommit code * Fix formatting * Extract function to create a new mock test app * Update comment for clarity * Fix comment * Add skeleton code for evidence-related test * Allow for addressing priv val by address * Generalize test beyond a single validator * Generalize TestValidateBlockEvidence past first height * Reorder code to clearly separate tests and utility code * Use a common constant for stop height for testing in state/validation_test.go * Refactor errors to resemble existing conventions * Fix formatting * Extract common helper functions Having the tests littered with helper functions makes them less easily readable imho, so I've pulled them out into a separate file. This also makes it easier to see what helper functions are available during testing, so we minimize the chance of duplication when writing new tests. * Remove unused parameter * Remove unused parameters * Add field keys * Remove unused height constant * Fix typo * Fix incorrect return error * Add field keys * Use separate package for tests This refactors all of the state package's tests into a state_test package, so as to keep any usage of the state package's internal methods explicit. Any internal methods/constants used by tests are now explicitly exported in state/export_test.go * Refactor: extract helper function to make, validate, execute and commit a block * Rename state function to makeState * Remove redundant constant for number of validators * Refactor mock evidence registration into TestMain * Remove extraneous nVals variable * Replace function-level TODOs with file-level TODO and explanation * Remove extraneous comment * Fix linting issues brought up by GolangCI (pulled in from latest merge from develop)
5 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
  1. package state_test
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/mock"
  8. "github.com/stretchr/testify/require"
  9. dbm "github.com/tendermint/tm-db"
  10. abciclient "github.com/tendermint/tendermint/abci/client"
  11. abci "github.com/tendermint/tendermint/abci/types"
  12. "github.com/tendermint/tendermint/crypto"
  13. "github.com/tendermint/tendermint/crypto/ed25519"
  14. "github.com/tendermint/tendermint/crypto/encoding"
  15. "github.com/tendermint/tendermint/crypto/tmhash"
  16. mmock "github.com/tendermint/tendermint/internal/mempool/mock"
  17. "github.com/tendermint/tendermint/internal/proxy"
  18. sm "github.com/tendermint/tendermint/internal/state"
  19. "github.com/tendermint/tendermint/internal/state/mocks"
  20. sf "github.com/tendermint/tendermint/internal/state/test/factory"
  21. "github.com/tendermint/tendermint/internal/store"
  22. "github.com/tendermint/tendermint/libs/log"
  23. tmtime "github.com/tendermint/tendermint/libs/time"
  24. "github.com/tendermint/tendermint/types"
  25. "github.com/tendermint/tendermint/version"
  26. )
  27. var (
  28. chainID = "execution_chain"
  29. testPartSize uint32 = 65536
  30. )
  31. func TestApplyBlock(t *testing.T) {
  32. app := &testApp{}
  33. cc := abciclient.NewLocalCreator(app)
  34. proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics())
  35. err := proxyApp.Start()
  36. require.Nil(t, err)
  37. defer proxyApp.Stop() //nolint:errcheck // ignore for tests
  38. state, stateDB, _ := makeState(1, 1)
  39. stateStore := sm.NewStore(stateDB)
  40. blockStore := store.NewBlockStore(dbm.NewMemDB())
  41. blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
  42. mmock.Mempool{}, sm.EmptyEvidencePool{}, blockStore)
  43. block := sf.MakeBlock(state, 1, new(types.Commit))
  44. blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
  45. state, err = blockExec.ApplyBlock(state, blockID, block)
  46. require.Nil(t, err)
  47. // TODO check state and mempool
  48. assert.EqualValues(t, 1, state.Version.Consensus.App, "App version wasn't updated")
  49. }
  50. // TestBeginBlockValidators ensures we send absent validators list.
  51. func TestBeginBlockValidators(t *testing.T) {
  52. app := &testApp{}
  53. cc := abciclient.NewLocalCreator(app)
  54. proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics())
  55. err := proxyApp.Start()
  56. require.Nil(t, err)
  57. defer proxyApp.Stop() //nolint:errcheck // no need to check error again
  58. state, stateDB, _ := makeState(2, 2)
  59. stateStore := sm.NewStore(stateDB)
  60. prevHash := state.LastBlockID.Hash
  61. prevParts := types.PartSetHeader{}
  62. prevBlockID := types.BlockID{Hash: prevHash, PartSetHeader: prevParts}
  63. var (
  64. now = tmtime.Now()
  65. commitSig0 = types.NewCommitSigForBlock(
  66. []byte("Signature1"),
  67. state.Validators.Validators[0].Address,
  68. now)
  69. commitSig1 = types.NewCommitSigForBlock(
  70. []byte("Signature2"),
  71. state.Validators.Validators[1].Address,
  72. now)
  73. absentSig = types.NewCommitSigAbsent()
  74. )
  75. testCases := []struct {
  76. desc string
  77. lastCommitSigs []types.CommitSig
  78. expectedAbsentValidators []int
  79. }{
  80. {"none absent", []types.CommitSig{commitSig0, commitSig1}, []int{}},
  81. {"one absent", []types.CommitSig{commitSig0, absentSig}, []int{1}},
  82. {"multiple absent", []types.CommitSig{absentSig, absentSig}, []int{0, 1}},
  83. }
  84. for _, tc := range testCases {
  85. lastCommit := types.NewCommit(1, 0, prevBlockID, tc.lastCommitSigs)
  86. // block for height 2
  87. block := sf.MakeBlock(state, 2, lastCommit)
  88. _, err = sm.ExecCommitBlock(nil, proxyApp.Consensus(), block, log.TestingLogger(), stateStore, 1, state)
  89. require.Nil(t, err, tc.desc)
  90. // -> app receives a list of validators with a bool indicating if they signed
  91. ctr := 0
  92. for i, v := range app.CommitVotes {
  93. if ctr < len(tc.expectedAbsentValidators) &&
  94. tc.expectedAbsentValidators[ctr] == i {
  95. assert.False(t, v.SignedLastBlock)
  96. ctr++
  97. } else {
  98. assert.True(t, v.SignedLastBlock)
  99. }
  100. }
  101. }
  102. }
  103. // TestBeginBlockByzantineValidators ensures we send byzantine validators list.
  104. func TestBeginBlockByzantineValidators(t *testing.T) {
  105. app := &testApp{}
  106. cc := abciclient.NewLocalCreator(app)
  107. proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics())
  108. err := proxyApp.Start()
  109. require.Nil(t, err)
  110. defer proxyApp.Stop() //nolint:errcheck // ignore for tests
  111. state, stateDB, privVals := makeState(1, 1)
  112. stateStore := sm.NewStore(stateDB)
  113. defaultEvidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  114. privVal := privVals[state.Validators.Validators[0].Address.String()]
  115. blockID := makeBlockID([]byte("headerhash"), 1000, []byte("partshash"))
  116. header := &types.Header{
  117. Version: version.Consensus{Block: version.BlockProtocol, App: 1},
  118. ChainID: state.ChainID,
  119. Height: 10,
  120. Time: defaultEvidenceTime,
  121. LastBlockID: blockID,
  122. LastCommitHash: crypto.CRandBytes(tmhash.Size),
  123. DataHash: crypto.CRandBytes(tmhash.Size),
  124. ValidatorsHash: state.Validators.Hash(),
  125. NextValidatorsHash: state.Validators.Hash(),
  126. ConsensusHash: crypto.CRandBytes(tmhash.Size),
  127. AppHash: crypto.CRandBytes(tmhash.Size),
  128. LastResultsHash: crypto.CRandBytes(tmhash.Size),
  129. EvidenceHash: crypto.CRandBytes(tmhash.Size),
  130. ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
  131. }
  132. // we don't need to worry about validating the evidence as long as they pass validate basic
  133. dve := types.NewMockDuplicateVoteEvidenceWithValidator(3, defaultEvidenceTime, privVal, state.ChainID)
  134. dve.ValidatorPower = 1000
  135. lcae := &types.LightClientAttackEvidence{
  136. ConflictingBlock: &types.LightBlock{
  137. SignedHeader: &types.SignedHeader{
  138. Header: header,
  139. Commit: types.NewCommit(10, 0, makeBlockID(header.Hash(), 100, []byte("partshash")), []types.CommitSig{{
  140. BlockIDFlag: types.BlockIDFlagNil,
  141. ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
  142. Timestamp: defaultEvidenceTime,
  143. Signature: crypto.CRandBytes(types.MaxSignatureSize),
  144. }}),
  145. },
  146. ValidatorSet: state.Validators,
  147. },
  148. CommonHeight: 8,
  149. ByzantineValidators: []*types.Validator{state.Validators.Validators[0]},
  150. TotalVotingPower: 12,
  151. Timestamp: defaultEvidenceTime,
  152. }
  153. ev := []types.Evidence{dve, lcae}
  154. abciEv := []abci.Evidence{
  155. {
  156. Type: abci.EvidenceType_DUPLICATE_VOTE,
  157. Height: 3,
  158. Time: defaultEvidenceTime,
  159. Validator: types.TM2PB.Validator(state.Validators.Validators[0]),
  160. TotalVotingPower: 10,
  161. },
  162. {
  163. Type: abci.EvidenceType_LIGHT_CLIENT_ATTACK,
  164. Height: 8,
  165. Time: defaultEvidenceTime,
  166. Validator: types.TM2PB.Validator(state.Validators.Validators[0]),
  167. TotalVotingPower: 12,
  168. },
  169. }
  170. evpool := &mocks.EvidencePool{}
  171. evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return(ev, int64(100))
  172. evpool.On("Update", mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return()
  173. evpool.On("CheckEvidence", mock.AnythingOfType("types.EvidenceList")).Return(nil)
  174. blockStore := store.NewBlockStore(dbm.NewMemDB())
  175. blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
  176. mmock.Mempool{}, evpool, blockStore)
  177. block := sf.MakeBlock(state, 1, new(types.Commit))
  178. block.Evidence = types.EvidenceData{Evidence: ev}
  179. block.Header.EvidenceHash = block.Evidence.Hash()
  180. blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
  181. _, err = blockExec.ApplyBlock(state, blockID, block)
  182. require.Nil(t, err)
  183. // TODO check state and mempool
  184. assert.Equal(t, abciEv, app.ByzantineValidators)
  185. }
  186. func TestValidateValidatorUpdates(t *testing.T) {
  187. pubkey1 := ed25519.GenPrivKey().PubKey()
  188. pubkey2 := ed25519.GenPrivKey().PubKey()
  189. pk1, err := encoding.PubKeyToProto(pubkey1)
  190. assert.NoError(t, err)
  191. pk2, err := encoding.PubKeyToProto(pubkey2)
  192. assert.NoError(t, err)
  193. defaultValidatorParams := types.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}}
  194. testCases := []struct {
  195. name string
  196. abciUpdates []abci.ValidatorUpdate
  197. validatorParams types.ValidatorParams
  198. shouldErr bool
  199. }{
  200. {
  201. "adding a validator is OK",
  202. []abci.ValidatorUpdate{{PubKey: pk2, Power: 20}},
  203. defaultValidatorParams,
  204. false,
  205. },
  206. {
  207. "updating a validator is OK",
  208. []abci.ValidatorUpdate{{PubKey: pk1, Power: 20}},
  209. defaultValidatorParams,
  210. false,
  211. },
  212. {
  213. "removing a validator is OK",
  214. []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
  215. defaultValidatorParams,
  216. false,
  217. },
  218. {
  219. "adding a validator with negative power results in error",
  220. []abci.ValidatorUpdate{{PubKey: pk2, Power: -100}},
  221. defaultValidatorParams,
  222. true,
  223. },
  224. }
  225. for _, tc := range testCases {
  226. tc := tc
  227. t.Run(tc.name, func(t *testing.T) {
  228. err := sm.ValidateValidatorUpdates(tc.abciUpdates, tc.validatorParams)
  229. if tc.shouldErr {
  230. assert.Error(t, err)
  231. } else {
  232. assert.NoError(t, err)
  233. }
  234. })
  235. }
  236. }
  237. func TestUpdateValidators(t *testing.T) {
  238. pubkey1 := ed25519.GenPrivKey().PubKey()
  239. val1 := types.NewValidator(pubkey1, 10)
  240. pubkey2 := ed25519.GenPrivKey().PubKey()
  241. val2 := types.NewValidator(pubkey2, 20)
  242. pk, err := encoding.PubKeyToProto(pubkey1)
  243. require.NoError(t, err)
  244. pk2, err := encoding.PubKeyToProto(pubkey2)
  245. require.NoError(t, err)
  246. testCases := []struct {
  247. name string
  248. currentSet *types.ValidatorSet
  249. abciUpdates []abci.ValidatorUpdate
  250. resultingSet *types.ValidatorSet
  251. shouldErr bool
  252. }{
  253. {
  254. "adding a validator is OK",
  255. types.NewValidatorSet([]*types.Validator{val1}),
  256. []abci.ValidatorUpdate{{PubKey: pk2, Power: 20}},
  257. types.NewValidatorSet([]*types.Validator{val1, val2}),
  258. false,
  259. },
  260. {
  261. "updating a validator is OK",
  262. types.NewValidatorSet([]*types.Validator{val1}),
  263. []abci.ValidatorUpdate{{PubKey: pk, Power: 20}},
  264. types.NewValidatorSet([]*types.Validator{types.NewValidator(pubkey1, 20)}),
  265. false,
  266. },
  267. {
  268. "removing a validator is OK",
  269. types.NewValidatorSet([]*types.Validator{val1, val2}),
  270. []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
  271. types.NewValidatorSet([]*types.Validator{val1}),
  272. false,
  273. },
  274. {
  275. "removing a non-existing validator results in error",
  276. types.NewValidatorSet([]*types.Validator{val1}),
  277. []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
  278. types.NewValidatorSet([]*types.Validator{val1}),
  279. true,
  280. },
  281. }
  282. for _, tc := range testCases {
  283. tc := tc
  284. t.Run(tc.name, func(t *testing.T) {
  285. updates, err := types.PB2TM.ValidatorUpdates(tc.abciUpdates)
  286. assert.NoError(t, err)
  287. err = tc.currentSet.UpdateWithChangeSet(updates)
  288. if tc.shouldErr {
  289. assert.Error(t, err)
  290. } else {
  291. assert.NoError(t, err)
  292. require.Equal(t, tc.resultingSet.Size(), tc.currentSet.Size())
  293. assert.Equal(t, tc.resultingSet.TotalVotingPower(), tc.currentSet.TotalVotingPower())
  294. assert.Equal(t, tc.resultingSet.Validators[0].Address, tc.currentSet.Validators[0].Address)
  295. if tc.resultingSet.Size() > 1 {
  296. assert.Equal(t, tc.resultingSet.Validators[1].Address, tc.currentSet.Validators[1].Address)
  297. }
  298. }
  299. })
  300. }
  301. }
  302. // TestEndBlockValidatorUpdates ensures we update validator set and send an event.
  303. func TestEndBlockValidatorUpdates(t *testing.T) {
  304. app := &testApp{}
  305. cc := abciclient.NewLocalCreator(app)
  306. proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics())
  307. err := proxyApp.Start()
  308. require.Nil(t, err)
  309. defer proxyApp.Stop() //nolint:errcheck // ignore for tests
  310. state, stateDB, _ := makeState(1, 1)
  311. stateStore := sm.NewStore(stateDB)
  312. blockStore := store.NewBlockStore(dbm.NewMemDB())
  313. blockExec := sm.NewBlockExecutor(
  314. stateStore,
  315. log.TestingLogger(),
  316. proxyApp.Consensus(),
  317. mmock.Mempool{},
  318. sm.EmptyEvidencePool{},
  319. blockStore,
  320. )
  321. eventBus := types.NewEventBus()
  322. err = eventBus.Start()
  323. require.NoError(t, err)
  324. defer eventBus.Stop() //nolint:errcheck // ignore for tests
  325. blockExec.SetEventBus(eventBus)
  326. updatesSub, err := eventBus.Subscribe(
  327. context.Background(),
  328. "TestEndBlockValidatorUpdates",
  329. types.EventQueryValidatorSetUpdates,
  330. )
  331. require.NoError(t, err)
  332. block := sf.MakeBlock(state, 1, new(types.Commit))
  333. blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
  334. pubkey := ed25519.GenPrivKey().PubKey()
  335. pk, err := encoding.PubKeyToProto(pubkey)
  336. require.NoError(t, err)
  337. app.ValidatorUpdates = []abci.ValidatorUpdate{
  338. {PubKey: pk, Power: 10},
  339. }
  340. state, err = blockExec.ApplyBlock(state, blockID, block)
  341. require.Nil(t, err)
  342. // test new validator was added to NextValidators
  343. if assert.Equal(t, state.Validators.Size()+1, state.NextValidators.Size()) {
  344. idx, _ := state.NextValidators.GetByAddress(pubkey.Address())
  345. if idx < 0 {
  346. t.Fatalf("can't find address %v in the set %v", pubkey.Address(), state.NextValidators)
  347. }
  348. }
  349. // test we threw an event
  350. select {
  351. case msg := <-updatesSub.Out():
  352. event, ok := msg.Data().(types.EventDataValidatorSetUpdates)
  353. require.True(t, ok, "Expected event of type EventDataValidatorSetUpdates, got %T", msg.Data())
  354. if assert.NotEmpty(t, event.ValidatorUpdates) {
  355. assert.Equal(t, pubkey, event.ValidatorUpdates[0].PubKey)
  356. assert.EqualValues(t, 10, event.ValidatorUpdates[0].VotingPower)
  357. }
  358. case <-updatesSub.Canceled():
  359. t.Fatalf("updatesSub was canceled (reason: %v)", updatesSub.Err())
  360. case <-time.After(1 * time.Second):
  361. t.Fatal("Did not receive EventValidatorSetUpdates within 1 sec.")
  362. }
  363. }
  364. // TestEndBlockValidatorUpdatesResultingInEmptySet checks that processing validator updates that
  365. // would result in empty set causes no panic, an error is raised and NextValidators is not updated
  366. func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) {
  367. app := &testApp{}
  368. cc := abciclient.NewLocalCreator(app)
  369. proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics())
  370. err := proxyApp.Start()
  371. require.Nil(t, err)
  372. defer proxyApp.Stop() //nolint:errcheck // ignore for tests
  373. state, stateDB, _ := makeState(1, 1)
  374. stateStore := sm.NewStore(stateDB)
  375. blockStore := store.NewBlockStore(dbm.NewMemDB())
  376. blockExec := sm.NewBlockExecutor(
  377. stateStore,
  378. log.TestingLogger(),
  379. proxyApp.Consensus(),
  380. mmock.Mempool{},
  381. sm.EmptyEvidencePool{},
  382. blockStore,
  383. )
  384. block := sf.MakeBlock(state, 1, new(types.Commit))
  385. blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
  386. vp, err := encoding.PubKeyToProto(state.Validators.Validators[0].PubKey)
  387. require.NoError(t, err)
  388. // Remove the only validator
  389. app.ValidatorUpdates = []abci.ValidatorUpdate{
  390. {PubKey: vp, Power: 0},
  391. }
  392. assert.NotPanics(t, func() { state, err = blockExec.ApplyBlock(state, blockID, block) })
  393. assert.NotNil(t, err)
  394. assert.NotEmpty(t, state.NextValidators.Validators)
  395. }
  396. func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID {
  397. var (
  398. h = make([]byte, tmhash.Size)
  399. psH = make([]byte, tmhash.Size)
  400. )
  401. copy(h, hash)
  402. copy(psH, partSetHash)
  403. return types.BlockID{
  404. Hash: h,
  405. PartSetHeader: types.PartSetHeader{
  406. Total: partSetSize,
  407. Hash: psH,
  408. },
  409. }
  410. }