Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce ParentchainHandler on untrusted side #1064

Merged
merged 17 commits into from
Oct 14, 2022
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);
Comment on lines -289 to +286
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been around for a long time 🤣 finally gets fixed now 🎉

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)?;
murerfel marked this conversation as resolved.
Show resolved Hide resolved

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