1. Save pre-commit state in the beginning of end block.
2. Provide an interface for custom elections to rollback on crash recovery.
3. Simplify pre-commit management.
4. Add crash recovery for updert-validator and chain migration elecitons.
* Separate pending and effective validator updates.
- Pending validator updates do not prevent elections from concluding.
- ValidatorElection overrides has_conclude to not conclude when there is a pending update for the matching height.
- Effective validator updates deem past elections inconclusive.
* Problem: Looking for election block is inefficient.
Solution: Record placed elections, update the records upon election conclusion.
* Clarify the conclusion order in Election.process_blocks.
* Insert election records in bulk.
Otherwise, one can significantly slow nodes down by posting a whole bunch of unique elections.
* Change get_election to use find_one.
* Calculate total votes without making extra query.
* Fix the pending valset check.
* Fix election test setup.
* Problem: We need a way to synchronize a halt to block production to allow for upgrades across breaking changes.
* Solution: Created `MigrationElection`.
* Problem: Need documentation for `migration` elections.
* Solution: Updated the docs.
* Problem: `MigrationElection` needs 'new' CLI method.
* Solution: Updated the definition of `election` to include the new `migration` type.
* Problem: The way `end_block` checks for concluded elections assumes there is only one type of election (so we can't conclude an `upsert-validator` and a `chain-migration` at the same height).
* Solution: Re-engineered the code in `Elections` to conclude multiple elections in the same block. If more than one election change the validator set, only one of them is applied.
* Problem: Tendermint change to store validator changes at height h+2 will break `Election.get_status`.
* Solution: Reworked `get_validator_change` to look at only the latest block height or less.
* Problem: `ValidatorElection` and `MigrationElection` need to inherit from a common `Election` class.
Solution: Factored the common logic out of `ValidatorElection` and moved it to `Election` parent class.
* Problem: No need to store different types of elections in their own tables
Solution: Remove `DB_TABLE` property from `Election` class.
Solution: Created the `elections` table with secondary_index `election_id`.
* Problem: `UpsertValidatorVote` can be generalized to just be `Vote`
Solution: Renamed, refactored and moved the `Vote` class to tie in with the more general `Election` base class.
* Problem: `election_id` is not unique if two elections have the same properties.
Solution: Added a random `uuid4` seed to enforce uniqueness.
* Problem: cyrptoconditions dependency updated because of vulnerability CVE-2018-10903
* update cc to ~=0.7.2
* Fix test using b58encode
* Fixing some more tests failing because of base58 update
* Problem: We need to store the `election_id` as part of the `validator_update` so we can efficiently check which election was resposible for the change
Solution: Added the parameter to `store_validator_set` and aligned the tests
* Problem: Logic for `upsert-validator show` is convoluted
Solution: Rewrote the function to be much simpler
* Problem: Need a uniqueness constraint for election_id wrt validator changes
Solution: Added a new key to the db schema
Solution: Transfer vote to the election public key; generalize implemenation to handle election txn type
* Problem: Upsert valdiator 'new' doesn't accept public in base64 format
Solution: Tendermint stores all keys in base64 format so it would suitable to
abandon base58 encoding in favour of base64 encoding
* Problem: Not test for invalid execution of upsert-validator 'new'
Solution: Write tests to when invalid power or private key path has been supplied
* Problem: Exceptions are not informational when executing upsert-validator
Solution: generate error logs or print statement indicating success
* Problem: `run_upsert_validator_approve` was getting the voting power in a convoluted way
Solution: Changed it to get the voting power from the election outputs
* Problem: `run_upsert_validator_approve` casts votes for *all* voters, not just the user calling the command
Solution: Filter vote txs by the users public key
* Problem: Docs needed a more specific description of how to input the path to the private-key file
Solution: Changed the wording a bit
* Problem: Source files contain no license info
Solution: Add comments with SPDX license info to source files
* Python 3 files don't need # -*- coding: utf-8 -*-