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.

976 lines
29 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
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 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
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 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
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 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. abcimocks "github.com/tendermint/tendermint/abci/types/mocks"
  13. "github.com/tendermint/tendermint/crypto"
  14. "github.com/tendermint/tendermint/crypto/ed25519"
  15. "github.com/tendermint/tendermint/crypto/encoding"
  16. "github.com/tendermint/tendermint/crypto/tmhash"
  17. "github.com/tendermint/tendermint/internal/eventbus"
  18. mpmocks "github.com/tendermint/tendermint/internal/mempool/mocks"
  19. "github.com/tendermint/tendermint/internal/proxy"
  20. "github.com/tendermint/tendermint/internal/pubsub"
  21. sm "github.com/tendermint/tendermint/internal/state"
  22. "github.com/tendermint/tendermint/internal/state/mocks"
  23. sf "github.com/tendermint/tendermint/internal/state/test/factory"
  24. "github.com/tendermint/tendermint/internal/store"
  25. "github.com/tendermint/tendermint/internal/test/factory"
  26. "github.com/tendermint/tendermint/libs/log"
  27. "github.com/tendermint/tendermint/types"
  28. "github.com/tendermint/tendermint/version"
  29. )
  30. var (
  31. chainID = "execution_chain"
  32. testPartSize uint32 = 65536
  33. )
  34. func TestApplyBlock(t *testing.T) {
  35. app := &testApp{}
  36. logger := log.NewNopLogger()
  37. cc := abciclient.NewLocalClient(logger, app)
  38. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  39. ctx, cancel := context.WithCancel(context.Background())
  40. defer cancel()
  41. require.NoError(t, proxyApp.Start(ctx))
  42. eventBus := eventbus.NewDefault(logger)
  43. require.NoError(t, eventBus.Start(ctx))
  44. state, stateDB, _ := makeState(t, 1, 1)
  45. stateStore := sm.NewStore(stateDB)
  46. blockStore := store.NewBlockStore(dbm.NewMemDB())
  47. mp := &mpmocks.Mempool{}
  48. mp.On("Lock").Return()
  49. mp.On("Unlock").Return()
  50. mp.On("FlushAppConn", mock.Anything).Return(nil)
  51. mp.On("Update",
  52. mock.Anything,
  53. mock.Anything,
  54. mock.Anything,
  55. mock.Anything,
  56. mock.Anything,
  57. mock.Anything).Return(nil)
  58. blockExec := sm.NewBlockExecutor(stateStore, logger, proxyApp, mp, sm.EmptyEvidencePool{}, blockStore, eventBus)
  59. block := sf.MakeBlock(state, 1, new(types.Commit))
  60. bps, err := block.MakePartSet(testPartSize)
  61. require.NoError(t, err)
  62. blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
  63. state, err = blockExec.ApplyBlock(ctx, state, blockID, block)
  64. require.NoError(t, err)
  65. // TODO check state and mempool
  66. assert.EqualValues(t, 1, state.Version.Consensus.App, "App version wasn't updated")
  67. }
  68. // TestFinalizeBlockDecidedLastCommit ensures we correctly send the DecidedLastCommit to the
  69. // application. The test ensures that the DecidedLastCommit properly reflects
  70. // which validators signed the preceding block.
  71. func TestFinalizeBlockDecidedLastCommit(t *testing.T) {
  72. ctx, cancel := context.WithCancel(context.Background())
  73. defer cancel()
  74. logger := log.NewNopLogger()
  75. app := &testApp{}
  76. cc := abciclient.NewLocalClient(logger, app)
  77. appClient := proxy.New(cc, logger, proxy.NopMetrics())
  78. err := appClient.Start(ctx)
  79. require.NoError(t, err)
  80. state, stateDB, privVals := makeState(t, 7, 1)
  81. stateStore := sm.NewStore(stateDB)
  82. absentSig := types.NewCommitSigAbsent()
  83. testCases := []struct {
  84. name string
  85. absentCommitSigs map[int]bool
  86. }{
  87. {"none absent", map[int]bool{}},
  88. {"one absent", map[int]bool{1: true}},
  89. {"multiple absent", map[int]bool{1: true, 3: true}},
  90. }
  91. for _, tc := range testCases {
  92. t.Run(tc.name, func(t *testing.T) {
  93. blockStore := store.NewBlockStore(dbm.NewMemDB())
  94. evpool := &mocks.EvidencePool{}
  95. evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, 0)
  96. evpool.On("Update", ctx, mock.Anything, mock.Anything).Return()
  97. evpool.On("CheckEvidence", ctx, mock.Anything).Return(nil)
  98. mp := &mpmocks.Mempool{}
  99. mp.On("Lock").Return()
  100. mp.On("Unlock").Return()
  101. mp.On("FlushAppConn", mock.Anything).Return(nil)
  102. mp.On("Update",
  103. mock.Anything,
  104. mock.Anything,
  105. mock.Anything,
  106. mock.Anything,
  107. mock.Anything,
  108. mock.Anything).Return(nil)
  109. eventBus := eventbus.NewDefault(logger)
  110. require.NoError(t, eventBus.Start(ctx))
  111. blockExec := sm.NewBlockExecutor(stateStore, log.NewNopLogger(), appClient, mp, evpool, blockStore, eventBus)
  112. state, _, lastCommit := makeAndCommitGoodBlock(ctx, t, state, 1, new(types.Commit), state.NextValidators.Validators[0].Address, blockExec, privVals, nil)
  113. for idx, isAbsent := range tc.absentCommitSigs {
  114. if isAbsent {
  115. lastCommit.Signatures[idx] = absentSig
  116. }
  117. }
  118. // block for height 2
  119. block := sf.MakeBlock(state, 2, lastCommit)
  120. bps, err := block.MakePartSet(testPartSize)
  121. require.NoError(t, err)
  122. blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
  123. _, err = blockExec.ApplyBlock(ctx, state, blockID, block)
  124. require.NoError(t, err)
  125. // -> app receives a list of validators with a bool indicating if they signed
  126. for i, v := range app.CommitVotes {
  127. _, absent := tc.absentCommitSigs[i]
  128. assert.Equal(t, !absent, v.SignedLastBlock)
  129. }
  130. })
  131. }
  132. }
  133. // TestFinalizeBlockByzantineValidators ensures we send byzantine validators list.
  134. func TestFinalizeBlockByzantineValidators(t *testing.T) {
  135. ctx, cancel := context.WithCancel(context.Background())
  136. defer cancel()
  137. app := &testApp{}
  138. logger := log.NewNopLogger()
  139. cc := abciclient.NewLocalClient(logger, app)
  140. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  141. err := proxyApp.Start(ctx)
  142. require.NoError(t, err)
  143. state, stateDB, privVals := makeState(t, 1, 1)
  144. stateStore := sm.NewStore(stateDB)
  145. defaultEvidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  146. privVal := privVals[state.Validators.Validators[0].Address.String()]
  147. blockID := makeBlockID([]byte("headerhash"), 1000, []byte("partshash"))
  148. header := &types.Header{
  149. Version: version.Consensus{Block: version.BlockProtocol, App: 1},
  150. ChainID: state.ChainID,
  151. Height: 10,
  152. Time: defaultEvidenceTime,
  153. LastBlockID: blockID,
  154. LastCommitHash: crypto.CRandBytes(tmhash.Size),
  155. DataHash: crypto.CRandBytes(tmhash.Size),
  156. ValidatorsHash: state.Validators.Hash(),
  157. NextValidatorsHash: state.Validators.Hash(),
  158. ConsensusHash: crypto.CRandBytes(tmhash.Size),
  159. AppHash: crypto.CRandBytes(tmhash.Size),
  160. LastResultsHash: crypto.CRandBytes(tmhash.Size),
  161. EvidenceHash: crypto.CRandBytes(tmhash.Size),
  162. ProposerAddress: crypto.CRandBytes(crypto.AddressSize),
  163. }
  164. // we don't need to worry about validating the evidence as long as they pass validate basic
  165. dve, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx, 3, defaultEvidenceTime, privVal, state.ChainID)
  166. require.NoError(t, err)
  167. dve.ValidatorPower = 1000
  168. lcae := &types.LightClientAttackEvidence{
  169. ConflictingBlock: &types.LightBlock{
  170. SignedHeader: &types.SignedHeader{
  171. Header: header,
  172. Commit: types.NewCommit(10, 0, makeBlockID(header.Hash(), 100, []byte("partshash")), []types.CommitSig{{
  173. BlockIDFlag: types.BlockIDFlagNil,
  174. ValidatorAddress: crypto.AddressHash([]byte("validator_address")),
  175. Timestamp: defaultEvidenceTime,
  176. Signature: crypto.CRandBytes(types.MaxSignatureSize),
  177. }}),
  178. },
  179. ValidatorSet: state.Validators,
  180. },
  181. CommonHeight: 8,
  182. ByzantineValidators: []*types.Validator{state.Validators.Validators[0]},
  183. TotalVotingPower: 12,
  184. Timestamp: defaultEvidenceTime,
  185. }
  186. ev := []types.Evidence{dve, lcae}
  187. abciEv := []abci.Evidence{
  188. {
  189. Type: abci.EvidenceType_DUPLICATE_VOTE,
  190. Height: 3,
  191. Time: defaultEvidenceTime,
  192. Validator: types.TM2PB.Validator(state.Validators.Validators[0]),
  193. TotalVotingPower: 10,
  194. },
  195. {
  196. Type: abci.EvidenceType_LIGHT_CLIENT_ATTACK,
  197. Height: 8,
  198. Time: defaultEvidenceTime,
  199. Validator: types.TM2PB.Validator(state.Validators.Validators[0]),
  200. TotalVotingPower: 12,
  201. },
  202. }
  203. evpool := &mocks.EvidencePool{}
  204. evpool.On("PendingEvidence", mock.AnythingOfType("int64")).Return(ev, int64(100))
  205. evpool.On("Update", ctx, mock.AnythingOfType("state.State"), mock.AnythingOfType("types.EvidenceList")).Return()
  206. evpool.On("CheckEvidence", ctx, mock.AnythingOfType("types.EvidenceList")).Return(nil)
  207. mp := &mpmocks.Mempool{}
  208. mp.On("Lock").Return()
  209. mp.On("Unlock").Return()
  210. mp.On("FlushAppConn", mock.Anything).Return(nil)
  211. mp.On("Update",
  212. mock.Anything,
  213. mock.Anything,
  214. mock.Anything,
  215. mock.Anything,
  216. mock.Anything,
  217. mock.Anything).Return(nil)
  218. eventBus := eventbus.NewDefault(logger)
  219. require.NoError(t, eventBus.Start(ctx))
  220. blockStore := store.NewBlockStore(dbm.NewMemDB())
  221. blockExec := sm.NewBlockExecutor(stateStore, log.NewNopLogger(), proxyApp,
  222. mp, evpool, blockStore, eventBus)
  223. block := sf.MakeBlock(state, 1, new(types.Commit))
  224. block.Evidence = ev
  225. block.Header.EvidenceHash = block.Evidence.Hash()
  226. bps, err := block.MakePartSet(testPartSize)
  227. require.NoError(t, err)
  228. blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
  229. _, err = blockExec.ApplyBlock(ctx, state, blockID, block)
  230. require.NoError(t, err)
  231. // TODO check state and mempool
  232. assert.Equal(t, abciEv, app.ByzantineValidators)
  233. }
  234. func TestProcessProposal(t *testing.T) {
  235. const height = 2
  236. txs := factory.MakeTenTxs(height)
  237. ctx, cancel := context.WithCancel(context.Background())
  238. defer cancel()
  239. app := abcimocks.NewBaseMock()
  240. logger := log.NewNopLogger()
  241. cc := abciclient.NewLocalClient(logger, app)
  242. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  243. err := proxyApp.Start(ctx)
  244. require.NoError(t, err)
  245. state, stateDB, privVals := makeState(t, 1, height)
  246. stateStore := sm.NewStore(stateDB)
  247. blockStore := store.NewBlockStore(dbm.NewMemDB())
  248. eventBus := eventbus.NewDefault(logger)
  249. require.NoError(t, eventBus.Start(ctx))
  250. blockExec := sm.NewBlockExecutor(
  251. stateStore,
  252. logger,
  253. proxyApp,
  254. new(mpmocks.Mempool),
  255. sm.EmptyEvidencePool{},
  256. blockStore,
  257. eventBus,
  258. )
  259. block0 := sf.MakeBlock(state, height-1, new(types.Commit))
  260. lastCommitSig := []types.CommitSig{}
  261. partSet, err := block0.MakePartSet(types.BlockPartSizeBytes)
  262. require.NoError(t, err)
  263. blockID := types.BlockID{Hash: block0.Hash(), PartSetHeader: partSet.Header()}
  264. voteInfos := []abci.VoteInfo{}
  265. for _, privVal := range privVals {
  266. vote, err := factory.MakeVote(ctx, privVal, block0.Header.ChainID, 0, 0, 0, 2, blockID, time.Now())
  267. require.NoError(t, err)
  268. pk, err := privVal.GetPubKey(ctx)
  269. require.NoError(t, err)
  270. addr := pk.Address()
  271. voteInfos = append(voteInfos,
  272. abci.VoteInfo{
  273. SignedLastBlock: true,
  274. Validator: abci.Validator{
  275. Address: addr,
  276. Power: 1000,
  277. },
  278. })
  279. lastCommitSig = append(lastCommitSig, vote.CommitSig())
  280. }
  281. lastCommit := types.NewCommit(height-1, 0, types.BlockID{}, lastCommitSig)
  282. block1 := sf.MakeBlock(state, height, lastCommit)
  283. block1.Txs = txs
  284. expectedRpp := abci.RequestProcessProposal{
  285. Hash: block1.Hash(),
  286. Header: *block1.Header.ToProto(),
  287. Txs: block1.Txs.ToSliceOfBytes(),
  288. ByzantineValidators: block1.Evidence.ToABCI(),
  289. ProposedLastCommit: abci.CommitInfo{
  290. Round: 0,
  291. Votes: voteInfos,
  292. },
  293. }
  294. app.On("ProcessProposal", mock.Anything).Return(abci.ResponseProcessProposal{Accept: true})
  295. acceptBlock, err := blockExec.ProcessProposal(ctx, block1, state)
  296. require.NoError(t, err)
  297. require.True(t, acceptBlock)
  298. app.AssertExpectations(t)
  299. app.AssertCalled(t, "ProcessProposal", expectedRpp)
  300. }
  301. func TestValidateValidatorUpdates(t *testing.T) {
  302. pubkey1 := ed25519.GenPrivKey().PubKey()
  303. pubkey2 := ed25519.GenPrivKey().PubKey()
  304. pk1, err := encoding.PubKeyToProto(pubkey1)
  305. assert.NoError(t, err)
  306. pk2, err := encoding.PubKeyToProto(pubkey2)
  307. assert.NoError(t, err)
  308. defaultValidatorParams := types.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}}
  309. testCases := []struct {
  310. name string
  311. abciUpdates []abci.ValidatorUpdate
  312. validatorParams types.ValidatorParams
  313. shouldErr bool
  314. }{
  315. {
  316. "adding a validator is OK",
  317. []abci.ValidatorUpdate{{PubKey: pk2, Power: 20}},
  318. defaultValidatorParams,
  319. false,
  320. },
  321. {
  322. "updating a validator is OK",
  323. []abci.ValidatorUpdate{{PubKey: pk1, Power: 20}},
  324. defaultValidatorParams,
  325. false,
  326. },
  327. {
  328. "removing a validator is OK",
  329. []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
  330. defaultValidatorParams,
  331. false,
  332. },
  333. {
  334. "adding a validator with negative power results in error",
  335. []abci.ValidatorUpdate{{PubKey: pk2, Power: -100}},
  336. defaultValidatorParams,
  337. true,
  338. },
  339. }
  340. for _, tc := range testCases {
  341. tc := tc
  342. t.Run(tc.name, func(t *testing.T) {
  343. err := sm.ValidateValidatorUpdates(tc.abciUpdates, tc.validatorParams)
  344. if tc.shouldErr {
  345. assert.Error(t, err)
  346. } else {
  347. assert.NoError(t, err)
  348. }
  349. })
  350. }
  351. }
  352. func TestUpdateValidators(t *testing.T) {
  353. pubkey1 := ed25519.GenPrivKey().PubKey()
  354. val1 := types.NewValidator(pubkey1, 10)
  355. pubkey2 := ed25519.GenPrivKey().PubKey()
  356. val2 := types.NewValidator(pubkey2, 20)
  357. pk, err := encoding.PubKeyToProto(pubkey1)
  358. require.NoError(t, err)
  359. pk2, err := encoding.PubKeyToProto(pubkey2)
  360. require.NoError(t, err)
  361. testCases := []struct {
  362. name string
  363. currentSet *types.ValidatorSet
  364. abciUpdates []abci.ValidatorUpdate
  365. resultingSet *types.ValidatorSet
  366. shouldErr bool
  367. }{
  368. {
  369. "adding a validator is OK",
  370. types.NewValidatorSet([]*types.Validator{val1}),
  371. []abci.ValidatorUpdate{{PubKey: pk2, Power: 20}},
  372. types.NewValidatorSet([]*types.Validator{val1, val2}),
  373. false,
  374. },
  375. {
  376. "updating a validator is OK",
  377. types.NewValidatorSet([]*types.Validator{val1}),
  378. []abci.ValidatorUpdate{{PubKey: pk, Power: 20}},
  379. types.NewValidatorSet([]*types.Validator{types.NewValidator(pubkey1, 20)}),
  380. false,
  381. },
  382. {
  383. "removing a validator is OK",
  384. types.NewValidatorSet([]*types.Validator{val1, val2}),
  385. []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
  386. types.NewValidatorSet([]*types.Validator{val1}),
  387. false,
  388. },
  389. {
  390. "removing a non-existing validator results in error",
  391. types.NewValidatorSet([]*types.Validator{val1}),
  392. []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}},
  393. types.NewValidatorSet([]*types.Validator{val1}),
  394. true,
  395. },
  396. }
  397. for _, tc := range testCases {
  398. tc := tc
  399. t.Run(tc.name, func(t *testing.T) {
  400. updates, err := types.PB2TM.ValidatorUpdates(tc.abciUpdates)
  401. assert.NoError(t, err)
  402. err = tc.currentSet.UpdateWithChangeSet(updates)
  403. if tc.shouldErr {
  404. assert.Error(t, err)
  405. } else {
  406. assert.NoError(t, err)
  407. require.Equal(t, tc.resultingSet.Size(), tc.currentSet.Size())
  408. assert.Equal(t, tc.resultingSet.TotalVotingPower(), tc.currentSet.TotalVotingPower())
  409. assert.Equal(t, tc.resultingSet.Validators[0].Address, tc.currentSet.Validators[0].Address)
  410. if tc.resultingSet.Size() > 1 {
  411. assert.Equal(t, tc.resultingSet.Validators[1].Address, tc.currentSet.Validators[1].Address)
  412. }
  413. }
  414. })
  415. }
  416. }
  417. // TestFinalizeBlockValidatorUpdates ensures we update validator set and send an event.
  418. func TestFinalizeBlockValidatorUpdates(t *testing.T) {
  419. ctx, cancel := context.WithCancel(context.Background())
  420. defer cancel()
  421. app := &testApp{}
  422. logger := log.NewNopLogger()
  423. cc := abciclient.NewLocalClient(logger, app)
  424. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  425. err := proxyApp.Start(ctx)
  426. require.NoError(t, err)
  427. state, stateDB, _ := makeState(t, 1, 1)
  428. stateStore := sm.NewStore(stateDB)
  429. blockStore := store.NewBlockStore(dbm.NewMemDB())
  430. mp := &mpmocks.Mempool{}
  431. mp.On("Lock").Return()
  432. mp.On("Unlock").Return()
  433. mp.On("FlushAppConn", mock.Anything).Return(nil)
  434. mp.On("Update",
  435. mock.Anything,
  436. mock.Anything,
  437. mock.Anything,
  438. mock.Anything,
  439. mock.Anything,
  440. mock.Anything).Return(nil)
  441. mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
  442. eventBus := eventbus.NewDefault(logger)
  443. require.NoError(t, eventBus.Start(ctx))
  444. blockExec := sm.NewBlockExecutor(
  445. stateStore,
  446. logger,
  447. proxyApp,
  448. mp,
  449. sm.EmptyEvidencePool{},
  450. blockStore,
  451. eventBus,
  452. )
  453. updatesSub, err := eventBus.SubscribeWithArgs(ctx, pubsub.SubscribeArgs{
  454. ClientID: "TestFinalizeBlockValidatorUpdates",
  455. Query: types.EventQueryValidatorSetUpdates,
  456. })
  457. require.NoError(t, err)
  458. block := sf.MakeBlock(state, 1, new(types.Commit))
  459. bps, err := block.MakePartSet(testPartSize)
  460. require.NoError(t, err)
  461. blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
  462. pubkey := ed25519.GenPrivKey().PubKey()
  463. pk, err := encoding.PubKeyToProto(pubkey)
  464. require.NoError(t, err)
  465. app.ValidatorUpdates = []abci.ValidatorUpdate{
  466. {PubKey: pk, Power: 10},
  467. }
  468. state, err = blockExec.ApplyBlock(ctx, state, blockID, block)
  469. require.NoError(t, err)
  470. // test new validator was added to NextValidators
  471. if assert.Equal(t, state.Validators.Size()+1, state.NextValidators.Size()) {
  472. idx, _ := state.NextValidators.GetByAddress(pubkey.Address())
  473. if idx < 0 {
  474. t.Fatalf("can't find address %v in the set %v", pubkey.Address(), state.NextValidators)
  475. }
  476. }
  477. // test we threw an event
  478. ctx, cancel = context.WithTimeout(ctx, 1*time.Second)
  479. defer cancel()
  480. msg, err := updatesSub.Next(ctx)
  481. require.NoError(t, err)
  482. event, ok := msg.Data().(types.EventDataValidatorSetUpdates)
  483. require.True(t, ok, "Expected event of type EventDataValidatorSetUpdates, got %T", msg.Data())
  484. if assert.NotEmpty(t, event.ValidatorUpdates) {
  485. assert.Equal(t, pubkey, event.ValidatorUpdates[0].PubKey)
  486. assert.EqualValues(t, 10, event.ValidatorUpdates[0].VotingPower)
  487. }
  488. }
  489. // TestFinalizeBlockValidatorUpdatesResultingInEmptySet checks that processing validator updates that
  490. // would result in empty set causes no panic, an error is raised and NextValidators is not updated
  491. func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) {
  492. ctx, cancel := context.WithCancel(context.Background())
  493. defer cancel()
  494. app := &testApp{}
  495. logger := log.NewNopLogger()
  496. cc := abciclient.NewLocalClient(logger, app)
  497. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  498. err := proxyApp.Start(ctx)
  499. require.NoError(t, err)
  500. eventBus := eventbus.NewDefault(logger)
  501. require.NoError(t, eventBus.Start(ctx))
  502. state, stateDB, _ := makeState(t, 1, 1)
  503. stateStore := sm.NewStore(stateDB)
  504. blockStore := store.NewBlockStore(dbm.NewMemDB())
  505. blockExec := sm.NewBlockExecutor(
  506. stateStore,
  507. log.NewNopLogger(),
  508. proxyApp,
  509. new(mpmocks.Mempool),
  510. sm.EmptyEvidencePool{},
  511. blockStore,
  512. eventBus,
  513. )
  514. block := sf.MakeBlock(state, 1, new(types.Commit))
  515. bps, err := block.MakePartSet(testPartSize)
  516. require.NoError(t, err)
  517. blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()}
  518. vp, err := encoding.PubKeyToProto(state.Validators.Validators[0].PubKey)
  519. require.NoError(t, err)
  520. // Remove the only validator
  521. app.ValidatorUpdates = []abci.ValidatorUpdate{
  522. {PubKey: vp, Power: 0},
  523. }
  524. assert.NotPanics(t, func() { state, err = blockExec.ApplyBlock(ctx, state, blockID, block) })
  525. assert.Error(t, err)
  526. assert.NotEmpty(t, state.NextValidators.Validators)
  527. }
  528. func TestEmptyPrepareProposal(t *testing.T) {
  529. const height = 2
  530. ctx, cancel := context.WithCancel(context.Background())
  531. defer cancel()
  532. logger := log.NewNopLogger()
  533. eventBus := eventbus.NewDefault(logger)
  534. require.NoError(t, eventBus.Start(ctx))
  535. app := abcimocks.NewBaseMock()
  536. cc := abciclient.NewLocalClient(logger, app)
  537. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  538. err := proxyApp.Start(ctx)
  539. require.NoError(t, err)
  540. state, stateDB, privVals := makeState(t, 1, height)
  541. stateStore := sm.NewStore(stateDB)
  542. mp := &mpmocks.Mempool{}
  543. mp.On("Lock").Return()
  544. mp.On("Unlock").Return()
  545. mp.On("FlushAppConn", mock.Anything).Return(nil)
  546. mp.On("Update",
  547. mock.Anything,
  548. mock.Anything,
  549. mock.Anything,
  550. mock.Anything,
  551. mock.Anything,
  552. mock.Anything).Return(nil)
  553. mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
  554. blockExec := sm.NewBlockExecutor(
  555. stateStore,
  556. logger,
  557. proxyApp,
  558. mp,
  559. sm.EmptyEvidencePool{},
  560. nil,
  561. eventBus,
  562. )
  563. pa, _ := state.Validators.GetByIndex(0)
  564. commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
  565. _, err = blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
  566. require.NoError(t, err)
  567. }
  568. // TestPrepareProposalPanicOnInvalid tests that the block creation logic panics
  569. // if the ResponsePrepareProposal returned from the application is invalid.
  570. func TestPrepareProposalPanicOnInvalid(t *testing.T) {
  571. const height = 2
  572. ctx, cancel := context.WithCancel(context.Background())
  573. defer cancel()
  574. logger := log.NewNopLogger()
  575. eventBus := eventbus.NewDefault(logger)
  576. require.NoError(t, eventBus.Start(ctx))
  577. state, stateDB, privVals := makeState(t, 1, height)
  578. stateStore := sm.NewStore(stateDB)
  579. evpool := &mocks.EvidencePool{}
  580. evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
  581. mp := &mpmocks.Mempool{}
  582. mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs{})
  583. app := abcimocks.NewBaseMock()
  584. // create an invalid ResponsePrepareProposal
  585. rpp := abci.ResponsePrepareProposal{
  586. ModifiedTx: true,
  587. TxRecords: []*abci.TxRecord{
  588. {
  589. Action: abci.TxRecord_REMOVED,
  590. Tx: []byte("new tx"),
  591. },
  592. },
  593. }
  594. app.On("PrepareProposal", mock.Anything).Return(rpp, nil)
  595. cc := abciclient.NewLocalClient(logger, app)
  596. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  597. err := proxyApp.Start(ctx)
  598. require.NoError(t, err)
  599. blockExec := sm.NewBlockExecutor(
  600. stateStore,
  601. logger,
  602. proxyApp,
  603. mp,
  604. evpool,
  605. nil,
  606. eventBus,
  607. )
  608. pa, _ := state.Validators.GetByIndex(0)
  609. commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
  610. require.Panics(t,
  611. func() {
  612. blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil) //nolint:errcheck
  613. })
  614. mp.AssertExpectations(t)
  615. }
  616. // TestPrepareProposalRemoveTxs tests that any transactions marked as REMOVED
  617. // are not included in the block produced by CreateProposalBlock. The test also
  618. // ensures that any transactions removed are also removed from the mempool.
  619. func TestPrepareProposalRemoveTxs(t *testing.T) {
  620. const height = 2
  621. ctx, cancel := context.WithCancel(context.Background())
  622. defer cancel()
  623. logger := log.NewNopLogger()
  624. eventBus := eventbus.NewDefault(logger)
  625. require.NoError(t, eventBus.Start(ctx))
  626. state, stateDB, privVals := makeState(t, 1, height)
  627. stateStore := sm.NewStore(stateDB)
  628. evpool := &mocks.EvidencePool{}
  629. evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
  630. txs := factory.MakeTenTxs(height)
  631. mp := &mpmocks.Mempool{}
  632. mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
  633. trs := txsToTxRecords(types.Txs(txs))
  634. trs[0].Action = abci.TxRecord_REMOVED
  635. trs[1].Action = abci.TxRecord_REMOVED
  636. mp.On("RemoveTxByKey", mock.Anything).Return(nil).Twice()
  637. app := abcimocks.NewBaseMock()
  638. app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{
  639. ModifiedTx: true,
  640. TxRecords: trs,
  641. }, nil)
  642. cc := abciclient.NewLocalClient(logger, app)
  643. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  644. err := proxyApp.Start(ctx)
  645. require.NoError(t, err)
  646. blockExec := sm.NewBlockExecutor(
  647. stateStore,
  648. logger,
  649. proxyApp,
  650. mp,
  651. evpool,
  652. nil,
  653. eventBus,
  654. )
  655. pa, _ := state.Validators.GetByIndex(0)
  656. commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
  657. block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
  658. require.NoError(t, err)
  659. require.Len(t, block.Data.Txs.ToSliceOfBytes(), len(trs)-2)
  660. require.Equal(t, -1, block.Data.Txs.Index(types.Tx(trs[0].Tx)))
  661. require.Equal(t, -1, block.Data.Txs.Index(types.Tx(trs[1].Tx)))
  662. mp.AssertCalled(t, "RemoveTxByKey", types.Tx(trs[0].Tx).Key())
  663. mp.AssertCalled(t, "RemoveTxByKey", types.Tx(trs[1].Tx).Key())
  664. mp.AssertExpectations(t)
  665. }
  666. // TestPrepareProposalAddedTxsIncluded tests that any transactions marked as ADDED
  667. // in the prepare proposal response are included in the block. The test also
  668. // ensures that any transactions added are also checked into the mempool.
  669. func TestPrepareProposalAddedTxsIncluded(t *testing.T) {
  670. const height = 2
  671. ctx, cancel := context.WithCancel(context.Background())
  672. defer cancel()
  673. logger := log.NewNopLogger()
  674. eventBus := eventbus.NewDefault(logger)
  675. require.NoError(t, eventBus.Start(ctx))
  676. state, stateDB, privVals := makeState(t, 1, height)
  677. stateStore := sm.NewStore(stateDB)
  678. evpool := &mocks.EvidencePool{}
  679. evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
  680. txs := factory.MakeTenTxs(height)
  681. mp := &mpmocks.Mempool{}
  682. mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs[2:]))
  683. mp.On("CheckTx", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Twice()
  684. trs := txsToTxRecords(types.Txs(txs))
  685. trs[0].Action = abci.TxRecord_ADDED
  686. trs[1].Action = abci.TxRecord_ADDED
  687. app := abcimocks.NewBaseMock()
  688. app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{
  689. ModifiedTx: true,
  690. TxRecords: trs,
  691. }, nil)
  692. cc := abciclient.NewLocalClient(logger, app)
  693. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  694. err := proxyApp.Start(ctx)
  695. require.NoError(t, err)
  696. blockExec := sm.NewBlockExecutor(
  697. stateStore,
  698. logger,
  699. proxyApp,
  700. mp,
  701. evpool,
  702. nil,
  703. eventBus,
  704. )
  705. pa, _ := state.Validators.GetByIndex(0)
  706. commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
  707. block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
  708. require.NoError(t, err)
  709. require.Equal(t, txs[0], block.Data.Txs[0])
  710. require.Equal(t, txs[1], block.Data.Txs[1])
  711. mp.AssertExpectations(t)
  712. mp.AssertCalled(t, "CheckTx", mock.Anything, types.Tx(trs[0].Tx), mock.Anything, mock.Anything)
  713. mp.AssertCalled(t, "CheckTx", mock.Anything, types.Tx(trs[1].Tx), mock.Anything, mock.Anything)
  714. }
  715. // TestPrepareProposalReorderTxs tests that CreateBlock produces a block with transactions
  716. // in the order matching the order they are returned from PrepareProposal.
  717. func TestPrepareProposalReorderTxs(t *testing.T) {
  718. const height = 2
  719. ctx, cancel := context.WithCancel(context.Background())
  720. defer cancel()
  721. logger := log.NewNopLogger()
  722. eventBus := eventbus.NewDefault(logger)
  723. require.NoError(t, eventBus.Start(ctx))
  724. state, stateDB, privVals := makeState(t, 1, height)
  725. stateStore := sm.NewStore(stateDB)
  726. evpool := &mocks.EvidencePool{}
  727. evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
  728. txs := factory.MakeTenTxs(height)
  729. mp := &mpmocks.Mempool{}
  730. mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
  731. trs := txsToTxRecords(types.Txs(txs))
  732. trs = trs[2:]
  733. trs = append(trs[len(trs)/2:], trs[:len(trs)/2]...)
  734. app := abcimocks.NewBaseMock()
  735. app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{
  736. ModifiedTx: true,
  737. TxRecords: trs,
  738. }, nil)
  739. cc := abciclient.NewLocalClient(logger, app)
  740. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  741. err := proxyApp.Start(ctx)
  742. require.NoError(t, err)
  743. blockExec := sm.NewBlockExecutor(
  744. stateStore,
  745. logger,
  746. proxyApp,
  747. mp,
  748. evpool,
  749. nil,
  750. eventBus,
  751. )
  752. pa, _ := state.Validators.GetByIndex(0)
  753. commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
  754. block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
  755. require.NoError(t, err)
  756. for i, tx := range block.Data.Txs {
  757. require.Equal(t, types.Tx(trs[i].Tx), tx)
  758. }
  759. mp.AssertExpectations(t)
  760. }
  761. // TestPrepareProposalModifiedTxFalse tests that CreateBlock correctly ignores
  762. // the ResponsePrepareProposal TxRecords if ResponsePrepareProposal does not
  763. // set ModifiedTx to true.
  764. func TestPrepareProposalModifiedTxFalse(t *testing.T) {
  765. const height = 2
  766. ctx, cancel := context.WithCancel(context.Background())
  767. defer cancel()
  768. logger := log.NewNopLogger()
  769. eventBus := eventbus.NewDefault(logger)
  770. require.NoError(t, eventBus.Start(ctx))
  771. state, stateDB, privVals := makeState(t, 1, height)
  772. stateStore := sm.NewStore(stateDB)
  773. evpool := &mocks.EvidencePool{}
  774. evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0))
  775. txs := factory.MakeTenTxs(height)
  776. mp := &mpmocks.Mempool{}
  777. mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(types.Txs(txs))
  778. trs := txsToTxRecords(types.Txs(txs))
  779. trs = append(trs[len(trs)/2:], trs[:len(trs)/2]...)
  780. trs = trs[1:]
  781. trs[0].Action = abci.TxRecord_REMOVED
  782. trs[1] = &abci.TxRecord{
  783. Tx: []byte("new"),
  784. Action: abci.TxRecord_ADDED,
  785. }
  786. app := abcimocks.NewBaseMock()
  787. app.On("PrepareProposal", mock.Anything).Return(abci.ResponsePrepareProposal{
  788. ModifiedTx: false,
  789. TxRecords: trs,
  790. }, nil)
  791. cc := abciclient.NewLocalClient(logger, app)
  792. proxyApp := proxy.New(cc, logger, proxy.NopMetrics())
  793. err := proxyApp.Start(ctx)
  794. require.NoError(t, err)
  795. blockExec := sm.NewBlockExecutor(
  796. stateStore,
  797. logger,
  798. proxyApp,
  799. mp,
  800. evpool,
  801. nil,
  802. eventBus,
  803. )
  804. pa, _ := state.Validators.GetByIndex(0)
  805. commit := makeValidCommit(ctx, t, height, types.BlockID{}, state.Validators, privVals)
  806. block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa, nil)
  807. require.NoError(t, err)
  808. for i, tx := range block.Data.Txs {
  809. require.Equal(t, txs[i], tx)
  810. }
  811. mp.AssertExpectations(t)
  812. }
  813. func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.BlockID {
  814. var (
  815. h = make([]byte, tmhash.Size)
  816. psH = make([]byte, tmhash.Size)
  817. )
  818. copy(h, hash)
  819. copy(psH, partSetHash)
  820. return types.BlockID{
  821. Hash: h,
  822. PartSetHeader: types.PartSetHeader{
  823. Total: partSetSize,
  824. Hash: psH,
  825. },
  826. }
  827. }
  828. func txsToTxRecords(txs []types.Tx) []*abci.TxRecord {
  829. trs := make([]*abci.TxRecord, len(txs))
  830. for i, tx := range txs {
  831. trs[i] = &abci.TxRecord{
  832. Action: abci.TxRecord_UNMODIFIED,
  833. Tx: tx,
  834. }
  835. }
  836. return trs
  837. }