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::{
13 types::{LightBlock as RawLightBlock, ValidatorSet as RawValidatorSet},
14 Protobuf,
15};
16
17use crate::{
18 common::{crypto::hash::Hash, namespace::Namespace},
19 consensus::{LightBlock, Validators},
20 storage::mkvs::{Root, RootType},
21};
22
23pub const BACKEND_NAME: &str = "tendermint";
26
27pub const TENDERMINT_CONTEXT: &[u8] = b"oasis-core/tendermint";
30
31pub fn chain_id(chain_context: &str) -> chain::Id {
33 chain_context[..chain::id::MAX_LENGTH].try_into().unwrap()
34}
35
36pub fn decode_light_block(light_block: LightBlock) -> Result<LightBlockMeta> {
38 LightBlockMeta::decode_vec(&light_block.meta).map_err(|e| anyhow!("{}", e))
39}
40
41pub fn encode_light_block(light_block_meta: LightBlockMeta) -> Result<LightBlock> {
43 let height = u64::from(
44 light_block_meta
45 .signed_header
46 .as_ref()
47 .ok_or_else(|| anyhow!("signed header should be present"))?
48 .header
49 .height,
50 );
51 let meta = LightBlockMeta::encode_vec(light_block_meta);
52
53 Ok(LightBlock { height, meta })
54}
55
56pub fn decode_validators(validators: Validators) -> Result<TMValidatorSet> {
58 Protobuf::<RawValidatorSet>::decode_vec(&validators.meta).map_err(|e| anyhow!("{}", e))
59}
60
61pub fn state_root_from_header(signed_header: &TMSignedHeader) -> Root {
68 let header = signed_header.header();
69 let height: u64 = header.height.into();
70 let hash: [u8; 32] = header
71 .app_hash
72 .as_bytes()
73 .try_into()
74 .expect("invalid app hash");
75
76 Root {
77 namespace: Namespace::default(),
78 version: height - 1,
79 root_type: RootType::State,
80 hash: Hash(hash),
81 }
82}
83
84#[derive(Debug, Clone)]
86pub struct LightBlockMeta {
87 pub signed_header: Option<TMSignedHeader>,
88 pub validators: TMValidatorSet,
89}
90
91impl LightBlockMeta {
92 pub fn get_state_root(&self) -> Root {
99 let header = self
100 .signed_header
101 .as_ref()
102 .expect("signed header should be present");
103
104 state_root_from_header(header)
105 }
106}
107
108impl Protobuf<RawLightBlock> for LightBlockMeta {}
109
110impl TryFrom<RawLightBlock> for LightBlockMeta {
111 type Error = anyhow::Error;
112
113 fn try_from(value: RawLightBlock) -> Result<Self> {
114 Ok(LightBlockMeta {
115 signed_header: value
116 .signed_header
117 .map(TryInto::try_into)
118 .transpose()
119 .map_err(|error| anyhow!("{}", error))?,
120 validators: value
121 .validator_set
122 .ok_or_else(|| anyhow!("missing validator set"))?
123 .try_into()
124 .map_err(|error| anyhow!("{}", error))?,
125 })
126 }
127}
128
129impl From<LightBlockMeta> for RawLightBlock {
130 fn from(value: LightBlockMeta) -> Self {
131 RawLightBlock {
132 signed_header: value.signed_header.map(Into::into),
133 validator_set: Some(value.validators.into()),
134 }
135 }
136}