use alloy_primitives::{Address, Keccak256, B256, U256};
use serde::{Deserialize, Serialize};
const DOMAIN_BINDING: &str = "init4.sequencer.v0";
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct SignRequest {
pub host_chain_id: U256,
pub ru_chain_id: U256,
pub sequence: U256,
pub confirm_by: U256,
pub gas_limit: U256,
pub ru_reward_address: Address,
pub contents: B256,
}
impl SignRequest {
pub fn signing_hash(&self) -> B256 {
let mut hasher = Keccak256::new();
hasher.update(DOMAIN_BINDING);
hasher.update(self.host_chain_id.to_be_bytes::<32>());
hasher.update(self.ru_chain_id.to_be_bytes::<32>());
hasher.update(self.sequence.to_be_bytes::<32>());
hasher.update(self.gas_limit.to_be_bytes::<32>());
hasher.update(self.confirm_by.to_be_bytes::<32>());
hasher.update(self.ru_reward_address);
hasher.update(self.contents);
hasher.finalize()
}
}
impl core::fmt::Display for SignRequest {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"SignRequest {{ host_chain_id: {}, ru_chain_id: {}, sequence: {}, confirm_by: {}, gas_limit: {}, ru_reward_address: {}, contents: {} }}",
self.host_chain_id,
self.ru_chain_id,
self.sequence,
self.confirm_by,
self.gas_limit,
self.ru_reward_address,
self.contents
)
}
}
#[cfg(test)]
mod test {
use super::*;
use alloy_primitives::b256;
#[test]
fn roundtrip() {
let req = SignRequest {
host_chain_id: U256::from(1),
ru_chain_id: U256::from(2),
sequence: U256::from(3),
confirm_by: U256::from(4),
gas_limit: U256::from(5),
ru_reward_address: Address::repeat_byte(6),
contents: B256::repeat_byte(7),
};
let ser = serde_json::to_string(&req).unwrap();
let de: SignRequest = serde_json::from_str(&ser).unwrap();
assert_eq!(req, de);
assert_eq!(
req.signing_hash(),
b256!("eabffc9ed79f68618d3628a804d40199c7888cb5274407ee0ad9ef95c7144d0f")
);
assert_eq!(de.signing_hash(), req.signing_hash());
}
}