Skip to main content

hyli_model/node/
data_availability.rs

1use std::{
2    collections::{BTreeMap, HashSet},
3    sync::Arc,
4};
5
6use borsh::{BorshDeserialize, BorshSerialize};
7use serde::{Deserialize, Serialize};
8use sha3::{Digest, Sha3_256};
9use utoipa::ToSchema;
10
11use crate::*;
12use hyli_net_traits::TcpMessageLabel;
13
14#[derive(Debug, Serialize, Deserialize, Clone, BorshSerialize, BorshDeserialize, Eq, PartialEq)]
15pub enum DataEvent {
16    OrderedSignedBlock(SignedBlock),
17}
18
19#[derive(
20    Default,
21    Debug,
22    Clone,
23    Serialize,
24    Deserialize,
25    ToSchema,
26    BorshSerialize,
27    BorshDeserialize,
28    Eq,
29    PartialEq,
30)]
31pub struct Contract {
32    pub name: ContractName,
33    pub program_id: ProgramId,
34    pub state: StateCommitment,
35    pub verifier: Verifier,
36    pub timeout_window: TimeoutWindow,
37}
38
39#[derive(
40    Default,
41    Debug,
42    Clone,
43    PartialEq,
44    Eq,
45    BorshSerialize,
46    BorshDeserialize,
47    serde::Serialize,
48    serde::Deserialize,
49    ToSchema,
50)]
51pub struct UnsettledBlobTransaction {
52    pub tx: BlobTransaction,
53    pub tx_id: TxId,
54    #[schema(value_type = TxContext)]
55    pub tx_context: Arc<TxContext>,
56    pub blobs_hash: BlobsHashes,
57    pub possible_proofs: BTreeMap<BlobIndex, Vec<(ProgramId, Verifier, TxId, HyliOutput)>>, // ToSchema doesn't like the alias
58    // The list of contracts whose settlement can be guaranteed, independently of the rest of the transaction's blobs
59    pub settleable_contracts: HashSet<ContractName>,
60}
61
62pub type BlobProof = (ProgramId, Verifier, TxId, HyliOutput);
63
64impl UnsettledBlobTransaction {
65    pub fn iter_blobs(&self) -> impl Iterator<Item = (&Blob, &Vec<BlobProof>)> + Clone {
66        std::iter::zip(self.tx.blobs.iter(), self.possible_proofs.values())
67    }
68}
69
70#[derive(
71    Debug,
72    Default,
73    Clone,
74    serde::Serialize,
75    serde::Deserialize,
76    BorshSerialize,
77    BorshDeserialize,
78    Eq,
79    PartialEq,
80)]
81pub struct HandledBlobProofOutput {
82    pub proof_tx_hash: TxHash,
83    pub blob_tx_hash: TxHash,
84    pub blob_index: BlobIndex,
85    pub contract_name: ContractName,
86    pub verifier: Verifier,
87    pub program_id: ProgramId,
88    pub hyli_output: HyliOutput,
89    pub blob_proof_output_index: usize,
90}
91
92#[derive(
93    Debug, Default, Serialize, Deserialize, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize,
94)]
95pub struct BlobProofOutput {
96    // TODO: this can be recovered from the hyli output
97    pub blob_tx_hash: TxHash,
98    // TODO: remove this?
99    pub original_proof_hash: ProofDataHash,
100
101    /// HyliOutput of the proof for this blob
102    pub hyli_output: HyliOutput,
103    /// Program ID used to verify the proof.
104    pub program_id: ProgramId,
105    /// verifier used to verify the proof.
106    pub verifier: Verifier,
107}
108
109pub struct BlobProofOutputHash(pub Vec<u8>);
110
111impl Hashed<BlobProofOutputHash> for BlobProofOutput {
112    fn hashed(&self) -> BlobProofOutputHash {
113        let mut hasher = Sha3_256::new();
114        hasher.update(&self.blob_tx_hash.0);
115        hasher.update(&self.original_proof_hash.0);
116        hasher.update(self.program_id.0.clone());
117        hasher.update(contract::Hashed::hashed(&self.hyli_output).0);
118        BlobProofOutputHash(hasher.finalize().to_vec())
119    }
120}
121
122pub struct HyliOutputHash(pub Vec<u8>);
123impl Hashed<HyliOutputHash> for HyliOutput {
124    fn hashed(&self) -> HyliOutputHash {
125        let mut hasher = Sha3_256::new();
126        hasher.update(self.version.to_le_bytes());
127        hasher.update(self.initial_state.0.clone());
128        hasher.update(self.next_state.0.clone());
129        hasher.update(self.identity.0.as_bytes());
130        hasher.update(self.index.0.to_le_bytes());
131        for blob in &self.blobs {
132            hasher.update(blob.0 .0.to_le_bytes());
133            hasher.update(blob.1.contract_name.0.as_bytes());
134            hasher.update(blob.1.data.0.as_slice());
135        }
136        hasher.update([self.success as u8]);
137        hasher.update(self.onchain_effects.len().to_le_bytes());
138        self.onchain_effects
139            .iter()
140            .for_each(|c| hasher.update(c.hashed().0));
141        hasher.update(&self.program_outputs);
142        HyliOutputHash(hasher.finalize().to_vec())
143    }
144}
145
146#[derive(
147    Debug, Clone, Serialize, Deserialize, ToSchema, BorshSerialize, BorshDeserialize, Eq, PartialEq,
148)]
149#[serde(tag = "name", content = "metadata")]
150pub enum TransactionStateEvent {
151    Sequenced,
152    Error(String),
153    NewProof {
154        blob_index: BlobIndex,
155        proof_tx_hash: TxHash,
156        program_output: Vec<u8>,
157    },
158    Settled,
159    SettledAsFailed,
160    TimedOut,
161    DroppedAsDuplicate,
162}
163
164#[derive(Default, Debug, Serialize, Deserialize, Clone, BorshSerialize, BorshDeserialize)]
165pub struct BlockStakingData {
166    pub new_bounded_validators: Vec<ValidatorPublicKey>,
167    pub staking_actions: Vec<(Identity, StakingAction)>,
168}
169
170#[derive(Default, Debug, Serialize, Deserialize, Clone, BorshSerialize, BorshDeserialize)]
171pub struct StatefulEvents {
172    pub events: Vec<(TxId, StatefulEvent)>,
173}
174
175#[derive(Debug, Serialize, Deserialize, Clone, BorshSerialize, BorshDeserialize)]
176pub enum StatefulEvent {
177    SequencedTx(BlobTransaction, Arc<TxContext>),
178    SettledTx(UnsettledBlobTransaction),
179    FailedTx(UnsettledBlobTransaction),
180    TimedOutTx(UnsettledBlobTransaction),
181    ContractRegistration(ContractName, Contract, Option<Vec<u8>>),
182    ContractUpdate(ContractName, Contract),
183    ContractDelete(ContractName),
184}
185
186#[derive(Default, Debug, Serialize, Deserialize, Clone, BorshSerialize, BorshDeserialize)]
187pub struct NodeStateBlock {
188    pub signed_block: std::sync::Arc<SignedBlock>,
189    pub staking_data: std::sync::Arc<BlockStakingData>,
190    pub stateful_events: std::sync::Arc<StatefulEvents>,
191}
192
193#[derive(Debug, Serialize, Deserialize, Clone, BorshSerialize, BorshDeserialize)]
194pub enum NodeStateEvent {
195    NewBlock(NodeStateBlock),
196}
197
198// Da Listener
199//
200#[derive(BorshDeserialize, BorshSerialize, Clone, Debug, PartialEq, Eq, TcpMessageLabel)]
201pub enum DataAvailabilityRequest {
202    /// Start streaming blocks from a given height
203    StreamFromHeight(BlockHeight),
204    /// Request a specific block by height (prioritized)
205    BlockRequest(BlockHeight),
206}
207
208#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize, TcpMessageLabel)]
209pub enum DataAvailabilityEvent {
210    SignedBlock(SignedBlock),
211    MempoolStatusEvent(MempoolStatusEvent),
212    /// Block not found at the requested height
213    BlockNotFound(BlockHeight),
214}