Vulnerability: BlockhashRegistry - Structure of provided blockheaders should be validated
Severity: medium

Description:
`getParentAndBlockhash` takes an rlp-encoded blockheader blob, extracts the parent parent hash and returns both the parent hash and the calculated blockhash of the provided data. The method is used to add blockhashes to the registry that are older than 256 blocks as they are not available to the evm directly. This is done by establishing a trust-chain from a blockhash that is already in the registry up to an older block\\nThe method assumes that valid rlp encoded data is provided but the structure is not verified (rlp decodes completely; block number is correct; timestamp is younger than prevs, …), giving a wide range of freedom to an attacker with enough hashing power (or exploiting potential future issues with keccak) to forge blocks that would never be accepted by clients, but may be accepted by this smart contract. (threat: mining pool forging arbitrary non-conformant blocks to exploit the BlockhashRegistry)\\nIt is not checked that input was actually provided. However, accessing an array at an invalid index will raise an exception in the EVM. Providing a single byte > `0xf7` will yield a result and succeed even though it would have never been accepted by a real node.\\nIt is assumed that the first byte is the rlp encoded length byte and an offset into the provided `_blockheader` bytes-array is calculated. Memory is subsequently accessed via a low-level `mload` at this calculated offset. However, it is never validated that the offset actually lies within the provided range of bytes `_blockheader` leading to an out-of-bounds memory read access.\\nThe rlp encoded data is only partially decoded. For the first rlp list the number of length bytes is extracted. For the rlp encoded long string a length byte of 1 is assumed. The inline comment appears to be inaccurate or might be misleading. `// we also have to add "2" = 1 byte to it to skip the length-information`\\nInvalid intermediary blocks (e.g. with parent hash 0x00) will be accepted potentially allowing an attacker to optimize the effort needed to forge invalid blocks skipping to the desired blocknumber overwriting a certain blockhash (see issue 6.18)\\nWith one collisions (very unlikely) an attacker can add arbitrary or even random values to the BlockchainRegistry. The parent-hash of the starting blockheader cannot be verified by the contract ([target_block_random]<--parent_hash--[rnd]<--parent_hash--[rnd]<--parent_hash--...<--parent_hash--[collision]<--parent_hash_collission--[anchor_block]). While nodes can verify block structure and bail on invalid structure and check the first blocks hash and make sure the chain is in-tact the contract can't. Therefore one cannot assume the same trust in the blockchain registry when recreating blocks compared to running a full node.\\n```\\nfunction getParentAndBlockhash(bytes memory \\_blockheader) public pure returns (bytes32 parentHash, bytes32 bhash) {\\n\\n    /// we need the 1st byte of the blockheader to calculate the position of the parentHash\\n    uint8 first = uint8(\\_blockheader[0]);\\n\\n    /// calculates the offset\\n    /// by using the 1st byte (usually f9) and substracting f7 to get the start point of the parentHash information\\n    /// we also have to add "2" = 1 byte to it to skip the length-information\\n    require(first > 0xf7, "invalid offset");\\n    uint8 offset = first - 0xf7 + 2;\\n\\n    /// we are using assembly because it's the most efficent way to access the parent blockhash within the rlp-encoded blockheader\\n    // solium-disable-next-line security/no-inline-assembly\\n    assembly { // solhint-disable-line no-inline-assembly\\n        // mstore to get the memory pointer of the blockheader to 0x20\\n        mstore(0x20, \\_blockheader)\\n\\n        // we load the pointer we just stored\\n        // then we add 0x20 (32 bytes) to get to the start of the blockheader\\n        // then we add the offset we calculated\\n        // and load it to the parentHash variable\\n        parentHash :=mload(\\n            add(\\n                add(\\n                    mload(0x20), 0x20\\n                ), offset)\\n        )\\n    }\\n    bhash = keccak256(\\_blockheader);\\n```\\n

Impact:

Recommended mitigation:
Validate that the provided data is within a sane range of bytes that is expected (min/max blockheader sizes).\\nValidate that the provided data is actually an rlp encoded blockheader.\\nValidate that the offset for the parent Hash is within the provided data.\\nValidate that the parent Hash is non zero.\\nValidate that blockhashes do not repeat.