sov_rollup_interface/node/services/da.rs
1//! The da module defines traits used by the full node to interact with the DA layer.
2use std::fmt::{self, Display};
3
4use async_trait::async_trait;
5use serde::de::DeserializeOwned;
6use serde::Serialize;
7
8use crate::da::{BlockHeaderTrait, DaSpec, DaVerifier};
9use crate::zk::ValidityCondition;
10
11/// A DaService is the local side of an RPC connection talking to a node of the DA layer
12/// It is *not* part of the logic that is zk-proven.
13///
14/// The DaService has two responsibilities - fetching data from the DA layer, transforming the
15/// data into a representation that can be efficiently verified in circuit.
16#[async_trait]
17pub trait DaService: Send + Sync + 'static {
18 /// A handle to the types used by the DA layer.
19 type Spec: DaSpec;
20
21 /// The verifier for this DA layer.
22 type Verifier: DaVerifier<Spec = Self::Spec>;
23
24 /// A DA layer block, possibly excluding some irrelevant information.
25 type FilteredBlock: SlotData<
26 BlockHeader = <Self::Spec as DaSpec>::BlockHeader,
27 Cond = <Self::Spec as DaSpec>::ValidityCondition,
28 >;
29
30 /// The error type for fallible methods.
31 type Error: fmt::Debug + Send + Sync + Display;
32
33 /// Retrieve the data for the given height, waiting for it to be
34 /// finalized if necessary. The block, once returned, must not be reverted
35 /// without a consensus violation.
36 async fn get_finalized_at(&self, height: u64) -> Result<Self::FilteredBlock, Self::Error>;
37
38 /// Fetch the block at the given height, waiting for one to be mined if necessary.
39 /// The returned block may not be final, and can be reverted without a consensus violation
40 async fn get_block_at(&self, height: u64) -> Result<Self::FilteredBlock, Self::Error>;
41
42 /// Extract the relevant transactions from a block. For example, this method might return
43 /// all of the blob transactions in rollup's namespace on Celestia.
44 fn extract_relevant_blobs(
45 &self,
46 block: &Self::FilteredBlock,
47 ) -> Vec<<Self::Spec as DaSpec>::BlobTransaction>;
48
49 /// Generate a proof that the relevant blob transactions have been extracted correctly from the DA layer
50 /// block.
51 async fn get_extraction_proof(
52 &self,
53 block: &Self::FilteredBlock,
54 blobs: &[<Self::Spec as DaSpec>::BlobTransaction],
55 ) -> (
56 <Self::Spec as DaSpec>::InclusionMultiProof,
57 <Self::Spec as DaSpec>::CompletenessProof,
58 );
59
60 /// Extract the relevant transactions from a block, along with a proof that the extraction has been done correctly.
61 /// For example, this method might return all of the blob transactions in rollup's namespace on Celestia,
62 /// together with a range proof against the root of the namespaced-merkle-tree, demonstrating that the entire
63 /// rollup namespace has been covered.
64 #[allow(clippy::type_complexity)]
65 async fn extract_relevant_blobs_with_proof(
66 &self,
67 block: &Self::FilteredBlock,
68 ) -> (
69 Vec<<Self::Spec as DaSpec>::BlobTransaction>,
70 <Self::Spec as DaSpec>::InclusionMultiProof,
71 <Self::Spec as DaSpec>::CompletenessProof,
72 ) {
73 let relevant_txs = self.extract_relevant_blobs(block);
74
75 let (etx_proofs, rollup_row_proofs) = self
76 .get_extraction_proof(block, relevant_txs.as_slice())
77 .await;
78
79 (relevant_txs, etx_proofs, rollup_row_proofs)
80 }
81
82 /// Send a transaction directly to the DA layer.
83 /// blob is the serialized and signed transaction.
84 /// Returns nothing if the transaction was successfully sent.
85 async fn send_transaction(&self, blob: &[u8]) -> Result<(), Self::Error>;
86}
87
88/// `SlotData` is the subset of a DA layer block which is stored in the rollup's database.
89/// At the very least, the rollup needs access to the hashes and headers of all DA layer blocks, but rollups
90/// may choose to store partial (or full) block data as well.
91pub trait SlotData:
92 Serialize + DeserializeOwned + PartialEq + core::fmt::Debug + Clone + Send + Sync
93{
94 /// The header type for a DA layer block as viewed by the rollup. This need not be identical
95 /// to the underlying rollup's header type, but it must be sufficient to reconstruct the block hash.
96 ///
97 /// For example, most fields of the a Tendermint-based DA chain like Celestia are irrelevant to the rollup.
98 /// For these fields, we only ever store their *serialized* representation in memory or on disk. Only a few special
99 /// fields like `data_root` are stored in decoded form in the `CelestiaHeader` struct.
100 type BlockHeader: BlockHeaderTrait;
101
102 /// The validity condition associated with the slot data.
103 type Cond: ValidityCondition;
104
105 /// The canonical hash of the DA layer block.
106 fn hash(&self) -> [u8; 32];
107 /// The header of the DA layer block.
108 fn header(&self) -> &Self::BlockHeader;
109 /// Get the validity condition set associated with the slot
110 fn validity_condition(&self) -> Self::Cond;
111}