Refactor dao state monitor domain.
Add support for requesting all hashed from genesis from a peer which is
in conflict (can help to find at which block the issue started).
Add parseBlockchainComplete check for onParseBlockChainComplete
before calling onParseBlockChainComplete to avoid duplicated calls of
onParseBlockChainComplete. Happened if there was only one seed node.
We create a chain of hashes of the dao state starting from the genesis
block height and using the previous hash in the hash. This ensures that
the history need to be correct if a particular hash at a block height is
correct. We request from seed nodes the last 10 hashes and broadcast to
our peers our hash at each new block. We build our list in memory and
listen on the new onSnapShotApplied event to start building our chain
from the genesis height up to the last snapshot block and after that
from each parsed block.
If we detect a mismatch we store it in a collection and the UI can show
a warning to the user.
We added also the onDaoStateChanged handler to the DaoStateListener.
This event is called after all parsing is completed and listeners have
completed their work. We must not use time based delays in the listener
code otherwise we would get changed our dao state after that event.
To detect such we added a assert method to throw an exception if the
dao state gets changed after the allowDaoStateChange is set to false.
We want to have a deterministic dao state. The PubKeyScript in the
TxOutput was the only optional field which was only set in the
dumpBlockchainData program argument was set as it was only required for
the json dump for the explorer. It has 50 bytes of data which is about
20% of the txOutput data size. We prefer atm to avoid additional
complexity which would be created if we would handle that optional
field (e.g. exclude from hash creation).
The property might be useful as well for other use cases in future.
We subtract 1 day to be sure to not have any issues with timezones.
Even if we can be sure that the timezone
is handled correctly it could be that the user created the wallet in
one timezone and make a restore at
a different timezone which could lead in the worst case that he miss
the first day of the wallet transactions.