Dynamic variable size for hash parameters
Description
The digest
and domain_hash
functions in checkpoint_lib.cairo, the format_message
function in message.cairo, and the domain_hash
function in validator_announce.cairo try to follow the behavior of abi.encodePacked
by appending the ByteData
struct with the size calculated with the u{64,256}_word_size
:
fn format_message(_message: Message) -> (u256, Message) {
let sender: felt252 = _message.sender.into();
let recipient: felt252 = _message.recipient.into();
let mut input: Array<ByteData> = array![
ByteData {
value: _message.version.into(), size: u64_word_size(_message.version.into()).into()
},
ByteData {
value: _message.nonce.into(), size: u64_word_size(_message.nonce.into()).into()
},
ByteData {
value: _message.origin.into(), size: u64_word_size(_message.origin.into()).into()
},
ByteData { value: sender.into(), size: ADDRESS_SIZE },
ByteData {
value: _message.destination.into(),
size: u64_word_size(_message.destination.into()).into()
},
ByteData { value: recipient.into(), size: ADDRESS_SIZE },
ByteData {
value: _message.body.size().into(),
size: u64_word_size(_message.body.size().into()).into()
},
];
// ...
}
However, static type variables such as uint32
, uint256
, and bytes32
take up the space of the result of the abi.encodePacked
function as much as its static size, like abi.encodePacked(bytes4(uint32(1)), bytes4(uint32(2)))
returns 0x0000000100000002
, not 0x0102
.
Since u{64,256}_word_size
returns the minimum byte length to store the given value (e.g., u64_word_size(1_u64) == 1_u8
), using these functions to encode the static type variables and implement the abi.encodePacked
function may result in incorrect behavior for inputs that start with the zero byte.
In the case where the 128-bit chunk of the body starts with the zero bytes, for instance, if the chunk of the body looks like 0x000...(total 16 bytes)...001
, the word size function will return one and it will be interpreted as 0x01
when it is hashed.
Impact
This bug may result in generating messages incompatible to the ABI of the Hyperlane protocol, which may lead to the failure of message dispatching and processing.
Recommendations
Consider using the static size instead of dynamically calculated size when generating messages.
Remediation
This issue has been acknowledged by Pragma, and fixes were implemented in the following commits: