Skip to content

Commit

Permalink
runtime/src/consensus/tendermint/verifier: Modify trust root storage key
Browse files Browse the repository at this point in the history
The Tendermint verifier now stores the trusted root under a key derived
from the enclave's identity and the runtime version. Relying solely
on the identity is not sufficient, as on non-SGX platforms, the identity
is set to the default value, causing new runtimes in the upgrade tests
to use trusted roots from the previous versions, which may not even
be compatible.
  • Loading branch information
peternose committed Jul 18, 2023
1 parent 0c6cf3c commit 8f34ee2
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 9 deletions.
Empty file added .changelog/5324.trivial.md
Empty file.
10 changes: 7 additions & 3 deletions runtime/src/consensus/tendermint/verifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,9 @@ impl Verifier {
// Build a light client using the embedded trust root or trust root
// stored in the local store.
info!(self.logger, "Loading trusted state");
let trusted_state: TrustedState = self.trusted_state_store.load(&self.trust_root)?;
let trusted_state: TrustedState = self
.trusted_state_store
.load(self.runtime_version, &self.trust_root)?;

// Verify if we can trust light blocks from a new chain if the consensus
// chain context changes.
Expand Down Expand Up @@ -696,7 +698,8 @@ impl Verifier {
// processing any requests.
let verified_block = self.verify_to_target(HEIGHT_LATEST, &mut cache, &mut instance)?;

self.trusted_state_store.save(&instance.state.light_store);
self.trusted_state_store
.save(self.runtime_version, &instance.state.light_store);

let mut last_saved_verified_block_height =
verified_block.signed_header.header.height.value();
Expand Down Expand Up @@ -770,7 +773,8 @@ impl Verifier {
if let Some(last_verified_block) = cache.last_verified_block.as_ref() {
let last_height = last_verified_block.signed_header.header.height.into();
if last_height - last_saved_verified_block_height > TRUSTED_STATE_SAVE_INTERVAL {
self.trusted_state_store.save(&instance.state.light_store);
self.trusted_state_store
.save(self.runtime_version, &instance.state.light_store);
last_saved_verified_block_height = last_height;
}
}
Expand Down
18 changes: 12 additions & 6 deletions runtime/src/consensus/tendermint/verifier/store/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
common::{
namespace::Namespace,
sgx::{seal, EnclaveIdentity},
version::Version,
},
consensus::verifier::{Error, TrustRoot},
protocol::ProtocolUntrustedLocalStorage,
Expand Down Expand Up @@ -93,7 +94,7 @@ impl TrustedStateStore {
///
/// Panics in case the light store does not have any blocks or if insertion to the underlying
/// runtime's untrusted local store fails.
pub fn save(&self, store: &Box<dyn LightStore>) {
pub fn save(&self, runtime_version: Version, store: &Box<dyn LightStore>) {
let lowest_block = store.lowest(Status::Trusted).unwrap();
let highest_block = store.highest(Status::Trusted).unwrap();

Expand All @@ -116,18 +117,22 @@ impl TrustedStateStore {

// Store the trusted state.
self.untrusted_local_store
.insert(Self::derive_storage_key(), sealed)
.insert(Self::derive_storage_key(runtime_version), sealed)
.unwrap();
}

/// Attempts to load previously sealed trusted state.
///
/// If no sealed trusted state is available, it returns state based on the passed trust root.
pub fn load(&self, trust_root: &TrustRoot) -> Result<TrustedState, Error> {
pub fn load(
&self,
runtime_version: Version,
trust_root: &TrustRoot,
) -> Result<TrustedState, Error> {
// Attempt to load the previously sealed trusted state.
let untrusted_value = self
.untrusted_local_store
.get(Self::derive_storage_key())
.get(Self::derive_storage_key(runtime_version))
.map_err(|_| Error::TrustedStateLoadingFailed)?;
if untrusted_value.is_empty() {
return Ok(TrustedState {
Expand All @@ -149,13 +154,14 @@ impl TrustedStateStore {
Ok(trusted_state)
}

fn derive_storage_key() -> Vec<u8> {
fn derive_storage_key(runtime_version: Version) -> Vec<u8> {
// Namespace storage key by MRENCLAVE as we can only unseal our own sealed data and we need
// to support upgrades. We assume that an upgrade will include an up-to-date trusted state
// anyway.
format!(
"{}.{:x}",
"{}.{}.{:x}",
TRUSTED_STATE_STORAGE_KEY_PREFIX,
u64::from(runtime_version),
EnclaveIdentity::current()
.map(|eid| eid.mr_enclave)
.unwrap_or_default()
Expand Down

0 comments on commit 8f34ee2

Please sign in to comment.