mirror of
https://github.com/fluencelabs/trust-graph
synced 2025-04-25 07:42:14 +00:00
refactoring (#30)
This commit is contained in:
parent
cb6e072231
commit
1f31ffecc7
64
service/src/error.rs
Normal file
64
service/src/error.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
use thiserror::Error as ThisError;
|
||||||
|
|
||||||
|
use crate::dto::DtoConversionError;
|
||||||
|
use fluence_keypair::error::DecodingError;
|
||||||
|
use trust_graph::{CertificateError, TrustError, TrustGraphError};
|
||||||
|
|
||||||
|
#[derive(ThisError, Debug)]
|
||||||
|
pub enum ServiceError {
|
||||||
|
#[error("peer id parse error: {0}")]
|
||||||
|
PeerIdParseError(String),
|
||||||
|
#[error("public key extraction from peer id failed: {0}")]
|
||||||
|
PublicKeyExtractionError(String),
|
||||||
|
#[error("{0}")]
|
||||||
|
PublicKeyDecodeError(
|
||||||
|
#[from]
|
||||||
|
#[source]
|
||||||
|
DecodingError,
|
||||||
|
),
|
||||||
|
#[error("{0}")]
|
||||||
|
TGError(
|
||||||
|
#[from]
|
||||||
|
#[source]
|
||||||
|
TrustGraphError,
|
||||||
|
),
|
||||||
|
#[error("{0}")]
|
||||||
|
CertError(
|
||||||
|
#[from]
|
||||||
|
#[source]
|
||||||
|
CertificateError,
|
||||||
|
),
|
||||||
|
#[error("{0}")]
|
||||||
|
DtoError(
|
||||||
|
#[from]
|
||||||
|
#[source]
|
||||||
|
DtoConversionError,
|
||||||
|
),
|
||||||
|
#[error("{0}")]
|
||||||
|
TrustError(
|
||||||
|
#[from]
|
||||||
|
#[source]
|
||||||
|
TrustError,
|
||||||
|
),
|
||||||
|
#[error("you should use host peer.timestamp_sec to pass timestamp")]
|
||||||
|
InvalidTimestampTetraplet,
|
||||||
|
#[error("{0} can't be issued later than the current timestamp")]
|
||||||
|
InvalidTimestamp(String),
|
||||||
|
#[error("Root could add only by trust graph service owner")]
|
||||||
|
NotOwner,
|
||||||
|
}
|
@ -7,12 +7,16 @@ use marine_rs_sdk::WasmLoggerBuilder;
|
|||||||
module_manifest!();
|
module_manifest!();
|
||||||
|
|
||||||
mod dto;
|
mod dto;
|
||||||
|
mod error;
|
||||||
|
mod misc;
|
||||||
mod results;
|
mod results;
|
||||||
mod service_api;
|
mod service_api;
|
||||||
mod service_impl;
|
|
||||||
mod storage_impl;
|
mod storage_impl;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
pub static TRUSTED_TIMESTAMP_SERVICE_ID: &str = "peer";
|
||||||
|
pub static TRUSTED_TIMESTAMP_FUNCTION_NAME: &str = "timestamp_sec";
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
WasmLoggerBuilder::new()
|
WasmLoggerBuilder::new()
|
||||||
.with_log_level(log::LevelFilter::Trace)
|
.with_log_level(log::LevelFilter::Trace)
|
||||||
|
72
service/src/misc.rs
Normal file
72
service/src/misc.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
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 fluence_keypair::PublicKey;
|
||||||
|
use libp2p_core::PeerId;
|
||||||
|
use marine_rs_sdk::CallParameters;
|
||||||
|
use parking_lot::MutexGuard;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use trust_graph::TrustGraph;
|
||||||
|
|
||||||
|
/// Check timestamps are generated on the current host with builtin ("peer" "timestamp_sec")
|
||||||
|
pub(crate) fn check_timestamp_tetraplets(
|
||||||
|
call_parameters: &CallParameters,
|
||||||
|
arg_number: usize,
|
||||||
|
) -> Result<(), ServiceError> {
|
||||||
|
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
|
||||||
|
&& tetraplet.peer_pk == call_parameters.host_id)
|
||||||
|
.then(|| ())
|
||||||
|
.ok_or(InvalidTimestampTetraplet)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_peer_id(peer_id: String) -> Result<PeerId, ServiceError> {
|
||||||
|
libp2p_core::PeerId::from_str(&peer_id)
|
||||||
|
.map_err(|e| ServiceError::PeerIdParseError(format!("{:?}", e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_tg<F, T>(func: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce(MutexGuard<TrustGraph<SQLiteStorage>>) -> T,
|
||||||
|
{
|
||||||
|
let tg = get_data().lock();
|
||||||
|
|
||||||
|
func(tg)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wrapped_try<F, T>(func: F) -> T
|
||||||
|
where
|
||||||
|
F: FnOnce() -> T,
|
||||||
|
{
|
||||||
|
func()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_public_key(peer_id: String) -> Result<PublicKey, ServiceError> {
|
||||||
|
PublicKey::try_from(
|
||||||
|
parse_peer_id(peer_id)
|
||||||
|
.map_err(|e| ServiceError::PublicKeyExtractionError(e.to_string()))?,
|
||||||
|
)
|
||||||
|
.map_err(ServiceError::PublicKeyDecodeError)
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use crate::dto::{Certificate, Revoke, Trust};
|
use crate::dto::{Certificate, Revoke, Trust};
|
||||||
use crate::service_impl::ServiceError;
|
use crate::error::ServiceError;
|
||||||
use marine_rs_sdk::marine;
|
use marine_rs_sdk::marine;
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
use crate::dto::{Certificate, Revoke, Trust};
|
use crate::dto::{Certificate, Revoke, Trust};
|
||||||
|
use crate::error::ServiceError;
|
||||||
|
use crate::misc::{check_timestamp_tetraplets, extract_public_key, with_tg, wrapped_try};
|
||||||
use crate::results::{
|
use crate::results::{
|
||||||
AddRootResult, AddTrustResult, AllCertsResult, GetRevokeBytesResult, GetTrustBytesResult,
|
AddRootResult, AddTrustResult, AllCertsResult, GetRevokeBytesResult, GetTrustBytesResult,
|
||||||
InsertResult, IssueRevocationResult, IssueTrustResult, RevokeResult, VerifyTrustResult,
|
InsertResult, IssueRevocationResult, IssueTrustResult, RevokeResult, VerifyTrustResult,
|
||||||
WeightResult,
|
WeightResult,
|
||||||
};
|
};
|
||||||
use crate::service_impl::{
|
use fluence_keypair::Signature;
|
||||||
add_root_impl, add_trust_impl, get_all_certs_impl, get_host_certs_impl, get_revoke_bytes_impl,
|
|
||||||
get_trust_bytes_impl, get_weight_impl, insert_cert_impl, insert_cert_impl_raw,
|
|
||||||
issue_revocation_impl, issue_trust_impl, revoke_impl, verify_trust_impl, ServiceError,
|
|
||||||
};
|
|
||||||
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::str::FromStr;
|
||||||
|
use std::time::Duration;
|
||||||
use trust_graph::MAX_WEIGHT_FACTOR;
|
use trust_graph::MAX_WEIGHT_FACTOR;
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
@ -23,7 +24,12 @@ 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 {
|
||||||
add_root_impl(peer_id, weight_factor).into()
|
with_tg(|mut tg| {
|
||||||
|
let public_key = extract_public_key(peer_id)?;
|
||||||
|
tg.add_root_weight_factor(public_key, weight_factor)?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.into()
|
||||||
} else {
|
} else {
|
||||||
return AddRootResult {
|
return AddRootResult {
|
||||||
success: false,
|
success: false,
|
||||||
@ -36,42 +42,77 @@ 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 {
|
||||||
insert_cert_impl_raw(certificate, timestamp_sec).into()
|
with_tg(|mut tg| {
|
||||||
|
let certificate = trust_graph::Certificate::from_str(&certificate)?;
|
||||||
|
let timestamp_sec = Duration::from_secs(timestamp_sec);
|
||||||
|
tg.add(certificate, timestamp_sec)?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
/// 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 {
|
||||||
insert_cert_impl(certificate, timestamp_sec).into()
|
with_tg(|mut tg| {
|
||||||
|
let timestamp_sec = Duration::from_secs(timestamp_sec);
|
||||||
|
tg.add(
|
||||||
|
trust_graph::Certificate::try_from(certificate)?,
|
||||||
|
timestamp_sec,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
fn get_all_certs(issued_for: String, timestamp_sec: u64) -> AllCertsResult {
|
fn get_all_certs(issued_for: String, timestamp_sec: u64) -> AllCertsResult {
|
||||||
get_all_certs_impl(issued_for, timestamp_sec).into()
|
with_tg(|mut 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())
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
fn get_host_certs(timestamp_sec: u64) -> AllCertsResult {
|
fn get_host_certs(timestamp_sec: u64) -> AllCertsResult {
|
||||||
get_host_certs_impl(timestamp_sec).into()
|
with_tg(|mut 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())
|
||||||
|
})
|
||||||
|
.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 {
|
||||||
let host_id = get_call_parameters().host_id;
|
with_tg(|mut tg| {
|
||||||
get_all_certs_impl(host_id, timestamp_sec)
|
let cp = get_call_parameters();
|
||||||
.map(|certs| {
|
check_timestamp_tetraplets(&cp, 1)?;
|
||||||
certs
|
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()
|
.into_iter()
|
||||||
.filter(|cert| cert.chain.iter().any(|t| t.issued_for == issuer))
|
.map(|c| c.into())
|
||||||
.collect()
|
.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 {
|
||||||
get_weight_impl(peer_id.clone(), timestamp_sec)
|
with_tg(|mut 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))?;
|
||||||
|
Ok(weight)
|
||||||
|
})
|
||||||
.map(|w| (w, peer_id))
|
.map(|w| (w, peer_id))
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
@ -82,7 +123,16 @@ fn get_trust_bytes(
|
|||||||
expires_at_sec: u64,
|
expires_at_sec: u64,
|
||||||
issued_at_sec: u64,
|
issued_at_sec: u64,
|
||||||
) -> GetTrustBytesResult {
|
) -> GetTrustBytesResult {
|
||||||
get_trust_bytes_impl(issued_for_peer_id, expires_at_sec, issued_at_sec).into()
|
wrapped_try(|| {
|
||||||
|
let public_key = extract_public_key(issued_for_peer_id)?;
|
||||||
|
|
||||||
|
Ok(trust_graph::Trust::signature_bytes(
|
||||||
|
&public_key,
|
||||||
|
Duration::from_secs(expires_at_sec),
|
||||||
|
Duration::from_secs(issued_at_sec),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
@ -92,28 +142,67 @@ fn issue_trust(
|
|||||||
issued_at_sec: u64,
|
issued_at_sec: u64,
|
||||||
trust_bytes: Vec<u8>,
|
trust_bytes: Vec<u8>,
|
||||||
) -> IssueTrustResult {
|
) -> IssueTrustResult {
|
||||||
issue_trust_impl(
|
wrapped_try(|| {
|
||||||
issued_for_peer_id,
|
let public_key = extract_public_key(issued_for_peer_id)?;
|
||||||
|
let expires_at_sec = Duration::from_secs(expires_at_sec);
|
||||||
|
let issued_at_sec = Duration::from_secs(issued_at_sec);
|
||||||
|
let signature = Signature::from_bytes(public_key.get_key_format(), trust_bytes);
|
||||||
|
Ok(Trust::from(trust_graph::Trust::new(
|
||||||
|
public_key,
|
||||||
expires_at_sec,
|
expires_at_sec,
|
||||||
issued_at_sec,
|
issued_at_sec,
|
||||||
trust_bytes,
|
signature,
|
||||||
)
|
)))
|
||||||
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
fn verify_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> VerifyTrustResult {
|
fn verify_trust(trust: Trust, issuer_peer_id: String, timestamp_sec: u64) -> VerifyTrustResult {
|
||||||
verify_trust_impl(trust, issuer_peer_id, timestamp_sec).into()
|
wrapped_try(|| {
|
||||||
|
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 2)?;
|
||||||
|
let public_key = extract_public_key(issuer_peer_id)?;
|
||||||
|
trust_graph::Trust::verify(
|
||||||
|
&trust.try_into()?,
|
||||||
|
&public_key,
|
||||||
|
Duration::from_secs(timestamp_sec),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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 {
|
||||||
add_trust_impl(trust, issuer_peer_id, timestamp_sec).into()
|
with_tg(|mut 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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
tg.add_trust(
|
||||||
|
&trust.try_into()?,
|
||||||
|
public_key,
|
||||||
|
Duration::from_secs(timestamp_sec),
|
||||||
|
)
|
||||||
|
.map_err(ServiceError::TGError)
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
fn get_revoke_bytes(revoked_peer_id: String, revoked_at: u64) -> GetRevokeBytesResult {
|
fn get_revoke_bytes(revoked_peer_id: String, revoked_at: u64) -> GetRevokeBytesResult {
|
||||||
get_revoke_bytes_impl(revoked_peer_id, revoked_at).into()
|
wrapped_try(|| {
|
||||||
|
let public_key = extract_public_key(revoked_peer_id)?;
|
||||||
|
Ok(trust_graph::Revoke::signature_bytes(
|
||||||
|
&public_key,
|
||||||
|
Duration::from_secs(revoked_at),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
@ -123,16 +212,27 @@ fn issue_revocation(
|
|||||||
revoked_at_sec: u64,
|
revoked_at_sec: u64,
|
||||||
signature_bytes: Vec<u8>,
|
signature_bytes: Vec<u8>,
|
||||||
) -> IssueRevocationResult {
|
) -> IssueRevocationResult {
|
||||||
issue_revocation_impl(
|
wrapped_try(|| {
|
||||||
revoked_peer_id,
|
let revoked_pk = extract_public_key(revoked_peer_id)?;
|
||||||
revoked_by_peer_id,
|
let revoked_by_pk = extract_public_key(revoked_by_peer_id)?;
|
||||||
revoked_at_sec,
|
|
||||||
signature_bytes,
|
let revoked_at = Duration::from_secs(revoked_at_sec);
|
||||||
)
|
let signature = Signature::from_bytes(revoked_by_pk.get_key_format(), signature_bytes);
|
||||||
|
Ok(trust_graph::Revoke::new(revoked_pk, revoked_by_pk, revoked_at, signature).into())
|
||||||
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[marine]
|
#[marine]
|
||||||
fn revoke(revoke: Revoke, timestamp_sec: u64) -> RevokeResult {
|
fn revoke(revoke: Revoke, timestamp_sec: u64) -> RevokeResult {
|
||||||
revoke_impl(revoke, timestamp_sec).into()
|
with_tg(|mut tg| {
|
||||||
|
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?;
|
||||||
|
|
||||||
|
if revoke.revoked_at > timestamp_sec {
|
||||||
|
return Err(ServiceError::InvalidTimestamp("Revoke".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
tg.revoke(revoke.try_into()?).map_err(ServiceError::TGError)
|
||||||
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
@ -1,255 +0,0 @@
|
|||||||
use crate::dto::{Certificate, DtoConversionError, Revoke, Trust};
|
|
||||||
use crate::service_impl::ServiceError::InvalidTimestampTetraplet;
|
|
||||||
use crate::storage_impl::get_data;
|
|
||||||
use fluence_keypair::error::DecodingError;
|
|
||||||
use fluence_keypair::{PublicKey, Signature};
|
|
||||||
use libp2p_core::PeerId;
|
|
||||||
use marine_rs_sdk::CallParameters;
|
|
||||||
use std::convert::{Into, TryFrom, TryInto};
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::time::Duration;
|
|
||||||
use thiserror::Error as ThisError;
|
|
||||||
use trust_graph::{CertificateError, TrustError, TrustGraphError};
|
|
||||||
|
|
||||||
pub static TRUSTED_TIMESTAMP_SERVICE_ID: &str = "peer";
|
|
||||||
pub static TRUSTED_TIMESTAMP_FUNCTION_NAME: &str = "timestamp_sec";
|
|
||||||
|
|
||||||
/// Check timestamps are generated on the current host with builtin ("peer" "timestamp_sec")
|
|
||||||
pub(crate) fn check_timestamp_tetraplets(
|
|
||||||
call_parameters: &CallParameters,
|
|
||||||
arg_number: usize,
|
|
||||||
) -> Result<(), ServiceError> {
|
|
||||||
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
|
|
||||||
&& tetraplet.peer_pk == call_parameters.host_id)
|
|
||||||
.then(|| ())
|
|
||||||
.ok_or(InvalidTimestampTetraplet)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ThisError, Debug)]
|
|
||||||
pub enum ServiceError {
|
|
||||||
#[error("peer id parse error: {0}")]
|
|
||||||
PeerIdParseError(String),
|
|
||||||
#[error("public key extraction from peer id failed: {0}")]
|
|
||||||
PublicKeyExtractionError(String),
|
|
||||||
#[error("{0}")]
|
|
||||||
PublicKeyDecodeError(
|
|
||||||
#[from]
|
|
||||||
#[source]
|
|
||||||
DecodingError,
|
|
||||||
),
|
|
||||||
#[error("{0}")]
|
|
||||||
TGError(
|
|
||||||
#[from]
|
|
||||||
#[source]
|
|
||||||
TrustGraphError,
|
|
||||||
),
|
|
||||||
#[error("{0}")]
|
|
||||||
CertError(
|
|
||||||
#[from]
|
|
||||||
#[source]
|
|
||||||
CertificateError,
|
|
||||||
),
|
|
||||||
#[error("{0}")]
|
|
||||||
DtoError(
|
|
||||||
#[from]
|
|
||||||
#[source]
|
|
||||||
DtoConversionError,
|
|
||||||
),
|
|
||||||
#[error("{0}")]
|
|
||||||
TrustError(
|
|
||||||
#[from]
|
|
||||||
#[source]
|
|
||||||
TrustError,
|
|
||||||
),
|
|
||||||
#[error("you should use host peer.timestamp_sec to pass timestamp")]
|
|
||||||
InvalidTimestampTetraplet,
|
|
||||||
#[error("{0} can't be issued later than the current timestamp")]
|
|
||||||
InvalidTimestamp(String),
|
|
||||||
#[error("Root could add only by trust graph service owner")]
|
|
||||||
NotOwner,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_peer_id(peer_id: String) -> Result<PeerId, ServiceError> {
|
|
||||||
libp2p_core::PeerId::from_str(&peer_id)
|
|
||||||
.map_err(|e| ServiceError::PeerIdParseError(format!("{:?}", e)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_public_key(peer_id: String) -> Result<PublicKey, ServiceError> {
|
|
||||||
PublicKey::try_from(
|
|
||||||
parse_peer_id(peer_id)
|
|
||||||
.map_err(|e| ServiceError::PublicKeyExtractionError(e.to_string()))?,
|
|
||||||
)
|
|
||||||
.map_err(ServiceError::PublicKeyDecodeError)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_weight_impl(peer_id: String, timestamp_sec: u64) -> Result<u32, ServiceError> {
|
|
||||||
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?;
|
|
||||||
let mut tg = get_data().lock();
|
|
||||||
let public_key = extract_public_key(peer_id)?;
|
|
||||||
let weight = tg.weight(public_key, Duration::from_secs(timestamp_sec))?;
|
|
||||||
Ok(weight)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_cert(certificate: trust_graph::Certificate, timestamp_sec: u64) -> Result<(), ServiceError> {
|
|
||||||
let timestamp_sec = Duration::from_secs(timestamp_sec);
|
|
||||||
let mut tg = get_data().lock();
|
|
||||||
tg.add(certificate, timestamp_sec)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_cert_impl_raw(certificate: String, timestamp_sec: u64) -> Result<(), ServiceError> {
|
|
||||||
let certificate = trust_graph::Certificate::from_str(&certificate)?;
|
|
||||||
|
|
||||||
add_cert(certificate, timestamp_sec)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_all_certs_impl(
|
|
||||||
issued_for: String,
|
|
||||||
timestamp_sec: u64,
|
|
||||||
) -> Result<Vec<Certificate>, ServiceError> {
|
|
||||||
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?;
|
|
||||||
get_certs_helper(issued_for, timestamp_sec)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_host_certs_impl(timestamp_sec: u64) -> Result<Vec<Certificate>, ServiceError> {
|
|
||||||
let cp = marine_rs_sdk::get_call_parameters();
|
|
||||||
check_timestamp_tetraplets(&cp, 0)?;
|
|
||||||
get_certs_helper(cp.host_id, timestamp_sec)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_certs_helper(
|
|
||||||
issued_for: String,
|
|
||||||
timestamp_sec: u64,
|
|
||||||
) -> Result<Vec<Certificate>, ServiceError> {
|
|
||||||
let mut tg = get_data().lock();
|
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_cert_impl(certificate: Certificate, timestamp_sec: u64) -> Result<(), ServiceError> {
|
|
||||||
let certificate: trust_graph::Certificate = certificate.try_into()?;
|
|
||||||
|
|
||||||
add_cert(certificate, timestamp_sec)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_root_impl(peer_id: String, weight: u32) -> Result<(), ServiceError> {
|
|
||||||
let mut tg = get_data().lock();
|
|
||||||
let public_key = extract_public_key(peer_id)?;
|
|
||||||
tg.add_root_weight_factor(public_key, weight)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_trust_bytes_impl(
|
|
||||||
peer_id: String,
|
|
||||||
expires_at_sec: u64,
|
|
||||||
issued_at_sec: u64,
|
|
||||||
) -> Result<Vec<u8>, ServiceError> {
|
|
||||||
let public_key = extract_public_key(peer_id)?;
|
|
||||||
Ok(trust_graph::Trust::signature_bytes(
|
|
||||||
&public_key,
|
|
||||||
Duration::from_secs(expires_at_sec),
|
|
||||||
Duration::from_secs(issued_at_sec),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn issue_trust_impl(
|
|
||||||
peer_id: String,
|
|
||||||
expires_at_sec: u64,
|
|
||||||
issued_at_sec: u64,
|
|
||||||
trust_bytes: Vec<u8>,
|
|
||||||
) -> Result<Trust, ServiceError> {
|
|
||||||
let public_key = extract_public_key(peer_id)?;
|
|
||||||
let expires_at_sec = Duration::from_secs(expires_at_sec);
|
|
||||||
let issued_at_sec = Duration::from_secs(issued_at_sec);
|
|
||||||
let signature = Signature::from_bytes(public_key.get_key_format(), trust_bytes);
|
|
||||||
Ok(Trust::from(trust_graph::Trust::new(
|
|
||||||
public_key,
|
|
||||||
expires_at_sec,
|
|
||||||
issued_at_sec,
|
|
||||||
signature,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn verify_trust_impl(
|
|
||||||
trust: Trust,
|
|
||||||
issuer_peer_id: String,
|
|
||||||
timestamp_sec: u64,
|
|
||||||
) -> Result<(), ServiceError> {
|
|
||||||
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 2)?;
|
|
||||||
let public_key = extract_public_key(issuer_peer_id)?;
|
|
||||||
trust_graph::Trust::verify(
|
|
||||||
&trust.try_into()?,
|
|
||||||
&public_key,
|
|
||||||
Duration::from_secs(timestamp_sec),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_trust_impl(
|
|
||||||
trust: Trust,
|
|
||||||
issuer_peer_id: String,
|
|
||||||
timestamp_sec: u64,
|
|
||||||
) -> Result<u32, ServiceError> {
|
|
||||||
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()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut tg = get_data().lock();
|
|
||||||
tg.add_trust(
|
|
||||||
&trust.try_into()?,
|
|
||||||
public_key,
|
|
||||||
Duration::from_secs(timestamp_sec),
|
|
||||||
)
|
|
||||||
.map_err(ServiceError::TGError)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_revoke_bytes_impl(
|
|
||||||
revoked_peer_id: String,
|
|
||||||
revoked_at: u64,
|
|
||||||
) -> Result<Vec<u8>, ServiceError> {
|
|
||||||
let public_key = extract_public_key(revoked_peer_id)?;
|
|
||||||
Ok(trust_graph::Revoke::signature_bytes(
|
|
||||||
&public_key,
|
|
||||||
Duration::from_secs(revoked_at),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn issue_revocation_impl(
|
|
||||||
revoked_peer_id: String,
|
|
||||||
revoked_by_peer_id: String,
|
|
||||||
revoked_at_sec: u64,
|
|
||||||
signature_bytes: Vec<u8>,
|
|
||||||
) -> Result<Revoke, ServiceError> {
|
|
||||||
let revoked_pk = extract_public_key(revoked_peer_id)?;
|
|
||||||
let revoked_by_pk = extract_public_key(revoked_by_peer_id)?;
|
|
||||||
|
|
||||||
let revoked_at = Duration::from_secs(revoked_at_sec);
|
|
||||||
let signature = Signature::from_bytes(revoked_by_pk.get_key_format(), signature_bytes);
|
|
||||||
Ok(trust_graph::Revoke::new(revoked_pk, revoked_by_pk, revoked_at, signature).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn revoke_impl(revoke: Revoke, timestamp_sec: u64) -> Result<(), ServiceError> {
|
|
||||||
check_timestamp_tetraplets(&marine_rs_sdk::get_call_parameters(), 1)?;
|
|
||||||
|
|
||||||
if revoke.revoked_at > timestamp_sec {
|
|
||||||
return Err(ServiceError::InvalidTimestamp("Revoke".to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut tg = get_data().lock();
|
|
||||||
|
|
||||||
tg.revoke(revoke.try_into()?).map_err(ServiceError::TGError)
|
|
||||||
}
|
|
@ -17,10 +17,9 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod service_tests {
|
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::service_impl::{
|
use crate::error::ServiceError;
|
||||||
ServiceError, TRUSTED_TIMESTAMP_FUNCTION_NAME, TRUSTED_TIMESTAMP_SERVICE_ID,
|
|
||||||
};
|
|
||||||
use crate::storage_impl::DB_PATH;
|
use crate::storage_impl::DB_PATH;
|
||||||
|
use crate::{TRUSTED_TIMESTAMP_FUNCTION_NAME, TRUSTED_TIMESTAMP_SERVICE_ID};
|
||||||
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};
|
||||||
@ -780,7 +779,7 @@ mod service_tests {
|
|||||||
add_trust_checked(&mut trust_graph, auth.trust.clone(), auth.issuer, cur_time);
|
add_trust_checked(&mut trust_graph, auth.trust.clone(), auth.issuer, cur_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cp = get_correct_timestamp_cp_with_host_id(
|
let cp = get_correct_timestamp_cp_with_host_id(
|
||||||
0,
|
0,
|
||||||
key_pairs.last().unwrap().get_peer_id().to_base58(),
|
key_pairs.last().unwrap().get_peer_id().to_base58(),
|
||||||
);
|
);
|
||||||
@ -799,7 +798,7 @@ mod service_tests {
|
|||||||
fn test_get_one_host_cert_from() {
|
fn test_get_one_host_cert_from() {
|
||||||
let mut trust_graph = ServiceInterface::new();
|
let mut trust_graph = ServiceInterface::new();
|
||||||
clear_env();
|
clear_env();
|
||||||
let (key_pairs, mut trusts) =
|
let (key_pairs, trusts) =
|
||||||
generate_trust_chain_with_len(&mut trust_graph, 5, HashMap::new());
|
generate_trust_chain_with_len(&mut trust_graph, 5, HashMap::new());
|
||||||
|
|
||||||
let cur_time = current_time();
|
let cur_time = current_time();
|
||||||
@ -810,7 +809,7 @@ mod service_tests {
|
|||||||
add_trust_checked(&mut trust_graph, auth.trust.clone(), auth.issuer, cur_time);
|
add_trust_checked(&mut trust_graph, auth.trust.clone(), auth.issuer, cur_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cp = get_correct_timestamp_cp_with_host_id(
|
let cp = get_correct_timestamp_cp_with_host_id(
|
||||||
1,
|
1,
|
||||||
key_pairs.last().unwrap().get_peer_id().to_base58(),
|
key_pairs.last().unwrap().get_peer_id().to_base58(),
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user