Open ajlopez opened 4 years ago
Having 10 uncles is not the average case, but I totally agree this must be addressed.
Make sure the delay is reproducible (to discard cases where it is due to coarse clock granularity)
As far as I remember, this issue is solved very easily re-using the cache created by ForkDetectionDataRule. Since the issue is very old, I will check again the code.
There are 3 problems:
1) The first problem is that for each uncle, a new class ConsensusValidationMainchainViewImpl is created and the block headers are pulled from the block store again and again. What is needed is to have a single ConsensusValidationMainchainView object that is created when a block needs to be processed, containing N headers from the current block. Here N = REQUIRED_NUMBER_OF_BLOCKS_FOR_FORK_DETECTION_CALCULATION + uncleListLimit Currently this is N = 449+10 = 559.
The ForkDetectionDataCalculator class method buildCommitToParentsVector() should receive an offset (between 0 and 10) so that it can access the data at the correct place
2) The second problem is that ConsensusValidationMainchainView does not cache the Nonce LSB, but the RSK block header. Each time the nonce LSB is required, the bitcoin block is created, and double-hashed. The ConsensusValidationMainchainView should contain at each position two fields: the block header and the cached nonce LSB.
3) Most of the items in the ConsensusValidationMainchainView are unused, because the fork detection mechanism only looks for blocks whose height is == 0 (mod 64). (64 is the CPV_JUMP_FACTOR). Therefore most of the headers that are read into the view are never accessed. It would be faster just to load the block headers (by number, not by hash) at positions i*64 for i = 0.. (559/64+1).
Informal run of long synchronization againts RSK testnet, produced these logs describing the process of a block
Notice that many log items have the SAME timestamp. Except the process of
ForkDetectionDataRule
, with a duration of 0.03 seconds (in this machine, context, etc)This rule is executed ten times if the block has TEN uncles. And when the validation is run twice, it is executed TWENTY times, yielding 0.6 seconds only in block validation. In many circunstance, the rest of the block is executed under 0.1 seconds (involving storage, execution of transactions, receipts, etc), so the time employed by this rule seems excesive.
Recommendations: