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

pink: Add chain extension to get RA report #1527

Merged
merged 18 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
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
2 changes: 1 addition & 1 deletion .github/actions/install_toolchain/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ runs:
- name: Install latest stable
uses: actions-rs/toolchain@v1
with:
toolchain: 1.73.0
toolchain: 1.75.0
override: true
target: wasm32-unknown-unknown
components: cargo, clippy, rust-analyzer, rust-src, rust-std, rustc-dev, rustc, rustfmt
Expand Down
8 changes: 7 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/phactory/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ bitflags = "1"
async-trait = "0.1.57"
phala-scheduler = { path = "../phala-scheduler" }
sgx-api-lite = { path = "../sgx-api-lite" }
sgx-attestation = { path = "../sgx-attestation" }
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls", "socks", "trust-dns"] }
reqwest-env-proxy = { path = "../reqwest-env-proxy" }
libc = "0.2"
Expand Down
1 change: 0 additions & 1 deletion crates/phactory/api/src/proto_generated/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ mod protos_codec_extensions;
#[allow(clippy::derive_partial_eq_without_eq, clippy::let_unit_value)]
mod pruntime_rpc;

pub use protos_codec_extensions::*;
pub use pruntime_rpc::*;

pub const PROTO_DEF: &str = include_str!("../../proto/pruntime_rpc.proto");
Expand Down
9 changes: 6 additions & 3 deletions crates/phactory/pal/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Platform abstraction layer for Trusted Execution Environments

use core::time::Duration;
use std::fmt::Debug;
use std::path::Path;
use core::time::Duration;

use phala_types::AttestationProvider;

Expand Down Expand Up @@ -53,7 +53,10 @@ pub trait AppInfo {
}

pub trait Platform:
Sealing + RA + Machine + MemoryStats + AppInfo + Clone + Send + 'static
Sealing + RA + Machine + MemoryStats + AppInfo + Clone + Send + Sync + 'static
{
}
impl<T: Sealing + RA + Machine + MemoryStats + AppInfo + Clone + Send + Sync + 'static> Platform
for T
{
}
impl<T: Sealing + RA + Machine + MemoryStats + AppInfo + Clone + Send + 'static> Platform for T {}
42 changes: 35 additions & 7 deletions crates/phactory/src/contracts/pink.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use once_cell::sync::Lazy;
use sgx_attestation::SgxQuote;
use std::sync::Mutex;
use std::{convert::TryInto, time::Duration};

Expand Down Expand Up @@ -137,11 +138,12 @@ pub(crate) mod context {
use std::time::{Duration, Instant};

use anyhow::{anyhow, Result};
use phala_types::{wrap_content_to_sign, SignedContentType};
use phala_types::{wrap_content_to_sign, AttestationProvider, SignedContentType};
use pink::{
capi::v1::ocall::ExecContext,
types::{AccountId, BlockNumber, ExecutionMode},
};
use sgx_attestation::SgxQuote;
use sidevm::OutgoingRequestChannel;
use sp_core::Pair;

Expand All @@ -163,6 +165,7 @@ pub(crate) mod context {
timeout: Duration,
) -> Result<Vec<u8>>;
fn sidevm_event_tx(&self) -> OutgoingRequestChannel;
fn worker_sgx_quote(&self) -> Option<SgxQuote>;
}

pub struct ContractExecContext {
Expand All @@ -175,6 +178,7 @@ pub(crate) mod context {
pub start_at: Instant,
pub req_id: u64,
pub sidevm_event_tx: OutgoingRequestChannel,
pub attestation_provider: Option<AttestationProvider>,
}

impl ContractExecContext {
Expand All @@ -188,6 +192,7 @@ pub(crate) mod context {
req_id: u64,
contracts: ContractsKeeper,
sidevm_event_tx: OutgoingRequestChannel,
attestation_provider: Option<AttestationProvider>,
) -> Self {
Self {
mode,
Expand All @@ -199,6 +204,7 @@ pub(crate) mod context {
req_id,
contracts,
sidevm_event_tx,
attestation_provider,
}
}
}
Expand Down Expand Up @@ -266,6 +272,14 @@ pub(crate) mod context {
fn sidevm_event_tx(&self) -> OutgoingRequestChannel {
self.sidevm_event_tx.clone()
}

fn worker_sgx_quote(&self) -> Option<SgxQuote> {
use AttestationProvider::*;
let Some(Ias | Dcap) = self.attestation_provider else {
return None;
};
sgx_attestation::gramine::create_quote(&self.worker_pubkey())
}
}

pub fn get() -> ExecContext {
Expand Down Expand Up @@ -295,13 +309,17 @@ pub(crate) mod context {
exec_context::with(|ctx| ctx.call_elapsed()).unwrap_or_else(|| Duration::from_secs(0))
}

pub fn time_remaining() -> u64 {
pub fn time_remaining_ms() -> u64 {
time_remaining().as_millis() as u64
}

pub fn time_remaining() -> Duration {
const MAX_QUERY_TIME: Duration = Duration::from_secs(10);
MAX_QUERY_TIME.saturating_sub(call_elapsed()).as_millis() as _
MAX_QUERY_TIME.saturating_sub(call_elapsed())
}

pub fn sidevm_query(origin: [u8; 32], vmid: [u8; 32], payload: Vec<u8>) -> Result<Vec<u8>> {
let timeout = Duration::from_millis(time_remaining());
let timeout = Duration::from_millis(time_remaining_ms());
exec_context::with(|ctx| ctx.sidevm_query(origin, vmid, payload, timeout))
.ok_or(anyhow!("sidevm_query called outside of contract execution"))?
}
Expand Down Expand Up @@ -466,7 +484,7 @@ impl OCalls for RuntimeHandle<'_> {
}
};
}
let result = pink_extension_runtime::http_request(request, context::time_remaining());
let result = pink_extension_runtime::http_request(request, context::time_remaining_ms());
match &result {
Ok(response) => {
http_counters::add(contract, response.status_code);
Expand All @@ -486,7 +504,7 @@ impl OCalls for RuntimeHandle<'_> {
) -> BatchHttpResult {
let results = pink_extension_runtime::batch_http_request(
requests,
context::time_remaining().min(timeout_ms),
context::time_remaining_ms().min(timeout_ms),
)?;
for result in &results {
match result {
Expand Down Expand Up @@ -518,7 +536,7 @@ impl OCalls for RuntimeHandle<'_> {
let Some(js_runtime) = self.cluster.config.js_runtime else {
return JsValue::Exception("No js runtime".into());
};
let timeout = Duration::from_millis(context::time_remaining());
let timeout = Duration::from_millis(context::time_remaining_ms());
let mut args = vec!["phatjs".into()];
for code in codes {
match code {
Expand Down Expand Up @@ -568,6 +586,10 @@ impl OCalls for RuntimeHandle<'_> {
fn origin(&self) -> Option<AccountId> {
context::get_origin()
}

fn worker_sgx_quote(&self) -> Option<SgxQuote> {
context::with(|ctx| ctx.worker_sgx_quote())
}
}

pub fn load_module(code_hash: &Hash, init: impl FnOnce() -> Option<Vec<u8>>) -> Result<WasmModule> {
Expand Down Expand Up @@ -700,6 +722,10 @@ impl OCalls for RuntimeHandleMut<'_> {
fn origin(&self) -> Option<AccountId> {
self.readonly().origin()
}

fn worker_sgx_quote(&self) -> Option<SgxQuote> {
self.readonly().worker_sgx_quote()
}
}

impl v1::CrossCall for RuntimeHandle<'_> {
Expand Down Expand Up @@ -863,6 +889,7 @@ impl Cluster {
context.req_id,
contracts,
context.sidevm_event_tx.clone(),
context.attestation_provider,
);
let log_handler = context.log_handler.clone();
let contract_id = contract_id.clone();
Expand Down Expand Up @@ -946,6 +973,7 @@ impl Cluster {
context.req_id,
contracts,
context.sidevm_event_tx.clone(),
context.attestation_provider,
);
let log_handler = context.log_handler.clone();
context::using(&mut ctx, move || {
Expand Down
2 changes: 2 additions & 0 deletions crates/phactory/src/contracts/support.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use anyhow::{anyhow, bail, Context, Result};
use core::time::Duration;
use phala_types::AttestationProvider;
use pink::types::{AccountId, ExecutionMode, TransactionArguments};
use pink_extension::{chain_extension::JsValue, SidevmConfig};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -50,6 +51,7 @@ pub struct QueryContext {
pub chain_storage: ChainStorage,
pub req_id: u64,
pub sidevm_event_tx: OutgoingRequestChannel,
pub attestation_provider: Option<AttestationProvider>,
}

pub(crate) struct RawData(Vec<u8>);
Expand Down
1 change: 1 addition & 0 deletions crates/phactory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ impl<P: pal::Platform> Phactory<P> {
.expect("runtime state always exists here")
.chain_storage,
self.sidevm_spawner.event_tx(),
self.attestation_provider,
);
let pink_runtime_version = self
.cluster_runtime_version()
Expand Down
2 changes: 1 addition & 1 deletion crates/phactory/src/light_validation/types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub use phactory_api::blocks::{AuthoritySet, AuthoritySetChange, find_scheduled_change};
pub use phactory_api::blocks::{find_scheduled_change, AuthoritySet};

pub type BlockHeader = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
30 changes: 24 additions & 6 deletions crates/phactory/src/prpc_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
req_id,
contracts,
self.sidevm_spawner.event_tx(),
None, // Not allowed in TX
);
self.check_requirements();
contracts::pink::context::using(&mut context, || {
Expand Down Expand Up @@ -516,17 +517,31 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
Ok(resp)
}

fn allow_attestation(&self) -> bool {
// The IdentityKey is considered valid in two situations:
//
// 1. It's generated by pRuntime thus is safe;
// 2. It's handovered, but we find out that it was successfully registered as a worker on-chain;
let Some(system) = &self.system else {
return false;
};
let Some(runtime_state) = &self.runtime_state else {
return false;
};
let validated_identity_key = self.trusted_sk || system.registered();
let validated_state = runtime_state.storage_synchronizer.state_validated();

validated_state && (validated_identity_key || self.attestation_provider.is_none())
}

fn get_runtime_info(
&mut self,
refresh_ra: bool,
operator: Option<chain::AccountId>,
) -> RpcResult<pb::InitRuntimeResponse> {
// The IdentityKey is considered valid in two situations:
//
// 1. It's generated by pRuntime thus is safe;
// 2. It's handovered, but we find out that it was successfully registered as a worker on-chain;
let validated_identity_key = self.trusted_sk || self.system()?.registered();
let validated_state = self.runtime_state()?.storage_synchronizer.state_validated();
let allow_attestation = self.allow_attestation();

let reset_operator = operator.is_some();
if reset_operator {
Expand All @@ -550,8 +565,6 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
}
}

let allow_attestation =
validated_state && (validated_identity_key || self.attestation_provider.is_none());
info!("validated_identity_key :{validated_identity_key}");
info!("validated_state :{validated_state}");
info!("refresh_ra :{refresh_ra}");
Expand Down Expand Up @@ -632,6 +645,10 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
let rest = data_cursor.len();

let query_scheduler = self.query_scheduler.clone();
let attestation_provider = self
.allow_attestation()
.then_some(self.attestation_provider)
.flatten();
// Dispatch
let query_future = self
.system
Expand All @@ -649,6 +666,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
.expect("runtime state always exists here")
.chain_storage,
self.sidevm_spawner.event_tx(),
attestation_provider,
)?;

Ok(async move {
Expand Down
4 changes: 2 additions & 2 deletions crates/phactory/src/system/gk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ impl<MsgChan: MessageChannel<Signer = Sr25519Signer>> ComputingEconomics<MsgChan
}
event_listener.emit_event(EconomicEvent::ExitUnresponsive, worker_info);
}
} else if let Some(&hb_sent_at) = worker_info.waiting_heartbeats.get(0) {
} else if let Some(&hb_sent_at) = worker_info.waiting_heartbeats.front() {
if block.block_number - hb_sent_at > heartbeat_window {
trace!(
target: "gk_computing",
Expand Down Expand Up @@ -922,7 +922,7 @@ impl<MsgChan: MessageChannel<Signer = Sr25519Signer>> ComputingEconomics<MsgChan
worker_info.stat.last_heartbeat_for_block = challenge_block;
}

if Some(&challenge_block) != worker_info.waiting_heartbeats.get(0) {
if Some(&challenge_block) != worker_info.waiting_heartbeats.front() {
error!(target: "gk_computing", "Fatal error: Unexpected heartbeat {:?}", event);
error!(target: "gk_computing", "Sent from worker {}", hex::encode(worker_pubkey));
error!(target: "gk_computing", "Waiting heartbeats {:#?}", worker_info.waiting_heartbeats);
Expand Down
4 changes: 3 additions & 1 deletion crates/phactory/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use phala_types::{
NewGatekeeperEvent, RemoveGatekeeperEvent, RotateMasterKeyEvent, SystemEvent, WorkerEvent,
WorkingReportEvent,
},
wrap_content_to_sign, EcdhPublicKey, SignedContentType, WorkerPublicKey,
wrap_content_to_sign, AttestationProvider, EcdhPublicKey, SignedContentType, WorkerPublicKey,
};
use serde::{Deserialize, Serialize};
use sidevm::{
Expand Down Expand Up @@ -544,6 +544,7 @@ impl<Platform: pal::Platform> System<Platform> {
query_scheduler: RequestScheduler<AccountId>,
chain_storage: &ChainStorage,
sidevm_event_tx: OutgoingRequestChannel,
attestation_provider: Option<AttestationProvider>,
) -> Result<
impl Future<
Output = Result<
Expand Down Expand Up @@ -579,6 +580,7 @@ impl<Platform: pal::Platform> System<Platform> {
chain_storage: chain_storage.snapshot(),
req_id,
sidevm_event_tx,
attestation_provider,
};
let origin = origin.cloned();
let query = deopaque_query::<Query>(&query)?;
Expand Down
Loading
Loading