From 7528256e789b67717a7ca35be300215d961f3a5e Mon Sep 17 00:00:00 2001 From: Aleksey Proshutisnkiy Date: Wed, 24 Nov 2021 18:35:38 +0300 Subject: [PATCH] Remove mutex from TG instance (#31) --- service/src/error.rs | 4 +-- service/src/main.rs | 3 +-- service/src/misc.rs | 28 ++++++++++--------- service/src/service_api.rs | 54 ++++++++++++++++++++----------------- service/src/storage_impl.rs | 15 +---------- service/src/tests.rs | 6 ++--- 6 files changed, 52 insertions(+), 58 deletions(-) diff --git a/service/src/error.rs b/service/src/error.rs index 5ac7df1..8d071c7 100644 --- a/service/src/error.rs +++ b/service/src/error.rs @@ -55,8 +55,8 @@ pub enum ServiceError { #[source] TrustError, ), - #[error("you should use host peer.timestamp_sec to pass timestamp")] - InvalidTimestampTetraplet, + #[error("you should use host peer.timestamp_sec to pass timestamp: {0}")] + InvalidTimestampTetraplet(String), #[error("{0} can't be issued later than the current timestamp")] InvalidTimestamp(String), #[error("Root could add only by trust graph service owner")] diff --git a/service/src/main.rs b/service/src/main.rs index 060cc8e..d4e2c57 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -14,8 +14,7 @@ mod service_api; mod storage_impl; mod tests; -pub static TRUSTED_TIMESTAMP_SERVICE_ID: &str = "peer"; -pub static TRUSTED_TIMESTAMP_FUNCTION_NAME: &str = "timestamp_sec"; +pub static TRUSTED_TIMESTAMP: (&str, &str) = ("peer", "timestamp_sec"); pub fn main() { WasmLoggerBuilder::new() diff --git a/service/src/misc.rs b/service/src/misc.rs index 97f0ad0..2306469 100644 --- a/service/src/misc.rs +++ b/service/src/misc.rs @@ -15,13 +15,14 @@ */ use crate::error::ServiceError; use crate::error::ServiceError::*; -use crate::storage_impl::{get_data, SQLiteStorage}; -use crate::{TRUSTED_TIMESTAMP_FUNCTION_NAME, TRUSTED_TIMESTAMP_SERVICE_ID}; +use crate::storage_impl::{SQLiteStorage, DB_PATH}; +use crate::TRUSTED_TIMESTAMP; use fluence_keypair::PublicKey; use libp2p_core::PeerId; use marine_rs_sdk::CallParameters; -use parking_lot::MutexGuard; +use std::cell::RefCell; use std::convert::TryFrom; +use std::ops::DerefMut; use std::str::FromStr; use trust_graph::TrustGraph; @@ -33,13 +34,14 @@ pub(crate) fn check_timestamp_tetraplets( let tetraplets = call_parameters .tetraplets .get(arg_number) - .ok_or(InvalidTimestampTetraplet)?; - let tetraplet = tetraplets.get(0).ok_or(InvalidTimestampTetraplet)?; - (tetraplet.service_id == TRUSTED_TIMESTAMP_SERVICE_ID - && tetraplet.function_name == TRUSTED_TIMESTAMP_FUNCTION_NAME + .ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", call_parameters.tetraplets)))?; + let tetraplet = tetraplets + .get(0) + .ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", call_parameters.tetraplets)))?; + (TRUSTED_TIMESTAMP.eq(&(&tetraplet.service_id, &tetraplet.function_name)) && tetraplet.peer_pk == call_parameters.host_id) .then(|| ()) - .ok_or(InvalidTimestampTetraplet) + .ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", tetraplet))) } fn parse_peer_id(peer_id: String) -> Result { @@ -47,13 +49,15 @@ fn parse_peer_id(peer_id: String) -> Result { .map_err(|e| ServiceError::PeerIdParseError(format!("{:?}", e))) } +thread_local!(static INSTANCE: RefCell> = RefCell::new(TrustGraph::new( + SQLiteStorage::new(marine_sqlite_connector::open(DB_PATH).unwrap()), +))); + pub fn with_tg(func: F) -> T where - F: FnOnce(MutexGuard>) -> T, + F: FnOnce(&mut TrustGraph) -> T, { - let tg = get_data().lock(); - - func(tg) + INSTANCE.with(|tg| func(tg.borrow_mut().deref_mut())) } pub fn wrapped_try(func: F) -> T diff --git a/service/src/service_api.rs b/service/src/service_api.rs index 40ee1e7..20cb631 100644 --- a/service/src/service_api.rs +++ b/service/src/service_api.rs @@ -6,12 +6,13 @@ use crate::results::{ InsertResult, IssueRevocationResult, IssueTrustResult, RevokeResult, VerifyTrustResult, WeightResult, }; +use crate::storage_impl::SQLiteStorage; use fluence_keypair::Signature; use marine_rs_sdk::{get_call_parameters, marine, CallParameters}; use std::convert::{TryFrom, TryInto}; use std::str::FromStr; use std::time::Duration; -use trust_graph::MAX_WEIGHT_FACTOR; +use trust_graph::{TrustGraph, MAX_WEIGHT_FACTOR}; #[marine] fn get_weight_factor(max_chain_len: u32) -> u32 { @@ -24,7 +25,7 @@ fn add_root(peer_id: String, weight_factor: u32) -> AddRootResult { let call_parameters: CallParameters = marine_rs_sdk::get_call_parameters(); let init_peer_id = call_parameters.init_peer_id; if call_parameters.service_creator_peer_id == init_peer_id { - with_tg(|mut tg| { + with_tg(|tg| { let public_key = extract_public_key(peer_id)?; tg.add_root_weight_factor(public_key, weight_factor)?; Ok(()) @@ -42,7 +43,7 @@ fn add_root(peer_id: String, weight_factor: u32) -> AddRootResult { /// add a certificate in string representation to trust graph if it is valid /// see `trust_graph::Certificate` class for string encoding/decoding fn insert_cert_raw(certificate: String, timestamp_sec: u64) -> InsertResult { - with_tg(|mut tg| { + with_tg(|tg| { let certificate = trust_graph::Certificate::from_str(&certificate)?; let timestamp_sec = Duration::from_secs(timestamp_sec); tg.add(certificate, timestamp_sec)?; @@ -55,7 +56,7 @@ fn insert_cert_raw(certificate: String, timestamp_sec: u64) -> InsertResult { /// add a certificate in JSON representation to trust graph if it is valid /// see `dto::Certificate` class for structure fn insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult { - with_tg(|mut tg| { + with_tg(|tg| { let timestamp_sec = Duration::from_secs(timestamp_sec); tg.add( trust_graph::Certificate::try_from(certificate)?, @@ -66,48 +67,51 @@ fn insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult { .into() } +fn get_certs( + tg: &mut TrustGraph, + issued_for: String, + timestamp_sec: u64, +) -> Result, ServiceError> { + let public_key = extract_public_key(issued_for)?; + let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?; + Ok(certs.into_iter().map(|c| c.into())) +} + #[marine] fn get_all_certs(issued_for: String, timestamp_sec: u64) -> AllCertsResult { - with_tg(|mut tg| { + with_tg(|tg| { check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?; - let public_key = extract_public_key(issued_for)?; - let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?; - Ok(certs.into_iter().map(|c| c.into()).collect()) + get_certs(tg, issued_for, timestamp_sec).map(|iter| iter.collect()) }) .into() } #[marine] fn get_host_certs(timestamp_sec: u64) -> AllCertsResult { - with_tg(|mut tg| { + with_tg(|tg| { let cp = marine_rs_sdk::get_call_parameters(); check_timestamp_tetraplets(&cp, 0)?; - let public_key = extract_public_key(cp.host_id)?; - let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?; - Ok(certs.into_iter().map(|c| c.into()).collect()) + get_certs(tg, cp.host_id, timestamp_sec).map(|iter| iter.collect()) }) .into() } #[marine] fn get_host_certs_from(issuer: String, timestamp_sec: u64) -> AllCertsResult { - with_tg(|mut tg| { + with_tg(|tg| { let cp = get_call_parameters(); check_timestamp_tetraplets(&cp, 1)?; - let public_key = extract_public_key(cp.host_id)?; - let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?; - Ok(certs - .into_iter() - .map(|c| c.into()) - .filter(|cert: &Certificate| cert.chain.iter().any(|t| t.issued_for == issuer)) - .collect()) + get_certs(tg, cp.host_id, timestamp_sec).map(|c| { + c.filter(|cert: &Certificate| cert.chain.iter().any(|t| t.issued_for == issuer)) + .collect() + }) }) .into() } #[marine] fn get_weight(peer_id: String, timestamp_sec: u64) -> WeightResult { - with_tg(|mut tg| { + with_tg(|tg| { check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?; let public_key = extract_public_key(peer_id.clone())?; let weight = tg.weight(public_key, Duration::from_secs(timestamp_sec))?; @@ -175,12 +179,12 @@ fn verify_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> Ver #[marine] fn add_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> AddTrustResult { - with_tg(|mut tg| { + with_tg(|tg| { let public_key = extract_public_key(issuer_peer_id)?; check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 2)?; if trust.issued_at > timestamp_sec { - return Err(ServiceError::InvalidTimestamp("Trust".to_string())); + return Err(ServiceError::InvalidTimestamp("trust".to_string())); } tg.add_trust( @@ -225,11 +229,11 @@ fn issue_revocation( #[marine] fn revoke(revoke: Revoke, timestamp_sec: u64) -> RevokeResult { - with_tg(|mut tg| { + with_tg(|tg| { check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?; if revoke.revoked_at > timestamp_sec { - return Err(ServiceError::InvalidTimestamp("Revoke".to_string())); + return Err(ServiceError::InvalidTimestamp("revoke".to_string())); } tg.revoke(revoke.try_into()?).map_err(ServiceError::TGError) diff --git a/service/src/storage_impl.rs b/service/src/storage_impl.rs index 54e3389..4d8568d 100644 --- a/service/src/storage_impl.rs +++ b/service/src/storage_impl.rs @@ -10,8 +10,6 @@ use core::convert::TryFrom; use fluence_keypair::error::DecodingError; use fluence_keypair::Signature; use marine_sqlite_connector::{Connection, Error as InternalSqliteError, Value}; -use once_cell::sync::OnceCell; -use parking_lot::Mutex; use rmp_serde::decode::Error as RmpDecodeError; use rmp_serde::encode::Error as RmpEncodeError; use std::convert::From; @@ -20,12 +18,9 @@ use std::time::Duration; use thiserror::Error as ThisError; use trust_graph::{ Auth, PublicKeyHashable as PK, PublicKeyHashable, Revoke, Storage, StorageError, Trust, - TrustGraph, TrustRelation, WeightFactor, + TrustRelation, WeightFactor, }; -#[allow(dead_code)] -static INSTANCE: OnceCell>> = OnceCell::new(); - static AUTH_TYPE: i64 = 0; static REVOKE_TYPE: i64 = 1; pub static DB_PATH: &str = "/tmp/trust-graph.sqlite"; @@ -56,14 +51,6 @@ pub fn create_tables() { .unwrap(); } -#[allow(dead_code)] -pub fn get_data() -> &'static Mutex> { - INSTANCE.get_or_init(|| { - let connection = marine_sqlite_connector::open(DB_PATH).unwrap(); - Mutex::new(TrustGraph::new(SQLiteStorage::new(connection))) - }) -} - pub struct SQLiteStorage { connection: Connection, } diff --git a/service/src/tests.rs b/service/src/tests.rs index 55d4fad..f035a76 100644 --- a/service/src/tests.rs +++ b/service/src/tests.rs @@ -19,7 +19,7 @@ mod service_tests { marine_rs_sdk_test::include_test_env!("/marine_test_env.rs"); use crate::error::ServiceError; use crate::storage_impl::DB_PATH; - use crate::{TRUSTED_TIMESTAMP_FUNCTION_NAME, TRUSTED_TIMESTAMP_SERVICE_ID}; + use crate::TRUSTED_TIMESTAMP; use fluence_keypair::KeyPair; use libp2p_core::PeerId; use marine_rs_sdk::{CallParameters, SecurityTetraplet}; @@ -79,8 +79,8 @@ mod service_tests { cp.tetraplets.push(vec![SecurityTetraplet { peer_pk: host_id, - service_id: TRUSTED_TIMESTAMP_SERVICE_ID.to_string(), - function_name: TRUSTED_TIMESTAMP_FUNCTION_NAME.to_string(), + service_id: TRUSTED_TIMESTAMP.0.to_string(), + function_name: TRUSTED_TIMESTAMP.1.to_string(), json_path: "".to_string(), }]);