Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
fetch peer for provisioning based on their activity and avoid fetchin…
…g from other shards or self
  • Loading branch information
brenzi committed Dec 8, 2023
commit 0f1f85e34fbc82c40f770be8058ecd432c31d471
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

use crate::ApiResult;
use itp_api_client_types::{traits::GetStorage, Api, Config, Request};
use itp_types::{AccountId, IpfsHash, MultiEnclave, ShardIdentifier, ShardStatus};
use itp_types::{
AccountId, IpfsHash, MultiEnclave, ShardIdentifier, ShardSignerStatus, ShardStatus,
};
use log::error;

pub const TEEREX: &str = "Teerex";
Expand All @@ -40,6 +42,11 @@ pub trait PalletTeerexApi {
shard: &ShardIdentifier,
at_block: Option<Self::Hash>,
) -> ApiResult<Option<MultiEnclave<Vec<u8>>>>;
fn shard_status(
&self,
shard: &ShardIdentifier,
at_block: Option<Self::Hash>,
) -> ApiResult<Option<Vec<ShardSignerStatus>>>;
fn latest_ipfs_hash(
&self,
shard: &ShardIdentifier,
Expand Down Expand Up @@ -100,6 +107,14 @@ where
)
}

fn shard_status(
&self,
shard: &ShardIdentifier,
at_block: Option<Self::Hash>,
) -> ApiResult<Option<Vec<ShardSignerStatus>>> {
self.get_storage_map(ENCLAVE_BRIDGE, "ShardStatus", shard, at_block)
}

fn latest_ipfs_hash(
&self,
shard: &ShardIdentifier,
Expand Down
9 changes: 4 additions & 5 deletions service/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,10 @@ mod needs_enclave {
println!("[+] Initialize the shard");
init_shard(enclave, shard_identifier);

println!("[+] Generate key files");
generate_signing_key_file(enclave);
// if we are not the primary worker, this might be overwritten later upon provisioning
generate_shielding_key_file(enclave);

let pubkey = enclave.get_ecc_signing_pubkey().unwrap();
debug!("Enclave signing key (public) raw: {:?}", pubkey);
let pubkey = enclave.get_rsa_shielding_pubkey().unwrap();
debug!("Enclave shielding key (public) raw (may be overwritten later): {:?}", pubkey);
Ok(())
}

Expand Down
52 changes: 43 additions & 9 deletions service/src/sync_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ use itp_enclave_api::{
};
use itp_node_api::api_client::PalletTeerexApi;
use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode};
use itp_types::ShardIdentifier;
use itp_types::{parentchain::AccountId, ShardIdentifier};
use log::info;
use sgx_types::sgx_quote_sign_type_t;
use sp_runtime::MultiSigner;
use std::string::String;
use teerex_primitives::AnySigner;

pub(crate) fn sync_state<
E: TlsRemoteAttestation + EnclaveBase + RemoteAttestation,
Expand All @@ -42,13 +45,13 @@ pub(crate) fn sync_state<
enclave_api: &E,
skip_ra: bool,
) {
// FIXME: we now assume that keys are equal for all shards.
let provider_url = match WorkerModeProvider::worker_mode() {
WorkerMode::Sidechain =>
executor::block_on(get_author_url_of_last_finalized_sidechain_block(node_api, shard))
WorkerMode::Sidechain | WorkerMode::OffChainWorker =>
executor::block_on(get_enclave_url_of_last_active(node_api, enclave_api, shard))
.expect("author of most recent shard update not found"),
WorkerMode::Teeracle =>
executor::block_on(get_enclave_url_of_first_registered(node_api, enclave_api))
.expect("Author of last finalized sidechain block could not be found"),
_ => executor::block_on(get_enclave_url_of_first_registered(node_api, enclave_api))
.expect("Author of last finalized sidechain block could not be found"),
};

println!("Requesting state provisioning from worker at {}", &provider_url);
Expand Down Expand Up @@ -82,20 +85,51 @@ async fn get_author_url_of_last_finalized_sidechain_block<NodeApi: PalletTeerexA
Ok(worker_api_direct.get_mu_ra_url()?)
}

/// Returns the url of the first Enclave that matches our own MRENCLAVE.
///
/// This should be run before we register ourselves as enclave, to ensure we don't get our own url.
/// Returns the url of the first Enclave that matches our own MRENCLAVE which isn't ourself.
/// this is not reliable because there may be other active peers although the very first one went offline
async fn get_enclave_url_of_first_registered<NodeApi: PalletTeerexApi, EnclaveApi: EnclaveBase>(
node_api: &NodeApi,
enclave_api: &EnclaveApi,
) -> Result<String> {
let self_mr_enclave = enclave_api.get_fingerprint()?;
let self_account = enclave_api.get_ecc_signing_pubkey()?;
let first_enclave = node_api
.all_enclaves(None)?
.into_iter()
.filter(|e| e.instance_signer() != AnySigner::Known(MultiSigner::Ed25519(self_account)))
.find(|e| e.fingerprint() == self_mr_enclave)
.ok_or(Error::NoPeerWorkerFound)?;
let worker_api_direct =
DirectWorkerApi::new(String::from_utf8(first_enclave.instance_url().unwrap()).unwrap());
Ok(worker_api_direct.get_mu_ra_url()?)
}

/// Returns the url of the last active worker on our shard
async fn get_enclave_url_of_last_active<NodeApi: PalletTeerexApi, EnclaveApi: EnclaveBase>(
node_api: &NodeApi,
enclave_api: &EnclaveApi,
shard: &ShardIdentifier,
) -> Result<String> {
let self_account = enclave_api.get_ecc_signing_pubkey()?;
let shard_status = node_api
.shard_status(shard, None)
.expect("must be able to fetch shard status")
.expect("can only sync state for active shards");
info!("fetching active peer. shard status: {:?}", shard_status);
let last_active_signer_status = shard_status
.iter()
.filter(|&s| s.signer != AccountId::from(self_account))
.max_by_key(|&signer_status| signer_status.last_activity)
.expect("there has to be a most recently active peer")
.clone();
info!("most recently active signer on this shard: {:?}", last_active_signer_status);
let provider_enclave = node_api
.enclave(&last_active_signer_status.signer, None)
.expect("must be able to fetch enclaves")
.expect("active peer must exist in registry");
let worker_api_direct = DirectWorkerApi::new(
String::from_utf8(provider_enclave.instance_url().expect("provider must specify url"))
.unwrap(),
);
Ok(worker_api_direct.get_mu_ra_url()?)
}
14 changes: 12 additions & 2 deletions service/src/tests/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
*/

use codec::Encode;
use enclave_bridge_primitives::ShardSignerStatus;
use itp_node_api::api_client::{ApiResult, PalletTeerexApi};
use itp_types::{
AccountId, MultiEnclave, SgxBuildMode, SgxEnclave, SgxReportData, SgxStatus, ShardIdentifier,
H256 as Hash,
parentchain::BlockNumber, AccountId, MultiEnclave, SgxBuildMode, SgxEnclave, SgxReportData,
SgxStatus, ShardIdentifier, H256 as Hash,
};

pub struct TestNodeApi;
Expand Down Expand Up @@ -79,6 +80,15 @@ impl PalletTeerexApi for TestNodeApi {
) -> ApiResult<Option<MultiEnclave<Vec<u8>>>> {
unreachable!()
}

fn shard_status(
&self,
_: &ShardIdentifier,
_at_block: Option<Hash>,
) -> ApiResult<Option<Vec<ShardSignerStatus<AccountId, BlockNumber>>>> {
unreachable!()
}

fn latest_ipfs_hash(
&self,
_: &ShardIdentifier,
Expand Down