Skip to main content

ave_core/model/
event.rs

1//! # Event data model.
2//!
3
4use super::network::TimeOut;
5
6use crate::{
7    evaluation::response::{EvaluatorError, EvaluatorResponse},
8    subject::Metadata,
9    validation::request::ActualProtocols,
10};
11
12use ave_actors::ActorError;
13use ave_common::{
14    bridge::request::EventRequestType,
15    identity::{DigestIdentifier, Signature, Signed, TimeStamp},
16    request::EventRequest,
17    response::{EvalResDB, LedgerDB, RequestEventDB},
18};
19
20use borsh::{BorshDeserialize, BorshSerialize};
21use serde::{Deserialize, Serialize};
22use thiserror::Error;
23
24#[derive(Debug, Error, Clone)]
25pub enum ProtocolsError {
26    #[error(
27        "invalid evaluation: evaluation result does not match expected state"
28    )]
29    InvalidEvaluation,
30
31    #[error("invalid evaluation: approval required but not provided")]
32    ApprovalRequired,
33
34    #[error("invalid actual protocols: expected {expected}, got {got}")]
35    InvalidActualProtocols {
36        expected: &'static str,
37        got: &'static str,
38    },
39
40    #[error(
41        "invalid event request type: {request_type} is not supported for is_gov={is_gov}"
42    )]
43    InvalidEventRequestType {
44        request_type: &'static str,
45        is_gov: bool,
46    },
47
48    #[error(
49        "expected create event with metadata, got different protocol or validation metadata"
50    )]
51    NotCreateWithMetadata,
52}
53
54impl From<ProtocolsError> for ActorError {
55    fn from(error: ProtocolsError) -> Self {
56        Self::Functional {
57            description: error.to_string(),
58        }
59    }
60}
61
62#[derive(
63    Clone, Debug, Serialize, Deserialize, BorshDeserialize, BorshSerialize,
64)]
65pub enum EvaluationResponse {
66    Ok(EvaluatorResponse),
67    Error(EvaluatorError),
68}
69
70#[derive(
71    Clone, Debug, Serialize, Deserialize, BorshDeserialize, BorshSerialize,
72)]
73pub struct EvaluationData {
74    pub eval_req_signature: Signature,
75    pub eval_req_hash: DigestIdentifier,
76    pub evaluators_signatures: Vec<Signature>,
77    pub response: EvaluationResponse,
78}
79
80impl EvaluationData {
81    pub fn evaluator_res(&self) -> Option<EvaluatorResponse> {
82        match &self.response {
83            EvaluationResponse::Ok(evaluator_response) => {
84                Some(evaluator_response.clone())
85            }
86            _ => None,
87        }
88    }
89}
90
91#[derive(
92    Clone, Debug, Serialize, Deserialize, BorshDeserialize, BorshSerialize,
93)]
94pub struct ApprovalData {
95    pub approval_req_signature: Signature,
96    pub approval_req_hash: DigestIdentifier,
97    pub approvers_agrees_signatures: Vec<Signature>,
98    pub approvers_disagrees_signatures: Vec<Signature>,
99    pub approvers_timeout: Vec<TimeOut>,
100    pub approved: bool,
101}
102
103#[derive(
104    Debug, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize,
105)]
106pub struct ValidationData {
107    pub validation_req_signature: Signature,
108    pub validation_req_hash: DigestIdentifier,
109    pub validators_signatures: Vec<Signature>,
110    pub validation_metadata: ValidationMetadata,
111}
112
113#[derive(
114    Debug,
115    Clone,
116    Serialize,
117    Deserialize,
118    BorshSerialize,
119    BorshDeserialize,
120    Eq,
121    PartialEq,
122    Hash,
123)]
124pub enum ValidationMetadata {
125    ModifiedHash(DigestIdentifier),
126    Metadata(Box<Metadata>),
127}
128
129#[derive(
130    Debug, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize,
131)]
132pub enum Protocols {
133    Create {
134        validation: ValidationData,
135    },
136    TrackerFact {
137        evaluation: EvaluationData,
138        validation: ValidationData,
139    },
140    GovFact {
141        evaluation: EvaluationData,
142        approval: Option<ApprovalData>,
143        validation: ValidationData,
144    },
145    Transfer {
146        evaluation: EvaluationData,
147        validation: ValidationData,
148    },
149    TrackerConfirm {
150        validation: ValidationData,
151    },
152    GovConfirm {
153        evaluation: EvaluationData,
154        validation: ValidationData,
155    },
156    Reject {
157        validation: ValidationData,
158    },
159    EOL {
160        validation: ValidationData,
161    },
162}
163
164impl Protocols {
165    pub fn buidl_event_db(
166        &self,
167        event_request: &EventRequest,
168    ) -> (RequestEventDB, DigestIdentifier) {
169        match (self, event_request) {
170            (Self::Create { validation }, EventRequest::Create(create)) => {
171                let ValidationMetadata::Metadata(metadata) =
172                    &validation.validation_metadata
173                else {
174                    unreachable!(
175                        "Unreachable combination is a create event request"
176                    )
177                };
178
179                (
180                    RequestEventDB::Create {
181                        name: create.name.clone(),
182                        description: create.description.clone(),
183                        schema_id: create.schema_id.to_string(),
184                        namespace: create.namespace.to_string(),
185                    },
186                    metadata.subject_id.clone(),
187                )
188            }
189            (
190                Self::TrackerFact { evaluation, .. },
191                EventRequest::Fact(fact_request),
192            ) => {
193                let evaluation_response = match evaluation.response.clone() {
194                    EvaluationResponse::Ok(eval_res) => {
195                        EvalResDB::Patch(eval_res.patch.0)
196                    }
197                    EvaluationResponse::Error(e) => {
198                        EvalResDB::Error(e.to_string())
199                    }
200                };
201
202                (
203                    RequestEventDB::TrackerFact {
204                        payload: fact_request.payload.0.clone(),
205                        evaluation_response,
206                    },
207                    event_request.get_subject_id(),
208                )
209            }
210            (
211                Self::GovFact {
212                    evaluation,
213                    approval,
214                    ..
215                },
216                EventRequest::Fact(fact_request),
217            ) => {
218                let (evaluation_response, approval_success) = match evaluation
219                    .response
220                    .clone()
221                {
222                    EvaluationResponse::Ok(eval_res) => {
223                        if let Some(appr) = approval {
224                            (
225                                EvalResDB::Patch(eval_res.patch.0),
226                                Some(appr.approved),
227                            )
228                        } else {
229                            unreachable!(
230                                "In a factual governance event, if the assessment is correct, there should be approval"
231                            )
232                        }
233                    }
234                    EvaluationResponse::Error(e) => {
235                        (EvalResDB::Error(e.to_string()), None)
236                    }
237                };
238                (
239                    RequestEventDB::GovernanceFact {
240                        payload: fact_request.payload.0.clone(),
241                        evaluation_response,
242                        approval_success,
243                    },
244                    event_request.get_subject_id(),
245                )
246            }
247            (
248                Self::Transfer { evaluation, .. },
249                EventRequest::Transfer(transfer_request),
250            ) => {
251                let evaluation_error = match evaluation.response.clone() {
252                    EvaluationResponse::Ok(_) => None,
253                    EvaluationResponse::Error(e) => Some(e.to_string()),
254                };
255                (
256                    RequestEventDB::Transfer {
257                        new_owner: transfer_request.new_owner.to_string(),
258                        evaluation_error,
259                    },
260                    event_request.get_subject_id(),
261                )
262            }
263            (Self::TrackerConfirm { .. }, EventRequest::Confirm(..)) => (
264                RequestEventDB::TrackerConfirm,
265                event_request.get_subject_id(),
266            ),
267            (
268                Self::GovConfirm { evaluation, .. },
269                EventRequest::Confirm(confirm_request),
270            ) => {
271                let evaluation_response = match evaluation.response.clone() {
272                    EvaluationResponse::Ok(eval_res) => {
273                        EvalResDB::Patch(eval_res.patch.0)
274                    }
275                    EvaluationResponse::Error(e) => {
276                        EvalResDB::Error(e.to_string())
277                    }
278                };
279                (
280                    RequestEventDB::GovernanceConfirm {
281                        name_old_owner: confirm_request.name_old_owner.clone(),
282                        evaluation_response,
283                    },
284                    event_request.get_subject_id(),
285                )
286            }
287            (Self::Reject { .. }, EventRequest::Reject(..)) => {
288                (RequestEventDB::Reject, event_request.get_subject_id())
289            }
290            (Self::EOL { .. }, EventRequest::EOL(..)) => {
291                (RequestEventDB::EOL, event_request.get_subject_id())
292            }
293            _ => unreachable!(
294                "Unreachable combination of protocol and event request"
295            ),
296        }
297    }
298
299    pub fn get_validation_data(&self) -> ValidationData {
300        match self {
301            Self::Create { validation }
302            | Self::TrackerFact { validation, .. }
303            | Self::GovFact { validation, .. }
304            | Self::Transfer { validation, .. }
305            | Self::TrackerConfirm { validation }
306            | Self::GovConfirm { validation, .. }
307            | Self::Reject { validation }
308            | Self::EOL { validation } => validation.clone(),
309        }
310    }
311
312    pub fn is_success(&self) -> bool {
313        match self {
314            Self::Create { .. } => true,
315            Self::TrackerFact { evaluation, .. } => {
316                evaluation.evaluator_res().is_some()
317            }
318            Self::GovFact { approval, .. } => {
319                approval.as_ref().is_some_and(|approval| approval.approved)
320            }
321            Self::Transfer { evaluation, .. } => {
322                evaluation.evaluator_res().is_some()
323            }
324            Self::TrackerConfirm { .. } => true,
325            Self::GovConfirm { evaluation, .. } => {
326                evaluation.evaluator_res().is_some()
327            }
328            Self::Reject { .. } => true,
329            Self::EOL { .. } => true,
330        }
331    }
332
333    pub fn build(
334        is_gov: bool,
335        event_request: EventRequestType,
336        actual_protocols: ActualProtocols,
337        validation: ValidationData,
338    ) -> Result<Self, ProtocolsError> {
339        match (event_request, is_gov) {
340            (EventRequestType::Fact, true) => {
341                let (evaluation, approval) = match actual_protocols {
342                    ActualProtocols::Eval { eval_data } => {
343                        if eval_data.evaluator_res().is_some() {
344                            return Err(ProtocolsError::InvalidEvaluation);
345                        } else {
346                            (eval_data, None)
347                        }
348                    }
349                    ActualProtocols::EvalApprove {
350                        eval_data,
351                        approval_data,
352                    } => {
353                        if let Some(eval_res) = eval_data.evaluator_res() {
354                            if !eval_res.appr_required {
355                                return Err(ProtocolsError::ApprovalRequired);
356                            }
357                        } else {
358                            return Err(ProtocolsError::InvalidEvaluation);
359                        };
360
361                        (eval_data, Some(approval_data))
362                    }
363                    ActualProtocols::None => {
364                        return Err(ProtocolsError::InvalidActualProtocols {
365                            expected: "Eval or EvalApprove",
366                            got: "None",
367                        });
368                    }
369                };
370
371                Ok(Self::GovFact {
372                    evaluation,
373                    approval,
374                    validation,
375                })
376            }
377            (EventRequestType::Fact, false) => {
378                let evaluation = match actual_protocols {
379                    ActualProtocols::Eval { eval_data } => eval_data,
380                    ActualProtocols::None => {
381                        return Err(ProtocolsError::InvalidActualProtocols {
382                            expected: "Eval",
383                            got: "None",
384                        });
385                    }
386                    ActualProtocols::EvalApprove { .. } => {
387                        return Err(ProtocolsError::InvalidActualProtocols {
388                            expected: "Eval",
389                            got: "EvalApprove",
390                        });
391                    }
392                };
393
394                Ok(Self::TrackerFact {
395                    evaluation,
396                    validation,
397                })
398            }
399            (EventRequestType::Transfer, true)
400            | (EventRequestType::Transfer, false) => {
401                let evaluation = match actual_protocols {
402                    ActualProtocols::Eval { eval_data } => eval_data,
403                    ActualProtocols::None => {
404                        return Err(ProtocolsError::InvalidActualProtocols {
405                            expected: "Eval",
406                            got: "None",
407                        });
408                    }
409                    ActualProtocols::EvalApprove { .. } => {
410                        return Err(ProtocolsError::InvalidActualProtocols {
411                            expected: "Eval",
412                            got: "EvalApprove",
413                        });
414                    }
415                };
416
417                Ok(Self::Transfer {
418                    evaluation,
419                    validation,
420                })
421            }
422            (EventRequestType::Confirm, true) => {
423                let evaluation = match actual_protocols {
424                    ActualProtocols::Eval { eval_data } => eval_data,
425                    ActualProtocols::None => {
426                        return Err(ProtocolsError::InvalidActualProtocols {
427                            expected: "Eval",
428                            got: "None",
429                        });
430                    }
431                    ActualProtocols::EvalApprove { .. } => {
432                        return Err(ProtocolsError::InvalidActualProtocols {
433                            expected: "Eval",
434                            got: "EvalApprove",
435                        });
436                    }
437                };
438                Ok(Self::GovConfirm {
439                    evaluation,
440                    validation,
441                })
442            }
443            (EventRequestType::Confirm, false) => {
444                match actual_protocols {
445                    ActualProtocols::Eval { .. } => {
446                        return Err(ProtocolsError::InvalidActualProtocols {
447                            expected: "None",
448                            got: "Eval",
449                        });
450                    }
451                    ActualProtocols::EvalApprove { .. } => {
452                        return Err(ProtocolsError::InvalidActualProtocols {
453                            expected: "None",
454                            got: "EvalApprove",
455                        });
456                    }
457                    ActualProtocols::None => {}
458                }
459                Ok(Self::TrackerConfirm { validation })
460            }
461            (EventRequestType::Reject, true)
462            | (EventRequestType::Reject, false) => {
463                match actual_protocols {
464                    ActualProtocols::Eval { .. } => {
465                        return Err(ProtocolsError::InvalidActualProtocols {
466                            expected: "None",
467                            got: "Eval",
468                        });
469                    }
470                    ActualProtocols::EvalApprove { .. } => {
471                        return Err(ProtocolsError::InvalidActualProtocols {
472                            expected: "None",
473                            got: "EvalApprove",
474                        });
475                    }
476                    ActualProtocols::None => {}
477                }
478                Ok(Self::Reject { validation })
479            }
480            (EventRequestType::Eol, true) | (EventRequestType::Eol, false) => {
481                match actual_protocols {
482                    ActualProtocols::Eval { .. } => {
483                        return Err(ProtocolsError::InvalidActualProtocols {
484                            expected: "None",
485                            got: "Eval",
486                        });
487                    }
488                    ActualProtocols::EvalApprove { .. } => {
489                        return Err(ProtocolsError::InvalidActualProtocols {
490                            expected: "None",
491                            got: "EvalApprove",
492                        });
493                    }
494                    ActualProtocols::None => {}
495                }
496                Ok(Self::EOL { validation })
497            }
498            (EventRequestType::Create, _) => {
499                Err(ProtocolsError::InvalidEventRequestType {
500                    request_type: "Create",
501                    is_gov,
502                })
503            }
504        }
505    }
506}
507
508#[derive(
509    Debug, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize,
510)]
511pub struct Ledger {
512    pub event_request: Signed<EventRequest>,
513    pub gov_version: u64,
514    pub sn: u64,
515    pub prev_ledger_event_hash: DigestIdentifier,
516    pub protocols: Protocols,
517}
518
519impl Ledger {
520    pub fn get_subject_id(&self) -> DigestIdentifier {
521        if let Protocols::Create { validation } = &self.protocols
522            && let ValidationMetadata::Metadata(metadata) =
523                &validation.validation_metadata
524        {
525            metadata.subject_id.clone()
526        } else {
527            self.event_request.content().get_subject_id()
528        }
529    }
530
531    pub fn build_ledger_db(&self, signature_timestamp: u64) -> LedgerDB {
532        let (event, subject_id) =
533            self.protocols.buidl_event_db(self.event_request.content());
534
535        LedgerDB {
536            subject_id: subject_id.to_string(),
537            sn: self.sn,
538            event_request_timestamp: self
539                .event_request
540                .signature()
541                .timestamp
542                .as_nanos(),
543            event_ledger_timestamp: signature_timestamp,
544            sink_timestamp: TimeStamp::now().as_nanos(),
545            event_type: event.get_event_type(),
546            event,
547        }
548    }
549    pub fn get_create_metadata(&self) -> Result<Metadata, ProtocolsError> {
550        if let Protocols::Create { validation } = &self.protocols
551            && let ValidationMetadata::Metadata(metadata) =
552                &validation.validation_metadata
553        {
554            Ok(*metadata.clone())
555        } else {
556            Err(ProtocolsError::NotCreateWithMetadata)
557        }
558    }
559}