Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
99afeb2
[itc-light-client] light-client db is now a generic parameter to faci…
clangenb Apr 24, 2023
317045b
[itc-light-client] fix import paths
clangenb Apr 24, 2023
89bed89
[itc-light-client] add no-genesis error, which was lost in rebase
clangenb Apr 26, 2023
d319b8c
[itc-light-client] `LightClientSeal` does no longer refer to a static…
clangenb Apr 26, 2023
cdd09b1
[itc-light-client] remove obsolete fixme
clangenb Apr 26, 2023
93b9473
[itc-light-client] better naming for generic type parameter
clangenb Apr 26, 2023
98318f5
Cargo.lock
clangenb Apr 26, 2023
f5b25fc
[itc-parentchain-light-client] fix test compilation
clangenb Apr 26, 2023
8857420
[itc-parentchain-light-client] fix `cargo test -p itc-parentchain-lig…
clangenb May 6, 2023
524e809
add sgx compatible temp-dir implementation
clangenb May 6, 2023
5fac89e
[itc-parentchain-light-client] the path is now a `Path` instead of a …
clangenb May 6, 2023
d0164a2
[itp-sgx-tempdir] add process-id like behaviour
clangenb May 6, 2023
12d01f6
[itc-parentchain-light-client] fix: enable std feature in sgx-temp-dir.
clangenb May 6, 2023
b18b4c5
more accurate docs.
clangenb May 6, 2023
4ad3269
typos
clangenb May 6, 2023
e9ab9d8
add doc
clangenb May 6, 2023
12ba016
fix clippy
clangenb May 6, 2023
07df91a
taplo fmt
clangenb May 6, 2023
d53bbe3
add debug logs for CI
clangenb May 6, 2023
74554e0
[itp-test] better re-exports
clangenb May 6, 2023
b60cdef
[itc-parentchain-test] better re-exports
clangenb May 6, 2023
940b4ce
[itc-parentchain-light-client] add seal test
clangenb May 6, 2023
828b562
[itc-parentchain-light-client] fix seal test
clangenb May 6, 2023
90856b4
[itc-parentchain-light-client] better naming
clangenb May 6, 2023
ca5771e
add todo for more light-client tests
clangenb May 6, 2023
4d2f3dd
Revert "add debug logs for CI"
clangenb May 6, 2023
9a16378
taplo fmt
clangenb May 6, 2023
a7eac03
Merge branch 'master' into cl/configurable-light-client-db
clangenb May 8, 2023
c03b5c4
[itc-parentchain-light-client] use `PathBuf` instead of `Box<Path>`
clangenb May 9, 2023
f87991a
add temp-dir deprecation note
clangenb May 9, 2023
fe23875
Merge branch 'master' into cl/configurable-light-client-db
clangenb May 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3090,7 +3090,6 @@ dependencies = [
"hash-db",
"itc-parentchain-test",
"itp-ocall-api",
"itp-settings",
"itp-sgx-io",
"itp-storage",
"itp-test",
Expand Down
1 change: 0 additions & 1 deletion core/parentchain/light-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ thiserror-sgx = { package = "thiserror", git = "https://github.com/mesalock-linu

# local deps
itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false }
itp-settings = { path = "../../../core-primitives/settings" }
itp-sgx-io = { path = "../../../core-primitives/sgx/io", default-features = false }
itp-storage = { path = "../../../core-primitives/storage", default-features = false }
itp-types = { path = "../../../core-primitives/types", default-features = false }
Expand Down
42 changes: 16 additions & 26 deletions core/parentchain/light-client/src/concurrent_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ use std::sync::RwLock;

use crate::{
error::{Error, Result},
ExtrinsicSender as ExtrinsicSenderTrait, LightClientState, LightValidationState,
Validator as ValidatorTrait,
ExtrinsicSender as ExtrinsicSenderTrait, LightClientSealing, LightClientState,
LightValidationState, Validator as ValidatorTrait,
};
use finality_grandpa::BlockNumberOps;
use itp_sgx_io::StaticSealedIO;
use sp_runtime::traits::{Block as ParentchainBlockTrait, NumberFor};
use std::marker::PhantomData;

Expand Down Expand Up @@ -62,30 +61,21 @@ where

/// Implementation of a validator access based on a global lock and corresponding file.
#[derive(Debug)]
pub struct ValidatorAccessor<Validator, ParentchainBlock, Seal>
where
Validator: ValidatorTrait<ParentchainBlock>
+ LightClientState<ParentchainBlock>
+ ExtrinsicSenderTrait,
Seal: StaticSealedIO<Error = Error, Unsealed = LightValidationState<ParentchainBlock>>,
ParentchainBlock: ParentchainBlockTrait,
NumberFor<ParentchainBlock>: BlockNumberOps,
{
pub struct ValidatorAccessor<Validator, ParentchainBlock, LightClientSeal> {
seal: LightClientSeal,
light_validation: RwLock<Validator>,
_phantom: PhantomData<(Seal, Validator, ParentchainBlock)>,
_phantom: PhantomData<(LightClientSeal, Validator, ParentchainBlock)>,
}

impl<Validator, ParentchainBlock, Seal> ValidatorAccessor<Validator, ParentchainBlock, Seal>
where
Validator: ValidatorTrait<ParentchainBlock>
+ LightClientState<ParentchainBlock>
+ ExtrinsicSenderTrait,
Seal: StaticSealedIO<Error = Error, Unsealed = LightValidationState<ParentchainBlock>>,
ParentchainBlock: ParentchainBlockTrait,
NumberFor<ParentchainBlock>: BlockNumberOps,
impl<Validator, ParentchainBlock, LightClientSeal>
ValidatorAccessor<Validator, ParentchainBlock, LightClientSeal>
{
pub fn new(validator: Validator) -> Self {
ValidatorAccessor { light_validation: RwLock::new(validator), _phantom: Default::default() }
pub fn new(validator: Validator, seal: LightClientSeal) -> Self {
ValidatorAccessor {
light_validation: RwLock::new(validator),
seal,
_phantom: Default::default(),
}
}
}

Expand All @@ -95,7 +85,7 @@ where
Validator: ValidatorTrait<ParentchainBlock>
+ LightClientState<ParentchainBlock>
+ ExtrinsicSenderTrait,
Seal: StaticSealedIO<Error = Error, Unsealed = LightValidationState<ParentchainBlock>>,
Seal: LightClientSealing<LightValidationState<ParentchainBlock>>,
ParentchainBlock: ParentchainBlockTrait,
NumberFor<ParentchainBlock>: BlockNumberOps,
{
Expand All @@ -117,7 +107,7 @@ where
let mut light_validation_lock =
self.light_validation.write().map_err(|_| Error::PoisonedLock)?;
let result = mutating_function(&mut light_validation_lock);
Seal::seal_to_static_file(light_validation_lock.get_state())?;
self.seal.seal(light_validation_lock.get_state())?;
result
}
}
Expand All @@ -135,7 +125,7 @@ mod tests {
#[test]
fn execute_with_and_without_mut_in_single_thread_works() {
let validator_mock = ValidatorMock::default();
let accessor = TestAccessor::new(validator_mock);
let accessor = TestAccessor::new(validator_mock, LightValidationStateSealMock);

let _read_result = accessor.execute_on_validator(|_v| Ok(())).unwrap();
let _write_result = accessor.execute_mut_on_validator(|_v| Ok(())).unwrap();
Expand Down
2 changes: 2 additions & 0 deletions core/parentchain/light-client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ pub enum JustificationError {

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Genesis not found")]
NoGenesis,
#[error(transparent)]
Storage(#[from] itp_storage::Error),
#[error("Validator set mismatch")]
Expand Down
90 changes: 45 additions & 45 deletions core/parentchain/light-client/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,73 +21,84 @@ use crate::{
light_client_init_params::{GrandpaParams, SimpleParams},
light_validation::{check_validator_set_proof, LightValidation},
state::RelayState,
Error, LightValidationState, NumberFor, Validator,
LightClientSealing, LightClientState, LightValidationState, NumberFor, Validator,
};
use codec::{Decode, Encode};
use core::fmt::Debug;
use core::{fmt::Debug, marker::PhantomData};
use itp_ocall_api::EnclaveOnChainOCallApi;
use itp_settings::files::LIGHT_CLIENT_DB;
use itp_sgx_io::{seal, unseal, StaticSealedIO};
use itp_sgx_io::{seal, unseal};
use log::*;
use sp_runtime::traits::{Block, Header};
use std::{boxed::Box, fs, sgxfs::SgxFile, sync::Arc};

#[derive(Copy, Clone, Debug)]
pub struct LightClientStateSeal<B, LightClientState> {
_phantom: (B, LightClientState),
path: &'static str,
_phantom: PhantomData<(B, LightClientState)>,
}

impl<B: Block, LightClientState: Decode + Encode + Debug> StaticSealedIO
for LightClientStateSeal<B, LightClientState>
{
type Error = Error;
type Unsealed = LightClientState;

fn unseal_from_static_file() -> Result<Self::Unsealed> {
Ok(unseal(LIGHT_CLIENT_DB).map(|b| Decode::decode(&mut b.as_slice()))??)
impl<B, L> LightClientStateSeal<B, L> {
pub fn new(path: &'static str) -> Self {
Self { path, _phantom: Default::default() }
}
}

fn seal_to_static_file(unsealed: &Self::Unsealed) -> Result<()> {
impl<B: Block, LightClientState: Decode + Encode + Debug> LightClientSealing<LightClientState>
for LightClientStateSeal<B, LightClientState>
{
fn seal(&self, unsealed: &LightClientState) -> Result<()> {
debug!("backup light client state");
if fs::copy(LIGHT_CLIENT_DB, format!("{}.1", LIGHT_CLIENT_DB)).is_err() {
if fs::copy(self.path, format!("{}.1", self.path())).is_err() {
warn!("could not backup previous light client state");
};
debug!("Seal light client State. Current state: {:?}", unsealed);
Ok(unsealed.using_encoded(|bytes| seal(bytes, LIGHT_CLIENT_DB))?)
Ok(unsealed.using_encoded(|bytes| seal(bytes, self.path))?)
}

fn unseal(&self) -> Result<LightClientState> {
Ok(unseal(self.path).map(|b| Decode::decode(&mut b.as_slice()))??)
}

fn exists(&self) -> bool {
SgxFile::open(self.path).is_err()
}

fn path(&self) -> &'static str {
self.path
}
}

// FIXME: This is a lot of duplicate code for the initialization of two
// different but sameish light clients. Should be tackled with #1081
pub fn read_or_init_grandpa_validator<B, OCallApi>(
pub fn read_or_init_grandpa_validator<B, OCallApi, LightClientSeal>(
params: GrandpaParams<B::Header>,
ocall_api: Arc<OCallApi>,
seal: &LightClientSeal,
) -> Result<LightValidation<B, OCallApi>>
where
B: Block,
NumberFor<B>: finality_grandpa::BlockNumberOps,
OCallApi: EnclaveOnChainOCallApi,
LightClientSeal: LightClientSealing<LightValidationState<B>>,
{
check_validator_set_proof::<B>(
params.genesis_header.state_root(),
params.authority_proof,
&params.authorities,
)?;

// FIXME: That should be an unique path.
if SgxFile::open(LIGHT_CLIENT_DB).is_err() {
info!("[Enclave] ChainRelay DB not found, creating new! {}", LIGHT_CLIENT_DB);
if !seal.exists() {
info!("[Enclave] ChainRelay DB not found, creating new! {}", seal.path());
let validator = init_grandpa_validator::<B, OCallApi>(
ocall_api,
RelayState::new(params.genesis_header, params.authorities).into(),
)?;
LightClientStateSeal::<B, LightValidationState<B>>::seal_to_static_file(
validator.get_state(),
)?;
seal.seal(validator.get_state())?;
return Ok(validator)
}

let (validation_state, genesis_hash) = get_validation_state::<B>()?;
let validation_state = seal.unseal()?;
let genesis_hash = validation_state.genesis_hash()?;

let init_state = if genesis_hash == params.genesis_header.hash() {
info!("Found already initialized light client with Genesis Hash: {:?}", genesis_hash);
Expand All @@ -104,33 +115,33 @@ where

info!("light client state: {:?}", validator);

LightClientStateSeal::<B, LightValidationState<B>>::seal_to_static_file(validator.get_state())?;
seal.seal(validator.get_state())?;
Ok(validator)
}

pub fn read_or_init_parachain_validator<B, OCallApi>(
pub fn read_or_init_parachain_validator<B, OCallApi, LightClientSeal>(
params: SimpleParams<B::Header>,
ocall_api: Arc<OCallApi>,
seal: &LightClientSeal,
) -> Result<LightValidation<B, OCallApi>>
where
B: Block,
NumberFor<B>: finality_grandpa::BlockNumberOps,
OCallApi: EnclaveOnChainOCallApi,
LightClientSeal: LightClientSealing<LightValidationState<B>>,
{
// FIXME: That should be an unique path.
if SgxFile::open(LIGHT_CLIENT_DB).is_err() {
info!("[Enclave] ChainRelay DB not found, creating new! {}", LIGHT_CLIENT_DB);
if !seal.exists() {
info!("[Enclave] ChainRelay DB not found, creating new! {}", seal.path());
let validator = init_parachain_validator::<B, OCallApi>(
ocall_api,
RelayState::new(params.genesis_header, Default::default()).into(),
)?;
LightClientStateSeal::<B, LightValidationState<B>>::seal_to_static_file(
validator.get_state(),
)?;
seal.seal(validator.get_state())?;
return Ok(validator)
}

let (validation_state, genesis_hash) = get_validation_state::<B>()?;
let validation_state = seal.unseal()?;
let genesis_hash = validation_state.genesis_hash()?;

let init_state = if genesis_hash == params.genesis_header.hash() {
info!("Found already initialized light client with Genesis Hash: {:?}", genesis_hash);
Expand All @@ -146,21 +157,10 @@ where
let validator = init_parachain_validator::<B, OCallApi>(ocall_api, init_state)?;
info!("light client state: {:?}", validator);

LightClientStateSeal::<B, LightValidationState<B>>::seal_to_static_file(validator.get_state())?;
seal.seal(validator.get_state())?;
Ok(validator)
}

// Todo: Implement this on the `LightClientStateSeal` itself.
fn get_validation_state<B: Block>() -> Result<(LightValidationState<B>, B::Hash)> {
let validation_state =
LightClientStateSeal::<B, LightValidationState<B>>::unseal_from_static_file()?;

let relay = validation_state.get_relay();
let genesis_hash = relay.header_hashes[0];

Ok((validation_state, genesis_hash))
}

fn init_grandpa_validator<B, OCallApi>(
ocall_api: Arc<OCallApi>,
state: LightValidationState<B>,
Expand Down
7 changes: 7 additions & 0 deletions core/parentchain/light-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ pub trait LightClientState<Block: ParentchainBlockTrait> {
fn penultimate_finalized_block_header(&self) -> Result<Block::Header, Error>;
}

pub trait LightClientSealing<LightClientState> {
fn seal(&self, state: &LightClientState) -> Result<(), Error>;
fn unseal(&self) -> Result<LightClientState, Error>;
fn exists(&self) -> bool;
fn path(&self) -> &'static str;
}

pub fn grandpa_log<Block: ParentchainBlockTrait>(
digest: &Digest,
) -> Option<ConsensusLog<NumberFor<Block>>> {
Expand Down
12 changes: 4 additions & 8 deletions core/parentchain/light-client/src/light_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,23 +210,19 @@ where
OCallApi: EnclaveOnChainOCallApi,
{
fn num_xt_to_be_included(&self) -> Result<usize, Error> {
let relay = self.light_validation_state.get_relay();
Ok(relay.verify_tx_inclusion.len())
self.light_validation_state.num_xt_to_be_included()
}

fn genesis_hash(&self) -> Result<HashFor<Block>, Error> {
let relay = self.light_validation_state.get_relay();
Ok(relay.header_hashes[0])
self.light_validation_state.genesis_hash()
}

fn latest_finalized_header(&self) -> Result<Block::Header, Error> {
let relay = self.light_validation_state.get_relay();
Ok(relay.last_finalized_block_header.clone())
self.light_validation_state.latest_finalized_header()
}

fn penultimate_finalized_block_header(&self) -> Result<Block::Header, Error> {
let relay = self.light_validation_state.get_relay();
Ok(relay.penultimate_finalized_block_header.clone())
self.light_validation_state.penultimate_finalized_block_header()
}
}

Expand Down
31 changes: 29 additions & 2 deletions core/parentchain/light-client/src/light_validation_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@

//! State of the light-client validation.

use crate::state::RelayState;
use crate::{state::RelayState, Error, HashFor, LightClientState};
use codec::{Decode, Encode};
pub use sp_finality_grandpa::SetId;
use sp_runtime::traits::Block as ParentchainBlockTrait;

pub use sp_finality_grandpa::SetId;

#[derive(Encode, Decode, Clone, Debug)]
pub struct LightValidationState<Block: ParentchainBlockTrait> {
pub(crate) relay_state: RelayState<Block>,
Expand All @@ -46,3 +47,29 @@ impl<Block: ParentchainBlockTrait> LightValidationState<Block> {
&mut self.relay_state
}
}

impl<Block> LightClientState<Block> for LightValidationState<Block>
where
Block: ParentchainBlockTrait,
{
fn num_xt_to_be_included(&self) -> Result<usize, Error> {
let relay = self.get_relay();
Ok(relay.verify_tx_inclusion.len())
}

fn genesis_hash(&self) -> Result<HashFor<Block>, Error> {
let relay = self.get_relay();
let hash = relay.header_hashes.get(0).ok_or(Error::NoGenesis)?;
Ok(*hash)
}

fn latest_finalized_header(&self) -> Result<Block::Header, Error> {
let relay = self.get_relay();
Ok(relay.last_finalized_block_header.clone())
}

fn penultimate_finalized_block_header(&self) -> Result<Block::Header, Error> {
let relay = self.get_relay();
Ok(relay.penultimate_finalized_block_header.clone())
}
}
Loading