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

feat:add get public service for miner to ensure which ceseal connect with #306

Merged
merged 3 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 3 additions & 6 deletions crates/ces-pdp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,14 @@ pub fn gen_keypair(bits: usize) -> Keys {
// ).unwrap()).unwrap();
let skey = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
let pkey = RsaPublicKey::from(&skey);
println!("{:?}", hex::encode(pkey.to_pkcs1_der().unwrap().to_vec()));
println!("Podr2 public key is {:?}", hex::encode(pkey.to_pkcs1_der().unwrap().to_vec()));

Keys { skey, pkey }
}

pub fn gen_keypair_from_private_key(skey: RsaPrivateKey) -> Keys {
let pkey = skey.to_public_key();
Keys{
skey,
pkey,
}
Keys { skey, pkey }
}

use rsa::{
Expand All @@ -169,7 +166,7 @@ impl Keys {
.sign(Pkcs1v15Sign::new_raw(), data)
.map_err(|e| PDPError { error_code: FailCode::ParameterError(e.to_string()) })
}

pub fn verify_data(&self, hashed: &[u8], sig: &[u8]) -> Result<(), PDPError> {
self.pkey
.verify(Pkcs1v15Sign::new_raw(), hashed, sig)
Expand Down
1 change: 1 addition & 0 deletions crates/cestory/api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ fn main() {

tonic_build::compile_protos("proto/pois-api.proto").unwrap();
tonic_build::compile_protos("proto/podr2-api.proto").unwrap();
tonic_build::compile_protos("proto/pubkeys.proto").unwrap();
}
45 changes: 45 additions & 0 deletions crates/cestory/api/proto/pubkeys.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
syntax = "proto3";

package ceseal.pubkeys;

// Provide the storage miners with Ceseal's various public key queries
service CesealPubkeysProvider {
// Get the Ceseal identity public key
rpc get_identity_pubkey(Request) returns (IdentityPubkeyResponse) {}
// Get the master public key
rpc get_master_pubkey(Request) returns (MasterPubkeyResponse) {}
// Get the PORD2 public key
rpc get_podr2_pubkey(Request) returns (Podr2PubkeyResponse) {}
}

message Request {
// The account id that the storage miner registered on the chain
bytes storage_miner_account_id = 1;
}

message IdentityPubkeyResponse {
// the identity public key
bytes pubkey = 1;
// The timestamp for the processing of the request
int64 timestamp = 2;
// Use the sr25519 algorithm to sign the timestamp fields above (use it's Big-Endian bytes)
bytes signature = 3;
}

message MasterPubkeyResponse {
// the master public key
bytes pubkey = 1;
// The timestamp for the processing of the request
int64 timestamp = 2;
// Use the sr25519 algorithm to sign the timestamp fields above (use it's Big-Endian bytes)
bytes signature = 3;
}

message Podr2PubkeyResponse {
// the PODR2 public key
bytes pubkey = 1;
// The timestamp for the processing of the request
int64 timestamp = 2;
// Use the RSA algorithm to sign the timestamp fields above (use it's Big-Endian bytes)
bytes signature = 3;
}
4 changes: 4 additions & 0 deletions crates/cestory/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ pub mod pois {
pub mod podr2 {
tonic::include_proto!("podr2");
}

pub mod pubkeys {
tonic::include_proto!("ceseal.pubkeys");
}
7 changes: 7 additions & 0 deletions crates/cestory/src/expert.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::types::MasterKey;

use super::{
pal::Platform, system::WorkerIdentityKey, types::ThreadPoolSafeBox, CesealProperties, CesealSafeBox, ChainStorage,
};
Expand Down Expand Up @@ -99,6 +101,10 @@ impl CesealExpertStub {
self.ceseal_props.identity_key.public()
}

pub fn master_key(&self) -> &MasterKey {
&self.ceseal_props.master_key
}

pub fn podr2_key(&self) -> &ces_pdp::Keys {
&self.ceseal_props.podr2_key
}
Expand Down Expand Up @@ -180,6 +186,7 @@ mod test {
let ceseal_props = CesealProperties {
role: WorkerRole::Full,
podr2_key: any_podr2_key(),
master_key: new_sr25519_key(),
identity_key: any_identity_key(),
cores: 2,
};
Expand Down
11 changes: 7 additions & 4 deletions crates/cestory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub mod expert;
mod light_validation;
pub mod podr2;
pub mod pois;
mod pubkeys;
mod secret_channel;
mod storage;
mod system;
Expand Down Expand Up @@ -833,7 +834,7 @@ async fn run_external_server<Platform>(
//FIXME: SHOULD BE DISABLE LOG KEY ON PRODUCTION !!!
debug!(
"Successfully load podr2 key public key is: {:?}",
&ceseal_props.podr2_key.pkey.to_pkcs1_der().unwrap().as_bytes()
hex::encode(&ceseal_props.podr2_key.pkey.to_pkcs1_der().unwrap().as_bytes())
);

let (ceseal_expert, expert_cmd_rx) = expert::CesealExpertStub::new(ceseal_props.clone());
Expand Down Expand Up @@ -862,9 +863,10 @@ async fn run_external_server<Platform>(
let pois_srv = pois::new_pois_certifier_api_server(pois_param.clone(), ceseal_expert.clone())
.max_decoding_message_size(MAX_DECODED_MSG_SIZE)
.max_encoding_message_size(MAX_ENCODED_MSG_SIZE);
let poisv_srv = pois::new_pois_verifier_api_server(pois_param, ceseal_expert)
let poisv_srv = pois::new_pois_verifier_api_server(pois_param, ceseal_expert.clone())
.max_decoding_message_size(MAX_DECODED_MSG_SIZE)
.max_encoding_message_size(MAX_ENCODED_MSG_SIZE);
let pubkeys = pubkeys::new_pubkeys_provider_server(ceseal_expert);

info!(
"keyfairy ready, external server will listening on {} run with {:?} role",
Expand All @@ -873,12 +875,13 @@ async fn run_external_server<Platform>(
let mut server = Server::builder();
let router = match ceseal_props.role {
ces_types::WorkerRole::Full => server
.add_service(pubkeys)
.add_service(podr2_srv)
.add_service(podr2v_srv)
.add_service(pois_srv)
.add_service(poisv_srv),
ces_types::WorkerRole::Verifier => server.add_service(podr2v_srv).add_service(poisv_srv),
ces_types::WorkerRole::Marker => server.add_service(podr2_srv).add_service(pois_srv),
ces_types::WorkerRole::Verifier => server.add_service(pubkeys).add_service(podr2v_srv).add_service(poisv_srv),
ces_types::WorkerRole::Marker => server.add_service(pubkeys).add_service(podr2_srv).add_service(pois_srv),
};
let result = router.serve(public_listener_addr).await;
let _ = ext_srv_quit_tx.send(result);
Expand Down
63 changes: 49 additions & 14 deletions crates/cestory/src/podr2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{expert::CesealExpertStub, types::ThreadPoolSafeBox};
use crate::{
expert::{CesealExpertStub, ExternalResourceKind},
types::ThreadPoolSafeBox,
};
use anyhow::{anyhow, Result};
use ces_crypto::sr25519::Signing;
use ces_pdp::{HashSelf, Keys, QElement, Tag as PdpTag};
Expand Down Expand Up @@ -38,6 +41,7 @@ pub fn new_podr2_api_server(ceseal_expert: CesealExpertStub) -> Podr2ApiServer {
threadpool: ceseal_expert.thread_pool(),
block_num: 1024,
ceseal_identity_key: ceseal_expert.identify_public_key().0,
ceseal_expert: ceseal_expert.clone(),
},
ceseal_expert,
};
Expand Down Expand Up @@ -66,6 +70,7 @@ pub struct Podr2Server {
pub threadpool: ThreadPoolSafeBox,
pub block_num: u64,
pub ceseal_identity_key: [u8; 32],
pub ceseal_expert: CesealExpertStub,
}

pub struct Podr2VerifierServer {
Expand Down Expand Up @@ -144,10 +149,25 @@ impl Podr2Api for Podr2Server {
threadpool: self.threadpool.clone(),
block_num: self.block_num.clone(),
ceseal_identity_key: self.ceseal_identity_key.clone(),
ceseal_expert: self.ceseal_expert.clone(),
};
//start receive
tokio::spawn(async move {
while let Some(result) = in_stream.next().await {
let _permit = match new_self
.ceseal_expert
.try_acquire_permit(ExternalResourceKind::Pord2Service)
.await
{
Ok(p) => p,
Err(err) => {
resp_tx
.send(Err(Status::internal(err.to_string())))
.await
.expect("send failure of permit locking msg fail");
return
},
};
match result {
Ok(v) => {
if v.fragment_data.is_empty() && stream_rec_times == 0 {
Expand All @@ -166,7 +186,7 @@ impl Podr2Api for Podr2Server {
continue
};
if !v.fragment_data.is_empty() && stream_rec_times == 1 {
match new_self.process_gen_tag_request(v) {
match new_self.process_gen_tag_request(v).await {
Ok(response) => resp_tx
.send(Ok(response))
.await
Expand Down Expand Up @@ -354,7 +374,7 @@ fn convert_to_q_elements(qslices: Qslice) -> Result<(Vec<QElement>, Challenge),
}

impl Podr2Server {
fn process_gen_tag_request<'life0>(&'life0 self, request: RequestGenTag) -> Result<ResponseGenTag, Status> {
async fn process_gen_tag_request<'life0>(&'life0 self, request: RequestGenTag) -> Result<ResponseGenTag, Status> {
let now = Instant::now();
let mut h = Podr2Hash::new();
h.load_field(request.custom_data.as_bytes());
Expand All @@ -369,10 +389,6 @@ impl Podr2Server {
.try_into()
.map_err(|_| Status::invalid_argument("file_name hash bytes length should be 64".to_string()))?;

let pool = self
.threadpool
.lock()
.map_err(|e| Status::internal("lock global threadpool fail:".to_string() + &e.to_string()))?;
//check fragement data is equal to fragement name
let mut check_fragment_hash = Podr2Hash::new();
check_fragment_hash.load_field(&request.fragment_data);
Expand All @@ -384,13 +400,6 @@ impl Podr2Server {
&request.fragment_name, &fragment_data_hash_string
)))
}
let tag = self
.podr2_keys
.sig_gen_with_data(request.fragment_data, self.block_num, &request.fragment_name, h, pool.clone())
.map_err(|e| Status::internal(format!("AlgorithmError: {}", e.error_code.to_string())))?;
let u_sig = self.podr2_keys.sign_data(&calculate_hash(tag.t.u.as_bytes())).map_err(|e| {
Status::invalid_argument(format!("Failed to calculate u's signature {:?}", e.error_code.to_string()))
})?;

let mut tag_sig_info_history = TagSigInfo {
miner: AccountId32::from_slice(&request.miner_id[..])
Expand Down Expand Up @@ -440,6 +449,32 @@ impl Podr2Server {
.sign_data(&calculate_hash(&tag_sig_info_history.encode()))
.0
.to_vec();
let new_self = Podr2Server {
podr2_keys: self.podr2_keys.clone(),
master_key: self.master_key.clone(),
threadpool: self.threadpool.clone(),
block_num: self.block_num.clone(),
ceseal_identity_key: self.ceseal_identity_key.clone(),
ceseal_expert: self.ceseal_expert.clone(),
};
let tag = tokio::task::spawn_blocking(move || {
let pool = new_self
.threadpool
.lock()
.map_err(|e| Status::internal("lock global threadpool fail:".to_string() + &e.to_string()))?;
new_self
.podr2_keys
.sig_gen_with_data(request.fragment_data, new_self.block_num, &request.fragment_name, h, pool.clone())
.map_err(|_| Status::invalid_argument("Algorithm error".to_string()))
})
.await
.map_err(|_| Status::invalid_argument("Waiting for tag generate fail".to_string()))??;

//compute u signature
let u_sig = self.podr2_keys.sign_data(&calculate_hash(tag.t.u.as_bytes())).map_err(|e| {
Status::invalid_argument(format!("Failed to calculate u's signature {:?}", e.error_code.to_string()))
})?;

info!("[🚀Generate tag] PoDR2 Sig Gen Completed in: {:.2?}. file name is {:?}", now.elapsed(), &tag.t.name);
Ok(ResponseGenTag {
processing: true,
Expand Down
91 changes: 91 additions & 0 deletions crates/cestory/src/pubkeys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use crate::expert::CesealExpertStub;
use cestory_api::pubkeys::{
ceseal_pubkeys_provider_server::{
CesealPubkeysProvider, CesealPubkeysProviderServer as CesealPubkeysProviderServerPb,
},
IdentityPubkeyResponse, MasterPubkeyResponse, Podr2PubkeyResponse, Request as InnerReq,
};
use sp_core::{crypto::AccountId32, ByteArray, Pair};
use std::result::Result as StdResult;
use tonic::{Request, Response, Status};

pub type Result<T> = StdResult<Response<T>, Status>;
pub type CesealPubkeysProviderServer = CesealPubkeysProviderServerPb<CesealPubkeysProviderImpl>;

pub struct CesealPubkeysProviderImpl {
ceseal_expert: CesealExpertStub,
}

pub fn new_pubkeys_provider_server(ceseal_expert: CesealExpertStub) -> CesealPubkeysProviderServer {
CesealPubkeysProviderServerPb::new(CesealPubkeysProviderImpl { ceseal_expert })
}

async fn is_storage_miner_registered_on_chain(
ceseal_expert: &CesealExpertStub,
account_id: &[u8],
) -> StdResult<(), Status> {
let account_id = AccountId32::from_slice(account_id).map_err(|_| Status::internal("invalid input account"))?;
let registered = ceseal_expert
.using_chain_storage(move |opt| {
if let Some(cs) = opt {
cs.is_storage_miner_registered_ignore_state(account_id)
} else {
false
}
})
.await
.map_err(|e| Status::internal(format!("internal error: {}", e.to_string())))?;
if !registered {
return Err(Status::internal("the storage miner is not registered on the chain"))
}
Ok(())
}

#[tonic::async_trait]
impl CesealPubkeysProvider for CesealPubkeysProviderImpl {
async fn get_identity_pubkey(&self, request: Request<InnerReq>) -> Result<IdentityPubkeyResponse> {
let request = request.into_inner();
is_storage_miner_registered_on_chain(&self.ceseal_expert, &request.storage_miner_account_id[..]).await?;
let now_ts = chrono::Utc::now().timestamp_millis();
let pubkey = self.ceseal_expert.identify_public_key();
let sign = self.ceseal_expert.identity_key().sign(&now_ts.to_be_bytes());
Ok(Response::new(IdentityPubkeyResponse {
pubkey: pubkey.to_raw_vec(),
timestamp: now_ts,
signature: sign.0.to_vec(),
}))
}

async fn get_master_pubkey(&self, request: Request<InnerReq>) -> Result<MasterPubkeyResponse> {
let request = request.into_inner();
is_storage_miner_registered_on_chain(&self.ceseal_expert, &request.storage_miner_account_id[..]).await?;
let now_ts = chrono::Utc::now().timestamp_millis();
let pubkey = self.ceseal_expert.master_key().public();
let sign = self.ceseal_expert.master_key().sign(&now_ts.to_be_bytes());
Ok(Response::new(MasterPubkeyResponse {
pubkey: pubkey.to_raw_vec(),
timestamp: now_ts,
signature: sign.0.to_vec(),
}))
}

async fn get_podr2_pubkey(&self, request: Request<InnerReq>) -> Result<Podr2PubkeyResponse> {
use rsa::{pkcs1::EncodeRsaPublicKey, Pkcs1v15Sign};

let request = request.into_inner();
is_storage_miner_registered_on_chain(&self.ceseal_expert, &request.storage_miner_account_id[..]).await?;
let now_ts = chrono::Utc::now().timestamp_millis();
let pubkey = self.ceseal_expert.podr2_key().pkey.clone();
let pubkey = pubkey
.to_pkcs1_der()
.map_err(|e| Status::internal(format!("PKCS#1-encoding Podr2 public key error: {:?}", e)))?
.to_vec();
let sign = self
.ceseal_expert
.podr2_key()
.skey
.sign(Pkcs1v15Sign::new_raw(), &now_ts.to_be_bytes())
.map_err(|e| Status::internal(format!("Podr2 key sign error: {:?}", e)))?;
Ok(Response::new(Podr2PubkeyResponse { pubkey, timestamp: now_ts, signature: sign }))
}
}
4 changes: 4 additions & 0 deletions crates/cestory/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ mod storage_ext {
self.execute_with(|| pallet_sminer::pallet::Pallet::miner_items(miner_account_id))
}

pub fn is_storage_miner_registered_ignore_state(&self, miner_account_id: AccountId) -> bool {
self.get_storage_miner_info(miner_account_id).is_some()
}

/// Return `None` if given ceseal hash is not allowed on-chain
pub(crate) fn get_ceseal_bin_added_at(&self, runtime_hash: &[u8]) -> Option<chain::BlockNumber> {
self.execute_with(|| pallet_tee_worker::CesealBinAddedAt::<chain::Runtime>::get(runtime_hash))
Expand Down
Loading
Loading