Vulnerability: RLPReader - Leading zeroes allow multiple valid encodings and exit / output ids for the same transaction
Severity: high

Description:
The current implementation of RLP decoding can take 2 different `txBytes` and decode them to the same structure. Specifically, the `RLPReader.toUint` method can decode 2 different types of bytes to the same number. For example:\\n`0x821234` is decoded to `uint(0x1234)`\\n`0x83001234` is decoded to `uint(0x1234)`\\n`0xc101` can decode to `uint(1)`, even though the tag specifies a short list\\n`0x01` can decode to `uint(1)`, even though the tag specifies a single byte\\nAs explanation for this encoding:\\n`0x821234` is broken down into 2 parts:\\n`0x82` - represents `0x80` (the string tag) + `0x02` bytes encoded\\n`0x1234` - are the encoded bytes\\nThe same for 0x83001234:\\n`0x83` - represents `0x80` (the string tag) + `0x03` bytes encoded\\n`0x001234` - are the encoded bytes\\nThe current implementation casts the encoded bytes into a uint256, so these different encodings are interpreted by the contracts as the same number:\\n`uint(0x1234) = uint(0x001234)`\\n```\\nresult := mload(memPtr)\\n```\\n\\nHaving different valid encodings for the same data is a problem because the encodings are used to create hashes that are used as unique ids. This means that multiple ids can be created for the same data. The data should only have one possible id.\\nThe encoding is used to create ids in these parts of the code:\\n```\\nreturn keccak256(abi.encodePacked(\\_txBytes, \\_outputIndex, \\_utxoPosValue));\\n```\\n\\n```\\nreturn keccak256(abi.encodePacked(\\_txBytes, \\_outputIndex));\\n```\\n\\n```\\nbytes32 hashData = keccak256(abi.encodePacked(\\_txBytes, \\_utxoPos.value));\\n```\\n\\n```\\nreturn uint160((uint256(keccak256(\\_txBytes))  105).setBit(151));\\n```\\n\\n```\\nbytes32 leafData = keccak256(data.txBytes);\\n```\\n\\nOther methods that are affected because they rely on the return values of these methods:

Impact:

Recommended mitigation:
Enforce strict-length decoding for `txBytes`, and specify that `uint` is decoded from a 32-byte short string.\\nEnforcing a 32-byte length for `uint` means that `0x1234` should always be encoded as:\\n`0xa00000000000000000000000000000000000000000000000000000000000001234`\\n`0xa0` represents the tag + the length: `0x80 + 32`\\n`0000000000000000000000000000000000000000000000000000000000001234` is the number 32 bytes long with leading zeroes\\nUnfortunately, using leading zeroes is against the RLP spec:\\nhttps://github.com/ethereum/wiki/wiki/RLP\\npositive RLP integers must be represented in big endian binary form with no leading zeroes\\nThis means that libraries interacting with OMG contracts which are going to correctly and fully implement the spec will generate “incorrect” encodings for uints; encodings that are not going to be recognized by the OMG contracts.\\nFully correct spec encoding: `0x821234`. Proposed encoding in this solution: `0xa00000000000000000000000000000000000000000000000000000000000001234`.\\nSimilarly enforce restrictions where they can be added; this is possible because of the strict structure format that needs to be encoded.\\nSome other potential solutions are included below. Note that these solutions are not recommended for reasons included below:\\nNormalize the encoding that gets passed to methods that hash the transaction for use as an id:\\nThis can be implemented in the methods that call `keccak256` on `txBytes` and should decode and re-encode the passed `txBytes` in order to normalize the passed encoding.\\na `txBytes` is passed\\nthe `txBytes` are decoded into structure: `tmpDecodedStruct` = decode(txBytes)\\nthe `tmpDecodedStruct` is re-encoded in order to normalize it: `normalizedTxBytes = encode(txBytes)`\\nThis method is not recommended because it needs a Solidity encoder to be implemented and a lot of gas will be used to decode and re-encode the initial `txBytes`.\\nCorrectly and fully implement RLP decoding\\nThis is another solution that adds a lot of code and is prone to errors.\\nThe solution would be to enforce all of the restrictions when decoding and not accept any encoding that doesn't fully follow the spec. This for example means that is should not accept uints with leading zeroes.\\nThis is a problem because it needs a lot of code that is not easy to write in Solidity (or EVM).