saving node info and restarts metric
Signed-off-by: Valentyn Faychuk <valy@detee.ltd>
This commit is contained in:
parent
91fe7d810d
commit
334b600a2d
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -1546,7 +1546,7 @@ dependencies = [
|
|||||||
"tonic",
|
"tonic",
|
||||||
"tonic-build",
|
"tonic-build",
|
||||||
"tower 0.5.1",
|
"tower 0.5.1",
|
||||||
"tower-http",
|
"tower-http 0.5.2",
|
||||||
"x509-parser 0.16.0",
|
"x509-parser 0.16.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2049,6 +2049,7 @@ dependencies = [
|
|||||||
"tonic",
|
"tonic",
|
||||||
"tonic-build",
|
"tonic-build",
|
||||||
"tower 0.5.1",
|
"tower 0.5.1",
|
||||||
|
"tower-http 0.6.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5708,6 +5709,37 @@ dependencies = [
|
|||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-http"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697"
|
||||||
|
dependencies = [
|
||||||
|
"async-compression",
|
||||||
|
"base64 0.22.1",
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"http 1.1.0",
|
||||||
|
"http-body 1.0.1",
|
||||||
|
"http-body-util",
|
||||||
|
"http-range-header",
|
||||||
|
"httpdate",
|
||||||
|
"iri-string",
|
||||||
|
"mime",
|
||||||
|
"mime_guess",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tower 0.5.1",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-layer"
|
name = "tower-layer"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -26,6 +26,7 @@ tonic = "0.12"
|
|||||||
rustls = "0.23"
|
rustls = "0.23"
|
||||||
tokio-rustls = "0.26"
|
tokio-rustls = "0.26"
|
||||||
tower = { version = "0.5", features = ["full"] }
|
tower = { version = "0.5", features = ["full"] }
|
||||||
|
tower-http = { version = "0.6", features = ["full"] }
|
||||||
hyper = "1.4.1"
|
hyper = "1.4.1"
|
||||||
hyper-util = "0.1.7"
|
hyper-util = "0.1.7"
|
||||||
hyper-rustls = { version = "0.27", features = ["http2"] }
|
hyper-rustls = { version = "0.27", features = ["http2"] }
|
||||||
|
104
src/datastore.rs
104
src/datastore.rs
@ -1,13 +1,20 @@
|
|||||||
use crate::persistence::Logfile;
|
use crate::persistence::{Logfile, SealError, SealedFile};
|
||||||
use dashmap::{DashMap, DashSet};
|
use dashmap::{DashMap, DashSet};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_with::{serde_as, TimestampSeconds};
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
type IP = String;
|
type IP = String;
|
||||||
pub const LOCALHOST: &str = "localhost";
|
pub const LOCALHOST: &str = "localhost";
|
||||||
|
const LOG_PATH: &str = "/host/main/logs";
|
||||||
|
const LOCAL_INFO_FILE: &str = "/host/main/node_info";
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[serde_as]
|
||||||
|
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Ord, PartialOrd)]
|
||||||
pub struct NodeInfo {
|
pub struct NodeInfo {
|
||||||
|
#[serde_as(as = "TimestampSeconds")]
|
||||||
pub started_at: SystemTime,
|
pub started_at: SystemTime,
|
||||||
|
#[serde_as(as = "TimestampSeconds")]
|
||||||
pub keepalive: SystemTime,
|
pub keepalive: SystemTime,
|
||||||
pub mint_requests: u64,
|
pub mint_requests: u64,
|
||||||
pub mints: u64,
|
pub mints: u64,
|
||||||
@ -19,27 +26,59 @@ pub struct NodeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NodeInfo {
|
impl NodeInfo {
|
||||||
pub fn newer_than(&self, other_node: &Self) -> bool {
|
pub fn is_newer_than(&self, older_self: &Self) -> bool {
|
||||||
if let Ok(duration) = self.keepalive.duration_since(other_node.keepalive) {
|
self > older_self
|
||||||
if duration > Duration::from_secs(30) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if self.mint_requests > other_node.mint_requests
|
pub fn to_json(&self) -> String {
|
||||||
|| self.net_attacks > other_node.net_attacks
|
serde_json::to_string(self).unwrap() // can fail only if time goes backwards :D
|
||||||
|| self.disk_attacks > other_node.disk_attacks
|
|
||||||
|| self.mratls_conns > other_node.mratls_conns
|
|
||||||
|| self.mints > other_node.mints
|
|
||||||
|| (self.public && !other_node.public)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log(&self, ip: &IP) {
|
pub fn log(&self, ip: &IP) {
|
||||||
if let Err(e) = Logfile::append(&format!("{}: {:?}", ip, self)) {
|
let json = format!("{{\"ip\":\"{}\",", ip) + &self.to_json()[1..];
|
||||||
println!("Could not log: {:?}", e);
|
if let Err(e) = Logfile::append(LOG_PATH, &format!("{}: {}", ip, &json)) {
|
||||||
|
println!("Could not log node info: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load() -> Self {
|
||||||
|
match Self::read(LOCAL_INFO_FILE) {
|
||||||
|
Ok(mut info) => {
|
||||||
|
info.mratls_conns = 0;
|
||||||
|
info.restarts += 1;
|
||||||
|
info
|
||||||
|
}
|
||||||
|
Err(SealError::Attack(e)) => {
|
||||||
|
println!("The local node file is corrupted: {}", e);
|
||||||
|
NodeInfo {
|
||||||
|
started_at: SystemTime::now(),
|
||||||
|
keepalive: SystemTime::now(),
|
||||||
|
mint_requests: 0,
|
||||||
|
mints: 0,
|
||||||
|
mratls_conns: 0,
|
||||||
|
net_attacks: 0,
|
||||||
|
public: false,
|
||||||
|
restarts: 0,
|
||||||
|
disk_attacks: 1, // add very first disk attack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => NodeInfo {
|
||||||
|
started_at: SystemTime::now(),
|
||||||
|
keepalive: SystemTime::now(),
|
||||||
|
mint_requests: 0,
|
||||||
|
mints: 0,
|
||||||
|
mratls_conns: 0,
|
||||||
|
net_attacks: 0,
|
||||||
|
public: false,
|
||||||
|
restarts: 0,
|
||||||
|
disk_attacks: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) {
|
||||||
|
if let Err(e) = self.write(LOCAL_INFO_FILE) {
|
||||||
|
println!("Could not save node info: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,22 +91,10 @@ pub struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn new() -> Self {
|
pub fn new_with_localhost() -> Self {
|
||||||
|
let localhost_info = NodeInfo::load();
|
||||||
let state = Self { nodes: DashMap::new(), conns: DashSet::new() };
|
let state = Self { nodes: DashMap::new(), conns: DashSet::new() };
|
||||||
state.nodes.insert(
|
state.nodes.insert(LOCALHOST.to_string(), localhost_info);
|
||||||
LOCALHOST.to_string(),
|
|
||||||
NodeInfo {
|
|
||||||
started_at: SystemTime::now(),
|
|
||||||
keepalive: SystemTime::now(),
|
|
||||||
mint_requests: 0,
|
|
||||||
mints: 0,
|
|
||||||
mratls_conns: 0,
|
|
||||||
net_attacks: 0,
|
|
||||||
public: false,
|
|
||||||
restarts: 0,
|
|
||||||
disk_attacks: 0,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +110,7 @@ impl State {
|
|||||||
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
||||||
localhost_info.mint_requests += 1;
|
localhost_info.mint_requests += 1;
|
||||||
localhost_info.log(localhost_info.key());
|
localhost_info.log(localhost_info.key());
|
||||||
|
localhost_info.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +118,7 @@ impl State {
|
|||||||
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
||||||
localhost_info.mints += 1;
|
localhost_info.mints += 1;
|
||||||
localhost_info.log(localhost_info.key());
|
localhost_info.log(localhost_info.key());
|
||||||
|
localhost_info.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +126,7 @@ impl State {
|
|||||||
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
||||||
localhost_info.mratls_conns += 1;
|
localhost_info.mratls_conns += 1;
|
||||||
localhost_info.log(localhost_info.key());
|
localhost_info.log(localhost_info.key());
|
||||||
|
localhost_info.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +134,7 @@ impl State {
|
|||||||
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
||||||
localhost_info.disk_attacks += 1;
|
localhost_info.disk_attacks += 1;
|
||||||
localhost_info.log(localhost_info.key());
|
localhost_info.log(localhost_info.key());
|
||||||
|
localhost_info.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +142,7 @@ impl State {
|
|||||||
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
|
||||||
localhost_info.net_attacks += 1;
|
localhost_info.net_attacks += 1;
|
||||||
localhost_info.log(localhost_info.key());
|
localhost_info.log(localhost_info.key());
|
||||||
|
localhost_info.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,12 +155,12 @@ impl State {
|
|||||||
/// This returns true if NodeInfo got modified.
|
/// This returns true if NodeInfo got modified.
|
||||||
pub fn process_node_update(&self, (ip, mut node_info): (String, NodeInfo)) -> bool {
|
pub fn process_node_update(&self, (ip, mut node_info): (String, NodeInfo)) -> bool {
|
||||||
if let Some(old_node) = self.nodes.get(&ip) {
|
if let Some(old_node) = self.nodes.get(&ip) {
|
||||||
if !node_info.newer_than(&old_node) {
|
if !node_info.is_newer_than(&old_node) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
node_info.public = node_info.public || old_node.public;
|
node_info.public = node_info.public || old_node.public;
|
||||||
}
|
}
|
||||||
println!("Inserting: {}, {:?}", ip, node_info);
|
println!("Inserting: {}, {}", ip, node_info.to_json());
|
||||||
node_info.log(&ip);
|
node_info.log(&ip);
|
||||||
self.nodes.insert(ip, node_info);
|
self.nodes.insert(ip, node_info);
|
||||||
true
|
true
|
||||||
|
@ -89,8 +89,7 @@ impl ConnManager {
|
|||||||
let rx_stream = BroadcastStream::new(rx).filter_map(|n| n.ok());
|
let rx_stream = BroadcastStream::new(rx).filter_map(|n| n.ok());
|
||||||
let response = client.get_updates(rx_stream).await.map_err(|e| {
|
let response = client.get_updates(rx_stream).await.map_err(|e| {
|
||||||
println!("Error connecting to {node_ip}: {e}");
|
println!("Error connecting to {node_ip}: {e}");
|
||||||
// TODO: fails few times during launch
|
self.state.increase_net_attacks();
|
||||||
//self.state.increase_net_attacks();
|
|
||||||
e
|
e
|
||||||
})?;
|
})?;
|
||||||
let mut resp_stream = response.into_inner();
|
let mut resp_stream = response.into_inner();
|
||||||
|
@ -112,6 +112,7 @@ impl MyServer {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ConnInfo {
|
struct ConnInfo {
|
||||||
addr: std::net::SocketAddr,
|
addr: std::net::SocketAddr,
|
||||||
|
#[allow(dead_code)]
|
||||||
certificates: Vec<CertificateDer<'static>>,
|
certificates: Vec<CertificateDer<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
src/main.rs
25
src/main.rs
@ -4,8 +4,10 @@ mod http_server;
|
|||||||
mod persistence;
|
mod persistence;
|
||||||
mod solana;
|
mod solana;
|
||||||
|
|
||||||
|
use crate::persistence::SealError;
|
||||||
use crate::{
|
use crate::{
|
||||||
datastore::LOCALHOST, grpc::challenge::NodeUpdate, persistence::KeysFile, solana::SolClient,
|
datastore::LOCALHOST, grpc::challenge::NodeUpdate, persistence::KeysFile,
|
||||||
|
persistence::SealedFile, solana::SolClient,
|
||||||
};
|
};
|
||||||
use datastore::State;
|
use datastore::State;
|
||||||
use detee_sgx::{InstanceMeasurement, RaTlsConfig};
|
use detee_sgx::{InstanceMeasurement, RaTlsConfig};
|
||||||
@ -33,9 +35,14 @@ pub async fn localhost_cron(state: Arc<State>, tx: Sender<NodeUpdate>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn get_sol_client(state: Arc<State>, ratls_config: RaTlsConfig) -> SolClient {
|
async fn get_sol_client(state: Arc<State>, ratls_config: RaTlsConfig) -> SolClient {
|
||||||
match KeysFile::read(KEYS_FILE, &state).await {
|
match KeysFile::read(KEYS_FILE) {
|
||||||
Ok(keys_file) => {
|
Ok(keys_file) => {
|
||||||
let sol_client = SolClient::try_from(keys_file).unwrap();
|
let sol_client = SolClient::try_from(keys_file)
|
||||||
|
.map_err(|e| {
|
||||||
|
println!("Read malformed keys from the disk: {e}");
|
||||||
|
state.increase_net_attacks();
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
println!(
|
println!(
|
||||||
"Found the following wallet saved to disk: {}",
|
"Found the following wallet saved to disk: {}",
|
||||||
sol_client.get_wallet_pubkey()
|
sol_client.get_wallet_pubkey()
|
||||||
@ -43,7 +50,13 @@ async fn get_sol_client(state: Arc<State>, ratls_config: RaTlsConfig) -> SolClie
|
|||||||
println!("Loading token mint address {}", sol_client.get_token_address());
|
println!("Loading token mint address {}", sol_client.get_token_address());
|
||||||
return sol_client;
|
return sol_client;
|
||||||
}
|
}
|
||||||
Err(e) => println!("Can't initialize using sealed keys: {e}"),
|
Err(SealError::Attack(e)) => {
|
||||||
|
println!("The local keys file is corrupted: {}", e);
|
||||||
|
state.increase_disk_attacks();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Could not read keys file: {e}");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let init_nodes = match File::open(INIT_NODES_FILE) {
|
let init_nodes = match File::open(INIT_NODES_FILE) {
|
||||||
@ -71,7 +84,7 @@ async fn get_sol_client(state: Arc<State>, ratls_config: RaTlsConfig) -> SolClie
|
|||||||
);
|
);
|
||||||
println!("The address of the Token is {}", sol_client.get_token_address());
|
println!("The address of the Token is {}", sol_client.get_token_address());
|
||||||
println!("Saving this data to disk in the file {KEYS_FILE}");
|
println!("Saving this data to disk in the file {KEYS_FILE}");
|
||||||
if let Err(e) = sol_client.get_keys_file().write(KEYS_FILE).await {
|
if let Err(e) = sol_client.get_keys_file().write(KEYS_FILE) {
|
||||||
println!("Could not save data to disk: {e}");
|
println!("Could not save data to disk: {e}");
|
||||||
}
|
}
|
||||||
return sol_client;
|
return sol_client;
|
||||||
@ -90,7 +103,7 @@ async fn main() {
|
|||||||
let ratls_config = RaTlsConfig::new()
|
let ratls_config = RaTlsConfig::new()
|
||||||
.allow_instance_measurement(InstanceMeasurement::new().with_current_mrenclave().unwrap());
|
.allow_instance_measurement(InstanceMeasurement::new().with_current_mrenclave().unwrap());
|
||||||
|
|
||||||
let state = Arc::new(State::new());
|
let state = Arc::new(State::new_with_localhost());
|
||||||
let sol_client = Arc::new(get_sol_client(state.clone(), ratls_config.clone()).await);
|
let sol_client = Arc::new(get_sol_client(state.clone(), ratls_config.clone()).await);
|
||||||
|
|
||||||
let (tx, _) = broadcast::channel(500);
|
let (tx, _) = broadcast::channel(500);
|
||||||
|
@ -1,8 +1,25 @@
|
|||||||
use crate::{datastore::State, grpc::challenge::Keys};
|
use crate::datastore::NodeInfo;
|
||||||
|
use crate::grpc::challenge::Keys;
|
||||||
|
use detee_sgx::SgxError;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::base64::Base64;
|
use serde_with::{base64::Base64, serde_as};
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
#[serde_with::serde_as]
|
pub struct Logfile {}
|
||||||
|
|
||||||
|
impl Logfile {
|
||||||
|
pub fn append(path: &str, msg: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let mut file = std::fs::OpenOptions::new().create(true).append(true).open(path)?;
|
||||||
|
file.write_all(msg.as_bytes())?;
|
||||||
|
file.write_all(b"\n")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SealedFile for KeysFile {}
|
||||||
|
impl SealedFile for NodeInfo {}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct KeysFile {
|
pub struct KeysFile {
|
||||||
random: String,
|
random: String,
|
||||||
@ -27,39 +44,49 @@ impl Into<Keys> for KeysFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeysFile {
|
pub trait SealedFile: Serialize + for<'de> Deserialize<'de> {
|
||||||
pub async fn write(self, path: &str) -> Result<(), Box<dyn std::error::Error>> {
|
fn write(&self, path: &str) -> Result<(), SealError> {
|
||||||
let serialized = serde_json::to_string(&self)?;
|
let serialized = serde_json::to_string(&self)?;
|
||||||
let sealed = detee_sgx::SealingConfig::new()?.seal_data(serialized.into_bytes())?;
|
let sealed = detee_sgx::SealingConfig::new()?.seal_data(serialized.into_bytes())?;
|
||||||
tokio::fs::write(path, sealed).await.map_err(Into::into)
|
std::fs::write(path, sealed).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read(path: &str, state: &State) -> Result<Self, Box<dyn std::error::Error>> {
|
fn read(path: &str) -> Result<Self, SealError> {
|
||||||
let sealed = tokio::fs::read(path).await?;
|
let sealed = std::fs::read(path)?;
|
||||||
let serialized = detee_sgx::SealingConfig::new()?.un_seal_data(sealed).map_err(|e| {
|
let serialized = detee_sgx::SealingConfig::new()?.un_seal_data(sealed)?;
|
||||||
match e {
|
serde_json::from_slice(&serialized).map_err(Into::into)
|
||||||
detee_sgx::SgxError::UnSealingError(ref ue) => {
|
|
||||||
state.increase_disk_attacks();
|
|
||||||
println!("The disk data is corrupted: {ue}");
|
|
||||||
}
|
|
||||||
_ => println!("Failed to unseal data: {e}"),
|
|
||||||
};
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
Ok(serde_json::from_str(&String::from_utf8(serialized)?)?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOG_PATH: &str = "/host/main/logs";
|
#[derive(Debug)]
|
||||||
|
pub enum SealError {
|
||||||
|
Error(String),
|
||||||
|
Attack(String),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Logfile {}
|
impl std::fmt::Display for SealError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
impl Logfile {
|
match self {
|
||||||
pub fn append(msg: &str) -> Result<(), Box<dyn std::error::Error>> {
|
SealError::Error(e) => write!(f, "Error: {}", e),
|
||||||
use std::io::Write;
|
SealError::Attack(e) => write!(f, "SealError: {}", e),
|
||||||
let mut file = std::fs::OpenOptions::new().create(true).append(true).open(LOG_PATH)?;
|
}
|
||||||
file.write_all(msg.as_bytes())?;
|
}
|
||||||
file.write_all(b"\n")?;
|
}
|
||||||
Ok(())
|
|
||||||
|
impl From<SgxError> for SealError {
|
||||||
|
fn from(e: SgxError) -> Self {
|
||||||
|
SealError::Attack(e.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<serde_json::Error> for SealError {
|
||||||
|
fn from(e: serde_json::Error) -> Self {
|
||||||
|
SealError::Error(e.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for SealError {
|
||||||
|
fn from(e: std::io::Error) -> Self {
|
||||||
|
SealError::Error(e.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user