Skip to content

Commit

Permalink
Introduce ParentchainHandler on untrusted side (#1064)
Browse files Browse the repository at this point in the history
* refactor: let parentchain handler handle all parentchain -> enclave connection

* add missing file

* make clippy happy

* make clippy happy once again :)

* add cargo.lock

* fix tests

* unify Enclave Mocks

* update cargo.lock

* cargo fmt

* fix comments

* fix clippy

* adapt comment

* fix comment

* add TODO comment

* adapt error comment
  • Loading branch information
haerdib committed Oct 14, 2022
1 parent d280b70 commit 3837075
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 240 deletions.
13 changes: 11 additions & 2 deletions core-primitives/node-api/api-client-extensions/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

use crate::ApiResult;
use itp_types::SignedBlock;
use itp_types::{Header, SignedBlock};
use sp_core::{storage::StorageKey, Pair, H256};
use sp_finality_grandpa::{AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY};
use sp_runtime::MultiSignature;
Expand All @@ -28,7 +28,8 @@ pub type StorageProof = Vec<Vec<u8>>;
pub trait ChainApi {
fn last_finalized_block(&self) -> ApiResult<Option<SignedBlock>>;
fn signed_block(&self, hash: Option<H256>) -> ApiResult<Option<SignedBlock>>;

fn get_genesis_hash(&self) -> ApiResult<H256>;
fn get_header(&self, header_hash: Option<H256>) -> ApiResult<Option<Header>>;
/// Fetch blocks from parentchain with blocknumber from until to, including both boundaries.
/// Returns a vector with one element if from equals to.
/// Returns an empty vector if from is greater than to.
Expand All @@ -54,6 +55,14 @@ where
self.get_signed_block(hash)
}

fn get_genesis_hash(&self) -> ApiResult<H256> {
self.get_genesis_hash()
}

fn get_header(&self, header_hash: Option<H256>) -> ApiResult<Option<Header>> {
self.get_header(header_hash)
}

fn get_blocks(&self, from: u32, to: u32) -> ApiResult<Vec<SignedBlock>> {
let mut blocks = Vec::<SignedBlock>::new();

Expand Down
8 changes: 7 additions & 1 deletion service/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ pub enum Error {
NoPeerWorkerFound,
#[error("No worker for shard {0} found on parentchain")]
NoWorkerForShardFound(ShardIdentifier),
#[error("Custom Error: {0}")]
#[error("Returned empty parentchain block vec after sync, even though there have been blocks given as input")]
EmptyChunk,
#[error("Could not find genesis header of the parentchain")]
MissingGenesisHeader,
#[error("Could not find last finalized block of the parentchain")]
MissingLastFinalizedBlock,
#[error("{0}")]
Custom(Box<dyn std::error::Error + Sync + Send + 'static>),
}
82 changes: 25 additions & 57 deletions service/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
ocall_bridge::{
bridge_api::Bridge as OCallBridge, component_factory::OCallBridgeComponentFactory,
},
parentchain_block_syncer::{ParentchainBlockSyncer, SyncParentchainBlocks},
parentchain_handler::{HandleParentchain, ParentchainHandler},
prometheus_metrics::{start_metrics_server, EnclaveMetricsReceiver, MetricsHandler},
sidechain_setup::{sidechain_init_block_production, sidechain_start_untrusted_rpc_server},
sync_block_broadcaster::SyncBlockBroadcaster,
Expand All @@ -46,7 +46,6 @@ use enclave::{
api::enclave_init,
tls_ra::{enclave_request_state_provisioning, enclave_run_state_provisioning_server},
};
use itc_parentchain_light_client::light_client_init_params::LightClientInitParams;
use itp_enclave_api::{
direct_request::DirectRequest,
enclave_base::EnclaveBase,
Expand All @@ -56,7 +55,7 @@ use itp_enclave_api::{
Enclave,
};
use itp_node_api::{
api_client::{AccountApi, ChainApi, PalletTeerexApi, ParentchainApi},
api_client::{AccountApi, PalletTeerexApi, ParentchainApi},
metadata::NodeMetadata,
node_api_factory::{CreateNodeApi, NodeApiFactory},
};
Expand All @@ -73,7 +72,6 @@ use log::*;
use my_node_runtime::{Event, Hash, Header};
use sgx_types::*;
use sp_core::crypto::{AccountId32, Ss58Codec};
use sp_finality_grandpa::VersionedAuthorityList;
use sp_keyring::AccountKeyring;
use std::{
path::PathBuf,
Expand All @@ -95,20 +93,19 @@ mod error;
mod globals;
mod initialized_service;
mod ocall_bridge;
mod parentchain_block_syncer;
mod parentchain_handler;
mod prometheus_metrics;
mod setup;
mod sidechain_setup;
mod sync_block_broadcaster;
mod sync_state;
#[cfg(feature = "teeracle")]
mod teeracle;
mod tests;
mod utils;
mod worker;
mod worker_peers_updater;

#[cfg(feature = "teeracle")]
mod teeracle;

const VERSION: &str = env!("CARGO_PKG_VERSION");

pub type EnclaveWorker =
Expand Down Expand Up @@ -286,7 +283,7 @@ fn start_worker<E, T, D, InitializationHandler, WorkerModeProvider>(
InitializationHandler: TrackInitialization + IsInitialized + Sync + Send + 'static,
WorkerModeProvider: ProvideWorkerMode,
{
println!("IntegriTEE Worker v{}", VERSION);
println!("Integritee Worker v{}", VERSION);
info!("starting worker on shard {}", shard.encode().to_base58());
// ------------------------------------------------------------------------
// check for required files
Expand Down Expand Up @@ -388,7 +385,8 @@ fn start_worker<E, T, D, InitializationHandler, WorkerModeProvider>(

// ------------------------------------------------------------------------
// Init parentchain specific stuff. Needed for parentchain communication.
let last_synced_header = init_parentchain_components(&node_api, enclave.clone()).unwrap();
let parentchain_handler = Arc::new(ParentchainHandler::new(node_api.clone(), enclave.clone()));
let last_synced_header = parentchain_handler.init_parentchain_components().unwrap();
let nonce = node_api.get_nonce_of(&tee_accountid).unwrap();
info!("Enclave nonce = {:?}", nonce);
enclave
Expand Down Expand Up @@ -462,35 +460,31 @@ fn start_worker<E, T, D, InitializationHandler, WorkerModeProvider>(
println!("*** [+] Finished syncing light client, syncing parentchain...");

// Syncing all parentchain blocks, this might take a while..
let parentchain_block_syncer =
Arc::new(ParentchainBlockSyncer::new(node_api.clone(), enclave.clone()));
let mut last_synced_header = parentchain_block_syncer.sync_parentchain(last_synced_header);
let mut last_synced_header =
parentchain_handler.sync_parentchain(last_synced_header).unwrap();

// ------------------------------------------------------------------------
// Initialize the sidechain
if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain {
last_synced_header = sidechain_init_block_production(
enclave.clone(),
enclave,
&register_enclave_xt_header,
we_are_primary_validateer,
parentchain_block_syncer,
parentchain_handler.clone(),
sidechain_storage,
&last_synced_header,
);
)
.unwrap();
}

// ------------------------------------------------------------------------
// start parentchain syncing loop (subscribe to header updates)
let api4 = node_api.clone();
let enclave_parentchain_sync = enclave;
thread::Builder::new()
.name("parentchain_sync_loop".to_owned())
.spawn(move || {
if let Err(e) = subscribe_to_parentchain_new_headers(
enclave_parentchain_sync,
&api4,
last_synced_header,
) {
if let Err(e) =
subscribe_to_parentchain_new_headers(parentchain_handler, last_synced_header)
{
error!("Parentchain block syncing terminated with a failure: {:?}", e);
}
println!("[!] Parentchain block syncing has terminated");
Expand Down Expand Up @@ -687,46 +681,20 @@ fn print_events(events: Events, _sender: Sender<String>) {
}
}

pub fn init_parentchain_components<E: EnclaveBase + Sidechain>(
api: &ParentchainApi,
enclave_api: Arc<E>,
) -> Result<Header, Error> {
let genesis_hash = api.get_genesis_hash().unwrap();
let genesis_header: Header = api.get_header(Some(genesis_hash)).unwrap().unwrap();
info!("Got genesis Header: \n {:?} \n", genesis_header);
if api.is_grandpa_available()? {
let grandpas = api.grandpa_authorities(Some(genesis_hash)).unwrap();
let grandpa_proof = api.grandpa_authorities_proof(Some(genesis_hash)).unwrap();

debug!("Grandpa Authority List: \n {:?} \n ", grandpas);

let authority_list = VersionedAuthorityList::from(grandpas);

let params = LightClientInitParams::Grandpa {
genesis_header,
authorities: authority_list.into(),
authority_proof: grandpa_proof,
};

Ok(enclave_api.init_parentchain_components(params).unwrap())
} else {
let params = LightClientInitParams::Parachain { genesis_header };

Ok(enclave_api.init_parentchain_components(params).unwrap())
}
}

/// Subscribe to the node API finalized heads stream and trigger a parent chain sync
/// upon receiving a new header.
fn subscribe_to_parentchain_new_headers<E: EnclaveBase + Sidechain>(
enclave_api: Arc<E>,
api: &ParentchainApi,
parentchain_handler: Arc<ParentchainHandler<ParentchainApi, E>>,
mut last_synced_header: Header,
) -> Result<(), Error> {
let (sender, receiver) = channel();
api.subscribe_finalized_heads(sender).map_err(Error::ApiClient)?;
//TODO: this should be implemented by parentchain_handler directly, and not via
// exposed parentchain_api. Blocked by https://github.com/scs/substrate-api-client/issues/267.
parentchain_handler
.parentchain_api()
.subscribe_finalized_heads(sender)
.map_err(Error::ApiClient)?;

let parentchain_block_syncer = ParentchainBlockSyncer::new(api.clone(), enclave_api);
loop {
let new_header: Header = match receiver.recv() {
Ok(header_str) => serde_json::from_str(&header_str).map_err(Error::Serialization),
Expand All @@ -738,7 +706,7 @@ fn subscribe_to_parentchain_new_headers<E: EnclaveBase + Sidechain>(
new_header.number
);

last_synced_header = parentchain_block_syncer.sync_parentchain(last_synced_header);
last_synced_header = parentchain_handler.sync_parentchain(last_synced_header)?;
}
}

Expand Down
114 changes: 0 additions & 114 deletions service/src/parentchain_block_syncer.rs

This file was deleted.

Loading

0 comments on commit 3837075

Please sign in to comment.