... | ... | @@ -35,30 +35,18 @@ |
|
|
|DevFund Address|mr59c3aniaN3qHXej5L8UBsssRZbiUUMnz |
|
|
|
|
|
|
# Interpretation
|
|
|
Current hypothesis is that the fork happened because of budget being inconsistent across the network: block 57750(A) that contained budget payment was rejected by several nodes in the network; later those nodes accepted block 57750(B) that contained failsafe payment.
|
|
|
The fork happened because of a bug in validating superblock payments that only reproduces with small amount (< 20) of masternodes in the network (which is exactly the case for the testnet). Hence, block 57750(A) that contained budget payment was rejected by several nodes in the network; later those nodes accepted block 57750(B) that contained failsafe payment.
|
|
|
|
|
|
Due to sloppy use of integer arithmetics in function CBudgetManager::IsTransactionValid superblock payment validity checks of all nodes that were online and synced at the moment (except for Volodymyr's wallet which was patched) rejected block 57750(A) by error. Mining pool node, however, produced the block before it had time to sync, so it still payed the budget that it had saved, but didn't run any masternode or budget related checks. Later, all the nodes that received block 57750(A) before they finished syncing ended up on chain A, others ended up on chain B.
|
|
|
Due to sloppy use of integer arithmetics in function `CBudgetManager::IsTransactionValid` superblock payment validity checks of all nodes that were online and synced at the moment (except for Volodymyr's wallet which was patched) rejected block 57750(A) by error. Mining pool node, however, produced the block before it had time to sync, so it still paid the budget that it had saved, but didn't run any masternode or budget related checks. Later, all the nodes that received block 57750(A) before they finished syncing ended up on chain A, others ended up on chain B.
|
|
|
|
|
|
So far, this is the only logical explanation, however there are few questions to be answered
|
|
|
|
|
|
### Further research directions
|
|
|
1. Why Volodymyr's masternodes rejected block 57750(A)? The obvious explanation would be that they didn't have the final budget, but they *actually gave votes for Final Budget A*! (todo: confirm with solid evidence)
|
|
|
* **Because of the failsafe payment code**. Due to sloppy use of integer arithmetics in function CBudgetManager::IsTransactionValid superblock payment validity checks won't work properly when there are less then 20 masternodes in the network. Specificly, any budget payments in superblock that are not devfund payments will be considered invalid.
|
|
|
2. **What caused issuing of block 57750(B) the next day? Which node mined it?** Probably, it won't help us understanding the problem, but it's just a strange unexplained event
|
|
|
3. **Why the failsafe even worked?** Based on code analysis done independently both by Volodymyr and Ashot the failsafe relies on impossible combination of events to work. In fact this was one of the reasons to eradicate it. We must have missed something
|
|
|
* Apparently, the "impossible" combination of events includes includes having less then 20 masternodes (**see the answer to Q1**). I suppose, this is exactly how it worked when it was tested in testnet
|
|
|
4. The last block on chain A is 58772 (01/20/2018 @ 11:54pm UTC), however Volodymyr's wallet received up to 57756 on Jan 22 and up to 58228 on Jan 23. **Why?** Probably it's due to the network being split, but it would be nice to have a more detailed explanation
|
|
|
5. **What mining pool has been doing since issuing block 58772?** No new blocks have been issued, but the pool is still working (Jan 23, morning)
|
|
|
6. **Is it a bug? If yes - how severe it is?** The testnet setup (little amount of nodes, unstable mining) obviously contributed in the fork, so it would be nice to know: to what extent?
|
|
|
* If I'm right about Q1 - **yes, it is**, and it's rather urgent, because it limits our capabilities of testing governance in the testnet
|
|
|
7. **How likely is it to reproduce in mainnet?** Hopefully, having answers for questions 1 - 6, it would be easy to answer this one.
|
|
|
* If I'm right about Q1 - **very unlikely**
|
|
|
|
|
|
# Next Actions
|
|
|
Therefore, following 3 events combined together resulted in the fork:
|
|
|
1. Calculation bug in `CBudgetManager::IsTransactionValid`
|
|
|
2. Small amount of masternodes in the testnet (which is the condition for the bug to reproduce)
|
|
|
3. Mining pool node having gone online exactly before the superblock (before it had time to sync the masternode list) - otherwise it wouldn't have created the block because of the bug mentioned above
|
|
|
|
|
|
# Actions taken
|
|
|
Following steps aim to test the hypothesis and fix the problem:
|
|
|
1. In the next couple of days Volodymyr will create an update that will fix incorrect superblock processing with small amount of masternodes.
|
|
|
2. This update will pass code review and will be merged into master
|
|
|
3. Mining pool node, testnet explorer and Volodymyr's masternodes will be updated to this version and restarted
|
|
|
4. If those nodes switch to chain A, the hypothesis is comfirmed. If no, we will need further investigation
|
|
|
5. We might need to test superblock payment several times and we will try to reproduce the situation before the fork as accurately as possible. If updated nodes are on the correct chain - hypothesis is confirmed, problem is fixed |
|
|
1. An update that fixes calculations in `IsTransactionValid` was produced.
|
|
|
2. The update was deployed into testnet
|
|
|
3. The miner continued to mine on chain A and all updated nodes in the network switched to that chain
|
|
|
|