use alloy::{
primitives::{keccak256, Bytes, B256},
sol_types::SolValue,
};
use serde::{Deserialize, Serialize};
use std::sync::LazyLock;
use crate::state_commit_registry::IStateRootCommittable::StateCommit;
pub static BN254_CERTIFICATE_TYPEHASH: LazyLock<B256> =
LazyLock::new(|| keccak256("BN254Certificate(uint32 referenceTimestamp,bytes32 messageHash)".as_bytes()));
pub fn compute_signable_digest(reference_timestamp: u32, message_hash: B256) -> B256 {
keccak256((*BN254_CERTIFICATE_TYPEHASH, reference_timestamp, message_hash).abi_encode())
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct GetStateCommitProposalRequest {
pub sequence_no: u64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct GetStateCommitProposalResponse {
pub new_state_root: B256,
pub da_cert_hash: B256,
pub pcr0_commitment: B256,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SignStateCommitRequest {
pub digest: B256,
pub commit: StateCommitWire,
pub reference_timestamp: u32,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct StateCommitWire {
pub version: u8,
pub sequence_no: u64,
pub prev_state_root: B256,
pub new_state_root: B256,
pub timestamp: u64,
pub da_cert_hash: B256,
pub pcr0_commitment: B256,
}
impl From<StateCommitWire> for StateCommit {
fn from(w: StateCommitWire) -> Self {
StateCommit {
version: w.version,
sequenceNo: w.sequence_no,
prevStateRoot: w.prev_state_root,
newStateRoot: w.new_state_root,
timestamp: w.timestamp,
daCertHash: w.da_cert_hash,
pcr0Commitment: w.pcr0_commitment,
}
}
}
impl From<&StateCommit> for StateCommitWire {
fn from(c: &StateCommit) -> Self {
StateCommitWire {
version: c.version,
sequence_no: c.sequenceNo,
prev_state_root: c.prevStateRoot,
new_state_root: c.newStateRoot,
timestamp: c.timestamp,
da_cert_hash: c.daCertHash,
pcr0_commitment: c.pcr0Commitment,
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SignStateCommitResponse {
pub signature_bytes: Bytes,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn state_commit_wire_round_trips_through_alloy_struct() {
let wire = StateCommitWire {
version: 1,
sequence_no: 42,
prev_state_root: B256::repeat_byte(0x11),
new_state_root: B256::repeat_byte(0x22),
timestamp: 1_700_000_000,
da_cert_hash: B256::repeat_byte(0x33),
pcr0_commitment: B256::repeat_byte(0x44),
};
let commit: StateCommit = wire.clone().into();
assert_eq!(commit.version, 1);
assert_eq!(commit.sequenceNo, 42);
assert_eq!(commit.prevStateRoot, wire.prev_state_root);
assert_eq!(commit.newStateRoot, wire.new_state_root);
assert_eq!(commit.timestamp, 1_700_000_000);
assert_eq!(commit.daCertHash, wire.da_cert_hash);
assert_eq!(commit.pcr0Commitment, wire.pcr0_commitment);
let back: StateCommitWire = (&commit).into();
assert_eq!(back.version, wire.version);
assert_eq!(back.sequence_no, wire.sequence_no);
assert_eq!(back.prev_state_root, wire.prev_state_root);
assert_eq!(back.new_state_root, wire.new_state_root);
assert_eq!(back.timestamp, wire.timestamp);
assert_eq!(back.da_cert_hash, wire.da_cert_hash);
assert_eq!(back.pcr0_commitment, wire.pcr0_commitment);
}
#[test]
fn snake_case_json_serialization() {
let wire = StateCommitWire {
version: 1,
sequence_no: 7,
prev_state_root: B256::ZERO,
new_state_root: B256::repeat_byte(0xab),
timestamp: 12345,
da_cert_hash: B256::ZERO,
pcr0_commitment: B256::ZERO,
};
let json = serde_json::to_string(&wire).expect("serialize");
assert!(json.contains("\"sequence_no\":7"));
assert!(json.contains("\"prev_state_root\""));
assert!(json.contains("\"new_state_root\""));
assert!(json.contains("\"da_cert_hash\""));
assert!(json.contains("\"pcr0_commitment\""));
let back: StateCommitWire = serde_json::from_str(&json).expect("deserialize");
assert_eq!(back.sequence_no, 7);
assert_eq!(back.new_state_root, B256::repeat_byte(0xab));
}
}