Skip to content

Commit

Permalink
omni-executor enclave registration (#3150)
Browse files Browse the repository at this point in the history
* attestation
  • Loading branch information
kziemianek authored Oct 31, 2024
1 parent 68fc670 commit c5d1243
Show file tree
Hide file tree
Showing 13 changed files with 267 additions and 66 deletions.
1 change: 1 addition & 0 deletions common/primitives/core/src/teebag/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub enum WorkerType {
#[default]
Identity,
BitAcross,
OmniExecutor,
}

#[derive(Encode, Decode, Clone, Copy, Default, PartialEq, Eq, RuntimeDebug, TypeInfo)]
Expand Down
8 changes: 4 additions & 4 deletions tee-worker/omni-executor/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ endif
# of the DEBUG setting is to control Gramine's loglevel.
-include $(SELF_EXE).d # See also: .cargo/config.toml
$(SELF_EXE): Cargo.toml
cargo build --release
cargo build --release --features=gramine-quote

omni-executor.manifest: omni-executor.manifest.template
gramine-manifest \
Expand Down Expand Up @@ -73,6 +73,6 @@ start-local:
stop-local:
docker compose down

.PHONY: get-omni-pallet-metadata
get-omni-pallet-metadata:
subxt metadata --url http://localhost:9944 --allow-insecure --pallets OmniAccount > parentchain/artifacts/rococo-omni-account.scale
.PHONY: get-pallet-metadata
get-pallet-metadata:
subxt metadata --url http://localhost:9944 --allow-insecure --pallets OmniAccount,Teebag > parentchain/artifacts/rococo-omni-account.scale
1 change: 1 addition & 0 deletions tee-worker/omni-executor/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ services:
- ethereum-node
- litentry-node
command: ["executor-worker", "ws://litentry-node:9944", "http://ethereum-node:8545"]
restart: always
ethereum-node:
image: ghcr.io/foundry-rs/foundry
command:
Expand Down
2 changes: 2 additions & 0 deletions tee-worker/omni-executor/omni-executor.manifest.template
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ sgx.trusted_files = [
# https://gramine.readthedocs.io/en/stable/manifest-syntax.html#number-of-threads
sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '64' }}

sgx.remote_attestation = "dcap"

# for easy demo setup
loader.insecure__use_cmdline_argv = true
loader.insecure__use_host_env = true
Binary file not shown.
3 changes: 3 additions & 0 deletions tee-worker/omni-executor/parentchain/listener/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ env_logger = { workspace = true }

[lints]
workspace = true

[features]
gramine-quote = []
84 changes: 32 additions & 52 deletions tee-worker/omni-executor/parentchain/listener/src/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,50 @@
use crate::metadata::{MetadataProvider, SubxtMetadataProvider};
use crate::primitives::BlockEvent;
use crate::rpc_client::{SubstrateRpcClient, SubstrateRpcClientFactory};
use crate::transaction_signer::TransactionSigner;
use async_trait::async_trait;
use executor_core::event_handler::Error::RecoverableError;
use executor_core::event_handler::{Error, EventHandler};
use executor_core::intent_executor::IntentExecutor;
use executor_core::key_store::KeyStore;
use executor_core::primitives::Intent;
use log::error;
use parity_scale_codec::Decode;
use std::marker::PhantomData;
use std::sync::RwLock;
use subxt::config::DefaultExtrinsicParamsBuilder;
use std::sync::Arc;
use subxt::ext::scale_decode;
use subxt::ext::scale_decode::DecodeAsFields;
use subxt::ext::subxt_core::tx;
use subxt::{Config, Metadata};
use subxt_core::config::DefaultExtrinsicParams;
use subxt_core::utils::{AccountId32, MultiAddress, MultiSignature};
use subxt_signer::sr25519::SecretKeyBytes;

pub struct IntentEventHandler<
ChainConfig: Config,
MetadataT,
MetadataProviderT: MetadataProvider<MetadataT>,
EthereumIntentExecutorT: IntentExecutor,
KeyStoreT: KeyStore<SecretKeyBytes>,
RpcClient: SubstrateRpcClient,
RpcClientFactory: SubstrateRpcClientFactory<RpcClient>,
> {
metadata_provider: MetadataProviderT,
metadata_provider: Arc<MetadataProviderT>,
ethereum_intent_executor: EthereumIntentExecutorT,
key_store: KeyStoreT,
rpc_client_factory: RpcClientFactory,
nonce: RwLock<u64>,
transaction_signer: Arc<
TransactionSigner<
KeyStoreT,
RpcClient,
RpcClientFactory,
ChainConfig,
MetadataT,
MetadataProviderT,
>,
>,
phantom_data: PhantomData<(MetadataT, RpcClient)>,
}

impl<
ChainConfig: Config,
MetadataT,
MetadataProviderT: MetadataProvider<MetadataT>,
EthereumIntentExecutorT: IntentExecutor,
Expand All @@ -61,6 +69,7 @@ impl<
RpcClientFactory: SubstrateRpcClientFactory<RpcClient>,
>
IntentEventHandler<
ChainConfig,
MetadataT,
MetadataProviderT,
EthereumIntentExecutorT,
Expand All @@ -70,17 +79,25 @@ impl<
>
{
pub fn new(
metadata_provider: MetadataProviderT,
metadata_provider: Arc<MetadataProviderT>,
ethereum_intent_executor: EthereumIntentExecutorT,
key_store: KeyStoreT,
rpc_client_factory: RpcClientFactory,
transaction_signer: Arc<
TransactionSigner<
KeyStoreT,
RpcClient,
RpcClientFactory,
ChainConfig,
MetadataT,
MetadataProviderT,
>,
>,
) -> Self {
Self {
metadata_provider,
ethereum_intent_executor,
key_store,
rpc_client_factory,
nonce: RwLock::new(0),
transaction_signer,
phantom_data: Default::default(),
}
}
Expand All @@ -100,6 +117,7 @@ impl<
RpcClientFactory: SubstrateRpcClientFactory<RpcClient> + Send + Sync,
> EventHandler<BlockEvent>
for IntentEventHandler<
ChainConfig,
Metadata,
SubxtMetadataProvider<ChainConfig>,
EthereumIntentExecutorT,
Expand All @@ -119,7 +137,7 @@ impl<

log::debug!("Got IntentRequested event: {:?}", event.id);

let metadata = self.metadata_provider.get(event.id.block_num).await;
let metadata = self.metadata_provider.get(Some(event.id.block_num)).await;

let pallet = metadata.pallet_by_name(&event.pallet_name).ok_or_else(move || {
log::error!(
Expand Down Expand Up @@ -205,51 +223,13 @@ impl<
execution_result,
);

let secret_key_bytes = self
.key_store
.read()
.map_err(|e| {
error!("Could not unseal key: {:?}", e);
})
.unwrap();
let signer = subxt_signer::sr25519::Keypair::from_secret_key(secret_key_bytes)
.map_err(|e| {
error!("Could not create secret key: {:?}", e);
})
.unwrap();

let mut client = self.rpc_client_factory.new_client().await.map_err(|e| {
error!("Could not create RPC client: {:?}", e);
RecoverableError
})?;
let runtime_version = client.runtime_version().await.map_err(|e| {
error!("Could not get runtime version: {:?}", e);
RecoverableError
})?;
let genesis_hash = client.get_genesis_hash().await.map_err(|e| {
error!("Could not get genesis hash: {:?}", e);
RecoverableError
})?;
let nonce = *self.nonce.read().map_err(|e| {
error!("Could not read nonce: {:?}", e);
RecoverableError
})?;
let params = DefaultExtrinsicParamsBuilder::<ChainConfig>::new().nonce(nonce).build();
*self.nonce.write().map_err(|e| {
error!("Could not write nonce: {:?}", e);
RecoverableError
})? = nonce + 1;

let state = tx::ClientState::<ChainConfig> {
metadata: { metadata },
genesis_hash: ChainConfig::Hash::decode(&mut genesis_hash.as_slice()).unwrap(),
runtime_version: tx::RuntimeVersion {
spec_version: runtime_version.spec_version,
transaction_version: runtime_version.transaction_version,
},
};
let signed_call = tx::create_signed(&call, &state, &signer, params).unwrap();
client.submit_tx(signed_call.encoded()).await.map_err(|e| {
let signed_call = self.transaction_signer.sign(call).await;
client.submit_tx(&signed_call).await.map_err(|e| {
error!("Error while submitting tx: {:?}", e);
RecoverableError
})?;
Expand Down
5 changes: 3 additions & 2 deletions tee-worker/omni-executor/parentchain/listener/src/fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,21 @@ use crate::rpc_client::SubstrateRpcClientFactory;
use async_trait::async_trait;
use executor_core::fetcher::{EventsFetcher, LastFinalizedBlockNumFetcher};
use log::error;
use std::sync::Arc;

/// Used for fetching data from parentchain
pub struct Fetcher<
RpcClient: SubstrateRpcClient,
RpcClientFactory: SubstrateRpcClientFactory<RpcClient>,
> {
client_factory: RpcClientFactory,
client_factory: Arc<RpcClientFactory>,
client: Option<RpcClient>,
}

impl<RpcClient: SubstrateRpcClient, RpcClientFactory: SubstrateRpcClientFactory<RpcClient>>
Fetcher<RpcClient, RpcClientFactory>
{
pub fn new(client_factory: RpcClientFactory) -> Self {
pub fn new(client_factory: Arc<RpcClientFactory>) -> Self {
Self { client: None, client_factory }
}

Expand Down
84 changes: 79 additions & 5 deletions tee-worker/omni-executor/parentchain/listener/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,29 @@ mod listener;
mod metadata;
mod primitives;
mod rpc_client;
mod transaction_signer;

use crate::event_handler::IntentEventHandler;
use crate::fetcher::Fetcher;
use crate::key_store::SubstrateKeyStore;
use crate::listener::ParentchainListener;
use crate::metadata::SubxtMetadataProvider;
use crate::rpc_client::SubstrateRpcClient;
use crate::rpc_client::{SubxtClient, SubxtClientFactory};
use crate::transaction_signer::TransactionSigner;
use executor_core::intent_executor::IntentExecutor;
use executor_core::key_store::KeyStore;
use executor_core::listener::Listener;
use executor_core::sync_checkpoint_repository::FileCheckpointRepository;
use litentry_rococo::runtime_types::core_primitives::teebag;
use log::{error, info};
use scale_encode::EncodeAsType;
use std::sync::Arc;
use subxt::config::signed_extensions;
use subxt::Config;
use subxt_core::utils::AccountId32;
use subxt_core::Metadata;
use subxt_signer::sr25519::Keypair;
use tokio::runtime::Handle;
use tokio::sync::oneshot::Receiver;

Expand Down Expand Up @@ -92,14 +99,16 @@ pub async fn create_listener<EthereumIntentExecutorT: IntentExecutor + Send + Sy
>,
(),
> {
let client_factory: SubxtClientFactory<CustomConfig> = SubxtClientFactory::new(ws_rpc_endpoint);
let client_factory: Arc<SubxtClientFactory<CustomConfig>> =
Arc::new(SubxtClientFactory::new(ws_rpc_endpoint));

let fetcher = Fetcher::new(client_factory);
let fetcher = Fetcher::new(client_factory.clone());
let last_processed_log_repository =
FileCheckpointRepository::new("data/parentchain_last_log.bin");

let metadata_provider = SubxtMetadataProvider::new(SubxtClientFactory::new(ws_rpc_endpoint));
let key_store = SubstrateKeyStore::new("/data/parentchain_key.bin".to_string());
let metadata_provider =
Arc::new(SubxtMetadataProvider::new(SubxtClientFactory::new(ws_rpc_endpoint)));
let key_store = Arc::new(SubstrateKeyStore::new("/data/parentchain_key.bin".to_string()));
let secret_key_bytes = key_store
.read()
.map_err(|e| {
Expand All @@ -114,11 +123,19 @@ pub async fn create_listener<EthereumIntentExecutorT: IntentExecutor + Send + Sy

info!("Substrate signer address: {}", AccountId32::from(signer.public_key()));

let transaction_signer = Arc::new(TransactionSigner::new(
metadata_provider.clone(),
client_factory.clone(),
key_store.clone(),
));

perform_attestation(client_factory, signer, &transaction_signer).await?;

let intent_event_handler = IntentEventHandler::new(
metadata_provider,
ethereum_intent_executor,
key_store,
SubxtClientFactory::new(ws_rpc_endpoint),
transaction_signer,
);

Listener::new(
Expand All @@ -130,3 +147,60 @@ pub async fn create_listener<EthereumIntentExecutorT: IntentExecutor + Send + Sy
last_processed_log_repository,
)
}

#[allow(unused_assignments, unused_mut, unused_variables, clippy::type_complexity)]
async fn perform_attestation(
client_factory: Arc<SubxtClientFactory<CustomConfig>>,
signer: Keypair,
transaction_signer: &Arc<
TransactionSigner<
SubstrateKeyStore,
SubxtClient<CustomConfig>,
SubxtClientFactory<CustomConfig>,
CustomConfig,
Metadata,
SubxtMetadataProvider<CustomConfig>,
>,
>,
) -> Result<(), ()> {
let mut quote = vec![];
let mut attestation_type =
litentry_rococo::teebag::calls::types::register_enclave::AttestationType::Dcap(
teebag::types::DcapProvider::Intel,
);

#[cfg(feature = "gramine-quote")]
{
use std::fs;
use std::fs::File;
use std::io::Write;
let mut f = File::create("/dev/attestation/user_report_data").unwrap();
let content = signer.public_key().0;
f.write_all(&content).unwrap();

quote = fs::read("/dev/attestation/quote").unwrap();
info!("Attestation quote {:?}", quote);
}
#[cfg(not(feature = "gramine-quote"))]
{
attestation_type =
litentry_rococo::teebag::calls::types::register_enclave::AttestationType::Ignore;
}

let registration_call = litentry_rococo::tx().teebag().register_enclave(
litentry_rococo::teebag::calls::types::register_enclave::WorkerType::OmniExecutor,
litentry_rococo::teebag::calls::types::register_enclave::WorkerMode::OffChainWorker,
quote,
vec![],
None,
None,
attestation_type,
);

let mut client = client_factory.new_client_until_connected().await;
let signed_call = transaction_signer.sign(registration_call).await;
client.submit_tx(&signed_call).await.map_err(|e| {
error!("Error while submitting tx: {:?}", e);
})?;
Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub type ParentchainListener<
IntentEventId,
BlockEvent,
IntentEventHandler<
ChainConfig,
Metadata,
SubxtMetadataProvider<ChainConfig>,
EthereumIntentExecutor,
Expand Down
Loading

0 comments on commit c5d1243

Please sign in to comment.