BlockhashRegistry - recreateBlockheaders succeeds and emits an event even though no blockheaders have been provided
The method is used to re-create blockhashes from a list of rlp-encoded `_blockheaders`. However, the method never checks if `_blockheaders` actually contains items. The result is, that the method will unnecessarily store the same value that is already in the `blockhashMapping` at the same location and wrongly log `LogBlockhashAdded` even though nothing has been added nor changed.\\nassume `_blockheaders` is empty and the registry already knows the blockhash of `_blockNumber`\\n```\\nfunction recreateBlockheaders(uint \\_blockNumber, bytes[] memory \\_blockheaders) public {\\n\\n    bytes32 currentBlockhash = blockhashMapping[\\_blockNumber];\\n    require(currentBlockhash != 0x0, "parentBlock is not available");\\n\\n    bytes32 calculatedHash = reCalculateBlockheaders(\\_blockheaders, currentBlockhash);\\n    require(calculatedHash != 0x0, "invalid headers");\\n```\\n\\nAn attempt is made to re-calculate the hash of an empty `_blockheaders` array (also passing the `currentBlockhash` from the registry)\\n```\\nbytes32 calculatedHash = reCalculateBlockheaders(\\_blockheaders, currentBlockhash);\\n```\\n\\nThe following loop in `reCalculateBlockheaders` is skipped and the `currentBlockhash` is returned.\\n```\\nfunction reCalculateBlockheaders(bytes[] memory \\_blockheaders, bytes32 \\_bHash) public pure returns (bytes32 bhash) {\\n\\n    bytes32 currentBlockhash = \\_bHash;\\n    bytes32 calcParent = 0x0;\\n    bytes32 calcBlockhash = 0x0;\\n\\n    /// save to use for up to 200 blocks, exponential increase of gas-usage afterwards\\n    for (uint i = 0; i < \\_blockheaders.length; i++) {\\n        (calcParent, calcBlockhash) = getParentAndBlockhash(\\_blockheaders[i]);\\n        if (calcBlockhash != currentBlockhash) {\\n            return 0x0;\\n        }\\n        currentBlockhash = calcParent;\\n    }\\n\\n    return currentBlockhash;\\n```\\n\\nThe assertion does not fire, the `bnr` to store the `calculatedHash` is the same as the one initially provided to the method as an argument.. Nothing has changed but an event is emitted.\\n```\\n    /// we should never fail this assert, as this would mean that we were able to recreate a invalid blockchain\\n    assert(\\_blockNumber > \\_blockheaders.length);\\n    uint bnr = \\_blockNumber - \\_blockheaders.length;\\n    blockhashMapping[bnr] = calculatedHash;\\n    emit LogBlockhashAdded(bnr, calculatedHash);\\n}\\n```\\n
The method is crucial for the system to work correctly and must be tightly controlled by input validation. It should not be allowed to overwrite an existing value in the contract (issue 6.29) or emit an event even though nothing has happened. Therefore validate that user provided input is within safe bounds. In this case, that at least one `_blockheader` has been provided. Validate that `_blockNumber` is less than `block.number` and do not expect that parts of the code will throw and safe the contract from exploitation.
```\\nfunction recreateBlockheaders(uint \\_blockNumber, bytes[] memory \\_blockheaders) public {\\n\\n    bytes32 currentBlockhash = blockhashMapping[\\_blockNumber];\\n    require(currentBlockhash != 0x0, "parentBlock is not available");\\n\\n    bytes32 calculatedHash = reCalculateBlockheaders(\\_blockheaders, currentBlockhash);\\n    require(calculatedHash != 0x0, "invalid headers");\\n```\\n