Remove mutex from TG instance (#31)

This commit is contained in:
Aleksey Proshutisnkiy 2021-11-24 18:35:38 +03:00 committed by GitHub
parent 1f31ffecc7
commit 7528256e78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 58 deletions

View File

@ -55,8 +55,8 @@ pub enum ServiceError {
#[source] #[source]
TrustError, TrustError,
), ),
#[error("you should use host peer.timestamp_sec to pass timestamp")] #[error("you should use host peer.timestamp_sec to pass timestamp: {0}")]
InvalidTimestampTetraplet, InvalidTimestampTetraplet(String),
#[error("{0} can't be issued later than the current timestamp")] #[error("{0} can't be issued later than the current timestamp")]
InvalidTimestamp(String), InvalidTimestamp(String),
#[error("Root could add only by trust graph service owner")] #[error("Root could add only by trust graph service owner")]

View File

@ -14,8 +14,7 @@ mod service_api;
mod storage_impl; mod storage_impl;
mod tests; mod tests;
pub static TRUSTED_TIMESTAMP_SERVICE_ID: &str = "peer"; pub static TRUSTED_TIMESTAMP: (&str, &str) = ("peer", "timestamp_sec");
pub static TRUSTED_TIMESTAMP_FUNCTION_NAME: &str = "timestamp_sec";
pub fn main() { pub fn main() {
WasmLoggerBuilder::new() WasmLoggerBuilder::new()

View File

@ -15,13 +15,14 @@
*/ */
use crate::error::ServiceError; use crate::error::ServiceError;
use crate::error::ServiceError::*; use crate::error::ServiceError::*;
use crate::storage_impl::{get_data, SQLiteStorage}; use crate::storage_impl::{SQLiteStorage, DB_PATH};
use crate::{TRUSTED_TIMESTAMP_FUNCTION_NAME, TRUSTED_TIMESTAMP_SERVICE_ID}; use crate::TRUSTED_TIMESTAMP;
use fluence_keypair::PublicKey; use fluence_keypair::PublicKey;
use libp2p_core::PeerId; use libp2p_core::PeerId;
use marine_rs_sdk::CallParameters; use marine_rs_sdk::CallParameters;
use parking_lot::MutexGuard; use std::cell::RefCell;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ops::DerefMut;
use std::str::FromStr; use std::str::FromStr;
use trust_graph::TrustGraph; use trust_graph::TrustGraph;
@ -33,13 +34,14 @@ pub(crate) fn check_timestamp_tetraplets(
let tetraplets = call_parameters let tetraplets = call_parameters
.tetraplets .tetraplets
.get(arg_number) .get(arg_number)
.ok_or(InvalidTimestampTetraplet)?; .ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", call_parameters.tetraplets)))?;
let tetraplet = tetraplets.get(0).ok_or(InvalidTimestampTetraplet)?; let tetraplet = tetraplets
(tetraplet.service_id == TRUSTED_TIMESTAMP_SERVICE_ID .get(0)
&& tetraplet.function_name == TRUSTED_TIMESTAMP_FUNCTION_NAME .ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", call_parameters.tetraplets)))?;
(TRUSTED_TIMESTAMP.eq(&(&tetraplet.service_id, &tetraplet.function_name))
&& tetraplet.peer_pk == call_parameters.host_id) && tetraplet.peer_pk == call_parameters.host_id)
.then(|| ()) .then(|| ())
.ok_or(InvalidTimestampTetraplet) .ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", tetraplet)))
} }
fn parse_peer_id(peer_id: String) -> Result<PeerId, ServiceError> { fn parse_peer_id(peer_id: String) -> Result<PeerId, ServiceError> {
@ -47,13 +49,15 @@ fn parse_peer_id(peer_id: String) -> Result<PeerId, ServiceError> {
.map_err(|e| ServiceError::PeerIdParseError(format!("{:?}", e))) .map_err(|e| ServiceError::PeerIdParseError(format!("{:?}", e)))
} }
thread_local!(static INSTANCE: RefCell<TrustGraph<SQLiteStorage>> = RefCell::new(TrustGraph::new(
SQLiteStorage::new(marine_sqlite_connector::open(DB_PATH).unwrap()),
)));
pub fn with_tg<F, T>(func: F) -> T pub fn with_tg<F, T>(func: F) -> T
where where
F: FnOnce(MutexGuard<TrustGraph<SQLiteStorage>>) -> T, F: FnOnce(&mut TrustGraph<SQLiteStorage>) -> T,
{ {
let tg = get_data().lock(); INSTANCE.with(|tg| func(tg.borrow_mut().deref_mut()))
func(tg)
} }
pub fn wrapped_try<F, T>(func: F) -> T pub fn wrapped_try<F, T>(func: F) -> T

View File

@ -6,12 +6,13 @@ use crate::results::{
InsertResult, IssueRevocationResult, IssueTrustResult, RevokeResult, VerifyTrustResult, InsertResult, IssueRevocationResult, IssueTrustResult, RevokeResult, VerifyTrustResult,
WeightResult, WeightResult,
}; };
use crate::storage_impl::SQLiteStorage;
use fluence_keypair::Signature; use fluence_keypair::Signature;
use marine_rs_sdk::{get_call_parameters, marine, CallParameters}; use marine_rs_sdk::{get_call_parameters, marine, CallParameters};
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
use trust_graph::MAX_WEIGHT_FACTOR; use trust_graph::{TrustGraph, MAX_WEIGHT_FACTOR};
#[marine] #[marine]
fn get_weight_factor(max_chain_len: u32) -> u32 { 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 call_parameters: CallParameters = marine_rs_sdk::get_call_parameters();
let init_peer_id = call_parameters.init_peer_id; let init_peer_id = call_parameters.init_peer_id;
if call_parameters.service_creator_peer_id == 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)?; let public_key = extract_public_key(peer_id)?;
tg.add_root_weight_factor(public_key, weight_factor)?; tg.add_root_weight_factor(public_key, weight_factor)?;
Ok(()) 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 /// add a certificate in string representation to trust graph if it is valid
/// see `trust_graph::Certificate` class for string encoding/decoding /// see `trust_graph::Certificate` class for string encoding/decoding
fn insert_cert_raw(certificate: String, timestamp_sec: u64) -> InsertResult { 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 certificate = trust_graph::Certificate::from_str(&certificate)?;
let timestamp_sec = Duration::from_secs(timestamp_sec); let timestamp_sec = Duration::from_secs(timestamp_sec);
tg.add(certificate, 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 /// add a certificate in JSON representation to trust graph if it is valid
/// see `dto::Certificate` class for structure /// see `dto::Certificate` class for structure
fn insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult { fn insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult {
with_tg(|mut tg| { with_tg(|tg| {
let timestamp_sec = Duration::from_secs(timestamp_sec); let timestamp_sec = Duration::from_secs(timestamp_sec);
tg.add( tg.add(
trust_graph::Certificate::try_from(certificate)?, trust_graph::Certificate::try_from(certificate)?,
@ -66,48 +67,51 @@ fn insert_cert(certificate: Certificate, timestamp_sec: u64) -> InsertResult {
.into() .into()
} }
#[marine] fn get_certs(
fn get_all_certs(issued_for: String, timestamp_sec: u64) -> AllCertsResult { tg: &mut TrustGraph<SQLiteStorage>,
with_tg(|mut tg| { issued_for: String,
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?; timestamp_sec: u64,
) -> Result<impl Iterator<Item = Certificate>, ServiceError> {
let public_key = extract_public_key(issued_for)?; let public_key = extract_public_key(issued_for)?;
let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?; let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?;
Ok(certs.into_iter().map(|c| c.into()).collect()) Ok(certs.into_iter().map(|c| c.into()))
}
#[marine]
fn get_all_certs(issued_for: String, timestamp_sec: u64) -> AllCertsResult {
with_tg(|tg| {
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?;
get_certs(tg, issued_for, timestamp_sec).map(|iter| iter.collect())
}) })
.into() .into()
} }
#[marine] #[marine]
fn get_host_certs(timestamp_sec: u64) -> AllCertsResult { fn get_host_certs(timestamp_sec: u64) -> AllCertsResult {
with_tg(|mut tg| { with_tg(|tg| {
let cp = marine_rs_sdk::get_call_parameters(); let cp = marine_rs_sdk::get_call_parameters();
check_timestamp_tetraplets(&cp, 0)?; check_timestamp_tetraplets(&cp, 0)?;
let public_key = extract_public_key(cp.host_id)?; get_certs(tg, cp.host_id, timestamp_sec).map(|iter| iter.collect())
let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?;
Ok(certs.into_iter().map(|c| c.into()).collect())
}) })
.into() .into()
} }
#[marine] #[marine]
fn get_host_certs_from(issuer: String, timestamp_sec: u64) -> AllCertsResult { fn get_host_certs_from(issuer: String, timestamp_sec: u64) -> AllCertsResult {
with_tg(|mut tg| { with_tg(|tg| {
let cp = get_call_parameters(); let cp = get_call_parameters();
check_timestamp_tetraplets(&cp, 1)?; check_timestamp_tetraplets(&cp, 1)?;
let public_key = extract_public_key(cp.host_id)?; get_certs(tg, cp.host_id, timestamp_sec).map(|c| {
let certs = tg.get_all_certs(public_key, Duration::from_secs(timestamp_sec))?; c.filter(|cert: &Certificate| cert.chain.iter().any(|t| t.issued_for == issuer))
Ok(certs .collect()
.into_iter() })
.map(|c| c.into())
.filter(|cert: &Certificate| cert.chain.iter().any(|t| t.issued_for == issuer))
.collect())
}) })
.into() .into()
} }
#[marine] #[marine]
fn get_weight(peer_id: String, timestamp_sec: u64) -> WeightResult { 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)?; check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?;
let public_key = extract_public_key(peer_id.clone())?; let public_key = extract_public_key(peer_id.clone())?;
let weight = tg.weight(public_key, Duration::from_secs(timestamp_sec))?; 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] #[marine]
fn add_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> AddTrustResult { 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)?; let public_key = extract_public_key(issuer_peer_id)?;
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 2)?; check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 2)?;
if trust.issued_at > timestamp_sec { if trust.issued_at > timestamp_sec {
return Err(ServiceError::InvalidTimestamp("Trust".to_string())); return Err(ServiceError::InvalidTimestamp("trust".to_string()));
} }
tg.add_trust( tg.add_trust(
@ -225,11 +229,11 @@ fn issue_revocation(
#[marine] #[marine]
fn revoke(revoke: Revoke, timestamp_sec: u64) -> RevokeResult { 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)?; check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?;
if revoke.revoked_at > timestamp_sec { 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) tg.revoke(revoke.try_into()?).map_err(ServiceError::TGError)

View File

@ -10,8 +10,6 @@ use core::convert::TryFrom;
use fluence_keypair::error::DecodingError; use fluence_keypair::error::DecodingError;
use fluence_keypair::Signature; use fluence_keypair::Signature;
use marine_sqlite_connector::{Connection, Error as InternalSqliteError, Value}; 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::decode::Error as RmpDecodeError;
use rmp_serde::encode::Error as RmpEncodeError; use rmp_serde::encode::Error as RmpEncodeError;
use std::convert::From; use std::convert::From;
@ -20,12 +18,9 @@ use std::time::Duration;
use thiserror::Error as ThisError; use thiserror::Error as ThisError;
use trust_graph::{ use trust_graph::{
Auth, PublicKeyHashable as PK, PublicKeyHashable, Revoke, Storage, StorageError, Trust, Auth, PublicKeyHashable as PK, PublicKeyHashable, Revoke, Storage, StorageError, Trust,
TrustGraph, TrustRelation, WeightFactor, TrustRelation, WeightFactor,
}; };
#[allow(dead_code)]
static INSTANCE: OnceCell<Mutex<TrustGraph<SQLiteStorage>>> = OnceCell::new();
static AUTH_TYPE: i64 = 0; static AUTH_TYPE: i64 = 0;
static REVOKE_TYPE: i64 = 1; static REVOKE_TYPE: i64 = 1;
pub static DB_PATH: &str = "/tmp/trust-graph.sqlite"; pub static DB_PATH: &str = "/tmp/trust-graph.sqlite";
@ -56,14 +51,6 @@ pub fn create_tables() {
.unwrap(); .unwrap();
} }
#[allow(dead_code)]
pub fn get_data() -> &'static Mutex<TrustGraph<SQLiteStorage>> {
INSTANCE.get_or_init(|| {
let connection = marine_sqlite_connector::open(DB_PATH).unwrap();
Mutex::new(TrustGraph::new(SQLiteStorage::new(connection)))
})
}
pub struct SQLiteStorage { pub struct SQLiteStorage {
connection: Connection, connection: Connection,
} }

View File

@ -19,7 +19,7 @@ mod service_tests {
marine_rs_sdk_test::include_test_env!("/marine_test_env.rs"); marine_rs_sdk_test::include_test_env!("/marine_test_env.rs");
use crate::error::ServiceError; use crate::error::ServiceError;
use crate::storage_impl::DB_PATH; 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 fluence_keypair::KeyPair;
use libp2p_core::PeerId; use libp2p_core::PeerId;
use marine_rs_sdk::{CallParameters, SecurityTetraplet}; use marine_rs_sdk::{CallParameters, SecurityTetraplet};
@ -79,8 +79,8 @@ mod service_tests {
cp.tetraplets.push(vec![SecurityTetraplet { cp.tetraplets.push(vec![SecurityTetraplet {
peer_pk: host_id, peer_pk: host_id,
service_id: TRUSTED_TIMESTAMP_SERVICE_ID.to_string(), service_id: TRUSTED_TIMESTAMP.0.to_string(),
function_name: TRUSTED_TIMESTAMP_FUNCTION_NAME.to_string(), function_name: TRUSTED_TIMESTAMP.1.to_string(),
json_path: "".to_string(), json_path: "".to_string(),
}]); }]);