oasis_core_runtime/consensus/
verifier.rs1use std::sync::Arc;
3
4use anyhow::anyhow;
5use async_trait::async_trait;
6use thiserror::Error;
7
8use super::{
9 beacon::EpochTime,
10 roothash::Header,
11 state::{registry::ImmutableState as RegistryState, ConsensusState},
12 Event, LightBlock,
13};
14use crate::{
15 common::{crypto::signature::PublicKey, namespace::Namespace, version::Version},
16 identity::Identity,
17 types::{self, EventKind},
18};
19
20#[derive(Debug, Error)]
21pub enum Error {
22 #[error("builder: {0}")]
23 Builder(#[source] anyhow::Error),
24
25 #[error("verification: {0}")]
26 VerificationFailed(#[source] anyhow::Error),
27
28 #[error("trusted state loading failed")]
29 TrustedStateLoadingFailed,
30
31 #[error("consensus chain context transition failed: {0}")]
32 ChainContextTransitionFailed(#[source] anyhow::Error),
33
34 #[error("freshness verification: {0}")]
35 FreshnessVerificationFailed(#[source] anyhow::Error),
36
37 #[error("transaction verification: {0}")]
38 TransactionVerificationFailed(#[source] anyhow::Error),
39
40 #[error("state root: {0}")]
41 StateRoot(#[source] anyhow::Error),
42
43 #[error("internal consensus verifier error")]
44 Internal,
45}
46
47impl Error {
48 fn code(&self) -> u32 {
49 match self {
50 Error::Builder(_) => 1,
51 Error::VerificationFailed(_) => 2,
52 Error::TrustedStateLoadingFailed => 3,
53 Error::ChainContextTransitionFailed(_) => 4,
54 Error::FreshnessVerificationFailed(_) => 5,
55 Error::TransactionVerificationFailed(_) => 6,
56 Error::StateRoot(_) => 7,
57 Error::Internal => 8,
58 }
59 }
60}
61
62impl From<Error> for types::Error {
63 fn from(e: Error) -> Self {
64 Self {
65 module: "verifier".to_string(),
66 code: e.code(),
67 message: e.to_string(),
68 }
69 }
70}
71
72#[allow(clippy::double_must_use)]
74#[async_trait]
75pub trait Verifier: Send + Sync {
76 async fn sync(&self, height: u64) -> Result<(), Error>;
78
79 async fn verify(
84 &self,
85 consensus_block: LightBlock,
86 runtime_header: Header,
87 epoch: EpochTime,
88 ) -> Result<ConsensusState, Error>;
89
90 async fn verify_for_query(
96 &self,
97 consensus_block: LightBlock,
98 runtime_header: Header,
99 epoch: EpochTime,
100 ) -> Result<ConsensusState, Error>;
101
102 async fn unverified_state(&self, consensus_block: LightBlock) -> Result<ConsensusState, Error>;
106
107 async fn latest_state(&self) -> Result<ConsensusState, Error>;
114
115 async fn state_at(&self, height: u64) -> Result<ConsensusState, Error>;
122
123 async fn events_at(&self, height: u64, kind: EventKind) -> Result<Vec<Event>, Error>;
130
131 async fn latest_height(&self) -> Result<u64, Error>;
133}
134
135#[allow(clippy::double_must_use)]
136#[async_trait]
137impl<T: ?Sized + Verifier> Verifier for Arc<T> {
138 async fn sync(&self, height: u64) -> Result<(), Error> {
139 Verifier::sync(&**self, height).await
140 }
141
142 async fn verify(
143 &self,
144 consensus_block: LightBlock,
145 runtime_header: Header,
146 epoch: EpochTime,
147 ) -> Result<ConsensusState, Error> {
148 Verifier::verify(&**self, consensus_block, runtime_header, epoch).await
149 }
150
151 async fn verify_for_query(
152 &self,
153 consensus_block: LightBlock,
154 runtime_header: Header,
155 epoch: EpochTime,
156 ) -> Result<ConsensusState, Error> {
157 Verifier::verify_for_query(&**self, consensus_block, runtime_header, epoch).await
158 }
159
160 async fn unverified_state(&self, consensus_block: LightBlock) -> Result<ConsensusState, Error> {
161 Verifier::unverified_state(&**self, consensus_block).await
162 }
163
164 async fn latest_state(&self) -> Result<ConsensusState, Error> {
165 Verifier::latest_state(&**self).await
166 }
167
168 async fn state_at(&self, height: u64) -> Result<ConsensusState, Error> {
169 Verifier::state_at(&**self, height).await
170 }
171
172 async fn events_at(&self, height: u64, kind: EventKind) -> Result<Vec<Event>, Error> {
173 Verifier::events_at(&**self, height, kind).await
174 }
175
176 async fn latest_height(&self) -> Result<u64, Error> {
177 Verifier::latest_height(&**self).await
178 }
179}
180
181#[derive(Debug, Clone, Default, PartialEq, Eq, cbor::Encode, cbor::Decode)]
183pub struct TrustRoot {
184 pub height: u64,
186 pub hash: String,
188 pub runtime_id: Namespace,
190 pub chain_context: String,
192}
193
194pub fn verify_state_freshness(
196 state: &ConsensusState,
197 identity: &Identity,
198 runtime_id: &Namespace,
199 version: &Version,
200 host_node_id: &PublicKey,
201) -> Result<(), Error> {
202 let registry_state = RegistryState::new(&state);
203
204 let node = registry_state.node(host_node_id).map_err(|err| {
205 Error::VerificationFailed(anyhow!(
206 "failed to retrieve node from the registry: {}",
207 err
208 ))
209 })?;
210 let node = node.ok_or_else(|| {
211 Error::VerificationFailed(anyhow!(
212 "own node ID '{}' not found in registry state",
213 host_node_id,
214 ))
215 })?;
216
217 if !node.has_tee(identity, runtime_id, version) {
218 return Err(Error::VerificationFailed(anyhow!(
219 "own identity not found in registry state"
220 )));
221 }
222
223 Ok(())
224}