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#[async_trait]
74pub trait Verifier: Send + Sync {
75 async fn sync(&self, height: u64) -> Result<(), Error>;
77
78 async fn verify(
83 &self,
84 consensus_block: LightBlock,
85 runtime_header: Header,
86 epoch: EpochTime,
87 ) -> Result<ConsensusState, Error>;
88
89 async fn verify_for_query(
95 &self,
96 consensus_block: LightBlock,
97 runtime_header: Header,
98 epoch: EpochTime,
99 ) -> Result<ConsensusState, Error>;
100
101 async fn unverified_state(&self, consensus_block: LightBlock) -> Result<ConsensusState, Error>;
105
106 async fn latest_state(&self) -> Result<ConsensusState, Error>;
113
114 async fn state_at(&self, height: u64) -> Result<ConsensusState, Error>;
121
122 async fn events_at(&self, height: u64, kind: EventKind) -> Result<Vec<Event>, Error>;
129
130 async fn latest_height(&self) -> Result<u64, Error>;
132}
133
134#[async_trait]
135impl<T: ?Sized + Verifier> Verifier for Arc<T> {
136 async fn sync(&self, height: u64) -> Result<(), Error> {
137 Verifier::sync(&**self, height).await
138 }
139
140 async fn verify(
141 &self,
142 consensus_block: LightBlock,
143 runtime_header: Header,
144 epoch: EpochTime,
145 ) -> Result<ConsensusState, Error> {
146 Verifier::verify(&**self, consensus_block, runtime_header, epoch).await
147 }
148
149 async fn verify_for_query(
150 &self,
151 consensus_block: LightBlock,
152 runtime_header: Header,
153 epoch: EpochTime,
154 ) -> Result<ConsensusState, Error> {
155 Verifier::verify_for_query(&**self, consensus_block, runtime_header, epoch).await
156 }
157
158 async fn unverified_state(&self, consensus_block: LightBlock) -> Result<ConsensusState, Error> {
159 Verifier::unverified_state(&**self, consensus_block).await
160 }
161
162 async fn latest_state(&self) -> Result<ConsensusState, Error> {
163 Verifier::latest_state(&**self).await
164 }
165
166 async fn state_at(&self, height: u64) -> Result<ConsensusState, Error> {
167 Verifier::state_at(&**self, height).await
168 }
169
170 async fn events_at(&self, height: u64, kind: EventKind) -> Result<Vec<Event>, Error> {
171 Verifier::events_at(&**self, height, kind).await
172 }
173
174 async fn latest_height(&self) -> Result<u64, Error> {
175 Verifier::latest_height(&**self).await
176 }
177}
178
179#[derive(Debug, Clone, Default, PartialEq, Eq, cbor::Encode, cbor::Decode)]
181pub struct TrustRoot {
182 pub height: u64,
184 pub hash: String,
186 pub runtime_id: Namespace,
188 pub chain_context: String,
190}
191
192pub fn verify_state_freshness(
194 state: &ConsensusState,
195 identity: &Identity,
196 runtime_id: &Namespace,
197 version: &Version,
198 host_node_id: &PublicKey,
199) -> Result<(), Error> {
200 let registry_state = RegistryState::new(&state);
201
202 let node = registry_state.node(host_node_id).map_err(|err| {
203 Error::VerificationFailed(anyhow!(
204 "failed to retrieve node from the registry: {}",
205 err
206 ))
207 })?;
208 let node = node.ok_or_else(|| {
209 Error::VerificationFailed(anyhow!(
210 "own node ID '{}' not found in registry state",
211 host_node_id,
212 ))
213 })?;
214
215 if !node.has_tee(identity, runtime_id, version) {
216 return Err(Error::VerificationFailed(anyhow!(
217 "own identity not found in registry state"
218 )));
219 }
220
221 Ok(())
222}