Compare commits
1 Commits
37d45f5b74
...
6ca02e91b9
Author | SHA1 | Date | |
---|---|---|---|
6ca02e91b9 |
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -246,7 +246,7 @@ dependencies = [
|
|||||||
"prost-types",
|
"prost-types",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_yaml",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
@ -307,6 +307,7 @@ dependencies = [
|
|||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"serde",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
@ -403,6 +404,7 @@ dependencies = [
|
|||||||
"lock_api",
|
"lock_api",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot_core",
|
"parking_lot_core",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -418,7 +420,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "detee-shared"
|
name = "detee-shared"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+ssh://git@gitea.detee.cloud/noormohammedb/detee-shared?branch=stable_01#b8f37dec1845d29ea0b69035712e6ebb214376f4"
|
source = "git+ssh://git@gitea.detee.cloud/noormohammedb/detee-shared?branch=stable_01#099f0a0488bce8e59c9c9e9a5e9b1f24998f1633"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"prost",
|
"prost",
|
||||||
|
@ -5,16 +5,16 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bs58 = "0.5.1"
|
bs58 = "0.5.1"
|
||||||
chrono = "0.4.39"
|
chrono = { version = "0.4.39", features = ["serde"] }
|
||||||
dashmap = "6.1.0"
|
dashmap = { version = "6.1.0", features = ["serde"] }
|
||||||
ed25519-dalek = "2.1.1"
|
ed25519-dalek = "2.1.1"
|
||||||
env_logger = "0.11.6"
|
env_logger = "0.11.6"
|
||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
prost = "0.13.4"
|
prost = "0.13.4"
|
||||||
prost-types = "0.13.4"
|
prost-types = "0.13.4"
|
||||||
reqwest = "0.12.10"
|
reqwest = "0.12.10"
|
||||||
serde = { version = "1.0.216", features = ["derive"] }
|
serde = { version = "1.0.217", features = ["derive"] }
|
||||||
serde_json = "1.0.134"
|
serde_yaml = "0.9.34"
|
||||||
thiserror = "2.0.11"
|
thiserror = "2.0.11"
|
||||||
tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] }
|
||||||
tokio-stream = "0.1.17"
|
tokio-stream = "0.1.17"
|
||||||
|
768
src/data.rs
768
src/data.rs
File diff suppressed because it is too large
Load Diff
336
src/grpc.rs
336
src/grpc.rs
@ -1,5 +1,3 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
pub mod snp_proto {
|
pub mod snp_proto {
|
||||||
tonic::include_proto!("vm_proto");
|
tonic::include_proto!("vm_proto");
|
||||||
}
|
}
|
||||||
@ -19,12 +17,13 @@ use tonic::{Request, Response, Status, Streaming};
|
|||||||
use detee_shared::sgx::pb::brain::brain_app_cli_server::BrainAppCli;
|
use detee_shared::sgx::pb::brain::brain_app_cli_server::BrainAppCli;
|
||||||
use detee_shared::sgx::pb::brain::brain_app_daemon_server::BrainAppDaemon;
|
use detee_shared::sgx::pb::brain::brain_app_daemon_server::BrainAppDaemon;
|
||||||
use detee_shared::sgx::pb::brain::{
|
use detee_shared::sgx::pb::brain::{
|
||||||
AppContract, BrainMessageApp, DaemonMessageApp, DelAppReq, ListAppContractsReq, NewAppReq,
|
AppContract, AppNodeFilters, AppNodeListResp, BrainMessageApp, DaemonMessageApp, DelAppReq,
|
||||||
NewAppRes, RegisterAppNodeReq,
|
ListAppContractsReq, NewAppReq, NewAppRes, RegisterAppNodeReq,
|
||||||
};
|
};
|
||||||
const ADMIN_ACCOUNTS: &[&str] = &[
|
const ADMIN_ACCOUNTS: &[&str] = &[
|
||||||
"x52w7jARC5erhWWK65VZmjdGXzBK6ZDgfv1A283d8XK",
|
"x52w7jARC5erhWWK65VZmjdGXzBK6ZDgfv1A283d8XK",
|
||||||
"FHuecMbeC1PfjkW2JKyoicJAuiU7khgQT16QUB3Q1XdL",
|
"FHuecMbeC1PfjkW2JKyoicJAuiU7khgQT16QUB3Q1XdL",
|
||||||
|
"H21Shi4iE7vgfjWEQNvzmpmBMJSaiZ17PYUcdNoAoKNc",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub struct BrainDaemonMock {
|
pub struct BrainDaemonMock {
|
||||||
@ -78,7 +77,7 @@ impl BrainVmDaemon for BrainDaemonMock {
|
|||||||
info!("Starting registration process for {:?}", req);
|
info!("Starting registration process for {:?}", req);
|
||||||
let node = crate::data::VmNode {
|
let node = crate::data::VmNode {
|
||||||
public_key: req.node_pubkey.clone(),
|
public_key: req.node_pubkey.clone(),
|
||||||
owner_key: req.owner_pubkey,
|
operator_wallet: req.operator_wallet,
|
||||||
country: req.country,
|
country: req.country,
|
||||||
region: req.region,
|
region: req.region,
|
||||||
city: req.city,
|
city: req.city,
|
||||||
@ -86,10 +85,10 @@ impl BrainVmDaemon for BrainDaemonMock {
|
|||||||
price: req.price,
|
price: req.price,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
self.data.insert_node(node);
|
self.data.register_node(node);
|
||||||
|
|
||||||
info!("Sending existing contracts to {}", req.node_pubkey);
|
info!("Sending existing contracts to {}", req.node_pubkey);
|
||||||
let contracts = self.data.find_contracts_by_node_pubkey(&req.node_pubkey);
|
let contracts = self.data.find_vm_contracts_by_node(&req.node_pubkey);
|
||||||
let (tx, rx) = mpsc::channel(6);
|
let (tx, rx) = mpsc::channel(6);
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
for contract in contracts {
|
for contract in contracts {
|
||||||
@ -187,6 +186,14 @@ impl BrainCli for BrainCliMock {
|
|||||||
async fn new_vm(&self, req: Request<NewVmReq>) -> Result<Response<NewVmResp>, Status> {
|
async fn new_vm(&self, req: Request<NewVmReq>) -> Result<Response<NewVmResp>, Status> {
|
||||||
let req = check_sig_from_req(req)?;
|
let req = check_sig_from_req(req)?;
|
||||||
info!("New VM requested via CLI: {req:?}");
|
info!("New VM requested via CLI: {req:?}");
|
||||||
|
if self
|
||||||
|
.data
|
||||||
|
.is_user_banned_by_node(&req.admin_pubkey, &req.node_pubkey)
|
||||||
|
{
|
||||||
|
return Err(Status::permission_denied(
|
||||||
|
"This operator banned you. What did you do?",
|
||||||
|
));
|
||||||
|
}
|
||||||
let admin_pubkey = req.admin_pubkey.clone();
|
let admin_pubkey = req.admin_pubkey.clone();
|
||||||
let (oneshot_tx, oneshot_rx) = tokio::sync::oneshot::channel();
|
let (oneshot_tx, oneshot_rx) = tokio::sync::oneshot::channel();
|
||||||
self.data.submit_newvm_req(req, oneshot_tx).await;
|
self.data.submit_newvm_req(req, oneshot_tx).await;
|
||||||
@ -214,9 +221,9 @@ impl BrainCli for BrainCliMock {
|
|||||||
info!("Sending UpdateVMResp: {response:?}");
|
info!("Sending UpdateVMResp: {response:?}");
|
||||||
Ok(Response::new(response))
|
Ok(Response::new(response))
|
||||||
}
|
}
|
||||||
Err(_) => Err(Status::unknown(
|
Err(e) => Err(Status::unknown(format!(
|
||||||
"Update VM request failed due to error: {e}",
|
"Update VM request failed due to error: {e}"
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,20 +238,55 @@ impl BrainCli for BrainCliMock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn delete_vm(&self, req: Request<DeleteVmReq>) -> Result<Response<Empty>, Status> {
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
match self.data.delete_vm(req).await {
|
||||||
|
Ok(()) => Ok(Response::new(Empty {})),
|
||||||
|
Err(e) => Err(Status::not_found(e.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn report_node(&self, req: Request<ReportNodeReq>) -> Result<Response<Empty>, Status> {
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
match self.data.find_contract_by_uuid(&req.contract) {
|
||||||
|
Ok(contract)
|
||||||
|
if contract.admin_pubkey == req.admin_pubkey
|
||||||
|
&& contract.node_pubkey == req.node_pubkey =>
|
||||||
|
{
|
||||||
|
()
|
||||||
|
}
|
||||||
|
_ => return Err(Status::unauthenticated("No contract found by this ID.")),
|
||||||
|
};
|
||||||
|
self.data
|
||||||
|
.report_node(req.admin_pubkey, &req.node_pubkey, req.reason);
|
||||||
|
Ok(Response::new(Empty {}))
|
||||||
|
}
|
||||||
|
|
||||||
type ListVmContractsStream = Pin<Box<dyn Stream<Item = Result<VmContract, Status>> + Send>>;
|
type ListVmContractsStream = Pin<Box<dyn Stream<Item = Result<VmContract, Status>> + Send>>;
|
||||||
async fn list_vm_contracts(
|
async fn list_vm_contracts(
|
||||||
&self,
|
&self,
|
||||||
req: Request<ListVmContractsReq>,
|
req: Request<ListVmContractsReq>,
|
||||||
) -> Result<Response<Self::ListVmContractsStream>, Status> {
|
) -> Result<Response<Self::ListVmContractsStream>, Status> {
|
||||||
let req = check_sig_from_req(req)?;
|
let req = check_sig_from_req(req)?;
|
||||||
info!("CLI {} requested ListVMVmContractsStream", req.admin_pubkey);
|
info!(
|
||||||
let contracts = match req.uuid.is_empty() {
|
"CLI {} requested ListVMVmContractsStream. As operator: {}",
|
||||||
false => match self.data.find_contract_by_uuid(&req.uuid) {
|
req.wallet, req.as_operator
|
||||||
Some(contract) => vec![contract],
|
);
|
||||||
None => Vec::new(),
|
let mut contracts = Vec::new();
|
||||||
},
|
if !req.uuid.is_empty() {
|
||||||
true => self.data.find_contracts_by_admin_pubkey(&req.admin_pubkey),
|
if let Ok(specific_contract) = self.data.find_contract_by_uuid(&req.uuid) {
|
||||||
};
|
if specific_contract.admin_pubkey == req.wallet {
|
||||||
|
contracts.push(specific_contract);
|
||||||
|
}
|
||||||
|
// TODO: allow operator to inspect contracts
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if req.as_operator {
|
||||||
|
contracts.append(&mut self.data.find_vm_contracts_by_operator(&req.wallet));
|
||||||
|
} else {
|
||||||
|
contracts.append(&mut self.data.find_vm_contracts_by_admin(&req.wallet));
|
||||||
|
}
|
||||||
|
}
|
||||||
let (tx, rx) = mpsc::channel(6);
|
let (tx, rx) = mpsc::channel(6);
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
for contract in contracts {
|
for contract in contracts {
|
||||||
@ -264,7 +306,7 @@ impl BrainCli for BrainCliMock {
|
|||||||
) -> Result<Response<Self::ListVmNodesStream>, tonic::Status> {
|
) -> Result<Response<Self::ListVmNodesStream>, tonic::Status> {
|
||||||
let req = check_sig_from_req(req)?;
|
let req = check_sig_from_req(req)?;
|
||||||
info!("CLI requested ListVmNodesStream: {req:?}");
|
info!("CLI requested ListVmNodesStream: {req:?}");
|
||||||
let nodes = self.data.find_nodes_by_filters(&req);
|
let nodes = self.data.find_vm_nodes_by_filters(&req);
|
||||||
let (tx, rx) = mpsc::channel(6);
|
let (tx, rx) = mpsc::channel(6);
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
for node in nodes {
|
for node in nodes {
|
||||||
@ -291,12 +333,65 @@ impl BrainCli for BrainCliMock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_vm(&self, req: Request<DeleteVmReq>) -> Result<Response<Empty>, Status> {
|
async fn register_operator(
|
||||||
|
&self,
|
||||||
|
req: Request<RegOperatorReq>,
|
||||||
|
) -> Result<Response<Empty>, Status> {
|
||||||
let req = check_sig_from_req(req)?;
|
let req = check_sig_from_req(req)?;
|
||||||
info!("Unknown CLI requested to delete vm {}", req.uuid);
|
info!("Regitering new operator: {req:?}");
|
||||||
match self.data.delete_vm(req).await {
|
match self.data.register_operator(req) {
|
||||||
Ok(()) => Ok(Response::new(Empty {})),
|
Ok(()) => Ok(Response::new(Empty {})),
|
||||||
Err(e) => Err(Status::not_found(e.to_string())),
|
Err(e) => Err(Status::failed_precondition(e.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn kick_contract(&self, req: Request<KickReq>) -> Result<Response<KickResp>, Status> {
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
match self
|
||||||
|
.data
|
||||||
|
.kick_contract(&req.operator_wallet, &req.contract_uuid, &req.reason)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(nano_lp) => Ok(Response::new(KickResp { nano_lp })),
|
||||||
|
Err(e) => Err(Status::permission_denied(e.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn ban_user(&self, req: Request<BanUserReq>) -> Result<Response<Empty>, Status> {
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
self.data.ban_user(&req.operator_wallet, &req.user_wallet);
|
||||||
|
Ok(Response::new(Empty {}))
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListOperatorsStream =
|
||||||
|
Pin<Box<dyn Stream<Item = Result<ListOperatorsResp, Status>> + Send>>;
|
||||||
|
async fn list_operators(
|
||||||
|
&self,
|
||||||
|
req: Request<Empty>,
|
||||||
|
) -> Result<Response<Self::ListOperatorsStream>, Status> {
|
||||||
|
let _ = check_sig_from_req(req)?;
|
||||||
|
let operators = self.data.list_operators();
|
||||||
|
let (tx, rx) = mpsc::channel(6);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
for op in operators {
|
||||||
|
let _ = tx.send(Ok(op.into())).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let output_stream = ReceiverStream::new(rx);
|
||||||
|
Ok(Response::new(
|
||||||
|
Box::pin(output_stream) as Self::ListOperatorsStream
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn inspect_operator(
|
||||||
|
&self,
|
||||||
|
req: Request<Pubkey>,
|
||||||
|
) -> Result<Response<InspectOperatorResp>, Status> {
|
||||||
|
match self.data.inspect_operator(&req.into_inner().pubkey) {
|
||||||
|
Some(op) => Ok(Response::new(op.into())),
|
||||||
|
None => Err(Status::not_found(
|
||||||
|
"The wallet you specified is not an operator",
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +402,13 @@ impl BrainCli for BrainCliMock {
|
|||||||
Ok(Response::new(Empty {}))
|
Ok(Response::new(Empty {}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn slash(&self, req: Request<SlashReq>) -> Result<Response<Empty>, Status> {
|
||||||
|
check_admin_key(&req)?;
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
self.data.slash_account(&req.pubkey, req.tokens);
|
||||||
|
Ok(Response::new(Empty {}))
|
||||||
|
}
|
||||||
|
|
||||||
type ListAllVmContractsStream = Pin<Box<dyn Stream<Item = Result<VmContract, Status>> + Send>>;
|
type ListAllVmContractsStream = Pin<Box<dyn Stream<Item = Result<VmContract, Status>> + Send>>;
|
||||||
async fn list_all_vm_contracts(
|
async fn list_all_vm_contracts(
|
||||||
&self,
|
&self,
|
||||||
@ -352,17 +454,14 @@ trait PubkeyGetter {
|
|||||||
fn get_pubkey(&self) -> Option<String>;
|
fn get_pubkey(&self) -> Option<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PubkeyGetter for Pubkey {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
Some(self.pubkey.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl BrainAppCli for BrainAppCliMock {
|
impl BrainAppCli for BrainAppCliMock {
|
||||||
type ListAppContractsStream = Pin<Box<dyn Stream<Item = Result<AppContract, Status>> + Send>>;
|
type ListAppContractsStream = Pin<Box<dyn Stream<Item = Result<AppContract, Status>> + Send>>;
|
||||||
|
type ListAppNodesStream = Pin<Box<dyn Stream<Item = Result<AppNodeListResp, Status>> + Send>>;
|
||||||
|
type ListAllAppContractsStream =
|
||||||
|
Pin<Box<dyn Stream<Item = Result<AppContract, Status>> + Send>>;
|
||||||
|
|
||||||
async fn create_app(
|
async fn deploy_app(
|
||||||
&self,
|
&self,
|
||||||
req: tonic::Request<NewAppReq>,
|
req: tonic::Request<NewAppReq>,
|
||||||
) -> Result<tonic::Response<NewAppRes>, Status> {
|
) -> Result<tonic::Response<NewAppRes>, Status> {
|
||||||
@ -420,6 +519,54 @@ impl BrainAppCli for BrainAppCliMock {
|
|||||||
Box::pin(output_stream) as Self::ListAppContractsStream
|
Box::pin(output_stream) as Self::ListAppContractsStream
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn list_app_nodes(
|
||||||
|
&self,
|
||||||
|
req: tonic::Request<AppNodeFilters>,
|
||||||
|
) -> Result<tonic::Response<Self::ListAppNodesStream>, Status> {
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
info!("CLI requested ListAppNodes: {req:?}");
|
||||||
|
let nodes = self.data.find_app_nodes_by_filters(&req);
|
||||||
|
let (tx, rx) = mpsc::channel(6);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
for node in nodes {
|
||||||
|
let _ = tx.send(Ok(node.into())).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let output_stream = ReceiverStream::new(rx);
|
||||||
|
Ok(Response::new(Box::pin(output_stream)))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_one_app_node(
|
||||||
|
&self,
|
||||||
|
req: tonic::Request<AppNodeFilters>,
|
||||||
|
) -> Result<tonic::Response<AppNodeListResp>, Status> {
|
||||||
|
let req = check_sig_from_req(req)?;
|
||||||
|
info!("CLI requested GetOneAppNode: {req:?}");
|
||||||
|
match self.data.get_one_app_node_by_filters(&req) {
|
||||||
|
Some(node) => Ok(Response::new(node.into())),
|
||||||
|
None => Err(Status::not_found(
|
||||||
|
"Could not find any node based on your search criteria",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_all_app_contracts(
|
||||||
|
&self,
|
||||||
|
req: tonic::Request<detee_shared::sgx::pb::brain::Empty>,
|
||||||
|
) -> Result<tonic::Response<Self::ListAllAppContractsStream>, Status> {
|
||||||
|
check_admin_key(&req)?;
|
||||||
|
let _ = check_sig_from_req(req)?;
|
||||||
|
let contracts = self.data.list_all_app_contracts();
|
||||||
|
let (tx, rx) = mpsc::channel(6);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
for contract in contracts {
|
||||||
|
let _ = tx.send(Ok(contract.into())).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let output_stream = ReceiverStream::new(rx);
|
||||||
|
Ok(Response::new(Box::pin(output_stream)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
@ -435,26 +582,22 @@ impl BrainAppDaemon for BrainAppDaemonMock {
|
|||||||
log::info!(
|
log::info!(
|
||||||
"registering app node_key : {}, operator_key: {}",
|
"registering app node_key : {}, operator_key: {}",
|
||||||
&req_data.node_pubkey,
|
&req_data.node_pubkey,
|
||||||
&req_data.operator_pubkey
|
&req_data.operator_wallet
|
||||||
);
|
);
|
||||||
|
|
||||||
let app_node = crate::data::AppNode {
|
let app_node = crate::data::AppNode {
|
||||||
node_pubkey: req_data.node_pubkey.clone(),
|
node_pubkey: req_data.node_pubkey.clone(),
|
||||||
operator_pubkey: req_data.operator_pubkey,
|
operator_wallet: req_data.operator_wallet,
|
||||||
ip: req_data.main_ip,
|
ip: req_data.main_ip,
|
||||||
city: req_data.city,
|
city: req_data.city,
|
||||||
region: req_data.region,
|
region: req_data.region,
|
||||||
country: req_data.country,
|
country: req_data.country,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
self.data.register_app_node(app_node);
|
||||||
|
|
||||||
self.data.insert_app_node(app_node);
|
|
||||||
log::info!("Sending existing contracts to {}", &req_data.node_pubkey);
|
log::info!("Sending existing contracts to {}", &req_data.node_pubkey);
|
||||||
|
let app_contracts = self.data.find_app_contracts_by_node(&req_data.node_pubkey);
|
||||||
let app_contracts = self
|
|
||||||
.data
|
|
||||||
.find_app_contracts_by_node_pubkey(&req_data.node_pubkey);
|
|
||||||
|
|
||||||
let (tx, rx) = mpsc::channel(6);
|
let (tx, rx) = mpsc::channel(6);
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
for contract in app_contracts {
|
for contract in app_contracts {
|
||||||
@ -549,83 +692,48 @@ impl BrainAppDaemon for BrainAppDaemonMock {
|
|||||||
Ok(Response::new(detee_shared::sgx::pb::brain::Empty {}))
|
Ok(Response::new(detee_shared::sgx::pb::brain::Empty {}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl PubkeyGetter for NewVmReq {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
macro_rules! impl_pubkey_getter {
|
||||||
Some(self.admin_pubkey.clone())
|
($t:ty, $field:ident) => {
|
||||||
}
|
impl PubkeyGetter for $t {
|
||||||
|
fn get_pubkey(&self) -> Option<String> {
|
||||||
|
Some(self.$field.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($t:ty) => {
|
||||||
|
impl PubkeyGetter for $t {
|
||||||
|
fn get_pubkey(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PubkeyGetter for DeleteVmReq {
|
impl_pubkey_getter!(Pubkey, pubkey);
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
impl_pubkey_getter!(NewVmReq, admin_pubkey);
|
||||||
Some(self.admin_pubkey.clone())
|
impl_pubkey_getter!(DeleteVmReq, admin_pubkey);
|
||||||
}
|
impl_pubkey_getter!(UpdateVmReq, admin_pubkey);
|
||||||
}
|
impl_pubkey_getter!(ExtendVmReq, admin_pubkey);
|
||||||
|
impl_pubkey_getter!(ReportNodeReq, admin_pubkey);
|
||||||
|
impl_pubkey_getter!(ListVmContractsReq, wallet);
|
||||||
|
impl_pubkey_getter!(RegisterVmNodeReq, node_pubkey);
|
||||||
|
impl_pubkey_getter!(RegOperatorReq, pubkey);
|
||||||
|
impl_pubkey_getter!(KickReq, operator_wallet);
|
||||||
|
impl_pubkey_getter!(BanUserReq, operator_wallet);
|
||||||
|
|
||||||
impl PubkeyGetter for UpdateVmReq {
|
impl_pubkey_getter!(VmNodeFilters);
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
impl_pubkey_getter!(Empty);
|
||||||
Some(self.admin_pubkey.clone())
|
impl_pubkey_getter!(AirdropReq);
|
||||||
}
|
impl_pubkey_getter!(SlashReq);
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for ExtendVmReq {
|
impl_pubkey_getter!(NewAppReq, admin_pubkey);
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
impl_pubkey_getter!(DelAppReq, admin_pubkey);
|
||||||
Some(self.admin_pubkey.clone())
|
impl_pubkey_getter!(ListAppContractsReq, admin_pubkey);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for ListVmContractsReq {
|
impl_pubkey_getter!(RegisterAppNodeReq);
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
impl_pubkey_getter!(detee_shared::sgx::pb::brain::Empty);
|
||||||
Some(self.admin_pubkey.clone())
|
impl_pubkey_getter!(AppNodeFilters);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for VmNodeFilters {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for RegisterVmNodeReq {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
Some(self.node_pubkey.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for Empty {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for AirdropReq {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for RegisterAppNodeReq {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for NewAppReq {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
Some(self.admin_pubkey.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for DelAppReq {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
Some(self.admin_pubkey.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PubkeyGetter for ListAppContractsReq {
|
|
||||||
fn get_pubkey(&self) -> Option<String> {
|
|
||||||
Some(self.admin_pubkey.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Result<T, Status> {
|
fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Result<T, Status> {
|
||||||
let time = match req.metadata().get("timestamp") {
|
let time = match req.metadata().get("timestamp") {
|
||||||
@ -640,9 +748,9 @@ fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Res
|
|||||||
let parsed_time = chrono::DateTime::parse_from_rfc3339(time)
|
let parsed_time = chrono::DateTime::parse_from_rfc3339(time)
|
||||||
.map_err(|_| Status::unauthenticated("Coult not parse timestamp"))?;
|
.map_err(|_| Status::unauthenticated("Coult not parse timestamp"))?;
|
||||||
let seconds_elapsed = now.signed_duration_since(parsed_time).num_seconds();
|
let seconds_elapsed = now.signed_duration_since(parsed_time).num_seconds();
|
||||||
if seconds_elapsed > 1 || seconds_elapsed < -1 {
|
if seconds_elapsed > 4 || seconds_elapsed < -4 {
|
||||||
return Err(Status::unauthenticated(format!(
|
return Err(Status::unauthenticated(format!(
|
||||||
"Date is not within 1 sec of the time of the server: CLI {} vs Server {}",
|
"Date is not within 4 sec of the time of the server: CLI {} vs Server {}",
|
||||||
parsed_time, now
|
parsed_time, now
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@ -695,9 +803,9 @@ fn check_sig_from_parts(pubkey: &str, time: &str, msg: &str, sig: &str) -> Resul
|
|||||||
let parsed_time = chrono::DateTime::parse_from_rfc3339(time)
|
let parsed_time = chrono::DateTime::parse_from_rfc3339(time)
|
||||||
.map_err(|_| Status::unauthenticated("Coult not parse timestamp"))?;
|
.map_err(|_| Status::unauthenticated("Coult not parse timestamp"))?;
|
||||||
let seconds_elapsed = now.signed_duration_since(parsed_time).num_seconds();
|
let seconds_elapsed = now.signed_duration_since(parsed_time).num_seconds();
|
||||||
if seconds_elapsed > 1 || seconds_elapsed < -1 {
|
if seconds_elapsed > 4 || seconds_elapsed < -4 {
|
||||||
return Err(Status::unauthenticated(format!(
|
return Err(Status::unauthenticated(format!(
|
||||||
"Date is not within 1 sec of the time of the server: CLI {} vs Server {}",
|
"Date is not within 4 sec of the time of the server: CLI {} vs Server {}",
|
||||||
parsed_time, now
|
parsed_time, now
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,12 @@ async fn main() {
|
|||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(60)).await;
|
tokio::time::sleep(tokio::time::Duration::from_secs(60)).await;
|
||||||
|
data_clone.vm_nodes_cron().await;
|
||||||
data_clone.vm_contracts_cron().await;
|
data_clone.vm_contracts_cron().await;
|
||||||
|
data_clone.app_contracts_cron().await;
|
||||||
|
if let Err(e) = data_clone.save_to_disk() {
|
||||||
|
log::error!("Could not save data to disk due to error: {e}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let addr = "0.0.0.0:31337".parse().unwrap();
|
let addr = "0.0.0.0:31337".parse().unwrap();
|
||||||
|
77
vm.proto
77
vm.proto
@ -55,7 +55,7 @@ message MeasurementIP {
|
|||||||
// This should also include a block hash or similar, for auth
|
// This should also include a block hash or similar, for auth
|
||||||
message RegisterVmNodeReq {
|
message RegisterVmNodeReq {
|
||||||
string node_pubkey = 1;
|
string node_pubkey = 1;
|
||||||
string owner_pubkey = 2;
|
string operator_wallet = 2;
|
||||||
string main_ip = 3;
|
string main_ip = 3;
|
||||||
string country = 4;
|
string country = 4;
|
||||||
string region = 5;
|
string region = 5;
|
||||||
@ -154,8 +154,8 @@ service BrainVmDaemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ListVmContractsReq {
|
message ListVmContractsReq {
|
||||||
string admin_pubkey = 1;
|
string wallet = 1;
|
||||||
string node_pubkey = 2;
|
bool as_operator = 2;
|
||||||
string uuid = 3;
|
string uuid = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,15 +174,14 @@ message VmNodeFilters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message VmNodeListResp {
|
message VmNodeListResp {
|
||||||
string node_pubkey = 1;
|
string operator = 1;
|
||||||
string country = 2;
|
string node_pubkey = 2;
|
||||||
string region = 3;
|
string country = 3;
|
||||||
string city = 4;
|
string region = 4;
|
||||||
string ip = 5; // required for latency test
|
string city = 5;
|
||||||
uint32 server_rating = 6;
|
string ip = 6; // required for latency test
|
||||||
uint32 provider_rating = 7;
|
repeated string reports = 7; // TODO: this will become an enum
|
||||||
// nanoLP per unit per minute
|
uint64 price = 8; // nanoLP per unit per minute
|
||||||
uint64 price = 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message ExtendVmReq {
|
message ExtendVmReq {
|
||||||
@ -196,12 +195,59 @@ message AirdropReq {
|
|||||||
uint64 tokens = 2;
|
uint64 tokens = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SlashReq {
|
||||||
|
string pubkey = 1;
|
||||||
|
uint64 tokens = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message Account {
|
message Account {
|
||||||
string pubkey = 1;
|
string pubkey = 1;
|
||||||
uint64 balance = 2;
|
uint64 balance = 2;
|
||||||
uint64 tmp_locked = 3;
|
uint64 tmp_locked = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message RegOperatorReq {
|
||||||
|
string pubkey = 1;
|
||||||
|
uint64 escrow = 2;
|
||||||
|
string email = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListOperatorsResp {
|
||||||
|
string pubkey = 1;
|
||||||
|
uint64 escrow = 2;
|
||||||
|
string email = 3;
|
||||||
|
uint64 app_nodes = 4;
|
||||||
|
uint64 vm_nodes = 5;
|
||||||
|
uint64 reports = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InspectOperatorResp {
|
||||||
|
ListOperatorsResp operator = 1;
|
||||||
|
repeated VmNodeListResp nodes = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReportNodeReq {
|
||||||
|
string admin_pubkey = 1;
|
||||||
|
string node_pubkey = 2;
|
||||||
|
string contract = 3;
|
||||||
|
string reason = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message KickReq {
|
||||||
|
string operator_wallet = 1;
|
||||||
|
string contract_uuid = 2;
|
||||||
|
string reason = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BanUserReq {
|
||||||
|
string operator_wallet = 1;
|
||||||
|
string user_wallet = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message KickResp {
|
||||||
|
uint64 nano_lp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
service BrainCli {
|
service BrainCli {
|
||||||
rpc GetBalance (Pubkey) returns (AccountBalance);
|
rpc GetBalance (Pubkey) returns (AccountBalance);
|
||||||
rpc NewVm (NewVmReq) returns (NewVmResp);
|
rpc NewVm (NewVmReq) returns (NewVmResp);
|
||||||
@ -211,8 +257,15 @@ service BrainCli {
|
|||||||
rpc DeleteVm (DeleteVmReq) returns (Empty);
|
rpc DeleteVm (DeleteVmReq) returns (Empty);
|
||||||
rpc UpdateVm (UpdateVmReq) returns (UpdateVmResp);
|
rpc UpdateVm (UpdateVmReq) returns (UpdateVmResp);
|
||||||
rpc ExtendVm (ExtendVmReq) returns (Empty);
|
rpc ExtendVm (ExtendVmReq) returns (Empty);
|
||||||
|
rpc ReportNode (ReportNodeReq) returns (Empty);
|
||||||
|
rpc ListOperators (Empty) returns (stream ListOperatorsResp);
|
||||||
|
rpc InspectOperator (Pubkey) returns (InspectOperatorResp);
|
||||||
|
rpc RegisterOperator (RegOperatorReq) returns (Empty);
|
||||||
|
rpc KickContract (KickReq) returns (KickResp);
|
||||||
|
rpc BanUser (BanUserReq) returns (Empty);
|
||||||
// admin commands
|
// admin commands
|
||||||
rpc Airdrop (AirdropReq) returns (Empty);
|
rpc Airdrop (AirdropReq) returns (Empty);
|
||||||
|
rpc Slash (SlashReq) returns (Empty);
|
||||||
rpc ListAllVmContracts (Empty) returns (stream VmContract);
|
rpc ListAllVmContracts (Empty) returns (stream VmContract);
|
||||||
rpc ListAccounts (Empty) returns (stream Account);
|
rpc ListAccounts (Empty) returns (stream Account);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user