agglayer_types/aggchain_data/
global.rs

1//! Represents the payload received from the chain, and the context fetched from
2//! the L1, for all the possible cases.
3//!
4//! 1. legacy ecdsa, kept as-is for now because of the v2~v3 migration struggles
5//!   - needs one ecdsa signature only
6//!
7//! 2. current generic, receive one aggchain proof with trusted sequencer
8//!    signature verified only on the agglayer
9//!   - stark proof
10//!   - single ecdsa verified on the agglayer (+ optional pv for debug)
11//!   - aggchain params
12//!
13//! 3. generic + multisig (one or the other, or both)
14//!   - aggchain proof + single ecdsa (trusted sequencer, not multisig) ->
15//!     single signature verified only on the agglayer
16//!   - aggchain proof + multisig (multi signer, not necessarily trusted
17//!     sequencer)
18//!   - multisig
19
20use agglayer_primitives::{Address, Signature};
21use pessimistic_proof::core::{self, MultisigError};
22use serde::{Deserialize, Serialize};
23use thiserror::Error;
24
25use crate::aggchain_data::{aggchain_proof, multisig, PayloadWithCtx};
26
27/// Represents the data needed from the API/Certificate to verify aggchain
28/// proofs and multisig.
29/// Made separately for now to not have to deal with storage and API design.
30#[derive(Clone, Debug, strum_macros::Display)]
31pub enum Payload {
32    LegacyEcdsa {
33        /// ECDSA Signature from the trusted sequencer.
34        signature: Signature,
35    },
36    MultisigOnly(multisig::Payload),
37    MultisigAndAggchainProof {
38        multisig: multisig::Payload,
39        aggchain_proof: aggchain_proof::Payload,
40    },
41}
42
43/// Represents the context fetched from L1 and/or defined by the agglayer.
44#[derive(Clone, Debug, strum_macros::Display)]
45pub enum Context {
46    LegacyEcdsa {
47        /// Address of the trusted sequencer.
48        signer: Address,
49    },
50    MultisigOnly(multisig::Ctx),
51    MultisigAndAggchainProof {
52        multisig_ctx: multisig::Ctx,
53        aggchain_proof_ctx: aggchain_proof::Context,
54    },
55}
56
57#[derive(Clone, Debug, Error, Deserialize, Serialize, Eq, PartialEq)]
58pub enum AggchainDataError {
59    #[error("Invalid variant: {0}")]
60    InvalidVariant(String),
61
62    #[error("Invalid multisig: {0}")]
63    InvalidMultisig(#[source] MultisigError),
64
65    #[error("Aggchain proof comes without its ECDSA")]
66    MissingSignature,
67}
68
69// Generate the prover inputs from the chain payload and the L1 context.
70impl TryInto<core::AggchainData> for PayloadWithCtx<Payload, Context> {
71    type Error = AggchainDataError;
72
73    fn try_into(self) -> Result<core::AggchainData, Self::Error> {
74        let PayloadWithCtx(payload, ctx) = self;
75        match (payload, ctx) {
76            (Payload::LegacyEcdsa { signature }, Context::LegacyEcdsa { signer }) => {
77                Ok(core::AggchainData::LegacyEcdsa { signer, signature })
78            }
79            (Payload::MultisigOnly(payload), Context::MultisigOnly(ctx)) => {
80                let prehash = ctx.prehash;
81                let multisig = core::MultiSignature::from(PayloadWithCtx(payload, ctx));
82                multisig
83                    .verify(prehash)
84                    .map_err(AggchainDataError::InvalidMultisig)?;
85                Ok(core::AggchainData::MultisigOnly(multisig))
86            }
87            (
88                Payload::MultisigAndAggchainProof {
89                    multisig,
90                    aggchain_proof,
91                },
92                Context::MultisigAndAggchainProof {
93                    multisig_ctx,
94                    aggchain_proof_ctx,
95                },
96            ) => {
97                let prehash = multisig_ctx.prehash;
98                let multisig = core::MultiSignature::from(PayloadWithCtx(multisig, multisig_ctx));
99                multisig
100                    .verify(prehash)
101                    .map_err(AggchainDataError::InvalidMultisig)?;
102                Ok(core::AggchainData::MultisigAndAggchainProof {
103                    multisig,
104                    aggchain_proof: PayloadWithCtx(aggchain_proof, aggchain_proof_ctx).into(),
105                })
106            }
107            (payload, context) => Err(AggchainDataError::InvalidVariant(format!(
108                "payload: {payload}, context: {context}"
109            ))),
110        }
111    }
112}