1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Consensus state wrappers.
use std::sync::Arc;

use anyhow::{Error, Result};
use thiserror::Error;

use crate::{
    protocol::Protocol,
    storage::mkvs::{sync::HostReadSyncer, ImmutableMKVS, Root, Tree},
    types::{self, HostStorageEndpoint},
};

pub mod beacon;
pub mod keymanager;
pub mod registry;
pub mod roothash;
pub mod staking;

#[derive(Error, Debug)]
pub enum StateError {
    #[error("consensus state: unavailable/corrupted state")]
    Unavailable(#[from] Error),
}

impl From<StateError> for types::Error {
    fn from(e: StateError) -> Self {
        Self {
            module: "consensus".to_string(),
            code: 1,
            message: e.to_string(),
        }
    }
}

/// Provides consensus state tree from the host.
pub struct ConsensusState {
    // An explicit height field is needed because the relationship between the underlying consensus
    // height and the corresponding state root is a consensus backend implementation detail.
    height: u64,
    mkvs: Tree,
}

impl ConsensusState {
    /// Creates a consensus state wrapping the provided tree.
    pub fn new(height: u64, tree: Tree) -> Self {
        Self { height, mkvs: tree }
    }

    /// Creates consensus state using host protocol.
    pub fn from_protocol(protocol: Arc<Protocol>, height: u64, root: Root) -> Self {
        let read_syncer = HostReadSyncer::new(protocol, HostStorageEndpoint::Consensus);
        Self {
            height,
            mkvs: Tree::builder()
                .with_capacity(100_000, 10_000_000)
                .with_root(root)
                .build(Box::new(read_syncer)),
        }
    }

    /// Consensus layer height that this data is for.
    pub fn height(&self) -> u64 {
        self.height
    }
}

impl ImmutableMKVS for ConsensusState {
    fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
        self.mkvs.get(key)
    }

    fn prefetch_prefixes(
        &self,
        prefixes: &[crate::storage::mkvs::Prefix],
        limit: u16,
    ) -> Result<()> {
        self.mkvs.prefetch_prefixes(prefixes, limit)
    }

    fn iter(&self) -> Box<dyn crate::storage::mkvs::Iterator + '_> {
        Box::new(self.mkvs.iter())
    }
}

impl ImmutableMKVS for &ConsensusState {
    fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
        self.mkvs.get(key)
    }

    fn prefetch_prefixes(
        &self,
        prefixes: &[crate::storage::mkvs::Prefix],
        limit: u16,
    ) -> Result<()> {
        self.mkvs.prefetch_prefixes(prefixes, limit)
    }

    fn iter(&self) -> Box<dyn crate::storage::mkvs::Iterator + '_> {
        Box::new(self.mkvs.iter())
    }
}