oasis_core_runtime/consensus/tendermint/
mod.rs1pub mod merkle;
4pub mod verifier;
5
6use std::convert::{TryFrom, TryInto};
7
8use anyhow::{anyhow, Result};
9use tendermint::{
10 block::signed_header::SignedHeader as TMSignedHeader, chain, validator::Set as TMValidatorSet,
11};
12use tendermint_proto::{types::LightBlock as RawLightBlock, Protobuf};
13
14use crate::{
15 common::{crypto::hash::Hash, namespace::Namespace},
16 consensus::LightBlock,
17 storage::mkvs::{Root, RootType},
18};
19
20pub const BACKEND_NAME: &str = "tendermint";
23
24pub const TENDERMINT_CONTEXT: &[u8] = b"oasis-core/tendermint";
27
28pub fn chain_id(chain_context: &str) -> chain::Id {
30 chain_context[..chain::id::MAX_LENGTH].try_into().unwrap()
31}
32
33pub fn decode_light_block(light_block: LightBlock) -> Result<LightBlockMeta> {
35 LightBlockMeta::decode_vec(&light_block.meta).map_err(|e| anyhow!("{}", e))
36}
37
38pub fn encode_light_block(light_block_meta: LightBlockMeta) -> Result<LightBlock> {
40 let height = u64::from(
41 light_block_meta
42 .signed_header
43 .as_ref()
44 .ok_or_else(|| anyhow!("signed header should be present"))?
45 .header
46 .height,
47 );
48 let meta = LightBlockMeta::encode_vec(light_block_meta);
49
50 Ok(LightBlock { height, meta })
51}
52
53pub fn state_root_from_header(signed_header: &TMSignedHeader) -> Root {
60 let header = signed_header.header();
61 let height: u64 = header.height.into();
62 let hash: [u8; 32] = header
63 .app_hash
64 .as_bytes()
65 .try_into()
66 .expect("invalid app hash");
67
68 Root {
69 namespace: Namespace::default(),
70 version: height - 1,
71 root_type: RootType::State,
72 hash: Hash(hash),
73 }
74}
75
76#[derive(Debug, Clone)]
78pub struct LightBlockMeta {
79 pub signed_header: Option<TMSignedHeader>,
80 pub validators: TMValidatorSet,
81}
82
83impl LightBlockMeta {
84 pub fn get_state_root(&self) -> Root {
91 let header = self
92 .signed_header
93 .as_ref()
94 .expect("signed header should be present");
95
96 state_root_from_header(header)
97 }
98}
99
100impl Protobuf<RawLightBlock> for LightBlockMeta {}
101
102impl TryFrom<RawLightBlock> for LightBlockMeta {
103 type Error = anyhow::Error;
104
105 fn try_from(value: RawLightBlock) -> Result<Self> {
106 Ok(LightBlockMeta {
107 signed_header: value
108 .signed_header
109 .map(TryInto::try_into)
110 .transpose()
111 .map_err(|error| anyhow!("{}", error))?,
112 validators: value
113 .validator_set
114 .ok_or_else(|| anyhow!("missing validator set"))?
115 .try_into()
116 .map_err(|error| anyhow!("{}", error))?,
117 })
118 }
119}
120
121impl From<LightBlockMeta> for RawLightBlock {
122 fn from(value: LightBlockMeta) -> Self {
123 RawLightBlock {
124 signed_header: value.signed_header.map(Into::into),
125 validator_set: Some(value.validators.into()),
126 }
127 }
128}