@@ -258,6 +258,9 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
258
258
) ,
259
259
"dispatch_block" ,
260
260
) ;
261
+
262
+ self . allow_handover_to = None ;
263
+
261
264
let counters = self . runtime_state ( ) ?. storage_synchronizer . counters ( ) ;
262
265
blocks. retain ( |b| b. block_header . number >= counters. next_block_number ) ;
263
266
@@ -381,7 +384,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> Phactory<Platform>
381
384
let chain_storage = ChainStorage :: from_pairs ( genesis_state. into_iter ( ) ) ;
382
385
let para_id = chain_storage. para_id ( ) ;
383
386
info ! (
384
- "Genesis state loaded: root={:?}, para_id={para_id}" ,
387
+ "Genesis state loaded: root={:?}, para_id={para_id}, genesis_hash={genesis_block_hash:?} " ,
385
388
chain_storage. root( )
386
389
) ;
387
390
@@ -1574,24 +1577,7 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
1574
1577
}
1575
1578
// 5. verify pruntime launch date, never handover to old pruntime
1576
1579
if !dev_mode && in_sgx {
1577
- let my_la_report = {
1578
- // target_info and reportdata not important, we just need the report metadata
1579
- let target_info =
1580
- sgx_api_lite:: target_info ( ) . expect ( "should not fail in SGX; qed." ) ;
1581
- sgx_api_lite:: report ( & target_info, & [ 0 ; 64 ] )
1582
- . map_err ( |_| from_display ( "Cannot read server pRuntime info" ) ) ?
1583
- } ;
1584
- let my_runtime_hash = {
1585
- let ias_fields = IasFields {
1586
- mr_enclave : my_la_report. body . mr_enclave . m ,
1587
- mr_signer : my_la_report. body . mr_signer . m ,
1588
- isv_prod_id : my_la_report. body . isv_prod_id . to_ne_bytes ( ) ,
1589
- isv_svn : my_la_report. body . isv_svn . to_ne_bytes ( ) ,
1590
- report_data : [ 0 ; 64 ] ,
1591
- confidence_level : 0 ,
1592
- } ;
1593
- ias_fields. extend_mrenclave ( )
1594
- } ;
1580
+ let my_runtime_hash = my_measurement ( ) ?;
1595
1581
let runtime_state = phactory. runtime_state ( ) ?;
1596
1582
let my_runtime_timestamp = runtime_state
1597
1583
. chain_storage
@@ -1611,13 +1597,15 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
1611
1597
ias_fields. extend_mrenclave ( )
1612
1598
}
1613
1599
} ;
1614
- let req_runtime_timestamp = runtime_state
1600
+ if let Some ( req_runtime_timestamp) = runtime_state
1615
1601
. chain_storage
1616
1602
. get_pruntime_added_at ( & runtime_hash)
1617
- . ok_or_else ( || from_display ( "Client pRuntime not allowed on chain" ) ) ?;
1618
-
1619
- if my_runtime_timestamp >= req_runtime_timestamp {
1620
- return Err ( from_display ( "No handover for old pRuntime" ) ) ;
1603
+ {
1604
+ if my_runtime_timestamp >= req_runtime_timestamp {
1605
+ return Err ( from_display ( "No handover for old pRuntime" ) ) ;
1606
+ }
1607
+ } else if phactory. allow_handover_to != Some ( runtime_hash) {
1608
+ return Err ( from_display ( "Client pRuntime not allowed on chain" ) ) ;
1621
1609
}
1622
1610
} else {
1623
1611
info ! ( "Skip pRuntime timestamp check in dev mode" ) ;
@@ -2004,4 +1992,69 @@ impl<Platform: pal::Platform + Serialize + DeserializeOwned> PhactoryApi for Rpc
2004
1992
. load_cluster_state ( & req. filename )
2005
1993
. map_err ( from_debug)
2006
1994
}
1995
+
1996
+ async fn allow_handover_to (
1997
+ & mut self ,
1998
+ request : pb:: AllowHandoverToRequest ,
1999
+ ) -> Result < ( ) , prpc:: server:: Error > {
2000
+ let mut phactory = self . lock_phactory ( false , true ) ?;
2001
+ let runtime_state = phactory. runtime_state ( ) ?;
2002
+ let council_members = runtime_state. chain_storage . council_members ( ) ;
2003
+ if request. signatures . len ( ) > council_members. len ( ) {
2004
+ return Err ( from_display ( "Too many signatures" ) ) ;
2005
+ }
2006
+ let genesis_hash = hex:: encode ( runtime_state. genesis_block_hash ) ;
2007
+ let mr_to = hex:: encode ( & request. measurement ) ;
2008
+ let mr_from = hex:: encode ( my_measurement ( ) ?) ;
2009
+ let signed_message = format ! ( "Allow pRuntime to handover\n from: 0x{mr_from}\n to: 0x{mr_to}\n genesis: 0x{genesis_hash}" ) . into_bytes ( ) ;
2010
+ debug ! ( "Signed message: {:?}" , hex:: encode( & signed_message) ) ;
2011
+ let mut signers = std:: collections:: BTreeSet :: new ( ) ;
2012
+ for sig in & request. signatures {
2013
+ let sig_type = pb:: SignatureType :: from_i32 ( sig. signature_type )
2014
+ . ok_or_else ( || from_display ( "Invalid signature type" ) ) ?;
2015
+ let signer = crypto:: recover_signer_account (
2016
+ & sig. pubkey ,
2017
+ & signed_message,
2018
+ Default :: default ( ) ,
2019
+ sig_type,
2020
+ & sig. signature ,
2021
+ )
2022
+ . map_err ( |_| from_display ( "Invalid signature" ) ) ?;
2023
+ if !council_members. contains ( & signer) {
2024
+ return Err ( from_display ( "Not a council member" ) ) ;
2025
+ }
2026
+ debug ! ( "Signed by {signer:?}" ) ;
2027
+ signers. insert ( signer) ;
2028
+ }
2029
+ let percent = signers. len ( ) * 100 / council_members. len ( ) ;
2030
+ // At least 7 of 8 members. 6/8 = 75%, 7/8 = 87.5%.
2031
+ let threshold = 80 ;
2032
+ if percent < threshold {
2033
+ return Err ( from_display ( "Not enough signatures" ) ) ;
2034
+ }
2035
+ phactory. allow_handover_to = Some ( request. measurement ) ;
2036
+ Ok ( ( ) )
2037
+ }
2038
+ }
2039
+
2040
+ fn my_measurement ( ) -> Result < Vec < u8 > , RpcError > {
2041
+ let my_la_report = {
2042
+ // target_info and reportdata not important, we just need the report metadata
2043
+ let target_info =
2044
+ sgx_api_lite:: target_info ( ) . or ( Err ( from_display ( "Failed to get SGX info" ) ) ) ?;
2045
+ sgx_api_lite:: report ( & target_info, & [ 0 ; 64 ] )
2046
+ . or ( Err ( from_display ( "Cannot read server pRuntime info" ) ) ) ?
2047
+ } ;
2048
+ let mrenclave = {
2049
+ let ias_fields = IasFields {
2050
+ mr_enclave : my_la_report. body . mr_enclave . m ,
2051
+ mr_signer : my_la_report. body . mr_signer . m ,
2052
+ isv_prod_id : my_la_report. body . isv_prod_id . to_ne_bytes ( ) ,
2053
+ isv_svn : my_la_report. body . isv_svn . to_ne_bytes ( ) ,
2054
+ report_data : [ 0 ; 64 ] ,
2055
+ confidence_level : 0 ,
2056
+ } ;
2057
+ ias_fields. extend_mrenclave ( )
2058
+ } ;
2059
+ Ok ( mrenclave)
2007
2060
}
0 commit comments