pessimistic_proof_core/aggchain_data/
mod.rs1use agglayer_primitives::{Address, Digest, Signature};
10use serde::{Deserialize, Serialize};
11
12pub use crate::aggchain_data::{
13 aggchain_hash::AggchainHashValues,
14 aggchain_proof::AggchainProof,
15 multisig::{MultiSignature, MultisigError},
16};
17use crate::{
18 local_state::commitment::{
19 PessimisticRootCommitmentVersion, SignatureCommitmentValues, SignatureCommitmentVersion,
20 },
21 proof::ConstrainedValues,
22 ProofError,
23};
24
25mod aggchain_hash;
26mod aggchain_proof;
27mod multisig;
28
29pub type Vkey = [u32; 8];
30
31#[derive(Clone, Debug, Serialize, Deserialize)]
34pub enum AggchainData {
35 LegacyEcdsa {
37 signer: Address,
39 signature: Signature,
41 },
42 MultisigOnly(MultiSignature),
44 MultisigAndAggchainProof {
46 multisig: MultiSignature,
48 aggchain_proof: AggchainProof,
50 },
51}
52
53impl AggchainData {
54 pub fn aggchain_hash(&self) -> Digest {
56 AggchainHashValues::from(self).hash()
57 }
58
59 pub fn verify(
60 &self,
61 constrained_values: ConstrainedValues,
62 ) -> Result<PessimisticRootCommitmentVersion, ProofError> {
63 let prev_pp_root_version = constrained_values.prev_pessimistic_root_version;
64
65 let target_pp_root_version = match self {
66 AggchainData::LegacyEcdsa { signer, signature } => {
67 AggchainData::legacy_ecdsa(signer, signature, constrained_values)?
68 }
69 AggchainData::MultisigOnly(multisig) => {
70 let commitment =
71 SignatureCommitmentValues::new(&constrained_values, None).multisig_commitment();
72
73 multisig
74 .verify(commitment)
75 .map_err(ProofError::InvalidMultisig)?;
76
77 PessimisticRootCommitmentVersion::V3
79 }
80 AggchainData::MultisigAndAggchainProof {
81 multisig,
82 aggchain_proof,
83 } => {
84 let commitment = SignatureCommitmentValues::new(
85 &constrained_values,
86 Some(aggchain_proof.aggchain_params), )
88 .multisig_commitment();
89
90 multisig
91 .verify(commitment)
92 .map_err(ProofError::InvalidMultisig)?;
93
94 aggchain_proof.verify_aggchain_proof(&constrained_values);
96
97 PessimisticRootCommitmentVersion::V3
99 }
100 };
101
102 match (prev_pp_root_version, target_pp_root_version) {
103 (PessimisticRootCommitmentVersion::V2, PessimisticRootCommitmentVersion::V2) => {}
105 (PessimisticRootCommitmentVersion::V3, PessimisticRootCommitmentVersion::V3) => {}
107 (PessimisticRootCommitmentVersion::V2, PessimisticRootCommitmentVersion::V3) => {}
109 _ => return Err(ProofError::InconsistentSignedPayload),
111 }
112
113 Ok(target_pp_root_version)
114 }
115}
116
117impl AggchainData {
118 pub fn legacy_ecdsa(
120 signer: &Address,
121 signature: &Signature,
122 constrained_values: ConstrainedValues,
123 ) -> Result<PessimisticRootCommitmentVersion, ProofError> {
124 let signature_values = SignatureCommitmentValues::new(&constrained_values, None);
125
126 let is_signed_with_version = |version: SignatureCommitmentVersion| {
127 let prehash = signature_values.commitment(version);
128 signature
129 .recover_address_from_prehash(&prehash)
130 .map(|recovered| *signer == recovered)
131 .map_err(|_| ProofError::InvalidSignature)
132 };
133
134 let target_pp_root_version = if is_signed_with_version(SignatureCommitmentVersion::V3)?
135 || is_signed_with_version(SignatureCommitmentVersion::V5)?
136 {
137 PessimisticRootCommitmentVersion::V3
138 } else if is_signed_with_version(SignatureCommitmentVersion::V2)? {
139 PessimisticRootCommitmentVersion::V2
140 } else {
141 return Err(ProofError::InvalidSignature);
142 };
143
144 Ok(target_pp_root_version)
145 }
146}