oasis_core_runtime/consensus/tendermint/verifier/
predicates.rs1use anyhow::anyhow;
2
3use crate::{
4 common::namespace::Namespace,
5 consensus::{
6 beacon::EpochTime,
7 roothash::Header,
8 state::{
9 beacon::ImmutableState as BeaconState, roothash::ImmutableState as RoothashState,
10 ConsensusState,
11 },
12 tendermint::{verifier::Cache, LightBlockMeta},
13 verifier::Error,
14 LightBlock,
15 },
16};
17
18pub fn verify_namespace(trusted: Namespace, runtime_header: &Header) -> Result<(), Error> {
20 if trusted != runtime_header.namespace {
21 return Err(Error::VerificationFailed(anyhow!(
22 "header namespace does not match trusted runtime id"
23 )));
24 }
25
26 Ok(())
27}
28
29pub fn verify_consensus_advance(cache: &Cache, consensus_block: &LightBlock) -> Result<(), Error> {
31 if consensus_block.height < cache.last_verified_height {
32 return Err(Error::VerificationFailed(anyhow!(
34 "height seems to have moved backwards"
35 )));
36 }
37
38 Ok(())
39}
40
41pub fn verify_round_advance(
43 cache: &Cache,
44 runtime_header: &Header,
45 consensus_block: &LightBlock,
46 epoch: EpochTime,
47) -> Result<(), Error> {
48 if runtime_header.round < cache.last_verified_round {
49 return Err(Error::VerificationFailed(anyhow!(
51 "round seems to have moved backwards"
52 )));
53 }
54 if epoch < cache.last_verified_epoch {
55 return Err(Error::VerificationFailed(anyhow!(
57 "epoch seems to have moved backwards"
58 )));
59 }
60
61 if runtime_header.round > cache.last_verified_round
65 && consensus_block.height <= cache.last_verified_height
66 {
67 return Err(Error::VerificationFailed(anyhow!(
68 "consensus height did not advance but runtime round did"
69 )));
70 }
71
72 Ok(())
73}
74
75pub fn verify_time(runtime_header: &Header, consensus_block: &LightBlockMeta) -> Result<(), Error> {
77 let consensus_header = &consensus_block
78 .signed_header
79 .as_ref()
80 .ok_or_else(|| Error::VerificationFailed(anyhow!("missing signed header")))?
81 .header;
82 if runtime_header.timestamp != consensus_header.time.unix_timestamp() as u64 {
83 return Err(Error::VerificationFailed(anyhow!(
84 "runtime block timestamp inconsistent with consensus time"
85 )));
86 }
87
88 Ok(())
89}
90
91pub fn verify_state_root(state: &ConsensusState, runtime_header: &Header) -> Result<(), Error> {
95 let roothash_state = RoothashState::new(&state);
96 let state_root = roothash_state
97 .state_root(runtime_header.namespace)
98 .map_err(|err| {
99 Error::VerificationFailed(anyhow!("failed to retrieve trusted state root: {}", err))
100 })?;
101
102 if runtime_header.state_root != state_root {
103 return Err(Error::VerificationFailed(anyhow!(
104 "state root mismatch (expected: {} got: {})",
105 state_root,
106 runtime_header.state_root
107 )));
108 }
109
110 Ok(())
111}
112
113pub fn verify_epoch(state: &ConsensusState, epoch: EpochTime) -> Result<(), Error> {
115 let beacon_state = BeaconState::new(&state);
116 let current_epoch = beacon_state
117 .epoch()
118 .map_err(|err| Error::VerificationFailed(anyhow!("failed to retrieve epoch: {}", err)))?;
119
120 if current_epoch != epoch {
121 return Err(Error::VerificationFailed(anyhow!(
122 "epoch number mismatch (expected: {} got: {})",
123 current_epoch,
124 epoch,
125 )));
126 }
127
128 Ok(())
129}