pessimistic_proof_core/aggchain_data/
aggchain_hash.rs1use agglayer_primitives::{
2 bytes::{BigEndian, ByteOrder as _},
3 keccak::keccak256_combine,
4 Digest,
5};
6use hex_literal::hex;
7
8use crate::aggchain_data::{aggchain_proof::AggchainProof, AggchainData, MultiSignature, Vkey};
9
10struct ConsensusType(u32);
11
12#[derive(Debug)]
13pub enum AggchainHashValues {
14 ConsensusType1 {
15 aggchain_vkey: Option<Vkey>,
16 aggchain_params: Option<Digest>,
17 multisig_hash: Digest,
18 },
19}
20
21impl From<&AggchainHashValues> for ConsensusType {
22 fn from(value: &AggchainHashValues) -> Self {
23 match value {
24 AggchainHashValues::ConsensusType1 { .. } => Self(1),
25 }
26 }
27}
28
29impl AggchainHashValues {
30 pub const EMPTY_MULTISIG_HASH: Digest = Digest(hex!(
32 "290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563"
34 ));
35
36 pub const EMPTY_AGGCHAIN_VKEY_HASH: Digest = Digest::ZERO;
38
39 pub const EMPTY_AGGCHAIN_PARAMS: Digest = Digest::ZERO;
41
42 pub fn hash(&self) -> Digest {
44 let consensus_type: u32 = ConsensusType::from(self).0;
45
46 match self {
47 AggchainHashValues::ConsensusType1 {
48 aggchain_vkey: aggchain_vkey_u32,
49 aggchain_params,
50 multisig_hash,
51 } => {
52 let aggchain_vkey_hash = aggchain_vkey_u32
53 .map(|vkey| {
54 let mut aggchain_vkey_hash = [0u8; 32];
55 BigEndian::write_u32_into(&vkey, &mut aggchain_vkey_hash);
56 aggchain_vkey_hash
57 })
58 .unwrap_or(*Self::EMPTY_AGGCHAIN_VKEY_HASH);
59
60 let aggchain_params = aggchain_params.unwrap_or(Self::EMPTY_AGGCHAIN_PARAMS);
61
62 keccak256_combine([
63 &consensus_type.to_be_bytes(),
64 aggchain_vkey_hash.as_slice(),
65 aggchain_params.as_slice(),
66 multisig_hash.as_slice(),
67 ])
68 }
69 }
70 }
71}
72
73impl From<&AggchainData> for AggchainHashValues {
74 fn from(value: &AggchainData) -> Self {
75 match value {
76 AggchainData::LegacyEcdsa { signer, signature } => AggchainHashValues::ConsensusType1 {
77 aggchain_vkey: None,
78 aggchain_params: None,
79 multisig_hash: MultiSignature {
80 signatures: vec![Some(*signature)],
81 expected_signers: vec![*signer],
82 threshold: 1,
83 }
84 .multisig_hash(),
85 },
86 AggchainData::MultisigOnly(multisig) => AggchainHashValues::ConsensusType1 {
87 aggchain_vkey: None,
88 aggchain_params: None,
89 multisig_hash: multisig.multisig_hash(),
90 },
91 AggchainData::MultisigAndAggchainProof {
92 multisig,
93 aggchain_proof:
94 AggchainProof {
95 aggchain_params,
96 aggchain_vkey,
97 },
98 } => AggchainHashValues::ConsensusType1 {
99 aggchain_vkey: Some(*aggchain_vkey),
100 aggchain_params: Some(*aggchain_params),
101 multisig_hash: multisig.multisig_hash(),
102 },
103 }
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use crate::aggchain_data::{AggchainHashValues, MultiSignature};
110
111 #[test]
112 fn nil_set() {
113 let empty = MultiSignature {
114 signatures: vec![], expected_signers: vec![],
116 threshold: 0,
117 };
118
119 assert_eq!(
120 empty.multisig_hash(),
121 AggchainHashValues::EMPTY_MULTISIG_HASH
122 );
123 }
124}