lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

verification.rs (6986B)


      1 #[cfg(not(feature = "std"))]
      2 use alloc::string::{String, ToString};
      3 
      4 use core::fmt;
      5 
      6 use radroots_event::contract::ContractValidationError;
      7 use radroots_event::envelope::EventEnvelope;
      8 use radroots_event::knowledge::{
      9     ContributionAttestation, EvidenceBounty, KnowledgeChangeProposal, KnowledgeClaim,
     10     KnowledgeFieldReport, KnowledgeRelation, KnowledgeReview, KnowledgeSource, WikiArticle,
     11     WikiMergeRequest, WikiRedirect,
     12 };
     13 
     14 use crate::error::EventParseError;
     15 use crate::knowledge::decode::{
     16     contribution_attestation_from_event, evidence_bounty_from_event,
     17     knowledge_change_proposal_from_event, knowledge_claim_from_event,
     18     knowledge_field_report_from_event, knowledge_relation_from_event, knowledge_review_from_event,
     19     knowledge_source_from_event, wiki_article_from_event, wiki_merge_request_from_event,
     20     wiki_redirect_from_event,
     21 };
     22 use crate::parsed::RadrootsParsedEvent;
     23 pub use crate::verification::{RadrootsContractValidatedEvent, validate_event_contract};
     24 use crate::verification::{RadrootsNip01VerificationError, verify_nip01_event};
     25 
     26 #[derive(Debug)]
     27 pub enum RadrootsDecodeError {
     28     Nip01Verification(RadrootsNip01VerificationError),
     29     ContractValidation(ContractValidationError),
     30     EventParse(EventParseError),
     31     UnsupportedContract { contract_id: String },
     32 }
     33 
     34 impl RadrootsDecodeError {
     35     pub const fn code(&self) -> &'static str {
     36         match self {
     37             Self::Nip01Verification(_) => "nip01_verification",
     38             Self::ContractValidation(_) => "contract_validation",
     39             Self::EventParse(_) => "event_parse",
     40             Self::UnsupportedContract { .. } => "unsupported_contract",
     41         }
     42     }
     43 }
     44 
     45 impl fmt::Display for RadrootsDecodeError {
     46     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
     47         match self {
     48             Self::Nip01Verification(error) => write!(formatter, "{error}"),
     49             Self::ContractValidation(error) => {
     50                 write!(
     51                     formatter,
     52                     "contract validation failed with code {}",
     53                     error.code()
     54                 )
     55             }
     56             Self::EventParse(error) => write!(formatter, "{error}"),
     57             Self::UnsupportedContract { contract_id } => {
     58                 write!(formatter, "unsupported event contract `{contract_id}`")
     59             }
     60         }
     61     }
     62 }
     63 
     64 #[cfg(feature = "std")]
     65 impl std::error::Error for RadrootsDecodeError {}
     66 
     67 impl From<EventParseError> for RadrootsDecodeError {
     68     fn from(value: EventParseError) -> Self {
     69         Self::EventParse(value)
     70     }
     71 }
     72 
     73 impl From<RadrootsNip01VerificationError> for RadrootsDecodeError {
     74     fn from(value: RadrootsNip01VerificationError) -> Self {
     75         Self::Nip01Verification(value)
     76     }
     77 }
     78 
     79 impl From<ContractValidationError> for RadrootsDecodeError {
     80     fn from(value: ContractValidationError) -> Self {
     81         Self::ContractValidation(value)
     82     }
     83 }
     84 
     85 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
     86 #[derive(Clone, Debug)]
     87 pub enum RadrootsDecodedEvent {
     88     WikiArticle(RadrootsParsedEvent<WikiArticle>),
     89     WikiRedirect(RadrootsParsedEvent<WikiRedirect>),
     90     WikiMergeRequest(RadrootsParsedEvent<WikiMergeRequest>),
     91     KnowledgeSource(RadrootsParsedEvent<KnowledgeSource>),
     92     KnowledgeClaim(RadrootsParsedEvent<KnowledgeClaim>),
     93     KnowledgeRelation(RadrootsParsedEvent<KnowledgeRelation>),
     94     KnowledgeReview(RadrootsParsedEvent<KnowledgeReview>),
     95     KnowledgeFieldReport(RadrootsParsedEvent<KnowledgeFieldReport>),
     96     EvidenceBounty(RadrootsParsedEvent<EvidenceBounty>),
     97     KnowledgeChangeProposal(RadrootsParsedEvent<KnowledgeChangeProposal>),
     98     ContributionAttestation(RadrootsParsedEvent<ContributionAttestation>),
     99 }
    100 
    101 impl RadrootsDecodedEvent {
    102     pub fn event(&self) -> &EventEnvelope {
    103         match self {
    104             Self::WikiArticle(parsed) => &parsed.event,
    105             Self::WikiRedirect(parsed) => &parsed.event,
    106             Self::WikiMergeRequest(parsed) => &parsed.event,
    107             Self::KnowledgeSource(parsed) => &parsed.event,
    108             Self::KnowledgeClaim(parsed) => &parsed.event,
    109             Self::KnowledgeRelation(parsed) => &parsed.event,
    110             Self::KnowledgeReview(parsed) => &parsed.event,
    111             Self::KnowledgeFieldReport(parsed) => &parsed.event,
    112             Self::EvidenceBounty(parsed) => &parsed.event,
    113             Self::KnowledgeChangeProposal(parsed) => &parsed.event,
    114             Self::ContributionAttestation(parsed) => &parsed.event,
    115         }
    116     }
    117 }
    118 
    119 pub fn decode_validated_event(
    120     event: RadrootsContractValidatedEvent,
    121 ) -> Result<RadrootsDecodedEvent, RadrootsDecodeError> {
    122     let contract_id = event.contract_id();
    123     let event = event.into_event();
    124     match contract_id {
    125         "radroots.wiki.article.v1" => Ok(RadrootsDecodedEvent::WikiArticle(
    126             wiki_article_from_event(event)?,
    127         )),
    128         "radroots.wiki.redirect.v1" => Ok(RadrootsDecodedEvent::WikiRedirect(
    129             wiki_redirect_from_event(event)?,
    130         )),
    131         "radroots.wiki.merge_request.v1" => Ok(RadrootsDecodedEvent::WikiMergeRequest(
    132             wiki_merge_request_from_event(event)?,
    133         )),
    134         "radroots.knowledge.source.v1" => Ok(RadrootsDecodedEvent::KnowledgeSource(
    135             knowledge_source_from_event(event)?,
    136         )),
    137         "radroots.knowledge.claim.v1" => Ok(RadrootsDecodedEvent::KnowledgeClaim(
    138             knowledge_claim_from_event(event)?,
    139         )),
    140         "radroots.knowledge.relation.v1" => Ok(RadrootsDecodedEvent::KnowledgeRelation(
    141             knowledge_relation_from_event(event)?,
    142         )),
    143         "radroots.knowledge.review.v1" => Ok(RadrootsDecodedEvent::KnowledgeReview(
    144             knowledge_review_from_event(event)?,
    145         )),
    146         "radroots.knowledge.field_report.v1" => Ok(RadrootsDecodedEvent::KnowledgeFieldReport(
    147             knowledge_field_report_from_event(event)?,
    148         )),
    149         "radroots.knowledge.evidence_bounty.v1" => Ok(RadrootsDecodedEvent::EvidenceBounty(
    150             evidence_bounty_from_event(event)?,
    151         )),
    152         "radroots.knowledge.change_proposal.v1" => {
    153             Ok(RadrootsDecodedEvent::KnowledgeChangeProposal(
    154                 knowledge_change_proposal_from_event(event)?,
    155             ))
    156         }
    157         "radroots.knowledge.contribution_attestation.v1" => {
    158             Ok(RadrootsDecodedEvent::ContributionAttestation(
    159                 contribution_attestation_from_event(event)?,
    160             ))
    161         }
    162         contract_id => Err(RadrootsDecodeError::UnsupportedContract {
    163             contract_id: contract_id.to_string(),
    164         }),
    165     }
    166 }
    167 
    168 /// Verifies NIP-01 identity before applying the knowledge contract and decoder.
    169 pub fn verify_and_decode_radroots_event(
    170     event: EventEnvelope,
    171 ) -> Result<RadrootsDecodedEvent, RadrootsDecodeError> {
    172     let verified = verify_nip01_event(event)?;
    173     let contract_validated = validate_event_contract(verified)?;
    174     decode_validated_event(contract_validated)
    175 }