1use 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}