oasis_core_runtime/consensus/state/keymanager/
churp.rs1use anyhow::anyhow;
3
4use crate::{
5 common::{
6 crypto::hash::Hash,
7 key_format::{KeyFormat, KeyFormatAtom},
8 namespace::Namespace,
9 },
10 consensus::{keymanager::churp::Status, state::StateError},
11 key_format,
12 storage::mkvs::ImmutableMKVS,
13};
14
15key_format!(StatusKeyFmt, 0x75, (Hash, u8));
16
17pub struct ImmutableState<'a, T: ImmutableMKVS> {
19 mkvs: &'a T,
20}
21
22impl<'a, T: ImmutableMKVS> ImmutableState<'a, T> {
23 pub fn new(mkvs: &'a T) -> ImmutableState<'a, T> {
25 ImmutableState { mkvs }
26 }
27}
28
29impl<'a, T: ImmutableMKVS> ImmutableState<'a, T> {
30 pub fn status(
32 &self,
33 runtime_id: Namespace,
34 churp_id: u8,
35 ) -> Result<Option<Status>, StateError> {
36 let h = Hash::digest_bytes(runtime_id.as_ref());
37 match self.mkvs.get(&StatusKeyFmt((h, churp_id)).encode()) {
38 Ok(Some(b)) => Ok(Some(self.decode_status(&b)?)),
39 Ok(None) => Ok(None),
40 Err(err) => Err(StateError::Unavailable(anyhow!(err))),
41 }
42 }
43
44 fn decode_status(&self, data: &[u8]) -> Result<Status, StateError> {
45 cbor::from_slice(data).map_err(|err| StateError::Unavailable(anyhow!(err)))
46 }
47}
48
49#[cfg(test)]
50mod test {
51 use std::collections::HashMap;
52
53 use super::*;
54 use crate::{
55 common::{
56 crypto::signature::{PublicKey, Signature, SignatureBundle},
57 sgx::{EnclaveIdentity, MrEnclave, MrSigner},
58 },
59 consensus::keymanager::churp::{Application, PolicySGX, SignedPolicySGX, SuiteId},
60 storage::mkvs::{
61 interop::{Fixture, ProtocolServer},
62 Root, RootType, Tree,
63 },
64 };
65
66 #[test]
67 fn test_keymanager_secrets_state_interop() {
68 let server = ProtocolServer::new(Fixture::ConsensusMock.into());
76 let mock_consensus_root = Root {
77 version: 1,
78 root_type: RootType::State,
79 hash: Hash::from("8e39bf193f8a954ab8f8d7cb6388c591fd0785ea060bbd8e3752e266b54499d3"),
80 ..Default::default()
81 };
82 let mkvs = Tree::builder()
83 .with_capacity(100_000, 10_000_000)
84 .with_root(mock_consensus_root)
85 .build(server.read_sync());
86 let state = ImmutableState::new(&mkvs);
87
88 let runtime_id =
90 Namespace::from("8000000000000000000000000000000000000000000000000000000000000000");
91 let enclave1 = EnclaveIdentity {
92 mr_enclave: MrEnclave::from(
93 "c9a589851b1f35627177fd70378ed778170f737611e4dfbf0b6d25bdff55b474",
94 ),
95 mr_signer: MrSigner::from(
96 "7d310664780931ae103ab30a90171c201af385a72757bb4683578fdebde9adf5",
97 ),
98 };
99 let enclave2 = EnclaveIdentity {
100 mr_enclave: MrEnclave::from(
101 "756eaf76f5482c5345808b1eaccdd5c60f864bb2aa2d2b870df00ce435af4e23",
102 ),
103 mr_signer: MrSigner::from(
104 "3597a2ff0743016f28e5d7e129304ee1c43dbdae3dba94e19cee3549038a5a32",
105 ),
106 };
107 let signer1 =
108 PublicKey::from("96533c123a6f4d33c68357109c2eb7c6e6a0f947be3ae1e320d153f561523ff2");
109 let signer2 =
110 PublicKey::from("4b97bfd95e829d5838131492b5c133e66ac6ef0db414c0be6207ec78c12d2b17");
111 let sig1 = Signature::from("eda666cff6e4030200737e0c7707ad4a378aab4cc0455306992c13da2155b97c91b0fde0325a7a6818f2cbf92813cc587723c8c205a7cb5389ca7b21a038b60a");
112 let sig2 = Signature::from("db90d354272e025aa9a5856f32ea4f5d6becb0ff6340f3cb7f9104ac04ef29ed4f9b5c21b7ea82924800b30f94724b40c376414f80780ff8b7b60a34edea9f02");
113 let checksum =
114 Hash::from("1bff211fae98c88ba82388ae954b88a71d3bbe327e162e9fa711fe7a1b759c3e");
115 let committee = vec![signer1, signer2];
116 let mut applications = HashMap::new();
117 applications.insert(
118 signer1,
119 Application {
120 checksum: checksum.clone(),
121 reconstructed: false,
122 },
123 );
124 applications.insert(
125 signer2,
126 Application {
127 checksum: checksum.clone(),
128 reconstructed: true,
129 },
130 );
131 let checksum = Some(checksum);
132 let next_checksum = checksum;
133
134 let status = Status {
136 ..Default::default()
137 };
138
139 let status = state
140 .status(status.runtime_id, status.id)
141 .expect("status query should work")
142 .expect("status query should return a result");
143 assert_eq!(status, status, "invalid status");
144
145 let status = Status {
147 id: 1,
148 runtime_id,
149 suite_id: SuiteId::NistP384Sha3_384,
150 threshold: 2,
151 extra_shares: 1,
152 handoff_interval: 3,
153 policy: SignedPolicySGX {
154 policy: PolicySGX {
155 id: 1,
156 runtime_id,
157 serial: 6,
158 may_share: vec![enclave1],
159 may_join: vec![enclave2],
160 may_query: HashMap::new(),
161 },
162 signatures: vec![
163 SignatureBundle {
164 public_key: signer1,
165 signature: sig1,
166 },
167 SignatureBundle {
168 public_key: signer2,
169 signature: sig2,
170 },
171 ],
172 },
173 handoff: 4,
174 checksum,
175 committee,
176 next_handoff: 5,
177 next_checksum,
178 applications,
179 };
180
181 let status = state
182 .status(status.runtime_id, status.id)
183 .expect("status query should work")
184 .expect("status query should return a result");
185 assert_eq!(status, status, "invalid status");
186 }
187}