Skip to content

Commit 41591a2

Browse files
committed
Add pRPC AllowHandoverTo
1 parent e11e27a commit 41591a2

File tree

6 files changed

+114
-58
lines changed

6 files changed

+114
-58
lines changed

crates/phactory/api/proto

crates/phactory/api/src/crypto.rs

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ impl From<CodecError> for SignatureVerifyError {
6161
}
6262
}
6363

64+
#[derive(Default, Clone, Encode, Decode, Debug)]
6465
pub enum MessageType {
6566
Certificate { ttl: u32 },
67+
#[default]
6668
ContractQuery,
6769
}
6870

@@ -216,38 +218,39 @@ impl CertificateBody {
216218
sig_type: SignatureType,
217219
signature: &[u8],
218220
) -> Result<AccountId32, SignatureVerifyError> {
219-
let signer = match sig_type {
220-
SignatureType::Ed25519 => {
221-
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, msg)?.into()
222-
}
223-
SignatureType::Sr25519 => {
224-
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, msg)?.into()
225-
}
226-
SignatureType::Ecdsa => account_id_from_evm_pubkey(recover::<sp_core::ecdsa::Pair>(
227-
&self.pubkey,
228-
signature,
229-
msg,
230-
)?),
231-
SignatureType::Ed25519WrapBytes => {
232-
let wrapped = wrap_bytes(msg);
233-
recover::<sp_core::ed25519::Pair>(&self.pubkey, signature, &wrapped)?.into()
234-
}
235-
SignatureType::Sr25519WrapBytes => {
236-
let wrapped = wrap_bytes(msg);
237-
recover::<sp_core::sr25519::Pair>(&self.pubkey, signature, &wrapped)?.into()
238-
}
239-
SignatureType::EcdsaWrapBytes => {
240-
let wrapped = wrap_bytes(msg);
241-
account_id_from_evm_pubkey(recover::<sp_core::ecdsa::Pair>(
242-
&self.pubkey,
243-
signature,
244-
&wrapped,
245-
)?)
246-
}
247-
SignatureType::Eip712 => {
248-
account_id_from_evm_pubkey(eip712::recover(&self.pubkey, signature, msg, msg_type)?)
249-
}
250-
};
251-
Ok(signer)
221+
recover_signer_account(&self.pubkey, msg, msg_type, sig_type, signature)
252222
}
253223
}
224+
225+
pub fn recover_signer_account(
226+
pubkey: &[u8],
227+
msg: &[u8],
228+
msg_type: MessageType,
229+
sig_type: SignatureType,
230+
signature: &[u8],
231+
) -> Result<AccountId32, SignatureVerifyError> {
232+
use account_id_from_evm_pubkey as evm_account;
233+
let signer = match sig_type {
234+
SignatureType::Ed25519 => recover::<sp_core::ed25519::Pair>(pubkey, signature, msg)?.into(),
235+
SignatureType::Sr25519 => recover::<sp_core::sr25519::Pair>(pubkey, signature, msg)?.into(),
236+
SignatureType::Ecdsa => {
237+
evm_account(recover::<sp_core::ecdsa::Pair>(pubkey, signature, msg)?)
238+
}
239+
SignatureType::Ed25519WrapBytes => {
240+
let wrapped = wrap_bytes(msg);
241+
recover::<sp_core::ed25519::Pair>(pubkey, signature, &wrapped)?.into()
242+
}
243+
SignatureType::Sr25519WrapBytes => {
244+
let wrapped = wrap_bytes(msg);
245+
recover::<sp_core::sr25519::Pair>(pubkey, signature, &wrapped)?.into()
246+
}
247+
SignatureType::EcdsaWrapBytes => {
248+
let wrapped = wrap_bytes(msg);
249+
evm_account(recover::<sp_core::ecdsa::Pair>(
250+
pubkey, signature, &wrapped,
251+
)?)
252+
}
253+
SignatureType::Eip712 => evm_account(eip712::recover(pubkey, signature, msg, msg_type)?),
254+
};
255+
Ok(signer)
256+
}

crates/phactory/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ pub struct Phactory<Platform> {
323323
#[serde(skip)]
324324
#[serde(default = "sidevm_helper::create_sidevm_service_default")]
325325
sidevm_spawner: sidevm::service::Spawner,
326+
327+
/// The pRuntime measurement that allowed by the Council.
328+
#[codec(skip)]
329+
#[serde(skip)]
330+
allow_handover_to: Option<Vec<u8>>,
326331
}
327332

328333
mod sidevm_helper {
@@ -409,6 +414,7 @@ impl<Platform: pal::Platform> Phactory<Platform> {
409414
args.cores as _,
410415
create_sidevm_outgoing_channel(weak_self),
411416
),
417+
allow_handover_to: None,
412418
};
413419
me.init(args);
414420
me

crates/phactory/src/prpc_service.rs

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,24 +1592,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
15921592
}
15931593
// 5. verify pruntime launch date, never handover to old pruntime
15941594
if !dev_mode && in_sgx {
1595-
let my_la_report = {
1596-
// target_info and reportdata not important, we just need the report metadata
1597-
let target_info =
1598-
sgx_api_lite::target_info().expect("should not fail in SGX; qed.");
1599-
sgx_api_lite::report(&target_info, &[0; 64])
1600-
.map_err(|_| from_display("Cannot read server pRuntime info"))?
1601-
};
1602-
let my_runtime_hash = {
1603-
let ias_fields = IasFields {
1604-
mr_enclave: my_la_report.body.mr_enclave.m,
1605-
mr_signer: my_la_report.body.mr_signer.m,
1606-
isv_prod_id: my_la_report.body.isv_prod_id.to_ne_bytes(),
1607-
isv_svn: my_la_report.body.isv_svn.to_ne_bytes(),
1608-
report_data: [0; 64],
1609-
confidence_level: 0,
1610-
};
1611-
ias_fields.extend_mrenclave()
1612-
};
1595+
let my_runtime_hash = my_measurement()?;
16131596
let runtime_state = phactory.runtime_state()?;
16141597
let my_runtime_timestamp = runtime_state
16151598
.chain_storage
@@ -1633,13 +1616,15 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
16331616
collateral: _,
16341617
} => todo!(),
16351618
};
1636-
let req_runtime_timestamp = runtime_state
1619+
if let Some(req_runtime_timestamp) = runtime_state
16371620
.chain_storage
16381621
.get_pruntime_added_at(&runtime_hash)
1639-
.ok_or_else(|| from_display("Client pRuntime not allowed on chain"))?;
1640-
1641-
if my_runtime_timestamp >= req_runtime_timestamp {
1642-
return Err(from_display("No handover for old pRuntime"));
1622+
{
1623+
if my_runtime_timestamp >= req_runtime_timestamp {
1624+
return Err(from_display("No handover for old pRuntime"));
1625+
}
1626+
} else if phactory.allow_handover_to != Some(runtime_hash) {
1627+
return Err(from_display("Client pRuntime not allowed on chain"));
16431628
}
16441629
} else {
16451630
info!("Skip pRuntime timestamp check in dev mode");
@@ -2046,4 +2031,60 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
20462031
cluster.on_idle(block_number);
20472032
Ok(())
20482033
}
2034+
2035+
async fn allow_handover_to(
2036+
&mut self,
2037+
request: pb::AllowHandoverToRequest,
2038+
) -> Result<(), prpc::server::Error> {
2039+
let mut phactory = self.lock_phactory(false, true)?;
2040+
let runtime_state = phactory.runtime_state()?;
2041+
let council_members = runtime_state.chain_storage.council_members();
2042+
let genesis_hash = hex::encode(runtime_state.genesis_block_hash);
2043+
let mr_to = hex::encode(&request.measurement);
2044+
let mr_from = hex::encode(my_measurement()?);
2045+
let signed_message = format!("Allow pRuntime to handover from 0x{mr_from} to 0x{mr_to} on chain of genesis 0x{genesis_hash}").into_bytes();
2046+
for sig in &request.signatures {
2047+
let sig_type = pb::SignatureType::from_i32(sig.signature_type)
2048+
.ok_or_else(|| from_display("Invalid signature type"))?;
2049+
let signer = crypto::recover_signer_account(
2050+
&sig.pubkey,
2051+
&signed_message,
2052+
Default::default(),
2053+
sig_type,
2054+
&sig.signature,
2055+
)
2056+
.map_err(|_| from_display("Invalid signature"))?;
2057+
if !council_members.contains(&signer) {
2058+
return Err(from_display("Not a council member"));
2059+
}
2060+
}
2061+
let percent = request.signatures.len() * 100 / council_members.len();
2062+
if percent < 50 {
2063+
return Err(from_display("Not enough signatures"));
2064+
}
2065+
phactory.allow_handover_to = Some(request.measurement);
2066+
Ok(())
2067+
}
2068+
}
2069+
2070+
fn my_measurement() -> Result<Vec<u8>, RpcError> {
2071+
let my_la_report = {
2072+
// target_info and reportdata not important, we just need the report metadata
2073+
let target_info =
2074+
sgx_api_lite::target_info().or(Err(from_display("Failed to get SGX info")))?;
2075+
sgx_api_lite::report(&target_info, &[0; 64])
2076+
.or(Err(from_display("Cannot read server pRuntime info")))?
2077+
};
2078+
let mrenclave = {
2079+
let ias_fields = IasFields {
2080+
mr_enclave: my_la_report.body.mr_enclave.m,
2081+
mr_signer: my_la_report.body.mr_signer.m,
2082+
isv_prod_id: my_la_report.body.isv_prod_id.to_ne_bytes(),
2083+
isv_svn: my_la_report.body.isv_svn.to_ne_bytes(),
2084+
report_data: [0; 64],
2085+
confidence_level: 0,
2086+
};
2087+
ias_fields.extend_mrenclave()
2088+
};
2089+
Ok(mrenclave)
20492090
}

crates/phactory/src/storage.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl BlockValidator for LightValidation<chain::Runtime> {
3636

3737
mod storage_ext {
3838
use crate::chain;
39-
use chain::{pallet_computation, pallet_mq, pallet_phat, pallet_registry};
39+
use chain::{pallet_computation, pallet_mq, pallet_phat, pallet_registry, AccountId};
4040
use phala_mq::{ContractClusterId, Message, MessageOrigin};
4141
use phala_trie_storage::TrieStorage;
4242
use phala_types::messaging::TokenomicParameters;
@@ -178,5 +178,9 @@ mod storage_ext {
178178
) -> Option<ContractClusterId> {
179179
self.execute_with(|| pallet_phat::ClusterByWorkers::<chain::Runtime>::get(worker))
180180
}
181+
182+
pub(crate) fn council_members(&self) -> Vec<AccountId> {
183+
self.execute_with(chain::Council::members)
184+
}
181185
}
182186
}

standalone/pruntime/src/api_server.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ fn rpc_type(method: &str) -> RpcType {
209209
SaveClusterState => Public,
210210
LoadClusterState => Private,
211211
TryUpgradePinkRuntime => Private,
212+
AllowHandoverTo => Private,
212213
},
213214
}
214215
}
@@ -254,6 +255,7 @@ fn default_payload_limit_for_method(method: PhactoryAPIMethod) -> ByteUnit {
254255
SaveClusterState => 1.kibibytes(),
255256
LoadClusterState => 1.kibibytes(),
256257
TryUpgradePinkRuntime => 1.kibibytes(),
258+
AllowHandoverTo => 64.kibibytes(),
257259
}
258260
}
259261

0 commit comments

Comments
 (0)